@stigmer/runner-slim 3.10.0 → 3.11.1-dev.20260812192248

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 (3) hide show
  1. package/main.js +1011 -433
  2. package/package.json +7 -7
  3. package/workflow-bundle.js +83 -5
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@stigmer/runner-slim",
3
- "version": "3.10.0",
3
+ "version": "3.11.1-dev.20260812192248",
4
4
  "description": "Self-contained Stigmer runner build for embedding in desktop apps — the bundle-friendly @stigmer/runner",
5
5
  "license": "Apache-2.0",
6
6
  "engines": {
7
- "node": ">=22.13"
7
+ "node": "^22.13.0 || >=23.4.0"
8
8
  },
9
9
  "bin": {
10
10
  "stigmer-runner": "./main.js"
@@ -16,11 +16,11 @@
16
16
  "jq-wasm": "^1.1.0-jq-1.8.1"
17
17
  },
18
18
  "optionalDependencies": {
19
- "@stigmer/runner-slim-darwin-arm64": "3.10.0",
20
- "@stigmer/runner-slim-darwin-x64": "3.10.0",
21
- "@stigmer/runner-slim-linux-x64": "3.10.0",
22
- "@stigmer/runner-slim-linux-arm64": "3.10.0",
23
- "@stigmer/runner-slim-win32-x64": "3.10.0"
19
+ "@stigmer/runner-slim-darwin-arm64": "3.11.1-dev.20260812192248",
20
+ "@stigmer/runner-slim-darwin-x64": "3.11.1-dev.20260812192248",
21
+ "@stigmer/runner-slim-linux-x64": "3.11.1-dev.20260812192248",
22
+ "@stigmer/runner-slim-linux-arm64": "3.11.1-dev.20260812192248",
23
+ "@stigmer/runner-slim-win32-x64": "3.11.1-dev.20260812192248"
24
24
  },
25
25
  "keywords": [
26
26
  "stigmer",
@@ -25152,12 +25152,14 @@ function buildRecoveryContext(tasks) {
25152
25152
  "use strict";
25153
25153
  __webpack_require__.r(__webpack_exports__);
25154
25154
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
25155
+ /* harmony export */ RuntimePlaceholderResolutionError: () => (/* binding */ RuntimePlaceholderResolutionError),
25155
25156
  /* harmony export */ collectExpressions: () => (/* binding */ collectExpressions),
25156
25157
  /* harmony export */ isRuntimePlaceholder: () => (/* binding */ isRuntimePlaceholder),
25157
25158
  /* harmony export */ resolveConfigExpressions: () => (/* binding */ resolveConfigExpressions),
25158
25159
  /* harmony export */ resolveEmbeddedExpressions: () => (/* binding */ resolveEmbeddedExpressions),
25159
25160
  /* harmony export */ resolveObjectPlaceholders: () => (/* binding */ resolveObjectPlaceholders),
25160
25161
  /* harmony export */ resolveRuntimePlaceholders: () => (/* binding */ resolveRuntimePlaceholders),
25162
+ /* harmony export */ resolveRuntimePlaceholdersStrict: () => (/* binding */ resolveRuntimePlaceholdersStrict),
25161
25163
  /* harmony export */ substituteResults: () => (/* binding */ substituteResults)
25162
25164
  /* harmony export */ });
25163
25165
  /* harmony import */ var _clone_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clone.js */ "./dist/workflow-engine/clone.js");
@@ -25288,6 +25290,8 @@ function parsePath(path) {
25288
25290
  return parts;
25289
25291
  }
25290
25292
  const RUNTIME_PLACEHOLDER_RE = /\$\{\.(secrets|env_vars)\.\w+\}/;
25293
+ /** Substitution form of {@link RUNTIME_PLACEHOLDER_RE} (global, capturing). */
25294
+ const RUNTIME_PLACEHOLDER_SUB_RE = /\$\{\.(secrets|env_vars)\.(\w+)\}/g;
25291
25295
  /**
25292
25296
  * Checks whether a string contains a runtime placeholder that should
25293
25297
  * NOT be evaluated in the workflow (deterministic) phase. These are
@@ -25301,16 +25305,49 @@ function isRuntimePlaceholder(value) {
25301
25305
  }
25302
25306
  /**
25303
25307
  * Resolves runtime placeholders (`${.secrets.KEY}`, `${.env_vars.KEY}`)
25304
- * in a string using values from the runtime environment map.
25308
+ * in a string using values from the runtime environment map. Missing
25309
+ * keys resolve to `""` — callers that must fail loudly instead use
25310
+ * {@link resolveRuntimePlaceholdersStrict}.
25305
25311
  *
25306
25312
  * This runs in activities only — never in the workflow sandbox.
25307
25313
  */
