@webpresso/agent-kit 3.1.30 → 3.2.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.
Potentially problematic release.
This version of @webpresso/agent-kit might be problematic. Click here for more details.
- package/README.md +53 -15
- package/bin/_run.js +179 -19
- package/catalog/AGENTS.md.tpl +3 -3
- package/catalog/agent/agents/implementer.md +45 -0
- package/catalog/agent/rules/parallel-orchestration-quota.md +100 -0
- package/catalog/agent/rules/pre-implementation.md +28 -1
- package/catalog/agent/rules/supported-agent-clis.md +9 -0
- package/catalog/agent/rules/typescript-version.md +50 -0
- package/catalog/agent/skills/codex/SKILL.md +25 -1
- package/catalog/agent/skills/verify/SKILL.md +4 -2
- package/catalog/docs/templates/blueprint.md +1 -1
- package/dist/esm/audit/agents.js +1 -0
- package/dist/esm/audit/blueprint-lifecycle-sql.d.ts +12 -0
- package/dist/esm/audit/blueprint-lifecycle-sql.js +23 -2
- package/dist/esm/audit/blueprint-pr-coverage.js +4 -0
- package/dist/esm/audit/ci-guardrails-wiring.d.ts +22 -0
- package/dist/esm/audit/ci-guardrails-wiring.js +90 -0
- package/dist/esm/audit/ci-test-perf.js +30 -0
- package/dist/esm/audit/command-surface.js +4 -2
- package/dist/esm/audit/host-substitution-risk.d.ts +2 -0
- package/dist/esm/audit/host-substitution-risk.js +256 -0
- package/dist/esm/audit/registry.d.ts +4 -4
- package/dist/esm/audit/registry.js +8 -1
- package/dist/esm/audit/toolchain-isolation.js +1 -2
- package/dist/esm/audit/typescript-version.d.ts +2 -0
- package/dist/esm/audit/typescript-version.js +123 -0
- package/dist/esm/blueprint/core/parser.js +43 -1
- package/dist/esm/blueprint/core/validation/criteria.d.ts +14 -0
- package/dist/esm/blueprint/core/validation/criteria.js +41 -2
- package/dist/esm/blueprint/core/validation/state.js +25 -14
- package/dist/esm/blueprint/db/migrations/run.js +4 -2
- package/dist/esm/blueprint/lifecycle/audit.d.ts +20 -0
- package/dist/esm/blueprint/lifecycle/audit.js +65 -10
- package/dist/esm/blueprint/lifecycle/canonicalize.d.ts +6 -0
- package/dist/esm/blueprint/lifecycle/canonicalize.js +135 -0
- package/dist/esm/blueprint/lifecycle/local.d.ts +2 -1
- package/dist/esm/blueprint/lifecycle/local.js +19 -3
- package/dist/esm/blueprint/lifecycle/review-provenance.js +36 -11
- package/dist/esm/blueprint/service/BlueprintCreationService.d.ts +1 -0
- package/dist/esm/blueprint/service/BlueprintCreationService.js +53 -4
- package/dist/esm/blueprint/service/blueprint-tech-debt-links.js +16 -2
- package/dist/esm/blueprint/trust/command-runner.d.ts +26 -0
- package/dist/esm/blueprint/trust/command-runner.js +148 -0
- package/dist/esm/blueprint/trust/gates.d.ts +7 -0
- package/dist/esm/blueprint/trust/gates.js +20 -0
- package/dist/esm/blueprint/trust/promotion.d.ts +8 -0
- package/dist/esm/blueprint/trust/promotion.js +62 -112
- package/dist/esm/blueprint/trust/scaffold.d.ts +19 -0
- package/dist/esm/blueprint/trust/scaffold.js +64 -0
- package/dist/esm/blueprint/trust/validator.d.ts +1 -0
- package/dist/esm/blueprint/trust/validator.js +7 -1
- package/dist/esm/blueprint/utils/archive.js +27 -5
- package/dist/esm/blueprint/utils/document-paths.d.ts +18 -0
- package/dist/esm/blueprint/utils/document-paths.js +45 -12
- package/dist/esm/build/cli-mcp-parity.js +10 -0
- package/dist/esm/cli/bundle/commands/blueprint.d.ts +1 -0
- package/dist/esm/cli/bundle/commands/blueprint.js +1 -0
- package/dist/esm/cli/cli.d.ts +1 -1
- package/dist/esm/cli/cli.js +34 -0
- package/dist/esm/cli/commands/agent-launch.d.ts +6 -1
- package/dist/esm/cli/commands/agent-launch.js +82 -4
- package/dist/esm/cli/commands/audit-core.d.ts +1 -1
- package/dist/esm/cli/commands/audit-core.js +8 -1
- package/dist/esm/cli/commands/audit.js +17 -5
- package/dist/esm/cli/commands/blueprint/execution.js +18 -6
- package/dist/esm/cli/commands/blueprint/mutations.js +59 -40
- package/dist/esm/cli/commands/blueprint/router-dispatch.d.ts +2 -1
- package/dist/esm/cli/commands/blueprint/router-dispatch.js +20 -1
- package/dist/esm/cli/commands/blueprint/router-output.d.ts +21 -0
- package/dist/esm/cli/commands/blueprint/router-output.js +48 -17
- package/dist/esm/cli/commands/blueprint/router.d.ts +7 -0
- package/dist/esm/cli/commands/blueprint/router.js +13 -1
- package/dist/esm/cli/commands/ci-preflight.d.ts +13 -2
- package/dist/esm/cli/commands/ci-preflight.js +6 -3
- package/dist/esm/cli/commands/compile.js +5 -31
- package/dist/esm/cli/commands/dash/delivery-status.d.ts +1 -0
- package/dist/esm/cli/commands/dash/delivery-status.js +11 -4
- package/dist/esm/cli/commands/doctor.js +5 -0
- package/dist/esm/cli/commands/hook.d.ts +5 -0
- package/dist/esm/cli/commands/hook.js +15 -9
- package/dist/esm/cli/commands/init/config.js +2 -2
- package/dist/esm/cli/commands/init/convergence-apply.d.ts +24 -0
- package/dist/esm/cli/commands/init/convergence-apply.js +221 -0
- package/dist/esm/cli/commands/init/convergence-state.d.ts +13 -0
- package/dist/esm/cli/commands/init/convergence-state.js +54 -0
- package/dist/esm/cli/commands/init/convergence.d.ts +23 -0
- package/dist/esm/cli/commands/init/convergence.js +57 -0
- package/dist/esm/cli/commands/init/git-convergence.d.ts +19 -0
- package/dist/esm/cli/commands/init/git-convergence.js +168 -0
- package/dist/esm/cli/commands/init/gitignore-patcher.js +2 -0
- package/dist/esm/cli/commands/init/grok-privacy-smoke.d.ts +52 -0
- package/dist/esm/cli/commands/init/grok-privacy-smoke.js +91 -0
- package/dist/esm/cli/commands/init/host-native-proof.d.ts +18 -0
- package/dist/esm/cli/commands/init/host-native-proof.js +88 -0
- package/dist/esm/cli/commands/init/host-visibility.d.ts +2 -2
- package/dist/esm/cli/commands/init/host-visibility.js +94 -5
- package/dist/esm/cli/commands/init/index.d.ts +1 -0
- package/dist/esm/cli/commands/init/index.js +326 -173
- package/dist/esm/cli/commands/init/mcp-spec.d.ts +57 -0
- package/dist/esm/cli/commands/init/mcp-spec.js +273 -0
- package/dist/esm/cli/commands/init/merge.d.ts +1 -0
- package/dist/esm/cli/commands/init/merge.js +30 -1
- package/dist/esm/cli/commands/init/plugin-cache-prune.d.ts +0 -3
- package/dist/esm/cli/commands/init/plugin-cache-prune.js +0 -1
- package/dist/esm/cli/commands/init/scaffold-agents-md.d.ts +1 -1
- package/dist/esm/cli/commands/init/scaffold-agents-md.js +9 -3
- package/dist/esm/cli/commands/init/scaffold-base-kit.d.ts +11 -0
- package/dist/esm/cli/commands/init/scaffold-base-kit.js +56 -1
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/grok.d.ts +14 -8
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/grok.js +41 -24
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.d.ts +2 -0
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.js +51 -23
- package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.d.ts +12 -31
- package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.js +288 -202
- package/dist/esm/cli/commands/init/scaffolders/file-transaction.d.ts +7 -0
- package/dist/esm/cli/commands/init/scaffolders/file-transaction.js +58 -0
- package/dist/esm/cli/commands/init/scaffolders/grok-mcp/index.d.ts +38 -0
- package/dist/esm/cli/commands/init/scaffolders/grok-mcp/index.js +73 -0
- package/dist/esm/cli/commands/init/scaffolders/opencode-plugin/index.d.ts +21 -0
- package/dist/esm/cli/commands/init/scaffolders/opencode-plugin/index.js +559 -63
- package/dist/esm/cli/commands/init/untracked-collision.d.ts +14 -0
- package/dist/esm/cli/commands/init/untracked-collision.js +42 -0
- package/dist/esm/cli/commands/opencode-rotate.d.ts +49 -0
- package/dist/esm/cli/commands/opencode-rotate.js +135 -0
- package/dist/esm/cli/commands/public-readiness.d.ts +11 -0
- package/dist/esm/cli/commands/public-readiness.js +42 -0
- package/dist/esm/cli/commands/review.d.ts +35 -3
- package/dist/esm/cli/commands/review.js +729 -209
- package/dist/esm/cli/commands/run-wait.d.ts +2 -0
- package/dist/esm/cli/commands/run-wait.js +122 -0
- package/dist/esm/cli/commands/setup-help.js +1 -1
- package/dist/esm/cli/commands/setup-repair-help.js +1 -1
- package/dist/esm/cli/commands/worktree/router-dispatch.js +13 -8
- package/dist/esm/cli/direct-provider-launch.js +9 -5
- package/dist/esm/cli/optional-tool-freshness.d.ts +27 -0
- package/dist/esm/cli/optional-tool-freshness.js +219 -9
- package/dist/esm/daemon/domains/git-actions.d.ts +29 -0
- package/dist/esm/daemon/domains/git-actions.js +136 -0
- package/dist/esm/daemon/domains/run-registry-interop.d.ts +16 -0
- package/dist/esm/daemon/domains/run-registry-interop.js +45 -0
- package/dist/esm/daemon/domains/sessions-search.d.ts +11 -0
- package/dist/esm/daemon/domains/sessions-search.js +29 -0
- package/dist/esm/daemon/handlers/blueprints-handlers.d.ts +5 -0
- package/dist/esm/daemon/handlers/blueprints-handlers.js +36 -0
- package/dist/esm/daemon/handlers/deploy-handlers.d.ts +6 -0
- package/dist/esm/daemon/handlers/deploy-handlers.js +5 -0
- package/dist/esm/daemon/handlers/fleet-handlers.d.ts +15 -0
- package/dist/esm/daemon/handlers/fleet-handlers.js +91 -0
- package/dist/esm/daemon/handlers/git-handlers.d.ts +6 -0
- package/dist/esm/daemon/handlers/git-handlers.js +27 -0
- package/dist/esm/daemon/handlers/product.d.ts +7 -0
- package/dist/esm/daemon/handlers/product.js +10 -119
- package/dist/esm/daemon/handlers/sessions-handlers.d.ts +12 -0
- package/dist/esm/daemon/handlers/sessions-handlers.js +31 -0
- package/dist/esm/daemon/handlers/shared.d.ts +5 -0
- package/dist/esm/daemon/handlers/shared.js +16 -0
- package/dist/esm/daemon/methods.d.ts +8 -1
- package/dist/esm/daemon/methods.js +7 -0
- package/dist/esm/daemon/protocol/contract.d.ts +43 -0
- package/dist/esm/daemon/protocol/contract.js +26 -0
- package/dist/esm/daemon/protocol/index.d.ts +1 -1
- package/dist/esm/daemon/protocol/index.js +1 -1
- package/dist/esm/hooks/__conformance__/matrix.d.ts +6 -0
- package/dist/esm/hooks/__conformance__/matrix.js +137 -0
- package/dist/esm/hooks/conformance/batch.js +5 -0
- package/dist/esm/hooks/doctor.d.ts +3 -3
- package/dist/esm/hooks/doctor.js +30 -15
- package/dist/esm/hooks/permission-request/index.js +9 -3
- package/dist/esm/hooks/permission-request/policy.d.ts +9 -0
- package/dist/esm/hooks/permission-request/policy.js +13 -0
- package/dist/esm/hooks/pretool-guard/dev-routing.d.ts +9 -0
- package/dist/esm/hooks/pretool-guard/dev-routing.js +41 -5
- package/dist/esm/hooks/pretool-guard/logger.d.ts +7 -0
- package/dist/esm/hooks/pretool-guard/logger.js +16 -0
- package/dist/esm/hooks/pretool-guard/runner.d.ts +6 -0
- package/dist/esm/hooks/pretool-guard/runner.js +68 -16
- package/dist/esm/hooks/pretool-guard/validators/blueprint.js +30 -10
- package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +54 -0
- package/dist/esm/hooks/pretool-guard/validators/index.d.ts +7 -0
- package/dist/esm/hooks/pretool-guard/validators/index.js +21 -0
- package/dist/esm/hooks/pretool-guard/validators/path-contract.d.ts +19 -0
- package/dist/esm/hooks/pretool-guard/validators/path-contract.js +25 -8
- package/dist/esm/hooks/shared/guard-outcome.d.ts +149 -0
- package/dist/esm/hooks/shared/guard-outcome.js +215 -0
- package/dist/esm/hooks/shared/hook-bootstrap.d.ts +26 -0
- package/dist/esm/hooks/shared/hook-bootstrap.js +64 -1
- package/dist/esm/hooks/shared/types.d.ts +8 -5
- package/dist/esm/hooks/shared/types.js +23 -8
- package/dist/esm/hooks/stop/qa-changed-files.d.ts +11 -0
- package/dist/esm/hooks/stop/qa-changed-files.js +74 -0
- package/dist/esm/mcp/blueprint/_shared/lifecycle.js +14 -1
- package/dist/esm/mcp/blueprint/handlers/document-mutations.js +78 -4
- package/dist/esm/mcp/blueprint/handlers/review-log.js +8 -1
- package/dist/esm/mcp/blueprint/handlers/task-advance.js +113 -54
- package/dist/esm/mcp/blueprint/handlers/task-verify.js +39 -19
- package/dist/esm/mcp/blueprint/registration.js +3 -2
- package/dist/esm/mcp/server.d.ts +1 -0
- package/dist/esm/mcp/server.js +27 -0
- package/dist/esm/mcp/tools/_names.d.ts +1 -1
- package/dist/esm/mcp/tools/_names.js +5 -0
- package/dist/esm/mcp/tools/_registry.js +10 -0
- package/dist/esm/mcp/tools/_shared/audit-kinds.d.ts +1 -1
- package/dist/esm/mcp/tools/_shared/result.js +44 -1
- package/dist/esm/mcp/tools/audit.d.ts +4 -1
- package/dist/esm/mcp/tools/audit.js +30 -0
- package/dist/esm/mcp/tools/audits.d.ts +3 -0
- package/dist/esm/mcp/tools/ci-preflight.d.ts +50 -0
- package/dist/esm/mcp/tools/ci-preflight.js +183 -0
- package/dist/esm/mcp/tools/pr-upsert.js +39 -1
- package/dist/esm/mcp/tools/review-run.d.ts +28 -0
- package/dist/esm/mcp/tools/review-run.js +216 -0
- package/dist/esm/mcp/tools/run-wait.d.ts +86 -0
- package/dist/esm/mcp/tools/run-wait.js +593 -0
- package/dist/esm/mcp/tools/session-id.d.ts +3 -0
- package/dist/esm/mcp/tools/session-id.js +45 -0
- package/dist/esm/mcp/tools/session-info.d.ts +3 -0
- package/dist/esm/mcp/tools/session-info.js +49 -0
- package/dist/esm/output-transforms/audit.d.ts +23 -0
- package/dist/esm/output-transforms/audit.js +47 -0
- package/dist/esm/output-transforms/index.js +2 -0
- package/dist/esm/review/authority.js +13 -5
- package/dist/esm/review/availability.d.ts +22 -0
- package/dist/esm/review/availability.js +107 -20
- package/dist/esm/review/delivery-verifier.d.ts +27 -0
- package/dist/esm/review/delivery-verifier.js +115 -0
- package/dist/esm/review/events.d.ts +3 -2
- package/dist/esm/review/events.js +23 -3
- package/dist/esm/review/execution/adapters.js +26 -9
- package/dist/esm/review/execution/output-policy.d.ts +2 -0
- package/dist/esm/review/execution/output-policy.js +12 -0
- package/dist/esm/review/execution/review-checkout.js +87 -6
- package/dist/esm/review/execution/supervisor.js +5 -0
- package/dist/esm/review/execution/types.d.ts +8 -0
- package/dist/esm/review/opencode-account.d.ts +24 -0
- package/dist/esm/review/opencode-account.js +68 -0
- package/dist/esm/review/opencode-auth.d.ts +33 -0
- package/dist/esm/review/opencode-auth.js +79 -0
- package/dist/esm/review/subject.d.ts +12 -0
- package/dist/esm/review/subject.js +74 -22
- package/dist/esm/runtime/opencode-account-materializer.d.ts +34 -0
- package/dist/esm/runtime/opencode-account-materializer.js +33 -0
- package/dist/esm/status/snapshot.js +30 -19
- package/dist/esm/test/duration-sequencer.d.ts +20 -0
- package/dist/esm/test/duration-sequencer.js +54 -0
- package/dist/esm/test/shard-durations.json +922 -0
- package/dist/esm/test/worker-budget.d.ts +6 -0
- package/dist/esm/test/worker-budget.js +59 -1
- package/dist/esm/test-helpers/global-setup.d.ts +1 -1
- package/dist/esm/test-helpers/global-setup.js +68 -24
- package/dist/esm/ultragoal/service.d.ts +7 -0
- package/dist/esm/ultragoal/service.js +42 -2
- package/dist/esm/utils/write-json-file.js +3 -1
- package/dist/esm/worktrees/codex-project-trust.d.ts +15 -0
- package/dist/esm/worktrees/codex-project-trust.js +56 -0
- package/dist/esm/worktrees/registry.d.ts +8 -0
- package/dist/esm/worktrees/registry.js +18 -3
- package/package.json +16 -13
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Daemon-side git helpers for review panel RPCs (Task 1.5).
|
|
3
3
|
* Runs real git via child_process — never re-implements porcelain.
|
|
4
|
+
*
|
|
5
|
+
* `gitCreatePr` additionally spawns `gh` (same class of utility-binary spawn
|
|
6
|
+
* as the `git` calls above — see Trust Dossier Material Decision MD1 on the
|
|
7
|
+
* desktop-daemon-rpc-completion blueprint overview for why this does not
|
|
8
|
+
* cross the daemon's "no agent-child spawn" invariant). It adapts
|
|
9
|
+
* the gh-wrapping logic from `src/mcp/tools/pr-upsert.ts` (preflight,
|
|
10
|
+
* collision detection, canonical re-fetch, output redaction) to this
|
|
11
|
+
* module's synchronous-git / injectable-deps pattern.
|
|
4
12
|
*/
|
|
5
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
+
import { runCommand, isRunFailure } from "#mcp/tools/_shared/run-command.js";
|
|
15
|
+
import { redactText } from "#mcp/tools/_shared/redact.js";
|
|
6
16
|
export function gitDiff(cwd) {
|
|
7
17
|
const out = execFileSync("git", ["status", "--porcelain=v1", "-uall", "--no-renames"], {
|
|
8
18
|
cwd,
|
|
@@ -45,3 +55,129 @@ export function gitCommit(cwd, message, paths, options) {
|
|
|
45
55
|
}).trim();
|
|
46
56
|
return { commitSha };
|
|
47
57
|
}
|
|
58
|
+
/** Same default timeoutMs `src/mcp/tools/pr-upsert.ts` already uses for `gh` calls. */
|
|
59
|
+
const GH_TIMEOUT_MS = 120_000;
|
|
60
|
+
function defaultCurrentBranch(cwd) {
|
|
61
|
+
const branch = execFileSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
62
|
+
cwd,
|
|
63
|
+
encoding: "utf8",
|
|
64
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
65
|
+
}).trim();
|
|
66
|
+
if (!branch || branch === "HEAD") {
|
|
67
|
+
throw new Error("git.createPr requires a named branch (HEAD is detached)");
|
|
68
|
+
}
|
|
69
|
+
return branch;
|
|
70
|
+
}
|
|
71
|
+
function defaultGh(args, cwd) {
|
|
72
|
+
return runCommand("gh", args, { cwd, timeoutMs: GH_TIMEOUT_MS });
|
|
73
|
+
}
|
|
74
|
+
function outcomeText(outcome) {
|
|
75
|
+
if (isRunFailure(outcome))
|
|
76
|
+
return outcome.error.message;
|
|
77
|
+
return [outcome.stdout, outcome.stderr].filter(Boolean).join("\n");
|
|
78
|
+
}
|
|
79
|
+
function outcomeOk(outcome) {
|
|
80
|
+
return !isRunFailure(outcome) && outcome.exitCode === 0;
|
|
81
|
+
}
|
|
82
|
+
function parseTarget(outcome) {
|
|
83
|
+
if (!outcomeOk(outcome))
|
|
84
|
+
return undefined;
|
|
85
|
+
try {
|
|
86
|
+
const parsed = JSON.parse(outcome.stdout);
|
|
87
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
88
|
+
return undefined;
|
|
89
|
+
const value = parsed;
|
|
90
|
+
return {
|
|
91
|
+
number: typeof value.number === "number" ? value.number : undefined,
|
|
92
|
+
url: typeof value.url === "string" ? value.url : undefined,
|
|
93
|
+
title: typeof value.title === "string" ? value.title : undefined,
|
|
94
|
+
state: typeof value.state === "string" ? value.state : undefined,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Mirrors `src/mcp/tools/pr-upsert.ts`'s `isNoPr` string-matching (do not reinvent). */
|
|
102
|
+
function isNoPr(outcome) {
|
|
103
|
+
if (outcomeOk(outcome))
|
|
104
|
+
return false;
|
|
105
|
+
const text = outcomeText(outcome).toLowerCase();
|
|
106
|
+
return (text.includes("no pull requests found") ||
|
|
107
|
+
text.includes("no pull request found") ||
|
|
108
|
+
text.includes("could not find pull request"));
|
|
109
|
+
}
|
|
110
|
+
/** Mirrors `src/mcp/tools/pr-upsert.ts`'s `isCreateCollision` string-matching (do not reinvent). */
|
|
111
|
+
function isCreateCollision(outcome) {
|
|
112
|
+
if (outcomeOk(outcome))
|
|
113
|
+
return false;
|
|
114
|
+
const text = outcomeText(outcome).toLowerCase();
|
|
115
|
+
return text.includes("already exists") || text.includes("a pull request already");
|
|
116
|
+
}
|
|
117
|
+
function throwGhFailure(action, outcome) {
|
|
118
|
+
const detail = redactText(outcomeText(outcome)) || "unknown error";
|
|
119
|
+
throw new Error(`git.createPr: gh ${action} failed: ${detail}`);
|
|
120
|
+
}
|
|
121
|
+
function requireUrl(target, context) {
|
|
122
|
+
if (!target.url) {
|
|
123
|
+
throw new Error(`git.createPr: ${context} did not return a PR url`);
|
|
124
|
+
}
|
|
125
|
+
return target.url;
|
|
126
|
+
}
|
|
127
|
+
function buildEditArgs(branch, title, body) {
|
|
128
|
+
const args = ["pr", "edit", branch, "--title", title];
|
|
129
|
+
if (body !== undefined)
|
|
130
|
+
args.push("--body", body);
|
|
131
|
+
return args;
|
|
132
|
+
}
|
|
133
|
+
function buildCreateArgs(branch, base, title, body) {
|
|
134
|
+
const args = ["pr", "create", "--head", branch, "--base", base, "--title", title];
|
|
135
|
+
if (body !== undefined)
|
|
136
|
+
args.push("--body", body);
|
|
137
|
+
return args;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Upsert semantics (the frozen daemon contract has no create/update `mode`
|
|
141
|
+
* field, see Trust Dossier MD2): edit the PR for the current branch if one
|
|
142
|
+
* already exists, else create it against the repo's default branch. Every
|
|
143
|
+
* success path re-fetches the canonical PR view rather than trusting
|
|
144
|
+
* `gh pr create`'s stdout alone (matches `src/mcp/tools/pr-upsert.ts`'s
|
|
145
|
+
* canonical-refetch pattern) so a create-collision (two callers racing)
|
|
146
|
+
* still returns the real PR instead of throwing.
|
|
147
|
+
*/
|
|
148
|
+
export async function gitCreatePr(cwd, title, body, deps) {
|
|
149
|
+
const currentBranch = deps?.currentBranch ?? defaultCurrentBranch;
|
|
150
|
+
const gh = deps?.gh ?? defaultGh;
|
|
151
|
+
const branch = currentBranch(cwd);
|
|
152
|
+
const preflight = await gh(["pr", "view", branch, "--json", "number,url,title,state"], cwd);
|
|
153
|
+
if (outcomeOk(preflight)) {
|
|
154
|
+
const target = parseTarget(preflight);
|
|
155
|
+
if (!target)
|
|
156
|
+
throwGhFailure("pr view (preflight)", preflight);
|
|
157
|
+
const edit = await gh(buildEditArgs(branch, title, body), cwd);
|
|
158
|
+
if (!outcomeOk(edit))
|
|
159
|
+
throwGhFailure("pr edit", edit);
|
|
160
|
+
return { url: requireUrl(target, "pr view (preflight)"), number: target.number };
|
|
161
|
+
}
|
|
162
|
+
if (!isNoPr(preflight))
|
|
163
|
+
throwGhFailure("pr view (preflight)", preflight);
|
|
164
|
+
const repoView = await gh(["repo", "view", "--json", "defaultBranchRef", "-q", ".defaultBranchRef.name"], cwd);
|
|
165
|
+
if (!outcomeOk(repoView))
|
|
166
|
+
throwGhFailure("repo view (default branch)", repoView);
|
|
167
|
+
const base = repoView.stdout.trim();
|
|
168
|
+
if (!base) {
|
|
169
|
+
throw new Error("git.createPr: could not resolve the repository default branch");
|
|
170
|
+
}
|
|
171
|
+
const create = await gh(buildCreateArgs(branch, base, title, body), cwd);
|
|
172
|
+
if (!outcomeOk(create) && !isCreateCollision(create)) {
|
|
173
|
+
throwGhFailure("pr create", create);
|
|
174
|
+
}
|
|
175
|
+
const canonical = await gh(["pr", "view", branch, "--json", "number,url,title,state"], cwd);
|
|
176
|
+
const canonicalTarget = parseTarget(canonical);
|
|
177
|
+
if (!canonicalTarget)
|
|
178
|
+
throwGhFailure("pr view (canonical)", canonical);
|
|
179
|
+
return {
|
|
180
|
+
url: requireUrl(canonicalTarget, "pr view (canonical)"),
|
|
181
|
+
number: canonicalTarget.number,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Cross-process run-registry interop between wp dash and the desktop app (1.6).
|
|
3
3
|
* Reuses the existing dash run-registry store paths — no second registry.
|
|
4
4
|
*/
|
|
5
|
+
import type { DashRun } from "#cli/commands/dash/run-types.js";
|
|
6
|
+
import type { SessionsListResult, SessionSummary } from "#daemon/protocol/contract.js";
|
|
5
7
|
export type RunRegistrySnapshot = {
|
|
6
8
|
readonly root: string;
|
|
7
9
|
readonly runIds: readonly string[];
|
|
@@ -12,3 +14,17 @@ export type RunRegistrySnapshot = {
|
|
|
12
14
|
* `root` should be the directory that contains per-run JSON sidecars.
|
|
13
15
|
*/
|
|
14
16
|
export declare function listRunRegistry(root: string): RunRegistrySnapshot;
|
|
17
|
+
/** Pure mapping from a dash run to the daemon's UI-facing session shape. */
|
|
18
|
+
export declare function toSessionSummary(run: DashRun): SessionSummary;
|
|
19
|
+
export interface ListDaemonSessionsOptions {
|
|
20
|
+
readonly cwd?: string;
|
|
21
|
+
readonly limit?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Daemon `sessions.list` backing implementation: reads the real dash
|
|
25
|
+
* run-registry (no second registry) and maps it to the daemon wire shape.
|
|
26
|
+
* Complexity: O(n log n) for the updatedAt-descending sort (n = dash runs at
|
|
27
|
+
* one repo root — small/bounded); no additional filesystem scans beyond the
|
|
28
|
+
* single locked registry read `readDashRuns` already performs.
|
|
29
|
+
*/
|
|
30
|
+
export declare function listDaemonSessions(options?: ListDaemonSessionsOptions): Promise<SessionsListResult>;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
6
6
|
import { join } from "node:path";
|
|
7
|
+
import { readDashRuns } from "#cli/commands/dash/run-registry.js";
|
|
7
8
|
/**
|
|
8
9
|
* List run ids under a dash-compatible registry root.
|
|
9
10
|
* `root` should be the directory that contains per-run JSON sidecars.
|
|
@@ -27,3 +28,47 @@ export function listRunRegistry(root) {
|
|
|
27
28
|
}
|
|
28
29
|
return { root, runIds: runIds.sort(), readable: true };
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Daemon `providerIdSchema` (src/daemon/protocol/contract.ts) only accepts
|
|
33
|
+
* 'claude' | 'codex' | 'opencode' | 'fleet'. `DashRun.provider` can also be
|
|
34
|
+
* 'grok' (src/cli/commands/dash/provider-capabilities.ts DASH_PROVIDERS).
|
|
35
|
+
* `parseUiMethodResult` is `.strict()` and would throw on the whole response
|
|
36
|
+
* for one out-of-enum row, so an unrecognized provider is omitted (the field
|
|
37
|
+
* is optional on `SessionSummary`) rather than passed through or fabricated.
|
|
38
|
+
*/
|
|
39
|
+
const KNOWN_DAEMON_PROVIDERS = new Set([
|
|
40
|
+
"claude",
|
|
41
|
+
"codex",
|
|
42
|
+
"opencode",
|
|
43
|
+
"fleet",
|
|
44
|
+
]);
|
|
45
|
+
function isKnownDaemonProvider(provider) {
|
|
46
|
+
return KNOWN_DAEMON_PROVIDERS.has(provider);
|
|
47
|
+
}
|
|
48
|
+
/** Pure mapping from a dash run to the daemon's UI-facing session shape. */
|
|
49
|
+
export function toSessionSummary(run) {
|
|
50
|
+
return {
|
|
51
|
+
id: run.id,
|
|
52
|
+
...(isKnownDaemonProvider(run.provider) ? { provider: run.provider } : {}),
|
|
53
|
+
label: run.label,
|
|
54
|
+
state: run.state,
|
|
55
|
+
cwd: run.cwd,
|
|
56
|
+
permissionMode: run.permissionMode,
|
|
57
|
+
updatedAt: run.updatedAt,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Daemon `sessions.list` backing implementation: reads the real dash
|
|
62
|
+
* run-registry (no second registry) and maps it to the daemon wire shape.
|
|
63
|
+
* Complexity: O(n log n) for the updatedAt-descending sort (n = dash runs at
|
|
64
|
+
* one repo root — small/bounded); no additional filesystem scans beyond the
|
|
65
|
+
* single locked registry read `readDashRuns` already performs.
|
|
66
|
+
*/
|
|
67
|
+
export async function listDaemonSessions(options = {}) {
|
|
68
|
+
const { runs } = await readDashRuns({ cwd: options.cwd });
|
|
69
|
+
const sorted = [...runs].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
70
|
+
const limited = typeof options.limit === "number" && options.limit >= 0
|
|
71
|
+
? sorted.slice(0, options.limit)
|
|
72
|
+
: sorted;
|
|
73
|
+
return { sessions: limited.map(toSessionSummary) };
|
|
74
|
+
}
|
|
@@ -18,3 +18,14 @@ export declare function searchSessions(backend: SessionSearchBackend, options: {
|
|
|
18
18
|
readonly query: string;
|
|
19
19
|
readonly limit?: number;
|
|
20
20
|
}): readonly SessionSearchHit[];
|
|
21
|
+
/**
|
|
22
|
+
* Production backend: opens the real `SessionMemoryStore` FTS index (porter
|
|
23
|
+
* → trigram → Levenshtein fallback, same engine behind `wp_session_search`)
|
|
24
|
+
* and reuses its indexed search — never a table scan. A fresh store is
|
|
25
|
+
* opened and closed per call, mirroring the exact pattern
|
|
26
|
+
* `src/mcp/tools/session-restore.ts`'s `buildRecallPayload` already uses for
|
|
27
|
+
* the identical class (avoids a stale open SQLite/WAL handle). Caching a
|
|
28
|
+
* store across daemon-lifetime calls is intentionally deferred (YAGNI) until
|
|
29
|
+
* there is evidence of per-RPC latency pressure.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createSessionMemorySearchBackend(indexDbPath: string): SessionSearchBackend;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Session search domain (Task 3.7).
|
|
3
3
|
* Pure ranking/filter helpers + injectable FTS backend (session-memory store).
|
|
4
4
|
*/
|
|
5
|
+
import { SessionMemoryStore } from "#session-memory/store.js";
|
|
5
6
|
/** Normalize and bound a search query; empty → no search. */
|
|
6
7
|
export function normalizeSearchQuery(query) {
|
|
7
8
|
return query.trim().replace(/\s+/gu, " ").slice(0, 200);
|
|
@@ -14,3 +15,31 @@ export function searchSessions(backend, options) {
|
|
|
14
15
|
const limit = Math.min(Math.max(options.limit ?? 20, 1), 100);
|
|
15
16
|
return backend.search(q, limit);
|
|
16
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Production backend: opens the real `SessionMemoryStore` FTS index (porter
|
|
20
|
+
* → trigram → Levenshtein fallback, same engine behind `wp_session_search`)
|
|
21
|
+
* and reuses its indexed search — never a table scan. A fresh store is
|
|
22
|
+
* opened and closed per call, mirroring the exact pattern
|
|
23
|
+
* `src/mcp/tools/session-restore.ts`'s `buildRecallPayload` already uses for
|
|
24
|
+
* the identical class (avoids a stale open SQLite/WAL handle). Caching a
|
|
25
|
+
* store across daemon-lifetime calls is intentionally deferred (YAGNI) until
|
|
26
|
+
* there is evidence of per-RPC latency pressure.
|
|
27
|
+
*/
|
|
28
|
+
export function createSessionMemorySearchBackend(indexDbPath) {
|
|
29
|
+
return {
|
|
30
|
+
search(query, limit) {
|
|
31
|
+
const store = new SessionMemoryStore(indexDbPath);
|
|
32
|
+
try {
|
|
33
|
+
return store.search({ query, limit }).map((hit) => ({
|
|
34
|
+
id: hit.id,
|
|
35
|
+
source: hit.source,
|
|
36
|
+
text: hit.text,
|
|
37
|
+
score: hit.score,
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
store.close();
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blueprint-domain product handlers: `blueprints.list` is a real
|
|
3
|
+
* implementation over the `blueprints/<status>/` directories; `blueprints.exec`
|
|
4
|
+
* is not implemented (exec remains CLI-owned).
|
|
5
|
+
*/
|
|
6
|
+
import { readdirSync, existsSync, statSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
function listBlueprintRows(repoRoot) {
|
|
9
|
+
const statuses = ["completed", "in-progress", "planned", "parked", "draft", "archived"];
|
|
10
|
+
const rows = [];
|
|
11
|
+
for (const status of statuses) {
|
|
12
|
+
const dir = join(repoRoot, "blueprints", status);
|
|
13
|
+
if (!existsSync(dir) || !statSync(dir).isDirectory())
|
|
14
|
+
continue;
|
|
15
|
+
for (const name of readdirSync(dir)) {
|
|
16
|
+
if (name.startsWith("."))
|
|
17
|
+
continue;
|
|
18
|
+
rows.push({ slug: name, status });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
rows.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
22
|
+
return rows;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build blueprint-domain handlers scoped to `repoRoot`.
|
|
26
|
+
*/
|
|
27
|
+
export function createBlueprintsHandlers(repoRoot) {
|
|
28
|
+
return {
|
|
29
|
+
"blueprints.list": () => ({
|
|
30
|
+
blueprints: listBlueprintRows(repoRoot),
|
|
31
|
+
}),
|
|
32
|
+
"blueprints.exec": () => {
|
|
33
|
+
throw new Error("blueprints.exec is not implemented (exec remains CLI-owned)");
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deploy-domain product handlers: `deploy.run` is not implemented (no deploy
|
|
3
|
+
* job ledger; refuse fabricated handles).
|
|
4
|
+
*/
|
|
5
|
+
import type { MethodHandler } from "#daemon/rpc.js";
|
|
6
|
+
export declare const deployHandlers: Readonly<Partial<Record<string, MethodHandler>>>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MethodHandler } from "#daemon/rpc.js";
|
|
2
|
+
import { type FleetStatus } from "#fleet/status.js";
|
|
3
|
+
import type { FleetStatusResult } from "#daemon/protocol/contract.js";
|
|
4
|
+
/**
|
|
5
|
+
* Adapt the rich `collectFleetStatus` output down to the FROZEN daemon wire
|
|
6
|
+
* contract `{ agents: [{ id, state, label? }] }` that
|
|
7
|
+
* apps/desktop/src-tauri/src/commands/fleet.rs already destructures. Pure /
|
|
8
|
+
* unit-testable without spawning real git or gh. Complexity: O(worktrees).
|
|
9
|
+
*/
|
|
10
|
+
export declare function toFleetStatusResult(status: FleetStatus): FleetStatusResult;
|
|
11
|
+
/**
|
|
12
|
+
* Build fleet-domain handlers. `repoRoot` is the default worktree root used
|
|
13
|
+
* when a request does not supply its own `repoRoot` param.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createFleetHandlers(repoRoot: string): Readonly<Partial<Record<string, MethodHandler>>>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fleet-domain product handlers: `worktrees.list` is a real implementation
|
|
3
|
+
* over `git worktree list`; `fleet.status` calls the production
|
|
4
|
+
* `collectFleetStatus` engine and adapts its shape to the frozen daemon
|
|
5
|
+
* wire contract.
|
|
6
|
+
*/
|
|
7
|
+
import { execFileSync } from "node:child_process";
|
|
8
|
+
import { collectFleetStatus } from "#fleet/status.js";
|
|
9
|
+
import { asRecord } from "./shared.js";
|
|
10
|
+
function worktreeRows(repoRoot) {
|
|
11
|
+
try {
|
|
12
|
+
const out = execFileSync("git", ["worktree", "list", "--porcelain"], {
|
|
13
|
+
cwd: repoRoot,
|
|
14
|
+
encoding: "utf8",
|
|
15
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
16
|
+
});
|
|
17
|
+
const rows = [];
|
|
18
|
+
let path;
|
|
19
|
+
let branch;
|
|
20
|
+
for (const line of out.split("\n")) {
|
|
21
|
+
if (line.startsWith("worktree ")) {
|
|
22
|
+
if (path)
|
|
23
|
+
rows.push({ path, branch });
|
|
24
|
+
path = line.slice("worktree ".length).trim();
|
|
25
|
+
branch = undefined;
|
|
26
|
+
}
|
|
27
|
+
else if (line.startsWith("branch ")) {
|
|
28
|
+
branch = line
|
|
29
|
+
.slice("branch ".length)
|
|
30
|
+
.trim()
|
|
31
|
+
.replace(/^refs\/heads\//u, "");
|
|
32
|
+
}
|
|
33
|
+
else if (line === "") {
|
|
34
|
+
if (path)
|
|
35
|
+
rows.push({ path, branch });
|
|
36
|
+
path = undefined;
|
|
37
|
+
branch = undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (path)
|
|
41
|
+
rows.push({ path, branch });
|
|
42
|
+
return rows;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return [{ path: repoRoot }];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Single-string worktree classification the frozen daemon wire contract carries as `state`. */
|
|
49
|
+
function classifyWorktreeState(git) {
|
|
50
|
+
if (git.dirtyFiles === null)
|
|
51
|
+
return "unknown";
|
|
52
|
+
if (git.dirtyFiles > 0)
|
|
53
|
+
return "dirty";
|
|
54
|
+
if ((git.ahead ?? 0) > 0 || (git.behind ?? 0) > 0)
|
|
55
|
+
return "drifted";
|
|
56
|
+
return "clean";
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Adapt the rich `collectFleetStatus` output down to the FROZEN daemon wire
|
|
60
|
+
* contract `{ agents: [{ id, state, label? }] }` that
|
|
61
|
+
* apps/desktop/src-tauri/src/commands/fleet.rs already destructures. Pure /
|
|
62
|
+
* unit-testable without spawning real git or gh. Complexity: O(worktrees).
|
|
63
|
+
*/
|
|
64
|
+
export function toFleetStatusResult(status) {
|
|
65
|
+
return {
|
|
66
|
+
agents: status.worktrees.map((worktree) => ({
|
|
67
|
+
id: worktree.path,
|
|
68
|
+
state: classifyWorktreeState(worktree.git),
|
|
69
|
+
...(worktree.label ? { label: worktree.label } : {}),
|
|
70
|
+
})),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Build fleet-domain handlers. `repoRoot` is the default worktree root used
|
|
75
|
+
* when a request does not supply its own `repoRoot` param.
|
|
76
|
+
*/
|
|
77
|
+
export function createFleetHandlers(repoRoot) {
|
|
78
|
+
return {
|
|
79
|
+
"fleet.status": async () => {
|
|
80
|
+
const status = await collectFleetStatus({ cwd: repoRoot });
|
|
81
|
+
return toFleetStatusResult(status);
|
|
82
|
+
},
|
|
83
|
+
"worktrees.list": (_session, params) => {
|
|
84
|
+
const record = asRecord(params);
|
|
85
|
+
const root = typeof record.repoRoot === "string" && record.repoRoot.length > 0
|
|
86
|
+
? record.repoRoot
|
|
87
|
+
: repoRoot;
|
|
88
|
+
return { worktrees: worktreeRows(root) };
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git-domain product handlers: `git.diff`, `git.commit`, and `git.createPr`
|
|
3
|
+
* are real implementations over `src/daemon/domains/git-actions.ts`.
|
|
4
|
+
*/
|
|
5
|
+
import type { MethodHandler } from "#daemon/rpc.js";
|
|
6
|
+
export declare const gitHandlers: Readonly<Partial<Record<string, MethodHandler>>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { gitDiff, gitCommit, gitCreatePr } from "#daemon/domains/git-actions.js";
|
|
2
|
+
import { asRecord, requireString } from "./shared.js";
|
|
3
|
+
export const gitHandlers = {
|
|
4
|
+
"git.diff": (_session, params) => {
|
|
5
|
+
const record = asRecord(params);
|
|
6
|
+
const cwd = requireString(record, "cwd");
|
|
7
|
+
return gitDiff(cwd);
|
|
8
|
+
},
|
|
9
|
+
"git.commit": (_session, params) => {
|
|
10
|
+
const record = asRecord(params);
|
|
11
|
+
const cwd = requireString(record, "cwd");
|
|
12
|
+
const message = requireString(record, "message");
|
|
13
|
+
const paths = Array.isArray(record.paths)
|
|
14
|
+
? record.paths.filter((p) => typeof p === "string")
|
|
15
|
+
: undefined;
|
|
16
|
+
return gitCommit(cwd, message, paths);
|
|
17
|
+
},
|
|
18
|
+
"git.createPr": (_session, params) => {
|
|
19
|
+
const record = asRecord(params);
|
|
20
|
+
const cwd = requireString(record, "cwd");
|
|
21
|
+
const title = requireString(record, "title");
|
|
22
|
+
// confirmationToken is already consumed by DaemonAuthz before this
|
|
23
|
+
// handler runs (methods.ts requiresConfirmation) — no re-check needed here.
|
|
24
|
+
const body = typeof record.body === "string" ? record.body : undefined;
|
|
25
|
+
return gitCreatePr(cwd, title, body);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default production handlers for registered product-domain RPC methods.
|
|
3
|
+
* Wired at daemon start so callers do not need ad-hoc injection.
|
|
4
|
+
*
|
|
5
|
+
* Domain implementations live in the sibling `*-handlers.ts` files; this
|
|
6
|
+
* module only aggregates them into the map `startDaemonServer` consumes.
|
|
7
|
+
*/
|
|
1
8
|
import type { MethodHandler } from "#daemon/rpc.js";
|
|
2
9
|
/**
|
|
3
10
|
* Build the default handler map. Callers may override individual methods via
|
|
@@ -1,78 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import { join } from "node:path";
|
|
7
|
-
import { execFileSync } from "node:child_process";
|
|
8
|
-
import { gitDiff, gitCommit } from "#daemon/domains/git-actions.js";
|
|
9
|
-
function asRecord(params) {
|
|
10
|
-
if (params === null || typeof params !== "object" || Array.isArray(params)) {
|
|
11
|
-
return {};
|
|
12
|
-
}
|
|
13
|
-
return params;
|
|
14
|
-
}
|
|
15
|
-
function requireString(record, key) {
|
|
16
|
-
const v = record[key];
|
|
17
|
-
if (typeof v !== "string" || v.length === 0) {
|
|
18
|
-
throw new Error(`missing string param: ${key}`);
|
|
19
|
-
}
|
|
20
|
-
return v;
|
|
21
|
-
}
|
|
22
|
-
function listBlueprintRows(repoRoot) {
|
|
23
|
-
const statuses = ["completed", "in-progress", "planned", "parked", "draft", "archived"];
|
|
24
|
-
const rows = [];
|
|
25
|
-
for (const status of statuses) {
|
|
26
|
-
const dir = join(repoRoot, "blueprints", status);
|
|
27
|
-
if (!existsSync(dir) || !statSync(dir).isDirectory())
|
|
28
|
-
continue;
|
|
29
|
-
for (const name of readdirSync(dir)) {
|
|
30
|
-
if (name.startsWith("."))
|
|
31
|
-
continue;
|
|
32
|
-
rows.push({ slug: name, status });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
rows.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
36
|
-
return rows;
|
|
37
|
-
}
|
|
38
|
-
function worktreeRows(repoRoot) {
|
|
39
|
-
try {
|
|
40
|
-
const out = execFileSync("git", ["worktree", "list", "--porcelain"], {
|
|
41
|
-
cwd: repoRoot,
|
|
42
|
-
encoding: "utf8",
|
|
43
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
44
|
-
});
|
|
45
|
-
const rows = [];
|
|
46
|
-
let path;
|
|
47
|
-
let branch;
|
|
48
|
-
for (const line of out.split("\n")) {
|
|
49
|
-
if (line.startsWith("worktree ")) {
|
|
50
|
-
if (path)
|
|
51
|
-
rows.push({ path, branch });
|
|
52
|
-
path = line.slice("worktree ".length).trim();
|
|
53
|
-
branch = undefined;
|
|
54
|
-
}
|
|
55
|
-
else if (line.startsWith("branch ")) {
|
|
56
|
-
branch = line
|
|
57
|
-
.slice("branch ".length)
|
|
58
|
-
.trim()
|
|
59
|
-
.replace(/^refs\/heads\//u, "");
|
|
60
|
-
}
|
|
61
|
-
else if (line === "") {
|
|
62
|
-
if (path)
|
|
63
|
-
rows.push({ path, branch });
|
|
64
|
-
path = undefined;
|
|
65
|
-
branch = undefined;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (path)
|
|
69
|
-
rows.push({ path, branch });
|
|
70
|
-
return rows;
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
return [{ path: repoRoot }];
|
|
74
|
-
}
|
|
75
|
-
}
|
|
1
|
+
import { gitHandlers } from "./git-handlers.js";
|
|
2
|
+
import { createFleetHandlers } from "./fleet-handlers.js";
|
|
3
|
+
import { createBlueprintsHandlers } from "./blueprints-handlers.js";
|
|
4
|
+
import { createSessionsHandlers } from "./sessions-handlers.js";
|
|
5
|
+
import { deployHandlers } from "./deploy-handlers.js";
|
|
76
6
|
/**
|
|
77
7
|
* Build the default handler map. Callers may override individual methods via
|
|
78
8
|
* `startDaemonServer({ handlers })` — overrides win.
|
|
@@ -80,49 +10,10 @@ function worktreeRows(repoRoot) {
|
|
|
80
10
|
export function createDefaultProductHandlers(options) {
|
|
81
11
|
const repoRoot = options?.repoRoot ?? process.cwd();
|
|
82
12
|
return {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"git.commit": (_session, params) => {
|
|
89
|
-
const record = asRecord(params);
|
|
90
|
-
const cwd = requireString(record, "cwd");
|
|
91
|
-
const message = requireString(record, "message");
|
|
92
|
-
const paths = Array.isArray(record.paths)
|
|
93
|
-
? record.paths.filter((p) => typeof p === "string")
|
|
94
|
-
: undefined;
|
|
95
|
-
return gitCommit(cwd, message, paths);
|
|
96
|
-
},
|
|
97
|
-
"git.createPr": () => {
|
|
98
|
-
throw new Error("git.createPr is not implemented in agent-kit daemon (host policy / gh required)");
|
|
99
|
-
},
|
|
100
|
-
"fleet.status": () => {
|
|
101
|
-
throw new Error("fleet.status is not implemented (no worktree fleet integration; refuse empty success)");
|
|
102
|
-
},
|
|
103
|
-
"worktrees.list": (_session, params) => {
|
|
104
|
-
const record = asRecord(params);
|
|
105
|
-
const root = typeof record.repoRoot === "string" && record.repoRoot.length > 0
|
|
106
|
-
? record.repoRoot
|
|
107
|
-
: repoRoot;
|
|
108
|
-
return { worktrees: worktreeRows(root) };
|
|
109
|
-
},
|
|
110
|
-
"blueprints.list": () => ({
|
|
111
|
-
blueprints: listBlueprintRows(repoRoot),
|
|
112
|
-
}),
|
|
113
|
-
"blueprints.exec": () => {
|
|
114
|
-
throw new Error("blueprints.exec is not implemented (exec remains CLI-owned)");
|
|
115
|
-
},
|
|
116
|
-
"sessions.list": () => {
|
|
117
|
-
throw new Error("sessions.list is not implemented (PTY sessions are Tauri-owned; refuse empty success)");
|
|
118
|
-
},
|
|
119
|
-
"deploy.run": () => {
|
|
120
|
-
throw new Error("deploy.run is not implemented (no deploy job ledger; refuse fabricated handles)");
|
|
121
|
-
},
|
|
122
|
-
"launch.permissionState": () => ({
|
|
123
|
-
mode: "safe",
|
|
124
|
-
yoloPreference: false,
|
|
125
|
-
isolationWarning: "permission state is advisory until full permission UX lands",
|
|
126
|
-
}),
|
|
13
|
+
...gitHandlers,
|
|
14
|
+
...createFleetHandlers(repoRoot),
|
|
15
|
+
...createBlueprintsHandlers(repoRoot),
|
|
16
|
+
...createSessionsHandlers(repoRoot),
|
|
17
|
+
...deployHandlers,
|
|
127
18
|
};
|
|
128
19
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session/launch-domain product handlers: `sessions.list` reads the real
|
|
3
|
+
* dash run-registry; `sessions.search` reuses the session-memory FTS index;
|
|
4
|
+
* `launch.permissionState` returns the advisory permission-state stub.
|
|
5
|
+
*/
|
|
6
|
+
import type { MethodHandler } from "#daemon/rpc.js";
|
|
7
|
+
/**
|
|
8
|
+
* Build session-domain handlers scoped to `repoRoot`. `repoRoot` doubles as
|
|
9
|
+
* the dash run-registry cwd (sessions.list) and the session-memory index
|
|
10
|
+
* root (sessions.search) — both already resolve per-repo paths on their own.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createSessionsHandlers(repoRoot: string): Readonly<Partial<Record<string, MethodHandler>>>;
|