xcoder-dna 0.0.0-stage → 1.3.1
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 +87 -2
- package/dist/agents/ai-chat-debate.d.ts +36 -0
- package/dist/agents/ai-chat-debate.js +300 -0
- package/dist/agents/ai-chat-report-writer.d.ts +7 -0
- package/dist/agents/ai-chat-report-writer.js +100 -0
- package/dist/agents/duplicate-detector.d.ts +41 -0
- package/dist/agents/duplicate-detector.js +65 -0
- package/dist/agents/genesis-agent.d.ts +61 -0
- package/dist/agents/genesis-agent.js +340 -0
- package/dist/agents/samurai-agent.d.ts +53 -0
- package/dist/agents/samurai-agent.js +279 -0
- package/dist/agents/sub-agent.d.ts +56 -0
- package/dist/agents/sub-agent.js +353 -0
- package/dist/backlog/backlog-requirement-validator.d.ts +10 -0
- package/dist/backlog/backlog-requirement-validator.js +60 -0
- package/dist/backlog/backlog-store.d.ts +29 -0
- package/dist/backlog/backlog-store.js +148 -0
- package/dist/backlog/po-agent.d.ts +16 -0
- package/dist/backlog/po-agent.js +121 -0
- package/dist/backlog/types.d.ts +25 -0
- package/dist/backlog/types.js +4 -0
- package/dist/bench/run.d.ts +11 -0
- package/dist/bench/run.js +185 -0
- package/dist/bench/types.d.ts +50 -0
- package/dist/bench/types.js +1 -0
- package/dist/cli/swarm.d.ts +10 -0
- package/dist/cli/swarm.js +100 -0
- package/dist/cli/task.d.ts +14 -0
- package/dist/cli/task.js +121 -0
- package/dist/cli/wbc-arg.d.ts +6 -0
- package/dist/cli/wbc-arg.js +40 -0
- package/dist/cli/wbc.d.ts +45 -0
- package/dist/cli/wbc.js +98 -0
- package/dist/commands/license.d.ts +9 -0
- package/dist/commands/license.js +140 -0
- package/dist/commands/release.d.ts +44 -0
- package/dist/commands/release.js +180 -0
- package/dist/commands/test.d.ts +50 -0
- package/dist/commands/test.js +385 -0
- package/dist/config/loadConfig.d.ts +82 -0
- package/dist/config/loadConfig.js +240 -0
- package/dist/config/secure-mode.d.ts +29 -0
- package/dist/config/secure-mode.js +63 -0
- package/dist/config/user-config.d.ts +39 -0
- package/dist/config/user-config.js +202 -0
- package/dist/engine/reasoning-engine.d.ts +21 -0
- package/dist/engine/reasoning-engine.js +59 -0
- package/dist/events/bus.d.ts +22 -0
- package/dist/events/bus.js +18 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +77 -0
- package/dist/indexing/ignoreRules.d.ts +1 -0
- package/dist/indexing/ignoreRules.js +53 -0
- package/dist/instance-swarm/instance-swarm-orchestrator.d.ts +57 -0
- package/dist/instance-swarm/instance-swarm-orchestrator.js +204 -0
- package/dist/instance-swarm/protocol-name-resolver.d.ts +23 -0
- package/dist/instance-swarm/protocol-name-resolver.js +64 -0
- package/dist/license/gate.d.ts +31 -0
- package/dist/license/gate.js +188 -0
- package/dist/license/http-client.d.ts +43 -0
- package/dist/license/http-client.js +195 -0
- package/dist/license/manager.d.ts +39 -0
- package/dist/license/manager.js +175 -0
- package/dist/license/receipt.d.ts +27 -0
- package/dist/license/receipt.js +108 -0
- package/dist/license/state-codec.d.ts +72 -0
- package/dist/license/state-codec.js +218 -0
- package/dist/license/state-paths.d.ts +17 -0
- package/dist/license/state-paths.js +64 -0
- package/dist/license/store.d.ts +44 -0
- package/dist/license/store.js +223 -0
- package/dist/license/trust-anchor.d.ts +24 -0
- package/dist/license/trust-anchor.js +74 -0
- package/dist/license/types.d.ts +34 -0
- package/dist/license/types.js +19 -0
- package/dist/llm/budget.d.ts +23 -0
- package/dist/llm/budget.js +58 -0
- package/dist/llm/client.d.ts +53 -0
- package/dist/llm/client.js +122 -0
- package/dist/llm/factory.d.ts +14 -0
- package/dist/llm/factory.js +32 -0
- package/dist/orchestrator/defect-logger.d.ts +31 -0
- package/dist/orchestrator/defect-logger.js +101 -0
- package/dist/orchestrator/defect-manager.d.ts +118 -0
- package/dist/orchestrator/defect-manager.js +338 -0
- package/dist/orchestrator/defect-migration.d.ts +14 -0
- package/dist/orchestrator/defect-migration.js +174 -0
- package/dist/orchestrator/defect-store.d.ts +48 -0
- package/dist/orchestrator/defect-store.js +76 -0
- package/dist/orchestrator/healing.d.ts +14 -0
- package/dist/orchestrator/healing.js +11 -0
- package/dist/orchestrator/interactive-steering.d.ts +64 -0
- package/dist/orchestrator/interactive-steering.js +107 -0
- package/dist/orchestrator/interrupt-handler.d.ts +30 -0
- package/dist/orchestrator/interrupt-handler.js +70 -0
- package/dist/orchestrator/lesson-manager.d.ts +25 -0
- package/dist/orchestrator/lesson-manager.js +122 -0
- package/dist/orchestrator/progress-summary.d.ts +15 -0
- package/dist/orchestrator/progress-summary.js +106 -0
- package/dist/orchestrator/reasoning-score.d.ts +49 -0
- package/dist/orchestrator/reasoning-score.js +117 -0
- package/dist/orchestrator/swarm.d.ts +36 -0
- package/dist/orchestrator/swarm.js +77 -0
- package/dist/orchestrator/task-factory.d.ts +15 -0
- package/dist/orchestrator/task-factory.js +176 -0
- package/dist/orchestrator/validation-gate.d.ts +23 -0
- package/dist/orchestrator/validation-gate.js +155 -0
- package/dist/protocol/react-contract.d.ts +136 -0
- package/dist/protocol/react-contract.js +698 -0
- package/dist/protocol/wks-protocol-manager.d.ts +22 -0
- package/dist/protocol/wks-protocol-manager.js +72 -0
- package/dist/sdlc-runtime/conversation-runner.d.ts +8 -0
- package/dist/sdlc-runtime/conversation-runner.js +64 -0
- package/dist/sdlc-runtime/dag-utils.d.ts +15 -0
- package/dist/sdlc-runtime/dag-utils.js +67 -0
- package/dist/sdlc-runtime/defect-integration.d.ts +7 -0
- package/dist/sdlc-runtime/defect-integration.js +99 -0
- package/dist/sdlc-runtime/execution-loop.d.ts +38 -0
- package/dist/sdlc-runtime/execution-loop.js +274 -0
- package/dist/sdlc-runtime/lesson-recorder.d.ts +9 -0
- package/dist/sdlc-runtime/lesson-recorder.js +27 -0
- package/dist/sdlc-runtime/plan-initializer.d.ts +47 -0
- package/dist/sdlc-runtime/plan-initializer.js +135 -0
- package/dist/sdlc-runtime/progress-persister.d.ts +10 -0
- package/dist/sdlc-runtime/progress-persister.js +34 -0
- package/dist/sdlc-runtime/protocol-loader.d.ts +10 -0
- package/dist/sdlc-runtime/protocol-loader.js +21 -0
- package/dist/sdlc-runtime/reporting.d.ts +24 -0
- package/dist/sdlc-runtime/reporting.js +68 -0
- package/dist/sdlc-runtime/sdlc-orchestrator.d.ts +59 -0
- package/dist/sdlc-runtime/sdlc-orchestrator.js +170 -0
- package/dist/sdlc-runtime/sdlc-skill.d.ts +44 -0
- package/dist/sdlc-runtime/sdlc-skill.js +148 -0
- package/dist/sdlc-runtime/steering-handler.d.ts +14 -0
- package/dist/sdlc-runtime/steering-handler.js +51 -0
- package/dist/sdlc-runtime/trace-recorder.d.ts +10 -0
- package/dist/sdlc-runtime/trace-recorder.js +7 -0
- package/dist/security/index.d.ts +16 -0
- package/dist/security/index.js +12 -0
- package/dist/security/input-screen.d.ts +30 -0
- package/dist/security/input-screen.js +75 -0
- package/dist/security/tool-call-guard.d.ts +16 -0
- package/dist/security/tool-call-guard.js +163 -0
- package/dist/security/untrusted-content.d.ts +34 -0
- package/dist/security/untrusted-content.js +63 -0
- package/dist/skills/advanced-dfir/SKILL.md +85 -0
- package/dist/skills/advanced-pentest-lab/SKILL.md +88 -0
- package/dist/skills/analyst/SKILL.md +55 -0
- package/dist/skills/architect/SKILL.md +54 -0
- package/dist/skills/aws/SKILL.md +92 -0
- package/dist/skills/azure/SKILL.md +90 -0
- package/dist/skills/bylaw-context.d.ts +45 -0
- package/dist/skills/bylaw-context.js +61 -0
- package/dist/skills/bylaw-review.d.ts +20 -0
- package/dist/skills/bylaw-review.js +101 -0
- package/dist/skills/conversation/SKILL.md +29 -0
- package/dist/skills/design-patterns/SKILL.md +190 -0
- package/dist/skills/devops/SKILL.md +55 -0
- package/dist/skills/directives.d.ts +20 -0
- package/dist/skills/directives.js +313 -0
- package/dist/skills/docker/SKILL.md +76 -0
- package/dist/skills/docker-expert/SKILL.md +56 -0
- package/dist/skills/enterprise-systems-analyst/SKILL.md +83 -0
- package/dist/skills/enterprise-systems-analyst/references/crm.md +41 -0
- package/dist/skills/enterprise-systems-analyst/references/erp.md +40 -0
- package/dist/skills/enterprise-systems-analyst/references/financial-systems.md +35 -0
- package/dist/skills/enterprise-systems-analyst/references/hcm.md +38 -0
- package/dist/skills/enterprise-systems-analyst/references/mrp.md +37 -0
- package/dist/skills/enterprise-systems-analyst/references/scm.md +32 -0
- package/dist/skills/ethical-hacking-methodology/SKILL.md +119 -0
- package/dist/skills/externalSkillLoader.d.ts +25 -0
- package/dist/skills/externalSkillLoader.js +65 -0
- package/dist/skills/externalSkillRegistry.d.ts +33 -0
- package/dist/skills/externalSkillRegistry.js +94 -0
- package/dist/skills/filesystem-management/SKILL.md +61 -0
- package/dist/skills/first-run-seed.d.ts +26 -0
- package/dist/skills/first-run-seed.js +75 -0
- package/dist/skills/git-vcs/SKILL.md +84 -0
- package/dist/skills/kafka/SKILL.md +89 -0
- package/dist/skills/kubernetes/SKILL.md +93 -0
- package/dist/skills/kubernetes-expert/SKILL.md +54 -0
- package/dist/skills/openshift/SKILL.md +93 -0
- package/dist/skills/pentester/SKILL.md +59 -0
- package/dist/skills/performance-tester/SKILL.md +57 -0
- package/dist/skills/playwright-ui-tester/SKILL.md +67 -0
- package/dist/skills/programmer/SKILL.md +58 -0
- package/dist/skills/project-scaffolding/SKILL.md +133 -0
- package/dist/skills/qa-engineer/SKILL.md +91 -0
- package/dist/skills/rca/SKILL.md +58 -0
- package/dist/skills/redhat/SKILL.md +92 -0
- package/dist/skills/rosa/SKILL.md +80 -0
- package/dist/skills/scrum-framework/SKILL.md +74 -0
- package/dist/skills/scrum-framework/references/artifacts_and_quality.md +79 -0
- package/dist/skills/scrum-framework/references/roles_and_events.md +105 -0
- package/dist/skills/scrum-master-agent/SKILL.md +74 -0
- package/dist/skills/scrum-master-agent/references/behaviors.md +56 -0
- package/dist/skills/sdlc-skill.d.ts +1 -0
- package/dist/skills/sdlc-skill.js +4 -0
- package/dist/skills/secops/SKILL.md +52 -0
- package/dist/skills/secure-architect.bylaws.d.ts +68 -0
- package/dist/skills/secure-architect.bylaws.js +525 -0
- package/dist/skills/seed-skills.d.ts +48 -0
- package/dist/skills/seed-skills.js +213 -0
- package/dist/skills/skill-authoring/SKILL.md +123 -0
- package/dist/skills/skill-header.d.ts +51 -0
- package/dist/skills/skill-header.js +163 -0
- package/dist/skills/skill-path-guard.d.ts +41 -0
- package/dist/skills/skill-path-guard.js +95 -0
- package/dist/skills/skillRouter.d.ts +51 -0
- package/dist/skills/skillRouter.js +90 -0
- package/dist/skills/skills-root.d.ts +64 -0
- package/dist/skills/skills-root.js +168 -0
- package/dist/skills/software-architect/SKILL.md +77 -0
- package/dist/skills/software-engineer/SKILL.md +74 -0
- package/dist/skills/solid-principles/SKILL.md +94 -0
- package/dist/skills/task-planning/SKILL.md +115 -0
- package/dist/skills/tester/SKILL.md +54 -0
- package/dist/skills/ubuntu/SKILL.md +87 -0
- package/dist/skills/ui-ux-design/SKILL.md +114 -0
- package/dist/skills/workspace-context/SKILL.md +103 -0
- package/dist/sprint/controller.d.ts +37 -0
- package/dist/sprint/controller.js +220 -0
- package/dist/sprint/dag-builder.d.ts +14 -0
- package/dist/sprint/dag-builder.js +105 -0
- package/dist/sprint/reporter.d.ts +11 -0
- package/dist/sprint/reporter.js +97 -0
- package/dist/sprint/state-store.d.ts +10 -0
- package/dist/sprint/state-store.js +71 -0
- package/dist/sprint/types.d.ts +24 -0
- package/dist/sprint/types.js +4 -0
- package/dist/store/file-version-store.d.ts +24 -0
- package/dist/store/file-version-store.js +73 -0
- package/dist/store/task-store.d.ts +90 -0
- package/dist/store/task-store.js +166 -0
- package/dist/task-ingest/architect-detailer.d.ts +43 -0
- package/dist/task-ingest/architect-detailer.js +141 -0
- package/dist/task-ingest/detail-schema.d.ts +9 -0
- package/dist/task-ingest/detail-schema.js +195 -0
- package/dist/task-ingest/detailed-run.d.ts +36 -0
- package/dist/task-ingest/detailed-run.js +108 -0
- package/dist/task-ingest/extract-id.d.ts +9 -0
- package/dist/task-ingest/extract-id.js +24 -0
- package/dist/task-ingest/index.d.ts +23 -0
- package/dist/task-ingest/index.js +14 -0
- package/dist/task-ingest/ingest.d.ts +45 -0
- package/dist/task-ingest/ingest.js +163 -0
- package/dist/task-ingest/list-ingested.d.ts +13 -0
- package/dist/task-ingest/list-ingested.js +30 -0
- package/dist/task-ingest/pending-filter.d.ts +30 -0
- package/dist/task-ingest/pending-filter.js +59 -0
- package/dist/task-ingest/scanner.d.ts +56 -0
- package/dist/task-ingest/scanner.js +216 -0
- package/dist/task-ingest/source-reader.d.ts +25 -0
- package/dist/task-ingest/source-reader.js +93 -0
- package/dist/task-ingest/spec-builder.d.ts +34 -0
- package/dist/task-ingest/spec-builder.js +89 -0
- package/dist/task-ingest/wbs-extract.d.ts +50 -0
- package/dist/task-ingest/wbs-extract.js +226 -0
- package/dist/task-ingest/wbs-parser.d.ts +36 -0
- package/dist/task-ingest/wbs-parser.js +170 -0
- package/dist/tools/apiTestTool.d.ts +37 -0
- package/dist/tools/apiTestTool.js +128 -0
- package/dist/tools/ast-tools.d.ts +183 -0
- package/dist/tools/ast-tools.js +853 -0
- package/dist/tools/browse-tool.d.ts +105 -0
- package/dist/tools/browse-tool.js +394 -0
- package/dist/tools/credential.d.ts +17 -0
- package/dist/tools/credential.js +32 -0
- package/dist/tools/dependency-graph.d.ts +23 -0
- package/dist/tools/dependency-graph.js +164 -0
- package/dist/tools/edit-tool.d.ts +34 -0
- package/dist/tools/edit-tool.js +95 -0
- package/dist/tools/file-header-manager.d.ts +27 -0
- package/dist/tools/file-header-manager.js +153 -0
- package/dist/tools/fs-tools.d.ts +154 -0
- package/dist/tools/fs-tools.js +337 -0
- package/dist/tools/git-tools.d.ts +79 -0
- package/dist/tools/git-tools.js +348 -0
- package/dist/tools/github-tool.d.ts +48 -0
- package/dist/tools/github-tool.js +147 -0
- package/dist/tools/globTool.d.ts +20 -0
- package/dist/tools/globTool.js +34 -0
- package/dist/tools/grepTool.d.ts +19 -0
- package/dist/tools/grepTool.js +44 -0
- package/dist/tools/index-freshness.d.ts +58 -0
- package/dist/tools/index-freshness.js +190 -0
- package/dist/tools/index-glob.d.ts +48 -0
- package/dist/tools/index-glob.js +175 -0
- package/dist/tools/load-skill-tool.d.ts +15 -0
- package/dist/tools/load-skill-tool.js +114 -0
- package/dist/tools/patch-tools.d.ts +58 -0
- package/dist/tools/patch-tools.js +153 -0
- package/dist/tools/playwright-tool.d.ts +66 -0
- package/dist/tools/playwright-tool.js +121 -0
- package/dist/tools/project-detect.d.ts +20 -0
- package/dist/tools/project-detect.js +87 -0
- package/dist/tools/prompt-guidance.d.ts +22 -0
- package/dist/tools/prompt-guidance.js +23 -0
- package/dist/tools/scheduleTool.d.ts +19 -0
- package/dist/tools/scheduleTool.js +181 -0
- package/dist/tools/search-tools.d.ts +27 -0
- package/dist/tools/search-tools.js +78 -0
- package/dist/tools/sed-tool.d.ts +66 -0
- package/dist/tools/sed-tool.js +402 -0
- package/dist/tools/shell-result.d.ts +11 -0
- package/dist/tools/shell-result.js +1 -0
- package/dist/tools/shell-tool.d.ts +45 -0
- package/dist/tools/shell-tool.js +141 -0
- package/dist/tools/siteCrawlerTool.d.ts +32 -0
- package/dist/tools/siteCrawlerTool.js +205 -0
- package/dist/tools/tool-registry.d.ts +67 -0
- package/dist/tools/tool-registry.js +596 -0
- package/dist/tools/validate-tool.d.ts +23 -0
- package/dist/tools/validate-tool.js +201 -0
- package/dist/tools/workspace-index.d.ts +46 -0
- package/dist/tools/workspace-index.js +173 -0
- package/dist/types.d.ts +222 -0
- package/dist/types.js +7 -0
- package/dist/updater/index.d.ts +14 -0
- package/dist/updater/index.js +120 -0
- package/dist/util/banner.d.ts +25 -0
- package/dist/util/banner.js +140 -0
- package/dist/util/command-suggester.d.ts +6 -0
- package/dist/util/command-suggester.js +25 -0
- package/dist/util/confirm-interrupt.d.ts +10 -0
- package/dist/util/confirm-interrupt.js +31 -0
- package/dist/util/continue-trigger.d.ts +11 -0
- package/dist/util/continue-trigger.js +20 -0
- package/dist/util/env-info.d.ts +18 -0
- package/dist/util/env-info.js +37 -0
- package/dist/util/file-access-log.d.ts +35 -0
- package/dist/util/file-access-log.js +140 -0
- package/dist/util/footer-manager.d.ts +124 -0
- package/dist/util/footer-manager.js +195 -0
- package/dist/util/footer-renderer.d.ts +67 -0
- package/dist/util/footer-renderer.js +319 -0
- package/dist/util/footer-state.d.ts +34 -0
- package/dist/util/footer-state.js +18 -0
- package/dist/util/footer-text.d.ts +51 -0
- package/dist/util/footer-text.js +74 -0
- package/dist/util/ids.d.ts +1 -0
- package/dist/util/ids.js +4 -0
- package/dist/util/levenshtein.d.ts +6 -0
- package/dist/util/levenshtein.js +34 -0
- package/dist/util/logger.d.ts +10 -0
- package/dist/util/logger.js +41 -0
- package/dist/util/logs.d.ts +26 -0
- package/dist/util/logs.js +88 -0
- package/dist/util/output-handler.d.ts +89 -0
- package/dist/util/output-handler.js +193 -0
- package/dist/util/output-interceptor.d.ts +18 -0
- package/dist/util/output-interceptor.js +49 -0
- package/dist/util/output-paths.d.ts +43 -0
- package/dist/util/output-paths.js +121 -0
- package/dist/util/package-json.d.ts +6 -0
- package/dist/util/package-json.js +36 -0
- package/dist/util/process-kill.d.ts +27 -0
- package/dist/util/process-kill.js +148 -0
- package/dist/util/protocol-error-logger.d.ts +33 -0
- package/dist/util/protocol-error-logger.js +73 -0
- package/dist/util/redact.d.ts +25 -0
- package/dist/util/redact.js +103 -0
- package/dist/util/scroll-region-guard.d.ts +33 -0
- package/dist/util/scroll-region-guard.js +63 -0
- package/dist/util/spinner.d.ts +15 -0
- package/dist/util/spinner.js +49 -0
- package/dist/util/terminal-output.d.ts +34 -0
- package/dist/util/terminal-output.js +1 -0
- package/dist/util/terminal-silent.d.ts +6 -0
- package/dist/util/terminal-silent.js +20 -0
- package/dist/util/terminal.d.ts +56 -0
- package/dist/util/terminal.js +124 -0
- package/dist/util/text-sanitize.d.ts +8 -0
- package/dist/util/text-sanitize.js +45 -0
- package/dist/util/thinking-spinner.d.ts +27 -0
- package/dist/util/thinking-spinner.js +189 -0
- package/dist/util/tool-error-logger.d.ts +33 -0
- package/dist/util/tool-error-logger.js +77 -0
- package/dist/util/tty.d.ts +13 -0
- package/dist/util/tty.js +16 -0
- package/dist/util/xcoder-paths.d.ts +56 -0
- package/dist/util/xcoder-paths.js +63 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +4 -0
- package/dist/worker-agent/to-subtask-node.d.ts +35 -0
- package/dist/worker-agent/to-subtask-node.js +41 -0
- package/dist/worker-agent/worker-orchestrator.d.ts +104 -0
- package/dist/worker-agent/worker-orchestrator.js +201 -0
- package/package.json +38 -3
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
// xcoder:version 7 | xcoder:task task-e16f85 | xcoder:updated 2026-10-30T18:16:54.862Z | xcoder:subtask code-st-791be4
|
|
2
|
+
import { readFileTool, writeFileTool, listDirTool, readOutlineTool, readMultipleFilesTool, readFullFileTool } from "./fs-tools.js";
|
|
3
|
+
import { linePatchTool } from "./patch-tools.js";
|
|
4
|
+
import { gitDiffTool, gitLogTool, applyUnifiedDiffTool } from "./git-tools.js";
|
|
5
|
+
import { getDependencyGraphTool } from "./dependency-graph.js";
|
|
6
|
+
import { searchAstTool, updateFunctionTool, renameSymbolTool } from "./ast-tools.js";
|
|
7
|
+
import { validateFileTool } from "./validate-tool.js";
|
|
8
|
+
import { PROMPT_GUIDANCE } from "./prompt-guidance.js";
|
|
9
|
+
import { editFileTool } from "./edit-tool.js";
|
|
10
|
+
import { buildIndex, getOrBuildIndex, searchIndex } from "./workspace-index.js";
|
|
11
|
+
import { globTool } from "./globTool.js";
|
|
12
|
+
import { logFileAccess } from "../util/file-access-log.js";
|
|
13
|
+
import { grepTool } from "./grepTool.js";
|
|
14
|
+
import { testApiEndpoint } from "./apiTestTool.js";
|
|
15
|
+
import { scheduleCron, scheduleOnce, listScheduled, removeScheduled } from "./scheduleTool.js";
|
|
16
|
+
import { runCommandTool } from "./shell-tool.js";
|
|
17
|
+
import { runUiTest } from "./playwright-tool.js";
|
|
18
|
+
import { runBrowse } from "./browse-tool.js";
|
|
19
|
+
import { githubCreateRepo, githubClone, githubCommit, githubPush } from "./github-tool.js";
|
|
20
|
+
import { recordLesson } from "../orchestrator/lesson-manager.js";
|
|
21
|
+
import { loadSkillTool } from "./load-skill-tool.js";
|
|
22
|
+
import { sedTool } from "./sed-tool.js";
|
|
23
|
+
import { crawlSiteMap, formatSiteMap } from "./siteCrawlerTool.js";
|
|
24
|
+
import { InstanceSwarmOrchestrator } from "../instance-swarm/instance-swarm-orchestrator.js";
|
|
25
|
+
import { createLlmClient } from "../llm/factory.js";
|
|
26
|
+
/**
|
|
27
|
+
* Tools whose file discovery must be answered by the index alone.
|
|
28
|
+
*
|
|
29
|
+
* Exported so a test can assert the property instead of trusting prose:
|
|
30
|
+
* `globTool` imports no filesystem enumerator, and every result it returns is
|
|
31
|
+
* a strict subset of `WorkspaceIndex.entries`.
|
|
32
|
+
*/
|
|
33
|
+
export const INDEX_ONLY_DISCOVERY_TOOLS = ["glob", "grep", "search_workspace", "list_dir"];
|
|
34
|
+
export const TOOL_MANIFEST = [
|
|
35
|
+
{
|
|
36
|
+
name: "search_workspace",
|
|
37
|
+
description: "Search the workspace index (the source of truth for what files exist) by path substring.",
|
|
38
|
+
discoverySource: "index",
|
|
39
|
+
inputHint: '{ "query": "src/auth" }',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "glob",
|
|
43
|
+
description: "Pattern-match file paths in the workspace index using *, **, ? and {a,b} — answered by the index with no filesystem walk, so it works identically on every OS. Files excluded from the index (dotfiles, node_modules, dist, >5MB) are excluded here too.",
|
|
44
|
+
discoverySource: "index",
|
|
45
|
+
inputHint: '{ "pattern": "src/**/*.test.ts" }',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "grep",
|
|
49
|
+
description: "Search file CONTENTS for a regex/string. The candidate file set comes from the workspace index (no filesystem walk); contents are then read from disk. Returns file, line number, and the matching line.",
|
|
50
|
+
discoverySource: "file-bytes",
|
|
51
|
+
inputHint: '{ "pattern": "function login\\\\(", "pathGlob": "src/**/*.ts" }',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "read_file",
|
|
55
|
+
description: "Read a file relative to the workspace root. Auto-reindexes once and retries if the path isn't in the index. Supports an optional line range for large files.",
|
|
56
|
+
inputHint: '{ "path": "src/auth/login.ts", "startLine": 1, "endLine": 200 }',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "edit_file",
|
|
60
|
+
description: "Surgically replace ONE exact, unique occurrence of old_str with new_str in an existing file — the accurate way to refactor part of a large file without rewriting the whole thing. old_str must match exactly once; if it matches 0 or 2+ times, widen it with more surrounding context and retry.",
|
|
61
|
+
inputHint: '{ "path": "src/auth/login.ts", "old_str": "exact existing text, unique in the file", "new_str": "its replacement" }',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "write_file",
|
|
65
|
+
description: "Write (create or fully overwrite) a file relative to the workspace root. Prefer edit_file for changes to an existing file of any real size — write_file is for new files or genuinely full rewrites.",
|
|
66
|
+
inputHint: '{ "path": "src/auth/login.ts", "content": "..." }',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "list_dir",
|
|
70
|
+
description: "List indexed files under a directory prefix.",
|
|
71
|
+
discoverySource: "index",
|
|
72
|
+
inputHint: '{ "dir": "src" }',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "reindex_workspace",
|
|
76
|
+
description: "Force a full workspace reindex. Use if you suspect the index is stale after many of your own writes.",
|
|
77
|
+
inputHint: "{}",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "run_command",
|
|
81
|
+
description: "Run a shell command from the workspace root (build, run tests, lint, type-check, start a dev server, reproduce a bug, etc.). Denylisted destructive patterns are refused. Mind the runtime-environment note in your system prompt — this may not be a unix shell.",
|
|
82
|
+
inputHint: '{ "command": "npm test", "timeoutMs": 60000 }',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: "ui_test",
|
|
86
|
+
description: "Run a Playwright browser test against a URL. Never pass a raw secret — pass a credentialRef (an environment variable name) instead.",
|
|
87
|
+
inputHint: '{ "kind": "ui", "url": "https://...", "credentialRef": "STAGING_PASSWORD", "steps": [ { "op": "click", "selector": "#submit" } ] }',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: "browse",
|
|
91
|
+
description: "Drive a real browser through steps and READ what is on the page (ops: goto, click, fill, type, press, select, check, hover, scroll, wait_for, wait, text, attr, links, title, url, back, forward, reload, screenshot, expect_text, expect_url, close). Returns per-step results, extracted text/links and the final page snapshot, so you can decide the next step. Only http(s) URLs (localhost ok; private networks blocked). Use `session` to stay logged in across calls. For passwords pass credentialRef (env var name), never the secret. Screenshots are saved inside the workspace.",
|
|
92
|
+
inputHint: '{ "url": "http://localhost:3000", "session": "app", "steps": [ { "op": "fill", "selector": "#user", "value": "admin" }, { "op": "fill", "selector": "#pass", "credentialRef": "APP_PASSWORD" }, { "op": "click", "selector": "button[type=submit]" }, { "op": "text", "selector": "h1" }, { "op": "screenshot" } ] }',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "api_test",
|
|
96
|
+
description: "Send one HTTP request and assert on status/body. Never pass a raw secret — pass a credentialRef instead.",
|
|
97
|
+
inputHint: '{ "kind": "api", "method": "GET", "url": "https://.../health", "expectStatus": 200 }',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "load_skill",
|
|
101
|
+
description: "Load the full bodies of external skill files (SKILL.md) by role or keyword. Use this when your task requires detailed process/strategy guidance that goes beyond the one-line summaries in your system prompt. Max 5 results for keyword.",
|
|
102
|
+
inputHint: '{ "role": "tester" } or { "keyword": "penetration testing" }',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: "github_create_repo",
|
|
106
|
+
description: "Create a new GitHub repository via the API. Requires a GITHUB_TOKEN env var (or a named credentialRef) — never pass a raw token.",
|
|
107
|
+
inputHint: '{ "name": "my-repo", "private": true, "description": "..." }',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: "github_clone",
|
|
111
|
+
description: "Clone a GitHub repository into a directory inside the workspace.",
|
|
112
|
+
inputHint: '{ "url": "https://github.com/org/repo.git", "dir": "repo" }',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "github_commit",
|
|
116
|
+
description: "Stage and commit changes in a workspace directory (defaults to the workspace root).",
|
|
117
|
+
inputHint: '{ "message": "fix: patch merges partial updates instead of overwriting" }',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "github_push",
|
|
121
|
+
description: "Push the current branch to a remote. Requires a GITHUB_TOKEN env var (or a named credentialRef) for an https remote — never pass a raw token.",
|
|
122
|
+
inputHint: '{ "remote": "origin", "branch": "main" }',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "sed_tool",
|
|
126
|
+
description: "Perform stream-editing operations (substitute, delete, deleteRange, insert, appendAfter) " +
|
|
127
|
+
"on workspace files using regex patterns. Supports multi-file glob, dry-run preview, " +
|
|
128
|
+
"cross-platform line-ending preservation, and JS regex back-references ($1, $&) in replacements. " +
|
|
129
|
+
"Use for bulk find/replace across many files — prefer edit_file for single surgical replacements.",
|
|
130
|
+
inputHint: '{ "path": "src/config.ts", "operation": "substitute", "pattern": "oldValue", "replacement": "newValue", "flags": "g" }',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "call_swarm",
|
|
134
|
+
description: "Dispatch an Instance Swarm — multiple concurrent specialized sub-agents — against a goal using a named protocol. " +
|
|
135
|
+
"Use this to parallelize complex multi-file work (code, test, review) in one call. " +
|
|
136
|
+
"The swarm returns a structured summary. Sub-agent crashes are isolated and reported as errors.",
|
|
137
|
+
inputHint: '{ "goal": "Implement a login endpoint", "protocol": "coder", "concurrency": 3 }',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "schedule",
|
|
141
|
+
description: "Manage scheduled jobs — create recurring (cron) or one-off delayed commands, list existing jobs, " +
|
|
142
|
+
"remove a job by id. POSIX uses cron; Windows uses schtasks.",
|
|
143
|
+
inputHint: '{ "operation": "create_cron", "id": "my-job", "cronExpr": "0 9 * * *", "command": "npm run daily" }',
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "site_crawler",
|
|
147
|
+
description: "Crawl a website starting from a URL and return a structured sitemap (tree format). Same-domain only. Respects maxPages and maxDepth limits.",
|
|
148
|
+
inputHint: '{ "url": "https://example.com", "maxPages": 10, "maxDepth": 3, "format": "json" }',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: "read_outline",
|
|
152
|
+
description: "Structural skeleton read (imports, signatures, docstrings, bodies collapsed) — the cheapest first read for files over ~150 lines. " +
|
|
153
|
+
PROMPT_GUIDANCE.readFirst,
|
|
154
|
+
inputHint: '{ "path": "src/auth/login.ts" }',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "read_multiple_files",
|
|
158
|
+
description: "Batched, labeled section reads in ONE call — prefer over N read_file calls for cross-file understanding. " +
|
|
159
|
+
PROMPT_GUIDANCE.readFirst,
|
|
160
|
+
inputHint: '{ "files": [{ "path": "src/a.ts", "startLine": 1, "endLine": 40 }], "maxTotalChars": 12000 }',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: "read_full_file",
|
|
164
|
+
description: "Gated whole-file read — refused above 500 lines unless allowLarge: true. Prefer read_outline / read_file with a range for big files. " +
|
|
165
|
+
PROMPT_GUIDANCE.readFirst,
|
|
166
|
+
inputHint: '{ "path": "src/big.ts", "allowLarge": false }',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "search_ast",
|
|
170
|
+
description: "Structural TS/JS search (function/class/call targets) via the scanner — no regex false positives inside strings or comments. " +
|
|
171
|
+
"For arbitrary regex search use grep instead.",
|
|
172
|
+
inputHint: '{ "query": "function login", "pathGlob": "src/**/*.ts" }',
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: "get_dependency_graph",
|
|
176
|
+
description: "Imports + importers for one file, best-effort over the workspace index (TS/JS/Python). Cheaper than grepping import lines by hand.",
|
|
177
|
+
inputHint: '{ "path": "src/auth/login.ts" }',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "git_diff",
|
|
181
|
+
description: "Low-token diff summary (git diff --stat by default). Pass rawDiff: true for the full unified diff. " +
|
|
182
|
+
PROMPT_GUIDANCE.gitFirst,
|
|
183
|
+
inputHint: '{ "ref": "HEAD~3", "path": "src/a.ts", "rawDiff": false }',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: "git_log",
|
|
187
|
+
description: "Recent commit subjects for the workspace or a single file. " +
|
|
188
|
+
PROMPT_GUIDANCE.gitFirst,
|
|
189
|
+
inputHint: '{ "path": "src/a.ts", "maxCount": 10 }',
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: "line_patch",
|
|
193
|
+
description: "Stale-enforced line replacement: replaces lines [startLine..endLine] with newContent, refusing if the file changed since you read it. " +
|
|
194
|
+
"Requires expectedSha1 from a prior read_file range read. " +
|
|
195
|
+
PROMPT_GUIDANCE.editFirst,
|
|
196
|
+
inputHint: '{ "path": "src/a.ts", "startLine": 10, "endLine": 12, "newContent": "...", "expectedSha1": "<from read>" }',
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: "apply_unified_diff",
|
|
200
|
+
description: "Apply a multi-hunk unified diff; inside a git repo it runs git apply --check first (zero writes on failure). " +
|
|
201
|
+
PROMPT_GUIDANCE.editFirst,
|
|
202
|
+
inputHint: '{ "path": "src/a.ts", "diff": "--- a/src/a.ts +++ b/src/a.ts @@ -1,3 +1,4 @@ ..." }',
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: "update_function",
|
|
206
|
+
description: "AST-scoped whole-function rewrite (TS/JS only) — replaces a unique function/class declaration's body range. " +
|
|
207
|
+
PROMPT_GUIDANCE.editFirst,
|
|
208
|
+
inputHint: '{ "path": "src/a.ts", "functionName": "login", "newCode": "export function login(...) {...}" }',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: "rename_symbol",
|
|
212
|
+
description: "Scope-aware identifier rename (TS/JS only) — replaces only references that resolve to the declared symbol; strings/comments/templates untouched. " +
|
|
213
|
+
"Never a blind sed.",
|
|
214
|
+
inputHint: '{ "path": "src/a.ts", "name": "oldName", "newName": "newName" }',
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: "validate_file",
|
|
218
|
+
description: "Post-edit syntax/type check on just the patched file; returns ONLY error lines. " +
|
|
219
|
+
PROMPT_GUIDANCE.validateAfterEdit,
|
|
220
|
+
inputHint: '{ "path": "src/a.ts", "lang": "typescript" }',
|
|
221
|
+
},
|
|
222
|
+
];
|
|
223
|
+
const RECORD_LESSON_MANIFEST_ENTRY = {
|
|
224
|
+
name: "record_lesson",
|
|
225
|
+
description: "Record a lesson learned into .xcoder/lesson.md. Use this when you encounter a hard-to-resolve situation, " +
|
|
226
|
+
"an opaque failure whose cause you eventually figured out, or when the task explicitly directs you to save learning.",
|
|
227
|
+
inputHint: '{ "source": "sub-agent:programmer", "taskId": "task-abc", "tags": ["build-failure", "npm"], "context": "npm install failed with EACCES...", "lesson": "Need to chown node_modules before npm install in CI" }',
|
|
228
|
+
};
|
|
229
|
+
/**
|
|
230
|
+
* Build the tool manifest array, conditionally including record_lesson.
|
|
231
|
+
* A function rather than a mutable global so that the manifest is
|
|
232
|
+
* immutable per call — testable and predictable.
|
|
233
|
+
*/
|
|
234
|
+
export function buildToolManifest(opts) {
|
|
235
|
+
const manifest = opts.lessonLearned
|
|
236
|
+
? [...TOOL_MANIFEST, RECORD_LESSON_MANIFEST_ENTRY]
|
|
237
|
+
: TOOL_MANIFEST;
|
|
238
|
+
return manifest;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Required top-level string fields per tool, checked BEFORE any case tries
|
|
242
|
+
* to destructure `input`. This exists because of a real failure mode: the
|
|
243
|
+
* model calling `glob` with no `input` key at all produced a raw
|
|
244
|
+
* `Cannot destructure property 'pattern' of 'input' as it is undefined`
|
|
245
|
+
* TypeError as the observation — technically caught (nothing crashed) but
|
|
246
|
+
* useless to the model, which had no way to tell from that message what
|
|
247
|
+
* shape was actually expected. This turns that into the same kind of
|
|
248
|
+
* clear, actionable `file_not_found`/`no_match`-style error every other
|
|
249
|
+
* tool already gives, quoting the tool's own manifest `inputHint`.
|
|
250
|
+
*/
|
|
251
|
+
const REQUIRED_STRING_FIELDS = {
|
|
252
|
+
search_workspace: ["query"],
|
|
253
|
+
glob: ["pattern"],
|
|
254
|
+
grep: ["pattern"],
|
|
255
|
+
read_file: ["path"],
|
|
256
|
+
edit_file: ["path", "old_str", "new_str"],
|
|
257
|
+
write_file: ["path", "content"],
|
|
258
|
+
list_dir: ["dir"],
|
|
259
|
+
run_command: ["command"],
|
|
260
|
+
ui_test: ["kind", "url"],
|
|
261
|
+
browse: ["steps"],
|
|
262
|
+
api_test: ["url", "method"],
|
|
263
|
+
schedule: ["operation"],
|
|
264
|
+
site_crawler: ["url"],
|
|
265
|
+
github_create_repo: ["name"],
|
|
266
|
+
github_clone: ["url", "dir"],
|
|
267
|
+
github_commit: ["message"],
|
|
268
|
+
record_lesson: ["source", "taskId", "context", "lesson"],
|
|
269
|
+
call_swarm: ["goal", "protocol"],
|
|
270
|
+
read_outline: ["path"],
|
|
271
|
+
read_multiple_files: ["files"],
|
|
272
|
+
read_full_file: ["path"],
|
|
273
|
+
search_ast: ["query"],
|
|
274
|
+
get_dependency_graph: ["path"],
|
|
275
|
+
git_diff: [],
|
|
276
|
+
git_log: ["path"],
|
|
277
|
+
line_patch: ["path", "newContent", "expectedSha1"], // startLine/endLine are numeric — validated post-string in linePatchTool
|
|
278
|
+
apply_unified_diff: ["path", "diff"],
|
|
279
|
+
update_function: ["path", "functionName", "newCode"],
|
|
280
|
+
rename_symbol: ["path", "name", "newName"],
|
|
281
|
+
validate_file: ["path"],
|
|
282
|
+
};
|
|
283
|
+
function validateInput(toolName, input) {
|
|
284
|
+
const required = REQUIRED_STRING_FIELDS[toolName];
|
|
285
|
+
if (!required)
|
|
286
|
+
return null; // no declared requirements (e.g. reindex_workspace, github_push — all-optional)
|
|
287
|
+
if (input === null || input === undefined || typeof input !== "object" || Array.isArray(input)) {
|
|
288
|
+
const manifest = TOOL_MANIFEST.find((t) => t.name === toolName);
|
|
289
|
+
return (`"${toolName}" requires an input object with ${required.map((f) => `"${f}"`).join(", ")} fields. ` +
|
|
290
|
+
`Expected shape: ${manifest?.inputHint ?? "(see tool manifest)"}`);
|
|
291
|
+
}
|
|
292
|
+
const obj = input;
|
|
293
|
+
const missing = required.filter((f) => {
|
|
294
|
+
if (toolName === "read_multiple_files" && f === "files") {
|
|
295
|
+
return !Array.isArray(obj[f]) || obj[f].length === 0;
|
|
296
|
+
}
|
|
297
|
+
return typeof obj[f] !== "string" || obj[f] === "";
|
|
298
|
+
});
|
|
299
|
+
if (missing.length) {
|
|
300
|
+
const manifest = TOOL_MANIFEST.find((t) => t.name === toolName);
|
|
301
|
+
return (`"${toolName}" is missing required field(s): ${missing.map((f) => `"${f}"`).join(", ")}. ` +
|
|
302
|
+
`Expected shape: ${manifest?.inputHint ?? "(see tool manifest)"}`);
|
|
303
|
+
}
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
/** Maximum characters for an observation returned to the LLM. */
|
|
307
|
+
const MAX_OBSERVATION_CHARS = 4000;
|
|
308
|
+
/**
|
|
309
|
+
* Implementation of the call_swarm tool — Layer 2 of crash isolation.
|
|
310
|
+
* Creates an InstanceSwarmOrchestrator, runs it against the goal+protocol,
|
|
311
|
+
* and returns a structured CallSwarmOutput. NEVER throws.
|
|
312
|
+
*/
|
|
313
|
+
async function callSwarmImpl(root, input) {
|
|
314
|
+
try {
|
|
315
|
+
const llm = createLlmClient("instance_agent");
|
|
316
|
+
const orchestrator = new InstanceSwarmOrchestrator({
|
|
317
|
+
workspaceRoot: root,
|
|
318
|
+
llm,
|
|
319
|
+
concurrency: input.concurrency ?? 3,
|
|
320
|
+
maxIterations: input.maxIterations,
|
|
321
|
+
});
|
|
322
|
+
const result = await orchestrator.run(input.goal, input.protocol);
|
|
323
|
+
const workersCompleted = result.results.filter((r) => !r.result.crashed).length;
|
|
324
|
+
const workersFailed = result.results.filter((r) => r.result.crashed).length;
|
|
325
|
+
let summary = `Swarm "${result.instanceId}" completed with status "${result.status}". ` +
|
|
326
|
+
`${workersCompleted} workers finished, ${workersFailed} crashed.`;
|
|
327
|
+
if (result.errors.length > 0) {
|
|
328
|
+
const errorPreview = result.errors.slice(0, 3).map((e) => ` - ${e}`).join("\n");
|
|
329
|
+
summary += `\nErrors:\n${errorPreview}${result.errors.length > 3 ? `\n ... and ${result.errors.length - 3} more` : ""}`;
|
|
330
|
+
}
|
|
331
|
+
// Include each worker's deliverable summary (truncated)
|
|
332
|
+
const workerSummaries = result.results
|
|
333
|
+
.map((r) => {
|
|
334
|
+
const status = r.result.crashed ? "CRASHED" : "OK";
|
|
335
|
+
const sub = r.result.summary ?? "(no summary)";
|
|
336
|
+
const short = sub.length > 200 ? sub.slice(0, 200) + "…" : sub;
|
|
337
|
+
return `[${status}] ${r.subtaskId}: ${short}`;
|
|
338
|
+
})
|
|
339
|
+
.join("\n");
|
|
340
|
+
let fullSummary = summary + "\n\nWorker results:\n" + workerSummaries;
|
|
341
|
+
if (fullSummary.length > MAX_OBSERVATION_CHARS) {
|
|
342
|
+
fullSummary = fullSummary.slice(0, MAX_OBSERVATION_CHARS - 3) + "…";
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
instanceId: result.instanceId,
|
|
346
|
+
status: result.status,
|
|
347
|
+
workersCompleted,
|
|
348
|
+
workersFailed,
|
|
349
|
+
errors: result.errors,
|
|
350
|
+
tokenUsage: result.totalTokenUsage,
|
|
351
|
+
summary: fullSummary,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
catch (e) {
|
|
355
|
+
return {
|
|
356
|
+
instanceId: "call_swarm-error",
|
|
357
|
+
status: "failed",
|
|
358
|
+
workersCompleted: 0,
|
|
359
|
+
workersFailed: 0,
|
|
360
|
+
errors: [`call_swarm orchestrator threw: ${e.message}`],
|
|
361
|
+
tokenUsage: { inputTokens: 0, outputTokens: 0 },
|
|
362
|
+
summary: `call_swarm failed: ${e.message}`,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* The one place a subtask's tool call actually executes. `root` pins every
|
|
368
|
+
* filesystem/shell action to this task's workspace — a subtask can never
|
|
369
|
+
* reach outside it (see `fs-tools.ts`'s `resolveInWorkspace`).
|
|
370
|
+
*
|
|
371
|
+
* Every branch is wrapped in try/catch here in addition to the caller's own
|
|
372
|
+
* try/catch (see `agents/sub-agent.ts`) — deliberate defense in depth: a
|
|
373
|
+
* tool throwing should never bring down the Sub Agent's loop, and a Sub
|
|
374
|
+
* Agent throwing should never bring down the Master Orchestrator (see
|
|
375
|
+
* `orchestrator/swarm.ts`).
|
|
376
|
+
*/
|
|
377
|
+
export async function dispatchTool(root, toolName, input, ctx) {
|
|
378
|
+
const result = await dispatchToolInner(root, toolName, input, ctx);
|
|
379
|
+
// Every file / shell command any tool touched goes to files.log (with rollover).
|
|
380
|
+
await logFileAccess(root, toolName, input, result.ok, ctx);
|
|
381
|
+
return result;
|
|
382
|
+
}
|
|
383
|
+
async function dispatchToolInner(root, toolName, input, ctx) {
|
|
384
|
+
const validationError = validateInput(toolName, input);
|
|
385
|
+
if (validationError) {
|
|
386
|
+
return { tool: toolName, ok: false, output: { error: validationError } };
|
|
387
|
+
}
|
|
388
|
+
try {
|
|
389
|
+
switch (toolName) {
|
|
390
|
+
case "search_workspace": {
|
|
391
|
+
const { query } = input;
|
|
392
|
+
const index = await getOrBuildIndex(root);
|
|
393
|
+
return { tool: toolName, ok: true, output: searchIndex(index, query) };
|
|
394
|
+
}
|
|
395
|
+
case "glob": {
|
|
396
|
+
const { pattern } = input;
|
|
397
|
+
const matches = await globTool(pattern, root);
|
|
398
|
+
return { tool: toolName, ok: true, output: { ok: true, matches } };
|
|
399
|
+
}
|
|
400
|
+
case "grep": {
|
|
401
|
+
const { pattern, pathGlob, contextLines } = input;
|
|
402
|
+
const result = contextLines !== undefined
|
|
403
|
+
? await grepTool(pattern, pathGlob ?? "**/*", root, { contextLines })
|
|
404
|
+
: await grepTool(pattern, pathGlob ?? "**/*", root);
|
|
405
|
+
return { tool: toolName, ok: true, output: { ok: true, matches: result } };
|
|
406
|
+
}
|
|
407
|
+
case "read_file": {
|
|
408
|
+
const { path, startLine, endLine } = input;
|
|
409
|
+
const result = await readFileTool(root, path, { startLine, endLine });
|
|
410
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
411
|
+
}
|
|
412
|
+
case "edit_file": {
|
|
413
|
+
const { path, old_str, new_str } = input;
|
|
414
|
+
const result = await editFileTool(root, { path, old_str, new_str }, ctx);
|
|
415
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
416
|
+
}
|
|
417
|
+
case "write_file": {
|
|
418
|
+
const { path, content, force } = input;
|
|
419
|
+
const result = force === true
|
|
420
|
+
? await writeFileTool(root, path, content, ctx, { force: true })
|
|
421
|
+
: await writeFileTool(root, path, content, ctx);
|
|
422
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
423
|
+
}
|
|
424
|
+
case "list_dir": {
|
|
425
|
+
const { dir } = input;
|
|
426
|
+
const index = await getOrBuildIndex(root);
|
|
427
|
+
const result = await listDirTool(index, dir);
|
|
428
|
+
return { tool: toolName, ok: true, output: result };
|
|
429
|
+
}
|
|
430
|
+
case "reindex_workspace": {
|
|
431
|
+
const index = await buildIndex(root);
|
|
432
|
+
return { tool: toolName, ok: true, output: { fileCount: index.entries.length, builtAt: index.builtAt } };
|
|
433
|
+
}
|
|
434
|
+
case "run_command": {
|
|
435
|
+
const { command, timeoutMs } = input;
|
|
436
|
+
const result = await runCommandTool(command, root, timeoutMs);
|
|
437
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
438
|
+
}
|
|
439
|
+
case "ui_test": {
|
|
440
|
+
const uiInput = input;
|
|
441
|
+
const result = await runUiTest(uiInput);
|
|
442
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
443
|
+
}
|
|
444
|
+
case "browse": {
|
|
445
|
+
const result = await runBrowse(root, input);
|
|
446
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
447
|
+
}
|
|
448
|
+
case "api_test": {
|
|
449
|
+
const { url, method, headers, body, bodyType, queryParams, maxBodyLength, timeout, expectStatus, expectBodyContains, credentialRef } = input;
|
|
450
|
+
try {
|
|
451
|
+
const result = await testApiEndpoint({
|
|
452
|
+
url, method, headers, body, bodyType, queryParams,
|
|
453
|
+
maxBodyLength, timeout, expectStatus, expectBodyContains, credentialRef,
|
|
454
|
+
});
|
|
455
|
+
return { tool: toolName, ok: true, output: result };
|
|
456
|
+
}
|
|
457
|
+
catch (e) {
|
|
458
|
+
return { tool: toolName, ok: false, output: { error: e.message } };
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
case "github_create_repo": {
|
|
462
|
+
const result = await githubCreateRepo(input);
|
|
463
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
464
|
+
}
|
|
465
|
+
case "github_clone": {
|
|
466
|
+
const result = await githubClone(root, input);
|
|
467
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
468
|
+
}
|
|
469
|
+
case "github_commit": {
|
|
470
|
+
const result = await githubCommit(root, input);
|
|
471
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
472
|
+
}
|
|
473
|
+
case "github_push": {
|
|
474
|
+
const result = await githubPush(root, input);
|
|
475
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
476
|
+
}
|
|
477
|
+
case "sed_tool": {
|
|
478
|
+
const result = await sedTool(root, input, ctx);
|
|
479
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
480
|
+
}
|
|
481
|
+
case "record_lesson": {
|
|
482
|
+
const entry = input;
|
|
483
|
+
await recordLesson(root, entry);
|
|
484
|
+
return { tool: toolName, ok: true, output: { recorded: true, source: entry.source, context: entry.context } };
|
|
485
|
+
}
|
|
486
|
+
case "call_swarm": {
|
|
487
|
+
const callInput = input;
|
|
488
|
+
const output = await callSwarmImpl(root, callInput);
|
|
489
|
+
return { tool: toolName, ok: output.status !== "failed", output };
|
|
490
|
+
}
|
|
491
|
+
case "load_skill": {
|
|
492
|
+
const result = await loadSkillTool(input, {});
|
|
493
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
494
|
+
}
|
|
495
|
+
case "schedule": {
|
|
496
|
+
const schedInput = input;
|
|
497
|
+
const { operation } = schedInput;
|
|
498
|
+
switch (operation) {
|
|
499
|
+
case "create_cron": {
|
|
500
|
+
if (!schedInput.id || !schedInput.cronExpr || !schedInput.command) {
|
|
501
|
+
return { tool: toolName, ok: false, output: { error: `"schedule" "create_cron" requires fields: "id", "cronExpr", "command"` } };
|
|
502
|
+
}
|
|
503
|
+
const result = await scheduleCron(schedInput.id, schedInput.cronExpr, schedInput.command);
|
|
504
|
+
return { tool: toolName, ok: true, output: result };
|
|
505
|
+
}
|
|
506
|
+
case "create_once": {
|
|
507
|
+
if (schedInput.delaySeconds === undefined || !schedInput.command) {
|
|
508
|
+
return { tool: toolName, ok: false, output: { error: `"schedule" "create_once" requires fields: "delaySeconds", "command"` } };
|
|
509
|
+
}
|
|
510
|
+
const result = await scheduleOnce(schedInput.delaySeconds, schedInput.command);
|
|
511
|
+
return { tool: toolName, ok: true, output: result };
|
|
512
|
+
}
|
|
513
|
+
case "list": {
|
|
514
|
+
const result = await listScheduled();
|
|
515
|
+
return { tool: toolName, ok: true, output: result };
|
|
516
|
+
}
|
|
517
|
+
case "remove": {
|
|
518
|
+
if (!schedInput.id) {
|
|
519
|
+
return { tool: toolName, ok: false, output: { error: `"schedule" "remove" requires field: "id"` } };
|
|
520
|
+
}
|
|
521
|
+
const result = await removeScheduled(schedInput.id);
|
|
522
|
+
return { tool: toolName, ok: true, output: result };
|
|
523
|
+
}
|
|
524
|
+
default:
|
|
525
|
+
return { tool: toolName, ok: false, output: { error: `unknown schedule operation "${operation}". Expected: create_cron, create_once, list, remove.` } };
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
case "site_crawler": {
|
|
529
|
+
const { url, maxPages, maxDepth, format } = input;
|
|
530
|
+
const sitemap = await crawlSiteMap(url, { maxPages, maxDepth });
|
|
531
|
+
if (format === "tree") {
|
|
532
|
+
const tree = formatSiteMap(sitemap);
|
|
533
|
+
return { tool: toolName, ok: true, output: tree };
|
|
534
|
+
}
|
|
535
|
+
return { tool: toolName, ok: true, output: sitemap };
|
|
536
|
+
}
|
|
537
|
+
case "read_outline": {
|
|
538
|
+
const { path } = input;
|
|
539
|
+
const result = await readOutlineTool(root, path);
|
|
540
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
541
|
+
}
|
|
542
|
+
case "read_multiple_files": {
|
|
543
|
+
const result = await readMultipleFilesTool(root, input);
|
|
544
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
545
|
+
}
|
|
546
|
+
case "read_full_file": {
|
|
547
|
+
const { path, allowLarge } = input;
|
|
548
|
+
const result = await readFullFileTool(root, path, allowLarge === true);
|
|
549
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
550
|
+
}
|
|
551
|
+
case "search_ast": {
|
|
552
|
+
const result = await searchAstTool(root, input);
|
|
553
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
554
|
+
}
|
|
555
|
+
case "get_dependency_graph": {
|
|
556
|
+
const { path } = input;
|
|
557
|
+
const result = await getDependencyGraphTool(root, path);
|
|
558
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
559
|
+
}
|
|
560
|
+
case "git_diff": {
|
|
561
|
+
const result = await gitDiffTool(root, input);
|
|
562
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
563
|
+
}
|
|
564
|
+
case "git_log": {
|
|
565
|
+
const result = await gitLogTool(root, input);
|
|
566
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
567
|
+
}
|
|
568
|
+
case "line_patch": {
|
|
569
|
+
const result = await linePatchTool(root, input, ctx);
|
|
570
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
571
|
+
}
|
|
572
|
+
case "apply_unified_diff": {
|
|
573
|
+
const result = await applyUnifiedDiffTool(root, input, ctx);
|
|
574
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
575
|
+
}
|
|
576
|
+
case "update_function": {
|
|
577
|
+
const result = await updateFunctionTool(root, input, ctx);
|
|
578
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
579
|
+
}
|
|
580
|
+
case "rename_symbol": {
|
|
581
|
+
const result = await renameSymbolTool(root, input, ctx);
|
|
582
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
583
|
+
}
|
|
584
|
+
case "validate_file": {
|
|
585
|
+
const { path, lang } = input;
|
|
586
|
+
const result = await validateFileTool(root, path, lang);
|
|
587
|
+
return { tool: toolName, ok: result.ok, output: result };
|
|
588
|
+
}
|
|
589
|
+
default:
|
|
590
|
+
return { tool: toolName, ok: false, output: { error: `unknown tool "${toolName}"` } };
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
catch (e) {
|
|
594
|
+
return { tool: toolName, ok: false, output: { error: `tool threw unexpectedly: ${e.message}` } };
|
|
595
|
+
}
|
|
596
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type ValidateFileResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
result: {
|
|
4
|
+
passed: boolean;
|
|
5
|
+
command: string;
|
|
6
|
+
tool: string;
|
|
7
|
+
errors?: string[];
|
|
8
|
+
tookMs: number;
|
|
9
|
+
};
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
code: "file_not_found" | "no_checker_available" | "workspace_escape";
|
|
13
|
+
error: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* validate_file (AC-17): post-edit syntax/type check on JUST the patched
|
|
17
|
+
* file. Prefers the workspace's own detected `typecheck`/`lint` commands,
|
|
18
|
+
* then fast per-language syntax fallbacks (node --check, py_compile, JSON
|
|
19
|
+
* parse). Returns ONLY error lines — never the file body. Like every tool,
|
|
20
|
+
* it never throws; uncheckable languages return `no_checker_available` with
|
|
21
|
+
* a fallback suggestion.
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateFileTool(root: string, relPath: string, lang?: string): Promise<ValidateFileResult>;
|