@stigmer/runner 3.12.3 → 3.12.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/.build-fingerprint +1 -1
  2. package/dist/activities/call-http.js +12 -0
  3. package/dist/activities/call-http.js.map +1 -1
  4. package/dist/activities/call-llm.d.ts +18 -0
  5. package/dist/activities/call-llm.js +56 -2
  6. package/dist/activities/call-llm.js.map +1 -1
  7. package/dist/activities/execute-cursor/agent-session-cache.d.ts +72 -0
  8. package/dist/activities/execute-cursor/agent-session-cache.js +186 -0
  9. package/dist/activities/execute-cursor/agent-session-cache.js.map +1 -0
  10. package/dist/activities/execute-cursor/index.js +61 -28
  11. package/dist/activities/execute-cursor/index.js.map +1 -1
  12. package/dist/activities/execute-cursor/service-tier.d.ts +5 -15
  13. package/dist/activities/execute-cursor/service-tier.js +5 -21
  14. package/dist/activities/execute-cursor/service-tier.js.map +1 -1
  15. package/dist/activities/execute-cursor/skill-resolver.js +1 -1
  16. package/dist/activities/execute-cursor/skill-resolver.js.map +1 -1
  17. package/dist/activities/execute-deep-agent/setup.js +14 -0
  18. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  19. package/dist/activities/execute-deep-agent/shell-env.d.ts +8 -5
  20. package/dist/activities/execute-deep-agent/shell-env.js +10 -7
  21. package/dist/activities/execute-deep-agent/shell-env.js.map +1 -1
  22. package/dist/config.js +10 -5
  23. package/dist/config.js.map +1 -1
  24. package/dist/encryption/config.js +7 -2
  25. package/dist/encryption/config.js.map +1 -1
  26. package/dist/main.js +12 -6
  27. package/dist/main.js.map +1 -1
  28. package/dist/payload-codecs.js +2 -1
  29. package/dist/payload-codecs.js.map +1 -1
  30. package/dist/runner-manager.js +20 -7
  31. package/dist/runner-manager.js.map +1 -1
  32. package/dist/runner.js +19 -6
  33. package/dist/runner.js.map +1 -1
  34. package/dist/shared/fingerprint-secret.d.ts +3 -2
  35. package/dist/shared/fingerprint-secret.js +5 -3
  36. package/dist/shared/fingerprint-secret.js.map +1 -1
  37. package/dist/shared/llm-backend.js +8 -1
  38. package/dist/shared/llm-backend.js.map +1 -1
  39. package/dist/shared/model-client.d.ts +15 -0
  40. package/dist/shared/model-client.js +57 -13
  41. package/dist/shared/model-client.js.map +1 -1
  42. package/dist/shared/registry-endpoint.d.ts +5 -0
  43. package/dist/shared/registry-endpoint.js +7 -1
  44. package/dist/shared/registry-endpoint.js.map +1 -1
  45. package/dist/shared/runner-credential-keys.d.ts +26 -1
  46. package/dist/shared/runner-credential-keys.js +34 -1
  47. package/dist/shared/runner-credential-keys.js.map +1 -1
  48. package/dist/shared/runner-credential-store.d.ts +77 -0
  49. package/dist/shared/runner-credential-store.js +111 -0
  50. package/dist/shared/runner-credential-store.js.map +1 -0
  51. package/dist/shared/service-tier.d.ts +55 -0
  52. package/dist/shared/service-tier.js +67 -0
  53. package/dist/shared/service-tier.js.map +1 -0
  54. package/dist/shared/skill-writer.js +2 -2
  55. package/dist/shared/skill-writer.js.map +1 -1
  56. package/dist/shared/zip-extract.d.ts +10 -3
  57. package/dist/shared/zip-extract.js +10 -3
  58. package/dist/shared/zip-extract.js.map +1 -1
  59. package/dist/workflow-engine/tasks/call-function.d.ts +14 -0
  60. package/dist/workflow-engine/tasks/call-function.js +49 -5
  61. package/dist/workflow-engine/tasks/call-function.js.map +1 -1
  62. package/dist/workflow-engine/types.d.ts +6 -0
  63. package/dist/workflow-engine/types.js.map +1 -1
  64. package/dist/workflows/engine-core.js +36 -8
  65. package/dist/workflows/engine-core.js.map +1 -1
  66. package/package.json +2 -2
  67. package/src/activities/__tests__/call-http.test.ts +36 -0
  68. package/src/activities/__tests__/call-llm.test.ts +77 -0
  69. package/src/activities/call-http.ts +17 -0
  70. package/src/activities/call-llm.ts +78 -2
  71. package/src/activities/execute-cursor/__tests__/agent-session-cache.test.ts +220 -0
  72. package/src/activities/execute-cursor/__tests__/service-tier.test.ts +1 -1
  73. package/src/activities/execute-cursor/agent-session-cache.ts +229 -0
  74. package/src/activities/execute-cursor/index.ts +66 -20
  75. package/src/activities/execute-cursor/service-tier.ts +5 -29
  76. package/src/activities/execute-cursor/skill-resolver.ts +1 -1
  77. package/src/activities/execute-deep-agent/setup.ts +15 -0
  78. package/src/activities/execute-deep-agent/shell-env.ts +10 -7
  79. package/src/config.ts +10 -5
  80. package/src/encryption/config.ts +8 -2
  81. package/src/main.ts +16 -6
  82. package/src/payload-codecs.ts +2 -1
  83. package/src/runner-manager.ts +29 -6
  84. package/src/runner.ts +25 -6
  85. package/src/shared/__tests__/model-client.test.ts +99 -0
  86. package/src/shared/__tests__/runner-credential-store.test.ts +155 -0
  87. package/src/shared/__tests__/zip-extract.test.ts +46 -11
  88. package/src/shared/fingerprint-secret.ts +5 -3
  89. package/src/shared/llm-backend.ts +7 -1
  90. package/src/shared/model-client.ts +76 -13
  91. package/src/shared/registry-endpoint.ts +9 -1
  92. package/src/shared/runner-credential-keys.ts +36 -1
  93. package/src/shared/runner-credential-store.ts +115 -0
  94. package/src/shared/service-tier.ts +78 -0
  95. package/src/shared/skill-writer.ts +2 -2
  96. package/src/shared/zip-extract.ts +14 -7
  97. package/src/workflow-engine/__tests__/golden-execution.test.ts +20 -1
  98. package/src/workflow-engine/__tests__/tasks/call-function.test.ts +105 -0
  99. package/src/workflow-engine/tasks/call-function.ts +74 -13
  100. package/src/workflow-engine/types.ts +6 -0
  101. package/src/workflows/engine-core.ts +39 -8
