intentdna 1.9.0 → 1.9.3
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +227 -87
- package/dist/cli/commands/run-lifecycle.d.ts +61 -11
- package/dist/cli/commands/run-lifecycle.js +184 -50
- package/dist/cli/commands/run-observer.d.ts +15 -0
- package/dist/cli/commands/run-observer.js +210 -0
- package/dist/cli/commands/run.d.ts +16 -20
- package/dist/cli/commands/run.js +461 -659
- package/dist/cli/commands/sync.js +16 -12
- package/dist/cli/index.js +14 -5
- package/dist/compiler/compile.d.ts +1 -0
- package/dist/compiler/compile.js +1 -1
- package/dist/compiler/controller.d.ts +16 -0
- package/dist/compiler/controller.js +693 -0
- package/dist/compiler/input-resolver.d.ts +2 -0
- package/dist/compiler/input-resolver.js +22 -6
- package/dist/hooks/cli.d.ts +45 -0
- package/dist/hooks/cli.js +263 -31
- package/dist/hooks/host-event.d.ts +57 -0
- package/dist/hooks/host-event.js +187 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/protocol.d.ts +7 -0
- package/dist/hooks/schema.d.ts +1 -0
- package/dist/hooks/schema.js +89 -1
- package/dist/hooks/state.d.ts +23 -1
- package/dist/hooks/state.js +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/tools-run.d.ts +4 -0
- package/dist/mcp/tools-run.js +419 -0
- package/dist/mcp/tools-state.d.ts +1 -1
- package/dist/mcp/tools-state.js +13 -241
- package/dist/runtime/artifact-store.d.ts +146 -0
- package/dist/runtime/artifact-store.js +1436 -0
- package/dist/runtime/canonical-attempt-outcome.d.ts +12 -0
- package/dist/runtime/canonical-attempt-outcome.js +195 -0
- package/dist/runtime/canonical-json.d.ts +10 -0
- package/dist/runtime/canonical-json.js +105 -0
- package/dist/runtime/canonical-run-application.d.ts +93 -0
- package/dist/runtime/canonical-run-application.js +229 -0
- package/dist/runtime/canonical-run-service.d.ts +454 -0
- package/dist/runtime/canonical-run-service.js +4760 -0
- package/dist/runtime/canonical-runtime-composition.d.ts +22 -0
- package/dist/runtime/canonical-runtime-composition.js +34 -0
- package/dist/runtime/canonical-runtime-projection.d.ts +3 -0
- package/dist/runtime/canonical-runtime-projection.js +4 -0
- package/dist/runtime/canonical-target-compiler.d.ts +46 -0
- package/dist/runtime/canonical-target-compiler.js +514 -0
- package/dist/runtime/claude-agent-identity.d.ts +2 -0
- package/dist/runtime/claude-agent-identity.js +21 -0
- package/dist/runtime/executable-run-plan.d.ts +328 -0
- package/dist/runtime/executable-run-plan.js +1485 -0
- package/dist/runtime/execution-authority.d.ts +83 -0
- package/dist/runtime/execution-authority.js +98 -0
- package/dist/runtime/handoff-resolver.js +4 -1
- package/dist/runtime/harness-pull-adapter.d.ts +146 -0
- package/dist/runtime/harness-pull-adapter.js +315 -0
- package/dist/runtime/index.d.ts +39 -14
- package/dist/runtime/index.js +29 -7
- package/dist/runtime/local-execution-authority.d.ts +194 -0
- package/dist/runtime/local-execution-authority.js +2897 -0
- package/dist/runtime/local-execution-reconciliation.d.ts +20 -0
- package/dist/runtime/local-execution-reconciliation.js +107 -0
- package/dist/runtime/local-execution-supervisor-script.d.ts +7 -0
- package/dist/runtime/local-execution-supervisor-script.js +793 -0
- package/dist/runtime/local-provider-sandbox.d.ts +42 -0
- package/dist/runtime/local-provider-sandbox.js +154 -0
- package/dist/runtime/local-verifier-execution.d.ts +24 -0
- package/dist/runtime/local-verifier-execution.js +290 -0
- package/dist/runtime/local-windows-execution-supervisor-script.d.ts +6 -0
- package/dist/runtime/local-windows-execution-supervisor-script.js +788 -0
- package/dist/runtime/plan-store.d.ts +30 -0
- package/dist/runtime/plan-store.js +231 -0
- package/dist/runtime/process-tree.d.ts +9 -0
- package/dist/runtime/process-tree.js +97 -24
- package/dist/runtime/providers/codex.js +2 -2
- package/dist/runtime/push-driver.d.ts +184 -0
- package/dist/runtime/push-driver.js +1002 -0
- package/dist/runtime/result-store.d.ts +34 -3
- package/dist/runtime/result-store.js +1073 -2
- package/dist/runtime/run-binding.d.ts +68 -0
- package/dist/runtime/run-binding.js +278 -0
- package/dist/runtime/run-contracts.d.ts +575 -0
- package/dist/runtime/run-contracts.js +58 -7
- package/dist/runtime/run-controller.d.ts +1 -6
- package/dist/runtime/run-controller.js +0 -41
- package/dist/runtime/run-store.d.ts +85 -7
- package/dist/runtime/run-store.js +2528 -186
- package/dist/runtime/skill-adapter.d.ts +18 -7
- package/dist/runtime/skill-adapter.js +100 -742
- package/dist/runtime/structured-output-validator.d.ts +44 -0
- package/dist/runtime/structured-output-validator.js +171 -0
- package/dist/runtime/verifier-command-binding.d.ts +22 -0
- package/dist/runtime/verifier-command-binding.js +162 -0
- package/dist/runtime/verifier.d.ts +46 -6
- package/dist/runtime/verifier.js +355 -53
- package/dist/runtime/windows-job-keeper.d.ts +47 -0
- package/dist/runtime/windows-job-keeper.js +231 -0
- package/dist/runtime/worker-executor.d.ts +17 -1
- package/dist/runtime/worker-executor.js +26 -5
- package/dist/runtime/workflow-plan-adapter.d.ts +19 -0
- package/dist/runtime/workflow-plan-adapter.js +502 -6
- package/dist/runtime/workflow-runtime-manifest.d.ts +1 -0
- package/dist/runtime/workflow-runtime-manifest.js +5 -0
- package/dist/runtime/workspace-isolation.d.ts +29 -2
- package/dist/runtime/workspace-isolation.js +488 -11
- package/dist/runtime/workspace-observation.d.ts +44 -0
- package/dist/runtime/workspace-observation.js +216 -0
- package/dist/schema/controller-registry.d.ts +0 -7
- package/dist/schema/controller-registry.js +0 -8
- package/dist/schema/types.d.ts +84 -10
- package/dist/schema/types.js +2 -0
- package/dist/schema/validate.js +151 -1
- package/dist/schema/validators/controllers.d.ts +1 -1
- package/dist/schema/validators/controllers.js +126 -41
- package/dist/schema/workflow-authoring-contract.js +2 -0
- package/dist/schema/yaml-parser.js +1 -1
- package/dist/templates/flutter-rewrite-new.dna.yaml +1 -0
- package/dist/templates/flutter-rewrite.dna.yaml +87 -60
- package/dist/templates/safe-refactoring.dna.yaml +1 -0
- package/native/windows-job-keeper/README.md +80 -0
- package/native/windows-job-keeper/bin/aarch64/intentdna-windows-job-keeper.exe +0 -0
- package/native/windows-job-keeper/bin/x86_64/intentdna-windows-job-keeper.exe +0 -0
- package/native/windows-job-keeper/keeper.c +979 -0
- package/native/windows-job-keeper/manifest.json +33 -0
- package/package.json +6 -2
- package/scripts/build-windows-job-keeper.mjs +172 -0
- package/scripts/verify-windows-job-keeper.mjs +184 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { join, resolve } from "node:path";
|
|
2
|
+
import { DNAStateManager } from "../hooks/state-manager.js";
|
|
3
|
+
import { safePathComponent, writeCanonicalHookRuntimeProjection, } from "../hooks/state.js";
|
|
4
|
+
import { createCanonicalRuntimeComposition } from "../runtime/canonical-runtime-composition.js";
|
|
5
|
+
import { HarnessPullAdapter, } from "../runtime/harness-pull-adapter.js";
|
|
6
|
+
import { ProductionLocalVerifierExecutionPort } from "../runtime/local-verifier-execution.js";
|
|
7
|
+
import { LocalAttemptWorkspaceAuthority } from "../runtime/workspace-isolation.js";
|
|
8
|
+
import { WORKFLOW_RUNTIME_INPUT_VARIABLE_NAMES } from "../runtime/workflow-runtime-manifest.js";
|
|
9
|
+
import { errorResult, textResult } from "./server.js";
|
|
10
|
+
const HARNESS_PROVIDER = Object.freeze({
|
|
11
|
+
provider: "harness",
|
|
12
|
+
model: null,
|
|
13
|
+
options: Object.freeze({}),
|
|
14
|
+
credential_references: Object.freeze([]),
|
|
15
|
+
});
|
|
16
|
+
const HARNESS_CAPABILITIES = Object.freeze({
|
|
17
|
+
driver: Object.freeze({
|
|
18
|
+
worktree_isolation: true,
|
|
19
|
+
parallelism: true,
|
|
20
|
+
cancellation: false,
|
|
21
|
+
hook_identity: true,
|
|
22
|
+
caller_attestation: false,
|
|
23
|
+
human_interaction: false,
|
|
24
|
+
direct_structured_submission: true,
|
|
25
|
+
network_policy_enforcement: false,
|
|
26
|
+
}),
|
|
27
|
+
submission_modes: Object.freeze(["relayed_submit"]),
|
|
28
|
+
stopped_execution_authority: false,
|
|
29
|
+
});
|
|
30
|
+
class MCPRunToolError extends Error {
|
|
31
|
+
code;
|
|
32
|
+
constructor(code, message) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = "MCPRunToolError";
|
|
35
|
+
this.code = code;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function jsonResult(value) {
|
|
39
|
+
return textResult(JSON.stringify({ ok: true, result: value }));
|
|
40
|
+
}
|
|
41
|
+
function errorCode(error) {
|
|
42
|
+
if (error !== null
|
|
43
|
+
&& typeof error === "object"
|
|
44
|
+
&& "code" in error
|
|
45
|
+
&& typeof error.code === "string"
|
|
46
|
+
&& error.code.length > 0) {
|
|
47
|
+
return error.code;
|
|
48
|
+
}
|
|
49
|
+
return "internal_error";
|
|
50
|
+
}
|
|
51
|
+
function jsonError(error) {
|
|
52
|
+
return errorResult(JSON.stringify({
|
|
53
|
+
ok: false,
|
|
54
|
+
error: {
|
|
55
|
+
code: errorCode(error),
|
|
56
|
+
message: error instanceof Error ? error.message : String(error),
|
|
57
|
+
},
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
function guarded(handler) {
|
|
61
|
+
return async (args) => {
|
|
62
|
+
try {
|
|
63
|
+
rejectClientCapabilities(args);
|
|
64
|
+
return jsonResult(await handler(args));
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
return jsonError(error);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function rejectClientCapabilities(args) {
|
|
72
|
+
if (Object.prototype.hasOwnProperty.call(args, "capabilities")) {
|
|
73
|
+
throw new MCPRunToolError("invalid_request", "harness capabilities are fixed by the MCP host and cannot be supplied by clients");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function requiredString(args, name) {
|
|
77
|
+
const value = args[name];
|
|
78
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
79
|
+
throw new MCPRunToolError("invalid_request", `${name} must be a non-empty string`);
|
|
80
|
+
}
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
function runId(args) {
|
|
84
|
+
return requiredString(args, "run_id");
|
|
85
|
+
}
|
|
86
|
+
function claimToken(args) {
|
|
87
|
+
return requiredString(args, "lease_token");
|
|
88
|
+
}
|
|
89
|
+
function workerSessionId(args) {
|
|
90
|
+
return requiredString(args, "worker_session_id");
|
|
91
|
+
}
|
|
92
|
+
function optionalString(args, name) {
|
|
93
|
+
const value = args[name];
|
|
94
|
+
if (value === undefined)
|
|
95
|
+
return undefined;
|
|
96
|
+
if (typeof value !== "string") {
|
|
97
|
+
throw new MCPRunToolError("invalid_request", `${name} must be a string`);
|
|
98
|
+
}
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
function requiredRecord(args, name) {
|
|
102
|
+
const value = args[name];
|
|
103
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
104
|
+
throw new MCPRunToolError("invalid_request", `${name} must be an object`);
|
|
105
|
+
}
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
function requiredStringArray(args, name) {
|
|
109
|
+
const value = args[name];
|
|
110
|
+
if (!Array.isArray(value)
|
|
111
|
+
|| value.length === 0
|
|
112
|
+
|| value.some((entry) => typeof entry !== "string" || entry.trim().length === 0)) {
|
|
113
|
+
throw new MCPRunToolError("invalid_request", `${name} must be a non-empty array of non-empty strings`);
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
function positiveInteger(args, name, fallback) {
|
|
118
|
+
const value = args[name] ?? fallback;
|
|
119
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
120
|
+
throw new MCPRunToolError("invalid_request", `${name} must be a positive integer`);
|
|
121
|
+
}
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
function submissionMode(args) {
|
|
125
|
+
const value = requiredString(args, "submission_mode");
|
|
126
|
+
if (value !== "relayed_submit" && value !== "attested_independent_submit") {
|
|
127
|
+
throw new MCPRunToolError("invalid_request", "submission_mode is invalid");
|
|
128
|
+
}
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
function jsonValue(value, name) {
|
|
132
|
+
try {
|
|
133
|
+
const serialized = JSON.stringify(value);
|
|
134
|
+
if (serialized === undefined)
|
|
135
|
+
throw new Error("not JSON serializable");
|
|
136
|
+
return JSON.parse(serialized);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
throw new MCPRunToolError("invalid_request", `${name} must be JSON serializable`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function logicalWorkflowStepId(stepId) {
|
|
143
|
+
const prefix = "worker:";
|
|
144
|
+
if (!stepId.startsWith(prefix) || stepId.length === prefix.length) {
|
|
145
|
+
throw new MCPRunToolError("invalid_service_response", `canonical worker step id is invalid: ${stepId}`);
|
|
146
|
+
}
|
|
147
|
+
return stepId.slice(prefix.length);
|
|
148
|
+
}
|
|
149
|
+
async function writeHarnessAttemptProjection(context) {
|
|
150
|
+
const compiled = context.metadata?.compiled_ir;
|
|
151
|
+
const packet = context.attached.packet;
|
|
152
|
+
if (compiled === null || compiled === undefined || packet === null)
|
|
153
|
+
return;
|
|
154
|
+
const workflowName = context.metadata?.target.key;
|
|
155
|
+
const manifest = compiled.workflow_runtime;
|
|
156
|
+
const binding = workflowName === undefined
|
|
157
|
+
? undefined
|
|
158
|
+
: manifest?.workflows[workflowName];
|
|
159
|
+
const compiledIRHash = compiled.compiled_ir_hash ?? compiled.ir.compiled_ir_hash;
|
|
160
|
+
if (workflowName === undefined
|
|
161
|
+
|| manifest === undefined
|
|
162
|
+
|| binding === undefined
|
|
163
|
+
|| compiledIRHash === undefined
|
|
164
|
+
|| manifest.compiled_ir_hash !== compiledIRHash) {
|
|
165
|
+
throw new MCPRunToolError("invalid_service_response", "harness run metadata is missing a valid pinned workflow projection");
|
|
166
|
+
}
|
|
167
|
+
const workingDirectory = packet.workspace.working_directory;
|
|
168
|
+
const state = new DNAStateManager(workingDirectory, context.worker_session_id);
|
|
169
|
+
const inputs = {};
|
|
170
|
+
for (const name of binding.runtime_input_refs) {
|
|
171
|
+
const value = context.run.run.run_binding.binding.validated_inputs[name];
|
|
172
|
+
if (typeof value === "string")
|
|
173
|
+
inputs[name] = value;
|
|
174
|
+
}
|
|
175
|
+
for (const name of WORKFLOW_RUNTIME_INPUT_VARIABLE_NAMES) {
|
|
176
|
+
const value = context.run.run.run_binding.binding.validated_inputs[name];
|
|
177
|
+
if (typeof value === "string" && binding.runtime_input_refs.includes(name)) {
|
|
178
|
+
inputs[name] = value;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
await writeCanonicalHookRuntimeProjection(workingDirectory, {
|
|
183
|
+
schema_version: "intentdna.canonical_hook_projection.v2",
|
|
184
|
+
run_id: context.run.run.run_id,
|
|
185
|
+
step_id: packet.step_id,
|
|
186
|
+
attempt_id: packet.attempt_id,
|
|
187
|
+
worker_session_id: context.worker_session_id,
|
|
188
|
+
compiled_ir_hash: compiledIRHash,
|
|
189
|
+
compiled_ir: compiled,
|
|
190
|
+
lease_token: context.lease_token,
|
|
191
|
+
owner_id: context.owner_id,
|
|
192
|
+
});
|
|
193
|
+
await state.writeWorkflowState({
|
|
194
|
+
active: true,
|
|
195
|
+
workflow_asset: binding.workflow_asset,
|
|
196
|
+
workflow: workflowName,
|
|
197
|
+
current_step: logicalWorkflowStepId(packet.step_id),
|
|
198
|
+
current_role: packet.role,
|
|
199
|
+
iteration: packet.workflow_round,
|
|
200
|
+
session_id: context.worker_session_id,
|
|
201
|
+
worker_session_id: context.worker_session_id,
|
|
202
|
+
run_id: context.run.run.run_id,
|
|
203
|
+
step_id: packet.step_id,
|
|
204
|
+
attempt_id: packet.attempt_id,
|
|
205
|
+
started_at: packet.created_at,
|
|
206
|
+
inputs,
|
|
207
|
+
resolved_variables: binding.resolved_variables,
|
|
208
|
+
resolved_variables_source: "compiled_manifest",
|
|
209
|
+
workflow_runtime_manifest_hash: manifest.manifest_hash,
|
|
210
|
+
workflow_runtime_compiled_ir_hash: manifest.compiled_ir_hash,
|
|
211
|
+
workflow_inputs_pinned: true,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
await state.cleanup().catch(() => undefined);
|
|
216
|
+
throw error;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export function createMCPHarnessAdapter(projectDirectory) {
|
|
220
|
+
const runtimeRoot = join(projectDirectory, ".dna", "runtime");
|
|
221
|
+
const composition = createCanonicalRuntimeComposition({
|
|
222
|
+
project_directory: projectDirectory,
|
|
223
|
+
workspace_authority: new LocalAttemptWorkspaceAuthority({
|
|
224
|
+
lock_root: join(runtimeRoot, "workspace-locks"),
|
|
225
|
+
}),
|
|
226
|
+
verifier_execution_port: new ProductionLocalVerifierExecutionPort({
|
|
227
|
+
root_directory: join(runtimeRoot, "verifier-execution-authority"),
|
|
228
|
+
}),
|
|
229
|
+
});
|
|
230
|
+
return new HarnessPullAdapter({
|
|
231
|
+
service: composition.service,
|
|
232
|
+
capabilities: HARNESS_CAPABILITIES,
|
|
233
|
+
attempt_projection_sink: writeHarnessAttemptProjection,
|
|
234
|
+
validate_worker_session_id: (workerSessionId) => {
|
|
235
|
+
safePathComponent(workerSessionId, "worker_session_id");
|
|
236
|
+
},
|
|
237
|
+
driver_id: `mcp-harness:${process.pid}`,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function tool(name, description, properties, required, handler) {
|
|
241
|
+
return {
|
|
242
|
+
name,
|
|
243
|
+
description,
|
|
244
|
+
inputSchema: { type: "object", properties, required },
|
|
245
|
+
handler: guarded(handler),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
export function createRunTools(projectDir) {
|
|
249
|
+
const projectDirectory = resolve(projectDir);
|
|
250
|
+
const adapter = createMCPHarnessAdapter(projectDirectory);
|
|
251
|
+
const identityProperties = {
|
|
252
|
+
run_id: { type: "string" },
|
|
253
|
+
attempt_id: { type: "string" },
|
|
254
|
+
lease_token: { type: "string" },
|
|
255
|
+
owner_id: { type: "string" },
|
|
256
|
+
};
|
|
257
|
+
return [
|
|
258
|
+
tool("dna_run_start", "Compile and start a canonical harness run in this MCP project's durable runtime", {
|
|
259
|
+
dna_sources: { type: "array", items: { type: "string" }, minItems: 1 },
|
|
260
|
+
target: {
|
|
261
|
+
type: "object",
|
|
262
|
+
properties: {
|
|
263
|
+
kind: { type: "string", enum: ["workflow", "controller"] },
|
|
264
|
+
key: { type: "string" },
|
|
265
|
+
},
|
|
266
|
+
required: ["kind", "key"],
|
|
267
|
+
},
|
|
268
|
+
inputs: { type: "object" },
|
|
269
|
+
max_concurrency: { type: "integer", minimum: 1 },
|
|
270
|
+
input_policy: { type: "string", enum: ["strict", "declared_only"] },
|
|
271
|
+
context: { type: ["string", "null"] },
|
|
272
|
+
attempt_policy: { type: "object" },
|
|
273
|
+
metadata: {},
|
|
274
|
+
run_id: { type: "string" },
|
|
275
|
+
}, ["dna_sources", "target", "inputs"], async (args) => {
|
|
276
|
+
if (Object.prototype.hasOwnProperty.call(args, "provider")
|
|
277
|
+
|| Object.prototype.hasOwnProperty.call(args, "project_root")
|
|
278
|
+
|| Object.prototype.hasOwnProperty.call(args, "workspace_root")) {
|
|
279
|
+
throw new MCPRunToolError("invalid_request", "provider, project_root, and workspace_root are fixed by the MCP host");
|
|
280
|
+
}
|
|
281
|
+
const target = requiredRecord(args, "target");
|
|
282
|
+
const kind = target.kind;
|
|
283
|
+
const key = target.key;
|
|
284
|
+
if ((kind !== "workflow" && kind !== "controller")
|
|
285
|
+
|| typeof key !== "string"
|
|
286
|
+
|| key.trim().length === 0) {
|
|
287
|
+
throw new MCPRunToolError("invalid_request", "target must contain a valid kind and key");
|
|
288
|
+
}
|
|
289
|
+
const inputPolicy = optionalString(args, "input_policy");
|
|
290
|
+
if (inputPolicy !== undefined && inputPolicy !== "strict" && inputPolicy !== "declared_only") {
|
|
291
|
+
throw new MCPRunToolError("invalid_request", "input_policy is invalid");
|
|
292
|
+
}
|
|
293
|
+
const context = args.context;
|
|
294
|
+
if (context !== undefined && context !== null && typeof context !== "string") {
|
|
295
|
+
throw new MCPRunToolError("invalid_request", "context must be a string or null");
|
|
296
|
+
}
|
|
297
|
+
const attemptPolicy = args.attempt_policy === undefined
|
|
298
|
+
? undefined
|
|
299
|
+
: requiredRecord(args, "attempt_policy");
|
|
300
|
+
if (attemptPolicy !== undefined
|
|
301
|
+
&& (!(attemptPolicy.timeout_ms === null || (Number.isSafeInteger(attemptPolicy.timeout_ms)
|
|
302
|
+
&& attemptPolicy.timeout_ms > 0))
|
|
303
|
+
|| !Number.isSafeInteger(attemptPolicy.cancellation_grace_ms)
|
|
304
|
+
|| attemptPolicy.cancellation_grace_ms < 0)) {
|
|
305
|
+
throw new MCPRunToolError("invalid_request", "attempt_policy must contain timeout_ms and a non-negative cancellation_grace_ms");
|
|
306
|
+
}
|
|
307
|
+
const request = {
|
|
308
|
+
dna_sources: requiredStringArray(args, "dna_sources"),
|
|
309
|
+
target: { kind, key },
|
|
310
|
+
inputs: requiredRecord(args, "inputs"),
|
|
311
|
+
environment: {
|
|
312
|
+
project_root: projectDirectory,
|
|
313
|
+
workspace_root: projectDirectory,
|
|
314
|
+
},
|
|
315
|
+
provider: HARNESS_PROVIDER,
|
|
316
|
+
max_concurrency: positiveInteger(args, "max_concurrency", 1),
|
|
317
|
+
...(inputPolicy === undefined ? {} : { input_policy: inputPolicy }),
|
|
318
|
+
...(context === undefined ? {} : { context: context }),
|
|
319
|
+
...(attemptPolicy === undefined
|
|
320
|
+
? {}
|
|
321
|
+
: {
|
|
322
|
+
attempt_policy: {
|
|
323
|
+
timeout_ms: attemptPolicy.timeout_ms,
|
|
324
|
+
cancellation_grace_ms: attemptPolicy.cancellation_grace_ms,
|
|
325
|
+
},
|
|
326
|
+
}),
|
|
327
|
+
...(args.metadata === undefined
|
|
328
|
+
? {}
|
|
329
|
+
: { metadata: jsonValue(args.metadata, "metadata") }),
|
|
330
|
+
...(args.run_id === undefined ? {} : { run_id: runId(args) }),
|
|
331
|
+
};
|
|
332
|
+
return adapter.start(request);
|
|
333
|
+
}),
|
|
334
|
+
tool("dna_run_next", "Resume a canonical run and acquire its next harness attempt", { run_id: { type: "string" } }, ["run_id"], (args) => adapter.next(runId(args))),
|
|
335
|
+
tool("dna_attempt_attach", "Attach a worker session to a claimed canonical harness attempt", {
|
|
336
|
+
...identityProperties,
|
|
337
|
+
worker_session_id: { type: "string" },
|
|
338
|
+
submission_mode: {
|
|
339
|
+
type: "string",
|
|
340
|
+
enum: ["relayed_submit", "attested_independent_submit"],
|
|
341
|
+
},
|
|
342
|
+
}, [
|
|
343
|
+
"run_id",
|
|
344
|
+
"attempt_id",
|
|
345
|
+
"lease_token",
|
|
346
|
+
"owner_id",
|
|
347
|
+
"worker_session_id",
|
|
348
|
+
"submission_mode",
|
|
349
|
+
], (args) => adapter.attach({
|
|
350
|
+
run_id: runId(args),
|
|
351
|
+
attempt_id: requiredString(args, "attempt_id"),
|
|
352
|
+
lease_token: claimToken(args),
|
|
353
|
+
owner_id: requiredString(args, "owner_id"),
|
|
354
|
+
worker_session_id: workerSessionId(args),
|
|
355
|
+
submission_mode: submissionMode(args),
|
|
356
|
+
})),
|
|
357
|
+
tool("dna_attempt_heartbeat", "Renew the lease for an attached canonical harness attempt", {
|
|
358
|
+
lease_token: { type: "string" },
|
|
359
|
+
owner_id: { type: "string" },
|
|
360
|
+
}, ["lease_token", "owner_id"], (args) => adapter.heartbeat({
|
|
361
|
+
lease_token: claimToken(args),
|
|
362
|
+
owner_id: requiredString(args, "owner_id"),
|
|
363
|
+
})),
|
|
364
|
+
tool("dna_attempt_submit", "Submit one structured execution result for an attached canonical harness attempt", {
|
|
365
|
+
...identityProperties,
|
|
366
|
+
submission_key: { type: "string" },
|
|
367
|
+
submission_mode: {
|
|
368
|
+
type: "string",
|
|
369
|
+
enum: ["relayed_submit", "attested_independent_submit"],
|
|
370
|
+
},
|
|
371
|
+
execution: { type: "object" },
|
|
372
|
+
evidence_refs: { type: "array", items: { type: "object" } },
|
|
373
|
+
}, [
|
|
374
|
+
"run_id",
|
|
375
|
+
"attempt_id",
|
|
376
|
+
"lease_token",
|
|
377
|
+
"owner_id",
|
|
378
|
+
"submission_key",
|
|
379
|
+
"submission_mode",
|
|
380
|
+
"execution",
|
|
381
|
+
], async (args) => {
|
|
382
|
+
const execution = requiredRecord(args, "execution");
|
|
383
|
+
if (execution.executor?.kind !== "worker") {
|
|
384
|
+
throw new MCPRunToolError("invalid_request", "harness execution.executor must identify the attached worker session");
|
|
385
|
+
}
|
|
386
|
+
const attachedWorkerSessionId = execution.executor.worker_session_id;
|
|
387
|
+
const evidenceRefs = args.evidence_refs;
|
|
388
|
+
if (evidenceRefs !== undefined && !Array.isArray(evidenceRefs)) {
|
|
389
|
+
throw new MCPRunToolError("invalid_request", "evidence_refs must be an array");
|
|
390
|
+
}
|
|
391
|
+
const request = {
|
|
392
|
+
run_id: runId(args),
|
|
393
|
+
attempt_id: requiredString(args, "attempt_id"),
|
|
394
|
+
lease_token: claimToken(args),
|
|
395
|
+
owner_id: requiredString(args, "owner_id"),
|
|
396
|
+
submission_key: requiredString(args, "submission_key"),
|
|
397
|
+
submission_mode: submissionMode(args),
|
|
398
|
+
execution,
|
|
399
|
+
...(evidenceRefs === undefined
|
|
400
|
+
? {}
|
|
401
|
+
: { evidence_refs: evidenceRefs }),
|
|
402
|
+
};
|
|
403
|
+
const response = await adapter.submit(request);
|
|
404
|
+
await new DNAStateManager(request.execution.workspace.root, attachedWorkerSessionId).cleanup();
|
|
405
|
+
return response;
|
|
406
|
+
}),
|
|
407
|
+
tool("dna_run_status", "Inspect the durable state of a canonical harness run", { run_id: { type: "string" } }, ["run_id"], (args) => adapter.status(runId(args))),
|
|
408
|
+
tool("dna_run_cancel", "Cancel a canonical harness run when the MCP host has trusted stopped-execution authority", {
|
|
409
|
+
run_id: { type: "string" },
|
|
410
|
+
reason: { type: ["string", "null"] },
|
|
411
|
+
}, ["run_id"], (args) => {
|
|
412
|
+
const reason = args.reason;
|
|
413
|
+
if (reason !== undefined && reason !== null && typeof reason !== "string") {
|
|
414
|
+
throw new MCPRunToolError("invalid_request", "reason must be a string or null");
|
|
415
|
+
}
|
|
416
|
+
return adapter.cancel(runId(args), reason === undefined ? undefined : reason);
|
|
417
|
+
}),
|
|
418
|
+
];
|
|
419
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Tools for reading/writing DNA governance state via MCP:
|
|
5
5
|
* - dna_status: Overview of DNA state
|
|
6
6
|
* - dna_workflow_read: Read current workflow state
|
|
7
|
-
* - dna_workflow_write:
|
|
7
|
+
* - dna_workflow_write: Close legacy workflow state
|
|
8
8
|
* - dna_trace_query: Query legacy diagnostic trace data with filters
|
|
9
9
|
*/
|
|
10
10
|
import type { ToolDef } from "./server.js";
|