@stigmer/runner-slim 3.1.10 → 3.1.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/runner-slim",
3
- "version": "3.1.10",
3
+ "version": "3.1.12",
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": {
@@ -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.1.10",
20
- "@stigmer/runner-slim-darwin-x64": "3.1.10",
21
- "@stigmer/runner-slim-linux-x64": "3.1.10",
22
- "@stigmer/runner-slim-linux-arm64": "3.1.10",
23
- "@stigmer/runner-slim-win32-x64": "3.1.10"
19
+ "@stigmer/runner-slim-darwin-arm64": "3.1.12",
20
+ "@stigmer/runner-slim-darwin-x64": "3.1.12",
21
+ "@stigmer/runner-slim-linux-x64": "3.1.12",
22
+ "@stigmer/runner-slim-linux-arm64": "3.1.12",
23
+ "@stigmer/runner-slim-win32-x64": "3.1.12"
24
24
  },
25
25
  "keywords": [
26
26
  "stigmer",
@@ -25324,9 +25324,16 @@ function collectEmbeddedExpressions(obj, prefix, mappings, batchExprs, skipPaths
25324
25324
  }
25325
25325
  }
25326
25326
  function collectEmbeddedFromValue(value, path, mappings, batchExprs, skipPaths) {
25327
+ // A Phase-1-resolved path holds data, not template text: skip its
25328
+ // entire subtree, whatever shape it resolved to. A strict expression
25329
+ // can resolve to an object or array whose nested strings carry literal
25330
+ // `${ ... }` text from external sources (webhook payloads, API
25331
+ // responses, documents under review) that must never be re-interpreted
25332
+ // as expressions. Checking only string values at the exact path — the
25333
+ // previous behavior — left those nested strings exposed.
25334
+ if (skipPaths.has(path))
25335
+ return;
25327
25336
  if (typeof value === "string") {
25328
- if (skipPaths.has(path))
25329
- return;
25330
25337
  if ((0,_expression_utils_js__WEBPACK_IMPORTED_MODULE_1__.isStrictExpr)(value))
25331
25338
  return;
25332
25339
  const expressions = (0,_expression_utils_js__WEBPACK_IMPORTED_MODULE_1__.extractEmbeddedExpressions)(value);
@@ -25856,7 +25863,7 @@ class TaskStatusAccumulator {
25856
25863
  error: reason,
25857
25864
  });
25858
25865
  }
