xcoder-dna 0.0.0-stage → 1.3.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 +66 -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 +39 -4
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { spawn, execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
const execFileP = promisify(execFile);
|
|
4
|
+
const MARKER_PREFIX = "# xcoder-schedule:";
|
|
5
|
+
const WIN_TASK_PREFIX = "xcoder_"; // schtasks task names: keep it simple/safe, no spaces or special chars
|
|
6
|
+
const isWindows = process.platform === "win32";
|
|
7
|
+
// ─── POSIX (cron) implementation ────────────────────────────────────────────
|
|
8
|
+
async function readCrontab() {
|
|
9
|
+
try {
|
|
10
|
+
const { stdout } = await execFileP("crontab", ["-l"]);
|
|
11
|
+
return stdout;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return ""; // no crontab yet for this user
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function writeCrontab(content) {
|
|
18
|
+
await new Promise((resolve, reject) => {
|
|
19
|
+
const child = spawn("crontab", ["-"]);
|
|
20
|
+
child.stdin.write(content);
|
|
21
|
+
child.stdin.end();
|
|
22
|
+
child.on("close", (code) => (code === 0 ? resolve() : reject(new Error(`crontab write failed (exit ${code})`))));
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
async function scheduleCronPosix(id, cronExpr, command) {
|
|
26
|
+
const current = await readCrontab();
|
|
27
|
+
const line = `${MARKER_PREFIX}${id}\n${cronExpr} ${command}\n`;
|
|
28
|
+
await writeCrontab(current + (current.endsWith("\n") || current === "" ? "" : "\n") + line);
|
|
29
|
+
return { id, cronExpr };
|
|
30
|
+
}
|
|
31
|
+
async function listScheduledPosix() {
|
|
32
|
+
const content = await readCrontab();
|
|
33
|
+
const lines = content.split("\n");
|
|
34
|
+
const jobs = [];
|
|
35
|
+
for (let i = 0; i < lines.length; i++) {
|
|
36
|
+
if (lines[i].startsWith(MARKER_PREFIX)) {
|
|
37
|
+
const id = lines[i].slice(MARKER_PREFIX.length);
|
|
38
|
+
const jobLine = lines[i + 1] ?? "";
|
|
39
|
+
const match = jobLine.match(/^(\S+\s+\S+\s+\S+\s+\S+\s+\S+)\s+(.*)$/);
|
|
40
|
+
if (match)
|
|
41
|
+
jobs.push({ id, cronExpr: match[1], command: match[2] });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return jobs;
|
|
45
|
+
}
|
|
46
|
+
async function removeScheduledPosix(id) {
|
|
47
|
+
const content = await readCrontab();
|
|
48
|
+
const lines = content.split("\n");
|
|
49
|
+
const out = [];
|
|
50
|
+
let skipNext = false;
|
|
51
|
+
let removed = false;
|
|
52
|
+
for (const line of lines) {
|
|
53
|
+
if (skipNext) {
|
|
54
|
+
skipNext = false;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (line === `${MARKER_PREFIX}${id}`) {
|
|
58
|
+
skipNext = true;
|
|
59
|
+
removed = true;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
out.push(line);
|
|
63
|
+
}
|
|
64
|
+
await writeCrontab(out.join("\n"));
|
|
65
|
+
return { removed };
|
|
66
|
+
}
|
|
67
|
+
function cronToSchtasks(cronExpr) {
|
|
68
|
+
const parts = cronExpr.trim().split(/\s+/);
|
|
69
|
+
if (parts.length !== 5) {
|
|
70
|
+
throw new Error(`Cron expression "${cronExpr}" doesn't have 5 fields — can't translate to Windows Task Scheduler.`);
|
|
71
|
+
}
|
|
72
|
+
const [min, hour, dom, month, dow] = parts;
|
|
73
|
+
// Every N minutes: "*/N * * * *"
|
|
74
|
+
const everyNMinutes = min.match(/^\*\/(\d+)$/);
|
|
75
|
+
if (everyNMinutes && hour === "*" && dom === "*" && month === "*" && dow === "*") {
|
|
76
|
+
return { sc: "MINUTE", extraArgs: ["/MO", everyNMinutes[1]] };
|
|
77
|
+
}
|
|
78
|
+
// Every N hours at minute M: "M */N * * *"
|
|
79
|
+
const everyNHours = hour.match(/^\*\/(\d+)$/);
|
|
80
|
+
if (/^\d+$/.test(min) && everyNHours && dom === "*" && month === "*" && dow === "*") {
|
|
81
|
+
return { sc: "HOURLY", extraArgs: ["/MO", everyNHours[1]] };
|
|
82
|
+
}
|
|
83
|
+
// Daily at a fixed time: "M H * * *"
|
|
84
|
+
if (/^\d+$/.test(min) && /^\d+$/.test(hour) && dom === "*" && month === "*" && dow === "*") {
|
|
85
|
+
return { sc: "DAILY", extraArgs: ["/ST", `${hour.padStart(2, "0")}:${min.padStart(2, "0")}`] };
|
|
86
|
+
}
|
|
87
|
+
// Weekly on a specific day at a fixed time: "M H * * D" (D = 0-6, Sun-Sat)
|
|
88
|
+
if (/^\d+$/.test(min) && /^\d+$/.test(hour) && dom === "*" && month === "*" && /^[0-6]$/.test(dow)) {
|
|
89
|
+
const days = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
|
|
90
|
+
return {
|
|
91
|
+
sc: "WEEKLY",
|
|
92
|
+
extraArgs: ["/D", days[Number(dow)], "/ST", `${hour.padStart(2, "0")}:${min.padStart(2, "0")}`],
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// Monthly on a specific day-of-month at a fixed time: "M H D * *"
|
|
96
|
+
if (/^\d+$/.test(min) && /^\d+$/.test(hour) && /^\d+$/.test(dom) && month === "*" && dow === "*") {
|
|
97
|
+
return {
|
|
98
|
+
sc: "MONTHLY",
|
|
99
|
+
extraArgs: ["/D", dom, "/ST", `${hour.padStart(2, "0")}:${min.padStart(2, "0")}`],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
throw new Error(`Cron expression "${cronExpr}" isn't one of the patterns translated to Windows Task Scheduler ` +
|
|
103
|
+
`(supported: "*/N * * * *", "M */N * * *", "M H * * *", "M H * * D", "M H D * *"). ` +
|
|
104
|
+
`Run this under WSL for full cron syntax support instead.`);
|
|
105
|
+
}
|
|
106
|
+
function winTaskName(id) {
|
|
107
|
+
return `${WIN_TASK_PREFIX}${id.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
108
|
+
}
|
|
109
|
+
async function scheduleCronWin(id, cronExpr, command) {
|
|
110
|
+
const { sc, extraArgs } = cronToSchtasks(cronExpr);
|
|
111
|
+
const taskName = winTaskName(id);
|
|
112
|
+
// /TR wraps the command in a PowerShell invocation so the same command strings work as they
|
|
113
|
+
// would under `run_command_tool` on this same host.
|
|
114
|
+
const tr = `powershell.exe -NoProfile -NonInteractive -Command "${command.replace(/"/g, '\\"')}"`;
|
|
115
|
+
await execFileP("schtasks", ["/Create", "/F", "/TN", taskName, "/SC", sc, ...extraArgs, "/TR", tr]);
|
|
116
|
+
return { id, cronExpr };
|
|
117
|
+
}
|
|
118
|
+
async function listScheduledWin() {
|
|
119
|
+
try {
|
|
120
|
+
const { stdout } = await execFileP("schtasks", ["/Query", "/FO", "CSV", "/V"]);
|
|
121
|
+
const lines = stdout.split("\n").filter(Boolean);
|
|
122
|
+
if (lines.length < 2)
|
|
123
|
+
return [];
|
|
124
|
+
const header = parseCsvLine(lines[0]);
|
|
125
|
+
const taskNameIdx = header.indexOf("TaskName");
|
|
126
|
+
const scheduleIdx = header.indexOf("Schedule Type");
|
|
127
|
+
const nextRunIdx = header.indexOf("Next Run Time");
|
|
128
|
+
const jobs = [];
|
|
129
|
+
for (const line of lines.slice(1)) {
|
|
130
|
+
const cols = parseCsvLine(line);
|
|
131
|
+
const taskPath = cols[taskNameIdx] ?? "";
|
|
132
|
+
const shortName = taskPath.split("\\").pop() ?? "";
|
|
133
|
+
if (!shortName.startsWith(WIN_TASK_PREFIX))
|
|
134
|
+
continue;
|
|
135
|
+
const id = shortName.slice(WIN_TASK_PREFIX.length);
|
|
136
|
+
jobs.push({
|
|
137
|
+
id,
|
|
138
|
+
cronExpr: cols[scheduleIdx] ?? "unknown",
|
|
139
|
+
command: `(see: schtasks /Query /TN "${taskPath}" /V /FO LIST — next run: ${cols[nextRunIdx] ?? "unknown"})`,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
return jobs;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function parseCsvLine(line) {
|
|
149
|
+
// schtasks' CSV output is simple enough (no embedded commas within quoted values we care
|
|
150
|
+
// about parsing) that a basic quoted-field split covers it.
|
|
151
|
+
return line.split(",").map((c) => c.replace(/^"|"$/g, "").trim());
|
|
152
|
+
}
|
|
153
|
+
async function removeScheduledWin(id) {
|
|
154
|
+
try {
|
|
155
|
+
await execFileP("schtasks", ["/Delete", "/F", "/TN", winTaskName(id)]);
|
|
156
|
+
return { removed: true };
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return { removed: false };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// ─── Public API (dispatches to the right platform implementation) ──────────
|
|
163
|
+
/** Registers a recurring job: cron on POSIX, a translated Windows Task Scheduler task on
|
|
164
|
+
* win32, tagged with an id for later listing/removal. */
|
|
165
|
+
export async function scheduleCron(id, cronExpr, command) {
|
|
166
|
+
return isWindows ? scheduleCronWin(id, cronExpr, command) : scheduleCronPosix(id, cronExpr, command);
|
|
167
|
+
}
|
|
168
|
+
/** Schedules a one-off command to run after `delaySeconds`, surviving beyond the current process. */
|
|
169
|
+
export async function scheduleOnce(delaySeconds, command) {
|
|
170
|
+
const child = isWindows
|
|
171
|
+
? spawn("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", `Start-Sleep -Seconds ${delaySeconds}; ${command}`], { detached: true, stdio: "ignore", windowsHide: true })
|
|
172
|
+
: spawn("bash", ["-c", `sleep ${delaySeconds} && ${command}`], { detached: true, stdio: "ignore" });
|
|
173
|
+
child.unref();
|
|
174
|
+
return { scheduledFor: new Date(Date.now() + delaySeconds * 1000).toISOString() };
|
|
175
|
+
}
|
|
176
|
+
export async function listScheduled() {
|
|
177
|
+
return isWindows ? listScheduledWin() : listScheduledPosix();
|
|
178
|
+
}
|
|
179
|
+
export async function removeScheduled(id) {
|
|
180
|
+
return isWindows ? removeScheduledWin(id) : removeScheduledPosix(id);
|
|
181
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { WorkspaceIndex } from "./workspace-index.js";
|
|
2
|
+
export interface GlobResult {
|
|
3
|
+
ok: true;
|
|
4
|
+
matches: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function indexGlobTool(index: WorkspaceIndex, pattern: string, limit?: number): GlobResult;
|
|
7
|
+
export interface GrepMatch {
|
|
8
|
+
relPath: string;
|
|
9
|
+
line: number;
|
|
10
|
+
text: string;
|
|
11
|
+
}
|
|
12
|
+
export interface GrepResult {
|
|
13
|
+
ok: true;
|
|
14
|
+
matches: GrepMatch[];
|
|
15
|
+
truncated: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Content search across every indexed text file. Bounded by both a
|
|
19
|
+
* per-file size guard (the index already excludes anything over 5MB) and
|
|
20
|
+
* an overall match cap, so a broad pattern against a large repo returns
|
|
21
|
+
* a useful sample rather than flooding the model's context.
|
|
22
|
+
*/
|
|
23
|
+
export declare function indexGrepTool(root: string, index: WorkspaceIndex, pattern: string, opts?: {
|
|
24
|
+
pathGlob?: string;
|
|
25
|
+
caseSensitive?: boolean;
|
|
26
|
+
limit?: number;
|
|
27
|
+
}): Promise<GrepResult>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// xcoder:version 2 | xcoder:task task-456d3f | xcoder:updated 2026-08-03T15:41:32.148Z | xcoder:subtask code-st-97a4d4
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { toPosixPath } from "./workspace-index.js";
|
|
5
|
+
/** Minimal glob → RegExp: supports `**`, `*`, `?`. No external dependency needed for this scope. */
|
|
6
|
+
function globToRegExp(pattern) {
|
|
7
|
+
let re = "";
|
|
8
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
9
|
+
const c = pattern[i];
|
|
10
|
+
if (c === "*") {
|
|
11
|
+
if (pattern[i + 1] === "*") {
|
|
12
|
+
re += ".*";
|
|
13
|
+
i++;
|
|
14
|
+
if (pattern[i + 1] === "/")
|
|
15
|
+
i++; // swallow the following slash, `**/` matches zero-or-more dirs
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
re += "[^/]*";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
else if (c === "?") {
|
|
22
|
+
re += "[^/]";
|
|
23
|
+
}
|
|
24
|
+
else if (".+^${}()|[]\\".includes(c)) {
|
|
25
|
+
re += "\\" + c;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
re += c;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return new RegExp(`^${re}$`);
|
|
32
|
+
}
|
|
33
|
+
export function indexGlobTool(index, pattern, limit = 200) {
|
|
34
|
+
const re = globToRegExp(toPosixPath(pattern));
|
|
35
|
+
const matches = index.entries.map((e) => e.relPath).filter((p) => re.test(p)).slice(0, limit);
|
|
36
|
+
return { ok: true, matches };
|
|
37
|
+
}
|
|
38
|
+
const BINARY_LOOKING = /\.(png|jpg|jpeg|gif|webp|ico|pdf|zip|tar|gz|woff2?|ttf|eot|mp4|mov|exe|dll|so|bin)$/i;
|
|
39
|
+
/**
|
|
40
|
+
* Content search across every indexed text file. Bounded by both a
|
|
41
|
+
* per-file size guard (the index already excludes anything over 5MB) and
|
|
42
|
+
* an overall match cap, so a broad pattern against a large repo returns
|
|
43
|
+
* a useful sample rather than flooding the model's context.
|
|
44
|
+
*/
|
|
45
|
+
export async function indexGrepTool(root, index, pattern, opts = {}) {
|
|
46
|
+
const limit = opts.limit ?? 100;
|
|
47
|
+
const flags = opts.caseSensitive ? "g" : "gi";
|
|
48
|
+
let re;
|
|
49
|
+
try {
|
|
50
|
+
re = new RegExp(pattern, flags);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
re = new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), flags);
|
|
54
|
+
}
|
|
55
|
+
const candidates = index.entries.filter((e) => !BINARY_LOOKING.test(e.relPath));
|
|
56
|
+
const filtered = opts.pathGlob
|
|
57
|
+
? candidates.filter((e) => globToRegExp(toPosixPath(opts.pathGlob)).test(e.relPath))
|
|
58
|
+
: candidates;
|
|
59
|
+
const matches = [];
|
|
60
|
+
for (const entry of filtered) {
|
|
61
|
+
if (matches.length >= limit)
|
|
62
|
+
break;
|
|
63
|
+
try {
|
|
64
|
+
const content = await fs.readFile(path.join(root, entry.relPath), "utf8");
|
|
65
|
+
const lines = content.split("\n");
|
|
66
|
+
for (let i = 0; i < lines.length && matches.length < limit; i++) {
|
|
67
|
+
re.lastIndex = 0;
|
|
68
|
+
if (re.test(lines[i])) {
|
|
69
|
+
matches.push({ relPath: entry.relPath, line: i + 1, text: lines[i].trim().slice(0, 300) });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
continue; // unreadable/binary — skip
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return { ok: true, matches, truncated: matches.length >= limit };
|
|
78
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export interface SedToolInput {
|
|
2
|
+
/** Single file path, workspace-relative. */
|
|
3
|
+
path?: string;
|
|
4
|
+
/** Glob pattern resolved against the workspace index. */
|
|
5
|
+
glob?: string;
|
|
6
|
+
operation: "substitute" | "delete" | "deleteRange" | "insert" | "appendAfter";
|
|
7
|
+
/** Regex pattern (for substitute, delete, appendAfter). */
|
|
8
|
+
pattern?: string;
|
|
9
|
+
/** Replacement string for substitute. Supports $1, $2, $& back-references. */
|
|
10
|
+
replacement?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Regex flags. Whitelist: g, i, m, s only.
|
|
13
|
+
* - g: global (replace all matches)
|
|
14
|
+
* - i: case-insensitive
|
|
15
|
+
* - m: multiline (^/$ match line boundaries)
|
|
16
|
+
* - s: dotall (. matches \n)
|
|
17
|
+
*/
|
|
18
|
+
flags?: string;
|
|
19
|
+
/** 1-indexed inclusive start line for deleteRange. Must be >= 1. */
|
|
20
|
+
startLine?: number;
|
|
21
|
+
/** 1-indexed inclusive end line for deleteRange. Must be >= startLine. */
|
|
22
|
+
endLine?: number;
|
|
23
|
+
/** The line of text to insert/append. */
|
|
24
|
+
text?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Line number to insert after (insert only).
|
|
27
|
+
* 0 = insert at the very beginning (before line 1).
|
|
28
|
+
* N = insert after line N.
|
|
29
|
+
* If afterLine exceeds the file's line count, text is appended at end.
|
|
30
|
+
*/
|
|
31
|
+
afterLine?: number;
|
|
32
|
+
/**
|
|
33
|
+
* When true: apply transformation, return the would-be output in the result,
|
|
34
|
+
* but DO NOT write to disk. Default: false (write to disk).
|
|
35
|
+
*/
|
|
36
|
+
dryRun?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface SedFileResult {
|
|
39
|
+
/** Workspace-relative path of the file that was (or would be) modified. */
|
|
40
|
+
relPath: string;
|
|
41
|
+
/** True if the operation actually changed the file content. */
|
|
42
|
+
matched: boolean;
|
|
43
|
+
/** Number of changes made. */
|
|
44
|
+
changes: number;
|
|
45
|
+
/**
|
|
46
|
+
* The full transformed file content.
|
|
47
|
+
* Present ONLY when `dryRun: true`. Not included in write-mode responses.
|
|
48
|
+
*/
|
|
49
|
+
output?: string;
|
|
50
|
+
}
|
|
51
|
+
export type SedToolResult = {
|
|
52
|
+
ok: true;
|
|
53
|
+
results: SedFileResult[];
|
|
54
|
+
} | {
|
|
55
|
+
ok: false;
|
|
56
|
+
code: "file_not_found" | "workspace_escape" | "invalid_regex" | "invalid_operation" | "no_target" | "io_error";
|
|
57
|
+
error: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Perform stream-editing operations on workspace files.
|
|
61
|
+
* Supports substitute, delete, deleteRange, insert, and appendAfter operations.
|
|
62
|
+
*/
|
|
63
|
+
export declare function sedTool(root: string, input: SedToolInput, ctx?: {
|
|
64
|
+
taskId: string;
|
|
65
|
+
subtaskId: string;
|
|
66
|
+
}): Promise<SedToolResult>;
|