devops-bot-sdk 1.4.118__tar.gz → 1.4.119__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 (90) hide show
  1. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/PKG-INFO +1 -1
  2. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
  3. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/devops_bot_sdk.egg-info/SOURCES.txt +0 -1
  4. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/__init__.py +2 -2
  5. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agentd.py +6 -7
  6. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/cli.py +25 -263
  7. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/client.py +8 -101
  8. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ipc/handlers.py +8 -8
  9. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/api.py +31 -228
  10. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/static/app.js +17 -35
  11. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/static/custom-agents.html +7 -8
  12. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/static/default-agents.html +3 -3
  13. devops_bot_sdk-1.4.118/sdk/ui/static/prompt-studio.html +0 -92
  14. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/README.md +0 -0
  15. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
  16. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
  17. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/devops_bot_sdk.egg-info/requires.txt +0 -0
  18. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/devops_bot_sdk.egg-info/top_level.txt +0 -0
  19. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/pyproject.toml +0 -0
  20. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/__init__.py +0 -0
  21. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/builder.py +0 -0
  22. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/chat.py +0 -0
  23. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/connectors.py +0 -0
  24. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/engines/__init__.py +0 -0
  25. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/engines/claude_code.py +0 -0
  26. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/engines/http.py +0 -0
  27. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/engines/mcp.py +0 -0
  28. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/engines/n8n.py +0 -0
  29. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/engines/shell.py +0 -0
  30. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/integrations.py +0 -0
  31. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/inventory.py +0 -0
  32. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/library/__init__.py +0 -0
  33. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/manifest.py +0 -0
  34. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/prompt_studio.py +0 -0
  35. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/prompt_template.py +0 -0
  36. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/prompt_vars.py +0 -0
  37. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/run_log.py +0 -0
  38. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/secrets.py +0 -0
  39. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/usage.py +0 -0
  40. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/agents/varstore.py +0 -0
  41. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/collectors/__init__.py +0 -0
  42. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/collectors/files.py +0 -0
  43. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/collectors/process.py +0 -0
  44. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/collectors/screenshot.py +0 -0
  45. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/config.py +0 -0
  46. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/crucial.py +0 -0
  47. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/design_verify/__init__.py +0 -0
  48. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/design_verify/assets.py +0 -0
  49. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/design_verify/bootstrap.py +0 -0
  50. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/design_verify/browser.py +0 -0
  51. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/design_verify/compare.py +0 -0
  52. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/design_verify/loop.py +0 -0
  53. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/exceptions.py +0 -0
  54. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/git_ops.py +0 -0
  55. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/graphify.py +0 -0
  56. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/hooks/__init__.py +0 -0
  57. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/hooks/crucial_guard.py +0 -0
  58. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ipc/__init__.py +0 -0
  59. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ipc/electron_bridge.py +0 -0
  60. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/local_exec.py +0 -0
  61. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/models/__init__.py +0 -0
  62. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/models/envelope.py +0 -0
  63. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/models/requests.py +0 -0
  64. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/models/responses.py +0 -0
  65. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/models/snapshots.py +0 -0
  66. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/platform_compat.py +0 -0
  67. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/py.typed +0 -0
  68. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/run_auto.py +0 -0
  69. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/sse.py +0 -0
  70. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/test.py +0 -0
  71. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/test_pipeline.py +0 -0
  72. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/__init__.py +0 -0
  73. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/dashboard.py +0 -0
  74. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/ip_allowlist.py +0 -0
  75. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/jobs.py +0 -0
  76. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/runner.py +0 -0
  77. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/security.py +0 -0
  78. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/server.py +0 -0
  79. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/service.py +0 -0
  80. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/setup_manager.py +0 -0
  81. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/static/agents.html +0 -0
  82. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/static/index.html +0 -0
  83. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/static/runs.html +0 -0
  84. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/static/setup.html +0 -0
  85. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/static/styles.css +0 -0
  86. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/ui/static/tickets.html +0 -0
  87. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/sdk/updater.py +0 -0
  88. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/setup.cfg +0 -0
  89. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/tests/test_agent_chat_features.py +0 -0
  90. {devops_bot_sdk-1.4.118 → devops_bot_sdk-1.4.119}/tests/test_agents_connectors_builder.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devops-bot-sdk
