cli-jaw 2.0.1 → 2.0.2
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.
- package/README.ko.md +3 -2
- package/README.md +41 -12
- package/dist/bin/_http-client.js +34 -0
- package/dist/bin/_http-client.js.map +1 -0
- package/dist/bin/cli-jaw.js +10 -5
- package/dist/bin/cli-jaw.js.map +1 -1
- package/dist/bin/commands/browser-web-ai.js +155 -38
- package/dist/bin/commands/browser-web-ai.js.map +1 -1
- package/dist/bin/commands/browser.js +265 -37
- package/dist/bin/commands/browser.js.map +1 -1
- package/dist/bin/commands/chat.js +18 -14
- package/dist/bin/commands/chat.js.map +1 -1
- package/dist/bin/commands/clone.js +3 -2
- package/dist/bin/commands/clone.js.map +1 -1
- package/dist/bin/commands/dashboard.js +22 -18
- package/dist/bin/commands/dashboard.js.map +1 -1
- package/dist/bin/commands/dispatch.js +9 -11
- package/dist/bin/commands/dispatch.js.map +1 -1
- package/dist/bin/commands/doctor.js +26 -14
- package/dist/bin/commands/doctor.js.map +1 -1
- package/dist/bin/commands/employee.js +12 -7
- package/dist/bin/commands/employee.js.map +1 -1
- package/dist/bin/commands/init.js +9 -9
- package/dist/bin/commands/init.js.map +1 -1
- package/dist/bin/commands/launchd.js +17 -7
- package/dist/bin/commands/launchd.js.map +1 -1
- package/dist/bin/commands/mcp.js +7 -4
- package/dist/bin/commands/mcp.js.map +1 -1
- package/dist/bin/commands/memory.js +7 -5
- package/dist/bin/commands/memory.js.map +1 -1
- package/dist/bin/commands/orchestrate.js +6 -3
- package/dist/bin/commands/orchestrate.js.map +1 -1
- package/dist/bin/commands/reset.js +4 -3
- package/dist/bin/commands/reset.js.map +1 -1
- package/dist/bin/commands/serve.js +3 -2
- package/dist/bin/commands/serve.js.map +1 -1
- package/dist/bin/commands/service.js +2 -2
- package/dist/bin/commands/service.js.map +1 -1
- package/dist/bin/commands/status.js +10 -9
- package/dist/bin/commands/status.js.map +1 -1
- package/dist/bin/commands/tui/api.js +26 -18
- package/dist/bin/commands/tui/api.js.map +1 -1
- package/dist/bin/commands/tui/overlays.js +3 -1
- package/dist/bin/commands/tui/overlays.js.map +1 -1
- package/dist/bin/commands/tui/simple-mode.js +1 -1
- package/dist/bin/commands/tui/simple-mode.js.map +1 -1
- package/dist/bin/commands/tui/types.js.map +1 -1
- package/dist/bin/postinstall.js +153 -65
- package/dist/bin/postinstall.js.map +1 -1
- package/dist/bin/star-prompt.js +4 -3
- package/dist/bin/star-prompt.js.map +1 -1
- package/dist/lib/mcp/format-converters.js +15 -10
- package/dist/lib/mcp/format-converters.js.map +1 -1
- package/dist/lib/mcp/mcp-install.js +2 -2
- package/dist/lib/mcp/mcp-install.js.map +1 -1
- package/dist/lib/mcp/skills-distribution.js +2 -2
- package/dist/lib/mcp/skills-distribution.js.map +1 -1
- package/dist/lib/mcp/skills-reset.js +5 -4
- package/dist/lib/mcp/skills-reset.js.map +1 -1
- package/dist/lib/mcp/skills-symlinks.js +9 -9
- package/dist/lib/mcp/skills-symlinks.js.map +1 -1
- package/dist/lib/mcp/skills-utils.js +5 -4
- package/dist/lib/mcp/skills-utils.js.map +1 -1
- package/dist/lib/mcp/unified-config.js +3 -2
- package/dist/lib/mcp/unified-config.js.map +1 -1
- package/dist/lib/mime-detect.js +65 -0
- package/dist/lib/mime-detect.js.map +1 -0
- package/dist/lib/quota-copilot.js +12 -10
- package/dist/lib/quota-copilot.js.map +1 -1
- package/dist/lib/stt.js +3 -3
- package/dist/lib/stt.js.map +1 -1
- package/dist/lib/upload.js +14 -5
- package/dist/lib/upload.js.map +1 -1
- package/dist/scripts/i18n-registry.js +4 -4
- package/dist/scripts/i18n-registry.js.map +1 -1
- package/dist/server.js +61 -57
- package/dist/server.js.map +1 -1
- package/dist/src/agent/alert-escalation.js +61 -0
- package/dist/src/agent/alert-escalation.js.map +1 -0
- package/dist/src/agent/args.js +71 -2
- package/dist/src/agent/args.js.map +1 -1
- package/dist/src/agent/error-classifier.js +9 -4
- package/dist/src/agent/error-classifier.js.map +1 -1
- package/dist/src/agent/events.js +130 -101
- package/dist/src/agent/events.js.map +1 -1
- package/dist/src/agent/lifecycle-handler.js +44 -19
- package/dist/src/agent/lifecycle-handler.js.map +1 -1
- package/dist/src/agent/live-run-state.js +7 -3
- package/dist/src/agent/live-run-state.js.map +1 -1
- package/dist/src/agent/memory-flush-controller.js +6 -4
- package/dist/src/agent/memory-flush-controller.js.map +1 -1
- package/dist/src/agent/opencode-diagnostics.js +7 -6
- package/dist/src/agent/opencode-diagnostics.js.map +1 -1
- package/dist/src/agent/session-persistence.js +1 -1
- package/dist/src/agent/session-persistence.js.map +1 -1
- package/dist/src/agent/spawn-env.js +33 -16
- package/dist/src/agent/spawn-env.js.map +1 -1
- package/dist/src/agent/spawn.js +176 -110
- package/dist/src/agent/spawn.js.map +1 -1
- package/dist/src/agent/watchdog.js +56 -0
- package/dist/src/agent/watchdog.js.map +1 -0
- package/dist/src/browser/actions.js +179 -70
- package/dist/src/browser/actions.js.map +1 -1
- package/dist/src/browser/connection.js +296 -19
- package/dist/src/browser/connection.js.map +1 -1
- package/dist/src/browser/index.js +4 -1
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/browser/launch-policy.js +1 -1
- package/dist/src/browser/launch-policy.js.map +1 -1
- package/dist/src/browser/primitives.js +11 -7
- package/dist/src/browser/primitives.js.map +1 -1
- package/dist/src/browser/runtime-diagnostics.js +45 -0
- package/dist/src/browser/runtime-diagnostics.js.map +1 -0
- package/dist/src/browser/runtime-orphans.js +127 -0
- package/dist/src/browser/runtime-orphans.js.map +1 -0
- package/dist/src/browser/runtime-owner-store.js +51 -0
- package/dist/src/browser/runtime-owner-store.js.map +1 -0
- package/dist/src/browser/runtime-owner.js +2 -2
- package/dist/src/browser/runtime-owner.js.map +1 -1
- package/dist/src/browser/tab-lifecycle.js +157 -0
- package/dist/src/browser/tab-lifecycle.js.map +1 -0
- package/dist/src/browser/vision.js +35 -11
- package/dist/src/browser/vision.js.map +1 -1
- package/dist/src/browser/web-ai/action-breadth.js +56 -0
- package/dist/src/browser/web-ai/action-breadth.js.map +1 -0
- package/dist/src/browser/web-ai/action-cache.js +9 -8
- package/dist/src/browser/web-ai/action-cache.js.map +1 -1
- package/dist/src/browser/web-ai/action-intent.js +64 -0
- package/dist/src/browser/web-ai/action-intent.js.map +1 -0
- package/dist/src/browser/web-ai/action-memory.js +82 -0
- package/dist/src/browser/web-ai/action-memory.js.map +1 -0
- package/dist/src/browser/web-ai/action-trace.js +11 -6
- package/dist/src/browser/web-ai/action-trace.js.map +1 -1
- package/dist/src/browser/web-ai/annotated-screenshot.js +2 -1
- package/dist/src/browser/web-ai/annotated-screenshot.js.map +1 -1
- package/dist/src/browser/web-ai/answer-artifact.js +97 -0
- package/dist/src/browser/web-ai/answer-artifact.js.map +1 -0
- package/dist/src/browser/web-ai/ax-snapshot.js +3 -2
- package/dist/src/browser/web-ai/ax-snapshot.js.map +1 -1
- package/dist/src/browser/web-ai/browser-primitives.js +10 -7
- package/dist/src/browser/web-ai/browser-primitives.js.map +1 -1
- package/dist/src/browser/web-ai/capability-registry.js +1 -1
- package/dist/src/browser/web-ai/capability-registry.js.map +1 -1
- package/dist/src/browser/web-ai/chatgpt-composer.js +12 -12
- package/dist/src/browser/web-ai/chatgpt-composer.js.map +1 -1
- package/dist/src/browser/web-ai/chatgpt-model.js +469 -50
- package/dist/src/browser/web-ai/chatgpt-model.js.map +1 -1
- package/dist/src/browser/web-ai/chatgpt-response.js +82 -10
- package/dist/src/browser/web-ai/chatgpt-response.js.map +1 -1
- package/dist/src/browser/web-ai/chatgpt.js +325 -49
- package/dist/src/browser/web-ai/chatgpt.js.map +1 -1
- package/dist/src/browser/web-ai/churn-log.js +1 -1
- package/dist/src/browser/web-ai/churn-log.js.map +1 -1
- package/dist/src/browser/web-ai/cli-sessions.js +42 -26
- package/dist/src/browser/web-ai/cli-sessions.js.map +1 -1
- package/dist/src/browser/web-ai/context-pack/builder.js +1 -1
- package/dist/src/browser/web-ai/context-pack/builder.js.map +1 -1
- package/dist/src/browser/web-ai/context-pack/file-selector.js +2 -2
- package/dist/src/browser/web-ai/context-pack/file-selector.js.map +1 -1
- package/dist/src/browser/web-ai/context-pack/report.js +1 -1
- package/dist/src/browser/web-ai/context-pack/report.js.map +1 -1
- package/dist/src/browser/web-ai/copy-markdown.js +25 -5
- package/dist/src/browser/web-ai/copy-markdown.js.map +1 -1
- package/dist/src/browser/web-ai/diagnostics.js +17 -14
- package/dist/src/browser/web-ai/diagnostics.js.map +1 -1
- package/dist/src/browser/web-ai/doctor.js +10 -6
- package/dist/src/browser/web-ai/doctor.js.map +1 -1
- package/dist/src/browser/web-ai/dom-hash.js.map +1 -1
- package/dist/src/browser/web-ai/errors.js +5 -22
- package/dist/src/browser/web-ai/errors.js.map +1 -1
- package/dist/src/browser/web-ai/gemini-live.js +7 -6
- package/dist/src/browser/web-ai/gemini-live.js.map +1 -1
- package/dist/src/browser/web-ai/grok-live.js +9 -5
- package/dist/src/browser/web-ai/grok-live.js.map +1 -1
- package/dist/src/browser/web-ai/index.js +5 -0
- package/dist/src/browser/web-ai/index.js.map +1 -1
- package/dist/src/browser/web-ai/observation-bundle.js +90 -0
- package/dist/src/browser/web-ai/observation-bundle.js.map +1 -0
- package/dist/src/browser/web-ai/observe-actions.js +186 -0
- package/dist/src/browser/web-ai/observe-actions.js.map +1 -0
- package/dist/src/browser/web-ai/observe-targets.js +6 -1
- package/dist/src/browser/web-ai/observe-targets.js.map +1 -1
- package/dist/src/browser/web-ai/planner-contract.js +18 -0
- package/dist/src/browser/web-ai/planner-contract.js.map +1 -0
- package/dist/src/browser/web-ai/post-action-assert.js +8 -7
- package/dist/src/browser/web-ai/post-action-assert.js.map +1 -1
- package/dist/src/browser/web-ai/product-surfaces.js +2 -1
- package/dist/src/browser/web-ai/product-surfaces.js.map +1 -1
- package/dist/src/browser/web-ai/provider-adapter.js.map +1 -1
- package/dist/src/browser/web-ai/question.js +14 -7
- package/dist/src/browser/web-ai/question.js.map +1 -1
- package/dist/src/browser/web-ai/ref-registry.js.map +1 -1
- package/dist/src/browser/web-ai/self-heal.js +20 -14
- package/dist/src/browser/web-ai/self-heal.js.map +1 -1
- package/dist/src/browser/web-ai/session-store.js +61 -1
- package/dist/src/browser/web-ai/session-store.js.map +1 -1
- package/dist/src/browser/web-ai/session.js +43 -2
- package/dist/src/browser/web-ai/session.js.map +1 -1
- package/dist/src/browser/web-ai/source-audit.js +116 -0
- package/dist/src/browser/web-ai/source-audit.js.map +1 -0
- package/dist/src/browser/web-ai/tab-finalizer.js +18 -0
- package/dist/src/browser/web-ai/tab-finalizer.js.map +1 -0
- package/dist/src/browser/web-ai/tab-lease-store.js +390 -0
- package/dist/src/browser/web-ai/tab-lease-store.js.map +1 -0
- package/dist/src/browser/web-ai/tab-pool.js +44 -0
- package/dist/src/browser/web-ai/tab-pool.js.map +1 -0
- package/dist/src/browser/web-ai/target-resolver.js +31 -0
- package/dist/src/browser/web-ai/target-resolver.js.map +1 -0
- package/dist/src/browser/web-ai/trace-persistence.js +4 -2
- package/dist/src/browser/web-ai/trace-persistence.js.map +1 -1
- package/dist/src/browser/web-ai/vendor-editor-contract.js.map +1 -1
- package/dist/src/browser/web-ai/watcher.js +8 -7
- package/dist/src/browser/web-ai/watcher.js.map +1 -1
- package/dist/src/cli/acp-client.js +40 -26
- package/dist/src/cli/acp-client.js.map +1 -1
- package/dist/src/cli/command-context.js +3 -3
- package/dist/src/cli/command-context.js.map +1 -1
- package/dist/src/cli/commands.js +25 -16
- package/dist/src/cli/commands.js.map +1 -1
- package/dist/src/cli/compact.js.map +1 -1
- package/dist/src/cli/handlers-completions.js +6 -4
- package/dist/src/cli/handlers-completions.js.map +1 -1
- package/dist/src/cli/handlers-runtime.js +45 -38
- package/dist/src/cli/handlers-runtime.js.map +1 -1
- package/dist/src/cli/handlers.js +44 -36
- package/dist/src/cli/handlers.js.map +1 -1
- package/dist/src/cli/readiness.js +3 -1
- package/dist/src/cli/readiness.js.map +1 -1
- package/dist/src/cli/registry.js +1 -1
- package/dist/src/cli/registry.js.map +1 -1
- package/dist/src/cli/tui/overlay.js +4 -1
- package/dist/src/cli/tui/overlay.js.map +1 -1
- package/dist/src/cli/types.js +4 -0
- package/dist/src/cli/types.js.map +1 -0
- package/dist/src/command-contract/catalog.js +1 -1
- package/dist/src/command-contract/catalog.js.map +1 -1
- package/dist/src/command-contract/help-renderer.js +1 -1
- package/dist/src/command-contract/help-renderer.js.map +1 -1
- package/dist/src/core/browser-open-default.js +13 -0
- package/dist/src/core/browser-open-default.js.map +1 -0
- package/dist/src/core/browser-open.js +41 -0
- package/dist/src/core/browser-open.js.map +1 -0
- package/dist/src/core/bus.js +13 -2
- package/dist/src/core/bus.js.map +1 -1
- package/dist/src/core/compact.js +5 -4
- package/dist/src/core/compact.js.map +1 -1
- package/dist/src/core/config.js +51 -52
- package/dist/src/core/config.js.map +1 -1
- package/dist/src/core/db.js +48 -6
- package/dist/src/core/db.js.map +1 -1
- package/dist/src/core/employees.js +9 -8
- package/dist/src/core/employees.js.map +1 -1
- package/dist/src/core/instance.js +7 -6
- package/dist/src/core/instance.js.map +1 -1
- package/dist/src/core/logger.js +1 -1
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/main-session.js +7 -7
- package/dist/src/core/main-session.js.map +1 -1
- package/dist/src/core/path-expand.js +10 -0
- package/dist/src/core/path-expand.js.map +1 -0
- package/dist/src/core/runtime-path.js +1 -1
- package/dist/src/core/runtime-path.js.map +1 -1
- package/dist/src/core/runtime-settings.js +13 -13
- package/dist/src/core/runtime-settings.js.map +1 -1
- package/dist/src/core/settings-merge.js +14 -14
- package/dist/src/core/settings-merge.js.map +1 -1
- package/dist/src/core/strip-undefined.js +13 -0
- package/dist/src/core/strip-undefined.js.map +1 -0
- package/dist/src/core/tcc.js +1 -1
- package/dist/src/core/tcc.js.map +1 -1
- package/dist/src/discord/bot.js +19 -18
- package/dist/src/discord/bot.js.map +1 -1
- package/dist/src/discord/channel-types.js +14 -0
- package/dist/src/discord/channel-types.js.map +1 -0
- package/dist/src/discord/commands.js +7 -6
- package/dist/src/discord/commands.js.map +1 -1
- package/dist/src/discord/discord-file.js.map +1 -1
- package/dist/src/discord/forwarder.js +3 -3
- package/dist/src/discord/forwarder.js.map +1 -1
- package/dist/src/http/error-middleware.js +3 -3
- package/dist/src/http/error-middleware.js.map +1 -1
- package/dist/src/http/response.js +2 -2
- package/dist/src/http/response.js.map +1 -1
- package/dist/src/ide/diff.js +7 -7
- package/dist/src/ide/diff.js.map +1 -1
- package/dist/src/manager/board/routes.js +28 -27
- package/dist/src/manager/board/routes.js.map +1 -1
- package/dist/src/manager/dashboard-home.js +3 -5
- package/dist/src/manager/dashboard-home.js.map +1 -1
- package/dist/src/manager/dashboard-service.js +2 -2
- package/dist/src/manager/dashboard-service.js.map +1 -1
- package/dist/src/manager/health-history.js +10 -9
- package/dist/src/manager/health-history.js.map +1 -1
- package/dist/src/manager/launchd-service.js +2 -2
- package/dist/src/manager/launchd-service.js.map +1 -1
- package/dist/src/manager/lifecycle-helpers.js +7 -6
- package/dist/src/manager/lifecycle-helpers.js.map +1 -1
- package/dist/src/manager/lifecycle.js +7 -6
- package/dist/src/manager/lifecycle.js.map +1 -1
- package/dist/src/manager/logs.js +18 -18
- package/dist/src/manager/logs.js.map +1 -1
- package/dist/src/manager/metadata.js +10 -2
- package/dist/src/manager/metadata.js.map +1 -1
- package/dist/src/manager/notes/assets.js +216 -0
- package/dist/src/manager/notes/assets.js.map +1 -0
- package/dist/src/manager/notes/capabilities.js +56 -0
- package/dist/src/manager/notes/capabilities.js.map +1 -0
- package/dist/src/manager/notes/constants.js +11 -0
- package/dist/src/manager/notes/constants.js.map +1 -0
- package/dist/src/manager/notes/frontmatter.js +120 -0
- package/dist/src/manager/notes/frontmatter.js.map +1 -0
- package/dist/src/manager/notes/link-resolver.js +96 -0
- package/dist/src/manager/notes/link-resolver.js.map +1 -0
- package/dist/src/manager/notes/path-guards.js +4 -0
- package/dist/src/manager/notes/path-guards.js.map +1 -1
- package/dist/src/manager/notes/remote-assets.js +128 -0
- package/dist/src/manager/notes/remote-assets.js.map +1 -0
- package/dist/src/manager/notes/routes.js +63 -13
- package/dist/src/manager/notes/routes.js.map +1 -1
- package/dist/src/manager/notes/store.js +3 -2
- package/dist/src/manager/notes/store.js.map +1 -1
- package/dist/src/manager/notes/system-trash.js +3 -3
- package/dist/src/manager/notes/system-trash.js.map +1 -1
- package/dist/src/manager/notes/vault-index.js +220 -0
- package/dist/src/manager/notes/vault-index.js.map +1 -0
- package/dist/src/manager/notes/watcher.js +27 -0
- package/dist/src/manager/notes/watcher.js.map +1 -0
- package/dist/src/manager/notes/wiki-links.js +109 -0
- package/dist/src/manager/notes/wiki-links.js.map +1 -0
- package/dist/src/manager/process-verify.js +29 -0
- package/dist/src/manager/process-verify.js.map +1 -1
- package/dist/src/manager/profiles.js +3 -2
- package/dist/src/manager/profiles.js.map +1 -1
- package/dist/src/manager/registry.js +60 -58
- package/dist/src/manager/registry.js.map +1 -1
- package/dist/src/manager/routes/electron-metrics.js +22 -22
- package/dist/src/manager/routes/electron-metrics.js.map +1 -1
- package/dist/src/manager/scan.js +2 -2
- package/dist/src/manager/scan.js.map +1 -1
- package/dist/src/manager/schedule/routes.js +24 -23
- package/dist/src/manager/schedule/routes.js.map +1 -1
- package/dist/src/manager/server.js +28 -28
- package/dist/src/manager/server.js.map +1 -1
- package/dist/src/manager/systemd-service.js +1 -1
- package/dist/src/manager/systemd-service.js.map +1 -1
- package/dist/src/memory/bootstrap.js +5 -4
- package/dist/src/memory/bootstrap.js.map +1 -1
- package/dist/src/memory/heartbeat-schedule.js +10 -10
- package/dist/src/memory/heartbeat-schedule.js.map +1 -1
- package/dist/src/memory/heartbeat.js +23 -22
- package/dist/src/memory/heartbeat.js.map +1 -1
- package/dist/src/memory/indexing.js.map +1 -1
- package/dist/src/memory/keyword-expand.js +1 -1
- package/dist/src/memory/keyword-expand.js.map +1 -1
- package/dist/src/memory/memory.js +2 -2
- package/dist/src/memory/memory.js.map +1 -1
- package/dist/src/memory/runtime.js +6 -5
- package/dist/src/memory/runtime.js.map +1 -1
- package/dist/src/memory/shared.js +2 -1
- package/dist/src/memory/shared.js.map +1 -1
- package/dist/src/memory/worklog.js +1 -1
- package/dist/src/memory/worklog.js.map +1 -1
- package/dist/src/messaging/runtime.js +13 -10
- package/dist/src/messaging/runtime.js.map +1 -1
- package/dist/src/messaging/send.js +16 -15
- package/dist/src/messaging/send.js.map +1 -1
- package/dist/src/orchestrator/collect.js +6 -6
- package/dist/src/orchestrator/collect.js.map +1 -1
- package/dist/src/orchestrator/distribute.js +112 -77
- package/dist/src/orchestrator/distribute.js.map +1 -1
- package/dist/src/orchestrator/gateway.js +6 -5
- package/dist/src/orchestrator/gateway.js.map +1 -1
- package/dist/src/orchestrator/pipeline.js +42 -42
- package/dist/src/orchestrator/pipeline.js.map +1 -1
- package/dist/src/orchestrator/state-machine.js +3 -3
- package/dist/src/orchestrator/state-machine.js.map +1 -1
- package/dist/src/orchestrator/worker-registry.js +4 -3
- package/dist/src/orchestrator/worker-registry.js.map +1 -1
- package/dist/src/prompt/builder.js +24 -19
- package/dist/src/prompt/builder.js.map +1 -1
- package/dist/src/prompt/templates/a1-system.md +15 -10
- package/dist/src/prompt/templates/control-system.md +9 -7
- package/dist/src/prompt/templates/employee.md +5 -4
- package/dist/src/prompt/templates/vision-click.md +1 -1
- package/dist/src/routes/_http-error.js +15 -0
- package/dist/src/routes/_http-error.js.map +1 -0
- package/dist/src/routes/avatar.js +6 -5
- package/dist/src/routes/avatar.js.map +1 -1
- package/dist/src/routes/browser.js +132 -45
- package/dist/src/routes/browser.js.map +1 -1
- package/dist/src/routes/employees.js +28 -21
- package/dist/src/routes/employees.js.map +1 -1
- package/dist/src/routes/heartbeat.js +12 -9
- package/dist/src/routes/heartbeat.js.map +1 -1
- package/dist/src/routes/i18n.js +13 -7
- package/dist/src/routes/i18n.js.map +1 -1
- package/dist/src/routes/jaw-memory.js +15 -11
- package/dist/src/routes/jaw-memory.js.map +1 -1
- package/dist/src/routes/memory.js +25 -20
- package/dist/src/routes/memory.js.map +1 -1
- package/dist/src/routes/messaging.js +50 -29
- package/dist/src/routes/messaging.js.map +1 -1
- package/dist/src/routes/orchestrate.js +38 -24
- package/dist/src/routes/orchestrate.js.map +1 -1
- package/dist/src/routes/quota.js +81 -17
- package/dist/src/routes/quota.js.map +1 -1
- package/dist/src/routes/settings.js +28 -18
- package/dist/src/routes/settings.js.map +1 -1
- package/dist/src/routes/skills.js +22 -13
- package/dist/src/routes/skills.js.map +1 -1
- package/dist/src/routes/traces.js +77 -0
- package/dist/src/routes/traces.js.map +1 -0
- package/dist/src/security/path-guards.js +2 -1
- package/dist/src/security/path-guards.js.map +1 -1
- package/dist/src/shared/tool-log-sanitize.js +191 -0
- package/dist/src/shared/tool-log-sanitize.js.map +1 -0
- package/dist/src/telegram/bot.js +65 -55
- package/dist/src/telegram/bot.js.map +1 -1
- package/dist/src/telegram/forwarder.js +5 -9
- package/dist/src/telegram/forwarder.js.map +1 -1
- package/dist/src/telegram/telegram-file.js +28 -24
- package/dist/src/telegram/telegram-file.js.map +1 -1
- package/dist/src/telegram/voice.js +4 -3
- package/dist/src/telegram/voice.js.map +1 -1
- package/dist/src/trace/redact.js +50 -0
- package/dist/src/trace/redact.js.map +1 -0
- package/dist/src/trace/store.js +162 -0
- package/dist/src/trace/store.js.map +1 -0
- package/dist/src/trace/types.js +2 -0
- package/dist/src/trace/types.js.map +1 -0
- package/dist/src/types/cli-engine.js +34 -0
- package/dist/src/types/cli-engine.js.map +1 -0
- package/dist/src/types/cli-events.js +31 -0
- package/dist/src/types/cli-events.js.map +1 -0
- package/package.json +22 -2
- package/public/css/tool-ui.css +3 -1
- package/public/css/trace-drawer.css +48 -0
- package/public/dist/assets/{AdvancedExport-3WAYIabE.js → AdvancedExport-DJZ2VmBR.js} +1 -1
- package/public/dist/assets/Agent-CgpLT8IY.js +1 -0
- package/public/dist/assets/Browser-CrkiQoB8.js +1 -0
- package/public/dist/assets/{ChannelsDiscord-UzFPlWT4.js → ChannelsDiscord-CVUC22D4.js} +1 -1
- package/public/dist/assets/{ChannelsTelegram-DNWtPX0w.js → ChannelsTelegram-DEatIQNM.js} +1 -1
- package/public/dist/assets/{DashboardMeta-Y_6nVeJO.js → DashboardMeta-BKoxRc7i.js} +1 -1
- package/public/dist/assets/{Display-D8vGOl4s.js → Display-DnNGV9Km.js} +1 -1
- package/public/dist/assets/{Employees-YR_sIRK4.js → Employees-DZ2iJYKy.js} +1 -1
- package/public/dist/assets/{HealthBadge-CPePajyU.js → HealthBadge-Cq2c7G9s.js} +1 -1
- package/public/dist/assets/{Heartbeat-DTpAULQR.js → Heartbeat-BML6eTXZ.js} +1 -1
- package/public/dist/assets/{Mcp-DM-PgG6z.js → Mcp-BlEviQ3h.js} +1 -1
- package/public/dist/assets/{Memory-C_LvJnkn.js → Memory-BRyH80He.js} +1 -1
- package/public/dist/assets/MilkdownWysiwygEditor-Cm3uXfWf.js +52 -0
- package/public/dist/assets/ModelProvider-DxyR7EL9.js +1 -0
- package/public/dist/assets/Network-DDOOESh1.js +1 -0
- package/public/dist/assets/{Permissions-B1naJjjw.js → Permissions-Br0eSbKb.js} +1 -1
- package/public/dist/assets/{Permissions-BKffrMJD.js → Permissions-QHkzStqQ.js} +1 -1
- package/public/dist/assets/{Profile-DIqjSe2C.js → Profile-C79NKumk.js} +1 -1
- package/public/dist/assets/{Prompts-BMfbV6Y4.js → Prompts-BmiIDiXW.js} +1 -1
- package/public/dist/assets/{SpeechKeys-DjiQTzSL.js → SpeechKeys-B8304XJK.js} +1 -1
- package/public/dist/assets/app-Be58Cs3Y.js +32 -0
- package/public/dist/assets/{app-BzvwJJiv.css → app-CphocJzo.css} +1 -1
- package/public/dist/assets/{dist-DTvxN3ux.js → dist-BD0UXfgF2.js} +1 -1
- package/public/dist/assets/{dist-CASeq-Tl.js → dist-BNfXO3Yr.js} +1 -1
- package/public/dist/assets/{dist-BMPiaUzF.js → dist-BUnPYbK3.js} +1 -1
- package/public/dist/assets/{dist-CT_X3hVT.js → dist-BZosRD2u.js} +1 -1
- package/public/dist/assets/{dist-4J6YbNXv.js → dist-Bd9PlnQm.js} +1 -1
- package/public/dist/assets/{dist-BcZjyn5g.js → dist-BsT5UdNP.js} +1 -1
- package/public/dist/assets/{dist-BfBhOPR-.js → dist-CIuXW-sc.js} +1 -1
- package/public/dist/assets/{dist-BMiCig3A2.js → dist-CL4PTYWf.js} +1 -1
- package/public/dist/assets/{dist-VyP6-HLb.js → dist-Ch5VAlV9.js} +1 -1
- package/public/dist/assets/dist-ClqO40BE.js +1 -0
- package/public/dist/assets/{dist-c98Tp7bP.js → dist-Cp42cMcI.js} +1 -1
- package/public/dist/assets/{dist-CIlYL1qe.js → dist-CpUK8ypo.js} +1 -1
- package/public/dist/assets/dist-CxeLAw2Y.js +1 -0
- package/public/dist/assets/dist-D2SH8nxa.js +1 -0
- package/public/dist/assets/{dist-84fwQ7bO.js → dist-D6cUXP7K.js} +1 -1
- package/public/dist/assets/{dist-BOCcQAyF.js → dist-D7bCuS3f.js} +1 -1
- package/public/dist/assets/{dist-DMmpfLVP.js → dist-DFYRUAjN.js} +1 -1
- package/public/dist/assets/{dist-DdY6pTJr.js → dist-DZsFVYF4.js} +1 -1
- package/public/dist/assets/{dist-B0p3Eyme.js → dist-Db16ogVk.js} +1 -1
- package/public/dist/assets/{dist-DlnNtr6L.js → dist-DfodGES_.js} +1 -1
- package/public/dist/assets/{dist-DO9so2a2.js → dist-SU-YTAIg.js} +1 -1
- package/public/dist/assets/{dist-DUjXiMLP.js → dist-UYn7T-GH.js} +1 -1
- package/public/dist/assets/{dist-BW1409rz.js → dist-W51oDoeA.js} +1 -1
- package/public/dist/assets/{dist-BimBQZx1.js → dist-eU7TyC86.js} +1 -1
- package/public/dist/assets/dist-l9HH00ip.js +1 -0
- package/public/dist/assets/{dist-BrOPNxdH.js → dist-urPTQzXL.js} +1 -1
- package/public/dist/assets/{dist-AloEV3J52.js → dist-yHP6L0Ty.js} +1 -1
- package/public/dist/assets/{employees-Bbabvbyx.js → employees-CxdghzoD.js} +7 -7
- package/public/dist/assets/{error-normalize-DdvKGLt_.js → error-normalize-5n-zlEQ3.js} +1 -1
- package/public/dist/assets/insert-image-markdown-DIEa-zjk.js +22 -0
- package/public/dist/assets/{manager-DyB2ZUr9.css → manager-DEiyrWDP.css} +1 -1
- package/public/dist/assets/manager-UEXd1_9T.js +25 -0
- package/public/dist/assets/{memory-B_plvcuQ.js → memory-CsMNkYtv.js} +9 -9
- package/public/dist/assets/memory-DXad_DPO.js +1 -0
- package/public/dist/assets/{page-shell-DML_HneX.js → page-shell-D5tbivHH.js} +1 -1
- package/public/dist/assets/{render-DEhbfUAW.js → render-DGQX46ei.js} +2 -2
- package/public/dist/assets/{settings-D7F-_kYG.js → settings-BH213Yv3.js} +14 -14
- package/public/dist/assets/settings-DXT87G2U.js +1 -0
- package/public/dist/assets/settings-client-ajlwI-oK.js +1 -0
- package/public/dist/assets/skills-5o_1v0nz.js +1 -0
- package/public/dist/assets/{skills-DoGJOc0D.js → skills-CQtCtHPA.js} +6 -6
- package/public/dist/assets/slash-commands-D4-hrrmh.js +1 -0
- package/public/dist/assets/{slash-commands-khNFPOyF.js → slash-commands-Dzk1xHWS.js} +1 -1
- package/public/dist/assets/trace-drawer-SRKcfm2S.js +15 -0
- package/public/dist/assets/ui-CdRKN2S6.js +141 -0
- package/public/dist/assets/ui-n43jmg_f.js +1 -0
- package/public/dist/assets/{ws-B2aJ-nD2.js → ws-CTHQFzM1.js} +8 -8
- package/public/dist/index.html +2 -2
- package/public/dist/manager/index.html +2 -2
- package/public/index.html +1 -0
- package/public/js/constants.ts +5 -5
- package/public/js/diagram/iframe-renderer.ts +11 -11
- package/public/js/features/chat.ts +1 -1
- package/public/js/features/memory.ts +10 -10
- package/public/js/features/pending-queue.ts +2 -2
- package/public/js/features/process-block.ts +257 -29
- package/public/js/features/process-step-match.ts +18 -0
- package/public/js/features/settings-cli-status.ts +1 -1
- package/public/js/features/settings-stt.ts +37 -11
- package/public/js/features/settings-templates.ts +2 -2
- package/public/js/features/slash-commands.ts +1 -1
- package/public/js/features/tool-ui.ts +13 -7
- package/public/js/features/trace-drawer.ts +122 -0
- package/public/js/icons.ts +1 -1
- package/public/js/main.ts +28 -28
- package/public/js/provider-icons.ts +1 -1
- package/public/js/render.ts +29 -27
- package/public/js/sanitizer.ts +4 -0
- package/public/js/ui.ts +234 -68
- package/public/js/virtual-scroll.ts +19 -33
- package/public/js/ws.ts +22 -10
- package/public/manager/src/App.tsx +34 -6
- package/public/manager/src/api.ts +55 -1
- package/public/manager/src/components/ActivityTimeline.tsx +1 -1
- package/public/manager/src/components/InstanceDetailPanel.tsx +2 -2
- package/public/manager/src/components/InstanceGroups.tsx +5 -5
- package/public/manager/src/components/InstanceListContent.tsx +1 -1
- package/public/manager/src/dashboard-features.ts +1 -1
- package/public/manager/src/manager-notes.css +49 -2
- package/public/manager/src/notes/MarkdownEditor.tsx +7 -3
- package/public/manager/src/notes/NotesFileTree.tsx +45 -6
- package/public/manager/src/notes/NotesSidebar.tsx +24 -55
- package/public/manager/src/notes/NotesWorkspace.tsx +50 -3
- package/public/manager/src/notes/image-assets/clipboard-images.ts +100 -0
- package/public/manager/src/notes/image-assets/insert-image-markdown.ts +85 -0
- package/public/manager/src/notes/notes-api.ts +2 -0
- package/public/manager/src/notes/notes-types.ts +8 -1
- package/public/manager/src/notes/rendering/MarkdownRenderer.tsx +6 -0
- package/public/manager/src/notes/rendering/markdown-render-security.ts +19 -1
- package/public/manager/src/notes/rich-markdown/paste-policy.ts +6 -2
- package/public/manager/src/notes/rich-markdown/rich-markdown-extension.ts +5 -5
- package/public/manager/src/notes/rich-markdown/rich-widget.ts +8 -8
- package/public/manager/src/notes/useNotesExternalSync.ts +37 -0
- package/public/manager/src/notes/useNotesModel.ts +91 -0
- package/public/manager/src/notes/wysiwyg/MilkdownWysiwygEditor.tsx +157 -17
- package/public/manager/src/notes/wysiwyg/milkdown-block-keymap.ts +14 -2
- package/public/manager/src/notes/wysiwyg/milkdown-code-block-view.ts +20 -20
- package/public/manager/src/notes/wysiwyg/milkdown-heading-source-view.ts +8 -8
- package/public/manager/src/notes/wysiwyg/milkdown-math.ts +25 -25
- package/public/manager/src/settings/pages/Browser.tsx +38 -20
- package/public/manager/src/settings/pages/ModelProvider.tsx +11 -9
- package/public/manager/src/settings/pages/Network.tsx +10 -10
- package/public/manager/src/settings/pages/components/HealthBadge.tsx +12 -12
- package/public/manager/src/settings/pages/components/agent/runtime-employees-helpers.ts +12 -10
- package/public/manager/src/settings/pages/components/employees-helpers.ts +9 -9
- package/public/manager/src/settings/pages/components/heartbeat-helpers.ts +13 -13
- package/public/manager/src/settings/pages/components/memory-helpers.ts +4 -4
- package/public/manager/src/settings/pages/mcp-helpers.ts +7 -7
- package/public/manager/src/settings/settings-client.ts +4 -3
- package/public/manager/src/sync/IframeBridge.tsx +29 -0
- package/public/manager/src/sync/VisibilityBridge.tsx +24 -0
- package/public/manager/src/sync/invalidation-bus.ts +30 -0
- package/public/manager/src/sync/useInvalidationSubscription.ts +19 -0
- package/public/manager/src/types.ts +101 -0
- package/scripts/check-strict-baseline.mjs +255 -0
- package/scripts/claim-audit.mjs +159 -0
- package/scripts/i18n-registry.ts +4 -4
- package/scripts/install-officecli.sh +2 -2
- package/scripts/install-wsl.sh +2 -1
- package/scripts/release-gates.mjs +347 -0
- package/scripts/release-preview.sh +3 -0
- package/scripts/release.sh +4 -0
- package/scripts/smoke/opencode-external-dir-smoke.ts +14 -5
- package/public/dist/assets/Agent-BYdzZwD0.js +0 -1
- package/public/dist/assets/Browser-CkGeczuN.js +0 -1
- package/public/dist/assets/MilkdownWysiwygEditor-B7k9bAey.js +0 -52
- package/public/dist/assets/ModelProvider-CX3Qhowu.js +0 -1
- package/public/dist/assets/Network-DfPLFAvw.js +0 -1
- package/public/dist/assets/app-DLYoRkU9.js +0 -32
- package/public/dist/assets/dist-8zNAQAIa.js +0 -1
- package/public/dist/assets/dist-BgeY6nvK.js +0 -1
- package/public/dist/assets/dist-BzDGGxHQ.js +0 -1
- package/public/dist/assets/dist-D3YKbVi-.js +0 -1
- package/public/dist/assets/manager-CUSgFbMO.js +0 -25
- package/public/dist/assets/markdown-render-security-DJfJPWO-.js +0 -22
- package/public/dist/assets/memory-DQ6dU0qs.js +0 -1
- package/public/dist/assets/settings-DxLPUbpj.js +0 -1
- package/public/dist/assets/settings-client-CGf3uPPf.js +0 -1
- package/public/dist/assets/skills-yMfNYJ8m.js +0 -1
- package/public/dist/assets/slash-commands-CZcwr1W6.js +0 -1
- package/public/dist/assets/ui-04YlOMgn.js +0 -136
- package/public/dist/assets/ui-D6hlMjRq.js +0 -1
- /package/public/dist/assets/{InlineWarn-CqgWEC41.js → InlineWarn-BooBRm7o.js} +0 -0
- /package/public/dist/assets/{agent-meta-puNn13DV.js → agent-meta-DHddpWHQ.js} +0 -0
- /package/public/dist/assets/{fields-DH9JS3mb.js → fields-BtncIZYA.js} +0 -0
- /package/public/dist/assets/{mermaid-loader-6XC0y10y.js → mermaid-loader-BEFIOoJn.js} +0 -0
- /package/public/dist/assets/{path-utils-CtsDDGZg.js → path-utils-BuEEtj9w.js} +0 -0
- /package/public/dist/assets/{w3c-keyname-VSld09PZ.js → w3c-keyname-IiiZScED.js} +0 -0
package/dist/src/agent/spawn.js
CHANGED
|
@@ -6,6 +6,7 @@ import { join } from 'path';
|
|
|
6
6
|
import { spawn, execFileSync } from 'child_process';
|
|
7
7
|
import { broadcast } from '../core/bus.js';
|
|
8
8
|
import { settings, UPLOADS_DIR, detectCli, normalizeModelForCli } from '../core/config.js';
|
|
9
|
+
import { stripUndefined } from '../core/strip-undefined.js';
|
|
9
10
|
import { clearEmployeeSession, getSession, insertMessage, getRecentMessages, listQueuedMessages, insertQueuedMessage, deleteQueuedMessage, getSessionBucket, } from '../core/db.js';
|
|
10
11
|
import { getSystemPrompt, regenerateB } from '../prompt/builder.js';
|
|
11
12
|
import { extractSessionId, extractFromEvent, extractFromAcpUpdate, extractOutputChunk, logEventSummary, flushClaudeBuffers } from './events.js';
|
|
@@ -23,7 +24,10 @@ import { resolveOrcScope } from '../orchestrator/scope.js';
|
|
|
23
24
|
import { beginLiveRun, appendLiveRunText, clearLiveRun, replaceLiveRunTools, appendLiveRunTool } from './live-run-state.js';
|
|
24
25
|
import { setSpawnRef as setMemorySpawnRef, } from './memory-flush-controller.js';
|
|
25
26
|
import { applyCliEnvDefaults, buildSessionResumeKey, ensureOpencodeAlwaysAllowPermissions } from './spawn-env.js';
|
|
27
|
+
import { attachWatchdog } from './watchdog.js';
|
|
26
28
|
import { buildOpencodeRuntimeSnapshot, buildOpencodeSpawnAudit, pushOpencodeRawEvent, resolveOpencodeBinary, } from './opencode-diagnostics.js';
|
|
29
|
+
import { asCliEventRecord, discriminate, fieldString } from '../types/cli-events.js';
|
|
30
|
+
import { appendTraceEvent, stampTraceTool, startTraceRun } from '../trace/store.js';
|
|
27
31
|
// ─── State ───────────────────────────────────────────
|
|
28
32
|
export let activeProcess = null;
|
|
29
33
|
export const activeProcesses = new Map(); // agentId → child process
|
|
@@ -99,7 +103,7 @@ function normalizeQueueItem(row) {
|
|
|
99
103
|
if (typeof parsed?.id !== 'string' || typeof parsed?.prompt !== 'string' || typeof parsed?.source !== 'string') {
|
|
100
104
|
return [];
|
|
101
105
|
}
|
|
102
|
-
return [{
|
|
106
|
+
return [stripUndefined({
|
|
103
107
|
id: parsed.id,
|
|
104
108
|
prompt: parsed.prompt,
|
|
105
109
|
source: parsed.source,
|
|
@@ -108,7 +112,7 @@ function normalizeQueueItem(row) {
|
|
|
108
112
|
chatId: parsed.chatId,
|
|
109
113
|
requestId: parsed.requestId,
|
|
110
114
|
ts: typeof parsed.ts === 'number' ? parsed.ts : Date.now(),
|
|
111
|
-
}];
|
|
115
|
+
})];
|
|
112
116
|
}
|
|
113
117
|
catch {
|
|
114
118
|
return [];
|
|
@@ -330,7 +334,7 @@ export async function steerAgent(newPrompt, source) {
|
|
|
330
334
|
const wasRunning = killActiveAgent('steer');
|
|
331
335
|
if (wasRunning)
|
|
332
336
|
await waitForProcessEnd(3000);
|
|
333
|
-
insertMessage.run('user', newPrompt, source, '', settings
|
|
337
|
+
insertMessage.run('user', newPrompt, source, '', settings["workingDir"] || null);
|
|
334
338
|
broadcast('new_message', { role: 'user', content: newPrompt, source });
|
|
335
339
|
const { orchestrate, orchestrateContinue, orchestrateReset, isContinueIntent, isResetIntent } = await import('../orchestrator/pipeline.js');
|
|
336
340
|
const origin = source || 'web';
|
|
@@ -371,7 +375,7 @@ export function removeQueuedMessage(id) {
|
|
|
371
375
|
return { removed: removed, pending: messageQueue.length };
|
|
372
376
|
}
|
|
373
377
|
export function enqueueMessage(prompt, source, meta) {
|
|
374
|
-
const item = {
|
|
378
|
+
const item = stripUndefined({
|
|
375
379
|
id: crypto.randomUUID(),
|
|
376
380
|
prompt,
|
|
377
381
|
source,
|
|
@@ -380,7 +384,7 @@ export function enqueueMessage(prompt, source, meta) {
|
|
|
380
384
|
chatId: meta?.chatId,
|
|
381
385
|
requestId: meta?.requestId,
|
|
382
386
|
ts: Date.now(),
|
|
383
|
-
};
|
|
387
|
+
});
|
|
384
388
|
insertQueuedMessage.run(item.id, JSON.stringify(item));
|
|
385
389
|
messageQueue.push(item);
|
|
386
390
|
console.log(`[queue] +1 (${messageQueue.length} pending)`);
|
|
@@ -449,7 +453,7 @@ export async function processQueue() {
|
|
|
449
453
|
console.log(`[queue] processing 1/${batch.length} message(s) for ${groupKey}, ${messageQueue.length} remaining`);
|
|
450
454
|
let inserted = false;
|
|
451
455
|
try {
|
|
452
|
-
insertMessage.run('user', combined, source, '', settings
|
|
456
|
+
insertMessage.run('user', combined, source, '', settings["workingDir"] || null);
|
|
453
457
|
deleteQueuedMessage.run(item.id);
|
|
454
458
|
inserted = true;
|
|
455
459
|
// Broadcast WITH fromQueue=true so the web client renders the user bubble
|
|
@@ -491,20 +495,20 @@ export async function processQueue() {
|
|
|
491
495
|
// ─── Helpers ─────────────────────────────────────────
|
|
492
496
|
function makeCleanEnv(extraEnv = {}) {
|
|
493
497
|
const env = { ...process.env };
|
|
494
|
-
delete env
|
|
495
|
-
delete env
|
|
498
|
+
delete env["CLAUDE_CODE_SSE_PORT"];
|
|
499
|
+
delete env["GEMINI_SYSTEM_MD"];
|
|
496
500
|
// Phase 8: strip boss-only dispatch token from employee spawns so employees
|
|
497
501
|
// cannot authenticate against /api/orchestrate/dispatch even via localhost.
|
|
498
502
|
// Detect employee spawn by the explicit JAW_EMPLOYEE_MODE flag; main spawns
|
|
499
503
|
// pass an empty extraEnv and keep the token inherited from process.env.
|
|
500
|
-
if (extraEnv
|
|
501
|
-
delete env
|
|
504
|
+
if (extraEnv["JAW_EMPLOYEE_MODE"] === '1') {
|
|
505
|
+
delete env["JAW_BOSS_TOKEN"];
|
|
502
506
|
}
|
|
503
|
-
env
|
|
507
|
+
env["PATH"] = buildServicePath(env["PATH"] || '');
|
|
504
508
|
return {
|
|
505
509
|
...env,
|
|
506
510
|
...extraEnv,
|
|
507
|
-
PATH: buildServicePath(extraEnv
|
|
511
|
+
PATH: buildServicePath(extraEnv["PATH"] || env["PATH"] || ''),
|
|
508
512
|
};
|
|
509
513
|
}
|
|
510
514
|
function buildHistoryBlock(currentPrompt, workingDir, maxSessions = 10, maxTotalChars = 8000) {
|
|
@@ -517,6 +521,8 @@ function buildHistoryBlock(currentPrompt, workingDir, maxSessions = 10, maxTotal
|
|
|
517
521
|
let charCount = 0;
|
|
518
522
|
for (let i = 0; i < recent.length; i++) {
|
|
519
523
|
const row = recent[i];
|
|
524
|
+
if (!row)
|
|
525
|
+
continue;
|
|
520
526
|
const role = String(row.role || '');
|
|
521
527
|
const content = String(row.content || '').trim();
|
|
522
528
|
// Exclude the just-inserted current prompt when caller path stores user text
|
|
@@ -562,7 +568,7 @@ function withHistoryPrompt(prompt, historyBlock) {
|
|
|
562
568
|
import { buildArgs, buildResumeArgs, resolveSessionBucket } from './args.js';
|
|
563
569
|
export { buildArgs, buildResumeArgs, resolveSessionBucket };
|
|
564
570
|
// ─── Upload wrapper ──────────────────────────────────
|
|
565
|
-
export const saveUpload = (buffer, originalName) => _saveUpload(UPLOADS_DIR, buffer, originalName);
|
|
571
|
+
export const saveUpload = (buffer, originalName, options) => _saveUpload(UPLOADS_DIR, Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer), originalName, options);
|
|
566
572
|
export { buildMediaPrompt, buildMediaPromptMany };
|
|
567
573
|
// ─── Spawn Agent ─────────────────────────────────────
|
|
568
574
|
import { AcpClient } from '../cli/acp-client.js';
|
|
@@ -599,7 +605,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
599
605
|
const { forceNew = false, agentId, sysPrompt: customSysPrompt, memorySnapshot } = opts;
|
|
600
606
|
const origin = opts.origin || 'web';
|
|
601
607
|
const empSid = opts.employeeSessionId || null;
|
|
602
|
-
const mainManaged = !forceNew && !empSid;
|
|
608
|
+
const mainManaged = !forceNew && !empSid && !opts.internal;
|
|
603
609
|
const gateEligibleMain = mainManaged && !opts.agentId && !opts.internal && !opts._isFallback && !opts._isSmokeContinuation;
|
|
604
610
|
const isEmployee = !mainManaged;
|
|
605
611
|
const empTag = isEmployee ? { isEmployee: true } : {};
|
|
@@ -638,7 +644,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
638
644
|
// Skip for employee spawns — distribute.ts manages AGENTS.md isolation
|
|
639
645
|
if (!opts.internal && !opts._isFallback && !opts.agentId)
|
|
640
646
|
regenerateB();
|
|
641
|
-
const liveScope = resolveOrcScope({ origin, chatId: opts.chatId, workingDir: settings
|
|
647
|
+
const liveScope = resolveOrcScope(stripUndefined({ origin, chatId: opts.chatId, workingDir: settings["workingDir"] || null }));
|
|
642
648
|
// Employee must not pollute boss's liveRun (see devlog 260423_employee_liverun_contamination)
|
|
643
649
|
const effectiveLiveScope = mainManaged ? liveScope : null;
|
|
644
650
|
// INVARIANT: 모든 외부 호출은 gateway.ts isAgentBusy()를 거침.
|
|
@@ -650,17 +656,17 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
650
656
|
// Capture Boss main session channel so disconnected worker results can be
|
|
651
657
|
// replayed to the correct origin/chatId later. Cleared in lifecycle-handler.
|
|
652
658
|
if (mainManaged) {
|
|
653
|
-
setCurrentMainMeta({
|
|
659
|
+
setCurrentMainMeta(stripUndefined({
|
|
654
660
|
origin,
|
|
655
661
|
target: opts.target,
|
|
656
662
|
chatId: opts.chatId,
|
|
657
663
|
requestId: opts.requestId,
|
|
658
664
|
scopeId: liveScope,
|
|
659
|
-
});
|
|
665
|
+
}));
|
|
660
666
|
}
|
|
661
667
|
let resolve;
|
|
662
668
|
const resultPromise = new Promise(r => { resolve = r; });
|
|
663
|
-
const session = getSession();
|
|
669
|
+
const session = getSession() ?? {};
|
|
664
670
|
const ownerGeneration = getSessionOwnershipGeneration();
|
|
665
671
|
let cli = resolveMainCli(opts.cli, settings, session);
|
|
666
672
|
// Phase 52: Bootstrap consumption is moved BELOW the bucket-aware `isResume`
|
|
@@ -680,17 +686,20 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
680
686
|
}
|
|
681
687
|
}
|
|
682
688
|
}
|
|
683
|
-
const permissions = opts.permissions || settings
|
|
689
|
+
const permissions = opts.permissions || settings["permissions"] || session.permissions || 'auto';
|
|
684
690
|
if (cli === 'opencode') {
|
|
685
691
|
ensureOpencodeAlwaysAllowPermissions();
|
|
686
692
|
}
|
|
687
|
-
const cfg = settings
|
|
688
|
-
const ao = settings
|
|
693
|
+
const cfg = settings["perCli"]?.[cli] || {};
|
|
694
|
+
const ao = settings["activeOverrides"]?.[cli] || {};
|
|
689
695
|
const model = opts.model || ao.model || cfg.model || 'default';
|
|
690
696
|
const effort = opts.effort || ao.effort || cfg.effort || '';
|
|
697
|
+
const includeDirectories = Array.isArray(cfg.includeDirectories)
|
|
698
|
+
? cfg.includeDirectories.filter((dir) => typeof dir === 'string' && dir.trim().length > 0)
|
|
699
|
+
: [];
|
|
691
700
|
const sysPrompt = customSysPrompt !== undefined
|
|
692
701
|
? customSysPrompt
|
|
693
|
-
: getSystemPrompt({ currentPrompt: prompt, forDisk: false, memorySnapshot, activeCli: cli });
|
|
702
|
+
: getSystemPrompt(stripUndefined({ currentPrompt: prompt, forDisk: false, memorySnapshot, activeCli: cli }));
|
|
694
703
|
// Bucket-aware resume: codex-spark is kept in its own session bucket so
|
|
695
704
|
// cross-model resume (gpt-5.4 ↔ gpt-5.3-codex-spark) doesn't send a
|
|
696
705
|
// mismatched session_id to the server.
|
|
@@ -738,23 +747,26 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
738
747
|
prompt = `${ts}\n${prompt}\n(need history? cli-jaw memory search "<keywords>" in "ENGLISH")`;
|
|
739
748
|
}
|
|
740
749
|
const resumeSessionId = empSid || (isResume ? bucketSessionId : null);
|
|
741
|
-
const historyBlock = !isResume ? buildHistoryBlock(prompt, settings
|
|
750
|
+
const historyBlock = !isResume && !opts._skipHistory ? buildHistoryBlock(prompt, settings["workingDir"]) : '';
|
|
742
751
|
const promptForArgs = (cli === 'gemini' || cli === 'opencode')
|
|
743
752
|
? withHistoryPrompt(prompt, historyBlock)
|
|
744
753
|
: prompt;
|
|
745
754
|
let args;
|
|
746
755
|
if (isResume) {
|
|
747
|
-
|
|
748
|
-
|
|
756
|
+
const sid = resumeSessionId || '';
|
|
757
|
+
console.log(`[jaw:resume] ${cli} session=${sid.slice(0, 12)}...`);
|
|
758
|
+
args = buildResumeArgs(cli, model, effort, sid, prompt, permissions, { fastMode: cfg.fastMode, sysPrompt, includeDirectories });
|
|
749
759
|
}
|
|
750
760
|
else {
|
|
751
|
-
args = buildArgs(cli, model, effort, promptForArgs, sysPrompt, permissions, { fastMode: cfg.fastMode });
|
|
761
|
+
args = buildArgs(cli, model, effort, promptForArgs, sysPrompt, permissions, { fastMode: cfg.fastMode, includeDirectories });
|
|
752
762
|
}
|
|
753
763
|
const agentLabel = agentId || 'main';
|
|
764
|
+
const traceAudience = (opts.internal || isEmployee) ? 'internal' : 'public';
|
|
765
|
+
const parentLiveScopeForChild = !opts.internal && isEmployee ? liveScope : null;
|
|
754
766
|
// ─── Universal employee isolation ────────────────────
|
|
755
767
|
// All CLIs auto-read AGENTS.md/CLAUDE.md/GEMINI.md from cwd.
|
|
756
768
|
// Employees must NOT see the Boss's instruction files.
|
|
757
|
-
let spawnCwd = settings
|
|
769
|
+
let spawnCwd = settings["workingDir"];
|
|
758
770
|
if (opts.agentId && (customSysPrompt || sysPrompt)) {
|
|
759
771
|
const empPrompt = customSysPrompt || sysPrompt;
|
|
760
772
|
const empPromptWithWorkspace = opts.workspaceContext
|
|
@@ -769,7 +781,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
769
781
|
fs.mkdirSync(dotClaudeDir, { recursive: true });
|
|
770
782
|
fs.writeFileSync(join(dotClaudeDir, 'CLAUDE.md'), empPromptWithWorkspace);
|
|
771
783
|
try {
|
|
772
|
-
fs.symlinkSync(settings
|
|
784
|
+
fs.symlinkSync(settings["workingDir"], join(tmpDir, 'workspace'), 'dir');
|
|
773
785
|
}
|
|
774
786
|
catch {
|
|
775
787
|
// Non-fatal: the absolute Project root in Workspace Context remains authoritative.
|
|
@@ -794,7 +806,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
794
806
|
resolve({ text: '', code: 127 });
|
|
795
807
|
if (mainManaged)
|
|
796
808
|
processQueue();
|
|
797
|
-
cleanupEmployeeTmpDir(spawnCwd, settings
|
|
809
|
+
cleanupEmployeeTmpDir(spawnCwd, settings["workingDir"], agentLabel);
|
|
798
810
|
return { child: null, promise: resultPromise };
|
|
799
811
|
}
|
|
800
812
|
if (cli === 'copilot') {
|
|
@@ -806,7 +818,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
806
818
|
if (cli === 'gemini' && sysPrompt) {
|
|
807
819
|
const tmpSysFile = join(os.tmpdir(), `jaw-gemini-sys-${agentLabel}.md`);
|
|
808
820
|
fs.writeFileSync(tmpSysFile, sysPrompt);
|
|
809
|
-
spawnEnv
|
|
821
|
+
spawnEnv["GEMINI_SYSTEM_MD"] = tmpSysFile;
|
|
810
822
|
}
|
|
811
823
|
// ─── Copilot ACP branch ──────────────────────
|
|
812
824
|
if (cli === 'copilot') {
|
|
@@ -842,6 +854,9 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
842
854
|
const acp = new AcpClient({ model, workDir: spawnCwd, permissions, env: spawnEnv });
|
|
843
855
|
acp.spawn();
|
|
844
856
|
const child = acp.proc;
|
|
857
|
+
if (!child) {
|
|
858
|
+
throw new Error('Copilot ACP process was not created');
|
|
859
|
+
}
|
|
845
860
|
if (mainManaged)
|
|
846
861
|
activeProcess = child;
|
|
847
862
|
// Phase 7-3: detect duplicate spawn for same agentLabel. claimWorker guards
|
|
@@ -850,8 +865,9 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
850
865
|
console.warn(`[spawn:dup] activeProcesses already has child for ${agentLabel} — orphaning previous reference`);
|
|
851
866
|
}
|
|
852
867
|
activeProcesses.set(agentLabel, child);
|
|
853
|
-
|
|
854
|
-
|
|
868
|
+
if (!opts.internal)
|
|
869
|
+
broadcast('agent_status', { running: true, agentId: agentLabel, cli, ...empTag });
|
|
870
|
+
if (mainManaged && !opts.internal)
|
|
855
871
|
beginLiveRun(liveScope, cli);
|
|
856
872
|
// ─── DIFF-C: ACP error guard — prevent uncaught EventEmitter crash ───
|
|
857
873
|
let acpSettled = false; // guard: error→exit can fire sequentially
|
|
@@ -859,7 +875,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
859
875
|
if (acpSettled)
|
|
860
876
|
return;
|
|
861
877
|
acpSettled = true;
|
|
862
|
-
cleanupEmployeeTmpDir(spawnCwd, settings
|
|
878
|
+
cleanupEmployeeTmpDir(spawnCwd, settings["workingDir"], agentLabel);
|
|
863
879
|
opts.lifecycle?.onExit?.(null);
|
|
864
880
|
const msg = `Copilot ACP spawn failed: ${err.message}`;
|
|
865
881
|
console.error(`[acp:error] ${msg}`);
|
|
@@ -875,16 +891,20 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
875
891
|
processQueue();
|
|
876
892
|
});
|
|
877
893
|
if (mainManaged && !opts.internal && !opts._skipInsert) {
|
|
878
|
-
insertMessage.run('user', prompt, cli, model, settings
|
|
894
|
+
insertMessage.run('user', prompt, cli, model, settings["workingDir"] || null);
|
|
879
895
|
}
|
|
880
|
-
|
|
896
|
+
if (!opts.internal)
|
|
897
|
+
broadcast('agent_status', { status: 'running', cli, agentId: agentLabel, ...empTag }, traceAudience);
|
|
898
|
+
const traceRunId = startTraceRun({ cli, model, workingDir: settings["workingDir"] || null, agentLabel, audience: traceAudience });
|
|
881
899
|
const ctx = {
|
|
882
900
|
fullText: '', traceLog: [], toolLog: [], seenToolKeys: new Set(),
|
|
883
901
|
hasClaudeStreamEvents: false, sessionId: null, cost: null,
|
|
884
902
|
turns: null, duration: null, tokens: null, stderrBuf: '',
|
|
885
903
|
thinkingBuf: '',
|
|
886
904
|
liveScope: effectiveLiveScope,
|
|
887
|
-
parentLiveScope:
|
|
905
|
+
parentLiveScope: parentLiveScopeForChild,
|
|
906
|
+
traceRunId,
|
|
907
|
+
traceAudience,
|
|
888
908
|
};
|
|
889
909
|
// Flush accumulated 💭 thinking buffer as a single merged event
|
|
890
910
|
function flushThinking() {
|
|
@@ -896,12 +916,13 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
896
916
|
const label = singleLine.length > 120 ? `${singleLine.slice(0, 119)}…` : singleLine;
|
|
897
917
|
console.log(` 💭 ${label}`);
|
|
898
918
|
const tool = { icon: '💭', label, toolType: 'thinking', detail: merged };
|
|
919
|
+
stampTraceTool(tool, ctx, 'thinking');
|
|
899
920
|
ctx.toolLog.push(tool);
|
|
900
921
|
if (ctx.liveScope)
|
|
901
922
|
replaceLiveRunTools(ctx.liveScope, ctx.toolLog);
|
|
902
923
|
if (ctx.parentLiveScope)
|
|
903
924
|
appendLiveRunTool(ctx.parentLiveScope, { ...tool, isEmployee: true });
|
|
904
|
-
broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag });
|
|
925
|
+
broadcast('agent_tool', { agentId: agentLabel, ...tool, ...empTag }, traceAudience);
|
|
905
926
|
}
|
|
906
927
|
ctx.thinkingBuf = '';
|
|
907
928
|
}
|
|
@@ -912,6 +933,8 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
912
933
|
acp.on('session/update', (params) => {
|
|
913
934
|
if (replayMode)
|
|
914
935
|
return; // 리플레이 중 모든 이벤트 무시
|
|
936
|
+
const update = asCliEventRecord(asCliEventRecord(params)["update"]);
|
|
937
|
+
appendTraceEvent({ runId: ctx.traceRunId, source: 'acp_raw', eventType: fieldString(update.sessionUpdate, 'session/update'), raw: params });
|
|
915
938
|
const parsed = extractFromAcpUpdate(params, ctx);
|
|
916
939
|
if (!parsed)
|
|
917
940
|
return;
|
|
@@ -928,12 +951,13 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
928
951
|
const key = `${parsedTool.icon}:${parsedTool.label}:${parsedTool.stepRef || ''}:${parsedTool.status || ''}`;
|
|
929
952
|
if (!ctx.seenToolKeys.has(key)) {
|
|
930
953
|
ctx.seenToolKeys.add(key);
|
|
954
|
+
stampTraceTool(parsedTool, ctx, parsedTool.toolType || 'tool');
|
|
931
955
|
ctx.toolLog.push(parsedTool);
|
|
932
956
|
if (ctx.liveScope)
|
|
933
957
|
replaceLiveRunTools(ctx.liveScope, ctx.toolLog);
|
|
934
958
|
if (ctx.parentLiveScope)
|
|
935
959
|
appendLiveRunTool(ctx.parentLiveScope, { ...parsedTool, isEmployee: true });
|
|
936
|
-
broadcast('agent_tool', { agentId: agentLabel, ...parsedTool, ...empTag });
|
|
960
|
+
broadcast('agent_tool', { agentId: agentLabel, ...parsedTool, ...empTag }, traceAudience);
|
|
937
961
|
// Reset heartbeat gate on actually visible broadcast (not 💭)
|
|
938
962
|
lastVisibleBroadcastTs = Date.now();
|
|
939
963
|
heartbeatSent = false;
|
|
@@ -950,34 +974,39 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
950
974
|
});
|
|
951
975
|
// [P2-3.14] session/cancelled → route through extractFromAcpUpdate for UI notification
|
|
952
976
|
acp.on('session/cancelled', (params) => {
|
|
977
|
+
appendTraceEvent({ runId: ctx.traceRunId, source: 'acp_raw', eventType: 'session/cancelled', raw: params });
|
|
953
978
|
const parsed = extractFromAcpUpdate({
|
|
954
979
|
update: { sessionUpdate: 'session_cancelled', ...(params || {}) },
|
|
955
980
|
});
|
|
956
981
|
if (parsed?.tool) {
|
|
982
|
+
stampTraceTool(parsed.tool, ctx, parsed.tool.toolType || 'tool');
|
|
957
983
|
ctx.toolLog.push(parsed.tool);
|
|
958
984
|
if (ctx.liveScope)
|
|
959
985
|
replaceLiveRunTools(ctx.liveScope, ctx.toolLog);
|
|
960
986
|
if (ctx.parentLiveScope)
|
|
961
987
|
appendLiveRunTool(ctx.parentLiveScope, { ...parsed.tool, isEmployee: true });
|
|
962
|
-
broadcast('agent_tool', { agentId: agentLabel, ...parsed.tool, ...empTag });
|
|
988
|
+
broadcast('agent_tool', { agentId: agentLabel, ...parsed.tool, ...empTag }, traceAudience);
|
|
963
989
|
}
|
|
964
990
|
});
|
|
965
991
|
// [P2-3.15] session/request_permission → audit record in toolLog
|
|
966
992
|
acp.on('session/request_permission', (params) => {
|
|
993
|
+
appendTraceEvent({ runId: ctx.traceRunId, source: 'acp_raw', eventType: 'session/request_permission', raw: params });
|
|
967
994
|
const parsed = extractFromAcpUpdate({
|
|
968
995
|
update: { sessionUpdate: 'request_permission', ...(params || {}) },
|
|
969
996
|
});
|
|
970
997
|
if (parsed?.tool) {
|
|
998
|
+
stampTraceTool(parsed.tool, ctx, parsed.tool.toolType || 'tool');
|
|
971
999
|
ctx.toolLog.push(parsed.tool);
|
|
972
1000
|
if (ctx.liveScope)
|
|
973
1001
|
replaceLiveRunTools(ctx.liveScope, ctx.toolLog);
|
|
974
1002
|
if (ctx.parentLiveScope)
|
|
975
1003
|
appendLiveRunTool(ctx.parentLiveScope, { ...parsed.tool, isEmployee: true });
|
|
976
|
-
broadcast('agent_tool', { agentId: agentLabel, ...parsed.tool, ...empTag });
|
|
1004
|
+
broadcast('agent_tool', { agentId: agentLabel, ...parsed.tool, ...empTag }, traceAudience);
|
|
977
1005
|
}
|
|
978
1006
|
});
|
|
979
1007
|
// stderr_activity → stderrBuf accumulation + conditional heartbeat
|
|
980
1008
|
acp.on('stderr_activity', (text) => {
|
|
1009
|
+
appendTraceEvent({ runId: ctx.traceRunId, source: 'stderr', eventType: 'stderr_activity', raw: text });
|
|
981
1010
|
// Accumulate stderr for diagnostics (capped)
|
|
982
1011
|
if (ctx.stderrBuf.length < 4000) {
|
|
983
1012
|
ctx.stderrBuf += text + '\n';
|
|
@@ -993,7 +1022,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
993
1022
|
icon: '⏳',
|
|
994
1023
|
label: 'working... (no visible progress)',
|
|
995
1024
|
...empTag,
|
|
996
|
-
});
|
|
1025
|
+
}, traceAudience);
|
|
997
1026
|
}
|
|
998
1027
|
});
|
|
999
1028
|
// Run ACP flow
|
|
@@ -1001,7 +1030,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1001
1030
|
(async () => {
|
|
1002
1031
|
try {
|
|
1003
1032
|
const initResult = await acp.initialize();
|
|
1004
|
-
if (process.env
|
|
1033
|
+
if (process.env["DEBUG"])
|
|
1005
1034
|
console.log('[acp:init]', JSON.stringify(initResult).slice(0, 200));
|
|
1006
1035
|
replayMode = true; // Phase 17.2: mute during session load
|
|
1007
1036
|
let loadSessionOk = false;
|
|
@@ -1030,23 +1059,23 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1030
1059
|
ctx.toolLog = [];
|
|
1031
1060
|
ctx.seenToolKeys.clear();
|
|
1032
1061
|
ctx.thinkingBuf = ''; // Phase 17.2: clear replay thinking too
|
|
1033
|
-
if (mainManaged)
|
|
1062
|
+
if (mainManaged && !opts.internal)
|
|
1034
1063
|
beginLiveRun(liveScope, cli);
|
|
1035
1064
|
// If loadSession failed (or not resuming), inject history into prompt
|
|
1036
1065
|
const needsHistoryFallback = isResume && !loadSessionOk;
|
|
1037
|
-
const fallbackHistory = needsHistoryFallback ? buildHistoryBlock(prompt, settings
|
|
1066
|
+
const fallbackHistory = needsHistoryFallback && !opts._skipHistory ? buildHistoryBlock(prompt, settings["workingDir"]) : '';
|
|
1038
1067
|
const acpPrompt = needsHistoryFallback
|
|
1039
1068
|
? withHistoryPrompt(prompt, fallbackHistory)
|
|
1040
1069
|
: (isResume ? prompt : withHistoryPrompt(prompt, historyBlock));
|
|
1041
1070
|
const { promise: promptPromise } = acp.prompt(acpPrompt);
|
|
1042
1071
|
const promptResult = await promptPromise;
|
|
1043
1072
|
promptCompleted = true;
|
|
1044
|
-
if (process.env
|
|
1073
|
+
if (process.env["DEBUG"])
|
|
1045
1074
|
console.log('[acp:prompt:result]', JSON.stringify(promptResult).slice(0, 200));
|
|
1046
1075
|
// Save session BEFORE shutdown — acp.shutdown() causes SIGTERM (code=null),
|
|
1047
1076
|
// which skips the exit handler's code===0 gate, losing session continuity.
|
|
1048
1077
|
const persistedAcpSessionId = ctx.sessionId;
|
|
1049
|
-
if (persistedAcpSessionId && persistMainSession({
|
|
1078
|
+
if (persistedAcpSessionId && persistMainSession(stripUndefined({
|
|
1050
1079
|
ownerGeneration,
|
|
1051
1080
|
forceNew,
|
|
1052
1081
|
employeeSessionId: empSid,
|
|
@@ -1056,7 +1085,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1056
1085
|
model,
|
|
1057
1086
|
resumeKey,
|
|
1058
1087
|
effort: cfg.effort || '',
|
|
1059
|
-
})) {
|
|
1088
|
+
}))) {
|
|
1060
1089
|
console.log(`[jaw:session] saved ${cli} session=${persistedAcpSessionId.slice(0, 12)}... (pre-shutdown)`);
|
|
1061
1090
|
}
|
|
1062
1091
|
await acp.shutdown();
|
|
@@ -1071,7 +1100,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1071
1100
|
if (acpSettled)
|
|
1072
1101
|
return; // error handler already resolved
|
|
1073
1102
|
acpSettled = true;
|
|
1074
|
-
cleanupEmployeeTmpDir(spawnCwd, settings
|
|
1103
|
+
cleanupEmployeeTmpDir(spawnCwd, settings["workingDir"], agentLabel);
|
|
1075
1104
|
opts.lifecycle?.onExit?.(code ?? null);
|
|
1076
1105
|
// [I2] Consume per-process kill reason
|
|
1077
1106
|
const acpKillReason = consumeKillReason(acp.proc?.pid);
|
|
@@ -1139,8 +1168,9 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1139
1168
|
console.warn(`[spawn:dup] activeProcesses already has child for ${agentLabel} — orphaning previous reference`);
|
|
1140
1169
|
}
|
|
1141
1170
|
activeProcesses.set(agentLabel, child);
|
|
1142
|
-
|
|
1143
|
-
|
|
1171
|
+
if (!opts.internal)
|
|
1172
|
+
broadcast('agent_status', { running: true, agentId: agentLabel, cli, ...empTag });
|
|
1173
|
+
if (mainManaged && !opts.internal)
|
|
1144
1174
|
beginLiveRun(liveScope, cli);
|
|
1145
1175
|
// ─── DIFF-A: error guard — prevent uncaught ENOENT crash ───
|
|
1146
1176
|
let stdSettled = false; // guard: error→close can fire sequentially
|
|
@@ -1157,7 +1187,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1157
1187
|
if (stdSettled)
|
|
1158
1188
|
return;
|
|
1159
1189
|
stdSettled = true;
|
|
1160
|
-
cleanupEmployeeTmpDir(spawnCwd, settings
|
|
1190
|
+
cleanupEmployeeTmpDir(spawnCwd, settings["workingDir"], agentLabel);
|
|
1161
1191
|
opts.lifecycle?.onExit?.(null);
|
|
1162
1192
|
const msg = err.code === 'ENOENT'
|
|
1163
1193
|
? `CLI '${cli}' 실행 실패 (ENOENT). 설치/경로를 확인하세요.`
|
|
@@ -1175,7 +1205,7 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1175
1205
|
processQueue();
|
|
1176
1206
|
});
|
|
1177
1207
|
if (mainManaged && !opts.internal && !opts._skipInsert) {
|
|
1178
|
-
insertMessage.run('user', prompt, cli, model, settings
|
|
1208
|
+
insertMessage.run('user', prompt, cli, model, settings["workingDir"] || null);
|
|
1179
1209
|
}
|
|
1180
1210
|
if (cli === 'claude') {
|
|
1181
1211
|
child.stdin.write(withHistoryPrompt(prompt, historyBlock));
|
|
@@ -1187,7 +1217,9 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1187
1217
|
child.stdin.write(codexStdin);
|
|
1188
1218
|
}
|
|
1189
1219
|
child.stdin.end();
|
|
1190
|
-
|
|
1220
|
+
if (!opts.internal)
|
|
1221
|
+
broadcast('agent_status', { status: 'running', cli, agentId: agentLabel, ...empTag }, traceAudience);
|
|
1222
|
+
const traceRunId = startTraceRun({ cli, model, workingDir: settings["workingDir"] || null, agentLabel, audience: traceAudience });
|
|
1191
1223
|
const ctx = {
|
|
1192
1224
|
fullText: '',
|
|
1193
1225
|
traceLog: [],
|
|
@@ -1201,14 +1233,41 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1201
1233
|
tokens: null,
|
|
1202
1234
|
stderrBuf: '',
|
|
1203
1235
|
hasActiveSubAgent: false,
|
|
1204
|
-
showReasoning: settings
|
|
1236
|
+
showReasoning: settings["showReasoning"] === true,
|
|
1205
1237
|
outputTextStarted: false,
|
|
1206
1238
|
liveScope: effectiveLiveScope,
|
|
1207
|
-
parentLiveScope:
|
|
1239
|
+
parentLiveScope: parentLiveScopeForChild,
|
|
1240
|
+
traceRunId,
|
|
1241
|
+
traceAudience,
|
|
1208
1242
|
geminiResultSeen: false,
|
|
1209
|
-
opencodeSpawnAudit: opencodeSpawnAudit,
|
|
1243
|
+
...(opencodeSpawnAudit ? { opencodeSpawnAudit: opencodeSpawnAudit } : {}),
|
|
1210
1244
|
};
|
|
1211
1245
|
let geminiWatchdog = null;
|
|
1246
|
+
// ─── Subprocess stall watchdog (Phase 1: #178 OAuth2 stall recovery) ───
|
|
1247
|
+
const rawAgentTimeoutCfg = settings["agentTimeout"];
|
|
1248
|
+
const agentTimeoutCfg = rawAgentTimeoutCfg && typeof rawAgentTimeoutCfg === 'object'
|
|
1249
|
+
? rawAgentTimeoutCfg
|
|
1250
|
+
: {};
|
|
1251
|
+
const watchdogConfig = {};
|
|
1252
|
+
if (typeof agentTimeoutCfg['firstProgressMs'] === 'number')
|
|
1253
|
+
watchdogConfig.firstProgressMs = agentTimeoutCfg['firstProgressMs'];
|
|
1254
|
+
if (typeof agentTimeoutCfg['idleMs'] === 'number')
|
|
1255
|
+
watchdogConfig.idleMs = agentTimeoutCfg['idleMs'];
|
|
1256
|
+
if (typeof agentTimeoutCfg['absoluteMs'] === 'number')
|
|
1257
|
+
watchdogConfig.absoluteMs = agentTimeoutCfg['absoluteMs'];
|
|
1258
|
+
const stallWatchdog = attachWatchdog(child, agentLabel, (reason) => {
|
|
1259
|
+
console.log(`[jaw:watchdog] killing ${agentLabel} — ${reason}`);
|
|
1260
|
+
ctx.stallReason = reason;
|
|
1261
|
+
if (child.pid) {
|
|
1262
|
+
killProcessTree(child.pid, 'SIGTERM');
|
|
1263
|
+
setTimeout(() => {
|
|
1264
|
+
try {
|
|
1265
|
+
killProcessTree(child.pid, 'SIGKILL');
|
|
1266
|
+
}
|
|
1267
|
+
catch { /* already dead */ }
|
|
1268
|
+
}, 5_000);
|
|
1269
|
+
}
|
|
1270
|
+
}, watchdogConfig);
|
|
1212
1271
|
let buffer = '';
|
|
1213
1272
|
const recordOpencodeEvent = (line, event) => {
|
|
1214
1273
|
if (cli !== 'opencode')
|
|
@@ -1217,6 +1276,62 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1217
1276
|
ctx.opencodeLastEventType = typeof event?.type === 'string' ? event.type : 'unknown';
|
|
1218
1277
|
ctx.opencodeLastEventAt = Date.now();
|
|
1219
1278
|
};
|
|
1279
|
+
const dispatchNdjsonLine = (line) => {
|
|
1280
|
+
let raw;
|
|
1281
|
+
try {
|
|
1282
|
+
raw = JSON.parse(line);
|
|
1283
|
+
}
|
|
1284
|
+
catch {
|
|
1285
|
+
appendTraceEvent({ runId: ctx.traceRunId, source: 'cli_raw', eventType: 'malformed_json', raw: line });
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
appendTraceEvent({
|
|
1289
|
+
runId: ctx.traceRunId,
|
|
1290
|
+
source: 'cli_raw',
|
|
1291
|
+
eventType: fieldString(asCliEventRecord(raw).type, '<no-type>'),
|
|
1292
|
+
raw,
|
|
1293
|
+
});
|
|
1294
|
+
const event = discriminate(cli, raw);
|
|
1295
|
+
if (!event) {
|
|
1296
|
+
const type = fieldString(asCliEventRecord(raw).type, '<no-type>');
|
|
1297
|
+
ctx.traceLog.push(`[cli:unknown-event] cli=${cli} type=${type} preview=${JSON.stringify(raw).slice(0, 200)}`);
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
recordOpencodeEvent(line, event);
|
|
1301
|
+
if (process.env["DEBUG"]) {
|
|
1302
|
+
console.log(`[jaw:event:${agentLabel}] ${cli} type=${event.type}`);
|
|
1303
|
+
console.log(`[jaw:raw:${agentLabel}] ${line.slice(0, 300)}`);
|
|
1304
|
+
}
|
|
1305
|
+
logEventSummary(agentLabel, cli, event, ctx);
|
|
1306
|
+
if (!ctx.sessionId)
|
|
1307
|
+
ctx.sessionId = extractSessionId(cli, event);
|
|
1308
|
+
extractFromEvent(cli, event, ctx, agentLabel, empTag);
|
|
1309
|
+
// Gemini watchdog: AFTER extractFromEvent sets geminiResultSeen
|
|
1310
|
+
if (cli === 'gemini' && ctx.geminiResultSeen && !geminiWatchdog) {
|
|
1311
|
+
geminiWatchdog = setTimeout(() => {
|
|
1312
|
+
console.warn(`[jaw:gemini-watchdog] ${agentLabel} — result seen but close not received after 10s, killing`);
|
|
1313
|
+
try {
|
|
1314
|
+
child.kill('SIGTERM');
|
|
1315
|
+
}
|
|
1316
|
+
catch { /* already dead */ }
|
|
1317
|
+
}, 10000);
|
|
1318
|
+
}
|
|
1319
|
+
// Sub-agent wait: keep stall timer alive
|
|
1320
|
+
if (ctx.hasActiveSubAgent) {
|
|
1321
|
+
opts.lifecycle?.onActivity?.('heartbeat');
|
|
1322
|
+
}
|
|
1323
|
+
const outputChunk = extractOutputChunk(cli, event, ctx);
|
|
1324
|
+
if (outputChunk) {
|
|
1325
|
+
if (ctx.liveScope)
|
|
1326
|
+
appendLiveRunText(ctx.liveScope, outputChunk);
|
|
1327
|
+
broadcast('agent_output', {
|
|
1328
|
+
agentId: agentLabel,
|
|
1329
|
+
cli,
|
|
1330
|
+
text: outputChunk,
|
|
1331
|
+
...empTag,
|
|
1332
|
+
}, (opts.internal || isEmployee) ? 'internal' : 'public');
|
|
1333
|
+
}
|
|
1334
|
+
};
|
|
1220
1335
|
if (cli === 'opencode') {
|
|
1221
1336
|
opencodeIdleTimer = setInterval(() => {
|
|
1222
1337
|
const idleMs = Date.now() - lastOpencodeIoAt;
|
|
@@ -1237,55 +1352,20 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1237
1352
|
for (const line of lines) {
|
|
1238
1353
|
if (!line.trim())
|
|
1239
1354
|
continue;
|
|
1240
|
-
|
|
1241
|
-
const event = JSON.parse(line);
|
|
1242
|
-
recordOpencodeEvent(line, event);
|
|
1243
|
-
if (process.env.DEBUG) {
|
|
1244
|
-
console.log(`[jaw:event:${agentLabel}] ${cli} type=${event.type}`);
|
|
1245
|
-
console.log(`[jaw:raw:${agentLabel}] ${line.slice(0, 300)}`);
|
|
1246
|
-
}
|
|
1247
|
-
logEventSummary(agentLabel, cli, event, ctx);
|
|
1248
|
-
if (!ctx.sessionId)
|
|
1249
|
-
ctx.sessionId = extractSessionId(cli, event);
|
|
1250
|
-
extractFromEvent(cli, event, ctx, agentLabel, empTag);
|
|
1251
|
-
// Gemini watchdog: AFTER extractFromEvent sets geminiResultSeen
|
|
1252
|
-
if (cli === 'gemini' && ctx.geminiResultSeen && !geminiWatchdog) {
|
|
1253
|
-
geminiWatchdog = setTimeout(() => {
|
|
1254
|
-
console.warn(`[jaw:gemini-watchdog] ${agentLabel} — result seen but close not received after 10s, killing`);
|
|
1255
|
-
try {
|
|
1256
|
-
child.kill('SIGTERM');
|
|
1257
|
-
}
|
|
1258
|
-
catch { /* already dead */ }
|
|
1259
|
-
}, 10000);
|
|
1260
|
-
}
|
|
1261
|
-
// Sub-agent wait: keep stall timer alive
|
|
1262
|
-
if (ctx.hasActiveSubAgent) {
|
|
1263
|
-
opts.lifecycle?.onActivity?.('heartbeat');
|
|
1264
|
-
}
|
|
1265
|
-
const outputChunk = extractOutputChunk(cli, event, ctx);
|
|
1266
|
-
if (outputChunk) {
|
|
1267
|
-
if (ctx.liveScope)
|
|
1268
|
-
appendLiveRunText(ctx.liveScope, outputChunk);
|
|
1269
|
-
broadcast('agent_output', {
|
|
1270
|
-
agentId: agentLabel,
|
|
1271
|
-
cli,
|
|
1272
|
-
text: outputChunk,
|
|
1273
|
-
...empTag,
|
|
1274
|
-
}, isEmployee ? 'internal' : 'public');
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
catch { /* non-JSON line */ }
|
|
1355
|
+
dispatchNdjsonLine(line);
|
|
1278
1356
|
}
|
|
1279
1357
|
});
|
|
1280
1358
|
child.stderr.on('data', (chunk) => {
|
|
1281
1359
|
opts.lifecycle?.onActivity?.('stderr');
|
|
1282
1360
|
lastOpencodeIoAt = Date.now();
|
|
1283
1361
|
const text = chunk.toString().trim();
|
|
1362
|
+
appendTraceEvent({ runId: ctx.traceRunId, source: 'stderr', eventType: 'stderr', raw: text });
|
|
1284
1363
|
console.error(`[jaw:stderr:${agentLabel}] ${text}`);
|
|
1285
1364
|
ctx.stderrBuf += text + '\n';
|
|
1286
1365
|
});
|
|
1287
1366
|
child.on('close', (code) => {
|
|
1288
1367
|
clearOpencodeIdleTimer();
|
|
1368
|
+
stallWatchdog.stop();
|
|
1289
1369
|
if (geminiWatchdog) {
|
|
1290
1370
|
clearTimeout(geminiWatchdog);
|
|
1291
1371
|
geminiWatchdog = null;
|
|
@@ -1294,25 +1374,11 @@ export function spawnAgent(prompt, opts = {}) {
|
|
|
1294
1374
|
return; // error handler already resolved
|
|
1295
1375
|
// [I1] Flush residual NDJSON buffer — last event may lack trailing newline
|
|
1296
1376
|
if (buffer.trim()) {
|
|
1297
|
-
|
|
1298
|
-
const lastEvent = JSON.parse(buffer);
|
|
1299
|
-
recordOpencodeEvent(buffer, lastEvent);
|
|
1300
|
-
logEventSummary(agentLabel, cli, lastEvent, ctx);
|
|
1301
|
-
if (!ctx.sessionId)
|
|
1302
|
-
ctx.sessionId = extractSessionId(cli, lastEvent);
|
|
1303
|
-
extractFromEvent(cli, lastEvent, ctx, agentLabel, empTag);
|
|
1304
|
-
const outputChunk = extractOutputChunk(cli, lastEvent, ctx);
|
|
1305
|
-
if (outputChunk) {
|
|
1306
|
-
if (ctx.liveScope)
|
|
1307
|
-
appendLiveRunText(ctx.liveScope, outputChunk);
|
|
1308
|
-
broadcast('agent_output', { agentId: agentLabel, cli, text: outputChunk, ...empTag }, isEmployee ? 'internal' : 'public');
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
catch { /* incomplete JSON — discard */ }
|
|
1377
|
+
dispatchNdjsonLine(buffer);
|
|
1312
1378
|
buffer = '';
|
|
1313
1379
|
}
|
|
1314
1380
|
flushClaudeBuffers(ctx, agentLabel, empTag); // flush any pending thinking/input buffers
|
|
1315
|
-
cleanupEmployeeTmpDir(spawnCwd, settings
|
|
1381
|
+
cleanupEmployeeTmpDir(spawnCwd, settings["workingDir"], agentLabel);
|
|
1316
1382
|
opts.lifecycle?.onExit?.(code ?? null);
|
|
1317
1383
|
// [I2] Consume per-process kill reason
|
|
1318
1384
|
const stdKillReason = consumeKillReason(child.pid);
|