25859
- taskWaitingApproval(name) {
25866
+ taskWaitingApproval(name, uiHint) {
25860
25867
  const existing = this.entries.get(name);
25861
25868
  this.entries.set(name, {
25862
25869
  ...existing,
@@ -25865,6 +25872,7 @@ class TaskStatusAccumulator {
25865
25872
  taskKind: existing?.taskKind ?? "",
25866
25873
  status: "waiting_approval",
25867
25874
  startedAt: existing?.startedAt,
25875
+ uiHint: uiHint ?? existing?.uiHint,
25868
25876
  });
25869
25877
  }
25870
25878
  setTaskMetadata(name, metadata) {
@@ -26711,6 +26719,8 @@ __webpack_require__.r(__webpack_exports__);
26711
26719
  * call: human_input
26712
26720
  * with:
26713
26721
  * prompt: "Please review this deployment"
26722
+ * payload: ${ $context.deployment_plan }
26723
+ * ui_hint: deployment-plan
26714
26724
  * timeout: 300
26715
26725
  * on_timeout: approve
26716
26726
  * outcomes:
@@ -26718,6 +26728,11 @@ __webpack_require__.r(__webpack_exports__);
26718
26728
  * - name: deny
26719
26729
  * - name: revise
26720
26730
  * then: gatherMore
26731
+ *
26732
+ * The payload (the material under review) is expression-resolved at gate
26733
+ * activation and attached to the approval_requested event — inline when
26734
+ * small, as an artifact reference when at/above the promotion threshold —
26735
+ * so the approval record captures exactly what the reviewer saw.
26721
26736
  */
26722
26737
 
26723
26738
 
@@ -26735,10 +26750,12 @@ async function executeHumanInputTask(taskDef, taskName, state, ctx) {
26735
26750
  const timeoutSeconds = config.timeout ?? DEFAULT_TIMEOUT_SECONDS;
26736
26751
  const onTimeout = config.onTimeout ?? DEFAULT_ON_TIMEOUT;
26737
26752
  const resolvedPrompt = await resolvePromptExpressions(config.prompt, state, ctx);
26753
+ const review = await resolveReviewPayload(config, taskName, state, ctx);
26738
26754
  const approvalRequestedAt = Date.now();
26739
- ctx.taskStatusAccumulator?.taskWaitingApproval(taskName);
26755
+ ctx.taskStatusAccumulator?.taskWaitingApproval(taskName, config.uiHint);
26740
26756
  if (ctx.emitEvents) {
26741
- await ctx.emitEvents([{
26757
+ await ctx.emitEvents([
26758
+ {
26742
26759
  type: "approval_requested",
26743
26760
  taskName,
26744
26761
  occurredAt: new Date().toISOString(),
@@ -26750,7 +26767,12 @@ async function executeHumanInputTask(taskDef, taskName, state, ctx) {
26750
26767
  label: o.label ?? "",
26751
26768
  })),
26752
26769
  formSchema: config.formSchema,
26753
- }]);
26770
+ payload: review.payload,
26771
+ uiHint: config.uiHint,
26772
+ payloadArtifactId: review.payloadArtifactId,
26773
+ },
26774
+ ...review.artifactEvents,
26775
+ ]);
26754
26776
  }
26755
26777
  const result = await ctx.awaitHumanInput({
26756
26778
  signalName,
@@ -26781,6 +26803,58 @@ function validateConfig(config, taskName) {
26781
26803
  throw new Error(`human_input task '${taskName}': 'prompt' is required`);
26782
26804
  }
26783
26805
  }
26806
+ const NO_REVIEW_PAYLOAD = { artifactEvents: [] };
26807
+ /**
26808
+ * Resolves the review payload's `${ ... }` expressions and decides how it
26809
+ * rides the approval_requested event: inline when small, or as an artifact
26810
+ * reference when at/above the promotion threshold (256KB).
26811
+ *
26812
+ * Resolution goes through `resolveConfigExpressions` for its two-phase
26813
+ * injection safety: review material resolved from `$context` (article
26814
+ * drafts, webhook data) may contain literal `${ ... }` text that must
26815
+ * never be re-evaluated as an expression.
26816
+ *
26817
+ * A resolution failure fails the task — a gate whose review material
26818
+ * failed to materialize must not present an empty review. Promotion
26819
+ * failure falls back to inline delivery (best-effort, matching the
26820
+ * do-executor's task-output promotion policy).
26821
+ */
26822
+ async function resolveReviewPayload(config, taskName, state, ctx) {
26823
+ if (config.payload === undefined || config.payload === null) {
26824
+ return NO_REVIEW_PAYLOAD;
26825
+ }
26826
+ let resolved;
26827
+ try {
26828
+ const result = await (0,_resolve_js__WEBPACK_IMPORTED_MODULE_0__.resolveConfigExpressions)({ payload: config.payload }, null, state, ctx.evaluateExpressions);
26829
+ resolved = result.payload;
26830
+ }
26831
+ catch (err) {
26832
+ const message = err instanceof Error ? err.message : String(err);
26833
+ throw new Error(`human_input task '${taskName}': failed to resolve 'payload' expressions: ${message}`);
26834
+ }
26835
+ // jq resolves missing paths to null rather than erroring. A configured
26836
+ // payload that materializes as nothing is an authoring error (typically a
26837
+ // wrong $context path) — fail loudly instead of presenting an empty review.
26838
+ if (resolved === undefined || resolved === null) {
26839
+ throw new Error(`human_input task '${taskName}': 'payload' resolved to null — ` +
26840
+ `check that the expression references existing workflow data`);
26841
+ }
26842
+ if (ctx.promoteTaskOutput) {
26843
+ try {
26844
+ const promotion = await ctx.promoteTaskOutput(resolved, state.env?.__stigmer_execution_id ?? "", taskName, `${taskName} — review-payload.json`);
26845
+ if (promotion.artifactIds.length > 0) {
26846
+ return {
26847
+ payloadArtifactId: promotion.artifactIds[0],
26848
+ artifactEvents: promotion.artifactCreatedEvents,
26849
+ };
26850
+ }
26851
+ }
26852
+ catch {
26853
+ // Promotion is best-effort; fall through to inline delivery.
26854
+ }
26855
+ }
26856
+ return { payload: resolved, artifactEvents: [] };
26857
+ }
26784
26858
  /**
26785
26859
  * Resolves `${ ... }` expressions in the prompt string against the
26786
26860
  * current workflow state. Handles both strict (whole-value) and embedded
@@ -28323,7 +28397,7 @@ async function runWorkflowEngine(input, options) {
28323
28397
  taskName: agentMeta.taskName,
28324
28398
  workflowExecutionId: agentMeta.workflowExecutionId || executionId,
28325
28399
  }),
28326
- promoteTaskOutput: (taskOutput, wexId, taskName) => promoteProxy.PromoteTaskOutput(taskOutput, wexId || executionId, taskName),
28400
+ promoteTaskOutput: (taskOutput, wexId, taskName, displayName) => promoteProxy.PromoteTaskOutput(taskOutput, wexId || executionId, taskName, displayName),
28327
28401
  };
28328
28402
  const state = (0,_workflow_engine_state_js__WEBPACK_IMPORTED_MODULE_7__.createState)();
28329
28403
  state.env = {