3
- Version: 1.4.118
3
+ Version: 1.4.119
4
4
  Summary: DevOps Bot Desktop SDK — thin client for the AgentOS Electron desktop app
5
5
  Author: noumanaziz2128
6
6
  License-Expression: LicenseRef-Proprietary
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devops-bot-sdk
3
- Version: 1.4.118
3
+ Version: 1.4.119
4
4
  Summary: DevOps Bot Desktop SDK — thin client for the AgentOS Electron desktop app
5
5
  Author: noumanaziz2128
6
6
  License-Expression: LicenseRef-Proprietary
@@ -79,7 +79,6 @@ sdk/ui/static/app.js
79
79
  sdk/ui/static/custom-agents.html
80
80
  sdk/ui/static/default-agents.html
81
81
  sdk/ui/static/index.html
82
- sdk/ui/static/prompt-studio.html
83
82
  sdk/ui/static/runs.html
84
83
  sdk/ui/static/setup.html
85
84
  sdk/ui/static/styles.css
@@ -1,6 +1,6 @@
1
1
  """AgentOS Desktop SDK — thin HTTPS/SSE client for the Electron app.
2
2
 
3
- Version: 1.4.118
3
+ Version: 1.4.119
4
4
 
5
5
  Public surface:
6
6
  BackendClient.from_config() — create client from ~/.agentos/config.toml
@@ -30,7 +30,7 @@ Rules:
30
30
  - All data egress through submit_webhook only
31
31
  """
32
32
 
33
- __version__ = "1.4.118" # SINGLE SOURCE OF TRUTH — bump on every change; pyproject,
33
+ __version__ = "1.4.119" # SINGLE SOURCE OF TRUTH — bump on every change; pyproject,
34
34
  __author__ = "AgentOS" # sdk.client.SDK_VERSION and the UI server version all read this.
35
35
 
36
36
  from sdk.client import BackendClient
@@ -15,9 +15,9 @@ See docs/GUIDE_2_Development_Plan_Custom_Agents.md:
15
15
  ``sdk/run_auto.py`` (which only ever drives the Jira To-Do queue) into a
16
16
  general-purpose daemon with five components:
17
17
  1. manifest loader — ``sdk.agents.manifest.load_agents()``
18
- 2. registration push every loaded PERSONAL manifest to the
19
- backend (``BackendClient.register_custom_agent``)
20
- so dashboards/routing stay in sync
18
+ 2. (removed) registration the daemon no longer pushes local manifests to
19
+ the backend; agents are authored in the web app
20
+ and the SDK is consume-only (local trigger/run).
21
21
  3. department pull — fetch this user's DEPARTMENT default agents
22
22
  (``BackendClient.list_department_agents()``)
23
23
  and materialize them alongside personal
@@ -451,12 +451,11 @@ class AgentDaemon:
451
451
  department = await self._load_department_agents()
452
452
  self._manifests = personal + department
453
453
 
454
+ # Consume-only: the daemon no longer registers/pushes local manifests to
455
+ # the backend — agents are authored in the web app and written to the
456
+ # `agents` table. The daemon just schedules + runs them LOCALLY on trigger.
454
457
  for m in personal:
455
458
  self._schedule_if_cron(m, job_id=m.name)
456
- try:
457
- await self.client.register_custom_agent(m.model_dump(mode="json"))
458
- except Exception as exc: # noqa: BLE001 — registration is best-effort
459
- logger.warning("agentd.register_failed agent=%s err=%s", m.name, exc)
460
459
 
461
460
  for m in department:
462
461
  # "dept:" job-id prefix avoids colliding with a personal agent
