fix: Windows CLI Unicode encoding errors (#411) · basicmachines-co/basic-memory@0ba6f21 · GitHub
Skip to content

Commit 0ba6f21

Browse files
groksrcphernandezclaude
authored
fix: Windows CLI Unicode encoding errors (#411)
Signed-off-by: phernandez <paul@basicmachines.co> Signed-off-by: Claude <noreply@anthropic.com> Signed-off-by: Paul Hernandez <60959+phernandez@users.noreply.github.com> Co-authored-by: phernandez <paul@basicmachines.co> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Paul Hernandez <60959+phernandez@users.noreply.github.com>
1 parent 0b3272a commit 0ba6f21

14 files changed

Lines changed: 63 additions & 59 deletions

File tree

.github/workflows/claude-code-review.yml

Lines changed: 4 additions & 1 deletion

src/basic_memory/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""basic-memory - Local-first knowledge management combining Zettelkasten with knowledge graphs"""
22

33
# Package version - updated by release automation
4-
__version__ = "0.15.2"
4+
__version__ = "0.15.3.dev42+36149d6"
55

66
# API version for FastAPI - independent of package version
77
__api_version__ = "v0"

src/basic_memory/cli/auth.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def display_user_instructions(self, device_response: dict) -> None:
7777
verification_uri = device_response["verification_uri"]
7878
verification_uri_complete = device_response.get("verification_uri_complete")
7979

80-
console.print("\n[bold blue]🔐 Authentication Required[/bold blue]")
80+
console.print("\n[bold blue]Authentication Required[/bold blue]")
8181
console.print("\nTo authenticate, please visit:")
8282
console.print(f"[bold cyan]{verification_uri}[/bold cyan]")
8383
console.print(f"\nAnd enter this code: [bold yellow]{user_code}[/bold yellow]")
@@ -171,7 +171,7 @@ def save_tokens(self, tokens: dict) -> None:
171171
# Secure the token file
172172
os.chmod(self.token_file, 0o600)
173173

174-
console.print(f"[green]Tokens saved to {self.token_file}[/green]")
174+
console.print(f"[green]Tokens saved to {self.token_file}[/green]")
175175

176176
def load_tokens(self) -> dict | None:
177177
"""Load tokens from .bm-auth.json file."""
@@ -233,7 +233,7 @@ async def get_valid_token(self) -> str | None:
233233
if new_tokens:
234234
# Save new tokens (may include rotated refresh token)
235235
self.save_tokens(new_tokens)
236-
console.print("[green]Token refreshed successfully[/green]")
236+
console.print("[green]Token refreshed successfully[/green]")
237237
return new_tokens["access_token"]
238238
else:
239239
console.print("[yellow]Token refresh failed. Please run 'login' again.[/yellow]")
@@ -265,13 +265,13 @@ async def login(self) -> bool:
265265
# Step 4: Save tokens
266266
self.save_tokens(tokens)
267267

268-
console.print("\n[green]Successfully authenticated with Basic Memory Cloud![/green]")
268+
console.print("\n[green]Successfully authenticated with Basic Memory Cloud![/green]")
269269
return True
270270

271271
def logout(self) -> None:
272272
"""Remove stored authentication tokens."""
273273
if self.token_file.exists():
274274
self.token_file.unlink()
275-
console.print("[green]Logged out successfully[/green]")
275+
console.print("[green]Logged out successfully[/green]")
276276
else:
277277
console.print("[yellow]No stored authentication found[/yellow]")

src/basic_memory/cli/commands/cloud/core_commands.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ async def _login():
5252
config.cloud_mode = True
5353
config_manager.save_config(config)
5454

55-
console.print("[green]Cloud mode enabled[/green]")
55+
console.print("[green]Cloud mode enabled[/green]")
5656
console.print(f"[dim]All CLI commands now work against {host_url}[/dim]")
5757

5858
except SubscriptionRequiredError as e:
59-
console.print("\n[red]Subscription Required[/red]\n")
59+
console.print("\n[red]Subscription Required[/red]\n")
6060
console.print(f"[yellow]{e.args[0]}[/yellow]\n")
6161
console.print(f"Subscribe at: [blue underline]{e.subscribe_url}[/blue underline]\n")
6262
console.print(
@@ -77,7 +77,7 @@ def logout():
7777
config.cloud_mode = False
7878
config_manager.save_config(config)
7979

80-
console.print("[green]Cloud mode disabled[/green]")
80+
console.print("[green]Cloud mode disabled[/green]")
8181
console.print("[dim]All CLI commands now work locally[/dim]")
8282

8383

@@ -157,12 +157,12 @@ def setup() -> None:
157157
# Step 2: Get tenant info
158158
console.print("\n[blue]Step 2: Getting tenant information...[/blue]")
159159
tenant_info = asyncio.run(get_mount_info())
160-
console.print(f"[green]Found tenant: {tenant_info.tenant_id}[/green]")
160+
console.print(f"[green]Found tenant: {tenant_info.tenant_id}[/green]")
161161

162162
# Step 3: Generate credentials
163163
console.print("\n[blue]Step 3: Generating sync credentials...[/blue]")
164164
creds = asyncio.run(generate_mount_credentials(tenant_info.tenant_id))
165-
console.print("[green]Generated secure credentials[/green]")
165+
console.print("[green]Generated secure credentials[/green]")
166166

167167
# Step 4: Configure rclone remote
168168
console.print("\n[blue]Step 4: Configuring rclone remote...[/blue]")
@@ -171,7 +171,7 @@ def setup() -> None:
171171
secret_key=creds.secret_key,
172172
)
173173

174-
console.print("\n[bold green]Cloud setup completed successfully![/bold green]")
174+
console.print("\n[bold green]Cloud setup completed successfully![/bold green]")
175175
console.print("\n[bold]Next steps:[/bold]")
176176
console.print("1. Add a project with local sync path:")
177177
console.print(" bm project add research --local-path ~/Documents/research")

src/basic_memory/cli/commands/cloud/rclone_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,5 @@ def configure_rclone_remote(
106106
# Save updated config
107107
save_rclone_config(config)
108108

109-
console.print(f"[green]Configured rclone remote: {REMOTE_NAME}[/green]")
109+
console.print(f"[green]Configured rclone remote: {REMOTE_NAME}[/green]")
110110
return REMOTE_NAME

src/basic_memory/cli/commands/cloud/rclone_installer.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def install_rclone_macos() -> None:
5858
try:
5959
console.print("[blue]Installing rclone via Homebrew...[/blue]")
6060
run_command(["brew", "install", "rclone"])
61-
console.print("[green]rclone installed via Homebrew[/green]")
61+
console.print("[green]rclone installed via Homebrew[/green]")
6262
return
6363
except RcloneInstallError:
6464
console.print(
@@ -69,7 +69,7 @@ def install_rclone_macos() -> None:
6969
console.print("[blue]Installing rclone via official script...[/blue]")
7070
try:
7171
run_command(["sh", "-c", "curl https://rclone.org/install.sh | sudo bash"])
72-
console.print("[green]rclone installed via official script[/green]")
72+
console.print("[green]rclone installed via official script[/green]")
7373
except RcloneInstallError:
7474
raise RcloneInstallError(
7575
"Failed to install rclone. Please install manually: brew install rclone"
@@ -83,7 +83,7 @@ def install_rclone_linux() -> None:
8383
try:
8484
console.print("[blue]Installing rclone via snap...[/blue]")
8585
run_command(["sudo", "snap", "install", "rclone"])
86-
console.print("[green]rclone installed via snap[/green]")
86+
console.print("[green]rclone installed via snap[/green]")
8787
return
8888
except RcloneInstallError:
8989
console.print("[yellow]Snap installation failed, trying apt...[/yellow]")
@@ -94,7 +94,7 @@ def install_rclone_linux() -> None:
9494
console.print("[blue]Installing rclone via apt...[/blue]")
9595
run_command(["sudo", "apt", "update"])
9696
run_command(["sudo", "apt", "install", "-y", "rclone"])
97-
console.print("[green]rclone installed via apt[/green]")
97+
console.print("[green]rclone installed via apt[/green]")
9898
return
9999
except RcloneInstallError:
100100
console.print("[yellow]apt installation failed, trying official script...[/yellow]")
@@ -103,7 +103,7 @@ def install_rclone_linux() -> None:
103103
console.print("[blue]Installing rclone via official script...[/blue]")
104104
try:
105105
run_command(["sh", "-c", "curl https://rclone.org/install.sh | sudo bash"])
106-
console.print("[green]rclone installed via official script[/green]")
106+
console.print("[green]rclone installed via official script[/green]")
107107
except RcloneInstallError:
108108
raise RcloneInstallError(
109109
"Failed to install rclone. Please install manually: sudo snap install rclone"
@@ -117,7 +117,7 @@ def install_rclone_windows() -> None:
117117
try:
118118
console.print("[blue]Installing rclone via winget...[/blue]")
119119
run_command(["winget", "install", "Rclone.Rclone"])
120-
console.print("[green]rclone installed via winget[/green]")
120+
console.print("[green]rclone installed via winget[/green]")
121121
return
122122
except RcloneInstallError:
123123
console.print("[yellow]winget installation failed, trying chocolatey...[/yellow]")
@@ -127,7 +127,7 @@ def install_rclone_windows() -> None:
127127
try:
128128
console.print("[blue]Installing rclone via chocolatey...[/blue]")
129129
run_command(["choco", "install", "rclone", "-y"])
130-
console.print("[green]rclone installed via chocolatey[/green]")
130+
console.print("[green]rclone installed via chocolatey[/green]")
131131
return
132132
except RcloneInstallError:
133133
console.print("[yellow]chocolatey installation failed, trying scoop...[/yellow]")
@@ -137,7 +137,7 @@ def install_rclone_windows() -> None:
137137
try:
138138
console.print("[blue]Installing rclone via scoop...[/blue]")
139139
run_command(["scoop", "install", "rclone"])
140-
console.print("[green]rclone installed via scoop[/green]")
140+
console.print("[green]rclone installed via scoop[/green]")
141141
return
142142
except RcloneInstallError:
143143
console.print("[yellow]scoop installation failed[/yellow]")
@@ -172,7 +172,7 @@ def install_rclone(platform_override: Optional[str] = None) -> None:
172172
if not is_rclone_installed():
173173
raise RcloneInstallError("rclone installation completed but command not found in PATH")
174174

175-
console.print("[green]rclone installation completed successfully[/green]")
175+
console.print("[green]rclone installation completed successfully[/green]")
176176

177177
except RcloneInstallError:
178178
raise

src/basic_memory/cli/commands/cloud/upload.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ async def upload_path(
108108
if dry_run:
109109
print(f"\nTotal: {len(files_to_upload)} file(s) ({size_str})")
110110
else:
111-
print(f"Upload complete: {len(files_to_upload)} file(s) ({size_str})")
111+
print(f"Upload complete: {len(files_to_upload)} file(s) ({size_str})")
112112

113113
return True
114114

src/basic_memory/cli/commands/cloud/upload_command.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ async def _upload():
7878
console.print(f"[blue]Creating cloud project '{project}'...[/blue]")
7979
try:
8080
await create_cloud_project(project)
81-
console.print(f"[green]Created project '{project}'[/green]")
81+
console.print(f"[green]Created project '{project}'[/green]")
8282
except Exception as e:
8383
console.print(f"[red]Failed to create project: {e}[/red]")
8484
raise typer.Exit(1)
@@ -109,7 +109,7 @@ async def _upload():
109109
if dry_run:
110110
console.print("[yellow]DRY RUN complete - no files were uploaded[/yellow]")
111111
else:
112-
console.print(f"[green]Successfully uploaded to '{project}'[/green]")
112+
console.print(f"[green]Successfully uploaded to '{project}'[/green]")
113113

114114
# Sync project if requested (skip on dry run)
115115
# Force full scan after bisync to ensure database is up-to-date with synced files

src/basic_memory/cli/commands/command_utils.py

Lines changed: 3 additions & 3 deletions

0 commit comments

Comments
 (0)