@stigmer/runner 3.40.0 → 3.41.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/README.md +3 -1
- package/dist/.build-fingerprint +1 -1
- package/dist/__test-utils__/execution-record-fixture.d.ts +2 -1
- package/dist/__test-utils__/execution-record-fixture.js.map +1 -1
- package/dist/activities/call-agent.js +1 -1
- package/dist/activities/discover-mcp-server.d.ts +7 -1
- package/dist/activities/discover-mcp-server.js +13 -29
- package/dist/activities/discover-mcp-server.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/fold.d.ts +4 -2
- package/dist/activities/execute-cursor/__test-utils__/fold.js +3 -4
- package/dist/activities/execute-cursor/__test-utils__/fold.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +1 -0
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
- package/dist/activities/execute-cursor/approval-policy.d.ts +1 -29
- package/dist/activities/execute-cursor/approval-policy.js +11 -35
- package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
- package/dist/activities/execute-cursor/boundary-rows.js +4 -4
- package/dist/activities/execute-cursor/boundary-rows.js.map +1 -1
- package/dist/activities/execute-cursor/translator.d.ts +12 -17
- package/dist/activities/execute-cursor/translator.js +13 -30
- package/dist/activities/execute-cursor/translator.js.map +1 -1
- package/dist/activities/execute-cursor/turn-stream.js +4 -2
- package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +11 -1
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +22 -3
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -1
- package/dist/activities/execute-deep-agent/inline-publisher.d.ts +33 -2
- package/dist/activities/execute-deep-agent/inline-publisher.js +33 -7
- package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
- package/dist/activities/execute-deep-agent/platform-route.d.ts +48 -13
- package/dist/activities/execute-deep-agent/platform-route.js +87 -19
- package/dist/activities/execute-deep-agent/platform-route.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +70 -35
- package/dist/activities/execute-deep-agent/prompt-builder.js +70 -55
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +20 -3
- package/dist/activities/execute-deep-agent/streaming-side-effects.js +26 -4
- package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
- package/dist/activities/execute-deep-agent/translator.d.ts +5 -4
- package/dist/activities/execute-deep-agent/translator.js +5 -4
- package/dist/activities/execute-deep-agent/translator.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn-settle.js +6 -6
- package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn-setup.d.ts +18 -13
- package/dist/activities/execute-deep-agent/turn-setup.js +42 -36
- package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn-stream.d.ts +10 -6
- package/dist/activities/execute-deep-agent/turn-stream.js +6 -16
- package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn.d.ts +4 -1
- package/dist/activities/execute-deep-agent/turn.js +15 -6
- package/dist/activities/execute-deep-agent/turn.js.map +1 -1
- package/dist/activities/workflow-event-activities.js +2 -0
- package/dist/activities/workflow-event-activities.js.map +1 -1
- package/dist/config.d.ts +9 -0
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/exit-backstop.d.ts +64 -0
- package/dist/exit-backstop.js +79 -0
- package/dist/exit-backstop.js.map +1 -0
- package/dist/harness/terminal-table.d.ts +12 -5
- package/dist/harness/terminal-table.js +13 -13
- package/dist/harness/terminal-table.js.map +1 -1
- package/dist/harness/transcript/builder.d.ts +21 -0
- package/dist/harness/transcript/builder.js +53 -31
- package/dist/harness/transcript/builder.js.map +1 -1
- package/dist/harness/transcript/events.d.ts +22 -26
- package/dist/harness/transcript/events.js +6 -5
- package/dist/harness/transcript/events.js.map +1 -1
- package/dist/harness/turn-context.d.ts +3 -1
- package/dist/harness/turn-context.js +5 -3
- package/dist/harness/turn-context.js.map +1 -1
- package/dist/main.js +10 -4
- package/dist/main.js.map +1 -1
- package/dist/middleware/cost-advisory.d.ts +6 -3
- package/dist/middleware/cost-advisory.js +6 -3
- package/dist/middleware/cost-advisory.js.map +1 -1
- package/dist/middleware/execution-budget.d.ts +22 -7
- package/dist/middleware/execution-budget.js +57 -35
- package/dist/middleware/execution-budget.js.map +1 -1
- package/dist/middleware/index.d.ts +10 -7
- package/dist/middleware/index.js +10 -7
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/types.d.ts +6 -1
- package/dist/runner-manager.js +3 -2
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.d.ts +25 -0
- package/dist/runner.js +41 -14
- package/dist/runner.js.map +1 -1
- package/dist/shared/approval-policy.d.ts +23 -13
- package/dist/shared/approval-policy.js +47 -14
- package/dist/shared/approval-policy.js.map +1 -1
- package/dist/shared/caller-identity.d.ts +4 -5
- package/dist/shared/caller-identity.js +4 -5
- package/dist/shared/caller-identity.js.map +1 -1
- package/dist/shared/channel-attachment.js +3 -2
- package/dist/shared/channel-attachment.js.map +1 -1
- package/dist/shared/connect-backfill.d.ts +2 -1
- package/dist/shared/connect-backfill.js +2 -2
- package/dist/shared/connect-backfill.js.map +1 -1
- package/dist/shared/mcp-resolver.d.ts +10 -1
- package/dist/shared/mcp-resolver.js +11 -2
- package/dist/shared/mcp-resolver.js.map +1 -1
- package/dist/shared/memory-attachment.js +3 -2
- package/dist/shared/memory-attachment.js.map +1 -1
- package/dist/shared/model-error.d.ts +25 -3
- package/dist/shared/model-error.js +78 -10
- package/dist/shared/model-error.js.map +1 -1
- package/dist/shared/platform-server-address.d.ts +71 -0
- package/dist/shared/platform-server-address.js +103 -0
- package/dist/shared/platform-server-address.js.map +1 -0
- package/dist/shared/prompt-sections.d.ts +6 -28
- package/dist/shared/prompt-sections.js +6 -35
- package/dist/shared/prompt-sections.js.map +1 -1
- package/dist/shared/skill-resolver.d.ts +2 -3
- package/dist/shared/skill-resolver.js +2 -3
- package/dist/shared/skill-resolver.js.map +1 -1
- package/dist/shared/synthesized-attachment.d.ts +0 -5
- package/dist/shared/synthesized-attachment.js +0 -12
- package/dist/shared/synthesized-attachment.js.map +1 -1
- package/dist/shared/tool-rounds.d.ts +51 -23
- package/dist/shared/tool-rounds.js +67 -24
- package/dist/shared/tool-rounds.js.map +1 -1
- package/dist/shared/workspace/platform-dir.d.ts +15 -0
- package/dist/shared/workspace/platform-dir.js +18 -1
- package/dist/shared/workspace/platform-dir.js.map +1 -1
- package/dist/shared/workspace/sources/git.js +13 -6
- package/dist/shared/workspace/sources/git.js.map +1 -1
- package/dist/shared/workspace/stigmer-link.d.ts +21 -14
- package/dist/shared/workspace/stigmer-link.js +91 -29
- package/dist/shared/workspace/stigmer-link.js.map +1 -1
- package/dist/tools/url-guard.d.ts +5 -1
- package/dist/tools/url-guard.js +9 -2
- package/dist/tools/url-guard.js.map +1 -1
- package/dist/worker.d.ts +11 -2
- package/dist/worker.js +1 -1
- package/dist/worker.js.map +1 -1
- package/dist/workflow-engine/tasks/human-input.d.ts +16 -0
- package/dist/workflow-engine/tasks/human-input.js +79 -37
- package/dist/workflow-engine/tasks/human-input.js.map +1 -1
- package/dist/workflow-engine/types.d.ts +14 -4
- package/dist/workflow-engine/types.js.map +1 -1
- package/dist/workflows/call-agent-orchestrator.d.ts +13 -0
- package/dist/workflows/call-agent-orchestrator.js.map +1 -1
- package/dist/workflows/engine-core.d.ts +25 -0
- package/dist/workflows/engine-core.js.map +1 -1
- package/dist/workflows/execute-from-execution.d.ts +3 -0
- package/dist/workflows/execute-from-execution.js.map +1 -1
- package/dist/workflows/human-input-orchestrator.d.ts +9 -12
- package/dist/workflows/human-input-orchestrator.js +12 -44
- package/dist/workflows/human-input-orchestrator.js.map +1 -1
- package/package.json +5 -5
- package/src/__test-utils__/config-fixture.ts +1 -0
- package/src/__test-utils__/execution-record-fixture.ts +2 -1
- package/src/__test-utils__/harness-contract/runtime-contract.ts +5 -3
- package/src/__test-utils__/test-gate.ts +8 -0
- package/src/__tests__/exit-backstop.test.ts +91 -0
- package/src/__tests__/golden-e2e.test.ts +80 -62
- package/src/__tests__/history-encryption-e2e.test.ts +51 -27
- package/src/__tests__/runner.test.ts +60 -2
- package/src/activities/__tests__/classify-tool-approvals.test.ts +1 -0
- package/src/activities/__tests__/discover-mcp-server.hang.test.ts +5 -1
- package/src/activities/__tests__/discover-mcp-server.test.ts +90 -49
- package/src/activities/__tests__/workflow-event-activities.test.ts +28 -7
- package/src/activities/call-agent.ts +1 -1
- package/src/activities/discover-mcp-server.ts +27 -37
- package/src/activities/execute-cursor/__test-utils__/fold.ts +6 -4
- package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +1 -0
- package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +4 -29
- package/src/activities/execute-cursor/__tests__/hermetic/bypassed-tool-call.test.ts +120 -0
- package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +5 -5
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-capture.status.json +0 -2
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/resolution-error.status.json +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.error-delta.status.json +0 -3
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.output-first.status.json +0 -2
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.status.json +0 -2
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/stall.status.json +0 -2
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +0 -3
- package/src/activities/execute-cursor/__tests__/hermetic/shell-output-delta.test.ts +9 -7
- package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +6 -1
- package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +8 -11
- package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +1 -3
- package/src/activities/execute-cursor/__tests__/translator.test.ts +68 -15
- package/src/activities/execute-cursor/approval-policy.ts +11 -36
- package/src/activities/execute-cursor/boundary-rows.ts +3 -3
- package/src/activities/execute-cursor/translator.ts +15 -32
- package/src/activities/execute-cursor/turn-stream.ts +4 -1
- package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +33 -2
- package/src/activities/execute-deep-agent/__tests__/adapter.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.build-from-plan.prompt.md +1 -27
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.everything.prompt.md +26 -30
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.plan-mode.prompt.md +1 -26
- package/src/activities/execute-deep-agent/__tests__/goldens/user-message.everything.md +36 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +4 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +1 -1
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +1 -1
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +1 -1
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +8 -73
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.status.json +1 -1
- package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +17 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +86 -26
- package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +9 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/thrown-turn-drains-publishes.test.ts +159 -0
- package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +84 -0
- package/src/activities/execute-deep-agent/__tests__/platform-route.test.ts +47 -10
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +127 -199
- package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +31 -26
- package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +34 -0
- package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +13 -5
- package/src/activities/execute-deep-agent/inline-publisher.ts +47 -7
- package/src/activities/execute-deep-agent/platform-route.ts +109 -20
- package/src/activities/execute-deep-agent/prompt-builder.ts +104 -92
- package/src/activities/execute-deep-agent/streaming-side-effects.ts +27 -4
- package/src/activities/execute-deep-agent/translator.ts +5 -4
- package/src/activities/execute-deep-agent/turn-settle.ts +6 -6
- package/src/activities/execute-deep-agent/turn-setup.ts +43 -38
- package/src/activities/execute-deep-agent/turn-stream.ts +15 -22
- package/src/activities/execute-deep-agent/turn.ts +16 -7
- package/src/activities/workflow-event-activities.ts +2 -0
- package/src/config.ts +11 -0
- package/src/exit-backstop.ts +97 -0
- package/src/harness/README.md +5 -5
- package/src/harness/terminal-table.ts +13 -13
- package/src/harness/transcript/__tests__/builder.test.ts +93 -21
- package/src/harness/transcript/builder.ts +53 -30
- package/src/harness/transcript/events.ts +22 -27
- package/src/harness/turn-context.ts +5 -3
- package/src/main.ts +9 -5
- package/src/middleware/__tests__/execution-budget.test.ts +181 -103
- package/src/middleware/cost-advisory.ts +6 -3
- package/src/middleware/execution-budget.ts +60 -34
- package/src/middleware/index.ts +10 -7
- package/src/middleware/types.ts +6 -1
- package/src/runner-manager.ts +3 -2
- package/src/runner.ts +57 -15
- package/src/shared/__tests__/approval-policy.test.ts +41 -0
- package/src/shared/__tests__/artifact-storage.test.ts +1 -0
- package/src/shared/__tests__/connect-backfill.test.ts +15 -11
- package/src/shared/__tests__/mcp-resolver.test.ts +72 -10
- package/src/shared/__tests__/model-error.test.ts +71 -3
- package/src/shared/__tests__/platform-server-address.test.ts +122 -0
- package/src/shared/__tests__/prompt-sections.test.ts +2 -54
- package/src/shared/__tests__/tool-rounds.test.ts +64 -14
- package/src/shared/approval-policy.ts +57 -14
- package/src/shared/caller-identity.ts +4 -5
- package/src/shared/channel-attachment.ts +2 -2
- package/src/shared/connect-backfill.ts +5 -1
- package/src/shared/mcp-resolver.ts +11 -1
- package/src/shared/memory-attachment.ts +2 -2
- package/src/shared/model-error.ts +87 -9
- package/src/shared/platform-server-address.ts +123 -0
- package/src/shared/prompt-sections.ts +6 -55
- package/src/shared/skill-resolver.ts +2 -3
- package/src/shared/synthesized-attachment.ts +0 -12
- package/src/shared/tool-rounds.ts +70 -24
- package/src/shared/workspace/__tests__/git-source.test.ts +11 -5
- package/src/shared/workspace/__tests__/stigmer-link.test.ts +107 -10
- package/src/shared/workspace/platform-dir.ts +19 -1
- package/src/shared/workspace/sources/git.ts +14 -8
- package/src/shared/workspace/stigmer-link.ts +99 -29
- package/src/tools/__tests__/url-guard.test.ts +19 -1
- package/src/tools/url-guard.ts +9 -1
- package/src/worker.ts +12 -2
- package/src/workflow-engine/__tests__/golden-execution.test.ts +2 -1
- package/src/workflow-engine/__tests__/loader.test.ts +1 -1
- package/src/workflow-engine/__tests__/tasks/human-input.test.ts +133 -57
- package/src/workflow-engine/tasks/human-input.ts +92 -42
- package/src/workflow-engine/types.ts +16 -4
- package/src/workflows/call-agent-orchestrator.ts +7 -0
- package/src/workflows/engine-core.ts +18 -0
- package/src/workflows/execute-from-execution.ts +2 -1
- package/src/workflows/human-input-orchestrator.ts +15 -56
- package/dist/shared/skill-relevance.d.ts +0 -65
- package/dist/shared/skill-relevance.js +0 -175
- package/dist/shared/skill-relevance.js.map +0 -1
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.skills-below-threshold.prompt.md +0 -146
- package/src/shared/__tests__/skill-relevance.test.ts +0 -292
- package/src/shared/skill-relevance.ts +0 -222
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
* converter has no Void special-case — a data-bearing encrypted result
|
|
16
16
|
* would fail its converter lookup.
|
|
17
17
|
*
|
|
18
|
-
* Follows the golden-e2e pattern:
|
|
19
|
-
* Temporal
|
|
18
|
+
* Follows the golden-e2e pattern: the test skips by name only when the
|
|
19
|
+
* Temporal dev server cannot boot; any later failure fails it.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
@@ -24,9 +24,11 @@ import { randomBytes } from "node:crypto";
|
|
|
24
24
|
import { join, dirname } from "node:path";
|
|
25
25
|
import { fileURLToPath } from "node:url";
|
|
26
26
|
import { loadWorkflowFromYaml } from "../workflow-engine/loader.js";
|
|
27
|
+
import { IN_TEST_GATE } from "../__test-utils__/test-gate.js";
|
|
27
28
|
import { evaluateExpressionBatch } from "../workflow-engine/expression.js";
|
|
28
29
|
import { EncryptionPayloadCodec } from "@stigmer/temporal-codecs";
|
|
29
|
-
import type { ExecuteServerlessWorkflowInput } from "../workflows/engine-core.js";
|
|
30
|
+
import type { EngineActivities, ExecuteServerlessWorkflowInput } from "../workflows/engine-core.js";
|
|
31
|
+
import type { HydrateActivities } from "../workflows/execute-from-execution.js";
|
|
30
32
|
|
|
31
33
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
32
34
|
const WORKFLOWS_PATH = join(__dirname, "../workflows/index.ts");
|
|
@@ -68,7 +70,8 @@ type Worker = import("@temporalio/worker").Worker;
|
|
|
68
70
|
let env: TestWorkflowEnvironment | null = null;
|
|
69
71
|
let worker: Worker | null = null;
|
|
70
72
|
let workerRunPromise: Promise<void> | null = null;
|
|
71
|
-
|
|
73
|
+
/** Why the Temporal dev server could not boot; `null` once it has. */
|
|
74
|
+
let bootError: string | null = "not attempted";
|
|
72
75
|
|
|
73
76
|
function createMockActivities() {
|
|
74
77
|
return {
|
|
@@ -90,6 +93,23 @@ function createMockActivities() {
|
|
|
90
93
|
EmitWorkflowEvents: async (): Promise<void> => {},
|
|
91
94
|
LoadRecoveryContext: async (): Promise<unknown[]> => [],
|
|
92
95
|
PromoteTaskOutput: async (): Promise<void> => {},
|
|
96
|
+
CallGrpc: unscheduled("CallGrpc"),
|
|
97
|
+
CallFunction: unscheduled("CallFunction"),
|
|
98
|
+
RunScript: unscheduled("RunScript"),
|
|
99
|
+
RunShell: unscheduled("RunShell"),
|
|
100
|
+
CallAgent: unscheduled("CallAgent"),
|
|
101
|
+
UpdateWorkflowTaskApprovalStatus: unscheduled("UpdateWorkflowTaskApprovalStatus"),
|
|
102
|
+
ClearWorkflowApprovalStatus: unscheduled("ClearWorkflowApprovalStatus"),
|
|
103
|
+
UpdateWorkflowFileReviewStatus: unscheduled("UpdateWorkflowFileReviewStatus"),
|
|
104
|
+
GetAwaitingFileReviewChangeSetIds: unscheduled("GetAwaitingFileReviewChangeSetIds"),
|
|
105
|
+
GetAgentExecutionProgress: unscheduled("GetAgentExecutionProgress"),
|
|
106
|
+
} satisfies Record<keyof (EngineActivities & HydrateActivities), unknown>;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** An activity the secret-bearing workflow never schedules; reaching it is a test bug. */
|
|
110
|
+
function unscheduled(name: string): () => Promise<never> {
|
|
111
|
+
return async () => {
|
|
112
|
+
throw new Error(`${name} is not scheduled by the secret-bearing workflow`);
|
|
93
113
|
};
|
|
94
114
|
}
|
|
95
115
|
|
|
@@ -110,31 +130,35 @@ function collectByteFields(value: unknown, out: Uint8Array[]): void {
|
|
|
110
130
|
|
|
111
131
|
describe("History encryption tripwire — Temporal TestWorkflowEnvironment", () => {
|
|
112
132
|
beforeAll(async () => {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const { Worker: W } = await import("@temporalio/worker");
|
|
133
|
+
const { TestWorkflowEnvironment: TWE } = await import("@temporalio/testing");
|
|
134
|
+
const { Worker: W } = await import("@temporalio/worker");
|
|
116
135
|
|
|
136
|
+
try {
|
|
117
137
|
env = await TWE.createLocal();
|
|
118
|
-
worker = await W.create({
|
|
119
|
-
connection: env.nativeConnection,
|
|
120
|
-
taskQueue: TASK_QUEUE,
|
|
121
|
-
workflowsPath: WORKFLOWS_PATH,
|
|
122
|
-
activities: createMockActivities(),
|
|
123
|
-
dataConverter: {
|
|
124
|
-
payloadCodecs: [
|
|
125
|
-
new EncryptionPayloadCodec({
|
|
126
|
-
primary: { keyId: "tripwire-key", key: randomBytes(32) },
|
|
127
|
-
}),
|
|
128
|
-
],
|
|
129
|
-
},
|
|
130
|
-
});
|
|
131
|
-
workerRunPromise = worker.run();
|
|
132
|
-
envReady = true;
|
|
133
138
|
} catch (err: unknown) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
// Inside a gate the test server is a provided dependency: not booting is a failure.
|
|
140
|
+
if (IN_TEST_GATE) throw err;
|
|
141
|
+
bootError = err instanceof Error ? err.message : String(err);
|
|
142
|
+
console.warn(`Temporal dev server cannot boot; the tripwire skips: ${bootError}`);
|
|
143
|
+
return;
|
|
137
144
|
}
|
|
145
|
+
bootError = null;
|
|
146
|
+
|
|
147
|
+
// Past the boot, a failure is the suite's to report, not to skip.
|
|
148
|
+
worker = await W.create({
|
|
149
|
+
connection: env.nativeConnection,
|
|
150
|
+
taskQueue: TASK_QUEUE,
|
|
151
|
+
workflowsPath: WORKFLOWS_PATH,
|
|
152
|
+
activities: createMockActivities(),
|
|
153
|
+
dataConverter: {
|
|
154
|
+
payloadCodecs: [
|
|
155
|
+
new EncryptionPayloadCodec({
|
|
156
|
+
primary: { keyId: "tripwire-key", key: randomBytes(32) },
|
|
157
|
+
}),
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
workerRunPromise = worker.run();
|
|
138
162
|
}, 60_000);
|
|
139
163
|
|
|
140
164
|
afterAll(async () => {
|
|
@@ -145,8 +169,8 @@ describe("History encryption tripwire — Temporal TestWorkflowEnvironment", ()
|
|
|
145
169
|
if (env) await env.teardown();
|
|
146
170
|
}, 30_000);
|
|
147
171
|
|
|
148
|
-
it("records no plaintext secret bytes anywhere in workflow history", async () => {
|
|
149
|
-
if (
|
|
172
|
+
it("records no plaintext secret bytes anywhere in workflow history", async (testCtx) => {
|
|
173
|
+
if (bootError !== null || !env) return testCtx.skip(`Temporal dev server cannot boot: ${bootError}`);
|
|
150
174
|
|
|
151
175
|
const workflowId = `tripwire-${Date.now()}`;
|
|
152
176
|
// The starting client has NO codec, mirroring the Java/Go
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { mapOptionsToConfig } from "../runner.js";
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { mapOptionsToConfig, releaseAfterDrain } from "../runner.js";
|
|
3
3
|
import type { StigmerRunnerOptions, StigmerRunner } from "../runner.js";
|
|
4
4
|
import type { TokenRef } from "../config.js";
|
|
5
5
|
|
|
@@ -224,3 +224,61 @@ describe("public API exports", () => {
|
|
|
224
224
|
expect(typeof mod.createStigmerRunner).toBe("function");
|
|
225
225
|
});
|
|
226
226
|
});
|
|
227
|
+
|
|
228
|
+
describe("releaseAfterDrain", () => {
|
|
229
|
+
function resources(opts: { harnessFails?: boolean; closeFails?: boolean } = {}) {
|
|
230
|
+
const order: string[] = [];
|
|
231
|
+
return {
|
|
232
|
+
order,
|
|
233
|
+
value: {
|
|
234
|
+
shutdownHarnesses: vi.fn(async () => {
|
|
235
|
+
order.push("harnesses");
|
|
236
|
+
if (opts.harnessFails) {
|
|
237
|
+
throw new Error("harness boom");
|
|
238
|
+
}
|
|
239
|
+
}),
|
|
240
|
+
connection: {
|
|
241
|
+
close: vi.fn(async () => {
|
|
242
|
+
order.push("connection");
|
|
243
|
+
if (opts.closeFails) {
|
|
244
|
+
throw new Error("close boom");
|
|
245
|
+
}
|
|
246
|
+
}),
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
it("releases the harnesses, then closes the Temporal connection", async () => {
|
|
253
|
+
const r = resources();
|
|
254
|
+
const logError = vi.fn<(line: string) => void>();
|
|
255
|
+
|
|
256
|
+
await releaseAfterDrain(r.value, logError);
|
|
257
|
+
|
|
258
|
+
expect(r.order).toEqual(["harnesses", "connection"]);
|
|
259
|
+
expect(logError).not.toHaveBeenCalled();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("still closes the connection when a harness teardown fails, and logs it", async () => {
|
|
263
|
+
const r = resources({ harnessFails: true });
|
|
264
|
+
const logError = vi.fn<(line: string) => void>();
|
|
265
|
+
|
|
266
|
+
await releaseAfterDrain(r.value, logError);
|
|
267
|
+
|
|
268
|
+
expect(r.order).toEqual(["harnesses", "connection"]);
|
|
269
|
+
expect(logError).toHaveBeenCalledTimes(1);
|
|
270
|
+
expect(logError.mock.calls[0]?.[0]).toContain("Harness shutdown failed after the worker drained");
|
|
271
|
+
expect(logError.mock.calls[0]?.[0]).toContain("harness boom");
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it("logs a failed close instead of throwing, so a clean stop stays clean", async () => {
|
|
275
|
+
const r = resources({ closeFails: true });
|
|
276
|
+
const logError = vi.fn<(line: string) => void>();
|
|
277
|
+
|
|
278
|
+
await expect(releaseAfterDrain(r.value, logError)).resolves.toBeUndefined();
|
|
279
|
+
|
|
280
|
+
expect(logError).toHaveBeenCalledTimes(1);
|
|
281
|
+
expect(logError.mock.calls[0]?.[0]).toContain("Temporal connection close failed after the worker drained");
|
|
282
|
+
expect(logError.mock.calls[0]?.[0]).toContain("close boom");
|
|
283
|
+
});
|
|
284
|
+
});
|
|
@@ -727,6 +727,7 @@ function makeConfig() {
|
|
|
727
727
|
temporalConnection: {},
|
|
728
728
|
stigmerBackendEndpoint: "http://localhost:7234",
|
|
729
729
|
mcpBridgeEndpoint: null,
|
|
730
|
+
mcpPublicEndpoint: null,
|
|
730
731
|
stigmerTokenRef: { current: "test-token" },
|
|
731
732
|
cursorApiKey: "",
|
|
732
733
|
workspaceRootDir: "/tmp/test",
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
16
16
|
import { createServer, type Server } from "node:http";
|
|
17
|
+
import { testConfig } from "../../__test-utils__/config-fixture.js";
|
|
18
|
+
|
|
19
|
+
/** The runner endpoints discovery fills STIGMER_SERVER_ADDRESS from. */
|
|
20
|
+
const PLATFORM_ENDPOINTS = testConfig();
|
|
17
21
|
|
|
18
22
|
vi.mock("../../idle-watchdog.js", () => ({
|
|
19
23
|
activityStarted: vi.fn(),
|
|
@@ -85,7 +89,7 @@ describe("discovery against a 4xx-then-silent-SSE endpoint (issue #239)", () =>
|
|
|
85
89
|
|
|
86
90
|
const promise = discoverMcpServer(
|
|
87
91
|
{ mcpServerId: "mcp-monday" },
|
|
88
|
-
{ stigmerClient: stigmerClient as never, transportPosture: "stdio-forbidden" },
|
|
92
|
+
{ stigmerClient: stigmerClient as never, transportPosture: "stdio-forbidden", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
89
93
|
);
|
|
90
94
|
// Attach the rejection expectation BEFORE advancing so the rejection is
|
|
91
95
|
// never momentarily unhandled.
|
|
@@ -4,6 +4,10 @@ import type {
|
|
|
4
4
|
DiscoveredToolResult,
|
|
5
5
|
DiscoverMcpServerOutput,
|
|
6
6
|
} from "../discover-mcp-server.js";
|
|
7
|
+
import { testConfig } from "../../__test-utils__/config-fixture.js";
|
|
8
|
+
|
|
9
|
+
/** The runner endpoints discovery fills STIGMER_SERVER_ADDRESS from. */
|
|
10
|
+
const PLATFORM_ENDPOINTS = testConfig();
|
|
7
11
|
|
|
8
12
|
vi.mock("../../idle-watchdog.js", () => ({
|
|
9
13
|
activityStarted: vi.fn(),
|
|
@@ -221,47 +225,83 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
221
225
|
});
|
|
222
226
|
|
|
223
227
|
// ─────────────────────────────────────────────────────────────────────────
|
|
224
|
-
//
|
|
228
|
+
// STIGMER_SERVER_ADDRESS — the platform fill (shared/platform-server-address.ts)
|
|
225
229
|
// ─────────────────────────────────────────────────────────────────────────
|
|
226
230
|
|
|
227
|
-
describe("
|
|
228
|
-
|
|
231
|
+
describe("the platform STIGMER_SERVER_ADDRESS fill", () => {
|
|
232
|
+
async function connectionConfigFor(
|
|
233
|
+
spec: any,
|
|
234
|
+
executionContext: any,
|
|
235
|
+
platformEndpoints = PLATFORM_ENDPOINTS,
|
|
236
|
+
): Promise<any> {
|
|
237
|
+
const { discoverMcpServer } = await import("../discover-mcp-server.js");
|
|
238
|
+
const { MultiServerMCPClient } = await import("@langchain/mcp-adapters");
|
|
239
|
+
const mockClient = makeMockStigmerClient({
|
|
240
|
+
mcpServer: makeMcpServer({ metadata: { slug: "stigmer" }, spec }),
|
|
241
|
+
executionContext,
|
|
242
|
+
});
|
|
243
|
+
mockInitializeConnections.mockResolvedValue({});
|
|
244
|
+
mockGetClient.mockResolvedValue(makeMockMcpClient({ tools: [] }));
|
|
245
|
+
await discoverMcpServer(
|
|
246
|
+
{ mcpServerId: "mcp-stigmer", executionContextId: "ctx-addr" },
|
|
247
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints },
|
|
248
|
+
);
|
|
249
|
+
return (vi.mocked(MultiServerMCPClient).mock.calls[0][0] as any).stigmer;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
it("fills a stdio server's required address from the backend endpoint instead of failing closed", async () => {
|
|
253
|
+
const spec = makeStdioSpec("stigmer", ["mcp-server"]);
|
|
254
|
+
spec.env = { STIGMER_SERVER_ADDRESS: { description: "gRPC host:port" } };
|
|
229
255
|
|
|
230
|
-
|
|
231
|
-
process.env = savedEnv;
|
|
232
|
-
});
|
|
256
|
+
const config = await connectionConfigFor(spec, { spec: { data: {} } });
|
|
233
257
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const env = { SOME_KEY: "value" };
|
|
237
|
-
const result = injectPlatformEnv(new Set(["SOME_KEY"]), env);
|
|
238
|
-
expect(result).toBe(env);
|
|
258
|
+
// testConfig's backend endpoint is http://127.0.0.1:1.
|
|
259
|
+
expect(config.env.STIGMER_SERVER_ADDRESS).toBe("127.0.0.1:1");
|
|
239
260
|
});
|
|
240
261
|
|
|
241
|
-
it("
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
262
|
+
it("keeps an address the execution context delivered", async () => {
|
|
263
|
+
const spec = makeStdioSpec("stigmer", ["mcp-server"]);
|
|
264
|
+
spec.env = { STIGMER_SERVER_ADDRESS: { description: "gRPC host:port" } };
|
|
265
|
+
|
|
266
|
+
const config = await connectionConfigFor(
|
|
267
|
+
spec,
|
|
268
|
+
{ spec: { data: { STIGMER_SERVER_ADDRESS: { value: "other.example:7234" } } } },
|
|
269
|
+
testConfig({ mcpPublicEndpoint: "https://api.example.com" }),
|
|
247
270
|
);
|
|
248
|
-
|
|
271
|
+
|
|
272
|
+
expect(config.env.STIGMER_SERVER_ADDRESS).toBe("other.example:7234");
|
|
249
273
|
});
|
|
250
274
|
|
|
251
|
-
it("
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const
|
|
257
|
-
|
|
275
|
+
it("templates an http server's header from the operator's public endpoint", async () => {
|
|
276
|
+
const spec = makeHttpSpec("https://mcp.example.com");
|
|
277
|
+
spec.serverType.value.headers = { "X-Stigmer-Server": "${STIGMER_SERVER_ADDRESS}" };
|
|
278
|
+
spec.env = { STIGMER_SERVER_ADDRESS: {} };
|
|
279
|
+
|
|
280
|
+
const config = await connectionConfigFor(
|
|
281
|
+
spec,
|
|
282
|
+
{ spec: { data: {} } },
|
|
283
|
+
testConfig({ mcpPublicEndpoint: "https://api.example.com" }),
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
expect(config.headers["X-Stigmer-Server"]).toBe("api.example.com:443");
|
|
258
287
|
});
|
|
259
288
|
|
|
260
|
-
it("
|
|
261
|
-
const {
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
289
|
+
it("never hands an http server the backend endpoint: without a public one its required address is a credential the connect flow owes", async () => {
|
|
290
|
+
const { discoverMcpServer, CredentialResolutionError } = await import("../discover-mcp-server.js");
|
|
291
|
+
const spec = makeHttpSpec("https://mcp.example.com");
|
|
292
|
+
spec.env = { STIGMER_SERVER_ADDRESS: {} };
|
|
293
|
+
const mockClient = makeMockStigmerClient({
|
|
294
|
+
mcpServer: makeMcpServer({ metadata: { slug: "stigmer" }, spec }),
|
|
295
|
+
executionContext: { spec: { data: {} } },
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
const promise = discoverMcpServer(
|
|
299
|
+
{ mcpServerId: "mcp-stigmer", executionContextId: "ctx-addr" },
|
|
300
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
await expect(promise).rejects.toThrow(CredentialResolutionError);
|
|
304
|
+
await expect(promise).rejects.toThrow(/STIGMER_SERVER_ADDRESS/);
|
|
265
305
|
});
|
|
266
306
|
});
|
|
267
307
|
|
|
@@ -291,7 +331,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
291
331
|
|
|
292
332
|
const result = await discoverMcpServer(
|
|
293
333
|
{ mcpServerId: "mcp-123" },
|
|
294
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed" },
|
|
334
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
295
335
|
);
|
|
296
336
|
|
|
297
337
|
expect(result.tools).toHaveLength(2);
|
|
@@ -320,7 +360,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
320
360
|
await expect(
|
|
321
361
|
discoverMcpServer(
|
|
322
362
|
{ mcpServerId: "mcp-123" },
|
|
323
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden" },
|
|
363
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
324
364
|
),
|
|
325
365
|
).rejects.toThrow(McpTransportError);
|
|
326
366
|
expect(mockInitializeConnections).not.toHaveBeenCalled();
|
|
@@ -348,7 +388,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
348
388
|
|
|
349
389
|
const result = await discoverMcpServer(
|
|
350
390
|
{ mcpServerId: "mcp-456" },
|
|
351
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed" },
|
|
391
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
352
392
|
);
|
|
353
393
|
|
|
354
394
|
expect(result.tools).toHaveLength(1);
|
|
@@ -369,7 +409,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
369
409
|
});
|
|
370
410
|
|
|
371
411
|
await expect(
|
|
372
|
-
discoverMcpServer({ mcpServerId: "mcp-bad" }, { stigmerClient: mockClient as any, transportPosture: "stdio-allowed" }),
|
|
412
|
+
discoverMcpServer({ mcpServerId: "mcp-bad" }, { stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS }),
|
|
373
413
|
).rejects.toThrow("not found or has no spec");
|
|
374
414
|
});
|
|
375
415
|
|
|
@@ -384,7 +424,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
384
424
|
});
|
|
385
425
|
|
|
386
426
|
await expect(
|
|
387
|
-
discoverMcpServer({ mcpServerId: "mcp-noconfig" }, { stigmerClient: mockClient as any, transportPosture: "stdio-allowed" }),
|
|
427
|
+
discoverMcpServer({ mcpServerId: "mcp-noconfig" }, { stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS }),
|
|
388
428
|
).rejects.toThrow("no valid server type configured");
|
|
389
429
|
});
|
|
390
430
|
|
|
@@ -412,7 +452,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
412
452
|
|
|
413
453
|
const result = await discoverMcpServer(
|
|
414
454
|
{ mcpServerId: "mcp-env", executionContextId: "ctx-abc" },
|
|
415
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed" },
|
|
455
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
416
456
|
);
|
|
417
457
|
|
|
418
458
|
expect(result.tools).toEqual([]);
|
|
@@ -448,7 +488,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
448
488
|
executionContextId: "ctx-abc",
|
|
449
489
|
executionContextToken: "scoped-ec-token",
|
|
450
490
|
},
|
|
451
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed" },
|
|
491
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
452
492
|
);
|
|
453
493
|
|
|
454
494
|
expect(mockClient.getExecutionContextByExecutionId).toHaveBeenCalledWith(
|
|
@@ -494,7 +534,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
494
534
|
|
|
495
535
|
const result = await discoverMcpServer(
|
|
496
536
|
{ mcpServerId: "mcp-isc", executionContextId: "ctx-isc" },
|
|
497
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden" },
|
|
537
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
498
538
|
);
|
|
499
539
|
|
|
500
540
|
expect(result.tools).toHaveLength(1);
|
|
@@ -522,7 +562,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
522
562
|
|
|
523
563
|
await discoverMcpServer(
|
|
524
564
|
{ mcpServerId: "mcp-no-env" },
|
|
525
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed" },
|
|
565
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
526
566
|
);
|
|
527
567
|
|
|
528
568
|
expect(mockClient.getExecutionContextByExecutionId).not.toHaveBeenCalled();
|
|
@@ -548,7 +588,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
548
588
|
|
|
549
589
|
const result = await discoverMcpServer(
|
|
550
590
|
{ mcpServerId: "mcp-no-res" },
|
|
551
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed" },
|
|
591
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
552
592
|
);
|
|
553
593
|
|
|
554
594
|
expect(result.tools).toHaveLength(1);
|
|
@@ -582,7 +622,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
582
622
|
|
|
583
623
|
const result = await discoverMcpServer(
|
|
584
624
|
{ mcpServerId: "mcp-existing" },
|
|
585
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed" },
|
|
625
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
586
626
|
);
|
|
587
627
|
|
|
588
628
|
expect(result.previousToolsFingerprint).not.toBe("");
|
|
@@ -617,7 +657,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
617
657
|
|
|
618
658
|
const result = await discoverMcpServer(
|
|
619
659
|
{ mcpServerId: "mcp-fp" },
|
|
620
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed" },
|
|
660
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
621
661
|
);
|
|
622
662
|
|
|
623
663
|
const expected = toolsFingerprint(result.tools);
|
|
@@ -640,7 +680,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
640
680
|
|
|
641
681
|
const result = await discoverMcpServer(
|
|
642
682
|
{ mcpServerId: "mcp-empty" },
|
|
643
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed" },
|
|
683
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
644
684
|
);
|
|
645
685
|
|
|
646
686
|
expect(result.newToolsFingerprint).toBe("");
|
|
@@ -665,7 +705,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
665
705
|
await expect(
|
|
666
706
|
discoverMcpServer(
|
|
667
707
|
{ mcpServerId: "mcp-monday", executionContextId: "ctx-1" },
|
|
668
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden" },
|
|
708
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
669
709
|
),
|
|
670
710
|
).rejects.toThrow(CredentialResolutionError);
|
|
671
711
|
expect(mockInitializeConnections).not.toHaveBeenCalled();
|
|
@@ -689,7 +729,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
689
729
|
|
|
690
730
|
const result = await discoverMcpServer(
|
|
691
731
|
{ mcpServerId: "mcp-lenient", executionContextId: "ctx-2" },
|
|
692
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden" },
|
|
732
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
693
733
|
);
|
|
694
734
|
expect(result.tools).toEqual([]);
|
|
695
735
|
});
|
|
@@ -714,7 +754,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
714
754
|
|
|
715
755
|
const result = await discoverMcpServer(
|
|
716
756
|
{ mcpServerId: "mcp-optional", executionContextId: "ctx-3" },
|
|
717
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden" },
|
|
757
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
718
758
|
);
|
|
719
759
|
expect(result.tools).toEqual([]);
|
|
720
760
|
});
|
|
@@ -731,7 +771,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
731
771
|
|
|
732
772
|
const promise = discoverMcpServer(
|
|
733
773
|
{ mcpServerId: "mcp-monday", executionContextId: "ctx-4" },
|
|
734
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden" },
|
|
774
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
735
775
|
);
|
|
736
776
|
await expect(promise).rejects.toThrow(CredentialResolutionError);
|
|
737
777
|
await expect(promise).rejects.toThrow(/delivered no credentials/);
|
|
@@ -755,7 +795,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
755
795
|
|
|
756
796
|
const promise = discoverMcpServer(
|
|
757
797
|
{ mcpServerId: "mcp-monday", executionContextId: "ctx-5" },
|
|
758
|
-
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden" },
|
|
798
|
+
{ stigmerClient: mockClient as any, transportPosture: "stdio-forbidden", platformEndpoints: PLATFORM_ENDPOINTS },
|
|
759
799
|
);
|
|
760
800
|
await expect(promise).rejects.toThrow(CredentialResolutionError);
|
|
761
801
|
await expect(promise).rejects.toThrow(/MONDAY_ACCESS_TOKEN.*delivered redacted|delivered redacted.*MONDAY_ACCESS_TOKEN/s);
|
|
@@ -775,7 +815,7 @@ describe("DiscoverMcpServer activity", () => {
|
|
|
775
815
|
mockInitializeConnections.mockRejectedValue(new Error("Connection refused"));
|
|
776
816
|
|
|
777
817
|
await expect(
|
|
778
|
-
discoverMcpServer({ mcpServerId: "mcp-fail" }, { stigmerClient: mockClient as any, transportPosture: "stdio-allowed" }),
|
|
818
|
+
discoverMcpServer({ mcpServerId: "mcp-fail" }, { stigmerClient: mockClient as any, transportPosture: "stdio-allowed", platformEndpoints: PLATFORM_ENDPOINTS }),
|
|
779
819
|
).rejects.toThrow("Connection refused");
|
|
780
820
|
|
|
781
821
|
expect(mockClose).toHaveBeenCalled();
|
|
@@ -903,6 +943,7 @@ function makeConfig() {
|
|
|
903
943
|
temporalConnection: {},
|
|
904
944
|
stigmerBackendEndpoint: "http://localhost:7234",
|
|
905
945
|
mcpBridgeEndpoint: null,
|
|
946
|
+
mcpPublicEndpoint: null,
|
|
906
947
|
stigmerTokenRef: { current: "test-token" },
|
|
907
948
|
cursorApiKey: "",
|
|
908
949
|
workspaceRootDir: "/tmp/test",
|
|
@@ -4,6 +4,7 @@ import { StigmerClient } from "../../client/stigmer-client.js";
|
|
|
4
4
|
import { WorkflowEventType } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/event_pb";
|
|
5
5
|
import { WorkflowTaskKind } from "@stigmer/protos/ai/stigmer/agentic/workflow/v1/enum_pb";
|
|
6
6
|
import { WorkflowTaskStatus } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/enum_pb";
|
|
7
|
+
import { ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
7
8
|
import type { WorkflowEventDescriptor } from "../../workflow-engine/types.js";
|
|
8
9
|
|
|
9
10
|
const mockGetEventLogHighWaterMark = vi.fn<(executionId: string) => Promise<bigint>>();
|
|
@@ -648,7 +649,7 @@ describe("toProtoEvent", () => {
|
|
|
648
649
|
expect(actor!.avatar).toBe("https://example.com/ada.png");
|
|
649
650
|
});
|
|
650
651
|
|
|
651
|
-
it("
|
|
652
|
+
it("maps the chosen outcome and a human decision's autoResolved=false", () => {
|
|
652
653
|
const evt = toProtoEvent({
|
|
653
654
|
type: "approval_resolved",
|
|
654
655
|
taskName: "gate",
|
|
@@ -657,16 +658,36 @@ describe("toProtoEvent", () => {
|
|
|
657
658
|
resolvedBy: "bob",
|
|
658
659
|
comment: "",
|
|
659
660
|
waitDurationMs: 1000,
|
|
661
|
+
autoResolved: false,
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
if (evt.payload.case !== "approvalResolved") throw new Error("unexpected");
|
|
665
|
+
const p = evt.payload.value;
|
|
666
|
+
expect(p.outcome).toBe("needs_revision");
|
|
667
|
+
expect(p.autoResolved).toBe(false);
|
|
668
|
+
// A human_input gate's outcome is a declared string, never mapped onto
|
|
669
|
+
// the agent ApprovalAction enum: action stays unset.
|
|
670
|
+
expect(p.action).toBe(ApprovalAction.UNSPECIFIED);
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
it("maps a timeout auto-resolution: the policy's outcome, autoResolved, no reviewer", () => {
|
|
674
|
+
const evt = toProtoEvent({
|
|
675
|
+
type: "approval_resolved",
|
|
676
|
+
taskName: "gate",
|
|
677
|
+
occurredAt: NOW,
|
|
678
|
+
outcome: "escalate",
|
|
679
|
+
resolvedBy: "",
|
|
680
|
+
comment: "",
|
|
681
|
+
waitDurationMs: 5000,
|
|
660
682
|
autoResolved: true,
|
|
661
683
|
});
|
|
662
684
|
|
|
663
685
|
if (evt.payload.case !== "approvalResolved") throw new Error("unexpected");
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
expect(
|
|
669
|
-
expect(evt.payload.value.waitDurationMs).toBe(BigInt(1000));
|
|
686
|
+
const p = evt.payload.value;
|
|
687
|
+
expect(p.outcome).toBe("escalate");
|
|
688
|
+
expect(p.autoResolved).toBe(true);
|
|
689
|
+
expect(p.resolvedBy).toBe("");
|
|
690
|
+
expect(p.resolvedByActor).toBeUndefined();
|
|
670
691
|
});
|
|
671
692
|
});
|
|
672
693
|
|
|
@@ -228,7 +228,7 @@ export async function callAgentAction(
|
|
|
228
228
|
// the author may set is forwarded to a field the runner enforces.
|
|
229
229
|
// model_name replaces the agent's default outright; max_cost_usd feeds
|
|
230
230
|
// the turn runtime's cost guard (shared/cost-guard.ts, both harnesses);
|
|
231
|
-
// max_tool_rounds feeds
|
|
231
|
+
// max_tool_rounds feeds resolveToolRoundLimit (native
|
|
232
232
|
// harness only); service_tier and thinking_mode feed the cursor
|
|
233
233
|
// harness's explicit variant selection (issues #357/#772). Zero/unset
|
|
234
234
|
// means "no override" and is omitted.
|