@@ -104,10 +104,10 @@ def _print_usage() -> None:
104
104
  print("usage: agentos <configure|agent|integration|default-agents|agentd> ...")
105
105
  print()
106
106
  print(" agentos configure [--rotate]")
107
- print(" agentos agent <new|add PATH|list|run NAME|chat NAME MSG|logs NAME|enable NAME|disable NAME|rm NAME>")
107
+ print(" agentos agent <list|run NAME|chat NAME MSG|logs NAME|enable NAME|disable NAME|rm NAME>")
108
108
  print(" agentos agent <set-key NAME KEY[=VALUE]…|keys NAME|rm-key NAME KEY…> # persistent API keys (custom agents)")
109
109
  print(" agentos integration <add PATH|test NAME|list|rm NAME>")
110
- print(" agentos default-agents <list|activate NAME|seed PATH|seed-library [SLUG]|enable NAME|disable NAME|rm NAME> [--department-id UUID]")
110
+ print(" agentos default-agents list [--department-id UUID] # read-only; agents are created in the web app")
111
111
  print(" agentos agentd <start [--foreground]|status>")
112
112
 
113
113
 
@@ -117,11 +117,13 @@ def _agent_command(args: list[str]) -> None:
117
117
  verb = args[0] if args else None
118
118
  rest = args[1:]
119
119
 
120
- if verb == "new":
121
- _agent_new()
122
- return
123
- if verb == "add" and rest:
124
- _agent_add(rest[0])
120
+ # Agent CREATION (`new` / `add`) is not owned by the SDK anymore — agents are
121
+ # authored in the web app and written to the backend `agents` table. The CLI is
122
+ # consume-only: list / run / chat / logs / enable / disable / rm / keys.
123
+ if verb in ("new", "add"):
124
+ print("`agentos agent new/add` has been removed — agents are created in the "
125
+ "web app now. Use `agentos agent list` to see yours and `agentos agent "
126
+ "run <name>` to run one.")
125
127
  return
126
128
  if verb == "list":
127
129
  _agent_list()
@@ -132,10 +134,6 @@ def _agent_command(args: list[str]) -> None:
132
134
  if verb == "chat" and len(rest) >= 2:
133
135
  _agent_chat(rest[0], " ".join(rest[1:]))
134
136
  return
135
- if verb == "template":
136
- from sdk.agents.prompt_template import render_system_prompt
137
- print(render_system_prompt(name=(rest[0] if rest else "my-agent")))
138
- return
139
137
  if verb == "logs" and rest:
140
138
  _agent_logs(rest[0])
141
139
  return
@@ -183,80 +181,6 @@ def _agent_chat(name: str, message: str) -> None:
183
181
  sys.exit(1)
184
182
 
185
183
 
