praxis-agent 0.1.0
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/LICENSE +21 -0
- package/README.md +534 -0
- package/dist/application/background-agent-manager.d.ts +66 -0
- package/dist/application/background-agent-manager.d.ts.map +1 -0
- package/dist/application/background-agent-manager.js +362 -0
- package/dist/application/background-agent-manager.js.map +1 -0
- package/dist/application/background-bash-manager.d.ts +54 -0
- package/dist/application/background-bash-manager.d.ts.map +1 -0
- package/dist/application/background-bash-manager.js +354 -0
- package/dist/application/background-bash-manager.js.map +1 -0
- package/dist/application/background-task-id.d.ts +5 -0
- package/dist/application/background-task-id.d.ts.map +1 -0
- package/dist/application/background-task-id.js +25 -0
- package/dist/application/background-task-id.js.map +1 -0
- package/dist/application/claude-project-purge.d.ts +50 -0
- package/dist/application/claude-project-purge.d.ts.map +1 -0
- package/dist/application/claude-project-purge.js +459 -0
- package/dist/application/claude-project-purge.js.map +1 -0
- package/dist/application/managed-worktree.d.ts +15 -0
- package/dist/application/managed-worktree.d.ts.map +1 -0
- package/dist/application/managed-worktree.js +127 -0
- package/dist/application/managed-worktree.js.map +1 -0
- package/dist/application/model-compactor.d.ts +8 -0
- package/dist/application/model-compactor.d.ts.map +1 -0
- package/dist/application/model-compactor.js +70 -0
- package/dist/application/model-compactor.js.map +1 -0
- package/dist/application/scheduled-prompt-manager.d.ts +69 -0
- package/dist/application/scheduled-prompt-manager.d.ts.map +1 -0
- package/dist/application/scheduled-prompt-manager.js +387 -0
- package/dist/application/scheduled-prompt-manager.js.map +1 -0
- package/dist/application/session-service.d.ts +142 -0
- package/dist/application/session-service.d.ts.map +1 -0
- package/dist/application/session-service.js +1690 -0
- package/dist/application/session-service.js.map +1 -0
- package/dist/application/session-worktree.d.ts +55 -0
- package/dist/application/session-worktree.d.ts.map +1 -0
- package/dist/application/session-worktree.js +311 -0
- package/dist/application/session-worktree.js.map +1 -0
- package/dist/application/subagent-service.d.ts +98 -0
- package/dist/application/subagent-service.d.ts.map +1 -0
- package/dist/application/subagent-service.js +1305 -0
- package/dist/application/subagent-service.js.map +1 -0
- package/dist/application/tool-use-summary.d.ts +8 -0
- package/dist/application/tool-use-summary.d.ts.map +1 -0
- package/dist/application/tool-use-summary.js +53 -0
- package/dist/application/tool-use-summary.js.map +1 -0
- package/dist/application/top-level-agent-manager.d.ts +58 -0
- package/dist/application/top-level-agent-manager.d.ts.map +1 -0
- package/dist/application/top-level-agent-manager.js +907 -0
- package/dist/application/top-level-agent-manager.js.map +1 -0
- package/dist/application/workflow-manager.d.ts +61 -0
- package/dist/application/workflow-manager.d.ts.map +1 -0
- package/dist/application/workflow-manager.js +582 -0
- package/dist/application/workflow-manager.js.map +1 -0
- package/dist/application/workflow-meta.d.ts +18 -0
- package/dist/application/workflow-meta.d.ts.map +1 -0
- package/dist/application/workflow-meta.js +146 -0
- package/dist/application/workflow-meta.js.map +1 -0
- package/dist/application/workflow-runtime.d.ts +29 -0
- package/dist/application/workflow-runtime.d.ts.map +1 -0
- package/dist/application/workflow-runtime.js +176 -0
- package/dist/application/workflow-runtime.js.map +1 -0
- package/dist/application/workflow-worktree.d.ts +9 -0
- package/dist/application/workflow-worktree.d.ts.map +1 -0
- package/dist/application/workflow-worktree.js +11 -0
- package/dist/application/workflow-worktree.js.map +1 -0
- package/dist/cli/agents-dashboard.d.ts +37 -0
- package/dist/cli/agents-dashboard.d.ts.map +1 -0
- package/dist/cli/agents-dashboard.js +408 -0
- package/dist/cli/agents-dashboard.js.map +1 -0
- package/dist/cli/controls.d.ts +15 -0
- package/dist/cli/controls.d.ts.map +1 -0
- package/dist/cli/controls.js +219 -0
- package/dist/cli/controls.js.map +1 -0
- package/dist/cli/debug.d.ts +13 -0
- package/dist/cli/debug.d.ts.map +1 -0
- package/dist/cli/debug.js +37 -0
- package/dist/cli/debug.js.map +1 -0
- package/dist/cli/interactive.d.ts +63 -0
- package/dist/cli/interactive.d.ts.map +1 -0
- package/dist/cli/interactive.js +600 -0
- package/dist/cli/interactive.js.map +1 -0
- package/dist/cli/protocol.d.ts +251 -0
- package/dist/cli/protocol.d.ts.map +1 -0
- package/dist/cli/protocol.js +2146 -0
- package/dist/cli/protocol.js.map +1 -0
- package/dist/cli.d.ts +116 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +3901 -0
- package/dist/cli.js.map +1 -0
- package/dist/compatibility/claude/compaction.d.ts +19 -0
- package/dist/compatibility/claude/compaction.d.ts.map +1 -0
- package/dist/compatibility/claude/compaction.js +82 -0
- package/dist/compatibility/claude/compaction.js.map +1 -0
- package/dist/compatibility/claude/context.d.ts +24 -0
- package/dist/compatibility/claude/context.d.ts.map +1 -0
- package/dist/compatibility/claude/context.js +92 -0
- package/dist/compatibility/claude/context.js.map +1 -0
- package/dist/compatibility/claude/dynamic-context.d.ts +20 -0
- package/dist/compatibility/claude/dynamic-context.d.ts.map +1 -0
- package/dist/compatibility/claude/dynamic-context.js +168 -0
- package/dist/compatibility/claude/dynamic-context.js.map +1 -0
- package/dist/compatibility/claude/file-history.d.ts +14 -0
- package/dist/compatibility/claude/file-history.d.ts.map +1 -0
- package/dist/compatibility/claude/file-history.js +340 -0
- package/dist/compatibility/claude/file-history.js.map +1 -0
- package/dist/compatibility/claude/file-resources.d.ts +28 -0
- package/dist/compatibility/claude/file-resources.d.ts.map +1 -0
- package/dist/compatibility/claude/file-resources.js +168 -0
- package/dist/compatibility/claude/file-resources.js.map +1 -0
- package/dist/compatibility/claude/fork.d.ts +9 -0
- package/dist/compatibility/claude/fork.d.ts.map +1 -0
- package/dist/compatibility/claude/fork.js +225 -0
- package/dist/compatibility/claude/fork.js.map +1 -0
- package/dist/compatibility/claude/history.d.ts +4 -0
- package/dist/compatibility/claude/history.d.ts.map +1 -0
- package/dist/compatibility/claude/history.js +86 -0
- package/dist/compatibility/claude/history.js.map +1 -0
- package/dist/compatibility/claude/ownership.d.ts +87 -0
- package/dist/compatibility/claude/ownership.d.ts.map +1 -0
- package/dist/compatibility/claude/ownership.js +100 -0
- package/dist/compatibility/claude/ownership.js.map +1 -0
- package/dist/compatibility/claude/paths.d.ts +17 -0
- package/dist/compatibility/claude/paths.d.ts.map +1 -0
- package/dist/compatibility/claude/paths.js +54 -0
- package/dist/compatibility/claude/paths.js.map +1 -0
- package/dist/compatibility/claude/pr-links.d.ts +25 -0
- package/dist/compatibility/claude/pr-links.d.ts.map +1 -0
- package/dist/compatibility/claude/pr-links.js +80 -0
- package/dist/compatibility/claude/pr-links.js.map +1 -0
- package/dist/compatibility/claude/projection.d.ts +11 -0
- package/dist/compatibility/claude/projection.d.ts.map +1 -0
- package/dist/compatibility/claude/projection.js +325 -0
- package/dist/compatibility/claude/projection.js.map +1 -0
- package/dist/compatibility/claude/schema.d.ts +18 -0
- package/dist/compatibility/claude/schema.d.ts.map +1 -0
- package/dist/compatibility/claude/schema.js +983 -0
- package/dist/compatibility/claude/schema.js.map +1 -0
- package/dist/compatibility/claude/shared-resources.d.ts +51 -0
- package/dist/compatibility/claude/shared-resources.d.ts.map +1 -0
- package/dist/compatibility/claude/shared-resources.js +382 -0
- package/dist/compatibility/claude/shared-resources.js.map +1 -0
- package/dist/compatibility/claude/sidechain.d.ts +50 -0
- package/dist/compatibility/claude/sidechain.d.ts.map +1 -0
- package/dist/compatibility/claude/sidechain.js +90 -0
- package/dist/compatibility/claude/sidechain.js.map +1 -0
- package/dist/compatibility/claude/tool-links.d.ts +13 -0
- package/dist/compatibility/claude/tool-links.d.ts.map +1 -0
- package/dist/compatibility/claude/tool-links.js +61 -0
- package/dist/compatibility/claude/tool-links.js.map +1 -0
- package/dist/compatibility/claude/translation.d.ts +71 -0
- package/dist/compatibility/claude/translation.d.ts.map +1 -0
- package/dist/compatibility/claude/translation.js +443 -0
- package/dist/compatibility/claude/translation.js.map +1 -0
- package/dist/compatibility/claude/workflow-replay.d.ts +10 -0
- package/dist/compatibility/claude/workflow-replay.d.ts.map +1 -0
- package/dist/compatibility/claude/workflow-replay.js +66 -0
- package/dist/compatibility/claude/workflow-replay.js.map +1 -0
- package/dist/compatibility/claude/workflow.d.ts +33 -0
- package/dist/compatibility/claude/workflow.d.ts.map +1 -0
- package/dist/compatibility/claude/workflow.js +76 -0
- package/dist/compatibility/claude/workflow.js.map +1 -0
- package/dist/core/compaction.d.ts +16 -0
- package/dist/core/compaction.d.ts.map +1 -0
- package/dist/core/compaction.js +2 -0
- package/dist/core/compaction.js.map +1 -0
- package/dist/core/context-budget.d.ts +28 -0
- package/dist/core/context-budget.d.ts.map +1 -0
- package/dist/core/context-budget.js +108 -0
- package/dist/core/context-budget.js.map +1 -0
- package/dist/core/context.d.ts +16 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +13 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/runtime.d.ts +394 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/core/runtime.js +507 -0
- package/dist/core/runtime.js.map +1 -0
- package/dist/core/usage.d.ts +26 -0
- package/dist/core/usage.d.ts.map +1 -0
- package/dist/core/usage.js +133 -0
- package/dist/core/usage.js.map +1 -0
- package/dist/extensions/claude-extension-tools.d.ts +16 -0
- package/dist/extensions/claude-extension-tools.d.ts.map +1 -0
- package/dist/extensions/claude-extension-tools.js +78 -0
- package/dist/extensions/claude-extension-tools.js.map +1 -0
- package/dist/extensions/claude-extensions.d.ts +41 -0
- package/dist/extensions/claude-extensions.d.ts.map +1 -0
- package/dist/extensions/claude-extensions.js +270 -0
- package/dist/extensions/claude-extensions.js.map +1 -0
- package/dist/hooks/claude-hook-tools.d.ts +26 -0
- package/dist/hooks/claude-hook-tools.d.ts.map +1 -0
- package/dist/hooks/claude-hook-tools.js +129 -0
- package/dist/hooks/claude-hook-tools.js.map +1 -0
- package/dist/hooks/claude-hooks.d.ts +87 -0
- package/dist/hooks/claude-hooks.d.ts.map +1 -0
- package/dist/hooks/claude-hooks.js +411 -0
- package/dist/hooks/claude-hooks.js.map +1 -0
- package/dist/maintenance/doctor.d.ts +33 -0
- package/dist/maintenance/doctor.d.ts.map +1 -0
- package/dist/maintenance/doctor.js +391 -0
- package/dist/maintenance/doctor.js.map +1 -0
- package/dist/maintenance/self-update.d.ts +31 -0
- package/dist/maintenance/self-update.d.ts.map +1 -0
- package/dist/maintenance/self-update.js +81 -0
- package/dist/maintenance/self-update.js.map +1 -0
- package/dist/mcp/claude-mcp-management.d.ts +28 -0
- package/dist/mcp/claude-mcp-management.d.ts.map +1 -0
- package/dist/mcp/claude-mcp-management.js +169 -0
- package/dist/mcp/claude-mcp-management.js.map +1 -0
- package/dist/mcp/claude-mcp-oauth.d.ts +113 -0
- package/dist/mcp/claude-mcp-oauth.d.ts.map +1 -0
- package/dist/mcp/claude-mcp-oauth.js +1053 -0
- package/dist/mcp/claude-mcp-oauth.js.map +1 -0
- package/dist/mcp/claude-mcp-tools.d.ts +98 -0
- package/dist/mcp/claude-mcp-tools.d.ts.map +1 -0
- package/dist/mcp/claude-mcp-tools.js +1246 -0
- package/dist/mcp/claude-mcp-tools.js.map +1 -0
- package/dist/mcp/praxis-mcp-server.d.ts +35 -0
- package/dist/mcp/praxis-mcp-server.d.ts.map +1 -0
- package/dist/mcp/praxis-mcp-server.js +520 -0
- package/dist/mcp/praxis-mcp-server.js.map +1 -0
- package/dist/permissions/claude-auto-classifier.d.ts +20 -0
- package/dist/permissions/claude-auto-classifier.d.ts.map +1 -0
- package/dist/permissions/claude-auto-classifier.js +140 -0
- package/dist/permissions/claude-auto-classifier.js.map +1 -0
- package/dist/permissions/claude-permission-resolver.d.ts +30 -0
- package/dist/permissions/claude-permission-resolver.d.ts.map +1 -0
- package/dist/permissions/claude-permission-resolver.js +334 -0
- package/dist/permissions/claude-permission-resolver.js.map +1 -0
- package/dist/persistence/claude-job-store.d.ts +68 -0
- package/dist/persistence/claude-job-store.d.ts.map +1 -0
- package/dist/persistence/claude-job-store.js +311 -0
- package/dist/persistence/claude-job-store.js.map +1 -0
- package/dist/persistence/claude-scheduled-task-store.d.ts +29 -0
- package/dist/persistence/claude-scheduled-task-store.d.ts.map +1 -0
- package/dist/persistence/claude-scheduled-task-store.js +163 -0
- package/dist/persistence/claude-scheduled-task-store.js.map +1 -0
- package/dist/persistence/claude-sidechain-store.d.ts +18 -0
- package/dist/persistence/claude-sidechain-store.d.ts.map +1 -0
- package/dist/persistence/claude-sidechain-store.js +107 -0
- package/dist/persistence/claude-sidechain-store.js.map +1 -0
- package/dist/persistence/claude-task-store.d.ts +72 -0
- package/dist/persistence/claude-task-store.d.ts.map +1 -0
- package/dist/persistence/claude-task-store.js +440 -0
- package/dist/persistence/claude-task-store.js.map +1 -0
- package/dist/persistence/claude-transcript-store.d.ts +85 -0
- package/dist/persistence/claude-transcript-store.d.ts.map +1 -0
- package/dist/persistence/claude-transcript-store.js +385 -0
- package/dist/persistence/claude-transcript-store.js.map +1 -0
- package/dist/persistence/claude-workflow-store.d.ts +41 -0
- package/dist/persistence/claude-workflow-store.d.ts.map +1 -0
- package/dist/persistence/claude-workflow-store.js +263 -0
- package/dist/persistence/claude-workflow-store.js.map +1 -0
- package/dist/persistence/in-memory-sidechain-store.d.ts +12 -0
- package/dist/persistence/in-memory-sidechain-store.d.ts.map +1 -0
- package/dist/persistence/in-memory-sidechain-store.js +30 -0
- package/dist/persistence/in-memory-sidechain-store.js.map +1 -0
- package/dist/persistence/in-memory-transcript-store.d.ts +15 -0
- package/dist/persistence/in-memory-transcript-store.d.ts.map +1 -0
- package/dist/persistence/in-memory-transcript-store.js +95 -0
- package/dist/persistence/in-memory-transcript-store.js.map +1 -0
- package/dist/platform/atomic-write.d.ts +5 -0
- package/dist/platform/atomic-write.d.ts.map +1 -0
- package/dist/platform/atomic-write.js +25 -0
- package/dist/platform/atomic-write.js.map +1 -0
- package/dist/platform/bounded-process-runner.d.ts +28 -0
- package/dist/platform/bounded-process-runner.d.ts.map +1 -0
- package/dist/platform/bounded-process-runner.js +209 -0
- package/dist/platform/bounded-process-runner.js.map +1 -0
- package/dist/platform/claude-version.d.ts +5 -0
- package/dist/platform/claude-version.d.ts.map +1 -0
- package/dist/platform/claude-version.js +17 -0
- package/dist/platform/claude-version.js.map +1 -0
- package/dist/platform/command-shell.d.ts +3 -0
- package/dist/platform/command-shell.d.ts.map +1 -0
- package/dist/platform/command-shell.js +15 -0
- package/dist/platform/command-shell.js.map +1 -0
- package/dist/platform/exclusive-file-lease.d.ts +15 -0
- package/dist/platform/exclusive-file-lease.d.ts.map +1 -0
- package/dist/platform/exclusive-file-lease.js +265 -0
- package/dist/platform/exclusive-file-lease.js.map +1 -0
- package/dist/platform/sensitive-data.d.ts +8 -0
- package/dist/platform/sensitive-data.d.ts.map +1 -0
- package/dist/platform/sensitive-data.js +138 -0
- package/dist/platform/sensitive-data.js.map +1 -0
- package/dist/platform/tmux-worktree.d.ts +30 -0
- package/dist/platform/tmux-worktree.d.ts.map +1 -0
- package/dist/platform/tmux-worktree.js +138 -0
- package/dist/platform/tmux-worktree.js.map +1 -0
- package/dist/plugins/claude-plugin-eval-discovery.d.ts +20 -0
- package/dist/plugins/claude-plugin-eval-discovery.d.ts.map +1 -0
- package/dist/plugins/claude-plugin-eval-discovery.js +128 -0
- package/dist/plugins/claude-plugin-eval-discovery.js.map +1 -0
- package/dist/plugins/claude-plugin-eval-graders.d.ts +49 -0
- package/dist/plugins/claude-plugin-eval-graders.d.ts.map +1 -0
- package/dist/plugins/claude-plugin-eval-graders.js +137 -0
- package/dist/plugins/claude-plugin-eval-graders.js.map +1 -0
- package/dist/plugins/claude-plugin-eval-runner.d.ts +50 -0
- package/dist/plugins/claude-plugin-eval-runner.d.ts.map +1 -0
- package/dist/plugins/claude-plugin-eval-runner.js +189 -0
- package/dist/plugins/claude-plugin-eval-runner.js.map +1 -0
- package/dist/plugins/claude-plugin-eval-schema.d.ts +80 -0
- package/dist/plugins/claude-plugin-eval-schema.d.ts.map +1 -0
- package/dist/plugins/claude-plugin-eval-schema.js +436 -0
- package/dist/plugins/claude-plugin-eval-schema.js.map +1 -0
- package/dist/plugins/claude-plugin-eval.d.ts +66 -0
- package/dist/plugins/claude-plugin-eval.d.ts.map +1 -0
- package/dist/plugins/claude-plugin-eval.js +438 -0
- package/dist/plugins/claude-plugin-eval.js.map +1 -0
- package/dist/plugins/claude-plugin-maintenance.d.ts +39 -0
- package/dist/plugins/claude-plugin-maintenance.d.ts.map +1 -0
- package/dist/plugins/claude-plugin-maintenance.js +336 -0
- package/dist/plugins/claude-plugin-maintenance.js.map +1 -0
- package/dist/plugins/claude-plugin-marketplace.d.ts +97 -0
- package/dist/plugins/claude-plugin-marketplace.d.ts.map +1 -0
- package/dist/plugins/claude-plugin-marketplace.js +1433 -0
- package/dist/plugins/claude-plugin-marketplace.js.map +1 -0
- package/dist/plugins/claude-plugin-mcpb.d.ts +71 -0
- package/dist/plugins/claude-plugin-mcpb.d.ts.map +1 -0
- package/dist/plugins/claude-plugin-mcpb.js +885 -0
- package/dist/plugins/claude-plugin-mcpb.js.map +1 -0
- package/dist/plugins/claude-plugin-runtime.d.ts +120 -0
- package/dist/plugins/claude-plugin-runtime.d.ts.map +1 -0
- package/dist/plugins/claude-plugin-runtime.js +1263 -0
- package/dist/plugins/claude-plugin-runtime.js.map +1 -0
- package/dist/providers/anthropic-compatible.d.ts +35 -0
- package/dist/providers/anthropic-compatible.d.ts.map +1 -0
- package/dist/providers/anthropic-compatible.js +733 -0
- package/dist/providers/anthropic-compatible.js.map +1 -0
- package/dist/providers/environment.d.ts +14 -0
- package/dist/providers/environment.d.ts.map +1 -0
- package/dist/providers/environment.js +67 -0
- package/dist/providers/environment.js.map +1 -0
- package/dist/providers/fallback-provider.d.ts +17 -0
- package/dist/providers/fallback-provider.d.ts.map +1 -0
- package/dist/providers/fallback-provider.js +70 -0
- package/dist/providers/fallback-provider.js.map +1 -0
- package/dist/providers/openai-compatible.d.ts +30 -0
- package/dist/providers/openai-compatible.d.ts.map +1 -0
- package/dist/providers/openai-compatible.js +409 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/tools/claude-interactive-tools.d.ts +58 -0
- package/dist/tools/claude-interactive-tools.d.ts.map +1 -0
- package/dist/tools/claude-interactive-tools.js +390 -0
- package/dist/tools/claude-interactive-tools.js.map +1 -0
- package/dist/tools/claude-lsp-formatters.d.ts +2 -0
- package/dist/tools/claude-lsp-formatters.d.ts.map +1 -0
- package/dist/tools/claude-lsp-formatters.js +291 -0
- package/dist/tools/claude-lsp-formatters.js.map +1 -0
- package/dist/tools/claude-lsp-tool.d.ts +22 -0
- package/dist/tools/claude-lsp-tool.d.ts.map +1 -0
- package/dist/tools/claude-lsp-tool.js +744 -0
- package/dist/tools/claude-lsp-tool.js.map +1 -0
- package/dist/tools/claude-scheduled-tools.d.ts +20 -0
- package/dist/tools/claude-scheduled-tools.d.ts.map +1 -0
- package/dist/tools/claude-scheduled-tools.js +344 -0
- package/dist/tools/claude-scheduled-tools.js.map +1 -0
- package/dist/tools/claude-task-tools.d.ts +30 -0
- package/dist/tools/claude-task-tools.d.ts.map +1 -0
- package/dist/tools/claude-task-tools.js +503 -0
- package/dist/tools/claude-task-tools.js.map +1 -0
- package/dist/tools/claude-user-message.d.ts +16 -0
- package/dist/tools/claude-user-message.d.ts.map +1 -0
- package/dist/tools/claude-user-message.js +98 -0
- package/dist/tools/claude-user-message.js.map +1 -0
- package/dist/tools/claude-workflow-tools.d.ts +27 -0
- package/dist/tools/claude-workflow-tools.d.ts.map +1 -0
- package/dist/tools/claude-workflow-tools.js +257 -0
- package/dist/tools/claude-workflow-tools.js.map +1 -0
- package/dist/tools/claude-worktree-tools.d.ts +17 -0
- package/dist/tools/claude-worktree-tools.d.ts.map +1 -0
- package/dist/tools/claude-worktree-tools.js +135 -0
- package/dist/tools/claude-worktree-tools.js.map +1 -0
- package/dist/tools/filtered-tool-registry.d.ts +16 -0
- package/dist/tools/filtered-tool-registry.d.ts.map +1 -0
- package/dist/tools/filtered-tool-registry.js +51 -0
- package/dist/tools/filtered-tool-registry.js.map +1 -0
- package/dist/tools/glob.d.ts +9 -0
- package/dist/tools/glob.d.ts.map +1 -0
- package/dist/tools/glob.js +88 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/local-tools.d.ts +47 -0
- package/dist/tools/local-tools.d.ts.map +1 -0
- package/dist/tools/local-tools.js +1082 -0
- package/dist/tools/local-tools.js.map +1 -0
- package/dist/tools/notebook.d.ts +22 -0
- package/dist/tools/notebook.d.ts.map +1 -0
- package/dist/tools/notebook.js +154 -0
- package/dist/tools/notebook.js.map +1 -0
- package/dist/tools/web.d.ts +48 -0
- package/dist/tools/web.d.ts.map +1 -0
- package/dist/tools/web.js +726 -0
- package/dist/tools/web.js.map +1 -0
- package/package.json +145 -0
|
@@ -0,0 +1,1305 @@
|
|
|
1
|
+
import { randomBytes, randomUUID } from 'node:crypto';
|
|
2
|
+
import { readdir, stat } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { Ajv2020 } from 'ajv/dist/2020.js';
|
|
5
|
+
import { resolveClaudePaths } from '../compatibility/claude/paths.js';
|
|
6
|
+
import { workflowAgentFiles } from '../compatibility/claude/workflow.js';
|
|
7
|
+
import { createClaudeAsyncAgentToolUseResult, createClaudeAgentToolUseResult, createClaudeSidechainRoot, resolveClaudeSidechainPaths, toClaudeSidechainEntry, } from '../compatibility/claude/sidechain.js';
|
|
8
|
+
import { projectClaudeModelMessages } from '../compatibility/claude/projection.js';
|
|
9
|
+
import { selectClaudeSchemaAdapter, } from '../compatibility/claude/schema.js';
|
|
10
|
+
import { createClaudeHookAttachmentEntries, translateProviderEvents, } from '../compatibility/claude/translation.js';
|
|
11
|
+
import { injectFirstUserMessageContext, } from '../core/context.js';
|
|
12
|
+
import { ContextBudget } from '../core/context-budget.js';
|
|
13
|
+
import { AgentRuntime, } from '../core/runtime.js';
|
|
14
|
+
import { ClaudeHookToolCoordinator } from '../hooks/claude-hook-tools.js';
|
|
15
|
+
import { ClaudeSidechainStore } from '../persistence/claude-sidechain-store.js';
|
|
16
|
+
import { InMemorySidechainStore } from '../persistence/in-memory-sidechain-store.js';
|
|
17
|
+
import { BackgroundAgentManager, BackgroundAgentRunError, } from './background-agent-manager.js';
|
|
18
|
+
import { isBackgroundBashTaskId } from './background-task-id.js';
|
|
19
|
+
import { createManagedWorktree, } from './managed-worktree.js';
|
|
20
|
+
import { createWorkflowWorktree } from './workflow-worktree.js';
|
|
21
|
+
const DEFAULT_MAX_DEPTH = 4;
|
|
22
|
+
const DEFAULT_MAX_CALLS = 16;
|
|
23
|
+
const DEFAULT_MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
24
|
+
const structuredOnlyTools = {
|
|
25
|
+
definitions: () => [],
|
|
26
|
+
prepare: async (call) => call,
|
|
27
|
+
execute: async () => ({ content: '', isError: false }),
|
|
28
|
+
};
|
|
29
|
+
export class StructuredOutputRegistry {
|
|
30
|
+
base;
|
|
31
|
+
schema;
|
|
32
|
+
capture;
|
|
33
|
+
validate;
|
|
34
|
+
constructor(base, schema, capture) {
|
|
35
|
+
this.base = base;
|
|
36
|
+
this.schema = schema;
|
|
37
|
+
this.capture = capture;
|
|
38
|
+
this.validate = new Ajv2020({ allErrors: true, strict: false }).compile(schema);
|
|
39
|
+
}
|
|
40
|
+
definitions() {
|
|
41
|
+
const base = this.base.definitions();
|
|
42
|
+
const existing = new Set(base.map(({ name }) => name));
|
|
43
|
+
return [
|
|
44
|
+
...base,
|
|
45
|
+
...(existing.has('StructuredOutput')
|
|
46
|
+
? []
|
|
47
|
+
: [
|
|
48
|
+
{
|
|
49
|
+
name: 'StructuredOutput',
|
|
50
|
+
description: 'Use this tool to return your final response in the requested structured format. You MUST call this tool exactly once at the end of your response to provide the structured output.',
|
|
51
|
+
inputSchema: this.schema,
|
|
52
|
+
},
|
|
53
|
+
]),
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
prepare(call, context) {
|
|
57
|
+
if (call.name !== 'StructuredOutput')
|
|
58
|
+
return this.base.prepare(call, context);
|
|
59
|
+
if (this.capture && this.capture.calls > 0) {
|
|
60
|
+
throw new Error('StructuredOutput must be called exactly once');
|
|
61
|
+
}
|
|
62
|
+
if (!this.validate(call.input)) {
|
|
63
|
+
throw new Error(`StructuredOutput validation failed: ${this.validate.errors
|
|
64
|
+
?.map((error) => `${error.instancePath || '/'} ${error.message ?? 'is invalid'}`)
|
|
65
|
+
.join('; ')}`);
|
|
66
|
+
}
|
|
67
|
+
return Promise.resolve(call);
|
|
68
|
+
}
|
|
69
|
+
execute(call, context) {
|
|
70
|
+
if (call.name !== 'StructuredOutput')
|
|
71
|
+
return this.base.execute(call, context);
|
|
72
|
+
if (!this.capture)
|
|
73
|
+
throw new Error('StructuredOutput capture is unavailable');
|
|
74
|
+
this.capture.calls += 1;
|
|
75
|
+
this.capture.value = structuredClone(call.input);
|
|
76
|
+
return Promise.resolve({
|
|
77
|
+
content: 'Structured output recorded.',
|
|
78
|
+
isError: false,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function parseAgentInput(call) {
|
|
83
|
+
const allowed = new Set([
|
|
84
|
+
'description',
|
|
85
|
+
'prompt',
|
|
86
|
+
'subagent_type',
|
|
87
|
+
'model',
|
|
88
|
+
'run_in_background',
|
|
89
|
+
'name',
|
|
90
|
+
'team_name',
|
|
91
|
+
'mode',
|
|
92
|
+
'isolation',
|
|
93
|
+
]);
|
|
94
|
+
for (const key of Object.keys(call.input)) {
|
|
95
|
+
if (!allowed.has(key))
|
|
96
|
+
throw new Error(`Unknown Agent input field ${key}`);
|
|
97
|
+
}
|
|
98
|
+
const description = call.input.description;
|
|
99
|
+
const prompt = call.input.prompt;
|
|
100
|
+
const subagentType = call.input.subagent_type ?? 'general-purpose';
|
|
101
|
+
const model = call.input.model;
|
|
102
|
+
const name = call.input.name;
|
|
103
|
+
const teamName = call.input.team_name;
|
|
104
|
+
const permissionMode = call.input.mode;
|
|
105
|
+
const isolation = call.input.isolation;
|
|
106
|
+
if (typeof description !== 'string' || description.trim().length === 0) {
|
|
107
|
+
throw new Error('description must be a non-empty string');
|
|
108
|
+
}
|
|
109
|
+
if (typeof prompt !== 'string' || prompt.trim().length === 0) {
|
|
110
|
+
throw new Error('prompt must be a non-empty string');
|
|
111
|
+
}
|
|
112
|
+
if (typeof subagentType !== 'string' || subagentType.length === 0) {
|
|
113
|
+
throw new Error('subagent_type must be a non-empty string');
|
|
114
|
+
}
|
|
115
|
+
if (model !== undefined && typeof model !== 'string') {
|
|
116
|
+
throw new Error('model must be a string');
|
|
117
|
+
}
|
|
118
|
+
if (name !== undefined &&
|
|
119
|
+
(typeof name !== 'string' ||
|
|
120
|
+
!/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u.test(name))) {
|
|
121
|
+
throw new Error('name must be a valid agent name');
|
|
122
|
+
}
|
|
123
|
+
if (teamName !== undefined && typeof teamName !== 'string') {
|
|
124
|
+
throw new Error('team_name must be a string');
|
|
125
|
+
}
|
|
126
|
+
if (permissionMode !== undefined &&
|
|
127
|
+
(typeof permissionMode !== 'string' ||
|
|
128
|
+
![
|
|
129
|
+
'acceptEdits',
|
|
130
|
+
'auto',
|
|
131
|
+
'bypassPermissions',
|
|
132
|
+
'default',
|
|
133
|
+
'dontAsk',
|
|
134
|
+
'plan',
|
|
135
|
+
].includes(permissionMode))) {
|
|
136
|
+
throw new Error('mode is not a supported permission mode');
|
|
137
|
+
}
|
|
138
|
+
if (call.input.run_in_background !== undefined &&
|
|
139
|
+
typeof call.input.run_in_background !== 'boolean') {
|
|
140
|
+
throw new Error('run_in_background must be a boolean');
|
|
141
|
+
}
|
|
142
|
+
if (isolation !== undefined && isolation !== 'worktree') {
|
|
143
|
+
if (isolation !== 'remote') {
|
|
144
|
+
throw new Error('isolation must be worktree or remote');
|
|
145
|
+
}
|
|
146
|
+
throw new Error('Praxis does not support Agent isolation remote');
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
description,
|
|
150
|
+
prompt,
|
|
151
|
+
subagentType,
|
|
152
|
+
...(model === undefined ? {} : { model }),
|
|
153
|
+
...(name === undefined ? {} : { name }),
|
|
154
|
+
...(teamName === undefined ? {} : { teamName }),
|
|
155
|
+
...(permissionMode === undefined
|
|
156
|
+
? {}
|
|
157
|
+
: { permissionMode: permissionMode }),
|
|
158
|
+
...(isolation === undefined ? {} : { isolation }),
|
|
159
|
+
runInBackground: call.input.run_in_background !== false,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
export class ClaudeSubagentExecutor {
|
|
163
|
+
options;
|
|
164
|
+
schema;
|
|
165
|
+
calls = 0;
|
|
166
|
+
background = new BackgroundAgentManager();
|
|
167
|
+
ephemeralSidechains = new Map();
|
|
168
|
+
isEnabled(name) {
|
|
169
|
+
return this.options.toolNames?.includes(name) ?? true;
|
|
170
|
+
}
|
|
171
|
+
constructor(options) {
|
|
172
|
+
this.options = options;
|
|
173
|
+
this.schema = selectClaudeSchemaAdapter(options.claudeVersion);
|
|
174
|
+
}
|
|
175
|
+
async close() {
|
|
176
|
+
await this.background.close();
|
|
177
|
+
this.ephemeralSidechains.clear();
|
|
178
|
+
}
|
|
179
|
+
cwd() {
|
|
180
|
+
return this.options.cwdProvider?.() ?? this.options.cwd;
|
|
181
|
+
}
|
|
182
|
+
registry(sessionId, depth, promptIdForCall) {
|
|
183
|
+
return new ClaudeSubagentToolRegistry(this.options.baseTools, this, sessionId, depth, promptIdForCall);
|
|
184
|
+
}
|
|
185
|
+
definitions() {
|
|
186
|
+
return {
|
|
187
|
+
name: 'Agent',
|
|
188
|
+
description: 'Launch a new agent to handle complex, multi-step tasks. Agents run in the background by default; set run_in_background to false when the result is required synchronously.',
|
|
189
|
+
inputSchema: {
|
|
190
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
191
|
+
type: 'object',
|
|
192
|
+
properties: {
|
|
193
|
+
description: {
|
|
194
|
+
description: 'A short (3-5 word) description of the task',
|
|
195
|
+
type: 'string',
|
|
196
|
+
},
|
|
197
|
+
prompt: {
|
|
198
|
+
description: 'The task for the agent to perform',
|
|
199
|
+
type: 'string',
|
|
200
|
+
},
|
|
201
|
+
subagent_type: {
|
|
202
|
+
description: 'The type of specialized agent to use for this task',
|
|
203
|
+
type: 'string',
|
|
204
|
+
},
|
|
205
|
+
model: {
|
|
206
|
+
description: 'Optional model override for this agent. Takes precedence over the agent definition\'s model frontmatter. If omitted, uses the agent definition\'s model, or inherits from the parent. Ignored for subagent_type: "fork" — forks always inherit the parent model.',
|
|
207
|
+
type: 'string',
|
|
208
|
+
enum: ['sonnet', 'opus', 'haiku', 'fable'],
|
|
209
|
+
},
|
|
210
|
+
run_in_background: {
|
|
211
|
+
description: 'Agents run in the background by default; you will be notified when one completes. Set to false to run this agent synchronously when you need its result before continuing.',
|
|
212
|
+
type: 'boolean',
|
|
213
|
+
},
|
|
214
|
+
isolation: {
|
|
215
|
+
description: 'Isolation mode. "worktree" creates a temporary git worktree so the agent works on an isolated copy of the repo. "remote" launches the agent in a remote cloud environment (always runs in background; availability is gated).',
|
|
216
|
+
type: 'string',
|
|
217
|
+
enum: ['worktree', 'remote'],
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
required: ['description', 'prompt'],
|
|
221
|
+
additionalProperties: false,
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
managementDefinitions() {
|
|
226
|
+
return [
|
|
227
|
+
{
|
|
228
|
+
name: 'SendMessage',
|
|
229
|
+
description: 'Send a message to another agent.',
|
|
230
|
+
inputSchema: {
|
|
231
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
232
|
+
type: 'object',
|
|
233
|
+
properties: {
|
|
234
|
+
to: { description: 'Recipient: teammate name', type: 'string' },
|
|
235
|
+
summary: {
|
|
236
|
+
description: 'A 5-10 word summary shown as a preview in the UI (required when message is a string)',
|
|
237
|
+
type: 'string',
|
|
238
|
+
maxLength: 200,
|
|
239
|
+
},
|
|
240
|
+
message: {
|
|
241
|
+
description: 'Plain text message content',
|
|
242
|
+
type: 'string',
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
required: ['to', 'message'],
|
|
246
|
+
additionalProperties: false,
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: 'TaskOutput',
|
|
251
|
+
description: 'Retrieves output and status from a running or completed background task.',
|
|
252
|
+
inputSchema: {
|
|
253
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
254
|
+
type: 'object',
|
|
255
|
+
properties: {
|
|
256
|
+
task_id: {
|
|
257
|
+
description: 'The task ID to get output from',
|
|
258
|
+
type: 'string',
|
|
259
|
+
},
|
|
260
|
+
block: {
|
|
261
|
+
description: 'Whether to wait for completion',
|
|
262
|
+
default: true,
|
|
263
|
+
type: 'boolean',
|
|
264
|
+
},
|
|
265
|
+
timeout: {
|
|
266
|
+
description: 'Max wait time in ms',
|
|
267
|
+
default: 30000,
|
|
268
|
+
type: 'number',
|
|
269
|
+
minimum: 0,
|
|
270
|
+
maximum: 600000,
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
required: ['task_id', 'block', 'timeout'],
|
|
274
|
+
additionalProperties: false,
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: 'TaskStop',
|
|
279
|
+
description: 'Stops a running background task by its ID.',
|
|
280
|
+
inputSchema: {
|
|
281
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
282
|
+
type: 'object',
|
|
283
|
+
properties: {
|
|
284
|
+
task_id: {
|
|
285
|
+
description: 'The ID of the background task to stop. Agent-team teammates and named background agents are also accepted by agent ID or name.',
|
|
286
|
+
type: 'string',
|
|
287
|
+
},
|
|
288
|
+
shell_id: {
|
|
289
|
+
description: 'Deprecated: use task_id instead',
|
|
290
|
+
type: 'string',
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
additionalProperties: false,
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
];
|
|
297
|
+
}
|
|
298
|
+
prepare(call, depth) {
|
|
299
|
+
if (!this.isEnabled('Agent'))
|
|
300
|
+
throw new Error('Tool Agent is unavailable');
|
|
301
|
+
const input = parseAgentInput(call);
|
|
302
|
+
if (input.runInBackground && this.options.persistence === 'memory') {
|
|
303
|
+
throw new Error('Background agents require session persistence');
|
|
304
|
+
}
|
|
305
|
+
const spawnDepth = depth + 1;
|
|
306
|
+
if (spawnDepth > (this.options.maxDepth ?? DEFAULT_MAX_DEPTH)) {
|
|
307
|
+
throw new Error(`Agent spawn depth exceeded ${this.options.maxDepth ?? DEFAULT_MAX_DEPTH}`);
|
|
308
|
+
}
|
|
309
|
+
if (input.subagentType !== 'general-purpose' &&
|
|
310
|
+
!this.options.extensions?.agent(input.subagentType)) {
|
|
311
|
+
throw new Error(`Unknown Claude agent ${input.subagentType}`);
|
|
312
|
+
}
|
|
313
|
+
if (input.model && !this.options.providerForModel) {
|
|
314
|
+
throw new Error('Agent model overrides are unavailable for this provider');
|
|
315
|
+
}
|
|
316
|
+
if (input.permissionMode && !this.options.permissionResolverForMode) {
|
|
317
|
+
throw new Error('Agent permission mode overrides are unavailable');
|
|
318
|
+
}
|
|
319
|
+
return {
|
|
320
|
+
...call,
|
|
321
|
+
input: {
|
|
322
|
+
description: input.description,
|
|
323
|
+
prompt: input.prompt,
|
|
324
|
+
subagent_type: input.subagentType,
|
|
325
|
+
...(input.model ? { model: input.model } : {}),
|
|
326
|
+
...(input.name ? { name: input.name } : {}),
|
|
327
|
+
...(input.teamName ? { team_name: input.teamName } : {}),
|
|
328
|
+
...(input.permissionMode ? { mode: input.permissionMode } : {}),
|
|
329
|
+
...(input.isolation ? { isolation: input.isolation } : {}),
|
|
330
|
+
run_in_background: input.runInBackground,
|
|
331
|
+
},
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
async execute(call, sessionId, depth, promptId, context) {
|
|
335
|
+
this.calls += 1;
|
|
336
|
+
const maxCalls = this.options.maxCalls ?? DEFAULT_MAX_CALLS;
|
|
337
|
+
if (this.calls > maxCalls) {
|
|
338
|
+
throw new Error(`Agent call count exceeded ${maxCalls}`);
|
|
339
|
+
}
|
|
340
|
+
const input = parseAgentInput(call);
|
|
341
|
+
const spawnDepth = depth + 1;
|
|
342
|
+
const agentId = `a${randomBytes(8).toString('hex')}`;
|
|
343
|
+
const paths = resolveClaudePaths({
|
|
344
|
+
configDir: this.options.configRoot,
|
|
345
|
+
cwd: this.cwd(),
|
|
346
|
+
sessionId,
|
|
347
|
+
});
|
|
348
|
+
const initialIsolation = input.isolation
|
|
349
|
+
? await this.createAgentWorktree(paths.praxisRoot, sessionId, agentId)
|
|
350
|
+
: undefined;
|
|
351
|
+
const agentCwd = initialIsolation?.cwd ?? this.cwd();
|
|
352
|
+
const sidechainPaths = resolveClaudeSidechainPaths(paths.projectRoot, sessionId, agentId);
|
|
353
|
+
const sidechain = this.sidechainStore(sessionId, agentId, sidechainPaths);
|
|
354
|
+
const root = createClaudeSidechainRoot({
|
|
355
|
+
sessionId,
|
|
356
|
+
promptId,
|
|
357
|
+
prompt: input.prompt,
|
|
358
|
+
agentId,
|
|
359
|
+
cwd: agentCwd,
|
|
360
|
+
claudeVersion: this.options.claudeVersion,
|
|
361
|
+
gitBranch: null,
|
|
362
|
+
uuid: randomUUID(),
|
|
363
|
+
timestamp: new Date().toISOString(),
|
|
364
|
+
});
|
|
365
|
+
try {
|
|
366
|
+
await sidechain.create(root, {
|
|
367
|
+
agentType: input.subagentType,
|
|
368
|
+
description: input.description,
|
|
369
|
+
toolUseId: call.id,
|
|
370
|
+
spawnDepth,
|
|
371
|
+
...(input.name ? { name: input.name } : {}),
|
|
372
|
+
...(input.permissionMode
|
|
373
|
+
? { permissionMode: input.permissionMode }
|
|
374
|
+
: {}),
|
|
375
|
+
...(input.isolation ? { isolation: input.isolation } : {}),
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
await initialIsolation?.cleanup();
|
|
380
|
+
throw error;
|
|
381
|
+
}
|
|
382
|
+
const provider = input.model
|
|
383
|
+
? (this.options.providerForModel?.(input.model) ?? this.options.provider)
|
|
384
|
+
: this.options.provider;
|
|
385
|
+
const run = this.createBackgroundAgentRun({
|
|
386
|
+
input,
|
|
387
|
+
...(initialIsolation ? { initialIsolation } : {}),
|
|
388
|
+
createIsolation: () => this.createAgentWorktree(paths.praxisRoot, sessionId, agentId),
|
|
389
|
+
execute: (cwd, message, signal, continuation) => sidechain.withLease(async (lease) => this.runSidechain({
|
|
390
|
+
lease,
|
|
391
|
+
root,
|
|
392
|
+
input,
|
|
393
|
+
provider,
|
|
394
|
+
agentId,
|
|
395
|
+
spawnDepth,
|
|
396
|
+
promptId,
|
|
397
|
+
toolUseId: call.id,
|
|
398
|
+
transcriptPath: sidechainPaths.transcriptFile,
|
|
399
|
+
toolResultDirectory: join(paths.projectRoot, sessionId, 'tool-results'),
|
|
400
|
+
...(continuation ? { continuationMessage: message } : {}),
|
|
401
|
+
signal,
|
|
402
|
+
cwd,
|
|
403
|
+
})),
|
|
404
|
+
});
|
|
405
|
+
if (input.runInBackground) {
|
|
406
|
+
const resolvedModel = provider.model ?? 'praxis/provider';
|
|
407
|
+
this.background.launch({
|
|
408
|
+
agentId,
|
|
409
|
+
...(input.name ? { name: input.name } : {}),
|
|
410
|
+
agentType: input.subagentType,
|
|
411
|
+
description: input.description,
|
|
412
|
+
prompt: input.prompt,
|
|
413
|
+
toolUseId: call.id,
|
|
414
|
+
outputFile: sidechainPaths.transcriptFile,
|
|
415
|
+
resolvedModel,
|
|
416
|
+
run,
|
|
417
|
+
});
|
|
418
|
+
return {
|
|
419
|
+
content: this.asyncLaunchResult({
|
|
420
|
+
agentId,
|
|
421
|
+
description: input.description,
|
|
422
|
+
outputFile: sidechainPaths.transcriptFile,
|
|
423
|
+
...(initialIsolation ? { worktreePath: initialIsolation.cwd } : {}),
|
|
424
|
+
}),
|
|
425
|
+
isError: false,
|
|
426
|
+
nativeToolUseResult: {
|
|
427
|
+
...createClaudeAsyncAgentToolUseResult({
|
|
428
|
+
prompt: input.prompt,
|
|
429
|
+
agentId,
|
|
430
|
+
description: input.description,
|
|
431
|
+
resolvedModel,
|
|
432
|
+
outputFile: sidechainPaths.transcriptFile,
|
|
433
|
+
}),
|
|
434
|
+
...(initialIsolation ? { worktreePath: initialIsolation.cwd } : {}),
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
const controller = new AbortController();
|
|
439
|
+
const abort = () => controller.abort();
|
|
440
|
+
context.signal?.addEventListener('abort', abort, { once: true });
|
|
441
|
+
let result;
|
|
442
|
+
try {
|
|
443
|
+
result = await run(input.prompt, controller.signal, false);
|
|
444
|
+
}
|
|
445
|
+
finally {
|
|
446
|
+
context.signal?.removeEventListener('abort', abort);
|
|
447
|
+
}
|
|
448
|
+
const maxOutputBytes = this.options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
|
|
449
|
+
if (Buffer.byteLength(result.text) > maxOutputBytes) {
|
|
450
|
+
throw new Error(`Agent result exceeded ${maxOutputBytes} bytes`);
|
|
451
|
+
}
|
|
452
|
+
return {
|
|
453
|
+
content: [
|
|
454
|
+
result.text,
|
|
455
|
+
`agentId: ${agentId}`,
|
|
456
|
+
...(result.isolationPath
|
|
457
|
+
? [
|
|
458
|
+
`worktreePath: ${result.isolationPath}`,
|
|
459
|
+
`worktreeRetained: ${String(result.isolationRetained)}`,
|
|
460
|
+
...(result.isolationWarning
|
|
461
|
+
? [`worktreeWarning: ${result.isolationWarning}`]
|
|
462
|
+
: []),
|
|
463
|
+
]
|
|
464
|
+
: []),
|
|
465
|
+
].join('\n\n'),
|
|
466
|
+
isError: false,
|
|
467
|
+
usage: result.usage,
|
|
468
|
+
nativeToolUseResult: {
|
|
469
|
+
...createClaudeAgentToolUseResult({
|
|
470
|
+
prompt: input.prompt,
|
|
471
|
+
agentId,
|
|
472
|
+
agentType: input.subagentType,
|
|
473
|
+
text: result.text,
|
|
474
|
+
resolvedModel: provider.model ?? 'praxis/provider',
|
|
475
|
+
durationMs: result.durationMs,
|
|
476
|
+
usage: result.usage,
|
|
477
|
+
toolUseCount: result.toolUseCount,
|
|
478
|
+
}),
|
|
479
|
+
...(result.isolationPath
|
|
480
|
+
? {
|
|
481
|
+
worktreePath: result.isolationPath,
|
|
482
|
+
worktreeRetained: result.isolationRetained,
|
|
483
|
+
...(result.isolationWarning
|
|
484
|
+
? { worktreeWarning: result.isolationWarning }
|
|
485
|
+
: {}),
|
|
486
|
+
}
|
|
487
|
+
: {}),
|
|
488
|
+
},
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
sidechainStore(sessionId, agentId, paths) {
|
|
492
|
+
if (this.options.persistence !== 'memory') {
|
|
493
|
+
return new ClaudeSidechainStore(paths, join(this.options.configRoot, 'praxis', 'locks', `${sessionId}-${agentId}.lock`), this.schema);
|
|
494
|
+
}
|
|
495
|
+
const key = `${sessionId}/${agentId}`;
|
|
496
|
+
let store = this.ephemeralSidechains.get(key);
|
|
497
|
+
if (!store) {
|
|
498
|
+
store = new InMemorySidechainStore(paths);
|
|
499
|
+
this.ephemeralSidechains.set(key, store);
|
|
500
|
+
}
|
|
501
|
+
return store;
|
|
502
|
+
}
|
|
503
|
+
createAgentWorktree(praxisRoot, sessionId, agentId) {
|
|
504
|
+
return createManagedWorktree({
|
|
505
|
+
cwd: this.cwd(),
|
|
506
|
+
parentDirectory: join(praxisRoot, 'agent-worktrees'),
|
|
507
|
+
directoryName: `${sessionId}-${agentId}`,
|
|
508
|
+
label: 'Agent',
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
createBackgroundAgentRun(options) {
|
|
512
|
+
let availableIsolation = options.initialIsolation;
|
|
513
|
+
let retainedIsolation;
|
|
514
|
+
return async (message, signal, continuation) => {
|
|
515
|
+
const isolation = options.input.isolation
|
|
516
|
+
? (retainedIsolation ??
|
|
517
|
+
availableIsolation ??
|
|
518
|
+
(await options.createIsolation()))
|
|
519
|
+
: undefined;
|
|
520
|
+
availableIsolation = undefined;
|
|
521
|
+
const startedAt = Date.now();
|
|
522
|
+
let result;
|
|
523
|
+
let failure;
|
|
524
|
+
let cleanup;
|
|
525
|
+
try {
|
|
526
|
+
result = await options.execute(isolation?.cwd ?? this.cwd(), message, signal, continuation);
|
|
527
|
+
}
|
|
528
|
+
catch (error) {
|
|
529
|
+
failure = error;
|
|
530
|
+
}
|
|
531
|
+
finally {
|
|
532
|
+
cleanup = await isolation?.cleanup();
|
|
533
|
+
retainedIsolation = cleanup?.retained ? isolation : undefined;
|
|
534
|
+
}
|
|
535
|
+
if (failure !== undefined) {
|
|
536
|
+
if (isolation && cleanup) {
|
|
537
|
+
const message = failure instanceof Error ? failure.message : String(failure);
|
|
538
|
+
const result = {
|
|
539
|
+
text: message,
|
|
540
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
541
|
+
toolUseCount: 0,
|
|
542
|
+
durationMs: Date.now() - startedAt,
|
|
543
|
+
isolationPath: isolation.cwd,
|
|
544
|
+
isolationRetained: cleanup.retained,
|
|
545
|
+
...(cleanup.reason ? { isolationWarning: cleanup.reason } : {}),
|
|
546
|
+
};
|
|
547
|
+
throw new BackgroundAgentRunError(cleanup.reason ? `${message}\n${cleanup.reason}` : message, result, failure);
|
|
548
|
+
}
|
|
549
|
+
if (cleanup?.reason) {
|
|
550
|
+
throw new Error(`${failure instanceof Error ? failure.message : String(failure)}\n${cleanup.reason}`, { cause: failure });
|
|
551
|
+
}
|
|
552
|
+
throw failure;
|
|
553
|
+
}
|
|
554
|
+
if (!result)
|
|
555
|
+
throw new Error('Agent completed without a result');
|
|
556
|
+
return {
|
|
557
|
+
...result,
|
|
558
|
+
durationMs: Date.now() - startedAt,
|
|
559
|
+
...(isolation ? { isolationPath: isolation.cwd } : {}),
|
|
560
|
+
...(cleanup ? { isolationRetained: cleanup.retained } : {}),
|
|
561
|
+
...(cleanup?.reason ? { isolationWarning: cleanup.reason } : {}),
|
|
562
|
+
};
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
async runWorkflowAgent(options) {
|
|
566
|
+
if (this.options.persistence === 'memory') {
|
|
567
|
+
throw new Error('Workflow agents require session persistence');
|
|
568
|
+
}
|
|
569
|
+
if (options.agentType &&
|
|
570
|
+
options.agentType !== 'general-purpose' &&
|
|
571
|
+
!this.options.extensions?.agent(options.agentType)) {
|
|
572
|
+
throw new Error(`Unknown Claude agent ${options.agentType}`);
|
|
573
|
+
}
|
|
574
|
+
if (options.model && !this.options.providerForModel) {
|
|
575
|
+
throw new Error('Workflow agent model overrides are unavailable for this provider');
|
|
576
|
+
}
|
|
577
|
+
const provider = options.model
|
|
578
|
+
? (this.options.providerForModel?.(options.model) ??
|
|
579
|
+
this.options.provider)
|
|
580
|
+
: this.options.provider;
|
|
581
|
+
const input = {
|
|
582
|
+
description: options.label ?? 'Workflow agent',
|
|
583
|
+
prompt: options.prompt,
|
|
584
|
+
subagentType: options.agentType ?? 'workflow-subagent',
|
|
585
|
+
...(options.model ? { model: options.model } : {}),
|
|
586
|
+
runInBackground: false,
|
|
587
|
+
};
|
|
588
|
+
const agentFiles = workflowAgentFiles(options.transcriptDirectory, options.agentId);
|
|
589
|
+
const paths = {
|
|
590
|
+
sessionId: options.sessionId,
|
|
591
|
+
agentId: options.agentId,
|
|
592
|
+
directory: options.transcriptDirectory,
|
|
593
|
+
transcriptFile: agentFiles.transcriptFile,
|
|
594
|
+
metadataFile: agentFiles.metadataFile,
|
|
595
|
+
};
|
|
596
|
+
const sidechain = new ClaudeSidechainStore(paths, join(this.options.configRoot, 'praxis', 'locks', `${options.sessionId}-${options.runId}-${options.agentId}.lock`), this.schema);
|
|
597
|
+
const claudePaths = resolveClaudePaths({
|
|
598
|
+
configDir: this.options.configRoot,
|
|
599
|
+
cwd: this.cwd(),
|
|
600
|
+
sessionId: options.sessionId,
|
|
601
|
+
});
|
|
602
|
+
const isolation = options.isolation
|
|
603
|
+
? await createWorkflowWorktree({
|
|
604
|
+
cwd: this.cwd(),
|
|
605
|
+
praxisRoot: claudePaths.praxisRoot,
|
|
606
|
+
runId: options.runId,
|
|
607
|
+
agentId: options.agentId,
|
|
608
|
+
})
|
|
609
|
+
: null;
|
|
610
|
+
const agentCwd = isolation?.cwd ?? this.cwd();
|
|
611
|
+
const root = createClaudeSidechainRoot({
|
|
612
|
+
sessionId: options.sessionId,
|
|
613
|
+
promptId: options.promptId,
|
|
614
|
+
prompt: options.prompt,
|
|
615
|
+
agentId: options.agentId,
|
|
616
|
+
cwd: agentCwd,
|
|
617
|
+
claudeVersion: this.options.claudeVersion,
|
|
618
|
+
gitBranch: null,
|
|
619
|
+
uuid: randomUUID(),
|
|
620
|
+
timestamp: new Date().toISOString(),
|
|
621
|
+
});
|
|
622
|
+
const startedAt = Date.now();
|
|
623
|
+
const structured = { calls: 0, value: undefined };
|
|
624
|
+
let run;
|
|
625
|
+
let cleanup;
|
|
626
|
+
try {
|
|
627
|
+
await sidechain.createWorkflow(root, {
|
|
628
|
+
agentType: options.agentType ?? 'workflow-subagent',
|
|
629
|
+
spawnDepth: 1,
|
|
630
|
+
});
|
|
631
|
+
run = await sidechain.withLease((lease) => this.runSidechain({
|
|
632
|
+
lease,
|
|
633
|
+
root,
|
|
634
|
+
input,
|
|
635
|
+
provider,
|
|
636
|
+
agentId: options.agentId,
|
|
637
|
+
spawnDepth: 1,
|
|
638
|
+
promptId: options.promptId,
|
|
639
|
+
transcriptPath: paths.transcriptFile,
|
|
640
|
+
toolResultDirectory: join(claudePaths.projectRoot, options.sessionId, 'tool-results'),
|
|
641
|
+
...(options.schema
|
|
642
|
+
? { outputSchema: options.schema, structuredOutput: structured }
|
|
643
|
+
: {}),
|
|
644
|
+
...(options.effort ? { effort: options.effort } : {}),
|
|
645
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
646
|
+
cwd: agentCwd,
|
|
647
|
+
}));
|
|
648
|
+
}
|
|
649
|
+
finally {
|
|
650
|
+
cleanup = await isolation?.cleanup();
|
|
651
|
+
}
|
|
652
|
+
if (options.schema && structured.calls !== 1) {
|
|
653
|
+
throw new Error(`StructuredOutput must be called exactly once (received ${structured.calls})`);
|
|
654
|
+
}
|
|
655
|
+
return {
|
|
656
|
+
result: options.schema ? structured.value : run.text,
|
|
657
|
+
usage: run.usage,
|
|
658
|
+
toolUseCount: run.toolUseCount,
|
|
659
|
+
durationMs: Date.now() - startedAt,
|
|
660
|
+
resolvedModel: provider.model ?? 'praxis/provider',
|
|
661
|
+
...(isolation ? { isolationPath: isolation.cwd } : {}),
|
|
662
|
+
...(cleanup ? { isolationRetained: cleanup.retained } : {}),
|
|
663
|
+
...(cleanup?.reason ? { isolationWarning: cleanup.reason } : {}),
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
prepareManagement(call) {
|
|
667
|
+
if (!this.isEnabled(call.name)) {
|
|
668
|
+
throw new Error(`Tool ${call.name} is unavailable`);
|
|
669
|
+
}
|
|
670
|
+
const allowed = new Set(this.managementDefinitions().map(({ name }) => name));
|
|
671
|
+
if (!allowed.has(call.name))
|
|
672
|
+
throw new Error(`Unknown task tool ${call.name}`);
|
|
673
|
+
if (call.name === 'TaskOutput') {
|
|
674
|
+
const taskId = call.input.task_id;
|
|
675
|
+
const block = call.input.block ?? true;
|
|
676
|
+
const timeout = call.input.timeout ?? 30_000;
|
|
677
|
+
if (typeof taskId !== 'string' || taskId.length === 0) {
|
|
678
|
+
throw new Error('task_id must be a non-empty string');
|
|
679
|
+
}
|
|
680
|
+
if (typeof block !== 'boolean')
|
|
681
|
+
throw new Error('block must be a boolean');
|
|
682
|
+
if (typeof timeout !== 'number')
|
|
683
|
+
throw new Error('timeout must be a number');
|
|
684
|
+
return { ...call, input: { task_id: taskId, block, timeout } };
|
|
685
|
+
}
|
|
686
|
+
if (call.name === 'TaskStop') {
|
|
687
|
+
const taskId = call.input.task_id ?? call.input.shell_id;
|
|
688
|
+
if (typeof taskId !== 'string' || taskId.length === 0) {
|
|
689
|
+
throw new Error('task_id must be a non-empty string');
|
|
690
|
+
}
|
|
691
|
+
return { ...call, input: { task_id: taskId } };
|
|
692
|
+
}
|
|
693
|
+
const to = call.input.to;
|
|
694
|
+
const message = call.input.message;
|
|
695
|
+
const summary = call.input.summary;
|
|
696
|
+
if (typeof to !== 'string' || to.length === 0) {
|
|
697
|
+
throw new Error('to must be a non-empty string');
|
|
698
|
+
}
|
|
699
|
+
if (typeof message !== 'string' || message.trim().length === 0) {
|
|
700
|
+
throw new Error('message must be a non-empty string');
|
|
701
|
+
}
|
|
702
|
+
if (summary !== undefined && typeof summary !== 'string') {
|
|
703
|
+
throw new Error('summary must be a string');
|
|
704
|
+
}
|
|
705
|
+
return {
|
|
706
|
+
...call,
|
|
707
|
+
input: { to, message, ...(summary === undefined ? {} : { summary }) },
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
async executeManagement(call, sessionId) {
|
|
711
|
+
if (call.name === 'TaskOutput') {
|
|
712
|
+
const taskId = String(call.input.task_id);
|
|
713
|
+
await this.hydrateCompletedTask(sessionId, taskId);
|
|
714
|
+
return {
|
|
715
|
+
content: await this.background.output(taskId, {
|
|
716
|
+
block: Boolean(call.input.block),
|
|
717
|
+
timeout: Number(call.input.timeout),
|
|
718
|
+
}),
|
|
719
|
+
isError: false,
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
if (call.name === 'TaskStop') {
|
|
723
|
+
const taskId = String(call.input.task_id);
|
|
724
|
+
await this.hydrateCompletedTask(sessionId, taskId);
|
|
725
|
+
return { content: this.background.stop(taskId), isError: false };
|
|
726
|
+
}
|
|
727
|
+
const agentId = String(call.input.to);
|
|
728
|
+
await this.hydrateCompletedTask(sessionId, agentId);
|
|
729
|
+
return {
|
|
730
|
+
content: this.background.send(agentId, String(call.input.message), typeof call.input.summary === 'string' ? call.input.summary : undefined, call.id),
|
|
731
|
+
isError: false,
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
notifications(waitForRunning) {
|
|
735
|
+
return this.background.notifications({ waitForRunning });
|
|
736
|
+
}
|
|
737
|
+
async hydrateCompletedTask(sessionId, identifier) {
|
|
738
|
+
if (this.background.has(identifier))
|
|
739
|
+
return;
|
|
740
|
+
const paths = resolveClaudePaths({
|
|
741
|
+
configDir: this.options.configRoot,
|
|
742
|
+
cwd: this.cwd(),
|
|
743
|
+
sessionId,
|
|
744
|
+
});
|
|
745
|
+
const agentId = await this.resolvePersistedAgentId(paths.projectRoot, sessionId, identifier);
|
|
746
|
+
if (!agentId)
|
|
747
|
+
return;
|
|
748
|
+
const sidechainPaths = resolveClaudeSidechainPaths(paths.projectRoot, sessionId, agentId);
|
|
749
|
+
const sidechain = new ClaudeSidechainStore(sidechainPaths, join(paths.praxisRoot, 'locks', `${sessionId}-${agentId}.lock`), this.schema);
|
|
750
|
+
let metadata;
|
|
751
|
+
let snapshot;
|
|
752
|
+
try {
|
|
753
|
+
;
|
|
754
|
+
[metadata, snapshot] = await Promise.all([
|
|
755
|
+
sidechain.metadata(),
|
|
756
|
+
sidechain.loadReadOnly(),
|
|
757
|
+
]);
|
|
758
|
+
}
|
|
759
|
+
catch (error) {
|
|
760
|
+
if (error.code === 'ENOENT')
|
|
761
|
+
return;
|
|
762
|
+
throw error;
|
|
763
|
+
}
|
|
764
|
+
const root = snapshot.entries[0];
|
|
765
|
+
if (!root || root.type !== 'user') {
|
|
766
|
+
throw new Error(`Background agent ${agentId} has no sidechain root`);
|
|
767
|
+
}
|
|
768
|
+
const prompt = typeof root.message === 'object' &&
|
|
769
|
+
root.message !== null &&
|
|
770
|
+
typeof root.message.content === 'string'
|
|
771
|
+
? String(root.message.content)
|
|
772
|
+
: '';
|
|
773
|
+
const projected = projectClaudeModelMessages(snapshot.entries);
|
|
774
|
+
const lastAssistant = projected.at(-1);
|
|
775
|
+
if (!lastAssistant ||
|
|
776
|
+
lastAssistant.role !== 'assistant' ||
|
|
777
|
+
(lastAssistant.toolCalls?.length ?? 0) > 0) {
|
|
778
|
+
throw new Error(`Background agent ${agentId} is not completed`);
|
|
779
|
+
}
|
|
780
|
+
const input = {
|
|
781
|
+
description: metadata.description,
|
|
782
|
+
prompt,
|
|
783
|
+
subagentType: metadata.agentType,
|
|
784
|
+
...(metadata.name ? { name: metadata.name } : {}),
|
|
785
|
+
...(metadata.permissionMode
|
|
786
|
+
? { permissionMode: metadata.permissionMode }
|
|
787
|
+
: {}),
|
|
788
|
+
...(metadata.isolation ? { isolation: metadata.isolation } : {}),
|
|
789
|
+
runInBackground: true,
|
|
790
|
+
};
|
|
791
|
+
const provider = this.options.provider;
|
|
792
|
+
const run = this.createBackgroundAgentRun({
|
|
793
|
+
input,
|
|
794
|
+
createIsolation: () => this.createAgentWorktree(paths.praxisRoot, sessionId, agentId),
|
|
795
|
+
execute: (cwd, message, signal, continuation) => sidechain.withLease(async (lease) => this.runSidechain({
|
|
796
|
+
lease,
|
|
797
|
+
root,
|
|
798
|
+
input,
|
|
799
|
+
provider,
|
|
800
|
+
agentId,
|
|
801
|
+
spawnDepth: metadata.spawnDepth,
|
|
802
|
+
promptId: String(root.promptId ?? randomUUID()),
|
|
803
|
+
toolUseId: metadata.toolUseId,
|
|
804
|
+
transcriptPath: sidechainPaths.transcriptFile,
|
|
805
|
+
toolResultDirectory: join(paths.projectRoot, sessionId, 'tool-results'),
|
|
806
|
+
...(continuation ? { continuationMessage: message } : {}),
|
|
807
|
+
signal,
|
|
808
|
+
cwd,
|
|
809
|
+
})),
|
|
810
|
+
});
|
|
811
|
+
this.background.registerCompleted({
|
|
812
|
+
agentId,
|
|
813
|
+
...(metadata.name ? { name: metadata.name } : {}),
|
|
814
|
+
agentType: metadata.agentType,
|
|
815
|
+
description: metadata.description,
|
|
816
|
+
prompt,
|
|
817
|
+
toolUseId: metadata.toolUseId,
|
|
818
|
+
outputFile: sidechainPaths.transcriptFile,
|
|
819
|
+
resolvedModel: provider.model ?? 'praxis/provider',
|
|
820
|
+
run,
|
|
821
|
+
}, {
|
|
822
|
+
text: lastAssistant.content,
|
|
823
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
824
|
+
toolUseCount: 0,
|
|
825
|
+
durationMs: 0,
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
async resolvePersistedAgentId(projectRoot, sessionId, identifier) {
|
|
829
|
+
if (/^a[0-9a-f]{16}$/u.test(identifier))
|
|
830
|
+
return identifier;
|
|
831
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u.test(identifier))
|
|
832
|
+
return null;
|
|
833
|
+
const directory = join(projectRoot, sessionId, 'subagents');
|
|
834
|
+
let names;
|
|
835
|
+
try {
|
|
836
|
+
names = await readdir(directory);
|
|
837
|
+
}
|
|
838
|
+
catch (error) {
|
|
839
|
+
if (error.code === 'ENOENT')
|
|
840
|
+
return null;
|
|
841
|
+
throw error;
|
|
842
|
+
}
|
|
843
|
+
const matches = await Promise.all(names
|
|
844
|
+
.map((name) => /^agent-(a[0-9a-f]{16})\.meta\.json$/u.exec(name)?.[1])
|
|
845
|
+
.filter((agentId) => agentId !== undefined)
|
|
846
|
+
.map(async (agentId) => {
|
|
847
|
+
const sidechainPaths = resolveClaudeSidechainPaths(projectRoot, sessionId, agentId);
|
|
848
|
+
const sidechain = new ClaudeSidechainStore(sidechainPaths, join(this.options.configRoot, 'praxis', 'locks', `${sessionId}-${agentId}.lock`), this.schema);
|
|
849
|
+
const metadata = await sidechain.metadata();
|
|
850
|
+
if (metadata.name !== identifier)
|
|
851
|
+
return null;
|
|
852
|
+
const file = await stat(sidechainPaths.metadataFile);
|
|
853
|
+
return { agentId, modifiedAt: file.mtimeMs };
|
|
854
|
+
}));
|
|
855
|
+
return (matches
|
|
856
|
+
.filter((match) => match !== null)
|
|
857
|
+
.sort((left, right) => right.modifiedAt - left.modifiedAt ||
|
|
858
|
+
right.agentId.localeCompare(left.agentId))[0]?.agentId ?? null);
|
|
859
|
+
}
|
|
860
|
+
asyncLaunchResult(options) {
|
|
861
|
+
return [
|
|
862
|
+
'Async agent launched successfully. (This tool result is internal metadata - never quote or paste any part of it into a user-facing reply.)',
|
|
863
|
+
`agentId: ${options.agentId} (internal ID - do not mention to user. Use SendMessage with to: '${options.agentId}' to continue this agent.)`,
|
|
864
|
+
'The agent is working in the background. You will be notified automatically when it completes.',
|
|
865
|
+
"Do not duplicate this agent's work - avoid working with the same files or topics it is using.",
|
|
866
|
+
`output_file: ${options.outputFile}`,
|
|
867
|
+
...(options.worktreePath
|
|
868
|
+
? [`worktree_path: ${options.worktreePath}`]
|
|
869
|
+
: []),
|
|
870
|
+
'Do NOT Read or tail this file via the shell tool - it is the full subagent JSONL transcript.',
|
|
871
|
+
].join('\n');
|
|
872
|
+
}
|
|
873
|
+
async runSidechain(options) {
|
|
874
|
+
const cwd = options.cwd ?? this.cwd();
|
|
875
|
+
const permissions = options.input.permissionMode
|
|
876
|
+
? this.options.permissionResolverForMode?.(options.input.permissionMode)
|
|
877
|
+
: this.options.permissions;
|
|
878
|
+
if (!permissions) {
|
|
879
|
+
throw new Error('Agent permission mode overrides are unavailable');
|
|
880
|
+
}
|
|
881
|
+
let snapshot = await options.lease.load();
|
|
882
|
+
if (options.continuationMessage !== undefined) {
|
|
883
|
+
const [entry] = translateProviderEvents([
|
|
884
|
+
{
|
|
885
|
+
type: 'user-text-block',
|
|
886
|
+
text: `The coordinator sent a message while you were working:\n${options.continuationMessage}\n\nAddress this before completing your current task.`,
|
|
887
|
+
},
|
|
888
|
+
], {
|
|
889
|
+
sessionId: String(options.root.sessionId),
|
|
890
|
+
parentUuid: snapshot.tail.lastUuid,
|
|
891
|
+
cwd,
|
|
892
|
+
claudeVersion: this.options.claudeVersion,
|
|
893
|
+
gitBranch: null,
|
|
894
|
+
history: snapshot.entries,
|
|
895
|
+
});
|
|
896
|
+
if (!entry)
|
|
897
|
+
throw new Error('Could not translate subagent message');
|
|
898
|
+
const sidechainEntry = toClaudeSidechainEntry(entry, options.agentId, options.input.subagentType);
|
|
899
|
+
const appendResult = await options.lease.append(snapshot.tail, sidechainEntry);
|
|
900
|
+
if (appendResult.status === 'conflict') {
|
|
901
|
+
throw new Error(`Claude sidechain append conflict: ${appendResult.reason}`);
|
|
902
|
+
}
|
|
903
|
+
snapshot = {
|
|
904
|
+
entries: [...snapshot.entries, sidechainEntry],
|
|
905
|
+
tail: appendResult.tail,
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
let toolUseCount = 0;
|
|
909
|
+
let taskTokenTotal = 0;
|
|
910
|
+
let lastToolName;
|
|
911
|
+
const taskStartedAt = Date.now();
|
|
912
|
+
const append = async (entry) => {
|
|
913
|
+
const result = await options.lease.append(snapshot.tail, entry);
|
|
914
|
+
if (result.status === 'conflict') {
|
|
915
|
+
throw new Error(`Claude sidechain append conflict: ${result.reason}`);
|
|
916
|
+
}
|
|
917
|
+
snapshot = { entries: [...snapshot.entries, entry], tail: result.tail };
|
|
918
|
+
};
|
|
919
|
+
const translationContext = () => ({
|
|
920
|
+
sessionId: String(options.root.sessionId),
|
|
921
|
+
parentUuid: snapshot.tail.lastUuid,
|
|
922
|
+
cwd,
|
|
923
|
+
claudeVersion: this.options.claudeVersion,
|
|
924
|
+
gitBranch: null,
|
|
925
|
+
history: snapshot.entries,
|
|
926
|
+
});
|
|
927
|
+
const recordHookOutcome = async (outcome) => {
|
|
928
|
+
for (const entry of createClaudeHookAttachmentEntries(outcome, translationContext())) {
|
|
929
|
+
await append(toClaudeSidechainEntry(entry, options.agentId, options.input.subagentType));
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
const hookSession = {
|
|
933
|
+
session_id: String(options.root.sessionId),
|
|
934
|
+
transcript_path: options.transcriptPath,
|
|
935
|
+
cwd,
|
|
936
|
+
permission_mode: options.input.permissionMode ?? 'default',
|
|
937
|
+
};
|
|
938
|
+
const nestedTools = this.registry(String(options.root.sessionId), options.spawnDepth, () => options.promptId);
|
|
939
|
+
const agentTools = options.outputSchema
|
|
940
|
+
? new StructuredOutputRegistry(structuredOnlyTools, options.outputSchema, options.structuredOutput)
|
|
941
|
+
: nestedTools;
|
|
942
|
+
const runtimeTools = this.options.hooks
|
|
943
|
+
? new ClaudeHookToolCoordinator({
|
|
944
|
+
tools: agentTools,
|
|
945
|
+
permissions,
|
|
946
|
+
hooks: this.options.hooks,
|
|
947
|
+
session: hookSession,
|
|
948
|
+
recordOutcome: recordHookOutcome,
|
|
949
|
+
})
|
|
950
|
+
: agentTools;
|
|
951
|
+
const runtimePermissions = this.options.hooks
|
|
952
|
+
? runtimeTools
|
|
953
|
+
: permissions;
|
|
954
|
+
const emit = (event) => {
|
|
955
|
+
if (event.type === 'usage') {
|
|
956
|
+
taskTokenTotal += event.usage.inputTokens + event.usage.outputTokens;
|
|
957
|
+
this.options.eventSink?.({
|
|
958
|
+
type: 'task-progress',
|
|
959
|
+
taskId: options.agentId,
|
|
960
|
+
...(options.toolUseId ? { toolUseId: options.toolUseId } : {}),
|
|
961
|
+
description: options.input.description,
|
|
962
|
+
usage: {
|
|
963
|
+
totalTokens: taskTokenTotal,
|
|
964
|
+
toolUses: toolUseCount,
|
|
965
|
+
durationMs: Date.now() - taskStartedAt,
|
|
966
|
+
},
|
|
967
|
+
...(lastToolName ? { lastToolName } : {}),
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
if (event.type === 'tool-call') {
|
|
971
|
+
toolUseCount += 1;
|
|
972
|
+
lastToolName = event.call.name;
|
|
973
|
+
this.options.eventSink?.({
|
|
974
|
+
type: 'task-progress',
|
|
975
|
+
taskId: options.agentId,
|
|
976
|
+
...(options.toolUseId ? { toolUseId: options.toolUseId } : {}),
|
|
977
|
+
description: options.input.description,
|
|
978
|
+
usage: {
|
|
979
|
+
totalTokens: taskTokenTotal,
|
|
980
|
+
toolUses: toolUseCount,
|
|
981
|
+
durationMs: Date.now() - taskStartedAt,
|
|
982
|
+
},
|
|
983
|
+
lastToolName,
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
if (event.type === 'warning')
|
|
987
|
+
this.options.eventSink?.(event);
|
|
988
|
+
if (event.type === 'failed') {
|
|
989
|
+
this.options.eventSink?.({
|
|
990
|
+
type: 'warning',
|
|
991
|
+
message: `Subagent failed: ${event.message}`,
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
const runtime = new AgentRuntime(options.provider, emit, {
|
|
996
|
+
tools: runtimeTools,
|
|
997
|
+
permissions: runtimePermissions,
|
|
998
|
+
maxModelTurns: 16,
|
|
999
|
+
maxModelOutputBytes: this.options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES,
|
|
1000
|
+
maxToolCallsPerTurn: 32,
|
|
1001
|
+
maxToolInputBytes: 1024 * 1024,
|
|
1002
|
+
});
|
|
1003
|
+
const observer = {
|
|
1004
|
+
assistantCompleted: async (message) => {
|
|
1005
|
+
const [entry] = translateProviderEvents([
|
|
1006
|
+
{
|
|
1007
|
+
type: 'assistant-message',
|
|
1008
|
+
text: message.content,
|
|
1009
|
+
...(message.thinkingBlocks
|
|
1010
|
+
? { thinkingBlocks: message.thinkingBlocks }
|
|
1011
|
+
: {}),
|
|
1012
|
+
toolCalls: message.toolCalls ?? [],
|
|
1013
|
+
providerMessageId: `msg_${randomUUID().replaceAll('-', '')}`,
|
|
1014
|
+
model: options.provider.model ?? 'praxis/provider',
|
|
1015
|
+
},
|
|
1016
|
+
], translationContext());
|
|
1017
|
+
if (!entry)
|
|
1018
|
+
throw new Error('Could not translate subagent response');
|
|
1019
|
+
await append(toClaudeSidechainEntry(entry, options.agentId, options.input.subagentType));
|
|
1020
|
+
},
|
|
1021
|
+
toolCompleted: async (call, result) => {
|
|
1022
|
+
const nestedToolUseCount = result.nativeToolUseResult?.totalToolUseCount;
|
|
1023
|
+
if (call.name === 'Agent' &&
|
|
1024
|
+
typeof nestedToolUseCount === 'number' &&
|
|
1025
|
+
Number.isSafeInteger(nestedToolUseCount) &&
|
|
1026
|
+
nestedToolUseCount > 0) {
|
|
1027
|
+
toolUseCount += nestedToolUseCount;
|
|
1028
|
+
}
|
|
1029
|
+
const [entry] = translateProviderEvents([
|
|
1030
|
+
{
|
|
1031
|
+
type: 'tool-result',
|
|
1032
|
+
toolCallId: call.id,
|
|
1033
|
+
content: result.content,
|
|
1034
|
+
...(result.contentBlocks
|
|
1035
|
+
? { contentBlocks: result.contentBlocks }
|
|
1036
|
+
: {}),
|
|
1037
|
+
...(result.images ? { images: result.images } : {}),
|
|
1038
|
+
...(result.documents ? { documents: result.documents } : {}),
|
|
1039
|
+
isError: result.isError,
|
|
1040
|
+
...(result.nativeToolUseResult
|
|
1041
|
+
? { nativeToolUseResult: result.nativeToolUseResult }
|
|
1042
|
+
: {}),
|
|
1043
|
+
...(result.nativeMcpMeta
|
|
1044
|
+
? { nativeMcpMeta: result.nativeMcpMeta }
|
|
1045
|
+
: {}),
|
|
1046
|
+
},
|
|
1047
|
+
], translationContext());
|
|
1048
|
+
if (!entry)
|
|
1049
|
+
throw new Error('Could not translate subagent tool result');
|
|
1050
|
+
await append(toClaudeSidechainEntry(entry, options.agentId, options.input.subagentType));
|
|
1051
|
+
},
|
|
1052
|
+
followUpUserMessagesCompleted: async (messages) => {
|
|
1053
|
+
for (const text of messages) {
|
|
1054
|
+
const [entry] = translateProviderEvents([{ type: 'user-text-block', text }], translationContext());
|
|
1055
|
+
if (!entry)
|
|
1056
|
+
throw new Error('Could not translate subagent follow-up');
|
|
1057
|
+
await append(toClaudeSidechainEntry(entry, options.agentId, options.input.subagentType));
|
|
1058
|
+
}
|
|
1059
|
+
},
|
|
1060
|
+
};
|
|
1061
|
+
this.options.eventSink?.({
|
|
1062
|
+
type: 'task-started',
|
|
1063
|
+
taskId: options.agentId,
|
|
1064
|
+
...(options.toolUseId ? { toolUseId: options.toolUseId } : {}),
|
|
1065
|
+
description: options.input.description,
|
|
1066
|
+
taskType: options.input.subagentType,
|
|
1067
|
+
prompt: options.input.prompt,
|
|
1068
|
+
});
|
|
1069
|
+
try {
|
|
1070
|
+
if (this.options.hooks) {
|
|
1071
|
+
const start = await this.options.hooks.run({
|
|
1072
|
+
...hookSession,
|
|
1073
|
+
hook_event_name: 'SessionStart',
|
|
1074
|
+
source: 'startup',
|
|
1075
|
+
}, 'startup', options.signal);
|
|
1076
|
+
await recordHookOutcome(start);
|
|
1077
|
+
if (start.blockedReason) {
|
|
1078
|
+
throw new Error(`SessionStart hook error: ${start.blockedReason}`);
|
|
1079
|
+
}
|
|
1080
|
+
const prompt = await this.options.hooks.run({
|
|
1081
|
+
...hookSession,
|
|
1082
|
+
hook_event_name: 'UserPromptSubmit',
|
|
1083
|
+
prompt_id: options.promptId,
|
|
1084
|
+
prompt: options.input.prompt,
|
|
1085
|
+
}, undefined, options.signal);
|
|
1086
|
+
await recordHookOutcome(prompt);
|
|
1087
|
+
if (prompt.blockedReason) {
|
|
1088
|
+
throw new Error(`UserPromptSubmit hook error: ${prompt.blockedReason}`);
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
const customAgent = this.options.extensions?.agent(options.input.subagentType);
|
|
1092
|
+
const baseSystem = options.input.subagentType === 'general-purpose'
|
|
1093
|
+
? 'You are a general-purpose subagent. Complete the isolated task and return a concise result.'
|
|
1094
|
+
: options.input.subagentType === 'workflow-subagent'
|
|
1095
|
+
? 'You are a workflow subagent. Complete the isolated task. Your final text is the raw return value consumed by the workflow, not a user-facing message.'
|
|
1096
|
+
: `# Agent definition: ${options.input.subagentType}\n\n${customAgent?.body ?? ''}`;
|
|
1097
|
+
const system = options.outputSchema
|
|
1098
|
+
? `${baseSystem}\n\nYou MUST call StructuredOutput exactly once at the end with a value matching its schema.`
|
|
1099
|
+
: baseSystem;
|
|
1100
|
+
let stopHookActive = false;
|
|
1101
|
+
const contextBudget = options.provider.capabilities.contextWindowTokens
|
|
1102
|
+
? new ContextBudget({
|
|
1103
|
+
contextWindowTokens: options.provider.capabilities.contextWindowTokens,
|
|
1104
|
+
...(this.options.contextReserveTokens === undefined
|
|
1105
|
+
? {}
|
|
1106
|
+
: { reserveTokens: this.options.contextReserveTokens }),
|
|
1107
|
+
})
|
|
1108
|
+
: null;
|
|
1109
|
+
const definitions = options.provider.capabilities.tools
|
|
1110
|
+
? runtimeTools.definitions()
|
|
1111
|
+
: [];
|
|
1112
|
+
const assembleMessages = async () => {
|
|
1113
|
+
const assembledContext = await this.options.contextAssembler?.assemble({
|
|
1114
|
+
cwd,
|
|
1115
|
+
});
|
|
1116
|
+
const messages = [
|
|
1117
|
+
...(assembledContext?.systemMessages ?? []),
|
|
1118
|
+
{ role: 'system', content: system },
|
|
1119
|
+
...injectFirstUserMessageContext(projectClaudeModelMessages(snapshot.entries), assembledContext?.firstUserMessageContext),
|
|
1120
|
+
];
|
|
1121
|
+
if (contextBudget) {
|
|
1122
|
+
contextBudget.assertFits(contextBudget.evaluate(messages, definitions));
|
|
1123
|
+
}
|
|
1124
|
+
return messages;
|
|
1125
|
+
};
|
|
1126
|
+
const result = await runtime.run({
|
|
1127
|
+
messages: await assembleMessages(),
|
|
1128
|
+
reloadMessages: assembleMessages,
|
|
1129
|
+
cwd,
|
|
1130
|
+
...(options.effort ? { effort: options.effort } : {}),
|
|
1131
|
+
toolResultDirectory: options.toolResultDirectory,
|
|
1132
|
+
observer,
|
|
1133
|
+
...(this.options.approveTool
|
|
1134
|
+
? { approveTool: this.options.approveTool }
|
|
1135
|
+
: {}),
|
|
1136
|
+
...(this.options.hooks || this.options.backgroundTaskNotifications
|
|
1137
|
+
? {
|
|
1138
|
+
onStop: async (text) => {
|
|
1139
|
+
const messages = [];
|
|
1140
|
+
const outcome = await this.options.hooks?.run({
|
|
1141
|
+
...hookSession,
|
|
1142
|
+
hook_event_name: 'Stop',
|
|
1143
|
+
stop_hook_active: stopHookActive,
|
|
1144
|
+
last_assistant_message: text,
|
|
1145
|
+
}, undefined, options.signal);
|
|
1146
|
+
if (outcome) {
|
|
1147
|
+
await recordHookOutcome(outcome);
|
|
1148
|
+
if (outcome.blockedReason) {
|
|
1149
|
+
stopHookActive = true;
|
|
1150
|
+
messages.push(`Stop hook error: ${outcome.blockedReason}`);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
const background = await this.background.notifications({
|
|
1154
|
+
waitForRunning: false,
|
|
1155
|
+
excludeAgentId: options.agentId,
|
|
1156
|
+
});
|
|
1157
|
+
messages.push(...background.messages);
|
|
1158
|
+
messages.push(...((await this.options.backgroundTaskNotifications?.(true)) ?? []));
|
|
1159
|
+
return { messages, usage: background.usage };
|
|
1160
|
+
},
|
|
1161
|
+
}
|
|
1162
|
+
: {}),
|
|
1163
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
1164
|
+
});
|
|
1165
|
+
this.options.eventSink?.({
|
|
1166
|
+
type: 'task-progress',
|
|
1167
|
+
taskId: options.agentId,
|
|
1168
|
+
...(options.toolUseId ? { toolUseId: options.toolUseId } : {}),
|
|
1169
|
+
description: options.input.description,
|
|
1170
|
+
usage: {
|
|
1171
|
+
totalTokens: result.usage.inputTokens + result.usage.outputTokens,
|
|
1172
|
+
toolUses: toolUseCount,
|
|
1173
|
+
durationMs: Date.now() - taskStartedAt,
|
|
1174
|
+
},
|
|
1175
|
+
...(lastToolName ? { lastToolName } : {}),
|
|
1176
|
+
summary: result.text,
|
|
1177
|
+
});
|
|
1178
|
+
this.options.eventSink?.({
|
|
1179
|
+
type: 'task-notification',
|
|
1180
|
+
taskId: options.agentId,
|
|
1181
|
+
...(options.toolUseId ? { toolUseId: options.toolUseId } : {}),
|
|
1182
|
+
status: 'completed',
|
|
1183
|
+
outputFile: options.transcriptPath,
|
|
1184
|
+
summary: result.text,
|
|
1185
|
+
usage: {
|
|
1186
|
+
totalTokens: result.usage.inputTokens + result.usage.outputTokens,
|
|
1187
|
+
toolUses: toolUseCount,
|
|
1188
|
+
durationMs: Date.now() - taskStartedAt,
|
|
1189
|
+
},
|
|
1190
|
+
});
|
|
1191
|
+
return {
|
|
1192
|
+
...result,
|
|
1193
|
+
toolUseCount,
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
catch (error) {
|
|
1197
|
+
this.options.eventSink?.({
|
|
1198
|
+
type: 'task-notification',
|
|
1199
|
+
taskId: options.agentId,
|
|
1200
|
+
...(options.toolUseId ? { toolUseId: options.toolUseId } : {}),
|
|
1201
|
+
status: options.signal?.aborted ? 'stopped' : 'failed',
|
|
1202
|
+
outputFile: options.transcriptPath,
|
|
1203
|
+
summary: error instanceof Error ? error.message : String(error),
|
|
1204
|
+
usage: {
|
|
1205
|
+
totalTokens: 0,
|
|
1206
|
+
toolUses: toolUseCount,
|
|
1207
|
+
durationMs: Date.now() - taskStartedAt,
|
|
1208
|
+
},
|
|
1209
|
+
});
|
|
1210
|
+
throw error;
|
|
1211
|
+
}
|
|
1212
|
+
finally {
|
|
1213
|
+
try {
|
|
1214
|
+
const outcome = await this.options.hooks?.run({
|
|
1215
|
+
...hookSession,
|
|
1216
|
+
hook_event_name: 'SessionEnd',
|
|
1217
|
+
reason: 'other',
|
|
1218
|
+
}, 'other');
|
|
1219
|
+
for (const execution of outcome?.executions.filter((value) => value.exitCode !== 0) ?? []) {
|
|
1220
|
+
this.options.eventSink?.({
|
|
1221
|
+
type: 'warning',
|
|
1222
|
+
message: `Subagent SessionEnd hook failed: ${execution.stderr.trim() || execution.stdout.trim() || `exit code ${execution.exitCode}`}`,
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
catch (error) {
|
|
1227
|
+
this.options.eventSink?.({
|
|
1228
|
+
type: 'warning',
|
|
1229
|
+
message: `Subagent SessionEnd hook failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
class ClaudeSubagentToolRegistry {
|
|
1236
|
+
base;
|
|
1237
|
+
executor;
|
|
1238
|
+
sessionId;
|
|
1239
|
+
depth;
|
|
1240
|
+
promptIdForCall;
|
|
1241
|
+
constructor(base, executor, sessionId, depth, promptIdForCall) {
|
|
1242
|
+
this.base = base;
|
|
1243
|
+
this.executor = executor;
|
|
1244
|
+
this.sessionId = sessionId;
|
|
1245
|
+
this.depth = depth;
|
|
1246
|
+
this.promptIdForCall = promptIdForCall;
|
|
1247
|
+
}
|
|
1248
|
+
definitions() {
|
|
1249
|
+
const base = this.base.definitions();
|
|
1250
|
+
const management = this.executor
|
|
1251
|
+
.managementDefinitions()
|
|
1252
|
+
.filter(({ name }) => this.executor.isEnabled(name));
|
|
1253
|
+
const managementNames = new Set(management.map(({ name }) => name));
|
|
1254
|
+
const firstManagement = base.findIndex(({ name }) => managementNames.has(name));
|
|
1255
|
+
const insertionIndex = firstManagement < 0
|
|
1256
|
+
? base.length
|
|
1257
|
+
: base
|
|
1258
|
+
.slice(0, firstManagement)
|
|
1259
|
+
.filter(({ name }) => !managementNames.has(name)).length;
|
|
1260
|
+
const ordinary = base.filter(({ name }) => !managementNames.has(name));
|
|
1261
|
+
const baseByName = new Map(base.map((definition) => [definition.name, definition]));
|
|
1262
|
+
return [
|
|
1263
|
+
...ordinary.slice(0, insertionIndex),
|
|
1264
|
+
...(this.executor.isEnabled('Agent')
|
|
1265
|
+
? [this.executor.definitions()]
|
|
1266
|
+
: []),
|
|
1267
|
+
...management.map((definition) => baseByName.get(definition.name) ?? definition),
|
|
1268
|
+
...ordinary.slice(insertionIndex),
|
|
1269
|
+
];
|
|
1270
|
+
}
|
|
1271
|
+
async prepare(call, context) {
|
|
1272
|
+
if (call.name === 'Agent')
|
|
1273
|
+
return this.executor.prepare(call, this.depth);
|
|
1274
|
+
if (call.name === 'SendMessage') {
|
|
1275
|
+
return this.executor.prepareManagement(call);
|
|
1276
|
+
}
|
|
1277
|
+
if (call.name === 'TaskOutput' || call.name === 'TaskStop') {
|
|
1278
|
+
const taskId = call.input.task_id ?? call.input.shell_id;
|
|
1279
|
+
if (typeof taskId === 'string' && isBackgroundBashTaskId(taskId)) {
|
|
1280
|
+
return this.base.prepare(call, context);
|
|
1281
|
+
}
|
|
1282
|
+
return this.executor.prepareManagement(call);
|
|
1283
|
+
}
|
|
1284
|
+
return this.base.prepare(call, context);
|
|
1285
|
+
}
|
|
1286
|
+
async execute(call, context) {
|
|
1287
|
+
if (call.name === 'SendMessage') {
|
|
1288
|
+
return this.executor.executeManagement(call, this.sessionId);
|
|
1289
|
+
}
|
|
1290
|
+
if (call.name === 'TaskOutput' || call.name === 'TaskStop') {
|
|
1291
|
+
const taskId = call.input.task_id ?? call.input.shell_id;
|
|
1292
|
+
if (typeof taskId === 'string' && isBackgroundBashTaskId(taskId)) {
|
|
1293
|
+
return this.base.execute(call, context);
|
|
1294
|
+
}
|
|
1295
|
+
return this.executor.executeManagement(call, this.sessionId);
|
|
1296
|
+
}
|
|
1297
|
+
if (call.name !== 'Agent')
|
|
1298
|
+
return this.base.execute(call, context);
|
|
1299
|
+
const promptId = this.promptIdForCall(call.id);
|
|
1300
|
+
if (!promptId)
|
|
1301
|
+
throw new Error(`Could not locate prompt for Agent ${call.id}`);
|
|
1302
|
+
return this.executor.execute(call, this.sessionId, this.depth, promptId, context);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
//# sourceMappingURL=subagent-service.js.map
|