aiel-cli 1.3.2__tar.gz → 1.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/PKG-INFO +1 -1
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/auth/credentials.py +5 -3
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/auth.py +1 -1
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/repo.py +108 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/.coverage +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/.github/workflows/publish.yml +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/LICENSE +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/README.md +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/index.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/pyproject.toml +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/req.json +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/requirements.txt +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/__init__.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/auth/api.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/auth/credentials copy.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/cli.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/cli_utils.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/_index.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/config.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/files.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/info.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/integrations.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/config.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/context/__init__.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/context/store.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/context/user_context.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/data_plane.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/errors.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/integration_plane.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/roadmap.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/utilities.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/utils/__init__.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/utils/format_integrations.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/tests/data/test_profile.json +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/tests/test_cli_routes.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/tests/test_internal_modules.py +0 -0
- {aiel_cli-1.3.2 → aiel_cli-1.3.4}/workflows/publish.yml +0 -0
|
@@ -116,7 +116,7 @@ def get_current_base_url(default: str = settings.BASE_URL) -> str:
|
|
|
116
116
|
return (prof or {}).get("base_url") or default
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
def save_profile(profile: str, base_url: str, token: str, email: str, tenant: str, tenant_id: str) -> str:
|
|
119
|
+
def save_profile(profile: str, base_url: str, token: str, email: str, tenant: str, tenant_id: str, user_id: str) -> str:
|
|
120
120
|
data = read_json(CREDENTIALS_PATH, DEFAULT_CREDS)
|
|
121
121
|
data.setdefault("profiles", {})
|
|
122
122
|
|
|
@@ -127,7 +127,8 @@ def save_profile(profile: str, base_url: str, token: str, email: str, tenant: st
|
|
|
127
127
|
"token_ref": f"keyring:{APP_NAME}:{profile}",
|
|
128
128
|
"user": email,
|
|
129
129
|
"tenant": tenant,
|
|
130
|
-
"tenant_id": tenant_id
|
|
130
|
+
"tenant_id": tenant_id,
|
|
131
|
+
"user_id": user_id
|
|
131
132
|
}
|
|
132
133
|
else:
|
|
133
134
|
data["profiles"][profile] = {
|
|
@@ -135,7 +136,8 @@ def save_profile(profile: str, base_url: str, token: str, email: str, tenant: st
|
|
|
135
136
|
"token": token,
|
|
136
137
|
"user": email,
|
|
137
138
|
"tenant": tenant,
|
|
138
|
-
"tenant_id": tenant_id
|
|
139
|
+
"tenant_id": tenant_id,
|
|
140
|
+
"user_id": user_id
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
data["current_profile"] = profile
|
|
@@ -40,7 +40,7 @@ def login(
|
|
|
40
40
|
raise typer.BadParameter("Token cannot be empty.")
|
|
41
41
|
|
|
42
42
|
me = _validate_token(base_url, token)
|
|
43
|
-
token_source = save_profile(profile, base_url, token, me.get("email"), me.get("tenant_name"))
|
|
43
|
+
token_source = save_profile(profile, base_url, token, me.get("email"), me.get("tenant_name"), me.get("tenant_id"), me.get("user_id"))
|
|
44
44
|
|
|
45
45
|
console.print(
|
|
46
46
|
Panel.fit(
|
|
@@ -88,7 +88,9 @@ from ..auth.credentials import (
|
|
|
88
88
|
)
|
|
89
89
|
app = typer.Typer(help="Commit-related commands")
|
|
90
90
|
checkout_app = typer.Typer(no_args_is_help=True)
|
|
91
|
+
context_app = typer.Typer(no_args_is_help=True)
|
|
91
92
|
app.add_typer(checkout_app, name="checkout", help="Switch workspace/project context for this repo.")
|
|
93
|
+
app.add_typer(context_app, name="set", help="Set workspace/project context without modifying files.")
|
|
92
94
|
console = Console()
|
|
93
95
|
from aiel_cli.context.store import set_workspace, set_project, clear_project
|
|
94
96
|
|
|
@@ -331,6 +333,112 @@ def checkout_workspace(
|
|
|
331
333
|
console.print("Next: aiel pull")
|
|
332
334
|
|
|
333
335
|
|
|
336
|
+
@context_app.command("workspace")
|
|
337
|
+
@friendly_errors
|
|
338
|
+
def set_workspace_context(
|
|
339
|
+
workspace: str = typer.Argument(..., help="Workspace slug to switch to."),
|
|
340
|
+
project: str | None = typer.Option(
|
|
341
|
+
None,
|
|
342
|
+
"--project",
|
|
343
|
+
"-p",
|
|
344
|
+
help="Project slug to set (optional). If omitted, you may be prompted.",
|
|
345
|
+
),
|
|
346
|
+
) -> None:
|
|
347
|
+
"""
|
|
348
|
+
Set workspace/project context without modifying the working tree.
|
|
349
|
+
"""
|
|
350
|
+
ensure_repo()
|
|
351
|
+
|
|
352
|
+
data = list_profiles()
|
|
353
|
+
profiles = data.get("profiles") or {}
|
|
354
|
+
if not profiles:
|
|
355
|
+
raise CliError(
|
|
356
|
+
"No auth profiles configured.",
|
|
357
|
+
hint="Run `aiel auth login` before `aiel context workspace`.",
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
current = _current_profile(data)
|
|
361
|
+
prof = _get_profile(data, current)
|
|
362
|
+
base_url = (prof.get("base_url") or get_current_base_url()).strip()
|
|
363
|
+
if not base_url:
|
|
364
|
+
raise CliError(
|
|
365
|
+
"Missing base_url for the active profile.",
|
|
366
|
+
hint="Run `aiel auth login` to select or create a profile.",
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
me = _get_me(prof)
|
|
370
|
+
workspaces = me.get("workspaces") or []
|
|
371
|
+
ws = next((w for w in workspaces if w.get("slug") == workspace), None)
|
|
372
|
+
if not ws:
|
|
373
|
+
available = ", ".join(sorted([w.get("slug", "") for w in workspaces if w.get("slug")]))
|
|
374
|
+
raise CliError(
|
|
375
|
+
f"Workspace slug not found: {workspace}",
|
|
376
|
+
hint=f"Available workspaces: {available}" if available else "Run `aiel info workspaces`.",
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
projects = ws.get("projects") or []
|
|
380
|
+
chosen_project = None
|
|
381
|
+
if project:
|
|
382
|
+
chosen_project = next((p for p in projects if p.get("slug") == project), None)
|
|
383
|
+
if not chosen_project:
|
|
384
|
+
available = ", ".join(sorted([p.get("slug", "") for p in projects if p.get("slug")]))
|
|
385
|
+
raise CliError(
|
|
386
|
+
f"Project slug not found in workspace '{ws.get('slug') or workspace}': {project}",
|
|
387
|
+
hint=f"Available projects: {available}" if available else "This workspace has no projects.",
|
|
388
|
+
)
|
|
389
|
+
else:
|
|
390
|
+
chosen_project = _prompt_project(ws.get("slug") or workspace, projects)
|
|
391
|
+
|
|
392
|
+
prof["workspace"] = {"id": ws["id"], "slug": ws["slug"], "name": ws.get("name")}
|
|
393
|
+
set_workspace(current, {"id": ws["id"], "slug": ws["slug"], "name": ws.get("name")})
|
|
394
|
+
|
|
395
|
+
if chosen_project:
|
|
396
|
+
prof["project"] = {
|
|
397
|
+
"id": chosen_project["id"],
|
|
398
|
+
"slug": chosen_project["slug"],
|
|
399
|
+
"name": chosen_project.get("name"),
|
|
400
|
+
}
|
|
401
|
+
set_project(
|
|
402
|
+
current,
|
|
403
|
+
{"id": chosen_project["id"], "slug": chosen_project["slug"], "name": chosen_project.get("name")},
|
|
404
|
+
)
|
|
405
|
+
else:
|
|
406
|
+
prof.pop("project", None)
|
|
407
|
+
clear_project(current)
|
|
408
|
+
|
|
409
|
+
profiles[current] = prof
|
|
410
|
+
data["profiles"] = profiles
|
|
411
|
+
write_json_secure(CREDENTIALS_PATH, data)
|
|
412
|
+
|
|
413
|
+
s = _state()
|
|
414
|
+
s["version"] = s.get("version") or 1
|
|
415
|
+
s["base_url"] = base_url.rstrip("/")
|
|
416
|
+
s["workspace_id"] = ws.get("id")
|
|
417
|
+
s["project_id"] = (chosen_project or {}).get("id")
|
|
418
|
+
s["workspace_slug"] = ws.get("slug")
|
|
419
|
+
s["project_slug"] = (chosen_project or {}).get("slug")
|
|
420
|
+
_save_state(s)
|
|
421
|
+
|
|
422
|
+
ix = _index()
|
|
423
|
+
staged = ix.get("staged") or {}
|
|
424
|
+
pending = s.get("pending_commit_id")
|
|
425
|
+
if staged or pending:
|
|
426
|
+
console.print(
|
|
427
|
+
"[yellow]Note:[/yellow] staged changes or pending commits were left untouched "
|
|
428
|
+
"and may belong to the previous workspace."
|
|
429
|
+
)
|
|
430
|
+
if s.get("last_manifest"):
|
|
431
|
+
console.print("[yellow]Note:[/yellow] last_manifest was not refreshed. Run `aiel pull` when ready.")
|
|
432
|
+
|
|
433
|
+
console.print("[green]✓[/green] Repo context updated (no files modified)")
|
|
434
|
+
console.print(f"workspace: [bold]{ws.get('slug')}[/bold]")
|
|
435
|
+
if chosen_project:
|
|
436
|
+
console.print(f"project: [bold]{chosen_project.get('slug')}[/bold]")
|
|
437
|
+
else:
|
|
438
|
+
console.print("project: [bold]not set[/bold]")
|
|
439
|
+
console.print("Next: aiel pull")
|
|
440
|
+
|
|
441
|
+
|
|
334
442
|
@app.command("status")
|
|
335
443
|
@friendly_errors
|
|
336
444
|
def status():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|