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.
Files changed (37) hide show
  1. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/PKG-INFO +1 -1
  2. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/auth/credentials.py +5 -3
  3. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/auth.py +1 -1
  4. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/repo.py +108 -0
  5. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/.coverage +0 -0
  6. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/.github/workflows/publish.yml +0 -0
  7. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/LICENSE +0 -0
  8. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/README.md +0 -0
  9. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/index.py +0 -0
  10. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/pyproject.toml +0 -0
  11. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/req.json +0 -0
  12. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/requirements.txt +0 -0
  13. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/__init__.py +0 -0
  14. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/auth/api.py +0 -0
  15. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/auth/credentials copy.py +0 -0
  16. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/cli.py +0 -0
  17. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/cli_utils.py +0 -0
  18. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/_index.py +0 -0
  19. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/config.py +0 -0
  20. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/files.py +0 -0
  21. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/info.py +0 -0
  22. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/commands/integrations.py +0 -0
  23. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/config.py +0 -0
  24. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/context/__init__.py +0 -0
  25. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/context/store.py +0 -0
  26. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/context/user_context.py +0 -0
  27. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/data_plane.py +0 -0
  28. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/errors.py +0 -0
  29. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/integration_plane.py +0 -0
  30. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/roadmap.py +0 -0
  31. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/utilities.py +0 -0
  32. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/utils/__init__.py +0 -0
  33. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/src/aiel_cli/utils/format_integrations.py +0 -0
  34. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/tests/data/test_profile.json +0 -0
  35. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/tests/test_cli_routes.py +0 -0
  36. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/tests/test_internal_modules.py +0 -0
  37. {aiel_cli-1.3.2 → aiel_cli-1.3.4}/workflows/publish.yml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiel-cli
3
- Version: 1.3.2
3
+ Version: 1.3.4
4
4
  Summary: AI Execution Layer CLI
5
5
  Author-email: Aldenir Flauzino <aldenirsrv@gmail.com>
6
6
  License:
@@ -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