@@ -162,26 +162,87 @@ export class CallFunctionTaskBuilder implements TaskBuilder {
162
162
  const executionId =
163
163
  (state.env.__stigmer_execution_id as string | undefined) || undefined;
164
164
 
165
- const result = await ctx.callFunction(
166
- callType,
167
- resolved,
168
- state.env,
169
- {
170
- workflowExecutionId: executionId,
171
- },
172
- );
165
+ const fnMeta = { workflowExecutionId: executionId };
173
166
 
174
167
  if (callType === "llm") {
175
- return normalizeLlmOutput(
176
- result as LlmActivityResult,
177
- !!resolved.response_schema,
178
- );
168
+ return this.executeLlmCall(resolved, state.env, fnMeta, ctx);
179
169
  }
180
170
 
181
- return result;
171
+ return ctx.callFunction(callType, resolved, state.env, fnMeta);
182
172
  };
183
173
  }
184
174
 
175
+ /**
176
+ * Executes a `call: llm` with schema-validation policy orchestration —
177
+ * the llm twin of call-agent's output-contract loop (#686).
178
+ *
179
+ * With ON_INVALID_RETRY / ON_INVALID_FALLBACK the activity reports a
180
+ * validation miss as a `parse_error` result instead of throwing; each
181
+ * retry is its own activity invocation (visible in Temporal history)
182
+ * re-prompting with the validation errors so the model can self-correct.
183
+ * Exhausted retries (or immediate FALLBACK) branch to `fallback_task`
184
+ * via the engine's flow directive; without one, the task fails — the
185
+ * proto contract. ON_INVALID_FAIL (default) keeps the activity's
186
+ * throwing path: one attempt, LLM_SCHEMA_VALIDATION on miss.
187
+ */
188
+ private async executeLlmCall(
189
+ resolved: Record<string, unknown>,
190
+ env: Record<string, unknown>,
191
+ fnMeta: { workflowExecutionId?: string },
192
+ ctx: Parameters<TaskExecutorFn>[2],
193
+ ): Promise<unknown> {
194
+ const hasSchema = !!resolved.response_schema;
195
+ const onInvalid = (resolved.on_invalid as string | undefined) ?? "ON_INVALID_FAIL";
196
+ const softHandling =
197
+ hasSchema && (onInvalid === "ON_INVALID_RETRY" || onInvalid === "ON_INVALID_FALLBACK");
198
+
199
+ // Proto: max_retries "Default: 1", meaningful only for ON_INVALID_RETRY.
200
+ const maxRetries =
201
+ onInvalid === "ON_INVALID_RETRY" ? (resolved.max_retries as number | undefined) ?? 1 : 0;
202
+
203
+ let attempts = 0;
204
+ let lastParseError = "";
205
+
206
+ do {
207
+ const attemptConfig =
208
+ attempts === 0
209
+ ? resolved
210
+ : {
211
+ ...resolved,
212
+ prompt:
213
+ `${resolved.prompt}\n\n[RETRY — Your previous response did not match ` +
214
+ `the required output schema. Validation errors: ${lastParseError}. ` +
215
+ `Please ensure your response strictly matches the JSON schema provided.]`,
216
+ };
217
+
218
+ const result = (await ctx.callFunction(
219
+ "llm",
220
+ attemptConfig,
221
+ env,
222
+ fnMeta,
223
+ )) as LlmActivityResult;
224
+
225
+ if (!softHandling || !result.parse_error) {
226
+ return normalizeLlmOutput(result, hasSchema);
227
+ }
228
+
229
+ lastParseError = result.parse_error;
230
+ attempts++;
231
+ } while (onInvalid === "ON_INVALID_RETRY" && attempts <= maxRetries);
232
+
233
+ if (typeof resolved.fallback_task === "string" && resolved.fallback_task !== "") {
234
+ return {
235
+ __flow_directive__: resolved.fallback_task,
236
+ validation_errors: [lastParseError],
237
+ };
238
+ }
239
+
240
+ throw new Error(
241
+ `LLM output validation failed after ${attempts} attempt(s) ` +
242
+ `for task '${this.taskName}': ${lastParseError}`,
243
+ );
244
+ }
245
+
185
246
  async shouldRun(): Promise<boolean> {
186
247
  return true;
187
248
  }