186
- def _register_agent(manifest) -> None:
187
- """Register a validated manifest with the backend — shared by `new` and `add`."""
188
- from sdk.client import BackendClient
189
-
190
- resp = asyncio.run(
191
- BackendClient.from_config().register_custom_agent(manifest.model_dump(mode="json"))
192
- )
193
- resp = resp or {}
194
- agent_id = resp.get("id") or resp.get("agent_id")
195
- status = resp.get("status")
196
- print(f"registered '{manifest.name}' with backend — id={agent_id} status={status}")
197
-
198
-
199
- def _agent_new() -> None:
200
- from sdk.agents.manifest import AGENTS_DIR, AgentManifest, TriggerSpec
201
-
202
- print("AgentOS — New Agent")
203
- print("=" * 40)
204
- name = input("Name: ").strip()
205
- description = input("Description: ").strip()
206
- engine = input("Engine [claude_code]: ").strip() or "claude_code"
207
- trigger_type = input("Trigger type (schedule/ticket_label/manual/webhook): ").strip()
208
-
209
- trigger_kwargs: dict = {"type": trigger_type}
210
- if trigger_type == "schedule":
211
- trigger_kwargs["cron"] = input("Cron string: ").strip()
212
- elif trigger_type == "ticket_label":
213
- trigger_kwargs["ticket_label"] = input("Ticket label: ").strip()
214
- # manual / webhook need no extra prompt
215
-
216
- prompt_text = input("Prompt: ").strip()
217
-
218
- try:
219
- trigger = TriggerSpec(**trigger_kwargs)
220
- manifest = AgentManifest(
221
- name=name,
222
- description=description,
223
- engine=engine,
224
- trigger=trigger,
225
- prompt=prompt_text,
226
- )
227
- except Exception as exc: # noqa: BLE001 — surface pydantic's validation message plainly
228
- print(f"error: invalid agent — {exc}")
229
- sys.exit(1)
230
-
231
- AGENTS_DIR.mkdir(parents=True, exist_ok=True)
232
- dest = AGENTS_DIR / f"{manifest.name}.yaml"
233
- dest.write_text(yaml.safe_dump(manifest.model_dump(mode="json"), sort_keys=False))
234
- print(f"saved manifest to {dest}")
235
-
236
- _register_agent(manifest)
237
-
238
-
239
- def _agent_add(path: str) -> None:
240
- from sdk.agents.manifest import AGENTS_DIR, AgentManifest
241
-
242
- src = Path(path).expanduser()
243
- try:
244
- raw_text = src.read_text()
245
- data = yaml.safe_load(raw_text) or {}
246
- manifest = AgentManifest(**data)
247
- except Exception as exc: # noqa: BLE001 — surface a clear validation/IO error
248
- print(f"error: invalid agent manifest '{path}' — {exc}")
249
- sys.exit(1)
250
-
251
- AGENTS_DIR.mkdir(parents=True, exist_ok=True)
252
- dest = AGENTS_DIR / f"{manifest.name}.yaml"
253
- if dest.resolve() != src.resolve():
254
- dest.write_text(raw_text)
255
- print(f"copied manifest to {dest}")
256
-
257
- _register_agent(manifest)
258
-
259
-
260
184
  def _agent_list() -> None:
261
185
  from sdk.agents.manifest import load_agents
262
186
  from sdk.client import BackendClient
@@ -543,201 +467,39 @@ def _default_agents_command(args: list[str]) -> None:
543
467
  if verb == "list":
544
468
  _default_agents_list(_resolve_department_id(dept_id))
545
469
  return
546
- if verb == "activate" and tail:
547
- _default_agents_activate(_resolve_department_id(dept_id), tail[0])
548
- return
549
- # ── manager verbs (team_lead+ of the department) ──
550
- # Gated client-side by role (employees are refused); the backend also enforces.
551
- if verb == "seed" and tail:
552
- _require_department_manager(verb)
553
- _default_agents_seed(_resolve_department_id(dept_id), tail)
554
- return
555
- if verb == "seed-library":
556
- _require_department_manager(verb)
557
- _default_agents_seed_library(_resolve_department_id(dept_id), tail)
558
- return
559
- if verb in ("enable", "disable") and tail:
560
- _require_department_manager(verb)
561
- _default_agents_set_status(
562
- _resolve_department_id(dept_id), tail[0],
563
- "active" if verb == "enable" else "disabled",
564
- )
565
- return
566
- if verb == "rm" and tail:
567
- _require_department_manager(verb)
568
- _default_agents_rm(_resolve_department_id(dept_id), tail[0])
470
+
471
+ # Seeding / activating / managing department defaults is not owned by the SDK
472
+ # anymore — agents are authored in the web app and written to the backend
473
+ # `agents` table. The CLI is consume-only.
474
+ if verb in ("seed", "seed-library", "activate", "enable", "disable", "rm"):
475
+ print(f"`agentos default-agents {verb}` has been removed — department default "
476
+ "agents are managed in the web app now. Use `agentos default-agents list`.")
569
477
  return
570
478
 
