@stigmer/runner 3.12.4 → 3.12.6
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-fingerprint +1 -1
- package/dist/activities/call-agent.js +19 -6
- package/dist/activities/call-agent.js.map +1 -1
- package/dist/activities/execute-cursor/cursor-mcp-config.d.ts +45 -0
- package/dist/activities/execute-cursor/cursor-mcp-config.js +76 -0
- package/dist/activities/execute-cursor/cursor-mcp-config.js.map +1 -0
- package/dist/activities/execute-cursor/error-classifier.d.ts +9 -0
- package/dist/activities/execute-cursor/error-classifier.js +30 -1
- package/dist/activities/execute-cursor/error-classifier.js.map +1 -1
- package/dist/activities/execute-cursor/index.d.ts +10 -1
- package/dist/activities/execute-cursor/index.js +62 -36
- package/dist/activities/execute-cursor/index.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +13 -2
- package/dist/activities/execute-cursor/prompt-builder.js +11 -0
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/service-tier.d.ts +38 -29
- package/dist/activities/execute-cursor/service-tier.js +92 -63
- package/dist/activities/execute-cursor/service-tier.js.map +1 -1
- package/dist/activities/execute-cursor/session-lifecycle.d.ts +1 -1
- package/dist/activities/execute-cursor/skill-resolver.d.ts +2 -21
- package/dist/activities/execute-cursor/skill-resolver.js +5 -108
- package/dist/activities/execute-cursor/skill-resolver.js.map +1 -1
- package/dist/activities/execute-cursor/usage-accumulator.d.ts +16 -2
- package/dist/activities/execute-cursor/usage-accumulator.js +12 -2
- package/dist/activities/execute-cursor/usage-accumulator.js.map +1 -1
- package/dist/activities/execute-deep-agent/approval-file-change.d.ts +9 -0
- package/dist/activities/execute-deep-agent/approval-file-change.js +2 -1
- package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -1
- package/dist/activities/execute-deep-agent/cas-capture-backend.d.ts +18 -1
- package/dist/activities/execute-deep-agent/cas-capture-backend.js +20 -3
- package/dist/activities/execute-deep-agent/cas-capture-backend.js.map +1 -1
- package/dist/activities/execute-deep-agent/index.js +57 -5
- package/dist/activities/execute-deep-agent/index.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +9 -0
- package/dist/activities/execute-deep-agent/prompt-builder.js +10 -0
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/setup.js +17 -16
- package/dist/activities/execute-deep-agent/setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.js +17 -11
- package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/middleware/path-normalization.d.ts +49 -49
- package/dist/middleware/path-normalization.js +73 -84
- package/dist/middleware/path-normalization.js.map +1 -1
- package/dist/middleware/types.d.ts +3 -3
- package/dist/runner-manager.d.ts +1 -1
- package/dist/runner-manager.js +22 -15
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.js +11 -0
- package/dist/runner.js.map +1 -1
- package/dist/shared/args-preview.d.ts +8 -0
- package/dist/shared/args-preview.js +14 -3
- package/dist/shared/args-preview.js.map +1 -1
- package/dist/shared/artifact-storage.d.ts +11 -1
- package/dist/shared/artifact-storage.js +10 -1
- package/dist/shared/artifact-storage.js.map +1 -1
- package/dist/shared/caller-identity.d.ts +10 -7
- package/dist/shared/caller-identity.js +10 -7
- package/dist/shared/caller-identity.js.map +1 -1
- package/dist/shared/declared-preferences.d.ts +47 -0
- package/dist/shared/declared-preferences.js +64 -0
- package/dist/shared/declared-preferences.js.map +1 -0
- package/dist/shared/mcp-enabled-tools.d.ts +2 -3
- package/dist/shared/mcp-enabled-tools.js +2 -3
- package/dist/shared/mcp-enabled-tools.js.map +1 -1
- package/dist/shared/mcp-resolver.d.ts +20 -15
- package/dist/shared/mcp-resolver.js +11 -12
- package/dist/shared/mcp-resolver.js.map +1 -1
- package/dist/shared/placeholder-resolver.d.ts +9 -2
- package/dist/shared/placeholder-resolver.js +9 -2
- package/dist/shared/placeholder-resolver.js.map +1 -1
- package/dist/shared/plan-mode-permissions.d.ts +26 -46
- package/dist/shared/plan-mode-permissions.js +27 -55
- package/dist/shared/plan-mode-permissions.js.map +1 -1
- package/dist/shared/skill-mount.d.ts +89 -0
- package/dist/shared/skill-mount.js +142 -0
- package/dist/shared/skill-mount.js.map +1 -0
- package/dist/shared/skill-writer.d.ts +28 -26
- package/dist/shared/skill-writer.js +79 -102
- package/dist/shared/skill-writer.js.map +1 -1
- package/dist/shared/thinking-mode.d.ts +35 -0
- package/dist/shared/thinking-mode.js +43 -0
- package/dist/shared/thinking-mode.js.map +1 -0
- package/dist/shared/worker-shutdown.d.ts +67 -0
- package/dist/shared/worker-shutdown.js +79 -0
- package/dist/shared/worker-shutdown.js.map +1 -0
- package/dist/shared/workspace/types.d.ts +3 -2
- package/dist/workflow-engine/loader.js +82 -6
- package/dist/workflow-engine/loader.js.map +1 -1
- package/dist/workflow-engine/tasks/human-input.d.ts +2 -1
- package/dist/workflow-engine/tasks/human-input.js +31 -3
- package/dist/workflow-engine/tasks/human-input.js.map +1 -1
- package/dist/workflow-engine/types.d.ts +17 -3
- package/dist/workflow-engine/types.js.map +1 -1
- package/dist/workflows/human-input-orchestrator.d.ts +4 -0
- package/dist/workflows/human-input-orchestrator.js +13 -0
- package/dist/workflows/human-input-orchestrator.js.map +1 -1
- package/package.json +15 -11
- package/src/activities/call-agent.ts +20 -6
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +50 -0
- package/src/activities/execute-cursor/__tests__/cursor-mcp-config.test.ts +111 -0
- package/src/activities/execute-cursor/__tests__/error-classifier-billing.test.ts +67 -0
- package/src/activities/execute-cursor/__tests__/service-tier.test.ts +67 -7
- package/src/activities/execute-cursor/__tests__/skill-resolver.test.ts +3 -94
- package/src/activities/execute-cursor/__tests__/usage-accumulator.test.ts +33 -1
- package/src/activities/execute-cursor/cursor-mcp-config.ts +107 -0
- package/src/activities/execute-cursor/error-classifier.ts +42 -1
- package/src/activities/execute-cursor/index.ts +78 -41
- package/src/activities/execute-cursor/prompt-builder.ts +29 -2
- package/src/activities/execute-cursor/service-tier.ts +94 -63
- package/src/activities/execute-cursor/session-lifecycle.ts +1 -1
- package/src/activities/execute-cursor/skill-resolver.ts +10 -137
- package/src/activities/execute-cursor/usage-accumulator.ts +11 -1
- package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +15 -0
- package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +75 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/index.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +42 -29
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +52 -0
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +11 -8
- package/src/activities/execute-deep-agent/approval-file-change.ts +11 -1
- package/src/activities/execute-deep-agent/cas-capture-backend.ts +20 -3
- package/src/activities/execute-deep-agent/index.ts +57 -5
- package/src/activities/execute-deep-agent/prompt-builder.ts +22 -0
- package/src/activities/execute-deep-agent/setup.ts +21 -19
- package/src/activities/execute-deep-agent/subagent-transformer.ts +19 -12
- package/src/activities/execute-deep-agent/subagent-wiring.ts +3 -3
- package/src/index.ts +1 -1
- package/src/middleware/__tests__/path-normalization.test.ts +32 -32
- package/src/middleware/path-normalization.ts +78 -90
- package/src/middleware/types.ts +3 -3
- package/src/runner-manager.ts +26 -16
- package/src/runner.ts +14 -0
- package/src/shared/__tests__/artifact-storage.test.ts +28 -0
- package/src/shared/__tests__/bedrock-seam.test.ts +5 -5
- package/src/shared/__tests__/declared-preferences.test.ts +109 -0
- package/src/shared/__tests__/foundry-seam.test.ts +5 -5
- package/src/shared/__tests__/plan-mode-permissions.test.ts +15 -44
- package/src/shared/__tests__/skill-mount.test.ts +238 -0
- package/src/shared/__tests__/skill-writer.test.ts +151 -128
- package/src/shared/__tests__/vertex-adapter.test.ts +30 -3
- package/src/shared/__tests__/vertex-seam.test.ts +5 -5
- package/src/shared/__tests__/worker-shutdown.test.ts +101 -0
- package/src/shared/args-preview.ts +17 -3
- package/src/shared/artifact-storage.ts +20 -1
- package/src/shared/caller-identity.ts +10 -7
- package/src/shared/declared-preferences.ts +84 -0
- package/src/shared/mcp-enabled-tools.ts +2 -3
- package/src/shared/mcp-resolver.ts +20 -20
- package/src/shared/placeholder-resolver.ts +9 -2
- package/src/shared/plan-mode-permissions.ts +27 -58
- package/src/shared/skill-mount.ts +179 -0
- package/src/shared/skill-writer.ts +96 -130
- package/src/shared/thinking-mode.ts +52 -0
- package/src/shared/worker-shutdown.ts +99 -0
- package/src/shared/workspace/types.ts +3 -2
- package/src/workflow-engine/__tests__/loader.test.ts +95 -0
- package/src/workflow-engine/__tests__/tasks/human-input.test.ts +156 -0
- package/src/workflow-engine/loader.ts +97 -6
- package/src/workflow-engine/tasks/human-input.ts +41 -6
- package/src/workflow-engine/types.ts +18 -3
- package/src/workflows/human-input-orchestrator.ts +20 -2
- package/dist/activities/execute-cursor/connect-backfill.d.ts +0 -19
- package/dist/activities/execute-cursor/connect-backfill.js +0 -27
- package/dist/activities/execute-cursor/connect-backfill.js.map +0 -1
- package/dist/activities/execute-cursor/mcp-resolver.d.ts +0 -120
- package/dist/activities/execute-cursor/mcp-resolver.js +0 -194
- package/dist/activities/execute-cursor/mcp-resolver.js.map +0 -1
- package/dist/activities/execute-cursor/placeholder-resolver.d.ts +0 -34
- package/dist/activities/execute-cursor/placeholder-resolver.js +0 -82
- package/dist/activities/execute-cursor/placeholder-resolver.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/mcp-resolver.test.ts +0 -125
- package/src/activities/execute-cursor/connect-backfill.ts +0 -52
- package/src/activities/execute-cursor/mcp-resolver.ts +0 -324
- package/src/activities/execute-cursor/placeholder-resolver.ts +0 -109
|
@@ -1528,6 +1528,101 @@ do:
|
|
|
1528
1528
|
}
|
|
1529
1529
|
});
|
|
1530
1530
|
|
|
1531
|
+
// The server converter persists on_timeout as the proto enum NAME
|
|
1532
|
+
// (HumanInputTimeoutPolicy.String()), so every applied workflow carries
|
|
1533
|
+
// that form in its validated YAML. stigmer/stigmer#779: the loader used
|
|
1534
|
+
// to cast it unvalidated, and the orchestrator's switch silently treated
|
|
1535
|
+
// the unrecognized string as fail.
|
|
1536
|
+
const humanInputYamlWithOnTimeout = (onTimeout: string) => `
|
|
1537
|
+
document:
|
|
1538
|
+
dsl: '1.0.0'
|
|
1539
|
+
name: test
|
|
1540
|
+
do:
|
|
1541
|
+
- timedApproval:
|
|
1542
|
+
call: human_input
|
|
1543
|
+
with:
|
|
1544
|
+
prompt: "Approve within time limit"
|
|
1545
|
+
timeout: 3600
|
|
1546
|
+
on_timeout: ${onTimeout}
|
|
1547
|
+
`;
|
|
1548
|
+
|
|
1549
|
+
it("call: human_input normalizes proto enum-name on_timeout values to the internal policy words", () => {
|
|
1550
|
+
const cases = [
|
|
1551
|
+
["HUMAN_INPUT_TIMEOUT_FAIL", "fail"],
|
|
1552
|
+
["HUMAN_INPUT_TIMEOUT_APPROVE", "approve"],
|
|
1553
|
+
["HUMAN_INPUT_TIMEOUT_DENY", "deny"],
|
|
1554
|
+
] as const;
|
|
1555
|
+
for (const [wireForm, internalForm] of cases) {
|
|
1556
|
+
const model = loadWorkflowFromYaml(humanInputYamlWithOnTimeout(wireForm));
|
|
1557
|
+
const task = model.do[0].task;
|
|
1558
|
+
expect(task.kind).toBe("human_input");
|
|
1559
|
+
if (task.kind === "human_input") {
|
|
1560
|
+
expect(task.humanInput.onTimeout).toBe(internalForm);
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
});
|
|
1564
|
+
|
|
1565
|
+
// The escalate outcome-by-name contract (stigmer/stigmer#781): the policy
|
|
1566
|
+
// loads only when the gate declares an outcome named "escalate" with
|
|
1567
|
+
// `then` set — the timeout resolves to that outcome and follows its branch.
|
|
1568
|
+
const escalateYamlWithOutcomes = (onTimeout: string, outcomesYaml: string) => `
|
|
1569
|
+
document:
|
|
1570
|
+
dsl: '1.0.0'
|
|
1571
|
+
name: test
|
|
1572
|
+
do:
|
|
1573
|
+
- timedApproval:
|
|
1574
|
+
call: human_input
|
|
1575
|
+
with:
|
|
1576
|
+
prompt: "Approve within time limit"
|
|
1577
|
+
timeout: 3600
|
|
1578
|
+
on_timeout: ${onTimeout}
|
|
1579
|
+
outcomes:
|
|
1580
|
+
${outcomesYaml}
|
|
1581
|
+
`;
|
|
1582
|
+
|
|
1583
|
+
it("call: human_input accepts the escalate policy when an escalate outcome with then exists", () => {
|
|
1584
|
+
for (const form of ["HUMAN_INPUT_TIMEOUT_ESCALATE", "escalate"]) {
|
|
1585
|
+
const model = loadWorkflowFromYaml(escalateYamlWithOutcomes(form, `
|
|
1586
|
+
- name: proceed
|
|
1587
|
+
- name: escalate
|
|
1588
|
+
then: escalationPath
|
|
1589
|
+
`));
|
|
1590
|
+
const task = model.do[0].task;
|
|
1591
|
+
expect(task.kind).toBe("human_input");
|
|
1592
|
+
if (task.kind === "human_input") {
|
|
1593
|
+
expect(task.humanInput.onTimeout).toBe("escalate");
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
});
|
|
1597
|
+
|
|
1598
|
+
it("call: human_input rejects the escalate policy without an escalate outcome", () => {
|
|
1599
|
+
expect(() => loadWorkflowFromYaml(humanInputYamlWithOnTimeout("escalate")))
|
|
1600
|
+
.toThrow(/timedApproval.*escalate.*requires an outcome named 'escalate'/);
|
|
1601
|
+
expect(() => loadWorkflowFromYaml(escalateYamlWithOutcomes("HUMAN_INPUT_TIMEOUT_ESCALATE", `
|
|
1602
|
+
- name: proceed
|
|
1603
|
+
- name: reject
|
|
1604
|
+
`)))
|
|
1605
|
+
.toThrow(/timedApproval.*requires an outcome named 'escalate'/);
|
|
1606
|
+
});
|
|
1607
|
+
|
|
1608
|
+
it("call: human_input rejects the escalate policy when the escalate outcome has no then", () => {
|
|
1609
|
+
expect(() => loadWorkflowFromYaml(escalateYamlWithOutcomes("escalate", `
|
|
1610
|
+
- name: proceed
|
|
1611
|
+
- name: escalate
|
|
1612
|
+
`)))
|
|
1613
|
+
.toThrow(/timedApproval.*requires an outcome named 'escalate' with 'then' set/);
|
|
1614
|
+
});
|
|
1615
|
+
|
|
1616
|
+
it("call: human_input rejects unknown on_timeout values instead of silently failing at timeout", () => {
|
|
1617
|
+
expect(() => loadWorkflowFromYaml(humanInputYamlWithOnTimeout("sometimes")))
|
|
1618
|
+
.toThrow(/timedApproval.*unknown on_timeout value 'sometimes'.*fail, approve, deny/);
|
|
1619
|
+
});
|
|
1620
|
+
|
|
1621
|
+
it("call: human_input rejects non-string on_timeout values", () => {
|
|
1622
|
+
expect(() => loadWorkflowFromYaml(humanInputYamlWithOnTimeout("42")))
|
|
1623
|
+
.toThrow(/timedApproval.*on_timeout/);
|
|
1624
|
+
});
|
|
1625
|
+
|
|
1531
1626
|
it("call: human_input with payload and ui_hint", () => {
|
|
1532
1627
|
const yaml = `
|
|
1533
1628
|
document:
|
|
@@ -246,6 +246,162 @@ describe("executeHumanInputTask", () => {
|
|
|
246
246
|
});
|
|
247
247
|
});
|
|
248
248
|
|
|
249
|
+
// HumanInputTaskConfig.outcomes contract (human_input.proto): with custom
|
|
250
|
+
// outcomes, timeout auto-approve resolves to the FIRST outcome and timeout
|
|
251
|
+
// auto-deny to the LAST — downstream `then` routing and outcome switches
|
|
252
|
+
// must see declared outcome names, never the internal approve/deny words a
|
|
253
|
+
// reviewer was never offered. stigmer/stigmer#779 made this path reachable
|
|
254
|
+
// for the first time.
|
|
255
|
+
describe("timeout outcome mapping with custom outcomes", () => {
|
|
256
|
+
const outcomes = [
|
|
257
|
+
{ name: "proceed", label: "Proceed", then: "deployStep" },
|
|
258
|
+
{ name: "needs_revision", label: "Needs revision", then: "gatherMore" },
|
|
259
|
+
{ name: "reject", label: "Reject" },
|
|
260
|
+
];
|
|
261
|
+
|
|
262
|
+
it("maps timeout auto-approve to the FIRST outcome and routes its then", async () => {
|
|
263
|
+
const awaitFn: AwaitHumanInputFn = async () => ({
|
|
264
|
+
outcome: "approve",
|
|
265
|
+
auto_resolved: true,
|
|
266
|
+
reason: "timeout",
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const taskDef: HumanInputTaskDef = {
|
|
270
|
+
kind: "human_input",
|
|
271
|
+
humanInput: { prompt: "Review", timeout: 5, onTimeout: "approve", outcomes },
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const state = createState();
|
|
275
|
+
const result = await executeHumanInputTask(taskDef, "gate", state, makeCtx(awaitFn));
|
|
276
|
+
|
|
277
|
+
expect(result).toEqual({
|
|
278
|
+
outcome: "proceed",
|
|
279
|
+
auto_resolved: true,
|
|
280
|
+
reason: "timeout",
|
|
281
|
+
__flow_directive__: "deployStep",
|
|
282
|
+
});
|
|
283
|
+
expect(state.data.gate).toEqual({
|
|
284
|
+
outcome: "proceed",
|
|
285
|
+
auto_resolved: true,
|
|
286
|
+
reason: "timeout",
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("maps timeout auto-deny to the LAST outcome", async () => {
|
|
291
|
+
const awaitFn: AwaitHumanInputFn = async () => ({
|
|
292
|
+
outcome: "deny",
|
|
293
|
+
auto_resolved: true,
|
|
294
|
+
reason: "timeout",
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const taskDef: HumanInputTaskDef = {
|
|
298
|
+
kind: "human_input",
|
|
299
|
+
humanInput: { prompt: "Review", timeout: 5, onTimeout: "deny", outcomes },
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
const result = await executeHumanInputTask(taskDef, "gate", createState(), makeCtx(awaitFn));
|
|
303
|
+
|
|
304
|
+
// "reject" is the last outcome and declares no `then` — no directive.
|
|
305
|
+
expect(result).toEqual({ outcome: "reject", auto_resolved: true, reason: "timeout" });
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// The escalate outcome-by-name contract (stigmer/stigmer#781): the policy
|
|
309
|
+
// word IS the declared outcome's name, so no positional remapping happens
|
|
310
|
+
// — the ordinary name lookup finds the "escalate" outcome and routes its
|
|
311
|
+
// `then`, regardless of the outcome's position in the list.
|
|
312
|
+
it("resolves timeout escalate to the escalate-named outcome and routes its then", async () => {
|
|
313
|
+
const awaitFn: AwaitHumanInputFn = async () => ({
|
|
314
|
+
outcome: "escalate",
|
|
315
|
+
auto_resolved: true,
|
|
316
|
+
reason: "timeout",
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
const escalateOutcomes = [
|
|
320
|
+
{ name: "proceed", label: "Proceed", then: "deployStep" },
|
|
321
|
+
{ name: "escalate", label: "Escalate", then: "escalationPath" },
|
|
322
|
+
{ name: "reject", label: "Reject" },
|
|
323
|
+
];
|
|
324
|
+
const taskDef: HumanInputTaskDef = {
|
|
325
|
+
kind: "human_input",
|
|
326
|
+
humanInput: {
|
|
327
|
+
prompt: "Review", timeout: 5, onTimeout: "escalate", outcomes: escalateOutcomes,
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
const state = createState();
|
|
332
|
+
const result = await executeHumanInputTask(taskDef, "gate", state, makeCtx(awaitFn));
|
|
333
|
+
|
|
334
|
+
expect(result).toEqual({
|
|
335
|
+
outcome: "escalate",
|
|
336
|
+
auto_resolved: true,
|
|
337
|
+
reason: "timeout",
|
|
338
|
+
__flow_directive__: "escalationPath",
|
|
339
|
+
});
|
|
340
|
+
expect(state.data.gate).toEqual({
|
|
341
|
+
outcome: "escalate",
|
|
342
|
+
auto_resolved: true,
|
|
343
|
+
reason: "timeout",
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it("reports the mapped outcome on the approval_resolved event", async () => {
|
|
348
|
+
const emitted: WorkflowEventDescriptor[][] = [];
|
|
349
|
+
const emitFn: EmitEventsFn = async (events) => { emitted.push(events); };
|
|
350
|
+
const awaitFn: AwaitHumanInputFn = async () => ({
|
|
351
|
+
outcome: "approve",
|
|
352
|
+
auto_resolved: true,
|
|
353
|
+
reason: "timeout",
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
const taskDef: HumanInputTaskDef = {
|
|
357
|
+
kind: "human_input",
|
|
358
|
+
humanInput: { prompt: "Review", timeout: 5, onTimeout: "approve", outcomes },
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
await executeHumanInputTask(taskDef, "gate", createState(), makeCtx(awaitFn, emitFn));
|
|
362
|
+
|
|
363
|
+
const resolved = emitted.flat().find((e) => e.type === "approval_resolved");
|
|
364
|
+
expect(resolved).toMatchObject({ outcome: "proceed", autoResolved: true });
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it("leaves reviewer-selected outcomes untouched", async () => {
|
|
368
|
+
const awaitFn: AwaitHumanInputFn = async () => ({
|
|
369
|
+
outcome: "needs_revision",
|
|
370
|
+
reviewer: "alice",
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
const taskDef: HumanInputTaskDef = {
|
|
374
|
+
kind: "human_input",
|
|
375
|
+
humanInput: { prompt: "Review", timeout: 5, onTimeout: "approve", outcomes },
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
const result = await executeHumanInputTask(taskDef, "gate", createState(), makeCtx(awaitFn));
|
|
379
|
+
|
|
380
|
+
expect(result).toEqual({
|
|
381
|
+
outcome: "needs_revision",
|
|
382
|
+
reviewer: "alice",
|
|
383
|
+
__flow_directive__: "gatherMore",
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it("keeps plain approve/deny for binary gates without custom outcomes", async () => {
|
|
388
|
+
const awaitFn: AwaitHumanInputFn = async () => ({
|
|
389
|
+
outcome: "approve",
|
|
390
|
+
auto_resolved: true,
|
|
391
|
+
reason: "timeout",
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
const taskDef: HumanInputTaskDef = {
|
|
395
|
+
kind: "human_input",
|
|
396
|
+
humanInput: { prompt: "Review", timeout: 5, onTimeout: "approve" },
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
const result = await executeHumanInputTask(taskDef, "gate", createState(), makeCtx(awaitFn));
|
|
400
|
+
|
|
401
|
+
expect(result).toEqual({ outcome: "approve", auto_resolved: true, reason: "timeout" });
|
|
402
|
+
});
|
|
403
|
+
});
|
|
404
|
+
|
|
249
405
|
describe("event emission", () => {
|
|
250
406
|
it("emits approval_requested before blocking with correct fields", async () => {
|
|
251
407
|
const emitted: WorkflowEventDescriptor[][] = [];
|
|
@@ -34,6 +34,7 @@ import type {
|
|
|
34
34
|
BackoffConfig,
|
|
35
35
|
JitterConfig,
|
|
36
36
|
DurationDef,
|
|
37
|
+
HumanInputTimeoutPolicy,
|
|
37
38
|
} from "./types.js";
|
|
38
39
|
|
|
39
40
|
const SUPPORTED_DSL_RANGE = ">=1.0.0 <2.0.0";
|
|
@@ -548,12 +549,14 @@ function parseAgentCallRunConfig(raw: unknown): AgentCallConfig["run_config"] {
|
|
|
548
549
|
}
|
|
549
550
|
const obj = raw as Record<string, unknown>;
|
|
550
551
|
|
|
551
|
-
const known = new Set([
|
|
552
|
+
const known = new Set([
|
|
553
|
+
"model_name", "max_cost_usd", "max_tool_rounds", "service_tier", "thinking_mode",
|
|
554
|
+
]);
|
|
552
555
|
for (const key of Object.keys(obj)) {
|
|
553
556
|
if (!known.has(key)) {
|
|
554
557
|
throw new Error(
|
|
555
558
|
`call:agent 'run_config' has unknown field '${key}' ` +
|
|
556
|
-
`(expected: model_name, max_cost_usd, max_tool_rounds, service_tier)`,
|
|
559
|
+
`(expected: model_name, max_cost_usd, max_tool_rounds, service_tier, thinking_mode)`,
|
|
557
560
|
);
|
|
558
561
|
}
|
|
559
562
|
}
|
|
@@ -571,12 +574,14 @@ function parseAgentCallRunConfig(raw: unknown): AgentCallConfig["run_config"] {
|
|
|
571
574
|
throw new Error("call:agent 'run_config.max_tool_rounds' must be a number >= 0");
|
|
572
575
|
}
|
|
573
576
|
const serviceTier = parseServiceTier(obj.service_tier);
|
|
577
|
+
const thinkingMode = parseThinkingMode(obj.thinking_mode);
|
|
574
578
|
|
|
575
579
|
return {
|
|
576
580
|
model_name: modelName,
|
|
577
581
|
max_cost_usd: maxCostUsd,
|
|
578
582
|
max_tool_rounds: maxToolRounds,
|
|
579
583
|
service_tier: serviceTier,
|
|
584
|
+
thinking_mode: thinkingMode,
|
|
580
585
|
};
|
|
581
586
|
}
|
|
582
587
|
|
|
@@ -608,6 +613,73 @@ function parseServiceTier(raw: unknown): string | undefined {
|
|
|
608
613
|
return canonical;
|
|
609
614
|
}
|
|
610
615
|
|
|
616
|
+
/**
|
|
617
|
+
* Maps YAML thinking-mode shorthands to canonical enum names, mirroring
|
|
618
|
+
* SERVICE_TIER_SHORTHANDS (stigmer/stigmer#772). Unknown values are
|
|
619
|
+
* authoring errors: the mode exists to make the served variant
|
|
620
|
+
* deterministic, so a typo must never silently fall back to the default.
|
|
621
|
+
*/
|
|
622
|
+
const THINKING_MODE_SHORTHANDS: Record<string, string> = {
|
|
623
|
+
disabled: "THINKING_MODE_DISABLED",
|
|
624
|
+
enabled: "THINKING_MODE_ENABLED",
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
function parseThinkingMode(raw: unknown): string | undefined {
|
|
628
|
+
if (raw === undefined || raw === null) return undefined;
|
|
629
|
+
if (typeof raw !== "string") {
|
|
630
|
+
throw new Error("call:agent 'run_config.thinking_mode' must be a string");
|
|
631
|
+
}
|
|
632
|
+
const canonical =
|
|
633
|
+
THINKING_MODE_SHORTHANDS[raw.toLowerCase()] ??
|
|
634
|
+
(Object.values(THINKING_MODE_SHORTHANDS).includes(raw) ? raw : undefined);
|
|
635
|
+
if (!canonical) {
|
|
636
|
+
throw new Error(
|
|
637
|
+
`call:agent 'run_config.thinking_mode' has unknown value '${raw}' ` +
|
|
638
|
+
`(expected: disabled, enabled)`,
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
return canonical;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Maps on_timeout values to the runner's internal policy words, mirroring
|
|
646
|
+
* SERVICE_TIER_SHORTHANDS. The persisted CNCF YAML carries the proto enum
|
|
647
|
+
* NAMES (the server converter emits `HumanInputTimeoutPolicy.String()`),
|
|
648
|
+
* while hand-written fixtures use the lowercase words — both are accepted.
|
|
649
|
+
* Unknown values are authoring errors: a timeout policy must never silently
|
|
650
|
+
* fall back to fail (stigmer/stigmer#779 — the unvalidated cast let every
|
|
651
|
+
* enum-name policy reach the orchestrator unrecognized, so gates configured
|
|
652
|
+
* to auto-approve/deny failed at their first real timeout instead).
|
|
653
|
+
*/
|
|
654
|
+
const ON_TIMEOUT_VOCABULARY: Record<string, HumanInputTimeoutPolicy> = {
|
|
655
|
+
fail: "fail",
|
|
656
|
+
approve: "approve",
|
|
657
|
+
deny: "deny",
|
|
658
|
+
escalate: "escalate",
|
|
659
|
+
HUMAN_INPUT_TIMEOUT_FAIL: "fail",
|
|
660
|
+
HUMAN_INPUT_TIMEOUT_APPROVE: "approve",
|
|
661
|
+
HUMAN_INPUT_TIMEOUT_DENY: "deny",
|
|
662
|
+
HUMAN_INPUT_TIMEOUT_ESCALATE: "escalate",
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
function parseOnTimeout(
|
|
666
|
+
taskName: string,
|
|
667
|
+
raw: unknown,
|
|
668
|
+
): HumanInputTimeoutPolicy | undefined {
|
|
669
|
+
if (raw === undefined || raw === null) return undefined;
|
|
670
|
+
if (typeof raw !== "string") {
|
|
671
|
+
throw new Error(`human_input task '${taskName}': 'on_timeout' must be a string`);
|
|
672
|
+
}
|
|
673
|
+
const policy = ON_TIMEOUT_VOCABULARY[raw];
|
|
674
|
+
if (!policy) {
|
|
675
|
+
throw new Error(
|
|
676
|
+
`human_input task '${taskName}': unknown on_timeout value '${raw}' ` +
|
|
677
|
+
`(expected: fail, approve, deny, escalate, or a HUMAN_INPUT_TIMEOUT_* enum name)`,
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
return policy;
|
|
681
|
+
}
|
|
682
|
+
|
|
611
683
|
function parseHumanInputConfig(taskName: string, raw: unknown): import("./types.js").HumanInputConfig {
|
|
612
684
|
if (!raw || typeof raw !== "object") {
|
|
613
685
|
throw new Error(`human_input task '${taskName}' requires a 'with' configuration block`);
|
|
@@ -618,11 +690,30 @@ function parseHumanInputConfig(taskName: string, raw: unknown): import("./types.
|
|
|
618
690
|
throw new Error(`human_input task '${taskName}' requires 'prompt' in 'with'`);
|
|
619
691
|
}
|
|
620
692
|
|
|
693
|
+
const outcomes = Array.isArray(obj.outcomes) && obj.outcomes.length > 0
|
|
694
|
+
? obj.outcomes.map((o: any) => ({ name: o.name, label: o.label, then: o.then }))
|
|
695
|
+
: undefined;
|
|
696
|
+
const onTimeout = parseOnTimeout(taskName, obj.on_timeout);
|
|
697
|
+
|
|
698
|
+
// The escalate policy's outcome-by-name contract (stigmer/stigmer#781):
|
|
699
|
+
// a timeout resolves to the outcome NAMED "escalate", so that outcome must
|
|
700
|
+
// exist and declare where the escalation branch goes. Checked at load so a
|
|
701
|
+
// misconfigured gate fails before it ever waits on a reviewer — the server
|
|
702
|
+
// validator enforces the same shape at apply; this covers hand-written YAML.
|
|
703
|
+
if (onTimeout === "escalate") {
|
|
704
|
+
const escalation = outcomes?.find((o) => o.name === "escalate");
|
|
705
|
+
if (!escalation || !escalation.then) {
|
|
706
|
+
throw new Error(
|
|
707
|
+
`human_input task '${taskName}': on_timeout policy 'escalate' requires ` +
|
|
708
|
+
`an outcome named 'escalate' with 'then' set (the timeout resolves to ` +
|
|
709
|
+
`that outcome and follows its 'then' branch)`,
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
621
714
|
return {
|
|
622
715
|
prompt: obj.prompt,
|
|
623
|
-
outcomes
|
|
624
|
-
? obj.outcomes.map((o: any) => ({ name: o.name, label: o.label, then: o.then }))
|
|
625
|
-
: undefined,
|
|
716
|
+
outcomes,
|
|
626
717
|
formSchema: obj.form_schema && typeof obj.form_schema === "object"
|
|
627
718
|
? obj.form_schema as Record<string, unknown>
|
|
628
719
|
: undefined,
|
|
@@ -630,7 +721,7 @@ function parseHumanInputConfig(taskName: string, raw: unknown): import("./types.
|
|
|
630
721
|
? obj.approvers.filter((a: unknown) => typeof a === "string") as string[]
|
|
631
722
|
: undefined,
|
|
632
723
|
timeout: typeof obj.timeout === "number" ? obj.timeout : undefined,
|
|
633
|
-
onTimeout
|
|
724
|
+
onTimeout,
|
|
634
725
|
// Any JSON shape is a valid payload (expression string, object, array),
|
|
635
726
|
// so only null/undefined mean "no payload" here.
|
|
636
727
|
payload: obj.payload ?? undefined,
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Human input task executor — HITL approval gate.
|
|
3
3
|
*
|
|
4
4
|
* Pauses workflow execution until a human reviewer responds via signal.
|
|
5
|
-
* Supports configurable timeout with policies (fail, auto-approve,
|
|
5
|
+
* Supports configurable timeout with policies (fail, auto-approve,
|
|
6
|
+
* auto-deny, escalate).
|
|
6
7
|
*
|
|
7
8
|
* The kernel validates the config and delegates to `ctx.awaitHumanInput()`
|
|
8
9
|
* which is wired to the Temporal workflow layer's signal/timer selector.
|
|
@@ -96,11 +97,14 @@ export async function executeHumanInputTask(
|
|
|
96
97
|
]);
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
const result: HumanInputResult =
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
const result: HumanInputResult = applyTimeoutOutcomeContract(
|
|
101
|
+
await ctx.awaitHumanInput({
|
|
102
|
+
signalName,
|
|
103
|
+
timeoutSeconds,
|
|
104
|
+
onTimeout,
|
|
105
|
+
}),
|
|
106
|
+
config.outcomes,
|
|
107
|
+
);
|
|
104
108
|
|
|
105
109
|
if (ctx.emitEvents) {
|
|
106
110
|
await ctx.emitEvents([{
|
|
@@ -132,6 +136,37 @@ function validateConfig(config: HumanInputConfig, taskName: string): void {
|
|
|
132
136
|
}
|
|
133
137
|
}
|
|
134
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Applies the proto contract for timeout auto-resolution with custom
|
|
141
|
+
* outcomes (HumanInputTaskConfig.outcomes doc): auto-approve resolves to
|
|
142
|
+
* the FIRST declared outcome and auto-deny to the LAST, so `then` routing
|
|
143
|
+
* and downstream outcome switches see declared outcome names — never the
|
|
144
|
+
* orchestrator's internal approve/deny words, which a reviewer of a
|
|
145
|
+
* custom-outcome gate was never offered. Binary gates (no custom outcomes)
|
|
146
|
+
* keep the plain approve/deny result.
|
|
147
|
+
*
|
|
148
|
+
* Escalate needs no remapping by construction (stigmer/stigmer#781): its
|
|
149
|
+
* policy word IS the declared outcome's name — the loader (and the server
|
|
150
|
+
* validator) only accept the escalate policy when an outcome named
|
|
151
|
+
* "escalate" with `then` exists, so the caller's ordinary name lookup
|
|
152
|
+
* routes the escalation branch.
|
|
153
|
+
*/
|
|
154
|
+
function applyTimeoutOutcomeContract(
|
|
155
|
+
result: HumanInputResult,
|
|
156
|
+
outcomes: HumanInputConfig["outcomes"],
|
|
157
|
+
): HumanInputResult {
|
|
158
|
+
if (!result.auto_resolved || result.reason !== "timeout" || !outcomes?.length) {
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
if (result.outcome === "approve") {
|
|
162
|
+
return { ...result, outcome: outcomes[0].name };
|
|
163
|
+
}
|
|
164
|
+
if (result.outcome === "deny") {
|
|
165
|
+
return { ...result, outcome: outcomes[outcomes.length - 1].name };
|
|
166
|
+
}
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
|
|
135
170
|
interface ResolvedReviewPayload {
|
|
136
171
|
/** Resolved payload for inline delivery on the approval_requested event. */
|
|
137
172
|
readonly payload?: unknown;
|
|
@@ -557,14 +557,23 @@ export interface RunWorkflowExecutionConfig {
|
|
|
557
557
|
|
|
558
558
|
/**
|
|
559
559
|
* Blocks workflow execution until a human provides input via signal.
|
|
560
|
-
* Supports configurable timeout with policies (fail, approve, deny).
|
|
560
|
+
* Supports configurable timeout with policies (fail, approve, deny, escalate).
|
|
561
561
|
*/
|
|
562
562
|
export type AwaitHumanInputFn = (config: HumanInputExecutionConfig) => Promise<HumanInputResult>;
|
|
563
563
|
|
|
564
|
+
/**
|
|
565
|
+
* Internal timeout-policy vocabulary — the loader-normalized form of the
|
|
566
|
+
* proto's HumanInputTimeoutPolicy enum. "escalate" carries the outcome-by-name
|
|
567
|
+
* contract (stigmer/stigmer#781): it is only loadable when the gate declares
|
|
568
|
+
* an outcome named "escalate" with `then` set, and a timeout resolves to that
|
|
569
|
+
* outcome so the existing `then`/flow-directive routing takes the branch.
|
|
570
|
+
*/
|
|
571
|
+
export type HumanInputTimeoutPolicy = "fail" | "approve" | "deny" | "escalate";
|
|
572
|
+
|
|
564
573
|
export interface HumanInputExecutionConfig {
|
|
565
574
|
readonly signalName: string;
|
|
566
575
|
readonly timeoutSeconds: number;
|
|
567
|
-
readonly onTimeout:
|
|
576
|
+
readonly onTimeout: HumanInputTimeoutPolicy;
|
|
568
577
|
}
|
|
569
578
|
|
|
570
579
|
export interface HumanInputResult {
|
|
@@ -602,7 +611,7 @@ export interface HumanInputConfig {
|
|
|
602
611
|
readonly formSchema?: Record<string, unknown>;
|
|
603
612
|
readonly approvers?: readonly string[];
|
|
604
613
|
readonly timeout?: number;
|
|
605
|
-
readonly onTimeout?:
|
|
614
|
+
readonly onTimeout?: HumanInputTimeoutPolicy;
|
|
606
615
|
/**
|
|
607
616
|
* Material for the reviewer to examine — a whole-value expression
|
|
608
617
|
* string, or an object/array with embedded expressions. Resolved at
|
|
@@ -749,6 +758,12 @@ export interface AgentCallRunConfig {
|
|
|
749
758
|
* ("standard"/"fast") to these, mirroring harness.
|
|
750
759
|
*/
|
|
751
760
|
readonly service_tier?: string;
|
|
761
|
+
/**
|
|
762
|
+
* Canonical ThinkingMode enum name ("THINKING_MODE_DISABLED" /
|
|
763
|
+
* "THINKING_MODE_ENABLED"); the loader maps the YAML shorthands
|
|
764
|
+
* ("disabled"/"enabled") to these, mirroring service_tier (#772).
|
|
765
|
+
*/
|
|
766
|
+
readonly thinking_mode?: string;
|
|
752
767
|
}
|
|
753
768
|
|
|
754
769
|
export interface AgentCallOutputContract {
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
* - "fail": throws an error
|
|
8
8
|
* - "approve": returns auto-approved output
|
|
9
9
|
* - "deny": returns auto-denied output
|
|
10
|
+
* - "escalate": returns the "escalate" outcome — by the outcome-by-name
|
|
11
|
+
* contract (stigmer/stigmer#781) the loader guarantees the gate declares
|
|
12
|
+
* an outcome with that exact name and a `then` branch, so the executor's
|
|
13
|
+
* ordinary outcome routing takes the escalation path.
|
|
10
14
|
*
|
|
11
15
|
* Signal payload shape:
|
|
12
16
|
* { outcome, form_data?, reviewer, reviewer_actor?, responded_at }
|
|
@@ -16,7 +20,11 @@
|
|
|
16
20
|
|
|
17
21
|
import { defineSignal, setHandler, condition } from "@temporalio/workflow";
|
|
18
22
|
|
|
19
|
-
import type {
|
|
23
|
+
import type {
|
|
24
|
+
HumanInputExecutionConfig,
|
|
25
|
+
HumanInputResult,
|
|
26
|
+
HumanInputTimeoutPolicy,
|
|
27
|
+
} from "../workflow-engine/types.js";
|
|
20
28
|
|
|
21
29
|
/**
|
|
22
30
|
* Orchestrates a human_input task — blocks until signal or timeout.
|
|
@@ -51,7 +59,7 @@ export async function orchestrateHumanInput(
|
|
|
51
59
|
|
|
52
60
|
function handleTimeout(
|
|
53
61
|
signalName: string,
|
|
54
|
-
policy:
|
|
62
|
+
policy: HumanInputTimeoutPolicy,
|
|
55
63
|
): HumanInputResult {
|
|
56
64
|
switch (policy) {
|
|
57
65
|
case "approve":
|
|
@@ -68,6 +76,16 @@ function handleTimeout(
|
|
|
68
76
|
reason: "timeout",
|
|
69
77
|
};
|
|
70
78
|
|
|
79
|
+
case "escalate":
|
|
80
|
+
// The outcome word IS the declared outcome's name (loader-enforced),
|
|
81
|
+
// so no positional remapping happens downstream — the executor's name
|
|
82
|
+
// lookup routes the escalation branch directly.
|
|
83
|
+
return {
|
|
84
|
+
outcome: "escalate",
|
|
85
|
+
auto_resolved: true,
|
|
86
|
+
reason: "timeout",
|
|
87
|
+
};
|
|
88
|
+
|
|
71
89
|
case "fail":
|
|
72
90
|
default:
|
|
73
91
|
throw new Error(
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Connect backfill for MCP servers without discovered capabilities.
|
|
3
|
-
*
|
|
4
|
-
* Thin wrapper around the shared connect-backfill module that preserves
|
|
5
|
-
* the cursor-specific McpResolutionResult interface (which includes
|
|
6
|
-
* cursorConfig). The core backfill logic lives in shared/connect-backfill.ts.
|
|
7
|
-
*
|
|
8
|
-
* Non-fatal: if connect fails for any server, the original servers are
|
|
9
|
-
* kept and execution continues with empty policies (fail-closed).
|
|
10
|
-
*/
|
|
11
|
-
import type { McpResolutionResult } from "./mcp-resolver.js";
|
|
12
|
-
import type { StigmerClient } from "../../client/stigmer-client.js";
|
|
13
|
-
import type { McpTransportPosture } from "../../shared/mcp-transport-guard.js";
|
|
14
|
-
import type { McpServerUsage } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
15
|
-
/**
|
|
16
|
-
* Run connect backfill and return an updated cursor-specific
|
|
17
|
-
* McpResolutionResult with rebuilt cursorConfig.
|
|
18
|
-
*/
|
|
19
|
-
export declare function backfillMcpServersIfNeeded(client: StigmerClient, currentResult: McpResolutionResult, usages: McpServerUsage[], envVars: Record<string, string>, org: string, transportPosture: McpTransportPosture, onHeartbeat?: () => void, secretKeys?: ReadonlySet<string>): Promise<McpResolutionResult>;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Connect backfill for MCP servers without discovered capabilities.
|
|
3
|
-
*
|
|
4
|
-
* Thin wrapper around the shared connect-backfill module that preserves
|
|
5
|
-
* the cursor-specific McpResolutionResult interface (which includes
|
|
6
|
-
* cursorConfig). The core backfill logic lives in shared/connect-backfill.ts.
|
|
7
|
-
*
|
|
8
|
-
* Non-fatal: if connect fails for any server, the original servers are
|
|
9
|
-
* kept and execution continues with empty policies (fail-closed).
|
|
10
|
-
*/
|
|
11
|
-
import { toCursorMcpConfig } from "./mcp-resolver.js";
|
|
12
|
-
import { backfillMcpServersIfNeeded as sharedBackfill } from "../../shared/connect-backfill.js";
|
|
13
|
-
/**
|
|
14
|
-
* Run connect backfill and return an updated cursor-specific
|
|
15
|
-
* McpResolutionResult with rebuilt cursorConfig.
|
|
16
|
-
*/
|
|
17
|
-
export async function backfillMcpServersIfNeeded(client, currentResult, usages, envVars, org, transportPosture, onHeartbeat, secretKeys) {
|
|
18
|
-
const updatedServers = await sharedBackfill(client, currentResult.resolvedServers, usages, envVars, org, transportPosture, onHeartbeat, secretKeys);
|
|
19
|
-
if (updatedServers === currentResult.resolvedServers) {
|
|
20
|
-
return currentResult;
|
|
21
|
-
}
|
|
22
|
-
return {
|
|
23
|
-
cursorConfig: toCursorMcpConfig(updatedServers),
|
|
24
|
-
resolvedServers: updatedServers,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=connect-backfill.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"connect-backfill.js","sourceRoot":"","sources":["../../../src/activities/execute-cursor/connect-backfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAItD,OAAO,EAAE,0BAA0B,IAAI,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAEhG;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,MAAqB,EACrB,aAAkC,EAClC,MAAwB,EACxB,OAA+B,EAC/B,GAAW,EACX,gBAAqC,EACrC,WAAwB,EACxB,UAAgC;IAEhC,MAAM,cAAc,GAAG,MAAM,cAAc,CACzC,MAAM,EACN,aAAa,CAAC,eAAe,EAC7B,MAAM,EACN,OAAO,EACP,GAAG,EACH,gBAAgB,EAChB,WAAW,EACX,UAAU,CACX,CAAC;IAEF,IAAI,cAAc,KAAK,aAAa,CAAC,eAAe,EAAE,CAAC;QACrD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,OAAO;QACL,YAAY,EAAE,iBAAiB,CAAC,cAAc,CAAC;QAC/C,eAAe,EAAE,cAAc;KAChC,CAAC;AACJ,CAAC"}
|