@stigmer/runner 3.12.5 → 3.12.7
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-status.d.ts +14 -2
- package/dist/activities/call-agent-status.js +24 -7
- package/dist/activities/call-agent-status.js.map +1 -1
- package/dist/activities/call-agent.js +19 -6
- package/dist/activities/call-agent.js.map +1 -1
- 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 -0
- package/dist/activities/execute-cursor/index.js +20 -7
- package/dist/activities/execute-cursor/index.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +12 -0
- 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/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/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 +2 -0
- package/dist/activities/execute-deep-agent/setup.js.map +1 -1
- package/dist/config.d.ts +10 -0
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/main.js +3 -0
- package/dist/main.js.map +1 -1
- package/dist/runner-manager.d.ts +2 -0
- package/dist/runner-manager.js +1 -0
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.d.ts +2 -0
- package/dist/runner.js +33 -6
- package/dist/runner.js.map +1 -1
- package/dist/shared/artifact-storage.js +7 -4
- 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/recalled-memories.d.ts +55 -0
- package/dist/shared/recalled-memories.js +70 -0
- package/dist/shared/recalled-memories.js.map +1 -0
- 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/workflow-engine/loader.js +52 -13
- 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 +8 -1
- 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/call-agent-orchestrator.d.ts +14 -2
- package/dist/workflows/call-agent-orchestrator.js +55 -18
- package/dist/workflows/call-agent-orchestrator.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 +2 -2
- package/src/__tests__/golden-e2e.test.ts +1 -1
- package/src/activities/__tests__/call-agent-status.test.ts +30 -5
- package/src/activities/__tests__/classify-tool-approvals.test.ts +1 -0
- package/src/activities/__tests__/discover-mcp-server.test.ts +1 -0
- package/src/activities/call-agent-status.ts +25 -8
- package/src/activities/call-agent.ts +20 -6
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +79 -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__/usage-accumulator.test.ts +33 -1
- package/src/activities/execute-cursor/error-classifier.ts +42 -1
- package/src/activities/execute-cursor/index.ts +30 -6
- package/src/activities/execute-cursor/prompt-builder.ts +28 -0
- package/src/activities/execute-cursor/service-tier.ts +94 -63
- package/src/activities/execute-cursor/usage-accumulator.ts +11 -1
- 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__/prompt-builder.test.ts +48 -0
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +1 -0
- package/src/activities/execute-deep-agent/prompt-builder.ts +22 -0
- package/src/activities/execute-deep-agent/setup.ts +4 -0
- package/src/config.ts +13 -0
- package/src/main.ts +3 -0
- package/src/runner-manager.ts +5 -0
- package/src/runner.ts +42 -6
- package/src/shared/__tests__/artifact-storage.test.ts +21 -0
- package/src/shared/__tests__/recalled-memories.test.ts +88 -0
- package/src/shared/artifact-storage.ts +9 -4
- package/src/shared/caller-identity.ts +10 -7
- package/src/shared/recalled-memories.ts +90 -0
- package/src/shared/thinking-mode.ts +52 -0
- package/src/workflow-engine/__tests__/loader.test.ts +47 -3
- package/src/workflow-engine/__tests__/tasks/human-input.test.ts +39 -0
- package/src/workflow-engine/loader.ts +63 -17
- package/src/workflow-engine/tasks/human-input.ts +8 -1
- package/src/workflow-engine/types.ts +18 -3
- package/src/workflows/call-agent-orchestrator.ts +60 -24
- package/src/workflows/human-input-orchestrator.ts +20 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-agent-orchestrator.js","sourceRoot":"","sources":["../../src/workflows/call-agent-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,YAAY,EACZ,UAAU,EACV,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,GAAG,EAEH,cAAc,GACf,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"call-agent-orchestrator.js","sourceRoot":"","sources":["../../src/workflows/call-agent-orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -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 }
|
|
@@ -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 }
|
|
@@ -52,6 +56,15 @@ function handleTimeout(signalName, policy) {
|
|
|
52
56
|
auto_resolved: true,
|
|
53
57
|
reason: "timeout",
|
|
54
58
|
};
|
|
59
|
+
case "escalate":
|
|
60
|
+
// The outcome word IS the declared outcome's name (loader-enforced),
|
|
61
|
+
// so no positional remapping happens downstream — the executor's name
|
|
62
|
+
// lookup routes the escalation branch directly.
|
|
63
|
+
return {
|
|
64
|
+
outcome: "escalate",
|
|
65
|
+
auto_resolved: true,
|
|
66
|
+
reason: "timeout",
|
|
67
|
+
};
|
|
55
68
|
case "fail":
|
|
56
69
|
default:
|
|
57
70
|
throw new Error(`human_input task timed out waiting for signal '${signalName}'`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"human-input-orchestrator.js","sourceRoot":"","sources":["../../src/workflows/human-input-orchestrator.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"human-input-orchestrator.js","sourceRoot":"","sources":["../../src/workflows/human-input-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAQ3E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAiC;IAEjC,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAEzD,IAAI,OAAqC,CAAC;IAC1C,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,MAAM,GAAG,YAAY,CAAqB,UAAU,CAAC,CAAC;IAC5D,UAAU,CAAC,MAAM,EAAE,CAAC,IAAsB,EAAE,EAAE;QAC5C,OAAO,GAAG,IAAI,CAAC;QACf,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,cAAc,GAAG,IAAI,CAAC;QACxC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAE7D,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,OAAQ,CAAC;AAClB,CAAC;AAED,SAAS,aAAa,CACpB,UAAkB,EAClB,MAA+B;IAE/B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO;gBACL,OAAO,EAAE,SAAS;gBAClB,aAAa,EAAE,IAAI;gBACnB,MAAM,EAAE,SAAS;aAClB,CAAC;QAEJ,KAAK,MAAM;YACT,OAAO;gBACL,OAAO,EAAE,MAAM;gBACf,aAAa,EAAE,IAAI;gBACnB,MAAM,EAAE,SAAS;aAClB,CAAC;QAEJ,KAAK,UAAU;YACb,qEAAqE;YACrE,sEAAsE;YACtE,gDAAgD;YAChD,OAAO;gBACL,OAAO,EAAE,UAAU;gBACnB,aAAa,EAAE,IAAI;gBACnB,MAAM,EAAE,SAAS;aAClB,CAAC;QAEJ,KAAK,MAAM,CAAC;QACZ;YACE,MAAM,IAAI,KAAK,CACb,kDAAkD,UAAU,GAAG,CAChE,CAAC;IACN,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stigmer/runner",
|
|
3
|
-
"version": "3.12.
|
|
3
|
+
"version": "3.12.7",
|
|
4
4
|
"description": "Embeddable Temporal worker for the Stigmer AI agent platform — handles agent execution, workflow orchestration, and MCP server management",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"@opentelemetry/sdk-metrics": "^2.0.0",
|
|
95
95
|
"@opentelemetry/sdk-trace-base": "^2.0.0",
|
|
96
96
|
"@opentelemetry/sdk-trace-node": "^2.0.0",
|
|
97
|
-
"@stigmer/protos": "3.12.
|
|
97
|
+
"@stigmer/protos": "3.12.7",
|
|
98
98
|
"@temporalio/activity": "1.16.2",
|
|
99
99
|
"@temporalio/common": "1.16.2",
|
|
100
100
|
"@temporalio/interceptors-opentelemetry": "1.16.2",
|
|
@@ -76,7 +76,7 @@ function createMockActivities() {
|
|
|
76
76
|
}),
|
|
77
77
|
RunScript: async (): Promise<unknown> => ({ computed: 4 }),
|
|
78
78
|
RunShell: async (): Promise<unknown> => "hello from shell",
|
|
79
|
-
UpdateWorkflowTaskApprovalStatus: async (): Promise<
|
|
79
|
+
UpdateWorkflowTaskApprovalStatus: async (): Promise<boolean> => false,
|
|
80
80
|
ClearWorkflowApprovalStatus: async (): Promise<void> => {},
|
|
81
81
|
UpdateWorkflowFileReviewStatus: async (): Promise<void> => {},
|
|
82
82
|
GetAwaitingFileReviewChangeSetIds: async (): Promise<string[]> => [],
|
|
@@ -104,17 +104,42 @@ describe("call-agent-status file-review activities", () => {
|
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
describe("approval activities are scoped per-child (unify)", () => {
|
|
107
|
-
it("updateWorkflowTaskApprovalStatus scopes the write to
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
it("updateWorkflowTaskApprovalStatus derives the gate from the child record and scopes the write to it", async () => {
|
|
108
|
+
// Identity-only contract (DD-012, stigmer-cloud#509): the activity
|
|
109
|
+
// receives just the child id and reads the gate from the child's
|
|
110
|
+
// persisted status — the signal never carries approval details.
|
|
111
|
+
mockGetExecutionResult = {
|
|
112
|
+
status: {
|
|
113
|
+
pendingApprovals: [{ toolCallId: "tc_1", toolName: "deploy" } as any],
|
|
114
|
+
},
|
|
115
|
+
};
|
|
112
116
|
|
|
117
|
+
const surfaced = await updateWorkflowTaskApprovalStatus("wfx_1", "task_a", "aex_child");
|
|
118
|
+
|
|
119
|
+
expect(surfaced).toBe(true);
|
|
113
120
|
expect(capturedUpdates).toHaveLength(1);
|
|
114
121
|
const { status, options } = capturedUpdates[0];
|
|
115
122
|
expect(options.updatePendingApprovals).toBe(true);
|
|
116
123
|
expect(options.pendingUpdateChildAgentExecutionId).toBe("aex_child");
|
|
117
124
|
expect(status.pendingApprovals[0].childAgentExecutionId).toBe("aex_child");
|
|
125
|
+
expect(status.pendingApprovals[0].approval.toolCallId).toBe("tc_1");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("updateWorkflowTaskApprovalStatus answers false and writes nothing when the child's gate already resolved", async () => {
|
|
129
|
+
// The child persists its gate before signaling, so an empty read means
|
|
130
|
+
// the gate resolved in the interim — surfacing it would show a stale
|
|
131
|
+
// approval card, and the orchestrator deliberately does not retry.
|
|
132
|
+
mockGetExecutionResult = { status: { pendingApprovals: [] } };
|
|
133
|
+
|
|
134
|
+
const surfaced = await updateWorkflowTaskApprovalStatus("wfx_1", "task_a", "aex_child");
|
|
135
|
+
|
|
136
|
+
expect(surfaced).toBe(false);
|
|
137
|
+
expect(capturedUpdates).toHaveLength(0);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("updateWorkflowTaskApprovalStatus is a no-op without a child id", async () => {
|
|
141
|
+
expect(await updateWorkflowTaskApprovalStatus("wfx_1", "task_a", "")).toBe(false);
|
|
142
|
+
expect(capturedUpdates).toHaveLength(0);
|
|
118
143
|
});
|
|
119
144
|
|
|
120
145
|
it("clearWorkflowApprovalStatus scopes the clear to the given child", async () => {
|
|
@@ -737,6 +737,7 @@ function makeConfig() {
|
|
|
737
737
|
runnerId: null,
|
|
738
738
|
checkpointerType: "memory" as const,
|
|
739
739
|
checkpointerProxyEndpoint: null,
|
|
740
|
+
artifactProxyEndpoint: null,
|
|
740
741
|
primaryModel: "gpt-4.1",
|
|
741
742
|
cursorStreamStallTimeoutMs: 180000,
|
|
742
743
|
agentResolveTimeoutMs: 120000,
|
|
@@ -913,6 +913,7 @@ function makeConfig() {
|
|
|
913
913
|
runnerId: null,
|
|
914
914
|
checkpointerType: "memory" as const,
|
|
915
915
|
checkpointerProxyEndpoint: null,
|
|
916
|
+
artifactProxyEndpoint: null,
|
|
916
917
|
primaryModel: "gpt-4.1",
|
|
917
918
|
cursorStreamStallTimeoutMs: 180000,
|
|
918
919
|
agentResolveTimeoutMs: 120000,
|
|
@@ -16,7 +16,6 @@ import { StigmerClient } from "../client/stigmer-client.js";
|
|
|
16
16
|
import { loadConfig } from "../config.js";
|
|
17
17
|
import { create } from "@bufbuild/protobuf";
|
|
18
18
|
import { WorkflowExecutionStatusSchema, WorkflowPendingApprovalSchema, WorkflowPendingFileReviewSchema } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/api_pb";
|
|
19
|
-
import type { ChildApprovalNotification } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
|
|
20
19
|
import { ToolCallStatus, FileChangeSetStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
21
20
|
|
|
22
21
|
function buildClient(): StigmerClient {
|
|
@@ -27,23 +26,40 @@ function buildClient(): StigmerClient {
|
|
|
27
26
|
});
|
|
28
27
|
}
|
|
29
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Derives the child's approval gate onto the parent (DD-012: identity-only
|
|
31
|
+
* signal, derive-from-child). The signal carries only the child execution id;
|
|
32
|
+
* this activity reads the child's persisted `status.pending_approvals` — the
|
|
33
|
+
* single source of truth the child's server wrote BEFORE signaling — and
|
|
34
|
+
* mirrors it onto the parent as reference entries.
|
|
35
|
+
*
|
|
36
|
+
* Returns true when a gate was surfaced, false when the child currently has
|
|
37
|
+
* no pending approvals. The child persists its gate before the signal is
|
|
38
|
+
* sent (both editions), so an empty read means the gate already resolved
|
|
39
|
+
* (e.g. approved on the agent surface in the interim) — the caller must NOT
|
|
40
|
+
* retry: surfacing a resolved gate would show users a stale approval card.
|
|
41
|
+
*/
|
|
30
42
|
export async function updateWorkflowTaskApprovalStatus(
|
|
31
43
|
executionId: string,
|
|
32
44
|
_taskName: string,
|
|
33
|
-
|
|
34
|
-
): Promise<
|
|
35
|
-
if (!executionId) return;
|
|
45
|
+
childExecutionId: string,
|
|
46
|
+
): Promise<boolean> {
|
|
47
|
+
if (!executionId || !childExecutionId) return false;
|
|
36
48
|
|
|
37
|
-
const childExecId = notification.executionId;
|
|
38
49
|
const client = buildClient();
|
|
39
|
-
const
|
|
50
|
+
const child = await client.getExecution(childExecutionId);
|
|
51
|
+
const pendingApprovals = (child?.status?.pendingApprovals ?? []).map(
|
|
40
52
|
(approval) =>
|
|
41
53
|
create(WorkflowPendingApprovalSchema, {
|
|
42
54
|
approval,
|
|
43
|
-
childAgentExecutionId:
|
|
55
|
+
childAgentExecutionId: childExecutionId,
|
|
44
56
|
}),
|
|
45
57
|
);
|
|
46
58
|
|
|
59
|
+
if (pendingApprovals.length === 0) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
47
63
|
const status = create(WorkflowExecutionStatusSchema, {
|
|
48
64
|
pendingApprovals,
|
|
49
65
|
});
|
|
@@ -52,8 +68,9 @@ export async function updateWorkflowTaskApprovalStatus(
|
|
|
52
68
|
// approvals and preserves every parallel sibling's entries.
|
|
53
69
|
await client.updateWorkflowExecutionStatus(executionId, status, {
|
|
54
70
|
updatePendingApprovals: true,
|
|
55
|
-
pendingUpdateChildAgentExecutionId:
|
|
71
|
+
pendingUpdateChildAgentExecutionId: childExecutionId,
|
|
56
72
|
});
|
|
73
|
+
return true;
|
|
57
74
|
}
|
|
58
75
|
|
|
59
76
|
export async function clearWorkflowApprovalStatus(
|
|
@@ -31,7 +31,7 @@ import { AgentExecutionSpecSchema, ExecutionConfigSchema } from "@stigmer/protos
|
|
|
31
31
|
import { SessionSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
|
|
32
32
|
import { SessionSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/spec_pb";
|
|
33
33
|
import { Harness, ExecutionTarget } from "@stigmer/protos/ai/stigmer/agentic/session/v1/enum_pb";
|
|
34
|
-
import { ServiceTier } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
34
|
+
import { ServiceTier, ThinkingMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
35
35
|
import {
|
|
36
36
|
WorkspaceEntrySchema,
|
|
37
37
|
WorkspaceSourceSchema,
|
|
@@ -217,16 +217,16 @@ export async function callAgentAction(
|
|
|
217
217
|
// model_name replaces the agent's default outright; max_cost_usd feeds
|
|
218
218
|
// the harness-generic cost guards (cost-cap middleware / cursor
|
|
219
219
|
// cost-guard); max_tool_rounds feeds resolveRecursionLimit (native
|
|
220
|
-
// harness only); service_tier
|
|
221
|
-
// variant selection (
|
|
222
|
-
// omitted.
|
|
220
|
+
// harness only); service_tier and thinking_mode feed the cursor
|
|
221
|
+
// harness's explicit variant selection (issues #357/#772). Zero/unset
|
|
222
|
+
// means "no override" and is omitted.
|
|
223
223
|
const runConfig = resolved.run_config;
|
|
224
224
|
const hasModel = !!runConfig?.model_name;
|
|
225
225
|
const hasCostCap = (runConfig?.max_cost_usd ?? 0) > 0;
|
|
226
226
|
const hasToolRounds = (runConfig?.max_tool_rounds ?? 0) > 0;
|
|
227
227
|
// Loader guarantees a canonical enum name; an unknown one here means the
|
|
228
228
|
// loader and this mapping drifted — fail the task, never silently drop a
|
|
229
|
-
//
|
|
229
|
+
// variant directive.
|
|
230
230
|
const SERVICE_TIER_BY_NAME: Record<string, ServiceTier> = {
|
|
231
231
|
SERVICE_TIER_STANDARD: ServiceTier.STANDARD,
|
|
232
232
|
SERVICE_TIER_FAST: ServiceTier.FAST,
|
|
@@ -240,6 +240,19 @@ export async function callAgentAction(
|
|
|
240
240
|
);
|
|
241
241
|
}
|
|
242
242
|
const hasServiceTier = serviceTier !== undefined;
|
|
243
|
+
const THINKING_MODE_BY_NAME: Record<string, ThinkingMode> = {
|
|
244
|
+
THINKING_MODE_DISABLED: ThinkingMode.DISABLED,
|
|
245
|
+
THINKING_MODE_ENABLED: ThinkingMode.ENABLED,
|
|
246
|
+
};
|
|
247
|
+
const thinkingMode = runConfig?.thinking_mode
|
|
248
|
+
? THINKING_MODE_BY_NAME[runConfig.thinking_mode]
|
|
249
|
+
: undefined;
|
|
250
|
+
if (runConfig?.thinking_mode && thinkingMode === undefined) {
|
|
251
|
+
throw new Error(
|
|
252
|
+
`call:agent run_config.thinking_mode '${runConfig.thinking_mode}' has no proto mapping`,
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
const hasThinkingMode = thinkingMode !== undefined;
|
|
243
256
|
const hasOutputSchema = !!resolved.output?.schema;
|
|
244
257
|
|
|
245
258
|
console.log(
|
|
@@ -264,12 +277,13 @@ export async function callAgentAction(
|
|
|
264
277
|
runtimeEnv: runtimeEnvProto,
|
|
265
278
|
});
|
|
266
279
|
|
|
267
|
-
if (hasModel || hasCostCap || hasToolRounds || hasServiceTier || hasOutputSchema) {
|
|
280
|
+
if (hasModel || hasCostCap || hasToolRounds || hasServiceTier || hasThinkingMode || hasOutputSchema) {
|
|
268
281
|
const execConfig = create(ExecutionConfigSchema, {});
|
|
269
282
|
if (hasModel) execConfig.modelName = runConfig!.model_name!;
|
|
270
283
|
if (hasCostCap) execConfig.maxCostUsd = runConfig!.max_cost_usd!;
|
|
271
284
|
if (hasToolRounds) execConfig.maxToolRounds = runConfig!.max_tool_rounds!;
|
|
272
285
|
if (hasServiceTier) execConfig.serviceTier = serviceTier!;
|
|
286
|
+
if (hasThinkingMode) execConfig.thinkingMode = thinkingMode!;
|
|
273
287
|
if (hasOutputSchema) {
|
|
274
288
|
execConfig.structuredOutputSchema = resolved.output!.schema as JsonObject;
|
|
275
289
|
}
|
|
@@ -251,6 +251,85 @@ describe("buildPrompt", () => {
|
|
|
251
251
|
expect(prompt).not.toContain("<declared_preferences>");
|
|
252
252
|
});
|
|
253
253
|
|
|
254
|
+
it("carries the recalled memories on the first execution, framed as user-confirmed background", () => {
|
|
255
|
+
const prompt = buildPrompt(
|
|
256
|
+
input({
|
|
257
|
+
resolution: resolution("local", "created_first_execution"),
|
|
258
|
+
recalledMemories: {
|
|
259
|
+
facts: ["Deploys to us-east-1.", "Prefers OpenTofu."],
|
|
260
|
+
},
|
|
261
|
+
}),
|
|
262
|
+
);
|
|
263
|
+
expect(prompt).toContain("<recalled_memories>");
|
|
264
|
+
expect(prompt).toContain("- Deploys to us-east-1.");
|
|
265
|
+
expect(prompt).toContain("- Prefers OpenTofu.");
|
|
266
|
+
// Memories are CONTEXT like the bridge; the approval protocol keeps
|
|
267
|
+
// its pinned last-before-task slot.
|
|
268
|
+
expect(prompt.indexOf("<recalled_memories>"))
|
|
269
|
+
.toBeLessThan(prompt.indexOf("<tool_approval_protocol>"));
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it("orders remembered facts after declared preferences, before the embedder's session context (DD-006 D4)", () => {
|
|
273
|
+
const prompt = buildPrompt(
|
|
274
|
+
input({
|
|
275
|
+
resolution: resolution("local", "created_first_execution"),
|
|
276
|
+
declaredPreferences: { orgContext: "We deploy to us-east-1." },
|
|
277
|
+
recalledMemories: { facts: ["Prefers OpenTofu."] },
|
|
278
|
+
sessionContext: "Role: platform admin",
|
|
279
|
+
}),
|
|
280
|
+
);
|
|
281
|
+
const preferences = prompt.indexOf("<declared_preferences>");
|
|
282
|
+
const memories = prompt.indexOf("<recalled_memories>");
|
|
283
|
+
const context = prompt.indexOf("<session_context>");
|
|
284
|
+
expect(preferences).toBeGreaterThan(-1);
|
|
285
|
+
expect(memories).toBeGreaterThan(preferences);
|
|
286
|
+
expect(context).toBeGreaterThan(memories);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("never re-sends the memories to a successfully resumed agent — frozen per session by design (DD-002 D3, inherited by DD-006 D4)", () => {
|
|
290
|
+
const prompt = buildPrompt(
|
|
291
|
+
input({
|
|
292
|
+
resolution: resolution("local", "resumed_successfully"),
|
|
293
|
+
recalledMemories: { facts: ["Prefers OpenTofu."] },
|
|
294
|
+
}),
|
|
295
|
+
);
|
|
296
|
+
expect(prompt).toBe(USER_MESSAGE);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it("omits the memories section when the execution carries none", () => {
|
|
300
|
+
const prompt = buildPrompt(
|
|
301
|
+
input({ resolution: resolution("local", "created_first_execution") }),
|
|
302
|
+
);
|
|
303
|
+
expect(prompt).not.toContain("<recalled_memories>");
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it("carries the recalled memories through the HITL-recovery shape — the standing-context drop hazard (the buildFromPlan lesson)", () => {
|
|
307
|
+
// A fresh agent replacing a lost one mid-HITL gets the full recovery
|
|
308
|
+
// shape. Standing context is hand-copied into that shape's options at
|
|
309
|
+
// the buildPrompt routing — a missed copy would silently lose the
|
|
310
|
+
// memories for the session's whole life (frozen per session).
|
|
311
|
+
const approvalDecisions = new Map<string, ApprovalAction>([
|
|
312
|
+
["tool-call-1", ApprovalAction.APPROVE],
|
|
313
|
+
]);
|
|
314
|
+
const prompt = buildPrompt(
|
|
315
|
+
input({
|
|
316
|
+
resolution: resolution("local", "created_after_resume_failure"),
|
|
317
|
+
approvalDecisions,
|
|
318
|
+
recalledMemories: { facts: ["Prefers OpenTofu."] },
|
|
319
|
+
pendingApprovals: [
|
|
320
|
+
create(PendingApprovalSchema, {
|
|
321
|
+
toolCallId: "tool-call-1",
|
|
322
|
+
toolName: "Write",
|
|
323
|
+
message: "Write file: gated.txt",
|
|
324
|
+
}),
|
|
325
|
+
],
|
|
326
|
+
}),
|
|
327
|
+
);
|
|
328
|
+
expect(prompt).toContain("<recalled_memories>");
|
|
329
|
+
expect(prompt).toContain("- Prefers OpenTofu.");
|
|
330
|
+
expect(prompt).toContain("APPROVED");
|
|
331
|
+
});
|
|
332
|
+
|
|
254
333
|
it("uses the reinvocation prompt for a HITL reinvocation (human-meaningful, no opaque ids)", () => {
|
|
255
334
|
const approvalDecisions = new Map<string, ApprovalAction>([
|
|
256
335
|
["tool-call-1", ApprovalAction.APPROVE],
|
|
@@ -104,3 +104,70 @@ describe("error-classifier billing category", () => {
|
|
|
104
104
|
expect(result.category).toBe("billing");
|
|
105
105
|
});
|
|
106
106
|
});
|
|
107
|
+
|
|
108
|
+
describe("D4 platform attribution of billing errors (proxy mode)", () => {
|
|
109
|
+
// The exact message the 2026-08-15 pool-drain incident put in front of a
|
|
110
|
+
// customer: Cursor's team-usage-limit prose relayed raw, telling them to
|
|
111
|
+
// "reach out to an admin" of a Cursor team they cannot see.
|
|
112
|
+
const CURSOR_USAGE_LIMIT_MESSAGE =
|
|
113
|
+
"Your team has reached its usage limit. Please reach out to an admin to " +
|
|
114
|
+
"enable on-demand usage, or return on 8/20/2026 when your limit resets.";
|
|
115
|
+
|
|
116
|
+
beforeEach(() => {
|
|
117
|
+
vi.spyOn(console, "log").mockImplementation(() => {});
|
|
118
|
+
});
|
|
119
|
+
afterEach(() => {
|
|
120
|
+
vi.restoreAllMocks();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("rewords managed-key billing errors with platform attribution", () => {
|
|
124
|
+
const result = synthesizeError({
|
|
125
|
+
...base(),
|
|
126
|
+
streamErrorMessage: CURSOR_USAGE_LIMIT_MESSAGE,
|
|
127
|
+
proxyMode: true,
|
|
128
|
+
});
|
|
129
|
+
expect(result.category).toBe("billing");
|
|
130
|
+
expect(result.retryable).toBe(false);
|
|
131
|
+
expect(result.message).toContain("Stigmer platform");
|
|
132
|
+
expect(result.message).toContain("credits were not charged");
|
|
133
|
+
expect(result.message).toContain("STIGMER_PLATFORM_MODEL_CAPACITY");
|
|
134
|
+
// Cursor's limit-reset date must survive, quoted, not erased.
|
|
135
|
+
expect(result.message).toContain("return on 8/20/2026");
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("leaves BYO-key (direct mode) billing errors untouched", () => {
|
|
139
|
+
// A self-hoster's drained personal account: the raw message IS the
|
|
140
|
+
// actionable one — never hide it behind platform attribution.
|
|
141
|
+
const result = synthesizeError({
|
|
142
|
+
...base(),
|
|
143
|
+
streamErrorMessage: CURSOR_USAGE_LIMIT_MESSAGE,
|
|
144
|
+
proxyMode: false,
|
|
145
|
+
});
|
|
146
|
+
expect(result.category).toBe("billing");
|
|
147
|
+
expect(result.message).toBe(CURSOR_USAGE_LIMIT_MESSAGE);
|
|
148
|
+
expect(result.message).not.toContain("STIGMER_PLATFORM_MODEL_CAPACITY");
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("does not double-wrap a message the proxy already rewrote", () => {
|
|
152
|
+
const proxyRewritten =
|
|
153
|
+
"The Stigmer platform's Cursor capacity is temporarily exhausted. " +
|
|
154
|
+
"[code: STIGMER_PLATFORM_MODEL_CAPACITY]";
|
|
155
|
+
const result = synthesizeError({
|
|
156
|
+
...base(),
|
|
157
|
+
streamErrorMessage: proxyRewritten,
|
|
158
|
+
proxyMode: true,
|
|
159
|
+
});
|
|
160
|
+
expect(result.category).toBe("billing");
|
|
161
|
+
expect(result.message).toBe(proxyRewritten);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("never rewords non-billing categories in proxy mode", () => {
|
|
165
|
+
const result = synthesizeError({
|
|
166
|
+
...base(),
|
|
167
|
+
streamErrorMessage: "rate limit exceeded, retry after 2s",
|
|
168
|
+
proxyMode: true,
|
|
169
|
+
});
|
|
170
|
+
expect(result.category).toBe("rate-limit");
|
|
171
|
+
expect(result.message).not.toContain("Stigmer platform");
|
|
172
|
+
});
|
|
173
|
+
});
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
import { ServiceTier } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
2
|
+
import { ServiceTier, ThinkingMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Verifies the
|
|
6
|
-
* the runner must always send an
|
|
7
|
-
* parameters are a deterministic
|
|
8
|
-
* the catalog's
|
|
5
|
+
* Verifies the variant-attribute → Cursor variant-parameter translation
|
|
6
|
+
* (#357 service tier, #772 thinking mode): the runner must always send an
|
|
7
|
+
* explicit selection whose user-selectable parameters are a deterministic
|
|
8
|
+
* function of the requested attributes — never the catalog's
|
|
9
|
+
* (account-influenced) default variant.
|
|
9
10
|
*
|
|
10
11
|
* Catalog fixtures mirror the real shapes observed 2026-08-06: composer
|
|
11
12
|
* has a `fast` bool (default fast=true), haiku has a `thinking` bool
|
|
@@ -23,6 +24,7 @@ import {
|
|
|
23
24
|
resetCatalogCacheForTests,
|
|
24
25
|
} from "../service-tier.js";
|
|
25
26
|
import { resolveEffectiveServiceTier } from "../../../shared/service-tier.js";
|
|
27
|
+
import { resolveEffectiveThinkingMode } from "../../../shared/thinking-mode.js";
|
|
26
28
|
|
|
27
29
|
const CATALOG = [
|
|
28
30
|
{
|
|
@@ -66,8 +68,12 @@ const CATALOG = [
|
|
|
66
68
|
},
|
|
67
69
|
];
|
|
68
70
|
|
|
69
|
-
function opts(
|
|
70
|
-
|
|
71
|
+
function opts(
|
|
72
|
+
modelId: string,
|
|
73
|
+
tier: ServiceTier.STANDARD | ServiceTier.FAST,
|
|
74
|
+
thinking: ThinkingMode.DISABLED | ThinkingMode.ENABLED = ThinkingMode.DISABLED,
|
|
75
|
+
) {
|
|
76
|
+
return { apiKey: "key-1", modelId, tier, thinking, executionId: "aex_test" };
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
beforeEach(() => {
|
|
@@ -88,6 +94,18 @@ describe("resolveEffectiveServiceTier", () => {
|
|
|
88
94
|
});
|
|
89
95
|
});
|
|
90
96
|
|
|
97
|
+
describe("resolveEffectiveThinkingMode", () => {
|
|
98
|
+
it("resolves UNSPECIFIED to DISABLED — never the account default", () => {
|
|
99
|
+
expect(resolveEffectiveThinkingMode(ThinkingMode.UNSPECIFIED)).toBe(ThinkingMode.DISABLED);
|
|
100
|
+
expect(resolveEffectiveThinkingMode(undefined)).toBe(ThinkingMode.DISABLED);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("preserves explicit DISABLED and ENABLED", () => {
|
|
104
|
+
expect(resolveEffectiveThinkingMode(ThinkingMode.DISABLED)).toBe(ThinkingMode.DISABLED);
|
|
105
|
+
expect(resolveEffectiveThinkingMode(ThinkingMode.ENABLED)).toBe(ThinkingMode.ENABLED);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
91
109
|
describe("resolveServiceTierParams", () => {
|
|
92
110
|
it("STANDARD pins fast=false on a fast-capable model", async () => {
|
|
93
111
|
const params = await resolveServiceTierParams(opts("composer-2.5", ServiceTier.STANDARD));
|
|
@@ -123,6 +141,48 @@ describe("resolveServiceTierParams", () => {
|
|
|
123
141
|
]);
|
|
124
142
|
});
|
|
125
143
|
|
|
144
|
+
it("ENABLED pins thinking=true on a thinking-capable model (#772)", async () => {
|
|
145
|
+
const params = await resolveServiceTierParams(
|
|
146
|
+
opts("claude-haiku-4-5", ServiceTier.STANDARD, ThinkingMode.ENABLED),
|
|
147
|
+
);
|
|
148
|
+
expect(params).toEqual([{ id: "thinking", value: "true" }]);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("ENABLED on a model with no thinking parameter fails loudly, never a silent base variant", async () => {
|
|
152
|
+
await expect(
|
|
153
|
+
resolveServiceTierParams(opts("composer-2.5", ServiceTier.STANDARD, ThinkingMode.ENABLED)),
|
|
154
|
+
).rejects.toThrow(/no "thinking" parameter/);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("thinking combines freely with the fast tier — both pinned true, sorted", async () => {
|
|
158
|
+
const params = await resolveServiceTierParams(
|
|
159
|
+
opts("claude-opus-4-8", ServiceTier.FAST, ThinkingMode.ENABLED),
|
|
160
|
+
);
|
|
161
|
+
expect(params).toEqual([
|
|
162
|
+
{ id: "fast", value: "true" },
|
|
163
|
+
{ id: "thinking", value: "true" },
|
|
164
|
+
]);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("Auto + ENABLED is a loud failure (no variant dimensions to pin)", async () => {
|
|
168
|
+
await expect(
|
|
169
|
+
resolveServiceTierParams(opts("default", ServiceTier.STANDARD, ThinkingMode.ENABLED)),
|
|
170
|
+
).rejects.toThrow(/requires a pinned model/);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("unknown model + ENABLED fails loudly, never degrades", async () => {
|
|
174
|
+
await expect(
|
|
175
|
+
resolveServiceTierParams(opts("not-a-model", ServiceTier.STANDARD, ThinkingMode.ENABLED)),
|
|
176
|
+
).rejects.toThrow(/does not list that model/);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("catalog fetch failure + ENABLED fails loudly, never degrades", async () => {
|
|
180
|
+
listMock.mockRejectedValue(new Error("proxy down"));
|
|
181
|
+
await expect(
|
|
182
|
+
resolveServiceTierParams(opts("claude-haiku-4-5", ServiceTier.STANDARD, ThinkingMode.ENABLED)),
|
|
183
|
+
).rejects.toThrow(/catalog fetch failed/);
|
|
184
|
+
});
|
|
185
|
+
|
|
126
186
|
it("resolves models referenced by alias", async () => {
|
|
127
187
|
const params = await resolveServiceTierParams(opts("composer", ServiceTier.STANDARD));
|
|
128
188
|
expect(params).toEqual([{ id: "fast", value: "false" }]);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeAll } from "vitest";
|
|
2
|
-
import { ServiceTier } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
2
|
+
import { ServiceTier, ThinkingMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
3
3
|
|
|
4
4
|
import { UsageAccumulator } from "../usage-accumulator.js";
|
|
5
5
|
|
|
@@ -129,4 +129,36 @@ describe("UsageAccumulator", () => {
|
|
|
129
129
|
expect(unspecified.snapshot().estimatedCostUsd)
|
|
130
130
|
.toBe(standard.snapshot().estimatedCostUsd);
|
|
131
131
|
});
|
|
132
|
+
|
|
133
|
+
it("records the requested thinking mode into the snapshot (#772 audit trail)", () => {
|
|
134
|
+
const acc = new UsageAccumulator(
|
|
135
|
+
"claude-haiku-4-5",
|
|
136
|
+
ServiceTier.STANDARD,
|
|
137
|
+
[{ id: "thinking", value: "true" }],
|
|
138
|
+
ThinkingMode.ENABLED,
|
|
139
|
+
);
|
|
140
|
+
acc.addTurn({ inputTokens: 10, outputTokens: 5 });
|
|
141
|
+
const snap = acc.snapshot();
|
|
142
|
+
expect(snap.requestedThinkingMode).toBe(ThinkingMode.ENABLED);
|
|
143
|
+
expect(snap.requestedModelParams).toBe('[{"id":"thinking","value":"true"}]');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("thinking never changes the estimate — per-token price-neutral (#772)", () => {
|
|
147
|
+
// Ledger-verified 2026-08-15: thinking wire ids bill exactly base
|
|
148
|
+
// per-token rates; the extra cost of thinking is more output tokens,
|
|
149
|
+
// which the accumulator already counts as they arrive.
|
|
150
|
+
const turn = { inputTokens: 1_000_000, outputTokens: 1_000_000 };
|
|
151
|
+
|
|
152
|
+
const disabled = new UsageAccumulator(
|
|
153
|
+
"composer-2.5", ServiceTier.STANDARD, [], ThinkingMode.DISABLED,
|
|
154
|
+
);
|
|
155
|
+
disabled.addTurn(turn);
|
|
156
|
+
const enabled = new UsageAccumulator(
|
|
157
|
+
"composer-2.5", ServiceTier.STANDARD, [], ThinkingMode.ENABLED,
|
|
158
|
+
);
|
|
159
|
+
enabled.addTurn(turn);
|
|
160
|
+
|
|
161
|
+
expect(enabled.snapshot().estimatedCostUsd)
|
|
162
|
+
.toBe(disabled.snapshot().estimatedCostUsd);
|
|
163
|
+
});
|
|
132
164
|
});
|