571
- print(
572
- "usage: agentos default-agents "
573
- "<list|activate NAME|seed PATH|seed-library [SLUG]|enable NAME|disable NAME|rm NAME> "
574
- "[--department-id UUID]"
575
- )
576
- print(" (seed/enable/disable/rm require department-manager rights)")
479
+ print("usage: agentos default-agents list [--department-id UUID]")
577
480
  sys.exit(1)
578
481
 
579
482
 
580
- def _default_agents_seed(department_id: str, tail: list[str]) -> None:
581
- """Create/update ONE department default from a manifest YAML (manager only).
582
-
583
- Flags: --min-role-tier TIER, --sort-order N, --system.
584
- """
585
- import yaml
586
-
587
- path = tail[0]
588
- min_tier, sort_order, is_system = "employee", 0, False
589
- i = 1
590
- while i < len(tail):
591
- if tail[i] == "--min-role-tier" and i + 1 < len(tail):
592
- min_tier = tail[i + 1]; i += 2; continue
593
- if tail[i] == "--sort-order" and i + 1 < len(tail):
594
- sort_order = int(tail[i + 1]); i += 2; continue
595
- if tail[i] == "--system":
596
- is_system = True; i += 1; continue
597
- i += 1
598
-
599
- from sdk.agents.manifest import AgentManifest
600
- from sdk.client import BackendClient
601
-
602
- try:
603
- raw = yaml.safe_load(Path(path).expanduser().read_text()) or {}
604
- AgentManifest(**raw) # validate before sending
605
- except Exception as exc: # noqa: BLE001
606
- print(f"error: invalid manifest '{path}' — {exc}")
607
- sys.exit(1)
608
-
609
- payload = {
610
- "manifest": raw,
611
- "min_role_tier": min_tier,
612
- "is_system_default": is_system,
613
- "sort_order": sort_order,
614
- }
615
- try:
616
- result = asyncio.run(
617
- BackendClient.from_config().seed_department_default_agent(department_id, payload)
618
- )
619
- except Exception as exc: # noqa: BLE001 — surface 403 (not a manager) clearly
620
- print(f"error: {exc}")
621
- sys.exit(1)
622
- print(f"seeded default agent '{raw.get('name')}' into department {department_id} "
623
- f"(id={result.get('agent_id')})")
624
-
625
-
626
- def _default_agents_seed_library(department_id: str, tail: list[str]) -> None:
627
- """Seed a whole department's bundled library (manager only). SLUG defaults to 'developers'."""
628
- from sdk.agents.library import load_department
629
- from sdk.client import BackendClient
630
-
631
- slug = tail[0] if tail else "developers"
632
- try:
633
- templates = load_department(slug)
634
- except KeyError:
635
- print(f"error: no library department '{slug}'")
636
- sys.exit(1)
637
-
638
- client = BackendClient.from_config()
639
- ok = 0
640
- for t in templates:
641
- payload = {
642
- "manifest": t.manifest.model_dump(mode="json"),
643
- "min_role_tier": t.min_role_tier,
644
- "is_system_default": t.is_system_default,
645
- "sort_order": t.sort_order,
646
- }
647
- try:
648
- asyncio.run(client.seed_department_default_agent(department_id, payload))
649
- print(f" seeded {t.manifest.name}")
650
- ok += 1
651
- except Exception as exc: # noqa: BLE001
652
- print(f" FAILED {t.manifest.name}: {exc}", file=sys.stderr)
653
- print(f"seeded {ok}/{len(templates)} '{slug}' agents into department {department_id}")
654
-
655
-
656
- def _default_agents_set_status(department_id: str, name: str, status: str) -> None:
657
- from sdk.client import BackendClient
658
- try:
659
- asyncio.run(
660
- BackendClient.from_config().update_department_default_agent(
661
- department_id, name, status
662
- )
663
- )
664
- except Exception as exc: # noqa: BLE001
665
- print(f"error: {exc}")
666
- sys.exit(1)
667
- print(f"default agent '{name}' set to {status}")
668
-
669
-
670
- def _default_agents_rm(department_id: str, name: str) -> None:
671
- from sdk.client import BackendClient
672
- try:
673
- asyncio.run(
674
- BackendClient.from_config().delete_department_default_agent(department_id, name)
675
- )
676
- except Exception as exc: # noqa: BLE001
677
- print(f"error: {exc}")
678
- sys.exit(1)
679
- print(f"deleted default agent '{name}' from department {department_id}")
680
-
681
-
682
483
  def _default_agents_list(department_id: str) -> None:
