voratiq 0.1.0-beta.21 → 0.1.0-beta.23
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/README.md +19 -23
- package/dist/agents/launch/chat.d.ts +3 -1
- package/dist/agents/launch/chat.js +2 -0
- package/dist/agents/runtime/policy.js +2 -1
- package/dist/auth/providers/utils.js +1 -1
- package/dist/bin.js +28 -7
- package/dist/cli/auto.js +4 -16
- package/dist/cli/contract.d.ts +26 -17
- package/dist/cli/contract.js +3 -1
- package/dist/cli/doctor.d.ts +12 -0
- package/dist/cli/doctor.js +115 -0
- package/dist/cli/list.js +5 -1
- package/dist/cli/message.js +16 -11
- package/dist/cli/operator-envelope.d.ts +27 -7
- package/dist/cli/operator-envelope.js +95 -3
- package/dist/cli/option-parsers.d.ts +2 -0
- package/dist/cli/option-parsers.js +7 -0
- package/dist/cli/output.d.ts +1 -5
- package/dist/cli/reduce.js +5 -13
- package/dist/cli/run.js +5 -12
- package/dist/cli/spec.js +4 -10
- package/dist/cli/verify.d.ts +1 -1
- package/dist/cli/verify.js +51 -22
- package/dist/commands/auto/command.d.ts +1 -0
- package/dist/commands/auto/command.js +22 -15
- package/dist/commands/auto/errors.js +1 -1
- package/dist/commands/auto/validation.js +3 -1
- package/dist/commands/doctor/agents.d.ts +5 -0
- package/dist/commands/{init → doctor}/agents.js +40 -20
- package/dist/commands/doctor/command.d.ts +22 -0
- package/dist/commands/doctor/command.js +100 -0
- package/dist/commands/doctor/environment.d.ts +2 -0
- package/dist/commands/{init → doctor}/environment.js +41 -7
- package/dist/commands/{init/types.d.ts → doctor/fix-types.d.ts} +30 -9
- package/dist/commands/doctor/fix.d.ts +2 -0
- package/dist/commands/{init/command.js → doctor/fix.js} +109 -11
- package/dist/commands/doctor/reconcile.d.ts +2 -0
- package/dist/commands/doctor/reconcile.js +103 -0
- package/dist/commands/interactive/lifecycle.d.ts +2 -0
- package/dist/commands/interactive/lifecycle.js +16 -0
- package/dist/commands/list/command.d.ts +1 -0
- package/dist/commands/list/command.js +241 -361
- package/dist/commands/list/normalization.d.ts +51 -0
- package/dist/commands/list/normalization.js +309 -0
- package/dist/commands/list/records.d.ts +9 -0
- package/dist/commands/list/records.js +6 -0
- package/dist/commands/message/command.d.ts +2 -2
- package/dist/commands/message/command.js +29 -16
- package/dist/commands/message/errors.d.ts +12 -3
- package/dist/commands/message/errors.js +19 -3
- package/dist/commands/prune/command.js +4 -1
- package/dist/commands/reduce/command.js +16 -17
- package/dist/commands/reduce/errors.d.ts +2 -2
- package/dist/commands/reduce/errors.js +3 -3
- package/dist/commands/reduce/targets.js +12 -3
- package/dist/commands/root-launcher/command.js +12 -6
- package/dist/commands/run/command.d.ts +1 -0
- package/dist/commands/run/command.js +4 -1
- package/dist/commands/run/record-init.d.ts +2 -0
- package/dist/commands/run/record-init.js +8 -1
- package/dist/commands/run/spec-provenance.d.ts +37 -0
- package/dist/commands/run/spec-provenance.js +384 -0
- package/dist/commands/run/validation.d.ts +4 -0
- package/dist/commands/run/validation.js +25 -62
- package/dist/commands/shared/resolve-stage-competitors.js +2 -1
- package/dist/commands/spec/command.js +64 -138
- package/dist/commands/spec/errors.d.ts +5 -0
- package/dist/commands/spec/errors.js +9 -0
- package/dist/commands/verify/agents.d.ts +4 -2
- package/dist/commands/verify/agents.js +4 -11
- package/dist/commands/verify/command.js +23 -6
- package/dist/commands/verify/errors.d.ts +12 -0
- package/dist/commands/verify/errors.js +22 -0
- package/dist/commands/verify/lifecycle.js +1 -1
- package/dist/commands/verify/targets.js +108 -12
- package/dist/competition/shared/preflight.d.ts +1 -1
- package/dist/competition/shared/preflight.js +15 -2
- package/dist/competition/shared/teardown.d.ts +7 -0
- package/dist/competition/shared/teardown.js +6 -0
- package/dist/configs/agents/defaults.js +13 -44
- package/dist/configs/agents/loader.js +1 -1
- package/dist/configs/environment/loader.js +2 -1
- package/dist/configs/orchestration/loader.js +2 -1
- package/dist/configs/sandbox/loader.js +2 -1
- package/dist/configs/settings/loader.js +1 -1
- package/dist/configs/verification/loader.js +2 -1
- package/dist/contracts/list.d.ts +129 -149
- package/dist/contracts/list.js +47 -99
- package/dist/domain/interactive/model/types.d.ts +2 -0
- package/dist/domain/interactive/model/types.js +16 -1
- package/dist/domain/interactive/persistence/adapter.d.ts +23 -0
- package/dist/domain/interactive/persistence/adapter.js +67 -5
- package/dist/domain/interactive/prompt.d.ts +1 -1
- package/dist/domain/interactive/prompt.js +1 -1
- package/dist/domain/interactive/session-env.d.ts +10 -0
- package/dist/domain/interactive/session-env.js +25 -0
- package/dist/domain/message/competition/adapter.js +3 -9
- package/dist/domain/message/model/types.d.ts +32 -1
- package/dist/domain/message/model/types.js +25 -1
- package/dist/domain/reduce/competition/adapter.js +30 -16
- package/dist/domain/reduce/competition/finalize.d.ts +7 -0
- package/dist/domain/reduce/competition/finalize.js +19 -0
- package/dist/domain/reduce/model/types.d.ts +3 -3
- package/dist/domain/run/competition/agents/artifacts.js +4 -2
- package/dist/domain/run/competition/agents/lifecycle.js +1 -1
- package/dist/domain/run/competition/agents/workspace.js +2 -1
- package/dist/domain/run/competition/errors.d.ts +1 -1
- package/dist/domain/run/competition/errors.js +4 -7
- package/dist/domain/run/competition/reports.js +2 -1
- package/dist/domain/run/model/enhanced.d.ts +1 -1
- package/dist/domain/run/model/enhanced.js +2 -1
- package/dist/domain/run/model/types.d.ts +384 -0
- package/dist/domain/run/model/types.js +87 -0
- package/dist/domain/spec/competition/adapter.d.ts +1 -0
- package/dist/domain/spec/competition/adapter.js +9 -10
- package/dist/domain/spec/model/mutators.d.ts +20 -0
- package/dist/domain/spec/model/mutators.js +146 -0
- package/dist/domain/spec/model/types.d.ts +3 -0
- package/dist/domain/spec/model/types.js +5 -0
- package/dist/domain/spec/persistence/adapter.d.ts +1 -0
- package/dist/domain/spec/persistence/adapter.js +7 -2
- package/dist/domain/verify/competition/adapter.d.ts +1 -1
- package/dist/domain/verify/competition/adapter.js +4 -9
- package/dist/domain/verify/competition/finalize.d.ts +9 -0
- package/dist/domain/verify/competition/finalize.js +22 -3
- package/dist/domain/verify/competition/programmatic.js +2 -1
- package/dist/domain/verify/competition/prompt.js +1 -1
- package/dist/domain/verify/competition/shared-layout.js +1 -1
- package/dist/domain/verify/model/types.d.ts +2 -2
- package/dist/interactive/providers/launch.d.ts +2 -0
- package/dist/interactive/providers/launch.js +19 -2
- package/dist/interactive/providers/mcp.d.ts +1 -0
- package/dist/interactive/providers/mcp.js +45 -7
- package/dist/interactive/substrate.js +32 -5
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +337 -44
- package/dist/policy/auto.d.ts +0 -1
- package/dist/policy/auto.js +3 -14
- package/dist/policy/verification.js +18 -1
- package/dist/preflight/agents.d.ts +24 -0
- package/dist/preflight/agents.js +71 -0
- package/dist/preflight/environment.d.ts +6 -0
- package/dist/preflight/environment.js +17 -0
- package/dist/preflight/formatting.d.ts +5 -0
- package/dist/preflight/formatting.js +20 -0
- package/dist/preflight/index.d.ts +2 -0
- package/dist/preflight/index.js +6 -9
- package/dist/preflight/operator.d.ts +32 -0
- package/dist/preflight/operator.js +40 -0
- package/dist/preflight/settings.d.ts +2 -0
- package/dist/preflight/settings.js +17 -0
- package/dist/render/transcripts/apply.js +2 -1
- package/dist/render/transcripts/interactive.d.ts +16 -0
- package/dist/render/transcripts/interactive.js +42 -0
- package/dist/render/transcripts/list.d.ts +41 -0
- package/dist/render/transcripts/list.js +152 -3
- package/dist/render/transcripts/message.d.ts +3 -5
- package/dist/render/transcripts/message.js +29 -74
- package/dist/render/transcripts/reduce.d.ts +2 -4
- package/dist/render/transcripts/reduce.js +31 -75
- package/dist/render/transcripts/root-launcher.js +2 -12
- package/dist/render/transcripts/run.d.ts +4 -4
- package/dist/render/transcripts/run.js +36 -47
- package/dist/render/transcripts/spec.d.ts +1 -4
- package/dist/render/transcripts/spec.js +15 -62
- package/dist/render/transcripts/verify.d.ts +6 -7
- package/dist/render/transcripts/verify.js +54 -85
- package/dist/render/utils/cli-writer.d.ts +4 -0
- package/dist/render/utils/cli-writer.js +1 -0
- package/dist/render/utils/duration.d.ts +5 -0
- package/dist/render/utils/duration.js +6 -0
- package/dist/render/utils/progressive-render.d.ts +3 -0
- package/dist/render/utils/progressive-render.js +44 -0
- package/dist/render/utils/runs.d.ts +1 -0
- package/dist/render/utils/runs.js +1 -0
- package/dist/render/utils/transcript-shell.d.ts +2 -1
- package/dist/render/utils/transcript-shell.js +19 -6
- package/dist/utils/diff.d.ts +2 -0
- package/dist/utils/diff.js +1 -0
- package/dist/utils/errors.d.ts +2 -1
- package/dist/utils/errors.js +3 -1
- package/dist/utils/git.d.ts +1 -1
- package/dist/utils/git.js +25 -2
- package/dist/utils/list-target.d.ts +4 -0
- package/dist/utils/list-target.js +35 -0
- package/dist/utils/swarm-session-ack.d.ts +9 -0
- package/dist/utils/swarm-session-ack.js +17 -0
- package/dist/utils/terminal.d.ts +1 -0
- package/dist/utils/terminal.js +11 -0
- package/dist/workspace/artifact-paths.d.ts +55 -0
- package/dist/workspace/artifact-paths.js +106 -0
- package/dist/workspace/chat/artifacts.d.ts +7 -0
- package/dist/workspace/chat/artifacts.js +95 -4
- package/dist/workspace/chat/native-usage.js +1 -1
- package/dist/workspace/chat/sources.d.ts +2 -5
- package/dist/workspace/chat/sources.js +4 -4
- package/dist/workspace/constants.d.ts +47 -0
- package/dist/workspace/constants.js +47 -0
- package/dist/workspace/errors.js +2 -2
- package/dist/workspace/layout.js +3 -1
- package/dist/workspace/managed-state.d.ts +32 -0
- package/dist/workspace/managed-state.js +104 -0
- package/dist/workspace/path-formatters.d.ts +9 -0
- package/dist/workspace/path-formatters.js +46 -0
- package/dist/workspace/path-resolvers.d.ts +1 -0
- package/dist/workspace/path-resolvers.js +5 -0
- package/dist/workspace/session-paths.d.ts +16 -0
- package/dist/workspace/session-paths.js +59 -0
- package/dist/workspace/setup.js +67 -2
- package/dist/workspace/shim.d.ts +1 -0
- package/dist/workspace/shim.js +3 -3
- package/package.json +2 -2
- package/dist/cli/init.d.ts +0 -15
- package/dist/cli/init.js +0 -70
- package/dist/commands/init/agents.d.ts +0 -4
- package/dist/commands/init/command.d.ts +0 -2
- package/dist/commands/init/environment.d.ts +0 -2
- package/dist/render/transcripts/init.d.ts +0 -7
- package/dist/render/transcripts/init.js +0 -83
- package/dist/workspace/structure.d.ts +0 -143
- package/dist/workspace/structure.js +0 -319
- /package/dist/commands/{init/types.js → doctor/fix-types.js} +0 -0
|
@@ -6,7 +6,7 @@ import process from "node:process";
|
|
|
6
6
|
import { collectProviderArtifacts, prepareProviderArtifactCaptureContext, } from "../agents/launch/chat.js";
|
|
7
7
|
import { writeStagedPrompt } from "../agents/launch/prompt.js";
|
|
8
8
|
import { resolveAgentProviderForDefinition } from "../agents/launch/provider-state.js";
|
|
9
|
-
import { clearActiveInteractive, finalizeActiveInteractive, registerActiveInteractive, } from "../commands/interactive/lifecycle.js";
|
|
9
|
+
import { clearActiveInteractive, finalizeActiveInteractive, getActiveInteractiveTerminationStatus, registerActiveInteractive, } from "../commands/interactive/lifecycle.js";
|
|
10
10
|
import { createTeardownController, runTeardown, } from "../competition/shared/teardown.js";
|
|
11
11
|
import { AgentBinaryAccessError, AgentBinaryMissingError, AgentDisabledError, AgentNotFoundError, } from "../configs/agents/errors.js";
|
|
12
12
|
import { loadAgentById } from "../configs/agents/loader.js";
|
|
@@ -14,6 +14,7 @@ import { resolveFirstPartyLaunchPrompt } from "../domain/interactive/prompt.js";
|
|
|
14
14
|
import { toErrorMessage } from "../utils/errors.js";
|
|
15
15
|
import { isMissing } from "../utils/fs.js";
|
|
16
16
|
import { generateSessionId } from "../utils/session-id.js";
|
|
17
|
+
import { normalizeInteractiveTerm } from "../utils/terminal.js";
|
|
17
18
|
import { resolveVoratiqCliTarget } from "../utils/voratiq-cli-target.js";
|
|
18
19
|
import { createBundledVoratiqToolDeclaration, prepareProviderNativeLaunch, resolveFirstPartyMcpStatus, } from "./providers.js";
|
|
19
20
|
import { appendInteractiveSessionRecord, ensureInteractiveSessionDirectories, resolveInteractiveSessionPaths, rewriteInteractiveSessionRecord, toInteractiveSessionRelativePath, } from "./records.js";
|
|
@@ -127,6 +128,7 @@ export async function prepareNativeInteractiveSession(options) {
|
|
|
127
128
|
try {
|
|
128
129
|
firstPartyMcpResolution = await resolveFirstPartyMcpStatus({
|
|
129
130
|
providerId,
|
|
131
|
+
providerBinary: agent.binary,
|
|
130
132
|
root: options.root,
|
|
131
133
|
toolDeclarations,
|
|
132
134
|
promptForMcpInstall: options.promptForMcpInstall,
|
|
@@ -169,6 +171,11 @@ export async function prepareNativeInteractiveSession(options) {
|
|
|
169
171
|
agent,
|
|
170
172
|
root: options.root,
|
|
171
173
|
toolDeclarations,
|
|
174
|
+
sessionScopedMcpEnv: providerId === "codex"
|
|
175
|
+
? {
|
|
176
|
+
VORATIQ_INTERACTIVE_SESSION_ID: sessionId,
|
|
177
|
+
}
|
|
178
|
+
: undefined,
|
|
172
179
|
prompt,
|
|
173
180
|
launchMode: options.launchMode,
|
|
174
181
|
firstPartyMcpResolution,
|
|
@@ -182,8 +189,8 @@ export async function prepareNativeInteractiveSession(options) {
|
|
|
182
189
|
...process.env,
|
|
183
190
|
...providerLaunch.env,
|
|
184
191
|
VORATIQ_INTERACTIVE_SESSION_ID: sessionId,
|
|
185
|
-
VORATIQ_INTERACTIVE_SESSION_ROOT: paths.sessionRoot,
|
|
186
192
|
};
|
|
193
|
+
delete invocationEnv.VORATIQ_INTERACTIVE_SESSION_ROOT;
|
|
187
194
|
let artifactCaptureContext;
|
|
188
195
|
if (providerLaunch.artifactCaptureSupported) {
|
|
189
196
|
try {
|
|
@@ -191,6 +198,13 @@ export async function prepareNativeInteractiveSession(options) {
|
|
|
191
198
|
providerId,
|
|
192
199
|
sessionRoot: paths.sessionRoot,
|
|
193
200
|
searchEnv: invocationEnv,
|
|
201
|
+
selectionHint: providerId === "codex"
|
|
202
|
+
? {
|
|
203
|
+
strategy: "codex-session-meta",
|
|
204
|
+
cwd: cwd.path,
|
|
205
|
+
minStartedAt: createdAt,
|
|
206
|
+
}
|
|
207
|
+
: undefined,
|
|
194
208
|
});
|
|
195
209
|
}
|
|
196
210
|
catch {
|
|
@@ -251,9 +265,15 @@ export async function spawnPreparedInteractiveSession(prepared, options = {}) {
|
|
|
251
265
|
if (stdio === "inherit") {
|
|
252
266
|
process.stdout.write("\n");
|
|
253
267
|
}
|
|
268
|
+
const spawnEnv = stdio === "inherit"
|
|
269
|
+
? {
|
|
270
|
+
...prepared.invocation.env,
|
|
271
|
+
TERM: normalizeInteractiveTerm(prepared.invocation.env),
|
|
272
|
+
}
|
|
273
|
+
: prepared.invocation.env;
|
|
254
274
|
const child = spawn(prepared.invocation.command, prepared.invocation.args, {
|
|
255
275
|
cwd: prepared.invocation.cwd,
|
|
256
|
-
env:
|
|
276
|
+
env: spawnEnv,
|
|
257
277
|
stdio,
|
|
258
278
|
});
|
|
259
279
|
const completion = createProcessCompletionPromise(prepared, child);
|
|
@@ -321,9 +341,11 @@ function createProcessCompletionPromise(prepared, child) {
|
|
|
321
341
|
return;
|
|
322
342
|
}
|
|
323
343
|
finalized = true;
|
|
344
|
+
const terminationStatus = getActiveInteractiveTerminationStatus(prepared.sessionId);
|
|
345
|
+
const signalCountsAsSuccess = terminationStatus === "aborted" && options.signal !== null;
|
|
324
346
|
const runtimeFailureMessage = options.spawnError
|
|
325
347
|
? `Failed during provider execution: ${options.spawnError.message}`
|
|
326
|
-
: options.signal
|
|
348
|
+
: options.signal && !signalCountsAsSuccess
|
|
327
349
|
? `Provider process terminated by signal ${options.signal}`
|
|
328
350
|
: options.exitCode && options.exitCode !== 0
|
|
329
351
|
? `Provider process exited with code ${options.exitCode}`
|
|
@@ -509,10 +531,15 @@ function failure(kind, code, message, cause) {
|
|
|
509
531
|
};
|
|
510
532
|
}
|
|
511
533
|
function buildBaseRecord(options) {
|
|
512
|
-
const { sessionId, createdAt, status, agentId, toolAttachmentStatus, chat, error, } = options;
|
|
534
|
+
const { sessionId, createdAt, status, agentId, toolAttachmentStatus, startedAt, completedAt, chat, error, } = options;
|
|
535
|
+
const resolvedStartedAt = startedAt ?? createdAt;
|
|
513
536
|
return {
|
|
514
537
|
sessionId,
|
|
515
538
|
createdAt,
|
|
539
|
+
startedAt: resolvedStartedAt,
|
|
540
|
+
...(status !== "running"
|
|
541
|
+
? { completedAt: completedAt ?? resolvedStartedAt }
|
|
542
|
+
: {}),
|
|
516
543
|
status,
|
|
517
544
|
agentId,
|
|
518
545
|
toolAttachmentStatus,
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -62,6 +62,7 @@ interface JsonRpcErrorResponse {
|
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
type JsonRpcResponse = JsonRpcSuccessResponse | JsonRpcErrorResponse;
|
|
65
|
+
export declare const VORATIQ_GUIDE_RESOURCE_URI: "voratiq://guide";
|
|
65
66
|
export declare function getVoratiqMcpToolDefinitions(): readonly McpToolDefinition[];
|
|
66
67
|
export declare function createVoratiqMcpRequestHandler(options?: CreateVoratiqMcpRequestHandlerOptions): {
|
|
67
68
|
handleRequest: (message: JsonRpcRequestMessage) => Promise<JsonRpcResponse>;
|
package/dist/mcp/server.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
2
5
|
import process from "node:process";
|
|
3
6
|
import { z } from "zod";
|
|
4
|
-
import { externalApplyExecutionInputSchema,
|
|
5
|
-
import { operatorResultEnvelopeSchema, } from "../cli/operator-envelope.js";
|
|
6
|
-
import { listJsonOutputSchema, } from "../contracts/list.js";
|
|
7
|
+
import { externalApplyExecutionInputSchema, externalInspectionOperatorSchema, externalMessageExecutionInputSchema, externalPruneExecutionInputSchema, externalReduceExecutionInputSchema, externalRunExecutionInputSchema, externalSpecExecutionInputSchema, externalVerifyExecutionInputSchema, } from "../cli/contract.js";
|
|
8
|
+
import { buildSwarmSessionAcknowledgementEnvelope, operatorResultEnvelopeSchema, } from "../cli/operator-envelope.js";
|
|
9
|
+
import { listJsonModes, listJsonModeSchema, listJsonOutputSchema, } from "../contracts/list.js";
|
|
10
|
+
import { VORATIQ_MCP_ACK_OPERATOR_ENV, VORATIQ_MCP_ACK_PATH_ENV, } from "../utils/swarm-session-ack.js";
|
|
7
11
|
import { getVoratiqVersion } from "../utils/version.js";
|
|
8
12
|
import { createEntrypointVoratiqCliTarget as createEntrypointCliTarget, resolveVoratiqCliTarget, } from "../utils/voratiq-cli-target.js";
|
|
9
13
|
const JSON_RPC_VERSION = "2.0";
|
|
@@ -14,6 +18,8 @@ const JSON_RPC_INVALID_REQUEST = -32600;
|
|
|
14
18
|
const JSON_RPC_METHOD_NOT_FOUND = -32601;
|
|
15
19
|
const JSON_RPC_INVALID_PARAMS = -32602;
|
|
16
20
|
const JSON_RPC_INTERNAL_ERROR = -32603;
|
|
21
|
+
const SWARM_EARLY_ACK_TIMEOUT_MS = 15_000;
|
|
22
|
+
const SWARM_EARLY_ACK_POLL_INTERVAL_MS = 100;
|
|
17
23
|
export const VORATIQ_MCP_PROTOCOL_VERSION = "2025-11-25";
|
|
18
24
|
export const VORATIQ_SUPPORTED_MCP_PROTOCOL_VERSIONS = [
|
|
19
25
|
VORATIQ_MCP_PROTOCOL_VERSION,
|
|
@@ -23,6 +29,25 @@ export const VORATIQ_SUPPORTED_MCP_PROTOCOL_VERSIONS = [
|
|
|
23
29
|
function isSupportedMcpProtocolVersion(protocolVersion) {
|
|
24
30
|
return VORATIQ_SUPPORTED_MCP_PROTOCOL_VERSIONS.includes(protocolVersion);
|
|
25
31
|
}
|
|
32
|
+
const mcpListInspectionInputSchema = z.discriminatedUnion("mode", [
|
|
33
|
+
z
|
|
34
|
+
.object({
|
|
35
|
+
operator: externalInspectionOperatorSchema,
|
|
36
|
+
mode: z.literal(listJsonModes[0]),
|
|
37
|
+
verbose: z.boolean().optional(),
|
|
38
|
+
limit: z.number().int().positive().optional(),
|
|
39
|
+
})
|
|
40
|
+
.strict(),
|
|
41
|
+
z
|
|
42
|
+
.object({
|
|
43
|
+
operator: externalInspectionOperatorSchema,
|
|
44
|
+
mode: z.literal(listJsonModes[1]),
|
|
45
|
+
sessionId: z.string().min(1),
|
|
46
|
+
verbose: z.boolean().optional(),
|
|
47
|
+
limit: z.number().int().positive().optional(),
|
|
48
|
+
})
|
|
49
|
+
.strict(),
|
|
50
|
+
]);
|
|
26
51
|
const initializeRequestParamsSchema = z
|
|
27
52
|
.object({
|
|
28
53
|
protocolVersion: z.string(),
|
|
@@ -70,7 +95,7 @@ const toolSpecs = [
|
|
|
70
95
|
{
|
|
71
96
|
name: "voratiq_message",
|
|
72
97
|
operator: "message",
|
|
73
|
-
description: "Send an isolated prompt to one or more Voratiq agents and persist their independent replies as a
|
|
98
|
+
description: "Send an isolated prompt to one or more Voratiq agents and persist their independent replies as a recorded message session.",
|
|
74
99
|
inputSchemaSource: externalMessageExecutionInputSchema,
|
|
75
100
|
buildArgs: (input) => buildMessageExecutionArgs(input),
|
|
76
101
|
outputContract: "execution",
|
|
@@ -86,8 +111,8 @@ const toolSpecs = [
|
|
|
86
111
|
{
|
|
87
112
|
name: "voratiq_list",
|
|
88
113
|
operator: "list",
|
|
89
|
-
description: "List recorded Voratiq sessions for one operator (`spec`, `run`, `reduce`, `verify`, or `
|
|
90
|
-
inputSchemaSource:
|
|
114
|
+
description: "List recorded Voratiq sessions for one operator (`spec`, `run`, `reduce`, `verify`, `message`, or `interactive`) in list or detail mode.",
|
|
115
|
+
inputSchemaSource: mcpListInspectionInputSchema,
|
|
91
116
|
mcpInputSchema: createListMcpInputSchema(),
|
|
92
117
|
buildArgs: (input) => buildListInspectionArgs(input),
|
|
93
118
|
outputContract: "list",
|
|
@@ -107,7 +132,70 @@ const toolDefinitions = toolSpecs.map((tool) => ({
|
|
|
107
132
|
description: tool.description,
|
|
108
133
|
inputSchema: tool.mcpInputSchema ?? toToolInputJsonSchema(tool.inputSchemaSource),
|
|
109
134
|
}));
|
|
110
|
-
const
|
|
135
|
+
export const VORATIQ_GUIDE_RESOURCE_URI = "voratiq://guide";
|
|
136
|
+
const VORATIQ_GUIDE_RESOURCE_CONTENT = `# Voratiq Operator Guide
|
|
137
|
+
|
|
138
|
+
Voratiq is a workflow system built around composable operators that launch, evaluate, and manage multi-agent work against a repository. It gives interactive agents a structured way to delegate coding tasks, inspect recorded state, verify outcomes, and apply accepted changes without doing all of that inline.
|
|
139
|
+
|
|
140
|
+
## Operator Classes
|
|
141
|
+
|
|
142
|
+
Voratiq operators fall into two main classes:
|
|
143
|
+
|
|
144
|
+
- **Swarm operators** dispatch agents to produce, synthesize, or evaluate work: spec, run, reduce, verify, message
|
|
145
|
+
- **Control operators** inspect state or mutate accepted outcomes: list, apply, prune
|
|
146
|
+
|
|
147
|
+
## Swarm Operators
|
|
148
|
+
|
|
149
|
+
**spec** – Drafts or refines a specification for a task from a description, an existing spec, or related repository context. Launches one or more spec agents and records their outputs as a spec session.
|
|
150
|
+
|
|
151
|
+
**run** – Executes a spec session by launching run agents that read the spec, work against a sandboxed workspace, and produce artifacts including diffs and transcripts. Records a run session.
|
|
152
|
+
|
|
153
|
+
**reduce** – Summarizes artifacts from a spec, run, or message session into a single reduced output suitable for comparison or follow-on work. Records a reduce session.
|
|
154
|
+
|
|
155
|
+
**verify** – Evaluates a spec, run, reduction, or message session and records a structured verdict. This is Voratiq's main decision operator: use it to compare outputs, choose stronger candidates, and decide whether work should be applied, inspected further, rerun, or redirected.
|
|
156
|
+
|
|
157
|
+
**message** – Sends an isolated prompt to one or more agents and persists each reply independently as a message session. Use for standalone questions, reviews, or exploration that does not require a full spec/run workflow.
|
|
158
|
+
|
|
159
|
+
## Control Operators
|
|
160
|
+
|
|
161
|
+
**list** – Lists or inspects recorded sessions for a given operator. This is the primary way to inspect swarm sessions; use it to poll progress, retrieve session IDs, and inspect recorded workflow state.
|
|
162
|
+
|
|
163
|
+
**apply** – Applies an accepted run diff into the current working tree. Synchronous and non-durable; only invoke after verifying that the target run is in an acceptable state.
|
|
164
|
+
|
|
165
|
+
**prune** – Removes pruneable run workspaces or all pruneable state. Synchronous and non-durable; requires explicit confirmation.
|
|
166
|
+
|
|
167
|
+
## Workflow Composition
|
|
168
|
+
|
|
169
|
+
Operators compose into many workflow shapes rather than one required path. Common patterns include: using message for standalone exploration or review; using spec → verify to compare candidate specs before execution; using spec → run when a task needs structured execution; using run → verify to choose among competing implementations; using reduce when multiple outputs need synthesis before a decision; and using verify whenever a workflow needs a structured recommendation instead of ad hoc judgment. The list operator can be called at any point to inspect recorded state across all operators.
|
|
170
|
+
|
|
171
|
+
## Swarm Session Behavior
|
|
172
|
+
|
|
173
|
+
The five swarm operators are spec, run, reduce, verify, and message. Each one creates a recorded session and may return before the session is finished. Once a session has been created, treat that session as the unit of work. A returned sessionId means the work has been launched, not completed. Use voratiq_list to inspect active sessions.
|
|
174
|
+
|
|
175
|
+
## Status Interpretation
|
|
176
|
+
|
|
177
|
+
Session status is primary; recipient status is supporting detail.
|
|
178
|
+
|
|
179
|
+
- **queued** means the session has been accepted and recorded but its work has not started yet.
|
|
180
|
+
- **running** means the session is active and remains the canonical in-flight unit of work.
|
|
181
|
+
- **succeeded** means the session reached a successful terminal state; inspect its outputs and decide what should happen next.
|
|
182
|
+
- **failed** means the session reached a terminal failure state.
|
|
183
|
+
- **unresolved** means the session reached a terminal state without a clear winner or confident decision.
|
|
184
|
+
|
|
185
|
+
Mixed recipient states do not imply session failure. Some recipients may fail while others continue running, and the session remains active until its session status becomes terminal.
|
|
186
|
+
|
|
187
|
+
## extraContext Contract
|
|
188
|
+
|
|
189
|
+
The extraContext field accepts an array of file paths pointing to additional readable files staged alongside the operator workspace. Pass file paths only — not raw text content, and not paths to files that operators already see by default (such as standard repository context). Passing raw content or redundant paths increases token usage without providing new information.
|
|
190
|
+
|
|
191
|
+
## maxParallel Semantics
|
|
192
|
+
|
|
193
|
+
The maxParallel field controls the maximum number of agent recipients running in parallel for an operator invocation. Set it deliberately: it directly affects cost and latency. Higher values increase concurrency but also increase total token expenditure and can create contention. Do not treat maxParallel as a free dial to increase throughput without modeling the downstream cost and latency impact.
|
|
194
|
+
|
|
195
|
+
## Key Discipline Rules
|
|
196
|
+
|
|
197
|
+
Commit to one workflow objective per session; do not interleave unrelated operator calls in the same sequence. Wait for stage boundaries before acting on results: read voratiq_list output before proceeding from one stage to the next. Use voratiq_list as the primary control plane for inspecting recorded state rather than reading session files directly.`;
|
|
198
|
+
const VORATIQ_MCP_SERVER_INSTRUCTIONS = "Voratiq tools operate on Voratiq workflow state in the current repository. Use voratiq_list for questions about recent or specific spec, run, reduce, verify, message, or interactive sessions. The swarm operators (voratiq_spec, voratiq_run, voratiq_reduce, voratiq_verify, voratiq_message) create recorded sessions and may acknowledge before finishing; once launched, treat the session as the unit of work. If a swarm call times out or returns a non-terminal status, inspect progress with voratiq_list instead of retrying. Use voratiq_apply and voratiq_prune for synchronous control actions. Prefer these tools over shell inspection when the task is about Voratiq workflow history or state.";
|
|
111
199
|
const toolSpecsByName = new Map(toolSpecs.map((tool) => [tool.name, tool]));
|
|
112
200
|
export function getVoratiqMcpToolDefinitions() {
|
|
113
201
|
return toolDefinitions;
|
|
@@ -144,6 +232,7 @@ export function createVoratiqMcpRequestHandler(options = {}) {
|
|
|
144
232
|
tools: {
|
|
145
233
|
listChanged: true,
|
|
146
234
|
},
|
|
235
|
+
resources: {},
|
|
147
236
|
},
|
|
148
237
|
instructions: VORATIQ_MCP_SERVER_INSTRUCTIONS,
|
|
149
238
|
serverInfo: {
|
|
@@ -185,6 +274,33 @@ export function createVoratiqMcpRequestHandler(options = {}) {
|
|
|
185
274
|
});
|
|
186
275
|
return createSuccessResponse(message.id, result);
|
|
187
276
|
}
|
|
277
|
+
if (message.method === "resources/list") {
|
|
278
|
+
return createSuccessResponse(message.id, {
|
|
279
|
+
resources: [
|
|
280
|
+
{
|
|
281
|
+
uri: VORATIQ_GUIDE_RESOURCE_URI,
|
|
282
|
+
name: "Voratiq Operator Guide",
|
|
283
|
+
description: "Complete reference for Voratiq operators, workflow composition, swarm-session behavior, extraContext contract, and maxParallel semantics.",
|
|
284
|
+
mimeType: "text/plain",
|
|
285
|
+
},
|
|
286
|
+
],
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
if (message.method === "resources/read") {
|
|
290
|
+
const uri = isRecord(message.params) ? message.params.uri : undefined;
|
|
291
|
+
if (uri === VORATIQ_GUIDE_RESOURCE_URI) {
|
|
292
|
+
return createSuccessResponse(message.id, {
|
|
293
|
+
contents: [
|
|
294
|
+
{
|
|
295
|
+
uri: VORATIQ_GUIDE_RESOURCE_URI,
|
|
296
|
+
mimeType: "text/plain",
|
|
297
|
+
text: VORATIQ_GUIDE_RESOURCE_CONTENT,
|
|
298
|
+
},
|
|
299
|
+
],
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
return createErrorResponse(message.id, JSON_RPC_INVALID_PARAMS, `Unknown resource URI: ${String(uri)}`);
|
|
303
|
+
}
|
|
188
304
|
return createErrorResponse(message.id, JSON_RPC_METHOD_NOT_FOUND, `Method not found: ${message.method}`);
|
|
189
305
|
},
|
|
190
306
|
handleNotification(message) {
|
|
@@ -207,7 +323,10 @@ export async function runVoratiqMcpStdioServer(options = {}) {
|
|
|
207
323
|
const pendingPayloads = [];
|
|
208
324
|
let isDraining = false;
|
|
209
325
|
let hasEnded = false;
|
|
326
|
+
let inFlightHandlers = 0;
|
|
327
|
+
let hasCompletedInitialize = false;
|
|
210
328
|
let transportEncoding = "framed";
|
|
329
|
+
let writeChain = Promise.resolve();
|
|
211
330
|
await new Promise((resolve, reject) => {
|
|
212
331
|
const tryResolve = () => {
|
|
213
332
|
if (!hasEnded) {
|
|
@@ -219,8 +338,53 @@ export async function runVoratiqMcpStdioServer(options = {}) {
|
|
|
219
338
|
if (pendingPayloads.length > 0) {
|
|
220
339
|
return;
|
|
221
340
|
}
|
|
341
|
+
if (inFlightHandlers > 0) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
222
344
|
resolve();
|
|
223
345
|
};
|
|
346
|
+
const writeMessageSerialized = (outputEncoding, message) => {
|
|
347
|
+
writeChain = writeChain.then(() => {
|
|
348
|
+
writeMessage(stdout, outputEncoding, message);
|
|
349
|
+
});
|
|
350
|
+
return writeChain;
|
|
351
|
+
};
|
|
352
|
+
const handlePayload = async (payload, outputEncoding) => {
|
|
353
|
+
try {
|
|
354
|
+
const parsed = JSON.parse(payload);
|
|
355
|
+
const message = normalizeIncomingMessage(parsed);
|
|
356
|
+
if (!message) {
|
|
357
|
+
await writeMessageSerialized(outputEncoding, createErrorResponse(null, JSON_RPC_INVALID_REQUEST, "Invalid JSON-RPC message."));
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
if ("id" in message) {
|
|
361
|
+
const response = await requestHandler.handleRequest(message);
|
|
362
|
+
await writeMessageSerialized(outputEncoding, response);
|
|
363
|
+
if (message.method === "initialize" && !("error" in response)) {
|
|
364
|
+
hasCompletedInitialize = true;
|
|
365
|
+
await writeMessageSerialized(outputEncoding, createNotification("notifications/tools/list_changed"));
|
|
366
|
+
}
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
await requestHandler.handleNotification(message);
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
if (error instanceof SyntaxError) {
|
|
373
|
+
await writeMessageSerialized(outputEncoding, createErrorResponse(null, JSON_RPC_PARSE_ERROR, "Failed to parse JSON-RPC payload.", { message: error.message }));
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
await writeMessageSerialized(outputEncoding, createErrorResponse(null, JSON_RPC_INTERNAL_ERROR, "Unhandled MCP server error.", {
|
|
377
|
+
message: toErrorMessage(error),
|
|
378
|
+
}));
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
const dispatchPayload = (payload, outputEncoding) => {
|
|
382
|
+
inFlightHandlers += 1;
|
|
383
|
+
return handlePayload(payload, outputEncoding).finally(() => {
|
|
384
|
+
inFlightHandlers -= 1;
|
|
385
|
+
tryResolve();
|
|
386
|
+
});
|
|
387
|
+
};
|
|
224
388
|
const drainQueue = () => {
|
|
225
389
|
if (isDraining) {
|
|
226
390
|
return;
|
|
@@ -228,36 +392,15 @@ export async function runVoratiqMcpStdioServer(options = {}) {
|
|
|
228
392
|
isDraining = true;
|
|
229
393
|
void (async () => {
|
|
230
394
|
while (pendingPayloads.length > 0) {
|
|
231
|
-
const
|
|
232
|
-
if (
|
|
395
|
+
const queued = pendingPayloads.shift();
|
|
396
|
+
if (queued === undefined) {
|
|
233
397
|
continue;
|
|
234
398
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (!message) {
|
|
239
|
-
writeMessage(stdout, transportEncoding, createErrorResponse(null, JSON_RPC_INVALID_REQUEST, "Invalid JSON-RPC message."));
|
|
240
|
-
continue;
|
|
241
|
-
}
|
|
242
|
-
if ("id" in message) {
|
|
243
|
-
const response = await requestHandler.handleRequest(message);
|
|
244
|
-
writeMessage(stdout, transportEncoding, response);
|
|
245
|
-
if (message.method === "initialize" && !("error" in response)) {
|
|
246
|
-
writeMessage(stdout, transportEncoding, createNotification("notifications/tools/list_changed"));
|
|
247
|
-
}
|
|
248
|
-
continue;
|
|
249
|
-
}
|
|
250
|
-
await requestHandler.handleNotification(message);
|
|
251
|
-
}
|
|
252
|
-
catch (error) {
|
|
253
|
-
if (error instanceof SyntaxError) {
|
|
254
|
-
writeMessage(stdout, transportEncoding, createErrorResponse(null, JSON_RPC_PARSE_ERROR, "Failed to parse JSON-RPC payload.", { message: error.message }));
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
writeMessage(stdout, transportEncoding, createErrorResponse(null, JSON_RPC_INTERNAL_ERROR, "Unhandled MCP server error.", {
|
|
258
|
-
message: toErrorMessage(error),
|
|
259
|
-
}));
|
|
399
|
+
if (!hasCompletedInitialize) {
|
|
400
|
+
await dispatchPayload(queued.payload, queued.transportEncoding);
|
|
401
|
+
continue;
|
|
260
402
|
}
|
|
403
|
+
void dispatchPayload(queued.payload, queued.transportEncoding);
|
|
261
404
|
}
|
|
262
405
|
isDraining = false;
|
|
263
406
|
tryResolve();
|
|
@@ -276,7 +419,10 @@ export async function runVoratiqMcpStdioServer(options = {}) {
|
|
|
276
419
|
break;
|
|
277
420
|
}
|
|
278
421
|
transportEncoding = extracted.transportEncoding;
|
|
279
|
-
pendingPayloads.push(
|
|
422
|
+
pendingPayloads.push({
|
|
423
|
+
payload: extracted.payload,
|
|
424
|
+
transportEncoding,
|
|
425
|
+
});
|
|
280
426
|
buffer = Buffer.from(extracted.remaining);
|
|
281
427
|
}
|
|
282
428
|
drainQueue();
|
|
@@ -285,7 +431,10 @@ export async function runVoratiqMcpStdioServer(options = {}) {
|
|
|
285
431
|
const trailingPayload = extractTrailingJsonLine(buffer);
|
|
286
432
|
if (trailingPayload) {
|
|
287
433
|
transportEncoding = "jsonl";
|
|
288
|
-
pendingPayloads.push(
|
|
434
|
+
pendingPayloads.push({
|
|
435
|
+
payload: trailingPayload,
|
|
436
|
+
transportEncoding,
|
|
437
|
+
});
|
|
289
438
|
buffer = Buffer.alloc(0);
|
|
290
439
|
drainQueue();
|
|
291
440
|
}
|
|
@@ -498,10 +647,20 @@ function appendOptionalTrueFlag(args, flag, enabled) {
|
|
|
498
647
|
}
|
|
499
648
|
export { createEntrypointCliTarget, resolveVoratiqCliTarget };
|
|
500
649
|
export function createDefaultCliJsonContractInvoker(target = resolveVoratiqCliTarget()) {
|
|
501
|
-
return async (input) =>
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
650
|
+
return async (input) => {
|
|
651
|
+
if (isSwarmExecutionOperator(input.operator)) {
|
|
652
|
+
return await invokeSwarmSubprocessWithEarlyAck({
|
|
653
|
+
command: target.command,
|
|
654
|
+
args: [...target.argsPrefix, ...input.args],
|
|
655
|
+
operator: input.operator,
|
|
656
|
+
cwd: process.cwd(),
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
return await invokeSubprocess({
|
|
660
|
+
command: target.command,
|
|
661
|
+
args: [...target.argsPrefix, ...input.args],
|
|
662
|
+
});
|
|
663
|
+
};
|
|
505
664
|
}
|
|
506
665
|
async function invokeSubprocess(options) {
|
|
507
666
|
return await new Promise((resolve) => {
|
|
@@ -547,6 +706,142 @@ async function invokeSubprocess(options) {
|
|
|
547
706
|
});
|
|
548
707
|
});
|
|
549
708
|
}
|
|
709
|
+
async function invokeSwarmSubprocessWithEarlyAck(options) {
|
|
710
|
+
const ackDir = await mkdtemp(join(tmpdir(), "voratiq-mcp-ack-"));
|
|
711
|
+
const ackPath = join(ackDir, "ack.json");
|
|
712
|
+
return await new Promise((resolve) => {
|
|
713
|
+
let settled = false;
|
|
714
|
+
let shouldBufferOutput = true;
|
|
715
|
+
const child = spawn(options.command, options.args, {
|
|
716
|
+
cwd: options.cwd,
|
|
717
|
+
env: {
|
|
718
|
+
...process.env,
|
|
719
|
+
[VORATIQ_MCP_ACK_PATH_ENV]: ackPath,
|
|
720
|
+
[VORATIQ_MCP_ACK_OPERATOR_ENV]: options.operator,
|
|
721
|
+
},
|
|
722
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
723
|
+
});
|
|
724
|
+
const stdoutChunks = [];
|
|
725
|
+
const stderrChunks = [];
|
|
726
|
+
const settle = (result) => {
|
|
727
|
+
if (settled) {
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
settled = true;
|
|
731
|
+
void rm(ackDir, { recursive: true, force: true }).catch(() => { });
|
|
732
|
+
resolve(result);
|
|
733
|
+
};
|
|
734
|
+
child.stdout?.setEncoding("utf8");
|
|
735
|
+
child.stderr?.setEncoding("utf8");
|
|
736
|
+
child.stdout?.on("data", (chunk) => {
|
|
737
|
+
if (shouldBufferOutput) {
|
|
738
|
+
stdoutChunks.push(chunk);
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
child.stderr?.on("data", (chunk) => {
|
|
742
|
+
if (shouldBufferOutput) {
|
|
743
|
+
stderrChunks.push(chunk);
|
|
744
|
+
}
|
|
745
|
+
});
|
|
746
|
+
child.once("error", (error) => {
|
|
747
|
+
settle({
|
|
748
|
+
kind: "spawn_failed",
|
|
749
|
+
error,
|
|
750
|
+
});
|
|
751
|
+
});
|
|
752
|
+
child.once("close", (code) => {
|
|
753
|
+
settle({
|
|
754
|
+
kind: "success",
|
|
755
|
+
exitCode: code ?? 0,
|
|
756
|
+
stdout: stdoutChunks.join(""),
|
|
757
|
+
stderr: stderrChunks.join(""),
|
|
758
|
+
});
|
|
759
|
+
});
|
|
760
|
+
void waitForSwarmSessionObservation({
|
|
761
|
+
ackPath,
|
|
762
|
+
timeoutMs: SWARM_EARLY_ACK_TIMEOUT_MS,
|
|
763
|
+
pollIntervalMs: SWARM_EARLY_ACK_POLL_INTERVAL_MS,
|
|
764
|
+
})
|
|
765
|
+
.then((observation) => {
|
|
766
|
+
if (!observation) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
shouldBufferOutput = false;
|
|
770
|
+
settle({
|
|
771
|
+
kind: "success",
|
|
772
|
+
exitCode: 0,
|
|
773
|
+
stdout: JSON.stringify(buildSwarmSessionAcknowledgementEnvelope({
|
|
774
|
+
operator: options.operator,
|
|
775
|
+
sessionId: observation.sessionId,
|
|
776
|
+
status: observation.status,
|
|
777
|
+
})),
|
|
778
|
+
stderr: "",
|
|
779
|
+
});
|
|
780
|
+
})
|
|
781
|
+
.catch(() => { });
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
function isSwarmExecutionOperator(operator) {
|
|
785
|
+
return (operator === "spec" ||
|
|
786
|
+
operator === "run" ||
|
|
787
|
+
operator === "reduce" ||
|
|
788
|
+
operator === "verify" ||
|
|
789
|
+
operator === "message");
|
|
790
|
+
}
|
|
791
|
+
async function waitForSwarmSessionObservation(options) {
|
|
792
|
+
const deadline = Date.now() + options.timeoutMs;
|
|
793
|
+
while (Date.now() < deadline) {
|
|
794
|
+
const observation = await readSwarmSessionRecord({
|
|
795
|
+
ackPath: options.ackPath,
|
|
796
|
+
});
|
|
797
|
+
if (observation) {
|
|
798
|
+
return observation;
|
|
799
|
+
}
|
|
800
|
+
await sleep(options.pollIntervalMs);
|
|
801
|
+
}
|
|
802
|
+
return undefined;
|
|
803
|
+
}
|
|
804
|
+
async function readSwarmSessionRecord(options) {
|
|
805
|
+
try {
|
|
806
|
+
const raw = await readFile(options.ackPath, "utf8");
|
|
807
|
+
const parsed = JSON.parse(raw);
|
|
808
|
+
if (!isRecord(parsed)) {
|
|
809
|
+
return undefined;
|
|
810
|
+
}
|
|
811
|
+
const sessionId = parsed.sessionId;
|
|
812
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
813
|
+
return undefined;
|
|
814
|
+
}
|
|
815
|
+
const status = parsed.status;
|
|
816
|
+
if (status !== "queued" &&
|
|
817
|
+
status !== "running" &&
|
|
818
|
+
status !== "succeeded" &&
|
|
819
|
+
status !== "failed") {
|
|
820
|
+
return undefined;
|
|
821
|
+
}
|
|
822
|
+
return {
|
|
823
|
+
sessionId,
|
|
824
|
+
status,
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
catch (error) {
|
|
828
|
+
if (isMissingPathError(error) || error instanceof SyntaxError) {
|
|
829
|
+
return undefined;
|
|
830
|
+
}
|
|
831
|
+
throw error;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
function isMissingPathError(error) {
|
|
835
|
+
return (error !== null &&
|
|
836
|
+
typeof error === "object" &&
|
|
837
|
+
"code" in error &&
|
|
838
|
+
error.code === "ENOENT");
|
|
839
|
+
}
|
|
840
|
+
function sleep(ms) {
|
|
841
|
+
return new Promise((resolve) => {
|
|
842
|
+
setTimeout(resolve, ms);
|
|
843
|
+
});
|
|
844
|
+
}
|
|
550
845
|
function toToolInputJsonSchema(schema) {
|
|
551
846
|
const jsonSchema = z.toJSONSchema(schema, {
|
|
552
847
|
io: "input",
|
|
@@ -573,10 +868,8 @@ function createPruneMcpInputSchema() {
|
|
|
573
868
|
function createListMcpInputSchema() {
|
|
574
869
|
return toToolInputJsonSchema(z
|
|
575
870
|
.object({
|
|
576
|
-
operator:
|
|
577
|
-
mode:
|
|
578
|
-
.enum(["table", "detail"])
|
|
579
|
-
.describe("Use `detail` only when inspecting a specific session."),
|
|
871
|
+
operator: externalInspectionOperatorSchema,
|
|
872
|
+
mode: listJsonModeSchema.describe("Use `detail` only when inspecting a specific session."),
|
|
580
873
|
sessionId: z
|
|
581
874
|
.string()
|
|
582
875
|
.min(1)
|
package/dist/policy/auto.d.ts
CHANGED
|
@@ -8,6 +8,5 @@ export interface AutoVerificationSelectionActionRequired {
|
|
|
8
8
|
}
|
|
9
9
|
export type AutoVerificationSelectionDisposition = AutoVerificationSelectionProceed | AutoVerificationSelectionActionRequired;
|
|
10
10
|
export declare function classifyAutoVerificationSelection(options: {
|
|
11
|
-
targetKind: "spec" | "run";
|
|
12
11
|
selection?: SelectionDecision;
|
|
13
12
|
}): AutoVerificationSelectionDisposition;
|
package/dist/policy/auto.js
CHANGED
|
@@ -1,22 +1,11 @@
|
|
|
1
|
+
const UNRESOLVED_VERIFICATION_MESSAGE = "Verification did not produce a resolvable candidate; manual review required.";
|
|
1
2
|
export function classifyAutoVerificationSelection(options) {
|
|
2
|
-
const {
|
|
3
|
+
const { selection } = options;
|
|
3
4
|
if (selection?.state === "resolvable") {
|
|
4
5
|
return { kind: "proceed" };
|
|
5
6
|
}
|
|
6
7
|
return {
|
|
7
8
|
kind: "action_required",
|
|
8
|
-
detail:
|
|
9
|
+
detail: UNRESOLVED_VERIFICATION_MESSAGE,
|
|
9
10
|
};
|
|
10
11
|
}
|
|
11
|
-
function describeActionRequiredSelection(options) {
|
|
12
|
-
const { targetKind, selection } = options;
|
|
13
|
-
if (selection?.state === "unresolved" &&
|
|
14
|
-
selection.unresolvedReasons.some((reason) => reason.code === "verifier_disagreement")) {
|
|
15
|
-
return targetKind === "spec"
|
|
16
|
-
? "Verifiers disagreed on the preferred draft; manual selection required."
|
|
17
|
-
: "Verifiers disagreed on the preferred candidate; manual selection required.";
|
|
18
|
-
}
|
|
19
|
-
return targetKind === "spec"
|
|
20
|
-
? "Verification did not select a draft; manual selection required."
|
|
21
|
-
: "Verification did not produce a resolvable candidate; manual selection required.";
|
|
22
|
-
}
|