@@ -336,6 +336,12 @@ export interface HttpCallConfig {
336
336
  readonly query?: Record<string, string>;
337
337
  readonly output?: string;
338
338
  readonly redirect?: string;
339
+ /**
340
+ * Request timeout in seconds (proto: HttpCallTaskConfig.timeout_seconds,
341
+ * 1-300). Aborts the request and fails the task with HTTP_CALL_TIMEOUT;
342
+ * the engine also widens the activity's startToClose to fit it (#686).
343
+ */
344
+ readonly timeout_seconds?: number;
339
345
  }
340
346
 
341
347
  export type EndpointDef = string | { readonly uri: string; readonly authentication?: Record<string, unknown> };
@@ -67,17 +67,44 @@ const evalProxy = proxyLocalActivities<EvalActivities>({
67
67
  startToCloseTimeout: "10s",
68
68
  });
69
69
 
70
+ const CALL_PROXY_RETRY = {
71
+ maximumAttempts: 5,
72
+ initialInterval: "1s",
73
+ backoffCoefficient: 2,
74
+ maximumInterval: "1m",
75
+ } as const;
76
+
70
77
  const callProxy = proxyActivities<HttpActivities & GrpcActivities & FunctionActivities>({
71
78
  startToCloseTimeout: "5m",
72
79
  heartbeatTimeout: "30s",
73
- retry: {
74
- maximumAttempts: 5,
75
- initialInterval: "1s",
76
- backoffCoefficient: 2,
77
- maximumInterval: "1m",
78
- },
80
+ retry: CALL_PROXY_RETRY,
79
81
  });