484
+ """List the caller's department default agents (read-only, new prompt schema)."""
683
485
  from sdk.client import BackendClient
684
486
  from sdk.exceptions import BackendFeatureMissing
685
487
 
686
488
  try:
687
- agents = asyncio.run(
688
- BackendClient.from_config().list_department_default_agents(department_id)
689
- )
489
+ agents = asyncio.run(BackendClient.from_config().list_department_agents())
690
490
  except BackendFeatureMissing as exc:
691
- # A 404 here means the endpoint isn't deployed — NOT that the department
692
- # has no defaults. Say so, so this isn't mistaken for an empty list.
693
491
  print(f"error: {exc}")
694
492
  sys.exit(1)
695
493
  if not agents:
696
- print(f"no default agents seeded for department {department_id} "
697
- f"(a manager can add them with `agentos default-agents seed …`).")
494
+ print(f"no department default agents visible for department {department_id}.")
698
495
  return
699
496
 
700
- print(f"{'NAME':<26}{'ENGINE':<13}{'TRIGGER':<14}{'MIN TIER':<11}{'STATUS'}")
497
+ print(f"{'NAME':<28}{'STATUS':<10}{'SKILLS':<8}SUMMARY")
701
498
  for a in agents:
702
- print(
703
- f"{a.get('name',''):<26}{a.get('engine',''):<13}"
704
- f"{a.get('trigger_type',''):<14}{a.get('min_role_tier',''):<11}{a.get('status','')}"
705
- )
706
-
707
-
708
- def _default_agents_activate(department_id: str, name: str) -> None:
709
- """Clone a department default into the caller's custom agents + install locally."""
710
- import yaml as _yaml
711
-
712
- from sdk.agents.library import find_template
713
- from sdk.agents.manifest import AGENTS_DIR, SKILLS_DIR
714
- from sdk.client import BackendClient
715
-
716
- result = asyncio.run(
717
- BackendClient.from_config().activate_department_default_agent(department_id, name)
718
- )
719
- manifest = result.get("manifest") or {}
720
-
721
- # Install the manifest locally so agentd / `agent run` can execute it.
722
- if manifest:
723
- AGENTS_DIR.mkdir(parents=True, exist_ok=True)
724
- (AGENTS_DIR / f"{name}.yaml").write_text(
725
- _yaml.safe_dump(manifest, sort_keys=False)
726
- )
727
-
728
- # Copy any skills the template bundles into ~/.agentos/skills.
729
- template = find_template(name)
730
- copied_skills: list[str] = []
731
- if template and template.skills:
732
- SKILLS_DIR.mkdir(parents=True, exist_ok=True)
733
- for skill_name, path in template.skills.items():
734
- (SKILLS_DIR / f"{skill_name}.md").write_text(path.read_text(encoding="utf-8"))
735
- copied_skills.append(skill_name)
736
-
737
- print(f"activated '{name}' — cloned to your custom agents (id={result.get('custom_agent_id')})")
738
- print(f" installed manifest to {AGENTS_DIR / (name + '.yaml')}")
739
- if copied_skills:
740
- print(f" installed skills: {', '.join(copied_skills)}")
499
+ prompt = a.get("prompt") or {}
500
+ summary = (prompt.get("system_prompt") if isinstance(prompt, dict) else "") or ""
501
+ print(f"{a.get('name',''):<28}{a.get('status',''):<10}"
502
+ f"{len(a.get('skills') or []):<8}{summary.strip()[:60]}")
741
503
 
