@oomol-lab/open-flow 0.1.0-beta.63 → 0.1.0-beta.65

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.
@@ -3,6 +3,7 @@ import type { PreparedFlow } from './flow-semantics.js';
3
3
  import type { PreviousNode } from '../index.js';
4
4
  import type { AgentCheckpoint } from './runtime-contract.js';
5
5
  import * as Effect from 'effect/Effect';
6
+ export declare const withWaitNotificationMessage: (value: JsonValue) => JsonValue;
6
7
  export declare const normalizeWaitComment: (value?: string | null) => string | null;
7
8
  export interface WaitResolution {
8
9
  readonly action: WaitAction;
@@ -10563,6 +10563,12 @@ function resolutionOutputPorts(node) {
10563
10563
  pending: objectPort({
10564
10564
  inputs,
10565
10565
  prompt: { type: "string" },
10566
+ pageUrl: { type: "string" },
10567
+ message: {
10568
+ type: "string",
10569
+ minLength: 1,
10570
+ pattern: "\\S"
10571
+ },
10566
10572
  ...Object.fromEntries(actions.map((action) => [`${action}Url`, { type: "string" }])),
10567
10573
  expiresAt: { type: "string" }
10568
10574
  }),
@@ -10875,8 +10881,24 @@ var waitCommentSchema = string().trim().refine((value) => [...value].length <= 2
10875
10881
  function normalizeWaitComment$1(value) {
10876
10882
  return waitCommentSchema.parse(value) || null;
10877
10883
  }
10884
+ function withWaitNotificationMessage$1(value) {
10885
+ const source = schemaObject(value);
10886
+ if (source == null || source.pageUrl !== void 0 && source.message !== void 0) return value;
10887
+ const pageUrl = source.pageUrl === void 0 ? source.continueUrl ?? source.approveUrl : source.pageUrl;
10888
+ if (typeof pageUrl != "string" || typeof source.prompt != "string" || typeof source.expiresAt != "string") return value;
10889
+ return {
10890
+ ...source,
10891
+ pageUrl,
10892
+ message: source.message === void 0 ? [
10893
+ source.prompt,
10894
+ `Expires at: ${source.expiresAt}`,
10895
+ `Review request: ${pageUrl}`
10896
+ ].join("\n\n") : source.message
10897
+ };
10898
+ }
10878
10899
  //#endregion
10879
10900
  //#region src/execution/common/scheduler.ts
10901
+ var withWaitNotificationMessage = withWaitNotificationMessage$1;
10880
10902
  var normalizeWaitComment = normalizeWaitComment$1;
10881
10903
  var PortValidationError = class extends Error {};
10882
10904
  function usesPending(graph, nodeId) {
@@ -11349,7 +11371,7 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11349
11371
  const node = target.graph.nodes[nodeId];
11350
11372
  const waitId = nanoid$1();
11351
11373
  const notify = isResolutionNode(node) && usesPending(target.graph, nodeId);
11352
- const pending = yield* context.waits.create({
11374
+ const notification = yield* context.waits.create({
11353
11375
  jobId,
11354
11376
  nodeId,
11355
11377
  value,
@@ -11359,6 +11381,7 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11359
11381
  prompt: isResolutionNode(node) ? node.prompt : JSON.stringify(value, null, 2),
11360
11382
  ...isResolutionNode(node) ? {} : { notification: agentNotice(node, agents[jobId].input) }
11361
11383
  });
11384
+ const pending = notification == null ? notification : withWaitNotificationMessage(notification);
11362
11385
  if (notify) {
11363
11386
  validateOutputs(nodeId, node, { pending });
11364
11387
  dependencies.release(nodeId, { pending }, ["pending"], false);
@@ -11553,7 +11576,30 @@ function runFlow(prepared, options) {
11553
11576
  const emit = options.emit ?? (() => Effect.void);
11554
11577
  return Effect.gen(function* () {
11555
11578
  if (options.resume != null && (options.inputs != null || options.trigger != null || options.bindingValues != null)) return yield* Effect.fail(/* @__PURE__ */ new Error("A resumed Flow Run cannot accept launch inputs, binding values, or a Trigger seed."));
11556
- const checkpoint = options.resume == null ? void 0 : decodeFlowRunCheckpoint(options.resume.checkpoint);
11579
+ const decoded = options.resume == null ? void 0 : decodeFlowRunCheckpoint(options.resume.checkpoint);
11580
+ const outputs = (nodeId, value) => isResolutionNode(prepared.graph.nodes[nodeId]) && value.pending != null ? {
11581
+ ...value,
11582
+ pending: withWaitNotificationMessage(value.pending)
11583
+ } : value;
11584
+ const checkpoint = decoded == null ? void 0 : {
11585
+ ...decoded,
11586
+ results: Object.fromEntries(Object.entries(decoded.results).map(([id, result]) => [id, {
11587
+ ...result,
11588
+ outputs: outputs(id, result.outputs)
11589
+ }])),
11590
+ dependencies: {
11591
+ ...decoded.dependencies,
11592
+ nodes: Object.fromEntries(Object.entries(decoded.dependencies.nodes).map(([id, state]) => [id, {
11593
+ ...state,
11594
+ ...state.output == null ? {} : { output: outputs(id, state.output) },
11595
+ input: Object.fromEntries(Object.entries(state.input).map(([source, result]) => [source, {
11596
+ ...result,
11597
+ outputs: outputs(source, result.outputs)
11598
+ }]))
11599
+ }]))
11600
+ },
11601
+ waits: decoded.waits.map((wait) => wait.pending == null ? wait : Object.assign({}, wait, { pending: withWaitNotificationMessage(wait.pending) }))
11602
+ };
11557
11603
  if (checkpoint != null && new TextEncoder().encode(JSON.stringify(checkpoint)).byteLength > 16777216) return yield* Effect.fail(/* @__PURE__ */ new Error("Flow Run checkpoint exceeds 16 MiB."));
11558
11604
  if (checkpoint == null && options.trigger == null) return yield* Effect.fail(/* @__PURE__ */ new Error("A Flow Run requires a Trigger seed."));
11559
11605
  const triggerNode = options.trigger == null ? void 0 : prepared.graph.nodes[options.trigger.nodeId];
@@ -11576,4 +11622,4 @@ function runFlow(prepared, options) {
11576
11622
  });
11577
11623
  }
11578
11624
  //#endregion
11579
- export { PortValidationError, decodeFlowRunCheckpoint, normalizeWaitComment, runFlow, waitRetentionMs };
11625
+ export { PortValidationError, decodeFlowRunCheckpoint, normalizeWaitComment, runFlow, waitRetentionMs, withWaitNotificationMessage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oomol-lab/open-flow",
3
- "version": "0.1.0-beta.63",
3
+ "version": "0.1.0-beta.65",
4
4
  "description": "TypeScript contracts and Browser runtime for Open Flow.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -410,3 +410,32 @@ current online entries. The MCP equivalent is `flow_live({ flowId })`.
410
410
  A useful completion report identifies the Flow and Revision, what changed,
411
411
  what was actually checked or executed, and any remaining blocker. Its detail
412
412
  should match the task.
413
+
414
+ ## Workbench node annotations
415
+
416
+ Node annotations from the Codex browser show the node title as the annotation name.
417
+ Metadata contains `flowId`, `revisionId`, `nodeId`, and `syncState`, plus `description`
418
+ when nonempty. The identity fields are never truncated; `revisionId` identifies the
419
+ saved Revision. Descriptions may be shortened with an ellipsis to fit the annotation
420
+ limits; read full content
421
+ through the public API. The browser supplies the source page URL separately. Continue
422
+ using the configured deployment and verify it matches the referenced Flow.
423
+ Read the referenced node with the public read command before acting. Before editing,
424
+ read the current Draft and use its revision checks; a captured annotation may be older
425
+ than the current Draft. If the node no longer exists, report that instead of choosing
426
+ another node by name.
427
+
428
+ `syncState` describes the Workbench's known save state (`saved`, `dirty`, `saving`, or
429
+ `failed`). The revision always identifies saved data; pending local changes, including
430
+ unsaved code, are not part of that snapshot. An annotation does not save those changes
431
+ or establish a CLI/MCP connection. Missing or invalid metadata is not sufficient to
432
+ identify a node for editing.
433
+
434
+ A multi-node annotation carries the same `flowId`, `revisionId`, and `syncState`,
435
+ with `nodeIds` instead of `nodeId`. Parse `nodeIds` as a JSON-encoded string array
436
+ and read every referenced node. The group contains business nodes and Triggers;
437
+ Comment cards have no authoring node identity and are not included in this feature.
438
+ If the complete list exceeds the annotation limits, metadata contains `nodeCount`
439
+ and `error` instead of `nodeIds`. Ask for a smaller selection; never infer a partial
440
+ list or treat a missing list as the whole Flow. The annotation captures the selection
441
+ at creation time, not whichever nodes happen to be selected when the agent acts.