gemcode 0.3.114__tar.gz → 0.3.116__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.
- {gemcode-0.3.114/src/gemcode.egg-info → gemcode-0.3.116}/PKG-INFO +1 -1
- {gemcode-0.3.114 → gemcode-0.3.116}/pyproject.toml +1 -1
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/invoke.py +9 -2
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/kaira_daemon.py +85 -2
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/kaira_ipc.py +4 -1
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/kaira_job_store.py +5 -1
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/org_tools.py +99 -45
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/subtask.py +101 -1
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tui/scrollback.py +32 -0
- {gemcode-0.3.114 → gemcode-0.3.116/src/gemcode.egg-info}/PKG-INFO +1 -1
- {gemcode-0.3.114 → gemcode-0.3.116}/LICENSE +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/MANIFEST.in +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/README.md +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/setup.cfg +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/__init__.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/__main__.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/agent.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/audit.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/autocompact.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/automations.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/autotune.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/callbacks.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/capability_routing.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/checkpoints.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/cli.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/compaction.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/computer_use/__init__.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/computer_use/browser_computer.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/config.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/context_budget.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/context_warning.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/credentials.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/curated_memory.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/dynamic_policy.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/evals/harness.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/hitl_session.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/hooks.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/ide_protocol.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/ide_stdio.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/intent_classifier.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/interactions.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/kaira_client.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/learning.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/limits.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/live_audio_engine.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/logging_config.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/mcp_loader.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/memory/__init__.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/memory/embedding_memory_service.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/memory/file_memory_service.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/modality_tools.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/model_errors.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/model_routing.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/multimodal_input.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/openapi_loader.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/org.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/output_styles.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/paths.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/permissions.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/plugins/__init__.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/policy_profile.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/pricing.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/prompt_suggestions.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/query/__init__.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/query/config.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/query/deps.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/query/engine.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/query/stop_hooks.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/query/token_budget.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/query/transitions.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/query_sanitizer.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/refine.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/repl_commands.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/repl_slash.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/review_agent.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/rules.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/session_runtime.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/session_store.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/session_summariser.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/skills.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/slash_commands.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/thinking.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tool_prompt_manifest.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tool_registry.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tool_result_store.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/__init__.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/automations_tools.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/bash.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/browser.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/compress_memory.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/curated_memory.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/edit.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/filesystem.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/notebook.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/notes.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/repo_map.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/search.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/shell.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/shell_gate.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/skills.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/tasks.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/think.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/todo.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/user_choice.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/veomem_tools.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/web.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools/web_search.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tools_inspector.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/trust.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tui/input_handler.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tui/spinner.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tui/welcome_banner.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/tui/welcome_rich.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/veomem_bridge.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/version.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/vertex.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/wal.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/web/__init__.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/web/sse_adapter.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/web/terminal_repl.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/web/web_sse_compat.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode/workspace_hints.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode.egg-info/SOURCES.txt +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode.egg-info/dependency_links.txt +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode.egg-info/entry_points.txt +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode.egg-info/requires.txt +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/src/gemcode.egg-info/top_level.txt +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_add_dir.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_agent_instruction.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_autocompact.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_automations.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_capability_routing.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_checkpoint_diff_command.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_cli_init.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_compress_memory_tool.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_computer_use_permissions.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_context_budget.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_context_warning.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_credentials.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_eval_harness_layout.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_ide_stdio_attachments.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_interactive_permission_ask.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_kaira_scheduler.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_modality_tools.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_model_error_retry.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_model_errors.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_model_routing.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_multimodal_input.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_output_styles_and_rules.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_paths.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_permissions.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_prompt_suggestions.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_repl_commands.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_repl_slash.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_session_runtime_cache.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_skills.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_slash_commands.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_slash_completion_registry.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_thinking_config.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_token_budget.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_tool_context_circulation.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_tools.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_tools_inspector.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_web_sse_adapter.py +0 -0
- {gemcode-0.3.114 → gemcode-0.3.116}/tests/test_workspace_hints.py +0 -0
|
@@ -42,7 +42,14 @@ async def _maybe_enqueue_kaira_autopilot(*, cfg: "GemCodeConfig", session_id: st
|
|
|
42
42
|
return
|
|
43
43
|
object.__setattr__(cfg, "_kaira_autopilot_fp", fp)
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
try:
|
|
46
|
+
from gemcode.org import resolve_fleet_root
|
|
47
|
+
|
|
48
|
+
fleet_root = resolve_fleet_root(cfg.project_root)
|
|
49
|
+
except Exception:
|
|
50
|
+
fleet_root = cfg.project_root
|
|
51
|
+
|
|
52
|
+
sock = os.environ.get("GEMCODE_KAIRA_SOCKET") or str(fleet_root / ".gemcode" / "ipc.sock")
|
|
46
53
|
if not Path(sock).exists():
|
|
47
54
|
return
|
|
48
55
|
# Heuristic: suggest likely checks, but let the agent choose based on repo.
|
|
@@ -70,7 +77,7 @@ async def _maybe_enqueue_kaira_autopilot(*, cfg: "GemCodeConfig", session_id: st
|
|
|
70
77
|
)
|
|
71
78
|
if auto_org:
|
|
72
79
|
from gemcode.org import find_member
|
|
73
|
-
m = find_member(
|
|
80
|
+
m = find_member(fleet_root, "kaira")
|
|
74
81
|
if m is not None and m.kind == "kaira_worker":
|
|
75
82
|
from gemcode.tools.org_tools import make_org_tools
|
|
76
83
|
tools = make_org_tools(cfg)
|
|
@@ -151,6 +151,7 @@ class KairaJob:
|
|
|
151
151
|
prompt: str
|
|
152
152
|
priority: int
|
|
153
153
|
session_id: str
|
|
154
|
+
meta: dict | None = None
|
|
154
155
|
|
|
155
156
|
|
|
156
157
|
class KairaDaemon:
|
|
@@ -415,6 +416,7 @@ class KairaDaemon:
|
|
|
415
416
|
prompt: str,
|
|
416
417
|
priority: int | None = None,
|
|
417
418
|
session_id: str,
|
|
419
|
+
meta: dict | None = None,
|
|
418
420
|
) -> str:
|
|
419
421
|
"""Enqueue a new job into the priority queue and return job_id."""
|
|
420
422
|
job_id = f"job_{uuid.uuid4().hex[:10]}"
|
|
@@ -425,9 +427,10 @@ class KairaDaemon:
|
|
|
425
427
|
prompt=prompt,
|
|
426
428
|
priority=pr,
|
|
427
429
|
session_id=session_id,
|
|
430
|
+
meta=meta or None,
|
|
428
431
|
)
|
|
429
432
|
try:
|
|
430
|
-
rec = new_job_record(job_id=job_id, session_id=session_id, priority=pr, prompt=prompt)
|
|
433
|
+
rec = new_job_record(job_id=job_id, session_id=session_id, priority=pr, prompt=prompt, meta=meta or None)
|
|
431
434
|
self._job_records[job_id] = rec
|
|
432
435
|
self._store.upsert(rec)
|
|
433
436
|
except Exception:
|
|
@@ -469,7 +472,11 @@ class KairaDaemon:
|
|
|
469
472
|
|
|
470
473
|
try:
|
|
471
474
|
rec = self._job_records.get(job.job_id) or new_job_record(
|
|
472
|
-
job_id=job.job_id,
|
|
475
|
+
job_id=job.job_id,
|
|
476
|
+
session_id=job.session_id,
|
|
477
|
+
priority=job.priority,
|
|
478
|
+
prompt=job.prompt,
|
|
479
|
+
meta=(job.meta if isinstance(getattr(job, "meta", None), dict) else None),
|
|
473
480
|
)
|
|
474
481
|
self._job_records[job.job_id] = rec
|
|
475
482
|
self._store.upsert(mark_running(rec))
|
|
@@ -555,6 +562,46 @@ class KairaDaemon:
|
|
|
555
562
|
},
|
|
556
563
|
}
|
|
557
564
|
)
|
|
565
|
+
|
|
566
|
+
# If this job was enqueued as an org delegation, automatically publish
|
|
567
|
+
# an org.report back to the manager (and any notify_chain).
|
|
568
|
+
try:
|
|
569
|
+
meta = getattr(rec2, "meta", None) if isinstance(rec2, JobRecord) else None
|
|
570
|
+
org = meta.get("org") if isinstance(meta, dict) else None
|
|
571
|
+
if isinstance(org, dict):
|
|
572
|
+
member = org.get("member")
|
|
573
|
+
task = str(org.get("task") or "").strip()
|
|
574
|
+
context = str(org.get("context") or "").strip()
|
|
575
|
+
notify_chain = org.get("notify_chain")
|
|
576
|
+
if not isinstance(notify_chain, list):
|
|
577
|
+
notify_chain = ["manager"]
|
|
578
|
+
payload = {
|
|
579
|
+
"member": member if isinstance(member, dict) else {},
|
|
580
|
+
"capabilities": org.get("capabilities") if isinstance(org.get("capabilities"), dict) else {},
|
|
581
|
+
"status": "finished",
|
|
582
|
+
"task": task,
|
|
583
|
+
"context": context,
|
|
584
|
+
"job_id": job.job_id,
|
|
585
|
+
"error": "",
|
|
586
|
+
"result": {
|
|
587
|
+
"report_json": report_obj,
|
|
588
|
+
"report": (text or "")[:8000],
|
|
589
|
+
},
|
|
590
|
+
"notify_chain": notify_chain,
|
|
591
|
+
}
|
|
592
|
+
for to_addr in notify_chain:
|
|
593
|
+
await self._ipc.broadcast(
|
|
594
|
+
{
|
|
595
|
+
"type": "event",
|
|
596
|
+
"event": "bus_message",
|
|
597
|
+
"topic": "org.report",
|
|
598
|
+
"to": str(to_addr or "manager"),
|
|
599
|
+
"from_addr": "runtime",
|
|
600
|
+
"payload": payload,
|
|
601
|
+
}
|
|
602
|
+
)
|
|
603
|
+
except Exception:
|
|
604
|
+
pass
|
|
558
605
|
except Exception:
|
|
559
606
|
pass
|
|
560
607
|
except Exception:
|
|
@@ -618,6 +665,42 @@ class KairaDaemon:
|
|
|
618
665
|
)
|
|
619
666
|
except Exception:
|
|
620
667
|
pass
|
|
668
|
+
# Also emit org.report failures for org-delegated jobs.
|
|
669
|
+
try:
|
|
670
|
+
recf = self._job_records.get(job.job_id)
|
|
671
|
+
meta = getattr(recf, "meta", None) if recf is not None else None
|
|
672
|
+
org = meta.get("org") if isinstance(meta, dict) else None
|
|
673
|
+
if isinstance(org, dict):
|
|
674
|
+
member = org.get("member")
|
|
675
|
+
task = str(org.get("task") or "").strip()
|
|
676
|
+
context = str(org.get("context") or "").strip()
|
|
677
|
+
notify_chain = org.get("notify_chain")
|
|
678
|
+
if not isinstance(notify_chain, list):
|
|
679
|
+
notify_chain = ["manager"]
|
|
680
|
+
payload = {
|
|
681
|
+
"member": member if isinstance(member, dict) else {},
|
|
682
|
+
"capabilities": org.get("capabilities") if isinstance(org.get("capabilities"), dict) else {},
|
|
683
|
+
"status": "failed",
|
|
684
|
+
"task": task,
|
|
685
|
+
"context": context,
|
|
686
|
+
"job_id": job.job_id,
|
|
687
|
+
"error": f"{type(e).__name__}: {e}",
|
|
688
|
+
"result": None,
|
|
689
|
+
"notify_chain": notify_chain,
|
|
690
|
+
}
|
|
691
|
+
for to_addr in notify_chain:
|
|
692
|
+
await self._ipc.broadcast(
|
|
693
|
+
{
|
|
694
|
+
"type": "event",
|
|
695
|
+
"event": "bus_message",
|
|
696
|
+
"topic": "org.report",
|
|
697
|
+
"to": str(to_addr or "manager"),
|
|
698
|
+
"from_addr": "runtime",
|
|
699
|
+
"payload": payload,
|
|
700
|
+
}
|
|
701
|
+
)
|
|
702
|
+
except Exception:
|
|
703
|
+
pass
|
|
621
704
|
try:
|
|
622
705
|
rec3 = self._job_records.get(job.job_id)
|
|
623
706
|
if rec3 is not None:
|
|
@@ -250,7 +250,10 @@ class KairaIpcServer:
|
|
|
250
250
|
try:
|
|
251
251
|
pr = msg.get("priority", None)
|
|
252
252
|
sid = str(msg.get("session_id") or "").strip()
|
|
253
|
-
|
|
253
|
+
meta = msg.get("meta", None)
|
|
254
|
+
if not isinstance(meta, dict):
|
|
255
|
+
meta = None
|
|
256
|
+
job_id = self._enqueue_fn(prompt=prompt, priority=pr, session_id=sid, meta=meta)
|
|
254
257
|
client.emitter.send(make_response(id=req_id, ok=True, job_id=job_id))
|
|
255
258
|
except Exception as e:
|
|
256
259
|
client.emitter.send(
|
|
@@ -35,6 +35,7 @@ class JobRecord:
|
|
|
35
35
|
finished_ms: int | None = None
|
|
36
36
|
error: str | None = None
|
|
37
37
|
last_text: str = ""
|
|
38
|
+
meta: dict[str, Any] | None = None
|
|
38
39
|
|
|
39
40
|
def to_dict(self) -> dict[str, Any]:
|
|
40
41
|
return {
|
|
@@ -42,6 +43,7 @@ class JobRecord:
|
|
|
42
43
|
"session_id": self.session_id,
|
|
43
44
|
"priority": int(self.priority),
|
|
44
45
|
"prompt": self.prompt,
|
|
46
|
+
"meta": (self.meta or None),
|
|
45
47
|
"status": self.status,
|
|
46
48
|
"created_ms": int(self.created_ms),
|
|
47
49
|
"updated_ms": int(self.updated_ms),
|
|
@@ -83,6 +85,7 @@ class KairaJobStore:
|
|
|
83
85
|
session_id=str(obj.get("session_id") or ""),
|
|
84
86
|
priority=int(obj.get("priority") or 0),
|
|
85
87
|
prompt=str(obj.get("prompt") or ""),
|
|
88
|
+
meta=(obj.get("meta") if isinstance(obj.get("meta"), dict) else None),
|
|
86
89
|
status=str(obj.get("status") or "queued"), # type: ignore[arg-type]
|
|
87
90
|
created_ms=int(obj.get("created_ms") or 0),
|
|
88
91
|
updated_ms=int(obj.get("updated_ms") or 0),
|
|
@@ -110,13 +113,14 @@ class KairaJobStore:
|
|
|
110
113
|
return out
|
|
111
114
|
|
|
112
115
|
|
|
113
|
-
def new_job_record(*, job_id: str, session_id: str, priority: int, prompt: str) -> JobRecord:
|
|
116
|
+
def new_job_record(*, job_id: str, session_id: str, priority: int, prompt: str, meta: dict[str, Any] | None = None) -> JobRecord:
|
|
114
117
|
now = _now_ms()
|
|
115
118
|
return JobRecord(
|
|
116
119
|
job_id=job_id,
|
|
117
120
|
session_id=session_id,
|
|
118
121
|
priority=int(priority),
|
|
119
122
|
prompt=prompt,
|
|
123
|
+
meta=meta or None,
|
|
120
124
|
status="queued",
|
|
121
125
|
created_ms=now,
|
|
122
126
|
updated_ms=now,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import os
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
@@ -82,42 +83,60 @@ def make_org_tools(cfg: GemCodeConfig) -> list:
|
|
|
82
83
|
) -> None:
|
|
83
84
|
if not _bus_enabled():
|
|
84
85
|
return
|
|
85
|
-
|
|
86
|
-
from gemcode.kaira_client import KairaIpcClient
|
|
87
|
-
import os
|
|
86
|
+
fleet_root = resolve_fleet_root(getattr(cfg, "project_root", Path.cwd()))
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
getattr(cfg, "project_root", Path.cwd()) / ".gemcode" / "ipc.sock"
|
|
91
|
-
)
|
|
92
|
-
# Only attempt publish if socket exists (avoid noisy failures).
|
|
88
|
+
def _audit_fallback(payload: dict[str, Any], *, why: str) -> None:
|
|
93
89
|
try:
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
from gemcode.audit import append_audit
|
|
91
|
+
|
|
92
|
+
append_audit(
|
|
93
|
+
fleet_root,
|
|
94
|
+
{
|
|
95
|
+
"event": "org.report",
|
|
96
|
+
"why": why,
|
|
97
|
+
"payload": payload,
|
|
98
|
+
},
|
|
99
|
+
)
|
|
96
100
|
except Exception:
|
|
97
|
-
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
from_addr = str(getattr(m, "address", "") or getattr(m, "name", "") or "")
|
|
104
|
+
member_dict = (m.to_dict() if hasattr(m, "to_dict") else {})
|
|
105
|
+
# Capabilities snapshot: keep it small and stable.
|
|
106
|
+
caps = {
|
|
107
|
+
"kind": member_dict.get("kind"),
|
|
108
|
+
"address": member_dict.get("address") or from_addr,
|
|
109
|
+
"workspace_rel": member_dict.get("workspace_rel", ""),
|
|
110
|
+
"reports_to": member_dict.get("reports_to", ""),
|
|
111
|
+
}
|
|
112
|
+
chain = _ancestor_addresses_for(m)
|
|
113
|
+
payload: dict[str, Any] = {
|
|
114
|
+
"member": member_dict,
|
|
115
|
+
"capabilities": caps,
|
|
116
|
+
"status": status,
|
|
117
|
+
"task": task,
|
|
118
|
+
"context": context,
|
|
119
|
+
"job_id": job_id,
|
|
120
|
+
"error": error,
|
|
121
|
+
"result": result,
|
|
122
|
+
"notify_chain": chain,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
sock = os.environ.get("GEMCODE_KAIRA_SOCKET") or str(fleet_root / ".gemcode" / "ipc.sock")
|
|
126
|
+
# If runtime IPC isn't up, still persist the report locally.
|
|
127
|
+
try:
|
|
128
|
+
if not Path(sock).exists():
|
|
129
|
+
_audit_fallback(payload, why="ipc_socket_missing")
|
|
130
|
+
return
|
|
131
|
+
except Exception:
|
|
132
|
+
_audit_fallback(payload, why="ipc_socket_stat_failed")
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
from gemcode.kaira_client import KairaIpcClient
|
|
137
|
+
|
|
98
138
|
c = await KairaIpcClient.connect(socket_path=str(sock))
|
|
99
139
|
try:
|
|
100
|
-
from_addr = str(getattr(m, "address", "") or getattr(m, "name", "") or "")
|
|
101
|
-
member_dict = (m.to_dict() if hasattr(m, "to_dict") else {})
|
|
102
|
-
# Capabilities snapshot: keep it small and stable.
|
|
103
|
-
caps = {
|
|
104
|
-
"kind": member_dict.get("kind"),
|
|
105
|
-
"address": member_dict.get("address") or from_addr,
|
|
106
|
-
"workspace_rel": member_dict.get("workspace_rel", ""),
|
|
107
|
-
"reports_to": member_dict.get("reports_to", ""),
|
|
108
|
-
}
|
|
109
|
-
chain = _ancestor_addresses_for(m)
|
|
110
|
-
payload = {
|
|
111
|
-
"member": member_dict,
|
|
112
|
-
"capabilities": caps,
|
|
113
|
-
"status": status,
|
|
114
|
-
"task": task,
|
|
115
|
-
"context": context,
|
|
116
|
-
"job_id": job_id,
|
|
117
|
-
"error": error,
|
|
118
|
-
"result": result,
|
|
119
|
-
"notify_chain": chain,
|
|
120
|
-
}
|
|
121
140
|
# Notify parent, grandparent, ... (and manager).
|
|
122
141
|
for to_addr in chain:
|
|
123
142
|
await c.publish(
|
|
@@ -128,7 +147,8 @@ def make_org_tools(cfg: GemCodeConfig) -> list:
|
|
|
128
147
|
)
|
|
129
148
|
finally:
|
|
130
149
|
await c.close()
|
|
131
|
-
except Exception:
|
|
150
|
+
except Exception as e:
|
|
151
|
+
_audit_fallback(payload, why=f"ipc_publish_failed: {type(e).__name__}: {e}")
|
|
132
152
|
return
|
|
133
153
|
|
|
134
154
|
def org_list() -> dict:
|
|
@@ -191,21 +211,38 @@ def make_org_tools(cfg: GemCodeConfig) -> list:
|
|
|
191
211
|
prompt += "\n\nContext:\n" + ctx
|
|
192
212
|
|
|
193
213
|
if m.kind == "kaira_worker":
|
|
194
|
-
# Delegate to Kaira via IPC enqueue (background).
|
|
214
|
+
# Delegate to Kaira via IPC enqueue (background). If IPC is unavailable,
|
|
215
|
+
# fall back to an in-process subagent run so delegation still "just works".
|
|
195
216
|
try:
|
|
196
217
|
from gemcode.kaira_client import KairaIpcClient
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
)
|
|
200
|
-
sock_s = str(sock)
|
|
218
|
+
fleet_root = resolve_fleet_root(getattr(cfg, "project_root", Path.cwd()))
|
|
219
|
+
sock_s = os.environ.get("GEMCODE_KAIRA_SOCKET") or str(fleet_root / ".gemcode" / "ipc.sock")
|
|
201
220
|
client = await KairaIpcClient.connect(socket_path=sock_s)
|
|
202
221
|
try:
|
|
203
222
|
session_id = str(getattr(cfg, "_active_session_id", "") or "")
|
|
223
|
+
notify_chain = _ancestor_addresses_for(m)
|
|
224
|
+
# Attach org metadata so the runtime can auto-publish org.report when
|
|
225
|
+
# the job finishes/fails (default, no extra prompting needed).
|
|
226
|
+
meta = {
|
|
227
|
+
"org": {
|
|
228
|
+
"member": (m.to_dict() if hasattr(m, "to_dict") else {}),
|
|
229
|
+
"capabilities": {
|
|
230
|
+
"kind": getattr(m, "kind", ""),
|
|
231
|
+
"address": getattr(m, "address", "") or getattr(m, "name", ""),
|
|
232
|
+
"workspace_rel": getattr(m, "workspace_rel", "") or "",
|
|
233
|
+
"reports_to": getattr(m, "reports_to", "") or "",
|
|
234
|
+
},
|
|
235
|
+
"task": task,
|
|
236
|
+
"context": ctx,
|
|
237
|
+
"notify_chain": notify_chain,
|
|
238
|
+
}
|
|
239
|
+
}
|
|
204
240
|
res = await client.request(
|
|
205
241
|
action="enqueue",
|
|
206
242
|
prompt=prompt,
|
|
207
243
|
priority=0,
|
|
208
244
|
session_id=session_id,
|
|
245
|
+
meta=meta,
|
|
209
246
|
)
|
|
210
247
|
if not res.get("ok"):
|
|
211
248
|
await _publish_org_report(
|
|
@@ -229,14 +266,31 @@ def make_org_tools(cfg: GemCodeConfig) -> list:
|
|
|
229
266
|
finally:
|
|
230
267
|
await client.close()
|
|
231
268
|
except Exception as e:
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
269
|
+
# Fallback: run as a subagent right now (best-effort). This keeps UX
|
|
270
|
+
# consistent when users think "agent delegation" should always work.
|
|
271
|
+
try:
|
|
272
|
+
from gemcode.tools.subtask import make_run_subtask_tool
|
|
273
|
+
|
|
274
|
+
run_subtask = make_run_subtask_tool(cfg)
|
|
275
|
+
out = await run_subtask(prompt, "")
|
|
276
|
+
result = out.get("result") if isinstance(out, dict) else out
|
|
277
|
+
await _publish_org_report(
|
|
278
|
+
m=m,
|
|
279
|
+
status="finished",
|
|
280
|
+
task=task,
|
|
281
|
+
context=ctx,
|
|
282
|
+
result={"kind": "fallback_subagent", "error": f"kaira_ipc_unavailable: {type(e).__name__}: {e}", "result": result},
|
|
283
|
+
)
|
|
284
|
+
return {"ok": True, "delegated_to": m.to_dict(), "result": result, "fallback": "subagent"}
|
|
285
|
+
except Exception as e2:
|
|
286
|
+
await _publish_org_report(
|
|
287
|
+
m=m,
|
|
288
|
+
status="failed",
|
|
289
|
+
task=task,
|
|
290
|
+
context=ctx,
|
|
291
|
+
error=f"kaira_ipc_unavailable: {type(e).__name__}: {e}; fallback_subagent_failed: {type(e2).__name__}: {e2}",
|
|
292
|
+
)
|
|
293
|
+
return {"ok": False, "error": f"kaira_ipc_unavailable: {type(e).__name__}: {e}"}
|
|
240
294
|
|
|
241
295
|
# Delegate to an in-process isolated subagent.
|
|
242
296
|
try:
|
|
@@ -23,6 +23,9 @@ The sub-agent:
|
|
|
23
23
|
from __future__ import annotations
|
|
24
24
|
|
|
25
25
|
import asyncio
|
|
26
|
+
import os
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Any
|
|
26
29
|
from gemcode.config import GemCodeConfig
|
|
27
30
|
|
|
28
31
|
|
|
@@ -70,6 +73,60 @@ def _build_sub_tools(cfg: GemCodeConfig) -> list:
|
|
|
70
73
|
return tools
|
|
71
74
|
|
|
72
75
|
|
|
76
|
+
async def _publish_subtask_report(
|
|
77
|
+
*,
|
|
78
|
+
cfg: GemCodeConfig,
|
|
79
|
+
status: str,
|
|
80
|
+
task: str,
|
|
81
|
+
context: str,
|
|
82
|
+
sub_session_id: str,
|
|
83
|
+
result: object | None = None,
|
|
84
|
+
error: str = "",
|
|
85
|
+
) -> None:
|
|
86
|
+
"""
|
|
87
|
+
Durable report path for *all* in-process subagents:
|
|
88
|
+
- Publish to runtime bus when available
|
|
89
|
+
- Otherwise append to fleet-root `.gemcode/audit.log`
|
|
90
|
+
"""
|
|
91
|
+
try:
|
|
92
|
+
from gemcode.org import resolve_fleet_root
|
|
93
|
+
|
|
94
|
+
fleet_root = resolve_fleet_root(getattr(cfg, "project_root", Path.cwd()))
|
|
95
|
+
except Exception:
|
|
96
|
+
fleet_root = Path(getattr(cfg, "project_root", Path.cwd()))
|
|
97
|
+
|
|
98
|
+
payload: dict[str, Any] = {
|
|
99
|
+
"kind": "subagent",
|
|
100
|
+
"status": status,
|
|
101
|
+
"task": task,
|
|
102
|
+
"context": context,
|
|
103
|
+
"sub_session_id": sub_session_id,
|
|
104
|
+
"error": error,
|
|
105
|
+
"result": result,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
sock = os.environ.get("GEMCODE_KAIRA_SOCKET") or str(fleet_root / ".gemcode" / "ipc.sock")
|
|
109
|
+
try:
|
|
110
|
+
if Path(sock).exists():
|
|
111
|
+
from gemcode.kaira_client import KairaIpcClient
|
|
112
|
+
|
|
113
|
+
c = await KairaIpcClient.connect(socket_path=str(sock))
|
|
114
|
+
try:
|
|
115
|
+
await c.publish(topic="agent.report", to="manager", from_addr="subagent", payload=payload)
|
|
116
|
+
return
|
|
117
|
+
finally:
|
|
118
|
+
await c.close()
|
|
119
|
+
except Exception:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
from gemcode.audit import append_audit
|
|
124
|
+
|
|
125
|
+
append_audit(fleet_root, {"event": "agent.report", "payload": payload})
|
|
126
|
+
except Exception:
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
|
|
73
130
|
def make_run_subtask_tool(cfg: GemCodeConfig):
|
|
74
131
|
async def run_subtask(task: str, context: str = "") -> dict:
|
|
75
132
|
"""
|
|
@@ -155,8 +212,15 @@ def make_run_subtask_tool(cfg: GemCodeConfig):
|
|
|
155
212
|
sub_session_id = str(uuid.uuid4())
|
|
156
213
|
|
|
157
214
|
# Compose the sub-agent prompt.
|
|
158
|
-
task_clean = task.strip()
|
|
215
|
+
task_clean = (task or "").strip()
|
|
159
216
|
ctx_clean = (context or "").strip()
|
|
217
|
+
await _publish_subtask_report(
|
|
218
|
+
cfg=cfg,
|
|
219
|
+
status="started",
|
|
220
|
+
task=task_clean,
|
|
221
|
+
context=ctx_clean,
|
|
222
|
+
sub_session_id=sub_session_id,
|
|
223
|
+
)
|
|
160
224
|
prompt = task_clean
|
|
161
225
|
if ctx_clean:
|
|
162
226
|
prompt = f"{task_clean}\n\nAdditional context:\n{ctx_clean}"
|
|
@@ -188,6 +252,14 @@ def make_run_subtask_tool(cfg: GemCodeConfig):
|
|
|
188
252
|
cfg=cfg,
|
|
189
253
|
)
|
|
190
254
|
except Exception as e:
|
|
255
|
+
await _publish_subtask_report(
|
|
256
|
+
cfg=cfg,
|
|
257
|
+
status="failed",
|
|
258
|
+
task=task_clean,
|
|
259
|
+
context=ctx_clean,
|
|
260
|
+
sub_session_id=sub_session_id,
|
|
261
|
+
error=f"{type(e).__name__}: {e}",
|
|
262
|
+
)
|
|
191
263
|
return {"error": f"Sub-agent error: {type(e).__name__}: {e}"}
|
|
192
264
|
|
|
193
265
|
# Extract only non-thinking text parts from the sub-agent's output.
|
|
@@ -226,6 +298,18 @@ def make_run_subtask_tool(cfg: GemCodeConfig):
|
|
|
226
298
|
text=result_text,
|
|
227
299
|
preview_max_chars=max_chars,
|
|
228
300
|
)
|
|
301
|
+
await _publish_subtask_report(
|
|
302
|
+
cfg=cfg,
|
|
303
|
+
status="finished",
|
|
304
|
+
task=task_clean,
|
|
305
|
+
context=ctx_clean,
|
|
306
|
+
sub_session_id=sub_session_id,
|
|
307
|
+
result={
|
|
308
|
+
"offloaded": True,
|
|
309
|
+
"ref": ref_obj.get("ref"),
|
|
310
|
+
"preview": ref_obj.get("preview", "") or "",
|
|
311
|
+
},
|
|
312
|
+
)
|
|
229
313
|
return {
|
|
230
314
|
"result": ref_obj.get("preview", "") or "",
|
|
231
315
|
"offloaded": True,
|
|
@@ -234,8 +318,24 @@ def make_run_subtask_tool(cfg: GemCodeConfig):
|
|
|
234
318
|
}
|
|
235
319
|
except Exception:
|
|
236
320
|
result_text = result_text[:max_chars] + "\n… [truncated]"
|
|
321
|
+
await _publish_subtask_report(
|
|
322
|
+
cfg=cfg,
|
|
323
|
+
status="finished",
|
|
324
|
+
task=task_clean,
|
|
325
|
+
context=ctx_clean,
|
|
326
|
+
sub_session_id=sub_session_id,
|
|
327
|
+
result={"truncated": True, "result": result_text},
|
|
328
|
+
)
|
|
237
329
|
return {"result": result_text, "truncated": True}
|
|
238
330
|
|
|
331
|
+
await _publish_subtask_report(
|
|
332
|
+
cfg=cfg,
|
|
333
|
+
status="finished",
|
|
334
|
+
task=task_clean,
|
|
335
|
+
context=ctx_clean,
|
|
336
|
+
sub_session_id=sub_session_id,
|
|
337
|
+
result={"result": result_text},
|
|
338
|
+
)
|
|
239
339
|
return {"result": result_text}
|
|
240
340
|
|
|
241
341
|
return run_subtask
|
|
@@ -446,6 +446,38 @@ async def run_gemcode_scrollback_tui(
|
|
|
446
446
|
route = ""
|
|
447
447
|
if from_addr or to:
|
|
448
448
|
route = f" {from_addr or '?'}→{to or '*'}"
|
|
449
|
+
|
|
450
|
+
# Human-friendly rendering for common fleet-wide agent events.
|
|
451
|
+
try:
|
|
452
|
+
if topic in ("agent.report", "org.report") and isinstance(payload, dict):
|
|
453
|
+
status = str(payload.get("status") or "")
|
|
454
|
+
task = str(payload.get("task") or "").strip().replace("\n", " ")
|
|
455
|
+
task_short = (task[:160] + "…") if len(task) > 160 else task
|
|
456
|
+
if topic == "org.report":
|
|
457
|
+
mem = payload.get("member") or {}
|
|
458
|
+
mem_name = ""
|
|
459
|
+
try:
|
|
460
|
+
if isinstance(mem, dict):
|
|
461
|
+
mem_name = str(mem.get("name") or mem.get("id") or "")
|
|
462
|
+
except Exception:
|
|
463
|
+
mem_name = ""
|
|
464
|
+
jid = str(payload.get("job_id") or "")[:10]
|
|
465
|
+
prefix = f"{mem_name} " if mem_name else ""
|
|
466
|
+
extra = f" job={jid}" if jid else ""
|
|
467
|
+
await _kaira_print(
|
|
468
|
+
f"{ansi.dim}[{label}{route}]{ansi.reset} {prefix}{status}{extra} — {task_short}".rstrip()
|
|
469
|
+
)
|
|
470
|
+
continue
|
|
471
|
+
# agent.report
|
|
472
|
+
sid = str(payload.get("sub_session_id") or "")[:8]
|
|
473
|
+
extra = f" sub={sid}" if sid else ""
|
|
474
|
+
await _kaira_print(
|
|
475
|
+
f"{ansi.dim}[{label}{route}]{ansi.reset} {status}{extra} — {task_short}".rstrip()
|
|
476
|
+
)
|
|
477
|
+
continue
|
|
478
|
+
except Exception:
|
|
479
|
+
pass
|
|
480
|
+
|
|
449
481
|
try:
|
|
450
482
|
if isinstance(payload, (dict, list)):
|
|
451
483
|
import json as _json
|
|
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
|