742
504
 
743
505
  # ── agentd ───────────────────────────────────────────────────────────────
@@ -1202,47 +1202,10 @@ class BackendClient:
1202
1202
  _check_status(resp.status_code, self._base_url)
1203
1203
  return resp.json()
1204
1204
 
1205
- # ── Custom agents ─────────────────────────────────────────────────
1206
-
1207
- async def register_custom_agent(self, manifest: dict) -> dict:
1208
- """POST /api/v1/agents/register register a custom agent manifest.
1209
-
1210
- Guards the network boundary: a manifest carrying an inline secret is
1211
- rejected locally before anything is sent — custom-agent secrets stay on
1212
- the machine where the agent is installed, never in the backend DB.
1213
- """
1214
- from sdk.agents.manifest import assert_secret_free
1215
- assert_secret_free(manifest, "manifest")
1216
- async with httpx.AsyncClient(timeout=15.0) as client:
1217
- resp = await client.post(
1218
- self._url("/api/v1/agents/register"),
1219
- json=manifest,
1220
- headers=self._headers,
1221
- )
1222
- _check_status(resp.status_code, self._base_url)
1223
- return resp.json()
1224
-
1225
- async def register_department_agent(self, manifest: dict) -> dict:
1226
- """POST /api/v1/department-agents/register — publish a DEPARTMENT default.
1227
-
1228
- Head-gated server-side (team_lead+ of the caller's own department, or
1229
- master → 403 otherwise). Same secret-free guard as a custom agent: the
1230
- manifest may only carry ${ENV_VAR} placeholders, never raw secrets —
1231
- department agents resolve their keys from the backend/host environment.
1232
- """
1233
- from sdk.agents.manifest import assert_secret_free
1234
- assert_secret_free(manifest, "manifest")
1235
- url = self._url("/api/v1/department-agents/register")
1236
- async with httpx.AsyncClient(timeout=15.0) as client:
1237
- resp = await client.post(url, json=manifest, headers=self._headers)
1238
- if resp.status_code == 404:
1239
- raise BackendFeatureMissing("Department agent registration", url)
1240
- if resp.status_code == 403:
1241
- raise PermissionError(
1242
- "only a department manager (team_lead+) may publish a department default agent"
1243
- )
1244
- _check_status(resp.status_code, self._base_url)
1245
- return resp.json()
1205
+ # ── Custom agents (CONSUME-ONLY) ──────────────────────────────────
1206
+ # Agent CREATION is not owned by the SDK anymore — agents are authored in the
1207
+ # web app and written to the backend `agents` table (prompt/secrets/skills).
1208
+ # This client only lists/reads them and manages per-agent status/delete.
1246
1209
 
1247
1210
  async def list_custom_agents(self) -> list[dict]:
1248
1211
  """GET /api/v1/agents — list registered custom agents."""
@@ -1298,66 +1261,10 @@ class BackendClient:
1298
1261
  _check_status(resp.status_code, self._base_url)
1299
1262
  return resp.json().get("agents", [])
1300
1263
 
