@krapht/ork 1.0.0-alpha.3 → 1.0.0-alpha.4
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/dist/{__build_info__-BwrKe6yz.mjs → __build_info__-1i1IwLg7.mjs} +2 -2
- package/dist/bin.mjs +37 -29
- package/dist/{clean-hXSaN8BT.mjs → clean-B1zPxq6A.mjs} +1 -1
- package/dist/{completion-Cga01yQP.mjs → completion-BY-frez8.mjs} +5 -5
- package/dist/{context-mCAwzFFM.mjs → context-CD5TCD1D.mjs} +3 -3
- package/dist/{decide-BvZnKErW.mjs → decide-CBhYcjwI.mjs} +1 -1
- package/dist/{find-CbetS8I2.mjs → find-BgZjVKhv.mjs} +1 -1
- package/dist/{format-D87bY6Ud.mjs → format-Creyq4U3.mjs} +2 -2
- package/dist/{in-a-run-Bs4Wv-Cz.mjs → in-a-run-CsSBQQ2q.mjs} +1 -1
- package/dist/{limits-RzKQ_zPk.mjs → limits-D_HxH0CK.mjs} +1 -1
- package/dist/{list-DX65Sbu7.mjs → list-CzzpVEpM.mjs} +1 -1
- package/dist/{mcp-DKrrxowo.mjs → mcp-DYmQt372.mjs} +6 -6
- package/dist/{output-Q3TZ-Ave.mjs → output-CuivUcDa.mjs} +1 -1
- package/dist/{pause-B5Z41lR3.mjs → pause-W6MzQqg8.mjs} +4 -4
- package/dist/{relay-BLnjMdjT.mjs → relay-CsdoZUXJ.mjs} +2 -2
- package/dist/{remove-IbcZOemm.mjs → remove-DLfDjBdF.mjs} +3 -3
- package/dist/{send-CJKEhBL1.mjs → send-Bw2FI_Sv.mjs} +3 -3
- package/dist/{src-DnETlJ1r.mjs → src-BRB5EQyC.mjs} +133 -11
- package/dist/{src-XDSRnAZV.mjs → src-Bc9yaAiZ.mjs} +159 -161
- package/dist/{src-LSxjnWDH.mjs → src-CrYCkU9J.mjs} +16 -8
- package/dist/{src-BTDzibW3.mjs → src-CsjumY1t.mjs} +7 -7
- package/dist/ui/assets/{app-BNElhp7Z.js → app-m9Gfrg_S.js} +1 -1
- package/dist/ui/assets/{index-BkI68sr5.js → index-UEC5ZLYw.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-fvrO7Gxd.mjs → ui-wX050aH1.mjs} +4 -4
- package/dist/{usage-bNdcBcj9.mjs → usage-C96RDH-G.mjs} +5 -5
- package/dist/{watch-EhlO304A.mjs → watch-vdRobJil.mjs} +6 -6
- package/dist/{workflows-C5hYAVcE.mjs → workflows-B28q8zMY.mjs} +3 -3
- package/dist/{worktrees-BQFcpYz1.mjs → worktrees-CKDRkl6b.mjs} +4 -4
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { $n as
|
|
1
|
+
import { $n as isToolNode, At as runScope, Bt as serversIn, F as declaredProblem, Mt as envReadsOf, Ot as heldTimeout, Pt as declaredOutputOf, Rt as MCP_FILE, Wn as markValue, Zn as beforeOf, ar as integrationFor, er as programsRunBy, ft as sessionDriver, ir as TOOL_PREFIX, jt as calledWorkflows, mt as reportSchemaFor, nn as parseTemplate, nr as timeoutMs, rn as renderTemplate, rr as INTEGRATIONS, s as planReason, tn as evaluate, ut as planNodeSession, zt as mcpNotText } from "./src-BRB5EQyC.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { accessSync, constants,
|
|
3
|
+
import { accessSync, constants, lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
6
6
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
@@ -123,6 +123,156 @@ const resultOf = (outcome, declared) => {
|
|
|
123
123
|
if (!result.ok) result.error = report.summary;
|
|
124
124
|
return result;
|
|
125
125
|
};
|
|
126
|
+
// ../nodes/src/environ.ts
|
|
127
|
+
/** A variable of the user's. */
|
|
128
|
+
const readEnv = (environ, name) => Object.hasOwn(environ, name) ? environ[name] : void 0;
|
|
129
|
+
// ../nodes/src/mcp-servers.ts
|
|
130
|
+
/**
|
|
131
|
+
* @file Reading an MCP server's definition from the project's `.mcp.json`, the
|
|
132
|
+
* file Claude Code reads too, so a server is defined in one place (RFC-006).
|
|
133
|
+
* `${VAR}` and `${VAR:-default}` read the user's environment, which is where
|
|
134
|
+
* secrets stay: Ork stores none, and a run masks each value read this way. A
|
|
135
|
+
* server that needs an OAuth sign-in holds Claude Code's tokens, not Ork's,
|
|
136
|
+
* so it is refused.
|
|
137
|
+
*/
|
|
138
|
+
const VARIABLE = /\$\{([A-Za-z_]\w*)(?::-([^}]*))?\}/gu;
|
|
139
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
140
|
+
const stringsOf = (value) => isRecord(value) ? Object.fromEntries(Object.entries(value).flatMap(([key, item]) => typeof item === "string" ? [[key, item]] : [])) : {};
|
|
141
|
+
const listOf = (value) => Array.isArray(value) ? value.flatMap((item) => typeof item === "string" ? [item] : []) : [];
|
|
142
|
+
/** The server as written, or why Ork can't call it. */
|
|
143
|
+
const readMcpServer = (root, name) => {
|
|
144
|
+
const servers = serversIn(root);
|
|
145
|
+
if (!servers.ok) return servers;
|
|
146
|
+
const known = Object.keys(servers.value);
|
|
147
|
+
const server = Object.hasOwn(servers.value, name) ? servers.value[name] : void 0;
|
|
148
|
+
if (!isRecord(server)) return {
|
|
149
|
+
ok: false,
|
|
150
|
+
error: `no MCP server \`${name}\` in ${MCP_FILE}${known.length === 0 ? "" : `, which has ${known.join(", ")}`}`
|
|
151
|
+
};
|
|
152
|
+
if ("oauth" in server) return {
|
|
153
|
+
ok: false,
|
|
154
|
+
error: `MCP server \`${name}\` signs in with OAuth, whose tokens are Claude Code's: give it a token through headers and \`env:\`, or call it from a session`
|
|
155
|
+
};
|
|
156
|
+
const notText = mcpNotText(server);
|
|
157
|
+
if (notText !== void 0) return {
|
|
158
|
+
ok: false,
|
|
159
|
+
error: `MCP server \`${name}\` has a value in ${notText} that isn't a string: write it in quotes`
|
|
160
|
+
};
|
|
161
|
+
const { type, url, command } = server;
|
|
162
|
+
if (type === "http" && typeof url === "string") return {
|
|
163
|
+
ok: true,
|
|
164
|
+
value: {
|
|
165
|
+
kind: "http",
|
|
166
|
+
url,
|
|
167
|
+
headers: stringsOf(server["headers"])
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
if ((type === void 0 || type === "stdio") && typeof command === "string") return {
|
|
171
|
+
ok: true,
|
|
172
|
+
value: {
|
|
173
|
+
kind: "stdio",
|
|
174
|
+
command,
|
|
175
|
+
args: listOf(server["args"]),
|
|
176
|
+
env: stringsOf(server["env"])
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
return {
|
|
180
|
+
ok: false,
|
|
181
|
+
error: `MCP server \`${name}\` is not one Ork can call: it takes stdio and http servers`
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* The named servers' entries as written, for a session: `${VAR}` stays text for
|
|
186
|
+
* the `claude` that loads them to expand. The compiler has checked the names.
|
|
187
|
+
*/
|
|
188
|
+
const namedMcpEntries = (root, names) => {
|
|
189
|
+
if (names.length === 0) return {
|
|
190
|
+
ok: true,
|
|
191
|
+
value: {}
|
|
192
|
+
};
|
|
193
|
+
const servers = serversIn(root);
|
|
194
|
+
if (!servers.ok) return servers;
|
|
195
|
+
const mcpServers = {};
|
|
196
|
+
for (const name of names) {
|
|
197
|
+
const server = Object.hasOwn(servers.value, name) ? servers.value[name] : void 0;
|
|
198
|
+
if (!isRecord(server)) return {
|
|
199
|
+
ok: false,
|
|
200
|
+
error: `no MCP server \`${name}\` in ${MCP_FILE}`
|
|
201
|
+
};
|
|
202
|
+
mcpServers[name] = server;
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
ok: true,
|
|
206
|
+
value: { mcpServers }
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
/** Each variable a server reads, and whether it has a default. */
|
|
210
|
+
const readsOf = (server) => {
|
|
211
|
+
return (server.kind === "stdio" ? [
|
|
212
|
+
server.command,
|
|
213
|
+
...server.args,
|
|
214
|
+
...Object.values(server.env)
|
|
215
|
+
] : [server.url, ...Object.values(server.headers)]).flatMap((text) => [...text.matchAll(VARIABLE)].map((match) => ({
|
|
216
|
+
name: String(match[1]),
|
|
217
|
+
fallback: match[2] !== void 0
|
|
218
|
+
})));
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* The server with its variables filled in, and the values to mask: all it read
|
|
222
|
+
* but those `plain` names, which aren't secret.
|
|
223
|
+
*/
|
|
224
|
+
const expandServer = (server, environ, plain = []) => {
|
|
225
|
+
const unset = readsOf(server).find(({ name, fallback }) => !fallback && readEnv(environ, name) === void 0);
|
|
226
|
+
if (unset !== void 0) return {
|
|
227
|
+
ok: false,
|
|
228
|
+
error: `${MCP_FILE} reads ${unset.name}, which is not set`
|
|
229
|
+
};
|
|
230
|
+
const values = [];
|
|
231
|
+
const fill = (text) => text.replaceAll(VARIABLE, (_all, name, fallback) => {
|
|
232
|
+
const value = readEnv(environ, name);
|
|
233
|
+
if (value !== void 0 && !plain.includes(name)) values.push(value);
|
|
234
|
+
return value ?? fallback ?? "";
|
|
235
|
+
});
|
|
236
|
+
const fillAll = (record) => Object.fromEntries(Object.entries(record).map(([key, text]) => [key, fill(text)]));
|
|
237
|
+
return {
|
|
238
|
+
ok: true,
|
|
239
|
+
value: {
|
|
240
|
+
server: server.kind === "stdio" ? {
|
|
241
|
+
kind: "stdio",
|
|
242
|
+
command: fill(server.command),
|
|
243
|
+
args: server.args.map((arg) => fill(arg)),
|
|
244
|
+
env: fillAll(server.env)
|
|
245
|
+
} : {
|
|
246
|
+
kind: "http",
|
|
247
|
+
url: fill(server.url),
|
|
248
|
+
headers: fillAll(server.headers)
|
|
249
|
+
},
|
|
250
|
+
values
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
/** What a workflow's MCP servers read of the user's, unless called not secret. */
|
|
255
|
+
const mcpVariablesOf = (workflow, root) => Object.values(workflow.nodes).flatMap((node) => {
|
|
256
|
+
if (node.type !== "mcp.call") return [];
|
|
257
|
+
const read = readMcpServer(root, node.server);
|
|
258
|
+
return read.ok ? readsOf(read.value).map(({ name }) => name).filter((name) => node.plainEnv?.includes(name) !== true) : [];
|
|
259
|
+
});
|
|
260
|
+
/** A stdio server's program, when its name can be known before it is filled in. */
|
|
261
|
+
const programOf = (server) => server.kind === "stdio" && !server.command.includes("$") ? server.command : void 0;
|
|
262
|
+
/**
|
|
263
|
+
* What stops a workflow's `mcp.call` nodes, found before a run spends anything:
|
|
264
|
+
* a server that isn't there or can't be called, a program that isn't installed,
|
|
265
|
+
* or a variable that is not set.
|
|
266
|
+
*/
|
|
267
|
+
const mcpProblems = (workflow, root, environ = process.env, finished = /* @__PURE__ */ new Set(), installed = () => true) => Object.entries(workflow.nodes).flatMap(([id, node]) => {
|
|
268
|
+
if (node.type !== "mcp.call" || finished.has(id)) return [];
|
|
269
|
+
const read = readMcpServer(root, node.server);
|
|
270
|
+
if (!read.ok) return [`${id}: ${read.error}`];
|
|
271
|
+
const given = new Set(Object.keys(node.env ?? {}));
|
|
272
|
+
const unset = readsOf(read.value).flatMap(({ name, fallback }) => fallback || given.has(name) || readEnv(environ, name) !== void 0 ? [] : [`${id}: ${MCP_FILE} reads ${name}, which is not set`]);
|
|
273
|
+
const program = programOf(read.value);
|
|
274
|
+
return program === void 0 || installed(program) ? unset : [`\`${id}\`: MCP server \`${node.server}\` runs \`${program}\`, which is not installed`].concat(unset);
|
|
275
|
+
});
|
|
126
276
|
/** The only built-in tools a fork has: it reads, and reports. */
|
|
127
277
|
const FORK_TOOLS = [
|
|
128
278
|
"Read",
|
|
@@ -660,163 +810,6 @@ const tokenize = (command) => {
|
|
|
660
810
|
args
|
|
661
811
|
};
|
|
662
812
|
};
|
|
663
|
-
// ../nodes/src/environ.ts
|
|
664
|
-
/** A variable of the user's. */
|
|
665
|
-
const readEnv = (environ, name) => Object.hasOwn(environ, name) ? environ[name] : void 0;
|
|
666
|
-
// ../nodes/src/mcp-servers.ts
|
|
667
|
-
/**
|
|
668
|
-
* @file Reading an MCP server's definition from the project's `.mcp.json`, the
|
|
669
|
-
* file Claude Code reads too, so a server is defined in one place (RFC-006).
|
|
670
|
-
* `${VAR}` and `${VAR:-default}` read the user's environment, which is where
|
|
671
|
-
* secrets stay: Ork stores none, and a run masks each value read this way. A
|
|
672
|
-
* server that needs an OAuth sign-in holds Claude Code's tokens, not Ork's,
|
|
673
|
-
* so it is refused.
|
|
674
|
-
*/
|
|
675
|
-
const MCP_FILE = ".mcp.json";
|
|
676
|
-
const VARIABLE = /\$\{([A-Za-z_]\w*)(?::-([^}]*))?\}/gu;
|
|
677
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
678
|
-
/** The file's `mcpServers`; `{}` when there is no file. */
|
|
679
|
-
const serversIn = (root) => {
|
|
680
|
-
const file = path.join(root, MCP_FILE);
|
|
681
|
-
if (!existsSync(file)) return {
|
|
682
|
-
ok: true,
|
|
683
|
-
value: {}
|
|
684
|
-
};
|
|
685
|
-
try {
|
|
686
|
-
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
687
|
-
const servers = isRecord(parsed) ? parsed["mcpServers"] : void 0;
|
|
688
|
-
return {
|
|
689
|
-
ok: true,
|
|
690
|
-
value: isRecord(servers) ? servers : {}
|
|
691
|
-
};
|
|
692
|
-
} catch (error) {
|
|
693
|
-
const reason = error instanceof SyntaxError ? "it is not valid JSON" : error instanceof Error ? error.message : String(error);
|
|
694
|
-
return {
|
|
695
|
-
ok: false,
|
|
696
|
-
error: `${MCP_FILE} can't be read: ${reason}`
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
};
|
|
700
|
-
const stringsOf = (value) => isRecord(value) ? Object.fromEntries(Object.entries(value).flatMap(([key, item]) => typeof item === "string" ? [[key, item]] : [])) : {};
|
|
701
|
-
const listOf = (value) => Array.isArray(value) ? value.flatMap((item) => typeof item === "string" ? [item] : []) : [];
|
|
702
|
-
/** A server's field that holds something other than text: it would be dropped. */
|
|
703
|
-
const notTextIn = (server) => [
|
|
704
|
-
"args",
|
|
705
|
-
"env",
|
|
706
|
-
"headers"
|
|
707
|
-
].find((field) => {
|
|
708
|
-
const value = server[field];
|
|
709
|
-
return (Array.isArray(value) ? value : isRecord(value) ? Object.values(value) : []).some((item) => typeof item !== "string");
|
|
710
|
-
});
|
|
711
|
-
/** The server as written, or why Ork can't call it. */
|
|
712
|
-
const readMcpServer = (root, name) => {
|
|
713
|
-
const servers = serversIn(root);
|
|
714
|
-
if (!servers.ok) return servers;
|
|
715
|
-
const known = Object.keys(servers.value);
|
|
716
|
-
const server = Object.hasOwn(servers.value, name) ? servers.value[name] : void 0;
|
|
717
|
-
if (!isRecord(server)) return {
|
|
718
|
-
ok: false,
|
|
719
|
-
error: `no MCP server \`${name}\` in ${MCP_FILE}${known.length === 0 ? "" : `, which has ${known.join(", ")}`}`
|
|
720
|
-
};
|
|
721
|
-
if ("oauth" in server) return {
|
|
722
|
-
ok: false,
|
|
723
|
-
error: `MCP server \`${name}\` signs in with OAuth, whose tokens are Claude Code's: give it a token through headers and \`env:\`, or call it from a session`
|
|
724
|
-
};
|
|
725
|
-
const notText = notTextIn(server);
|
|
726
|
-
if (notText !== void 0) return {
|
|
727
|
-
ok: false,
|
|
728
|
-
error: `MCP server \`${name}\` has a value in ${notText} that isn't a string: write it in quotes`
|
|
729
|
-
};
|
|
730
|
-
const { type, url, command } = server;
|
|
731
|
-
if (type === "http" && typeof url === "string") return {
|
|
732
|
-
ok: true,
|
|
733
|
-
value: {
|
|
734
|
-
kind: "http",
|
|
735
|
-
url,
|
|
736
|
-
headers: stringsOf(server["headers"])
|
|
737
|
-
}
|
|
738
|
-
};
|
|
739
|
-
if ((type === void 0 || type === "stdio") && typeof command === "string") return {
|
|
740
|
-
ok: true,
|
|
741
|
-
value: {
|
|
742
|
-
kind: "stdio",
|
|
743
|
-
command,
|
|
744
|
-
args: listOf(server["args"]),
|
|
745
|
-
env: stringsOf(server["env"])
|
|
746
|
-
}
|
|
747
|
-
};
|
|
748
|
-
return {
|
|
749
|
-
ok: false,
|
|
750
|
-
error: `MCP server \`${name}\` is not one Ork can call: it takes stdio and http servers`
|
|
751
|
-
};
|
|
752
|
-
};
|
|
753
|
-
/** Each variable a server reads, and whether it has a default. */
|
|
754
|
-
const readsOf = (server) => {
|
|
755
|
-
return (server.kind === "stdio" ? [
|
|
756
|
-
server.command,
|
|
757
|
-
...server.args,
|
|
758
|
-
...Object.values(server.env)
|
|
759
|
-
] : [server.url, ...Object.values(server.headers)]).flatMap((text) => [...text.matchAll(VARIABLE)].map((match) => ({
|
|
760
|
-
name: String(match[1]),
|
|
761
|
-
fallback: match[2] !== void 0
|
|
762
|
-
})));
|
|
763
|
-
};
|
|
764
|
-
/**
|
|
765
|
-
* The server with its variables filled in, and the values to mask: all it read
|
|
766
|
-
* but those `plain` names, which aren't secret.
|
|
767
|
-
*/
|
|
768
|
-
const expandServer = (server, environ, plain = []) => {
|
|
769
|
-
const unset = readsOf(server).find(({ name, fallback }) => !fallback && readEnv(environ, name) === void 0);
|
|
770
|
-
if (unset !== void 0) return {
|
|
771
|
-
ok: false,
|
|
772
|
-
error: `${MCP_FILE} reads ${unset.name}, which is not set`
|
|
773
|
-
};
|
|
774
|
-
const values = [];
|
|
775
|
-
const fill = (text) => text.replaceAll(VARIABLE, (_all, name, fallback) => {
|
|
776
|
-
const value = readEnv(environ, name);
|
|
777
|
-
if (value !== void 0 && !plain.includes(name)) values.push(value);
|
|
778
|
-
return value ?? fallback ?? "";
|
|
779
|
-
});
|
|
780
|
-
const fillAll = (record) => Object.fromEntries(Object.entries(record).map(([key, text]) => [key, fill(text)]));
|
|
781
|
-
return {
|
|
782
|
-
ok: true,
|
|
783
|
-
value: {
|
|
784
|
-
server: server.kind === "stdio" ? {
|
|
785
|
-
kind: "stdio",
|
|
786
|
-
command: fill(server.command),
|
|
787
|
-
args: server.args.map((arg) => fill(arg)),
|
|
788
|
-
env: fillAll(server.env)
|
|
789
|
-
} : {
|
|
790
|
-
kind: "http",
|
|
791
|
-
url: fill(server.url),
|
|
792
|
-
headers: fillAll(server.headers)
|
|
793
|
-
},
|
|
794
|
-
values
|
|
795
|
-
}
|
|
796
|
-
};
|
|
797
|
-
};
|
|
798
|
-
/** What a workflow's MCP servers read of the user's, unless called not secret. */
|
|
799
|
-
const mcpVariablesOf = (workflow, root) => Object.values(workflow.nodes).flatMap((node) => {
|
|
800
|
-
if (node.type !== "mcp.call") return [];
|
|
801
|
-
const read = readMcpServer(root, node.server);
|
|
802
|
-
return read.ok ? readsOf(read.value).map(({ name }) => name).filter((name) => node.plainEnv?.includes(name) !== true) : [];
|
|
803
|
-
});
|
|
804
|
-
/** A stdio server's program, when its name can be known before it is filled in. */
|
|
805
|
-
const programOf = (server) => server.kind === "stdio" && !server.command.includes("$") ? server.command : void 0;
|
|
806
|
-
/**
|
|
807
|
-
* What stops a workflow's `mcp.call` nodes, found before a run spends anything:
|
|
808
|
-
* a server that isn't there or can't be called, a program that isn't installed,
|
|
809
|
-
* or a variable that is not set.
|
|
810
|
-
*/
|
|
811
|
-
const mcpProblems = (workflow, root, environ = process.env, finished = /* @__PURE__ */ new Set(), installed = () => true) => Object.entries(workflow.nodes).flatMap(([id, node]) => {
|
|
812
|
-
if (node.type !== "mcp.call" || finished.has(id)) return [];
|
|
813
|
-
const read = readMcpServer(root, node.server);
|
|
814
|
-
if (!read.ok) return [`${id}: ${read.error}`];
|
|
815
|
-
const given = new Set(Object.keys(node.env ?? {}));
|
|
816
|
-
const unset = readsOf(read.value).flatMap(({ name, fallback }) => fallback || given.has(name) || readEnv(environ, name) !== void 0 ? [] : [`${id}: ${MCP_FILE} reads ${name}, which is not set`]);
|
|
817
|
-
const program = programOf(read.value);
|
|
818
|
-
return program === void 0 || installed(program) ? unset : [`\`${id}\`: MCP server \`${node.server}\` runs \`${program}\`, which is not installed`].concat(unset);
|
|
819
|
-
});
|
|
820
813
|
// ../nodes/src/tool-scrub.ts
|
|
821
814
|
/**
|
|
822
815
|
* @file Masking a secret in what a program prints. A plain search, so a value
|
|
@@ -1589,7 +1582,12 @@ const claudeExecutor = (options) => async (context) => {
|
|
|
1589
1582
|
},
|
|
1590
1583
|
error: plan.error
|
|
1591
1584
|
};
|
|
1592
|
-
const
|
|
1585
|
+
const servers = namedMcpEntries(context.projectRoot, plan.mcp);
|
|
1586
|
+
if (!servers.ok) return notStarted(servers.error);
|
|
1587
|
+
const spec = {
|
|
1588
|
+
...specFor(plan.spec, context),
|
|
1589
|
+
...servers.value
|
|
1590
|
+
};
|
|
1593
1591
|
if (options.machineClaude === true) spec.machineClaude = true;
|
|
1594
1592
|
const driver = sessionDriver({
|
|
1595
1593
|
override: options.driver,
|
|
@@ -2130,4 +2128,4 @@ const missingPrograms = (workflow, installed = (program) => onPath(program)) =>
|
|
|
2130
2128
|
}
|
|
2131
2129
|
return [...missing.values()];
|
|
2132
2130
|
};
|
|
2133
|
-
export {
|
|
2131
|
+
export { namedMcpEntries as _, builtinExecutors as a, toolExecutor as c, maskedEnv as d, maskedNamesOfRun as f, clearOutputFiles as g, sessionEnv as h, onPath as i, clearStateFiles as l, runScrubber as m, missingProgramMessage as n, spawnTool as o, runMarkerIn as p, missingPrograms as r, mcpCallExecutor as s, envProblems as t, inheritedScrubber as u, resultOf as v };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ht as FEEDBACK_SEVERITIES, Ut as FEEDBACK_TARGETS, Vt as FEEDBACK_KINDS, pt as parseReport } from "./src-BRB5EQyC.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
4
4
|
import { createInterface } from "node:readline";
|
|
@@ -818,12 +818,15 @@ const userLine = (text, later = false) => `${JSON.stringify({
|
|
|
818
818
|
* `allowed` are the Ork tools that need no permission prompt.
|
|
819
819
|
*/
|
|
820
820
|
const buildCliArgs = (spec, mcp, allowed) => {
|
|
821
|
-
const mcpConfig = { mcpServers: {
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
821
|
+
const mcpConfig = { mcpServers: {
|
|
822
|
+
...spec.mcpServers,
|
|
823
|
+
["ork"]: {
|
|
824
|
+
type: "http",
|
|
825
|
+
url: mcp.url,
|
|
826
|
+
headers: { Authorization: `Bearer ${mcp.token}` },
|
|
827
|
+
timeout: ORK_TOOL_TIMEOUT_MS
|
|
828
|
+
}
|
|
829
|
+
} };
|
|
827
830
|
const args = [
|
|
828
831
|
"-p",
|
|
829
832
|
"--input-format",
|
|
@@ -1041,6 +1044,8 @@ const holdHook = (hold, onDefer, windowMs) => ({
|
|
|
1041
1044
|
} };
|
|
1042
1045
|
}]
|
|
1043
1046
|
});
|
|
1047
|
+
/** The compiler has checked each entry has a command or a url. */
|
|
1048
|
+
const namedServers = (spec) => Object.fromEntries(Object.entries(spec.mcpServers ?? {}).filter((entry) => typeof entry[1]["command"] === "string" || typeof entry[1]["url"] === "string"));
|
|
1044
1049
|
/** The Agent SDK options for a session spec. */
|
|
1045
1050
|
const buildSdkOptions = (spec, ports, env, held) => {
|
|
1046
1051
|
const { human } = ports;
|
|
@@ -1070,7 +1075,10 @@ const buildSdkOptions = (spec, ports, env, held) => {
|
|
|
1070
1075
|
permissionMode: spec.permissionMode,
|
|
1071
1076
|
allowedTools: [...spec.tools.allow, ...preapprovedTools(tools)],
|
|
1072
1077
|
disallowedTools: spec.tools.deny,
|
|
1073
|
-
mcpServers: {
|
|
1078
|
+
mcpServers: {
|
|
1079
|
+
...namedServers(spec),
|
|
1080
|
+
["ork"]: ork
|
|
1081
|
+
},
|
|
1074
1082
|
outputFormat: {
|
|
1075
1083
|
type: "json_schema",
|
|
1076
1084
|
schema: spec.reportSchema
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { B as linkNodes,
|
|
2
|
-
import { C as feedbackActions, S as placeOf$1, _ as previewPost, a as registryShown, b as acceptItem, c as checkDue, f as readUpdateCache, g as nodeSession, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, o as updateSwitchOff, p as refreshUpdateCache, s as runInstall, u as newerVersion, w as openFixRun, x as lessonPlaceOf, y as recordNote } from "./__build_info__-
|
|
3
|
-
import { n as pendingDecisions, r as builtinProblem, t as answerDecision } from "./decide-
|
|
4
|
-
import { n as newRunId, t as findRun } from "./find-
|
|
5
|
-
import { c as openStore, l as storePath, s as nodeOf } from "./output-
|
|
1
|
+
import { B as linkNodes, Bn as readDocument, Cn as placeFiles, Ct as walkChecks, En as runDirOf, G as requestContinue, Gn as EdgeInputSchema, Gt as planPost, Hn as parseWorkflow, In as skillsIn, J as tellLiveRun, Jn as expandEdge, K as requestPause, Kt as runGh, Ln as WorkflowEditSchema, Nt as nodeSays, On as workflowDirOf, Rn as applyEdits, St as checkWorkflowText, U as unlinkNodes, Vn as renderJsonSchema, Wt as DISCUSSIONS, Xn as NodeSchema, _t as runStatus, bt as processAlive, ct as explainWorkflowText, d as runningRunIds, f as runningScript, gt as pausedOf, ht as liveStatus, in as readCondition, jn as LESSON_CAP_TOKENS, kn as inside, l as planUpgrade, nt as resumable, o as limitsReport, ot as detachRun, p as detectInstaller, q as requestStop, qt as sendPost, r as capsHere, st as followEvents, tt as detachResume, u as releaseNotes, v as triggersReport, vn as loadAgents, vt as runTree, wn as placeFor, wt as walkSummary, zn as newWorkflowText } from "./src-BRB5EQyC.mjs";
|
|
2
|
+
import { C as feedbackActions, S as placeOf$1, _ as previewPost, a as registryShown, b as acceptItem, c as checkDue, f as readUpdateCache, g as nodeSession, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, o as updateSwitchOff, p as refreshUpdateCache, s as runInstall, u as newerVersion, w as openFixRun, x as lessonPlaceOf, y as recordNote } from "./__build_info__-1i1IwLg7.mjs";
|
|
3
|
+
import { n as pendingDecisions, r as builtinProblem, t as answerDecision } from "./decide-CBhYcjwI.mjs";
|
|
4
|
+
import { n as newRunId, t as findRun } from "./find-BgZjVKhv.mjs";
|
|
5
|
+
import { c as openStore, l as storePath, s as nodeOf } from "./output-CuivUcDa.mjs";
|
|
6
6
|
import { n as usageReport } from "./report-DK4LGqwF.mjs";
|
|
7
|
-
import { a as planClean, i as keyOf, o as stepActs, r as cleanStep, s as stepPrunes, t as applyClean } from "./clean-
|
|
8
|
-
import { a as readWorktrees, c as planLine, i as projectHead, l as removeRefusal, n as lostWork, o as labelOf, r as planRemove, s as mergeStateOf, t as applyRemove, u as stateParts } from "./remove-
|
|
7
|
+
import { a as planClean, i as keyOf, o as stepActs, r as cleanStep, s as stepPrunes, t as applyClean } from "./clean-B1zPxq6A.mjs";
|
|
8
|
+
import { a as readWorktrees, c as planLine, i as projectHead, l as removeRefusal, n as lostWork, o as labelOf, r as planRemove, s as mergeStateOf, t as applyRemove, u as stateParts } from "./remove-DLfDjBdF.mjs";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|