forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.py
More file actions
153 lines (130 loc) · 5.23 KB
/
Copy pathconfig.py
File metadata and controls
153 lines (130 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""``omi config`` — view and edit configuration / profiles."""
from __future__ import annotations
from typing import TYPE_CHECKING
import typer
from rich.markup import escape
from omi_cli import config as cfg
from omi_cli.errors import UsageError
if TYPE_CHECKING:
from omi_cli.main import AppContext
app = typer.Typer(no_args_is_help=True)
profile_app = typer.Typer(no_args_is_help=True, help="Manage named profiles.")
app.add_typer(profile_app, name="profile")
def _ctx(typer_ctx: typer.Context) -> "AppContext":
obj = typer_ctx.obj
if obj is None: # pragma: no cover
raise RuntimeError("AppContext not initialized")
return obj # type: ignore[no-any-return]
@app.command("show", help="Print the resolved configuration (credentials masked).")
def show(typer_ctx: typer.Context) -> None:
ctx = _ctx(typer_ctx)
config = ctx.load_config()
profiles = []
for name, profile in sorted(config.profiles.items()):
profiles.append(
{
"name": name,
"active": name == config.active_profile,
"auth_method": profile.auth_method,
"api_base": profile.api_base,
"credential": profile.masked_credential(),
"local_api_url": profile.local_api_url,
"local_token": profile.masked_local_token(),
}
)
payload = {
"config_path": str(config.path),
"active_profile": config.active_profile,
"profiles": profiles,
}
ctx.renderer.emit(payload, title="omi config show")
@app.command("path", help="Print the on-disk config path.")
def path(typer_ctx: typer.Context) -> None:
ctx = _ctx(typer_ctx)
config = ctx.load_config()
if ctx.renderer.json_mode:
ctx.renderer.emit({"path": str(config.path)})
else:
typer.echo(str(config.path))
_SETTABLE_KEYS = {"api_base", "local_api_url", "local_token"}
@app.command("set", help="Set a per-profile config value. Keys: api_base, local_api_url, local_token.")
def set_value(
typer_ctx: typer.Context,
key: str = typer.Argument(..., help=f"Config key to set. One of: {sorted(_SETTABLE_KEYS)}"),
value: str = typer.Argument(..., help="New value."),
) -> None:
ctx = _ctx(typer_ctx)
if key not in _SETTABLE_KEYS:
raise UsageError(
message=f"Unknown config key '{key}'",
detail=f"Settable keys: {sorted(_SETTABLE_KEYS)}",
)
config = ctx.load_config()
profile = config.get_profile(ctx.profile_name)
if key == "api_base":
profile.api_base = value.rstrip("/")
elif key == "local_api_url":
profile.local_api_url = value.rstrip("/")
elif key == "local_token":
profile.local_token = value
config.set_profile(profile)
cfg.save(config)
display_value = (
cfg.Profile(name=profile.name, local_token=value).masked_local_token() if key == "local_token" else value
)
ctx.renderer.success(
f"Set [bold]{escape(key)}[/bold] = {escape(display_value)} "
f"on profile [bold]{escape(profile.name)}[/bold]."
)
@profile_app.command("list", help="List all configured profiles.")
def profile_list(typer_ctx: typer.Context) -> None:
ctx = _ctx(typer_ctx)
config = ctx.load_config()
rows = []
for name in config.list_profiles() or [config.active_profile]:
profile = config.get_profile(name)
rows.append(
{
"name": name,
"active": name == config.active_profile,
"auth_method": profile.auth_method or "(none)",
"api_base": profile.api_base,
"credential": profile.masked_credential(),
"local_api_url": profile.local_api_url or "",
"local_token": profile.masked_local_token(),
}
)
ctx.renderer.emit(
rows,
columns=["name", "active", "auth_method", "api_base", "credential", "local_api_url", "local_token"],
title="profiles",
)
@profile_app.command("use", help="Switch the active profile.")
def profile_use(
typer_ctx: typer.Context,
name: str = typer.Argument(..., help="Profile name to make active."),
) -> None:
ctx = _ctx(typer_ctx)
config = ctx.load_config()
if name not in config.profiles:
# Allow switching to a brand-new (yet-unconfigured) profile so users can
# bootstrap a fresh context: `omi config profile use work && omi auth login`
config.profiles[name] = cfg.Profile(name=name)
config.active_profile = name
cfg.save(config)
ctx.renderer.success(f"Active profile: [bold]{escape(name)}[/bold].")
@profile_app.command("delete", help="Delete a profile and its credentials.")
def profile_delete(
typer_ctx: typer.Context,
name: str = typer.Argument(..., help="Profile name to delete."),
confirm: bool = typer.Option(False, "--yes", "-y", help="Skip the confirmation prompt."),
) -> None:
ctx = _ctx(typer_ctx)
config = ctx.load_config()
if name not in config.profiles:
raise UsageError(message=f"No such profile: '{name}'")
if not confirm:
typer.confirm(f"Delete profile '{name}'?", abort=True)
config.delete_profile(name)
cfg.save(config)
ctx.renderer.success(f"Deleted profile [bold]{escape(name)}[/bold].")