1301
- # ── Department default agents ───────────────────────────────────────
1302
-
1303
- async def list_department_default_agents(self, department_id: str) -> list[dict]:
1304
- """GET /api/v1/departments/{id}/default-agents templates the caller can see."""
1305
- url = self._url(f"/api/v1/departments/{department_id}/default-agents")
1306
- async with httpx.AsyncClient(timeout=15.0) as client:
1307
- resp = await client.get(url, headers=self._headers)
1308
- if resp.status_code == 404:
1309
- raise BackendFeatureMissing("Department default agents", url)
1310
- _check_status(resp.status_code, self._base_url)
1311
- return resp.json().get("agents", [])
1312
-
1313
- async def seed_department_default_agent(self, department_id: str, payload: dict) -> dict:
1314
- """POST /api/v1/departments/{id}/default-agents/seed — upsert one template.
1315
-
1316
- Same secret-free guard as custom-agent registration: default-agent
1317
- templates are stored sans secrets; ${ENV_VAR} placeholders only.
1318
- """
1319
- from sdk.agents.manifest import assert_secret_free
1320
- assert_secret_free(payload, "default_agent")
1321
- async with httpx.AsyncClient(timeout=15.0) as client:
1322
- resp = await client.post(
1323
- self._url(f"/api/v1/departments/{department_id}/default-agents/seed"),
1324
- json=payload,
1325
- headers=self._headers,
1326
- )
1327
- _check_status(resp.status_code, self._base_url)
1328
- return resp.json()
1329
-
1330
- async def activate_department_default_agent(self, department_id: str, name: str) -> dict:
1331
- """POST /api/v1/departments/{id}/default-agents/{name}/activate — clone to my custom agents."""
1332
- async with httpx.AsyncClient(timeout=15.0) as client:
1333
- resp = await client.post(
1334
- self._url(f"/api/v1/departments/{department_id}/default-agents/{name}/activate"),
1335
- headers=self._headers,
1336
- )
1337
- _check_status(resp.status_code, self._base_url)
1338
- return resp.json()
1339
-
1340
- async def update_department_default_agent(
1341
- self, department_id: str, name: str, status: str
1342
- ) -> dict:
1343
- """PATCH /api/v1/departments/{id}/default-agents/{name} — enable/disable (manager only)."""
1344
- async with httpx.AsyncClient(timeout=15.0) as client:
1345
- resp = await client.patch(
1346
- self._url(f"/api/v1/departments/{department_id}/default-agents/{name}"),
1347
- json={"status": status},
1348
- headers=self._headers,
1349
- )
1350
- _check_status(resp.status_code, self._base_url)
1351
- return resp.json()
1352
-
1353
- async def delete_department_default_agent(self, department_id: str, name: str) -> None:
1354
- """DELETE /api/v1/departments/{id}/default-agents/{name} — soft-delete (manager only)."""
1355
- async with httpx.AsyncClient(timeout=15.0) as client:
1356
- resp = await client.delete(
1357
- self._url(f"/api/v1/departments/{department_id}/default-agents/{name}"),
1358
- headers=self._headers,
1359
- )
1360
- _check_status(resp.status_code, self._base_url)
1264
+ # NOTE: the legacy per-department "default agents" endpoints
1265
+ # (/departments/{id}/default-agents[/seed|/activate|...]) were retired — that
1266
+ # table never existed. Department defaults are now plain rows in the `agents`
1267
+ # table (relation_type=department), read via `list_department_agents` above.
1361
1268
 
1362
1269
  async def list_connected_services(self) -> list[str]:
1363
1270
  """Best-effort: services the caller has connected (for connector discovery).
@@ -3957,15 +3957,15 @@ async def handle_orchestrate_auto_local_run(
3957
3957
  async def handle_agent_create(
3958
3958
  client: BackendClient, payload: dict, send: Callable
3959
3959
  ) -> None:
3960
- """agent:create — register a new custom agent manifest."""
3960
+ """agent:create — REMOVED. Agent creation is not owned by the SDK anymore;
3961
+ agents are authored in the web app and written to the backend `agents` table.
3962
+ """
3961
3963
  thread_id = str(payload.get("thread_id", "agent"))
3962
- try:
3963
- result = await client.register_custom_agent(payload["manifest"])
3964
- await send(Envelope(
3965
- type="agent.created", thread_id=thread_id, data=result,
3966
- ).model_dump())
3967
- except Exception as exc:
3968
- await send(_error_envelope(thread_id, exc).model_dump())
3964
+ await send(_error_envelope(
3965
+ thread_id,
3966
+ RuntimeError("Agent creation has moved to the web app — the desktop SDK is "
3967
+ "consume-only (list/run/manage). This action is no longer available."),
3968
+ ).model_dump())
3969
3969
 
3970
3970
 
3971
3971
  async def handle_agent_list(