@loomfsm/mcp-server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/cc-adapter/commands/done.md +30 -0
- package/cc-adapter/commands/task.md +29 -0
- package/cc-adapter/pipeline-guard.sh +58 -0
- package/cc-adapter/pipeline-stop.sh +65 -0
- package/dist/src/bin/stdio.d.ts +2 -0
- package/dist/src/bin/stdio.js +43 -0
- package/dist/src/bin/stdio.js.map +1 -0
- package/dist/src/bootstrap.d.ts +4 -0
- package/dist/src/bootstrap.js +130 -0
- package/dist/src/bootstrap.js.map +1 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.js +16 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib/parse-task-args.d.ts +4 -0
- package/dist/src/lib/parse-task-args.js +38 -0
- package/dist/src/lib/parse-task-args.js.map +1 -0
- package/dist/src/lib/persist-progress.d.ts +2 -0
- package/dist/src/lib/persist-progress.js +20 -0
- package/dist/src/lib/persist-progress.js.map +1 -0
- package/dist/src/server.d.ts +25 -0
- package/dist/src/server.js +257 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/tools/backup.d.ts +5 -0
- package/dist/src/tools/backup.js +69 -0
- package/dist/src/tools/backup.js.map +1 -0
- package/dist/src/tools/continue-task.d.ts +7 -0
- package/dist/src/tools/continue-task.js +156 -0
- package/dist/src/tools/continue-task.js.map +1 -0
- package/dist/src/tools/extensions-list.d.ts +2 -0
- package/dist/src/tools/extensions-list.js +49 -0
- package/dist/src/tools/extensions-list.js.map +1 -0
- package/dist/src/tools/issue-marker.d.ts +5 -0
- package/dist/src/tools/issue-marker.js +57 -0
- package/dist/src/tools/issue-marker.js.map +1 -0
- package/dist/src/tools/meta.d.ts +6 -0
- package/dist/src/tools/meta.js +52 -0
- package/dist/src/tools/meta.js.map +1 -0
- package/dist/src/tools/recover.d.ts +7 -0
- package/dist/src/tools/recover.js +243 -0
- package/dist/src/tools/recover.js.map +1 -0
- package/dist/src/tools/restore.d.ts +5 -0
- package/dist/src/tools/restore.js +82 -0
- package/dist/src/tools/restore.js.map +1 -0
- package/dist/src/tools/run-task.d.ts +7 -0
- package/dist/src/tools/run-task.js +172 -0
- package/dist/src/tools/run-task.js.map +1 -0
- package/dist/src/tools/state-get.d.ts +2 -0
- package/dist/src/tools/state-get.js +176 -0
- package/dist/src/tools/state-get.js.map +1 -0
- package/dist/src/transport-adapter.d.ts +6 -0
- package/dist/src/transport-adapter.js +94 -0
- package/dist/src/transport-adapter.js.map +1 -0
- package/dist/src/types.d.ts +171 -0
- package/dist/src/types.js +9 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/version.d.ts +3 -0
- package/dist/src/version.js +8 -0
- package/dist/src/version.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Host-neutral flag parser. Pulls a single leading `--flag <rest>` off
|
|
2
|
+
// the raw task string and resolves it to a named policy preset. Hosts
|
|
3
|
+
// that already speak policy_preset directly do not call this — it
|
|
4
|
+
// exists so a $ARGUMENTS-style command can be parsed server-side
|
|
5
|
+
// instead of every skill markdown re-implementing the same regex.
|
|
6
|
+
// The five recognized leading flags. Order is the registration order
|
|
7
|
+
// surfaced by `pipeline_meta.flag_vocabulary` — adding an entry here is
|
|
8
|
+
// the single point of edit; the meta tool derives the vocabulary list
|
|
9
|
+
// from `Object.keys(FLAG_TO_PRESET)` so parser and discovery surface
|
|
10
|
+
// can never drift.
|
|
11
|
+
export const FLAG_TO_PRESET = {
|
|
12
|
+
"--supervised": "full-supervised",
|
|
13
|
+
"--auto": "full-autonomous",
|
|
14
|
+
"--review-plan": "review-plan-only",
|
|
15
|
+
"--review-final": "review-final-only",
|
|
16
|
+
"--gates-on-blockers": "gates-on-blockers",
|
|
17
|
+
};
|
|
18
|
+
// Single leading flag: `--name <rest>`. `s` flag preserves newlines
|
|
19
|
+
// inside `rest` so multi-line task descriptions round-trip verbatim.
|
|
20
|
+
const LEADING_FLAG = /^(--[a-z][a-z-]*)\s+(.+)$/s;
|
|
21
|
+
export function parseTaskArgs(raw) {
|
|
22
|
+
const warnings = [];
|
|
23
|
+
const trimmed = raw.trim();
|
|
24
|
+
if (trimmed.length === 0)
|
|
25
|
+
return { task: "", warnings };
|
|
26
|
+
const match = LEADING_FLAG.exec(trimmed);
|
|
27
|
+
if (match === null)
|
|
28
|
+
return { task: trimmed, warnings };
|
|
29
|
+
const flag = match[1];
|
|
30
|
+
const rest = match[2].trim();
|
|
31
|
+
const preset = FLAG_TO_PRESET[flag];
|
|
32
|
+
if (preset !== undefined) {
|
|
33
|
+
return { task: rest, policy_preset: preset, warnings };
|
|
34
|
+
}
|
|
35
|
+
warnings.push(`unknown-flag: ${flag} — treated as no-op (task starts after flag)`);
|
|
36
|
+
return { task: rest, warnings };
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=parse-task-args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-task-args.js","sourceRoot":"","sources":["../../../src/lib/parse-task-args.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,sEAAsE;AACtE,kEAAkE;AAClE,iEAAiE;AACjE,kEAAkE;AAMlE,qEAAqE;AACrE,wEAAwE;AACxE,sEAAsE;AACtE,qEAAqE;AACrE,mBAAmB;AACnB,MAAM,CAAC,MAAM,cAAc,GAA2B;IACpD,cAAc,EAAE,iBAAiB;IACjC,QAAQ,EAAE,iBAAiB;IAC3B,eAAe,EAAE,kBAAkB;IACnC,gBAAgB,EAAE,mBAAmB;IACrC,qBAAqB,EAAE,mBAAmB;CAC3C,CAAC;AAEF,oEAAoE;AACpE,qEAAqE;AACrE,MAAM,YAAY,GAAG,4BAA4B,CAAC;AAElD,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;IAExD,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAEvD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAW,CAAC;IAChC,MAAM,IAAI,GAAI,KAAK,CAAC,CAAC,CAAY,CAAC,IAAI,EAAE,CAAC;IAEzC,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACzD,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,iBAAiB,IAAI,8CAA8C,CAAC,CAAC;IACnF,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Durably record the FSM driver's resume point after a tick.
|
|
2
|
+
//
|
|
3
|
+
// `runFSM` advances `step_index` only in memory as it walks past the
|
|
4
|
+
// positional step-stages within a single tick; the value persisted on
|
|
5
|
+
// disk moves by exactly one per delivery (the drain-advance inside
|
|
6
|
+
// `deliverContinue`). When two spawn/gate stages are adjacent in a flow
|
|
7
|
+
// those two agree, so the resume point is correct without help. But a
|
|
8
|
+
// flow that interleaves positional steps between spawns — read a diff,
|
|
9
|
+
// derive review flags, snapshot state — would, on the next delivery,
|
|
10
|
+
// only advance the persisted index by one and re-enter the just-emitted
|
|
11
|
+
// spawn, re-issuing it once per intervening step.
|
|
12
|
+
//
|
|
13
|
+
// Persisting the tick's paused index (the stage that produced the
|
|
14
|
+
// returned directive) closes that gap so every spawn is issued exactly
|
|
15
|
+
// once. It is a no-op when the paused index already equals the stored
|
|
16
|
+
// one, so flows without interleaved steps are unaffected.
|
|
17
|
+
export async function persistDriverStepIndex(tx, stepIndex) {
|
|
18
|
+
await tx.exec("UPDATE driver_state SET step_index = ? WHERE id = 1", [stepIndex]);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=persist-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persist-progress.js","sourceRoot":"","sources":["../../../src/lib/persist-progress.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,qEAAqE;AACrE,sEAAsE;AACtE,mEAAmE;AACnE,wEAAwE;AACxE,sEAAsE;AACtE,uEAAuE;AACvE,qEAAqE;AACrE,wEAAwE;AACxE,kDAAkD;AAClD,EAAE;AACF,kEAAkE;AAClE,uEAAuE;AACvE,sEAAsE;AACtE,0DAA0D;AAI1D,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,EAAe,EACf,SAAiB;IAEjB,MAAM,EAAE,CAAC,IAAI,CAAC,qDAAqD,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;AACpF,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Registry } from "@loomfsm/kernel";
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { type MetaInputWithProject } from "./tools/meta.js";
|
|
4
|
+
import type { BackupInput, BackupResponse, ContinueTaskRequestInput, ContinueTaskResponse, ExtensionsListInput, ExtensionsListResponse, IssueCrossOwnerMarkerInput, IssueCrossOwnerMarkerResponse, PipelineMetaResponse, PipelineStateView, RecoverTaskInput, RecoverTaskResponse, RestoreInput, RestoreResponse, RunTaskInput, RunTaskResponse, StateGetInput, ToolHandler } from "./types.js";
|
|
5
|
+
export interface ServerDeps {
|
|
6
|
+
resolveRegistry?: (projectDir: string) => Promise<Registry> | Registry;
|
|
7
|
+
allowlistPath?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ToolRegistry {
|
|
10
|
+
pipeline_meta: ToolHandler<MetaInputWithProject, PipelineMetaResponse>;
|
|
11
|
+
pipeline_state_get: ToolHandler<StateGetInput, PipelineStateView>;
|
|
12
|
+
pipeline_extensions_list: ToolHandler<ExtensionsListInput, ExtensionsListResponse>;
|
|
13
|
+
pipeline_run_task: ToolHandler<RunTaskInput, RunTaskResponse>;
|
|
14
|
+
pipeline_continue_task: ToolHandler<ContinueTaskRequestInput, ContinueTaskResponse>;
|
|
15
|
+
pipeline_recover: ToolHandler<RecoverTaskInput, RecoverTaskResponse>;
|
|
16
|
+
pipeline_issue_cross_owner_marker: ToolHandler<IssueCrossOwnerMarkerInput, IssueCrossOwnerMarkerResponse>;
|
|
17
|
+
pipeline_backup: ToolHandler<BackupInput, BackupResponse>;
|
|
18
|
+
pipeline_restore: ToolHandler<RestoreInput, RestoreResponse>;
|
|
19
|
+
}
|
|
20
|
+
export interface CreateServerHandle {
|
|
21
|
+
server: Server;
|
|
22
|
+
tools: ToolRegistry;
|
|
23
|
+
}
|
|
24
|
+
export declare function createServer(deps?: ServerDeps): CreateServerHandle;
|
|
25
|
+
export declare function runStdioServer(deps?: ServerDeps): Promise<void>;
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
// Stdio MCP server factory. Wires the three read-only tool handlers
|
|
2
|
+
// into the SDK's request-dispatch surface and surfaces them as a
|
|
3
|
+
// direct-callable map so tests skip the JSON-RPC framing and exercise
|
|
4
|
+
// the handler bodies in-process.
|
|
5
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
6
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
+
import { createBackupTool } from "./tools/backup.js";
|
|
9
|
+
import { createContinueTaskTool } from "./tools/continue-task.js";
|
|
10
|
+
import { createExtensionsListTool } from "./tools/extensions-list.js";
|
|
11
|
+
import { createIssueCrossOwnerMarkerTool } from "./tools/issue-marker.js";
|
|
12
|
+
import { createMetaTool } from "./tools/meta.js";
|
|
13
|
+
import { createRecoverTool } from "./tools/recover.js";
|
|
14
|
+
import { createRestoreTool } from "./tools/restore.js";
|
|
15
|
+
import { createRunTaskTool } from "./tools/run-task.js";
|
|
16
|
+
import { createStateGetTool } from "./tools/state-get.js";
|
|
17
|
+
const SERVER_NAME = "@loomfsm/mcp-server";
|
|
18
|
+
const SERVER_VERSION = "0.0.0";
|
|
19
|
+
// Tool descriptors surfaced on `tools/list`. Schemas stay coarse for
|
|
20
|
+
// these read-only handlers; richer per-property typing belongs with
|
|
21
|
+
// the mutating-tool surface whose required-field matrices justify a
|
|
22
|
+
// shared schema package.
|
|
23
|
+
const TOOL_DESCRIPTORS = [
|
|
24
|
+
{
|
|
25
|
+
name: "pipeline_meta",
|
|
26
|
+
description: "Returns protocol / plugin / kernel versions, transport surface, " +
|
|
27
|
+
"installed providers and bundles, and the flag vocabulary the " +
|
|
28
|
+
"server-side parser currently honors.",
|
|
29
|
+
inputSchema: {
|
|
30
|
+
type: "object",
|
|
31
|
+
properties: {
|
|
32
|
+
project_dir: { type: "string" },
|
|
33
|
+
client_identifier_unverified: { type: "string" },
|
|
34
|
+
client_capabilities: { type: "object" },
|
|
35
|
+
},
|
|
36
|
+
required: ["project_dir"],
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "pipeline_state_get",
|
|
41
|
+
description: "Inspects pipeline state. Four output formats: a compact summary " +
|
|
42
|
+
"(default), the full PipelineState aggregate, per-table JSONL, " +
|
|
43
|
+
"or a stable-width ASCII rendering.",
|
|
44
|
+
inputSchema: {
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {
|
|
47
|
+
project_dir: { type: "string" },
|
|
48
|
+
format: { type: "string", enum: ["summary", "json", "jsonl", "pretty-table"] },
|
|
49
|
+
table: { type: "string" },
|
|
50
|
+
since: { type: "string" },
|
|
51
|
+
limit: { type: "number" },
|
|
52
|
+
},
|
|
53
|
+
required: ["project_dir"],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "pipeline_extensions_list",
|
|
58
|
+
description: "Lists installed extensions (bundles, providers, mcp-clients) " +
|
|
59
|
+
"from the project registry. Filters by kind / status; " +
|
|
60
|
+
"include_manifest pulls the full manifest snapshot into each entry.",
|
|
61
|
+
inputSchema: {
|
|
62
|
+
type: "object",
|
|
63
|
+
properties: {
|
|
64
|
+
project_dir: { type: "string" },
|
|
65
|
+
kind: { type: "string", enum: ["bundle", "provider", "mcp-client"] },
|
|
66
|
+
status: { type: "string", enum: ["enabled", "disabled", "failed"] },
|
|
67
|
+
include_manifest: { type: "boolean" },
|
|
68
|
+
},
|
|
69
|
+
required: ["project_dir"],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "pipeline_run_task",
|
|
74
|
+
description: "Initializes a new task and returns the first directive shaped as a " +
|
|
75
|
+
"wire response (spawn-agent | spawn-agents-parallel | ask-user | " +
|
|
76
|
+
"complete | error). client_idempotency_uuid is required; a replay " +
|
|
77
|
+
"with the same value returns the cached creation response.",
|
|
78
|
+
inputSchema: {
|
|
79
|
+
type: "object",
|
|
80
|
+
properties: {
|
|
81
|
+
project_dir: { type: "string" },
|
|
82
|
+
task: { type: "string" },
|
|
83
|
+
client_idempotency_uuid: { type: "string" },
|
|
84
|
+
policy_preset: { type: "string" },
|
|
85
|
+
gate_policies: { type: "object" },
|
|
86
|
+
complexity_hint: { type: "string", enum: ["simple", "medium", "complex"] },
|
|
87
|
+
tests_mode_hint: { type: "string", enum: ["tdd", "regression-only"] },
|
|
88
|
+
stack: { type: "object" },
|
|
89
|
+
owner_id: { type: "string" },
|
|
90
|
+
client_identifier_unverified: { type: "string" },
|
|
91
|
+
},
|
|
92
|
+
required: ["project_dir", "task", "client_idempotency_uuid"],
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "pipeline_continue_task",
|
|
97
|
+
description: "Delivers an agent result, a fanout batch, or a user answer and " +
|
|
98
|
+
"returns the next directive shaped as a wire response. Idempotent " +
|
|
99
|
+
"by agent_run_id / gate_event_id — a duplicate delivery returns the " +
|
|
100
|
+
"cached next-step response.",
|
|
101
|
+
inputSchema: {
|
|
102
|
+
type: "object",
|
|
103
|
+
properties: {
|
|
104
|
+
project_dir: { type: "string" },
|
|
105
|
+
driver_state_id: { type: "string" },
|
|
106
|
+
input: { type: "object" },
|
|
107
|
+
client_identifier_unverified: { type: "string" },
|
|
108
|
+
},
|
|
109
|
+
required: ["project_dir", "driver_state_id", "input"],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "pipeline_recover",
|
|
114
|
+
description: "Recovers a stuck task. Five choices: abandon | force-close | retry | " +
|
|
115
|
+
"retry-failed | cancel-pending. recovery_id is server-issued — omit it " +
|
|
116
|
+
"on the first call (the kernel mints one and returns it), pass it back " +
|
|
117
|
+
"to replay the cached response, or omit it to issue a new recovery " +
|
|
118
|
+
"action. agent_run_ids is required for retry-failed.",
|
|
119
|
+
inputSchema: {
|
|
120
|
+
type: "object",
|
|
121
|
+
properties: {
|
|
122
|
+
project_dir: { type: "string" },
|
|
123
|
+
driver_state_id: { type: "string" },
|
|
124
|
+
choice: {
|
|
125
|
+
type: "string",
|
|
126
|
+
enum: ["abandon", "force-close", "retry", "retry-failed", "cancel-pending"],
|
|
127
|
+
},
|
|
128
|
+
agent_run_ids: { type: "array", items: { type: "string" } },
|
|
129
|
+
recovery_id: { type: "string" },
|
|
130
|
+
owner_id: { type: "string" },
|
|
131
|
+
marker: { type: "object" },
|
|
132
|
+
client_identifier_unverified: { type: "string" },
|
|
133
|
+
},
|
|
134
|
+
required: ["project_dir", "driver_state_id", "choice"],
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: "pipeline_issue_cross_owner_marker",
|
|
139
|
+
description: "Mints a single-use, TTL-bounded cross-owner bypass marker for a " +
|
|
140
|
+
"task whose owner differs from the caller. Possessing the bypass-HMAC " +
|
|
141
|
+
"key (env var or user-global key file) is the authorization to mint; " +
|
|
142
|
+
"returns the signed marker fields to pass to pipeline_recover.marker. " +
|
|
143
|
+
"Refuses with BYPASS_KEY_MISSING when no key is configured.",
|
|
144
|
+
inputSchema: {
|
|
145
|
+
type: "object",
|
|
146
|
+
properties: {
|
|
147
|
+
project_dir: { type: "string" },
|
|
148
|
+
driver_state_id: { type: "string" },
|
|
149
|
+
ttl_ms: { type: "number" },
|
|
150
|
+
client_identifier_unverified: { type: "string" },
|
|
151
|
+
},
|
|
152
|
+
required: ["project_dir", "driver_state_id", "ttl_ms"],
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: "pipeline_backup",
|
|
157
|
+
description: "Writes a consistent textual SQL snapshot of the project state to " +
|
|
158
|
+
"`to` (a relative path resolves against project_dir). Returns " +
|
|
159
|
+
"bytes_written, the threaded timestamp, and the resolved backup_path.",
|
|
160
|
+
inputSchema: {
|
|
161
|
+
type: "object",
|
|
162
|
+
properties: {
|
|
163
|
+
project_dir: { type: "string" },
|
|
164
|
+
to: { type: "string" },
|
|
165
|
+
client_identifier_unverified: { type: "string" },
|
|
166
|
+
},
|
|
167
|
+
required: ["project_dir", "to"],
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: "pipeline_restore",
|
|
172
|
+
description: "Restores project state from a backup. A .sql dump is parsed through a " +
|
|
173
|
+
"statement allowlist (out-of-allowlist statements surface " +
|
|
174
|
+
"RESTORE_REJECTED); a binary .db is an operator-explicit file swap. " +
|
|
175
|
+
"Refuses without confirm:true.",
|
|
176
|
+
inputSchema: {
|
|
177
|
+
type: "object",
|
|
178
|
+
properties: {
|
|
179
|
+
project_dir: { type: "string" },
|
|
180
|
+
from: { type: "string" },
|
|
181
|
+
format: { type: "string", enum: ["sql", "binary"] },
|
|
182
|
+
confirm: { type: "boolean" },
|
|
183
|
+
client_identifier_unverified: { type: "string" },
|
|
184
|
+
},
|
|
185
|
+
required: ["project_dir", "from", "format"],
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
];
|
|
189
|
+
export function createServer(deps = {}) {
|
|
190
|
+
const tools = {
|
|
191
|
+
pipeline_meta: createMetaTool(),
|
|
192
|
+
pipeline_state_get: createStateGetTool(),
|
|
193
|
+
pipeline_extensions_list: createExtensionsListTool(),
|
|
194
|
+
pipeline_run_task: createRunTaskTool(deps),
|
|
195
|
+
pipeline_continue_task: createContinueTaskTool(deps),
|
|
196
|
+
pipeline_recover: createRecoverTool(deps),
|
|
197
|
+
pipeline_issue_cross_owner_marker: createIssueCrossOwnerMarkerTool(deps),
|
|
198
|
+
pipeline_backup: createBackupTool(deps),
|
|
199
|
+
pipeline_restore: createRestoreTool(deps),
|
|
200
|
+
};
|
|
201
|
+
const server = new Server({ name: SERVER_NAME, version: SERVER_VERSION }, { capabilities: { tools: {} } });
|
|
202
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
203
|
+
tools: TOOL_DESCRIPTORS,
|
|
204
|
+
}));
|
|
205
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
206
|
+
const name = request.params.name;
|
|
207
|
+
const args = (request.params.arguments ?? {});
|
|
208
|
+
const result = await dispatch(tools, name, args);
|
|
209
|
+
return {
|
|
210
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
211
|
+
};
|
|
212
|
+
});
|
|
213
|
+
return { server, tools };
|
|
214
|
+
}
|
|
215
|
+
async function dispatch(tools, name, args) {
|
|
216
|
+
if (name === "pipeline_meta") {
|
|
217
|
+
return await tools.pipeline_meta(args);
|
|
218
|
+
}
|
|
219
|
+
if (name === "pipeline_state_get") {
|
|
220
|
+
return await tools.pipeline_state_get(args);
|
|
221
|
+
}
|
|
222
|
+
if (name === "pipeline_extensions_list") {
|
|
223
|
+
return await tools.pipeline_extensions_list(args);
|
|
224
|
+
}
|
|
225
|
+
if (name === "pipeline_run_task") {
|
|
226
|
+
return await tools.pipeline_run_task(args);
|
|
227
|
+
}
|
|
228
|
+
if (name === "pipeline_continue_task") {
|
|
229
|
+
return await tools.pipeline_continue_task(args);
|
|
230
|
+
}
|
|
231
|
+
if (name === "pipeline_recover") {
|
|
232
|
+
return await tools.pipeline_recover(args);
|
|
233
|
+
}
|
|
234
|
+
if (name === "pipeline_issue_cross_owner_marker") {
|
|
235
|
+
return await tools.pipeline_issue_cross_owner_marker(args);
|
|
236
|
+
}
|
|
237
|
+
if (name === "pipeline_backup") {
|
|
238
|
+
return await tools.pipeline_backup(args);
|
|
239
|
+
}
|
|
240
|
+
if (name === "pipeline_restore") {
|
|
241
|
+
return await tools.pipeline_restore(args);
|
|
242
|
+
}
|
|
243
|
+
throw new Error(`unknown tool: ${name}`);
|
|
244
|
+
}
|
|
245
|
+
// Stdio entry. The module never connects automatically — the binary
|
|
246
|
+
// entrypoint is the only caller, and it forwards the production
|
|
247
|
+
// dependencies (registry resolver + allowlist path). Called with no
|
|
248
|
+
// argument the read-only surface still works and the active-task tools
|
|
249
|
+
// answer with a structured REGISTRY_UNAVAILABLE envelope. Tests
|
|
250
|
+
// construct `createServer(deps)` and exercise the `tools` map directly,
|
|
251
|
+
// never reaching this function.
|
|
252
|
+
export async function runStdioServer(deps = {}) {
|
|
253
|
+
const handle = createServer(deps);
|
|
254
|
+
const transport = new StdioServerTransport();
|
|
255
|
+
await handle.server.connect(transport);
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// pipeline_backup — consistent textual SQL snapshot of the kernel-owned
|
|
2
|
+
// tables.
|
|
3
|
+
//
|
|
4
|
+
// Composition: project-dir allowlist → path-traversal guard (a relative
|
|
5
|
+
// `to` resolves against project_dir; an escaping path is refused) →
|
|
6
|
+
// dump inside one withStateTransaction (BEGIN holds a consistent view) →
|
|
7
|
+
// write the file → return { bytes_written, ts, backup_path }.
|
|
8
|
+
//
|
|
9
|
+
// `ts` is the threaded NowToken passed to the transaction, NOT a fresh
|
|
10
|
+
// clock read, so the reported timestamp matches the snapshot boundary.
|
|
11
|
+
import { writeFileSync } from "node:fs";
|
|
12
|
+
import { realpath } from "node:fs/promises";
|
|
13
|
+
import { resolve, sep } from "node:path";
|
|
14
|
+
import { assertProjectDirAllowed, captureNow, dumpStateSql, KernelError, withStateTransaction, } from "@loomfsm/kernel";
|
|
15
|
+
export function createBackupTool(deps = {}) {
|
|
16
|
+
return async (input) => {
|
|
17
|
+
const now = captureNow();
|
|
18
|
+
// 1. Project-dir allowlist.
|
|
19
|
+
try {
|
|
20
|
+
await assertProjectDirAllowed(input.project_dir, deps.allowlistPath !== undefined ? { allowlistPath: deps.allowlistPath } : undefined);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
return refusal(err, now);
|
|
24
|
+
}
|
|
25
|
+
// 2. Path-traversal guard — the destination must stay within the
|
|
26
|
+
// project directory so a backup cannot be written to an arbitrary
|
|
27
|
+
// host location through a `..`-laden or absolute escape.
|
|
28
|
+
let backupPath;
|
|
29
|
+
try {
|
|
30
|
+
backupPath = await resolveBackupPath(input.project_dir, input.to);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
return refusal(err, now);
|
|
34
|
+
}
|
|
35
|
+
// 3. Consistent dump inside one transaction view.
|
|
36
|
+
const sql = await withStateTransaction(input.project_dir, now, (tx) => dumpStateSql(tx));
|
|
37
|
+
// 4. Write + report.
|
|
38
|
+
writeFileSync(backupPath, sql, "utf8");
|
|
39
|
+
return {
|
|
40
|
+
bytes_written: Buffer.byteLength(sql, "utf8"),
|
|
41
|
+
ts: now,
|
|
42
|
+
backup_path: backupPath,
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async function resolveBackupPath(projectDir, to) {
|
|
47
|
+
const canonicalDir = await realpath(resolve(projectDir));
|
|
48
|
+
const resolved = resolve(canonicalDir, to);
|
|
49
|
+
if (resolved !== canonicalDir && !resolved.startsWith(canonicalDir + sep)) {
|
|
50
|
+
throw new KernelError({
|
|
51
|
+
code: "BACKUP_PATH_REJECTED",
|
|
52
|
+
message: `backup destination '${to}' escapes the project directory`,
|
|
53
|
+
detail: { to, project_dir: projectDir },
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return resolved;
|
|
57
|
+
}
|
|
58
|
+
function refusal(err, ts) {
|
|
59
|
+
if (err instanceof KernelError) {
|
|
60
|
+
return {
|
|
61
|
+
bytes_written: null,
|
|
62
|
+
ts,
|
|
63
|
+
backup_path: null,
|
|
64
|
+
error: { code: err.code, message: err.message },
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
throw err;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=backup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.js","sourceRoot":"","sources":["../../../src/tools/backup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type Registry } from "@loomfsm/kernel";
|
|
2
|
+
import type { ContinueTaskRequestInput, ContinueTaskResponse, ToolHandler } from "../types.js";
|
|
3
|
+
export interface ContinueTaskDeps {
|
|
4
|
+
resolveRegistry?: (projectDir: string) => Promise<Registry> | Registry;
|
|
5
|
+
allowlistPath?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function createContinueTaskTool(deps?: ContinueTaskDeps): ToolHandler<ContinueTaskRequestInput, ContinueTaskResponse>;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// pipeline_continue_task — delivery handler for agent results, fanout
|
|
2
|
+
// batches, and user answers.
|
|
3
|
+
//
|
|
4
|
+
// Composition mirrors pipeline_run_task: allowlist gate → variant
|
|
5
|
+
// refusals → ledger cache lookup → deliver inside one withStateTransaction
|
|
6
|
+
// (the op-shaped ledger row + a co-committed audit row land with the
|
|
7
|
+
// state mutation) → run the FSM against the post-delivery state → shape
|
|
8
|
+
// the next directive → materialize the cached response on the ledger
|
|
9
|
+
// row(s).
|
|
10
|
+
//
|
|
11
|
+
// Two variants are refused on this surface:
|
|
12
|
+
// recovery → RECOVERY_VIA_CONTINUE_REFUSED (its own primitive).
|
|
13
|
+
// agents-results with partial:true → PARTIAL_FANOUT_REFUSED.
|
|
14
|
+
//
|
|
15
|
+
// Refusals (allowlist, variant, kernel-coded errors like GATE_EVENT_STALE)
|
|
16
|
+
// become error-shaped wire envelopes; only programmer errors throw.
|
|
17
|
+
import { assertProjectDirAllowed, captureNow, deliverContinue, KernelError, loadState, openDb, readLedgerRow, runFSM, TransactionImpl, withStateTransaction, writeLedgerRow, } from "@loomfsm/kernel";
|
|
18
|
+
import { persistDriverStepIndex } from "../lib/persist-progress.js";
|
|
19
|
+
import { createTransportAdapter } from "../transport-adapter.js";
|
|
20
|
+
export function createContinueTaskTool(deps = {}) {
|
|
21
|
+
const adapter = createTransportAdapter();
|
|
22
|
+
return async (input) => {
|
|
23
|
+
const driverStateId = input.driver_state_id;
|
|
24
|
+
// 1. Project-dir allowlist.
|
|
25
|
+
try {
|
|
26
|
+
await assertProjectDirAllowed(input.project_dir, deps.allowlistPath !== undefined ? { allowlistPath: deps.allowlistPath } : undefined);
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
return refusal(err, driverStateId);
|
|
30
|
+
}
|
|
31
|
+
// 2. Variant refusals handled on this surface.
|
|
32
|
+
if (input.input.type === "recovery") {
|
|
33
|
+
return {
|
|
34
|
+
response: errorResponse(driverStateId, "RECOVERY_VIA_CONTINUE_REFUSED", "recovery is delivered through the recovery primitive, not pipeline_continue_task"),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (input.input.type === "agents-results" && input.input.partial === true) {
|
|
38
|
+
return {
|
|
39
|
+
response: errorResponse(driverStateId, "PARTIAL_FANOUT_REFUSED", "partial fanout delivery is not accepted on this surface"),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// 3. Replay — a materialized ledger blob under any of the op keys
|
|
43
|
+
// replays the cached next-step envelope verbatim.
|
|
44
|
+
const keys = ledgerKeysFor(input.input);
|
|
45
|
+
const cached = await readCachedDelivery(input.project_dir, keys);
|
|
46
|
+
if (cached !== null)
|
|
47
|
+
return { response: cached };
|
|
48
|
+
if (deps.resolveRegistry === undefined) {
|
|
49
|
+
return {
|
|
50
|
+
response: errorResponse(driverStateId, "REGISTRY_UNAVAILABLE", "no registry resolver is wired for the active-task path"),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const registry = await deps.resolveRegistry(input.project_dir);
|
|
54
|
+
const identifier = typeof input.client_identifier_unverified === "string" &&
|
|
55
|
+
input.client_identifier_unverified.length > 0
|
|
56
|
+
? input.client_identifier_unverified
|
|
57
|
+
: "unknown";
|
|
58
|
+
// 4. Deliver + co-committed audit row.
|
|
59
|
+
try {
|
|
60
|
+
await withStateTransaction(input.project_dir, captureNow(), async (tx) => {
|
|
61
|
+
await deliverContinue(tx, {
|
|
62
|
+
input: input.input,
|
|
63
|
+
driver_state_id: driverStateId,
|
|
64
|
+
resolveOutputKind: (agent) => registry.agents.get(agent)?.output_kind,
|
|
65
|
+
vocabularies: registry.vocabularies,
|
|
66
|
+
});
|
|
67
|
+
const taskId = await readTaskId(tx);
|
|
68
|
+
await writeAuditRow(tx, "pipeline_continue_task", taskId, driverStateId, {
|
|
69
|
+
client_identifier_unverified: identifier,
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
return refusal(err, driverStateId);
|
|
75
|
+
}
|
|
76
|
+
// 5. Run the FSM against the post-delivery state and shape it.
|
|
77
|
+
const loaded = await readState(input.project_dir);
|
|
78
|
+
const { state: ticked, directive } = await runFSM(loaded, registry);
|
|
79
|
+
const response = adapter.shape(directive, { driver_state_id: driverStateId });
|
|
80
|
+
// 6. Persist the tick's paused step index + materialize the cached
|
|
81
|
+
// response on every op key (the fanout batch shares one envelope
|
|
82
|
+
// across all its agent_run_ids), co-committed.
|
|
83
|
+
const taskId = loaded.task_id;
|
|
84
|
+
await withStateTransaction(input.project_dir, captureNow(), async (tx) => {
|
|
85
|
+
await persistDriverStepIndex(tx, ticked.driver.step_index);
|
|
86
|
+
for (const key of keys) {
|
|
87
|
+
await writeLedgerRow(tx, key, {
|
|
88
|
+
driver_state_id: driverStateId,
|
|
89
|
+
task_id: taskId,
|
|
90
|
+
response_blob: JSON.stringify(response),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return { response };
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function ledgerKeysFor(input) {
|
|
98
|
+
switch (input.type) {
|
|
99
|
+
case "agent-result":
|
|
100
|
+
return [`agent-result:${input.agent_run_id}`];
|
|
101
|
+
case "agents-results":
|
|
102
|
+
return input.results.map((r) => `agent-result:${r.agent_run_id}`);
|
|
103
|
+
case "user-answer":
|
|
104
|
+
return [`user-answer:${input.gate_event_id}`];
|
|
105
|
+
case "recovery":
|
|
106
|
+
return [];
|
|
107
|
+
default: {
|
|
108
|
+
const _exhaustive = input;
|
|
109
|
+
return _exhaustive;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async function readState(projectDir) {
|
|
114
|
+
const db = openDb(projectDir);
|
|
115
|
+
const tx = new TransactionImpl(db, captureNow());
|
|
116
|
+
return await loadState(tx);
|
|
117
|
+
}
|
|
118
|
+
async function readCachedDelivery(projectDir, keys) {
|
|
119
|
+
if (keys.length === 0)
|
|
120
|
+
return null;
|
|
121
|
+
const db = openDb(projectDir);
|
|
122
|
+
const tx = new TransactionImpl(db, captureNow());
|
|
123
|
+
for (const key of keys) {
|
|
124
|
+
const row = await readLedgerRow(tx, key);
|
|
125
|
+
if (row !== null && row.response_blob !== null) {
|
|
126
|
+
return JSON.parse(row.response_blob);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
async function readTaskId(tx) {
|
|
132
|
+
const row = await tx.queryRow("SELECT task_id FROM pipeline_state WHERE id = 1");
|
|
133
|
+
if (row === null || row.task_id === null)
|
|
134
|
+
return null;
|
|
135
|
+
return String(row.task_id);
|
|
136
|
+
}
|
|
137
|
+
async function writeAuditRow(tx, type, taskId, driverStateId, payload) {
|
|
138
|
+
await tx.exec("INSERT INTO audit (ts, type, task_id, driver_state_id, payload, verdict, error_class) " +
|
|
139
|
+
"VALUES (?, ?, ?, ?, ?, 'ok', NULL)", [tx.now, type, taskId, driverStateId, JSON.stringify(payload)]);
|
|
140
|
+
}
|
|
141
|
+
function refusal(err, driverStateId) {
|
|
142
|
+
if (err instanceof KernelError) {
|
|
143
|
+
return { response: errorResponse(driverStateId, err.code, err.message) };
|
|
144
|
+
}
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
function errorResponse(driverStateId, code, message) {
|
|
148
|
+
return {
|
|
149
|
+
status: "error",
|
|
150
|
+
driver_state_id: driverStateId,
|
|
151
|
+
code,
|
|
152
|
+
message,
|
|
153
|
+
recovery_options: [],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=continue-task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continue-task.js","sourceRoot":"","sources":["../../../src/tools/continue-task.ts"],"names":[],"mappings":"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"}
|