80
82
 
83
+ /**
84
+ * Task-config timeouts (llm_call.timeout ≤600s, http_call.timeout_seconds
85
+ * ≤300s) can exceed or crowd the default 5m startToClose, which would kill
86
+ * the activity before its own well-typed LLM_TIMEOUT / HTTP_CALL_TIMEOUT
87
+ * failure fires. When a task declares a budget, proxy its call with
88
+ * startToClose = budget + 30s so the in-activity bound always wins (#686).
89
+ *
90
+ * proxyActivities in workflow code is a deterministic proxy construction
91
+ * (no Temporal commands); the memo just avoids rebuilding per call.
92
+ */
93
+ const timeoutAwareProxies = new Map<number, typeof callProxy>();
94
+ function callProxyFor(timeoutSeconds: number | undefined): typeof callProxy {
95
+ if (!timeoutSeconds || !Number.isFinite(timeoutSeconds)) return callProxy;
96
+ let proxy = timeoutAwareProxies.get(timeoutSeconds);
97
+ if (!proxy) {
98
+ proxy = proxyActivities<HttpActivities & GrpcActivities & FunctionActivities>({
99
+ startToCloseTimeout: `${timeoutSeconds + 30}s`,
100
+ heartbeatTimeout: "30s",
101
+ retry: CALL_PROXY_RETRY,
102
+ });
103
+ timeoutAwareProxies.set(timeoutSeconds, proxy);
104
+ }
105
+ return proxy;
106
+ }
107
+
81
108
  const runProxy = proxyActivities<RunActivities>({
82
109
  startToCloseTimeout: "5m",
83
110
  heartbeatTimeout: "30s",
@@ -240,7 +267,7 @@ export async function runWorkflowEngine(
240
267
  runWorkflow: (config: RunWorkflowExecutionConfig) => orchestrateRunWorkflow(config),
241
268
  awaitHumanInput: (config: HumanInputExecutionConfig) => orchestrateHumanInput(config),
242
269
  callHttp: (config: HttpCallConfig, runtimeEnv: Record<string, unknown>) =>
243
- callProxy.CallHttp(config, runtimeEnv),
270
+ callProxyFor(config.timeout_seconds).CallHttp(config, runtimeEnv),
244
271
  callGrpc: (config: GrpcCallConfig, runtimeEnv: Record<string, unknown>) =>
245
272
  callProxy.CallGrpc(config, runtimeEnv),
246
273
  callFunction: (
@@ -249,7 +276,11 @@ export async function runWorkflowEngine(
249
276
  runtimeEnv: Record<string, unknown>,
250
277
  fnMeta: CallFunctionMetadata,
251
278
  ) =>
252
- callProxy.CallFunction(
279
+ callProxyFor(
280
+ call === "llm" && typeof config.timeout === "number"
281
+ ? config.timeout
282
+ : undefined,
283
+ ).CallFunction(
253
284
  call,
254
285
  config,
255
286
  runtimeEnv,