25308
25314
  function resolveRuntimePlaceholders(value, runtimeEnv) {
25309
- return value.replace(/\$\{\.(secrets|env_vars)\.(\w+)\}/g, (_match, _ns, key) => {
25315
+ return value.replace(RUNTIME_PLACEHOLDER_SUB_RE, (_match, _ns, key) => {
25310
25316
  const resolved = runtimeEnv[key];
25311
25317
  return resolved !== undefined ? String(resolved) : "";
25312
25318
  });
25313
25319
  }
25320
+ /** Thrown by {@link resolveRuntimePlaceholdersStrict} for a missing key. */
25321
+ class RuntimePlaceholderResolutionError extends Error {
25322
+ variableName;
25323
+ context;
25324
+ constructor(variableName, context) {
25325
+ const where = context ? ` in ${context}` : "";
25326
+ super(`Unresolved runtime placeholder for "${variableName}"${where}: ` +
25327
+ `variable is not present in the workflow's runtime environment`);
25328
+ this.variableName = variableName;
25329
+ this.context = context;
25330
+ this.name = "RuntimePlaceholderResolutionError";
25331
+ }
25332
+ }
25333
+ /**
25334
+ * Strict variant of {@link resolveRuntimePlaceholders}: a placeholder
25335
+ * whose key is missing from the runtime environment throws instead of
25336
+ * resolving to `""` — a silently-empty credential produces cryptic
25337
+ * downstream failures, so declared-value consumers (the run task's env
25338
+ * contract) fail fast with the variable named.
25339
+ *
25340
+ * This runs in activities only — never in the workflow sandbox.
25341
+ */
25342
+ function resolveRuntimePlaceholdersStrict(value, runtimeEnv, context) {
25343
+ return value.replace(RUNTIME_PLACEHOLDER_SUB_RE, (_match, _ns, key) => {
25344
+ const resolved = runtimeEnv[key];
25345
+ if (resolved === undefined) {
25346
+ throw new RuntimePlaceholderResolutionError(key, context);
25347
+ }
25348
+ return String(resolved);
25349
+ });
25350
+ }
25314
25351
  /**
25315
25352
  * Recursively resolves all runtime placeholders in a nested object.
25316
25353
  * Walks maps, arrays, and strings. Non-string leaves pass through.
@@ -28071,6 +28108,7 @@ async function emitProgress(input, childExecId, progress) {
28071
28108
  type: "agent_call_progress",
28072
28109
  taskName: input.taskName,
28073
28110
  occurredAt: new Date().toISOString(),
28111
+ sequenceNumber: input.nextEventSequence?.(),
28074
28112
  childExecutionId: childExecId,
28075
28113
  agentSlug: input.config.agent ?? "",
28076
28114
  agentPhase: progress?.agentPhase ?? 0,
@@ -28125,6 +28163,13 @@ __webpack_require__.r(__webpack_exports__);
28125
28163
  * type-only imports, and pure JS/TS logic.
28126
28164
  */
28127
28165
 
28166
+ // Discovery's bounds ladder (issue #239): the activity heartbeats every 15s,
28167
+ // so heartbeatTimeout is pure LIVENESS (dead worker/pod detection) — it no
28168
+ // longer kills slow-but-alive discoveries. The activity bounds its own WORK
28169
+ // with a transport-aware init timeout (30s HTTP / 270s stdio) that fails with
28170
+ // an actionable, endpoint-naming error; startToCloseTimeout is the hard cap
28171
+ // above both. Keep the ordering: work bound < hard cap, heartbeat interval
28172
+ // (15s) < heartbeatTimeout.
28128
28173
  const discover = (0,_temporalio_workflow__WEBPACK_IMPORTED_MODULE_0__.proxyActivities)({
28129
28174
  startToCloseTimeout: "600s",
28130
28175
  heartbeatTimeout: "60s",
@@ -28253,6 +28298,7 @@ async function connectMcpServer(input) {
28253
28298
  const discovery = await discover.DiscoverMcpServerCapabilities({
28254
28299
  mcpServerId: input.mcp_server_id,
28255
28300
  executionContextId: input.execution_context_id ?? null,
28301
+ executionContextToken: input.execution_context_token ?? null,
28256
28302
  invokerIdentityAccountId: input.invoker_identity_account_id ?? null,
28257
28303
  });
28258
28304
  // Content-addressed incremental classification: reuse prior decisions for
@@ -28317,6 +28363,7 @@ async function discoverMcpServerLegacy(input) {
28317
28363
  const discovery = await discover.DiscoverMcpServerCapabilities({
28318
28364
  mcpServerId: input.mcp_server_id,
28319
28365
  executionContextId: input.execution_context_id ?? null,
28366
+ executionContextToken: input.execution_context_token ?? null,
28320
28367
  invokerIdentityAccountId: input.invoker_identity_account_id ?? null,
28321
28368
  });
28322
28369
  return {
@@ -28452,7 +28499,21 @@ async function runWorkflowEngine(input, options) {
28452
28499
  dsl: model.document.dsl,
28453
28500
  });
28454
28501
  (0,_metrics_sink_js__WEBPACK_IMPORTED_MODULE_1__.recordExecutionStartMetric)(model.document.name);
28455
- await eventProxy.ResetEventSequence(executionId);
28502
+ // Event sequence numbers are workflow state: assigned here in the
28503
+ // deterministic sandbox (seeded from the persisted high-water mark) so
28504
+ // they are stable across activity retries, worker restarts, and
28505
+ // concurrent executions — the store can then treat re-sent sequences as
28506
+ // idempotent duplicates. Pre-patch histories recorded the activity
28507
+ // result as void and assigned sequences inside the emit activity from a
28508
+ // process-global counter; they must keep doing so on replay, hence the
28509
+ // gate. Remove the gate (and the activity's legacy counter) once
28510
+ // pre-patch executions have drained.
28511
+ const workflowAssignedSequences = (0,_temporalio_workflow__WEBPACK_IMPORTED_MODULE_0__.patched)("workflow-assigned-event-sequences");
28512
+ const eventLogHighWaterMark = await eventProxy.ResetEventSequence(executionId);
28513
+ let eventSequence = workflowAssignedSequences ? Number(eventLogHighWaterMark ?? 0) : 0;
28514
+ const nextEventSequence = workflowAssignedSequences
28515
+ ? () => ++eventSequence
28516
+ : undefined;
28456
28517
  let recoveryContext;
28457
28518
  if (options?.recoveryMode && executionId) {
28458
28519
  _temporalio_workflow__WEBPACK_IMPORTED_MODULE_0__.log.info("Recovery mode active — loading context", { executionId });
@@ -28476,10 +28537,16 @@ async function runWorkflowEngine(input, options) {
28476
28537
  const emitEvents = async (events) => {
28477
28538
  if (!executionId || events.length === 0)
28478
28539
  return;
28540
+ const stamped = nextEventSequence
28541
+ ? events.map(e => ({ ...e, sequenceNumber: nextEventSequence() }))
28542
+ : events;
28479
28543
  try {
28480
- await eventProxy.EmitWorkflowEvents(executionId, events, taskStatusAccumulator.toArray());
28544
+ await eventProxy.EmitWorkflowEvents(executionId, stamped, taskStatusAccumulator.toArray());
28481
28545
  }
28482
28546
  catch (err) {
28547
+ // Final guard after the activity's retries are exhausted: a run must
28548
+ // not die because its timeline write failed. With workflow-assigned
28549
+ // sequences the result is a gap in the log, never a poisoned log.
28483
28550
  _temporalio_workflow__WEBPACK_IMPORTED_MODULE_0__.log.warn("Failed to emit workflow events (non-fatal)", {
28484
28551
  executionId,
28485
28552
  eventCount: events.length,
@@ -28531,6 +28598,7 @@ async function runWorkflowEngine(input, options) {
28531
28598
  parentWorkflowId: agentMeta.parentWorkflowId || (0,_temporalio_workflow__WEBPACK_IMPORTED_MODULE_0__.workflowInfo)().workflowId,
28532
28599
  taskName: agentMeta.taskName,
28533
28600
  workflowExecutionId: agentMeta.workflowExecutionId || executionId,
28601
+ nextEventSequence,
28534
28602
  }),
28535
28603
  promoteTaskOutput: (taskOutput, wexId, taskName, displayName) => promoteProxy.PromoteTaskOutput(taskOutput, wexId || executionId, taskName, displayName),
28536
28604
  };
@@ -28714,7 +28782,17 @@ async function executeFromExecution(input) {
28714
28782
  envCount: Object.keys(materialized.env).length,
28715
28783
  });
28716
28784
  try {
28717
- return await (0,_engine_core_js__WEBPACK_IMPORTED_MODULE_1__.runWorkflowEngine)(materialized, {
28785
+ // The engine's output is deliberately NOT returned. Both orchestrator
28786
+ // parents discard this workflow's result (Java awaits it as Void, Go
28787
+ // passes nil to Get), and the output already reaches users through
28788
+ // PromoteTaskOutput and the event log. Returning it would (a) persist
28789
+ // the full workflow output — which may embed secrets — as a plaintext
28790
+ // payload in the cross-language parent's history, and (b) hand the Java
28791
+ // parent a payload it must decode: once the payload-encryption codec is
28792
+ // active, an encrypted result would fail Java's converter lookup
28793
+ // (fromPayloads has no Void special-case). A void return produces a
28794
+ // data-less binary/null payload that every SDK handles natively.
28795
+ await (0,_engine_core_js__WEBPACK_IMPORTED_MODULE_1__.runWorkflowEngine)(materialized, {
28718
28796
  checkPause,
28719
28797
  recoveryMode: input.recovery_mode ?? false,
28720
28798
  });