@bastani/atomic 0.9.11-alpha.1 → 0.9.11-alpha.2

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 (133) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/builtin/cursor/package.json +3 -3
  3. package/dist/builtin/intercom/package.json +2 -2
  4. package/dist/builtin/mcp/package.json +3 -3
  5. package/dist/builtin/subagents/package.json +4 -4
  6. package/dist/builtin/web-access/package.json +2 -2
  7. package/dist/builtin/workflows/CHANGELOG.md +6 -0
  8. package/dist/builtin/workflows/package.json +2 -2
  9. package/dist/builtin/workflows/src/durable/child-primitive.ts +3 -0
  10. package/dist/builtin/workflows/src/durable/completed-catalog.ts +182 -33
  11. package/dist/builtin/workflows/src/durable/completed-inspection.ts +9 -4
  12. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +31 -8
  13. package/dist/builtin/workflows/src/durable/resume-runtime.ts +6 -2
  14. package/dist/builtin/workflows/src/durable/stage-primitive.ts +48 -10
  15. package/dist/builtin/workflows/src/durable/types.ts +11 -0
  16. package/dist/builtin/workflows/src/engine/run-durable-stage-session.ts +9 -9
  17. package/dist/builtin/workflows/src/engine/run-durable-topology.ts +89 -0
  18. package/dist/builtin/workflows/src/engine/run.ts +18 -16
  19. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +3 -0
  20. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +3 -0
  21. package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +6 -3
  22. package/dist/builtin/workflows/src/runs/foreground/executor-stage-types.ts +2 -2
  23. package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +4 -1
  24. package/dist/builtin/workflows/src/tui/workflow-resume-selector.ts +2 -3
  25. package/dist/cli/args.d.ts.map +1 -1
  26. package/dist/cli/args.js +2 -0
  27. package/dist/cli/args.js.map +1 -1
  28. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  29. package/dist/core/agent-session-compaction.js +7 -1
  30. package/dist/core/agent-session-compaction.js.map +1 -1
  31. package/dist/core/agent-session-services.d.ts.map +1 -1
  32. package/dist/core/agent-session-services.js +3 -0
  33. package/dist/core/agent-session-services.js.map +1 -1
  34. package/dist/core/agent-session-tree.d.ts.map +1 -1
  35. package/dist/core/agent-session-tree.js +4 -1
  36. package/dist/core/agent-session-tree.js.map +1 -1
  37. package/dist/core/agent-session-types.d.ts +15 -0
  38. package/dist/core/agent-session-types.d.ts.map +1 -1
  39. package/dist/core/agent-session-types.js.map +1 -1
  40. package/dist/core/compaction/branch-summarization.d.ts +5 -1
  41. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  42. package/dist/core/compaction/branch-summarization.js +7 -8
  43. package/dist/core/compaction/branch-summarization.js.map +1 -1
  44. package/dist/core/compaction/compaction-runner.d.ts +3 -1
  45. package/dist/core/compaction/compaction-runner.d.ts.map +1 -1
  46. package/dist/core/compaction/compaction-runner.js +6 -1
  47. package/dist/core/compaction/compaction-runner.js.map +1 -1
  48. package/dist/core/compaction/range-planner.d.ts +3 -0
  49. package/dist/core/compaction/range-planner.d.ts.map +1 -1
  50. package/dist/core/compaction/range-planner.js +2 -1
  51. package/dist/core/compaction/range-planner.js.map +1 -1
  52. package/dist/core/model-registry.js +2 -2
  53. package/dist/core/model-registry.js.map +1 -1
  54. package/dist/core/model-resolver-defaults.d.ts.map +1 -1
  55. package/dist/core/model-resolver-defaults.js +2 -0
  56. package/dist/core/model-resolver-defaults.js.map +1 -1
  57. package/dist/core/prompt-templates.d.ts +1 -0
  58. package/dist/core/prompt-templates.d.ts.map +1 -1
  59. package/dist/core/prompt-templates.js +6 -4
  60. package/dist/core/prompt-templates.js.map +1 -1
  61. package/dist/core/remote-catalog-provider.d.ts +1 -1
  62. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  63. package/dist/core/remote-catalog-provider.js +25 -6
  64. package/dist/core/remote-catalog-provider.js.map +1 -1
  65. package/dist/core/sdk-exports.d.ts +1 -1
  66. package/dist/core/sdk-exports.d.ts.map +1 -1
  67. package/dist/core/sdk-exports.js.map +1 -1
  68. package/dist/core/sdk.d.ts.map +1 -1
  69. package/dist/core/sdk.js +4 -1
  70. package/dist/core/sdk.js.map +1 -1
  71. package/dist/core/session-manager-core.d.ts +1 -0
  72. package/dist/core/session-manager-core.d.ts.map +1 -1
  73. package/dist/core/session-manager-core.js +7 -4
  74. package/dist/core/session-manager-core.js.map +1 -1
  75. package/dist/core/session-manager-validation.d.ts.map +1 -1
  76. package/dist/core/session-manager-validation.js +3 -16
  77. package/dist/core/session-manager-validation.js.map +1 -1
  78. package/dist/core/summarization-retry.d.ts +11 -0
  79. package/dist/core/summarization-retry.d.ts.map +1 -0
  80. package/dist/core/summarization-retry.js +21 -0
  81. package/dist/core/summarization-retry.js.map +1 -0
  82. package/dist/core/tools/read.js +1 -1
  83. package/dist/core/tools/read.js.map +1 -1
  84. package/dist/index.d.ts +1 -1
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js.map +1 -1
  87. package/dist/main.d.ts.map +1 -1
  88. package/dist/main.js +2 -0
  89. package/dist/main.js.map +1 -1
  90. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  91. package/dist/modes/interactive/components/chat-session-host-events.js +16 -0
  92. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  93. package/dist/modes/interactive/components/footer.js +2 -2
  94. package/dist/modes/interactive/components/footer.js.map +1 -1
  95. package/dist/modes/interactive/interactive-agent-events.js +6 -0
  96. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  97. package/dist/modes/interactive/interactive-model-catalog-startup.d.ts +13 -0
  98. package/dist/modes/interactive/interactive-model-catalog-startup.d.ts.map +1 -0
  99. package/dist/modes/interactive/interactive-model-catalog-startup.js +24 -0
  100. package/dist/modes/interactive/interactive-model-catalog-startup.js.map +1 -0
  101. package/dist/modes/interactive/interactive-model-routing.js +4 -3
  102. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  103. package/dist/modes/interactive/interactive-queueing.js +3 -2
  104. package/dist/modes/interactive/interactive-queueing.js.map +1 -1
  105. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  106. package/dist/modes/interactive/interactive-startup.js +4 -7
  107. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  108. package/dist/modes/interactive/interactive-summarization-retry-events.d.ts +8 -0
  109. package/dist/modes/interactive/interactive-summarization-retry-events.d.ts.map +1 -0
  110. package/dist/modes/interactive/interactive-summarization-retry-events.js +40 -0
  111. package/dist/modes/interactive/interactive-summarization-retry-events.js.map +1 -0
  112. package/dist/modes/rpc/rpc-client-api.d.ts +1 -0
  113. package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
  114. package/dist/modes/rpc/rpc-client-api.js +3 -0
  115. package/dist/modes/rpc/rpc-client-api.js.map +1 -1
  116. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  117. package/dist/modes/rpc/rpc-command-handler.js +5 -0
  118. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  119. package/dist/modes/rpc/rpc-types.d.ts +11 -0
  120. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  121. package/dist/modes/rpc/rpc-types.js.map +1 -1
  122. package/docs/extensions.md +3 -3
  123. package/docs/json.md +7 -1
  124. package/docs/prompt-templates.md +1 -0
  125. package/docs/providers.md +4 -0
  126. package/docs/rpc.md +49 -0
  127. package/docs/sdk.md +3 -0
  128. package/docs/tui.md +2 -2
  129. package/docs/workflows.md +6 -6
  130. package/examples/extensions/README.md +1 -1
  131. package/examples/extensions/sandbox/package-lock.json +3 -3
  132. package/npm-shrinkwrap.json +36 -36
  133. package/package.json +5 -5
@@ -9,7 +9,7 @@ import { durableHash } from "./backend.js";
9
9
  import { recordCheckpointDurably } from "./tool-primitive.js";
10
10
  import { elapsedStageMs } from "../shared/timing.js";
11
11
  import { RESUME_CONTINUATION_PROMPT } from "../shared/resume-continuation.js";
12
- import { DURABLE_STAGE_TOPOLOGY_VERSION, type DurableStageCheckpoint } from "./types.js";
12
+ import { DURABLE_STAGE_TOPOLOGY_VERSION, type DurableStageCheckpoint, type DurableStageRunTopology } from "./types.js";
13
13
  export type DurableCompletedStageCheckpoint = DurableStageCheckpoint & { readonly output: WorkflowSerializableValue };
14
14
 
15
15
  export interface DurableStageDeps {
@@ -18,13 +18,14 @@ export interface DurableStageDeps {
18
18
  readonly nextCheckpointId: () => string;
19
19
  readonly nextReplayKey: (stageName: string) => string;
20
20
  readonly replayKeyForCompletedStage?: (stage: StageSnapshot) => string | undefined;
21
+ readonly runTopology?: DurableStageRunTopology;
21
22
  readonly now?: () => number;
22
23
  }
23
24
 
24
25
  export async function recordStageCheckpoint(deps: DurableStageDeps, stage: StageSnapshot): Promise<boolean> {
25
26
  if (stage.status !== "completed") return false;
26
27
  const replayKey = deps.replayKeyForCompletedStage?.(stage) ?? stage.replayKey ?? deps.nextReplayKey(stage.name);
27
- const metadata = checkpointMetadata(stage);
28
+ const metadata = durableStageCheckpointMetadata(stage, deps.runTopology);
28
29
  const hasExistingOutput = deps.backend.getStageOutput(deps.workflowId, replayKey) !== undefined;
29
30
  const checkpoint: DurableStageCheckpoint = hasExistingOutput
30
31
  ? {
@@ -62,13 +63,17 @@ function stageSessionDurationBucket(durationMs: number | undefined): number {
62
63
  return Math.floor((durationMs ?? 0) / STAGE_SESSION_DURATION_BUCKET_MS);
63
64
  }
64
65
 
65
- export async function recordStageSessionCheckpoint(deps: DurableStageDeps, stage: StageSnapshot): Promise<boolean> {
66
+ export async function recordStageSessionCheckpoint(
67
+ deps: DurableStageDeps,
68
+ stage: StageSnapshot,
69
+ options?: { readonly force?: boolean },
70
+ ): Promise<boolean> {
66
71
  const replayKey = deps.replayKeyForCompletedStage?.(stage) ?? stage.replayKey ?? deps.nextReplayKey(stage.name);
67
72
  if (stage.sessionFile === undefined) return false;
68
73
  const checkpointNow = deps.now?.() ?? Date.now();
69
74
  const durationMs = elapsedStageMs(stage, checkpointNow) ?? 0;
70
75
  const current = deps.backend.getStageSession(deps.workflowId, replayKey);
71
- if (current !== undefined
76
+ if (options?.force !== true && current !== undefined
72
77
  && current.sessionId === stage.sessionId
73
78
  && current.sessionFile === stage.sessionFile
74
79
  && current.startedAt === stage.startedAt
@@ -79,6 +84,7 @@ export async function recordStageSessionCheckpoint(deps: DurableStageDeps, stage
79
84
  checkpointId: stageSessionCheckpointId(replayKey, stage, durationMs),
80
85
  name: stage.name,
81
86
  replayKey,
87
+ ...durableStageCheckpointMetadata(stage, deps.runTopology),
82
88
  ...(stage.sessionId !== undefined ? { sessionId: stage.sessionId } : {}),
83
89
  sessionFile: stage.sessionFile,
84
90
  ...(stage.startedAt !== undefined ? { startedAt: stage.startedAt } : {}),
@@ -256,9 +262,17 @@ function stageOutput(stage: StageSnapshot): WorkflowSerializableValue {
256
262
  return { status: stage.status, stageId: stage.id };
257
263
  }
258
264
 
259
- function checkpointMetadata(stage: StageSnapshot): Partial<DurableStageCheckpoint> {
265
+ export function durableStageCheckpointMetadata(
266
+ stage: StageSnapshot,
267
+ run?: DurableStageRunTopology,
268
+ ): Partial<DurableStageCheckpoint> {
260
269
  return {
261
- topology: { version: DURABLE_STAGE_TOPOLOGY_VERSION, stageId: stage.id, parentIds: [...stage.parentIds] },
270
+ topology: {
271
+ version: DURABLE_STAGE_TOPOLOGY_VERSION,
272
+ stageId: stage.id,
273
+ parentIds: [...stage.parentIds],
274
+ ...(run !== undefined ? { run: { ...run } } : {}),
275
+ },
262
276
  ...(stage.startedAt !== undefined ? { startedAt: stage.startedAt } : {}),
263
277
  ...(stage.endedAt !== undefined ? { endedAt: stage.endedAt } : {}),
264
278
  ...(stage.durationMs !== undefined ? { durationMs: stage.durationMs } : {}),
@@ -311,6 +325,7 @@ function mergeCheckpointHydrationMetadata(
311
325
  if (checkpoints.length === 0) return replayValueCheckpoint;
312
326
  return {
313
327
  ...replayValueCheckpoint,
328
+ ...preferredHydrationTopology(replayValueCheckpoint, checkpoints),
314
329
  ...(replayValueCheckpoint.startedAt === undefined ? metadataValue(checkpoints, "startedAt") : {}),
315
330
  ...(replayValueCheckpoint.endedAt === undefined ? metadataValue(checkpoints, "endedAt") : {}),
316
331
  ...(replayValueCheckpoint.durationMs === undefined ? metadataValue(checkpoints, "durationMs") : {}),
@@ -323,6 +338,19 @@ function mergeCheckpointHydrationMetadata(
323
338
  ...(replayValueCheckpoint.modelAttempts === undefined ? metadataValue(checkpoints, "modelAttempts") : {}),
324
339
  };
325
340
  }
341
+ function preferredHydrationTopology(
342
+ replayValueCheckpoint: DurableCompletedStageCheckpoint,
343
+ checkpoints: readonly DurableStageCheckpoint[],
344
+ ): Pick<DurableStageCheckpoint, "topology"> | Record<string, never> {
345
+ for (let index = checkpoints.length - 1; index >= 0; index -= 1) {
346
+ const topology = checkpoints[index]?.topology;
347
+ if (topology?.run !== undefined) return { topology };
348
+ }
349
+ return replayValueCheckpoint.topology === undefined
350
+ ? metadataValue(checkpoints, "topology")
351
+ : {};
352
+ }
353
+
326
354
 
327
355
  function metadataValue<K extends keyof DurableStageCheckpoint>(
328
356
  checkpoints: readonly DurableStageCheckpoint[],
@@ -390,6 +418,7 @@ export function recordCachedStageIntoStore(
390
418
  id: stageId, name, status: "completed", parentIds: parentIds !== undefined ? Object.freeze([...parentIds]) : [],
391
419
  startedAt: checkpoint?.startedAt ?? endedAt, endedAt, durationMs: checkpoint?.durationMs ?? 0, result,
392
420
  replayKey, replayed: true, skippedReason: "durable checkpoint replay", toolEvents: [], attachable: false,
421
+ ...(checkpoint?.topology !== undefined ? { replayedFromStageId: checkpoint.topology.stageId } : {}),
393
422
  ...(workflowChild !== undefined ? { workflowChild } : {}),
394
423
  ...(checkpoint?.sessionId !== undefined ? { sessionId: checkpoint.sessionId } : {}),
395
424
  ...(checkpoint?.sessionFile !== undefined ? { sessionFile: checkpoint.sessionFile } : {}),
@@ -420,10 +449,19 @@ export function recordCachedStageWithTracker(
420
449
  ): void {
421
450
  const stageId = cachedStageId(runId, replayKey);
422
451
  let parentIds = tracker.onSpawn(stageId, name);
423
- const scopeParentIds = stageFailFastScope?.parentIds ?? [];
424
- if (stageFailFastScope !== undefined) {
425
- tracker.replaceParents(stageId, scopeParentIds);
426
- parentIds = [...scopeParentIds];
452
+ const sourceParents = checkpoint.topology?.run?.runId === runId
453
+ ? checkpoint.topology.parentIds
454
+ : undefined;
455
+ const run = store.runs().find((candidate) => candidate.id === runId);
456
+ const restored = sourceParents?.map((sourceId) =>
457
+ run?.stages.find((stage) => stage.replayedFromStageId === sourceId)?.id
458
+ );
459
+ if (restored !== undefined && restored.every((id): id is string => id !== undefined)) {
460
+ parentIds = restored;
461
+ tracker.replaceParents(stageId, parentIds);
462
+ } else if (stageFailFastScope !== undefined) {
463
+ parentIds = [...(stageFailFastScope.parentIds ?? [])];
464
+ tracker.replaceParents(stageId, parentIds);
427
465
  }
428
466
  recordCachedStageIntoStore(store, runId, name, replayKey, checkpoint.output, completedStageReplayKeys, parentIds, checkpoint);
429
467
  tracker.onSettle(stageId);
@@ -110,11 +110,22 @@ export interface DurableUiCheckpoint {
110
110
 
111
111
  export const DURABLE_STAGE_TOPOLOGY_VERSION = 1 as const;
112
112
 
113
+ /** Durable ownership metadata needed to rebuild nested workflow runs. */
114
+ export interface DurableStageRunTopology {
115
+ readonly runId: string;
116
+ readonly runName: string;
117
+ readonly parentRunId?: string;
118
+ readonly parentStageId?: string;
119
+ readonly rootRunId?: string;
120
+ }
121
+
113
122
  /** Versioned source-stage lineage used to reconstruct completed DAGs after restart. */
114
123
  export interface DurableStageTopology {
115
124
  readonly version: typeof DURABLE_STAGE_TOPOLOGY_VERSION;
116
125
  readonly stageId: string;
117
126
  readonly parentIds: readonly string[];
127
+ /** Owning run and boundary linkage for nested workflow graph reconstruction. */
128
+ readonly run?: DurableStageRunTopology;
118
129
  }
119
130
 
120
131
  /** A `ctx.stage(...)` / `ctx.task(...)` durable checkpoint or resumable session marker. */
@@ -1,11 +1,12 @@
1
1
  import type { RunSnapshot, StageSnapshot } from "../shared/store-types.js";
2
2
  import { recordStageSessionCheckpoint, type DurableStageDeps } from "../durable/stage-primitive.js";
3
+ import type { StageSessionCheckpointOptions } from "../runs/foreground/executor-types.js";
3
4
  import { recordRunTimingCheckpoint } from "../durable/run-timing.js";
4
5
 
5
6
  export interface DurableStageSessionRecorderInput {
6
7
  readonly runId: string;
7
8
  readonly deps: DurableStageDeps;
8
- readonly onStageSession?: (runId: string, snapshot: StageSnapshot) => unknown;
9
+ readonly onStageSession?: (runId: string, snapshot: StageSnapshot, options?: StageSessionCheckpointOptions) => unknown;
9
10
  /**
10
11
  * Live root-run snapshot. When present, stage-session checkpoints also
11
12
  * refresh the debounced run-level elapsed record so a durable resume can
@@ -17,15 +18,14 @@ export interface DurableStageSessionRecorderInput {
17
18
 
18
19
  export function createDurableStageSessionRecorder(
19
20
  input: DurableStageSessionRecorderInput,
20
- ): (stageRunId: string, snapshot: StageSnapshot) => void {
21
- return (stageRunId, snapshot) => {
21
+ ): (stageRunId: string, snapshot: StageSnapshot, options?: StageSessionCheckpointOptions) => Promise<void> {
22
+ return async (stageRunId, snapshot, options) => {
22
23
  if (stageRunId === input.runId) {
23
- void recordStageSessionCheckpoint(input.deps, snapshot).then(() => {
24
- if (input.runSnapshot !== undefined) {
25
- recordRunTimingCheckpoint(input.deps.backend, input.runSnapshot, { debounce: true });
26
- }
27
- }).catch(() => {});
24
+ await recordStageSessionCheckpoint(input.deps, snapshot, { force: options?.forceDurable === true });
25
+ if (input.runSnapshot !== undefined) {
26
+ recordRunTimingCheckpoint(input.deps.backend, input.runSnapshot, { debounce: options?.forceDurable !== true });
27
+ }
28
28
  }
29
- void input.onStageSession?.(stageRunId, snapshot);
29
+ await input.onStageSession?.(stageRunId, snapshot, options);
30
30
  };
31
31
  }
@@ -0,0 +1,89 @@
1
+ import { durableHash, type DurableWorkflowBackend } from "../durable/backend.js";
2
+ import { durableNestedRunSnapshots } from "../durable/completed-catalog.js";
3
+ import {
4
+ durableStageCheckpointMetadata,
5
+ recordCachedStageWithTracker,
6
+ type DurableCompletedStageCheckpoint,
7
+ type DurableStageDeps,
8
+ } from "../durable/stage-primitive.js";
9
+ import type { DurableStageRunTopology } from "../durable/types.js";
10
+ import type { GraphFrontierTracker } from "./graph-inference.js";
11
+ import type { RunSnapshot } from "../shared/store-types.js";
12
+ import type { Store } from "../shared/store.js";
13
+ import type { ParallelFailFastScope } from "../runs/foreground/executor-types.js";
14
+
15
+ export function durableRunTopology(run: RunSnapshot): DurableStageRunTopology {
16
+ return {
17
+ runId: run.id,
18
+ runName: run.name,
19
+ ...(run.parentRunId !== undefined ? { parentRunId: run.parentRunId } : {}),
20
+ ...(run.parentStageId !== undefined ? { parentStageId: run.parentStageId } : {}),
21
+ ...(run.rootRunId !== undefined ? { rootRunId: run.rootRunId } : {}),
22
+ };
23
+ }
24
+
25
+ export function createDurableStageDeps(input: {
26
+ readonly backend: DurableWorkflowBackend;
27
+ readonly run: RunSnapshot;
28
+ readonly nextCheckpointId: () => string;
29
+ readonly nextReplayKey: (stageName: string) => string;
30
+ readonly completedReplayKeys: Map<string, string>;
31
+ }): DurableStageDeps {
32
+ return {
33
+ workflowId: input.run.id,
34
+ backend: input.backend,
35
+ nextCheckpointId: input.nextCheckpointId,
36
+ nextReplayKey: input.nextReplayKey,
37
+ replayKeyForCompletedStage: (stage) => input.completedReplayKeys.get(stage.id),
38
+ runTopology: durableRunTopology(input.run),
39
+ };
40
+ }
41
+
42
+ export function createDurableCachedStageRecorder(input: {
43
+ readonly store: Store;
44
+ readonly tracker: GraphFrontierTracker;
45
+ readonly run: RunSnapshot;
46
+ readonly backend: DurableWorkflowBackend;
47
+ readonly rootBackend: DurableWorkflowBackend;
48
+ readonly completedStageReplayKeys: Map<string, string>;
49
+ }): {
50
+ readonly record: (name: string, replayKey: string, checkpoint: DurableCompletedStageCheckpoint, scope?: ParallelFailFastScope) => void;
51
+ readonly metadata: (replayKey: string) => Partial<DurableCompletedStageCheckpoint>;
52
+ } {
53
+ return {
54
+ record(name, replayKey, checkpoint, scope): void {
55
+ recordCachedStageWithTracker(
56
+ input.store, input.tracker, input.run.id, name, replayKey, checkpoint,
57
+ input.completedStageReplayKeys, scope,
58
+ );
59
+ const stage = input.store.runs().find((run) => run.id === input.run.id)?.stages
60
+ .find((candidate) => candidate.replayKey === replayKey);
61
+ if (stage !== undefined) {
62
+ input.backend.recordCheckpoint({
63
+ kind: "stage", workflowId: input.run.id,
64
+ checkpointId: `stage-replay-meta:${durableHash({ replayKey, stageId: stage.id, parentIds: stage.parentIds })}`,
65
+ name, replayKey, completedAt: Date.now(),
66
+ ...durableStageCheckpointMetadata(stage, durableRunTopology(input.run)),
67
+ });
68
+ }
69
+ if (workflowChildRunId(checkpoint) === undefined) return;
70
+ const durableRootId = input.run.rootRunId ?? input.run.id;
71
+ for (const childRun of durableNestedRunSnapshots(input.rootBackend, durableRootId)) {
72
+ if (!input.store.runs().some((candidate) => candidate.id === childRun.id)) input.store.recordRunStart(childRun);
73
+ }
74
+ },
75
+ metadata(replayKey) {
76
+ const stage = input.run.stages.find((candidate) => candidate.replayKey === replayKey);
77
+ return stage === undefined ? {} : durableStageCheckpointMetadata(stage, durableRunTopology(input.run));
78
+ },
79
+ };
80
+ }
81
+
82
+ function workflowChildRunId(checkpoint: DurableCompletedStageCheckpoint): string | undefined {
83
+ const output = checkpoint.output;
84
+ if (typeof output !== "object" || output === null || Array.isArray(output)) return undefined;
85
+ const record = output as Record<string, import("../shared/types.js").WorkflowSerializableValue>;
86
+ const runId = record["runId"];
87
+ const workflow = record["workflow"];
88
+ return typeof runId === "string" && typeof workflow === "string" ? runId : undefined;
89
+ }
@@ -39,14 +39,14 @@ import { isWorkflowDefinition, workflowDefinitionRequirementMessage } from "../r
39
39
  import { getDurableBackend } from "../durable/factory.js";
40
40
  import { classifyReturnedRunStatus } from "./run-returned-status.js";
41
41
  import { createToolPrimitive, createCheckpointIdGenerator } from "../durable/tool-primitive.js";
42
- import { createDurableStagePrimitive, createDurableTaskPrimitive, recordStageCheckpoint, createStageReplayKeyGenerator, recordCachedStageWithTracker } from "../durable/stage-primitive.js";
43
- import { inheritedRunElapsedMs } from "../durable/run-timing.js";
44
- import type { DurableCompletedStageCheckpoint } from "../durable/stage-primitive.js";
42
+ import { createDurableStagePrimitive, createDurableTaskPrimitive, recordStageCheckpoint, createStageReplayKeyGenerator } from "../durable/stage-primitive.js";
43
+ import { inheritedRunElapsedMs, recordRunTimingCheckpoint } from "../durable/run-timing.js";
45
44
  import { createDurableChildWorkflowPrimitive } from "../durable/child-primitive.js";
46
45
  import { ScopedDurableBackend, type DurableScope } from "../durable/scoped-backend.js";
47
46
  import { finalizeDurableTerminalStatus } from "./run-durable-finalize.js";
48
47
  import { createDurableStageSessionRecorder } from "./run-durable-stage-session.js";
49
48
  import type { DurableWorkflowBackend } from "../durable/backend.js";
49
+ import { createDurableCachedStageRecorder, createDurableStageDeps } from "./run-durable-topology.js";
50
50
 
51
51
  type WorkflowRunInputArgument = Parameters<typeof resolveAndValidateInputs>[1];
52
52
 
@@ -201,13 +201,11 @@ export async function run<
201
201
  const checkpointIdGenerator = createCheckpointIdGenerator();
202
202
  const stageReplayKeyGenerator = createStageReplayKeyGenerator(runId);
203
203
  const completedStageReplayKeys = new Map<string, string>();
204
- const durableStageDeps = {
205
- workflowId: runId,
206
- backend: durableBackend,
207
- nextCheckpointId: checkpointIdGenerator,
208
- nextReplayKey: stageReplayKeyGenerator,
209
- replayKeyForCompletedStage: (stage: StageSnapshot) => completedStageReplayKeys.get(stage.id),
210
- };
204
+ const durableStageDeps = createDurableStageDeps({
205
+ backend: durableBackend, run: runSnapshot,
206
+ nextCheckpointId: checkpointIdGenerator, nextReplayKey: stageReplayKeyGenerator,
207
+ completedReplayKeys: completedStageReplayKeys,
208
+ });
211
209
  const userOnStageEnd = opts.onStageEnd;
212
210
  const durableOnStageEnd = async (stageRunId: string, snapshot: StageSnapshot): Promise<void> => {
213
211
  if (stageRunId === runId && snapshot.status === "completed") {
@@ -340,18 +338,21 @@ export async function run<
340
338
 
341
339
  // Durable ctx.ui wrapper — caches completed user responses so a resumed workflow does not re-ask answered prompts.
342
340
  const durableUiDeps = { workflowId: runId, backend: durableBackend, nextCheckpointId: checkpointIdGenerator };
343
- const recordCachedStage = (name: string, replayKey: string, checkpoint: DurableCompletedStageCheckpoint): void =>
344
- recordCachedStageWithTracker(activeStore, tracker, runId, name, replayKey, checkpoint, completedStageReplayKeys);
341
+ const cachedStage = createDurableCachedStageRecorder({
342
+ store: activeStore, tracker, run: runSnapshot, backend: durableBackend,
343
+ rootBackend, completedStageReplayKeys,
344
+ });
345
345
  const durableTask = createDurableTaskPrimitive({
346
346
  workflowId: runId, backend: durableBackend,
347
347
  nextReplayKey: (stageName) => stageReplayKeyGenerator(stageName), task: taskRunners.task,
348
- recordCachedTask: (name, replayKey, checkpoint, scope) =>
349
- recordCachedStageWithTracker(activeStore, tracker, runId, name, replayKey, checkpoint, completedStageReplayKeys, scope),
348
+ recordCachedTask: cachedStage.record,
350
349
  });
351
350
  const durableWorkflow = createDurableChildWorkflowPrimitive({
352
351
  workflowId: runId, rootWorkflowId: opts.parentRun?.rootRunId ?? runId, backend: durableBackend,
353
352
  nextReplayKey: nextDurableChildReplayKey, setChildDurableScope: (scope) => { pendingChildDurableScope = scope; },
354
- recordCachedStage, workflow,
353
+ recordCachedStage: cachedStage.record,
354
+ checkpointMetadata: cachedStage.metadata,
355
+ workflow,
355
356
  });
356
357
  const ctx: WorkflowRunContext<TInputs> = {
357
358
  inputs: resolvedInputs as TInputs,
@@ -380,7 +381,7 @@ export async function run<
380
381
  workflowId: runId,
381
382
  backend: durableBackend,
382
383
  nextReplayKey: (stageName) => stageReplayKeyGenerator(stageName),
383
- recordCachedStage,
384
+ recordCachedStage: cachedStage.record,
384
385
  stage: (name, options, replayKey) => {
385
386
  const stage = runtime.stage(name, options);
386
387
  const stageId = activeStore.runs().find((r) => r.id === runId)?.stages.at(-1)?.id;
@@ -429,6 +430,7 @@ export async function run<
429
430
  const returned = classifyReturnedRunStatus(result, runSnapshot);
430
431
  const recorded = activeStore.recordRunEnd(runId, returned.status, result, returned.error, returned.metadata);
431
432
  appendRunEndWhenRecorded(opts.persistence, recorded, { runId, status: returned.status, result, ...(returned.error !== undefined ? { error: returned.error } : {}), ...(returned.metadata ?? {}), ...(runSnapshot.endedAt !== undefined ? { endedAt: runSnapshot.endedAt } : {}), ...(runSnapshot.durationMs !== undefined ? { durationMs: runSnapshot.durationMs } : {}), ts: Date.now() });
433
+ if (opts.parentRun === undefined) recordRunTimingCheckpoint(durableBackend, runSnapshot);
432
434
  durableBackend.setWorkflowStatus(runId, returned.status, undefined, returned.metadata?.resumable);
433
435
  await durableBackend.flush();
434
436
  return reconcileTerminalRunResult(runId, runSnapshot, activeStore, { status: returned.status, result, error: returned.error }, opts.onRunEnd);
@@ -20,6 +20,7 @@ import {
20
20
  } from "../durable/completed-inspection.js";
21
21
  import type { ResumableWorkflowEntry } from "../durable/types.js";
22
22
  import type { DurableWorkflowCatalogEntries } from "../durable/backend.js";
23
+ import { discoverWorkflows } from "./discovery.js";
23
24
 
24
25
  export interface DurableResumeRuntime {
25
26
  resumeDurableWorkflow(
@@ -76,6 +77,8 @@ export function createDurableResumeRuntime(
76
77
  registry: deps.registry,
77
78
  baseRunOpts: deps.baseRunOpts(options?.policy),
78
79
  durableBackend: backend,
80
+ resolveDefinition: async (name, cwd) =>
81
+ (await discoverWorkflows({ cwd: cwd ?? deps.runtimeCwd })).registry.get(name),
79
82
  ...(deps.jobs !== undefined ? { jobs: deps.jobs } : {}),
80
83
  };
81
84
  return await resumeDurableWorkflowAdapter(workflowIdOrPrefix, adapterDeps, preparedCatalog);
@@ -134,6 +134,9 @@ export function createStageControlHandle(runtime: LiveStageRuntime): StageContro
134
134
  ) ?? false;
135
135
  if (!stillActive) runtime.activeStore.recordRunPaused(runtime.runId);
136
136
  }
137
+ // Graceful pause/quit is an exact durability boundary. Force the latest
138
+ // pause-adjusted stage elapsed time even inside the normal 30s bucket.
139
+ await runtime.captureStageSessionMeta({ forceDurable: true });
137
140
  },
138
141
  async resume(message?: string) {
139
142
  runtime.throwIfStageMutationBlocked();
@@ -12,7 +12,7 @@ import type { GraphFrontierTracker } from "../../engine/graph-inference.js";
12
12
  import type { EngineStageRuntimeOptions } from "../../engine/options.js";
13
13
  import { createStageContext as createInnerStageContext, type InternalStageContext, type StageAdapters } from "./stage-runner.js";
14
14
  import type { StageControlRegistry } from "./stage-control-registry.js";
15
- import type { ParallelFailFastScope } from "./executor-types.js";
15
+ import type { ParallelFailFastScope, StageSessionCheckpointOptions } from "./executor-types.js";
16
16
  import type { WorkflowExitManager } from "./executor-exit-manager.js";
17
17
  import type { ContinuationReplayIndex } from "./executor-continuation.js";
18
18
  import { sameStringSet } from "./executor-continuation.js";
@@ -198,12 +198,15 @@ export function createWorkflowStageFactory(input: {
198
198
  };
199
199
 
200
200
  let runtime: LiveStageRuntime;
201
- const captureStageSessionMeta = (): void => {
201
+ const captureStageSessionMeta = (checkpointOptions?: StageSessionCheckpointOptions): unknown => {
202
202
  const meta = innerCtx.__sessionMeta();
203
203
  if (meta.sessionId !== undefined) stageSnapshot.sessionId = meta.sessionId;
204
204
  if (meta.sessionFile !== undefined) stageSnapshot.sessionFile = meta.sessionFile;
205
205
  if (meta.sessionId !== undefined || meta.sessionFile !== undefined) input.activeStore.recordStageSession(input.runId, stageId, meta);
206
- void input.opts.onStageSession?.(input.runId, stageSnapshot);
206
+ const pending = input.opts.onStageSession?.(input.runId, stageSnapshot, checkpointOptions);
207
+ if (checkpointOptions?.forceDurable === true) return pending;
208
+ void Promise.resolve(pending).catch(() => {});
209
+ return undefined;
207
210
  };
208
211
  const releaseLiveHandle = async (): Promise<void> => {
209
212
  if (state.liveHandleReleased) return;
@@ -3,7 +3,7 @@ import type { Store } from "../../shared/store.js";
3
3
  import type { StageContext } from "../../shared/types.js";
4
4
  import type { InternalStageContext } from "./stage-runner.js";
5
5
  import type { StageControlRegistry } from "./stage-control-registry.js";
6
- import type { ParallelFailFastScope } from "./executor-types.js";
6
+ import type { ParallelFailFastScope, StageSessionCheckpointOptions } from "./executor-types.js";
7
7
  import type { StageScheduler } from "./executor-scheduler.js";
8
8
  import type { WorkflowExitManager } from "./executor-exit-manager.js";
9
9
  import type { WorkflowFailure } from "../../shared/workflow-failures.js";
@@ -48,7 +48,7 @@ export interface LiveStageRuntime {
48
48
  unregisterStageHandle: () => void;
49
49
  dropStageControlHandle: () => void;
50
50
  unregisterWorkflowExitCleanup: () => void;
51
- readonly captureStageSessionMeta: () => void;
51
+ readonly captureStageSessionMeta: (options?: StageSessionCheckpointOptions) => unknown;
52
52
  readonly applyModelFallbackMeta: (meta: ReturnType<InternalStageContext["__modelFallbackMeta"]>) => void;
53
53
  readonly appendStageStartOnce: () => void;
54
54
  readonly finalizeStageSnapshot: () => Promise<boolean>;
@@ -24,6 +24,9 @@ export interface RunContinuationOpts {
24
24
  readonly resumeFromStageId: string;
25
25
  }
26
26
 
27
+ export interface StageSessionCheckpointOptions {
28
+ readonly forceDurable?: boolean;
29
+ }
27
30
  export interface RunOpts extends Omit<AuthoringContract.RunOpts, "adapters" | "store" | "cancellation" | "overlay" | "registry" | "stageControlRegistry" | "continuation" | "onRunStart" | "onStageStart" | "onStageEnd" | "onRunEnd" | "ui"> {
28
31
  adapters?: StageAdapters;
29
32
  /** Invocation working directory exposed to workflow definitions as ctx.cwd. */
@@ -104,7 +107,7 @@ export interface RunOpts extends Omit<AuthoringContract.RunOpts, "adapters" | "s
104
107
  onRunStart?: (snapshot: RunSnapshot) => void;
105
108
  onStageStart?: (runId: string, snapshot: StageSnapshot) => void;
106
109
  onStageEnd?: (runId: string, snapshot: StageSnapshot) => unknown;
107
- onStageSession?: (runId: string, snapshot: StageSnapshot) => unknown;
110
+ onStageSession?: (runId: string, snapshot: StageSnapshot, options?: StageSessionCheckpointOptions) => unknown;
108
111
  onRunEnd?: (runId: string, status: RunStatus, result?: WorkflowOutputValues, error?: string, exitReason?: string) => void;
109
112
  }
110
113
 
@@ -103,7 +103,6 @@ function durableWorkflowSession(
103
103
  kind: "durable" | "completed",
104
104
  ): WorkflowResumeSelectorItem {
105
105
  const checkpointText = `${entry.completedCheckpoints} checkpoints`;
106
- const promptText = `${entry.pendingPrompts} prompts`;
107
106
  const presentation = workflowStatusPresentation(entry.status, kind);
108
107
  return {
109
108
  result: { kind, workflowId: entry.workflowId },
@@ -114,8 +113,8 @@ function durableWorkflowSession(
114
113
  created: new Date(entry.createdAt),
115
114
  modified: new Date(entry.updatedAt),
116
115
  messageCount: entry.completedCheckpoints,
117
- firstMessage: `${entry.name} ${presentation.label} ${checkpointText} ${promptText}`,
118
- allMessagesText: `${entry.workflowId} ${entry.name} ${presentation.label} ${checkpointText} ${promptText}`,
116
+ firstMessage: `${entry.name} ${presentation.label} ${checkpointText}`,
117
+ allMessagesText: `${entry.workflowId} ${entry.name} ${presentation.label} ${checkpointText}`,
119
118
  ...(presentation.color !== undefined ? { messageColor: presentation.color } : {}),
120
119
  },
121
120
  };
@@ -1 +1 @@
1
- {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAanE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,IAAI;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;IAC5C,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnE;AAID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAE1E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+J9C;AAED,wBAAgB,SAAS,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,GAAG,IAAI,CAsLhE"}
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAanE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,IAAI;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;IAC5C,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnE;AAID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAE1E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+J9C;AAED,wBAAgB,SAAS,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,GAAG,IAAI,CAwLhE"}
package/dist/cli/args.js CHANGED
@@ -367,6 +367,8 @@ ${chalk.bold("Environment Variables:")}
367
367
  CLOUDFLARE_API_KEY - Cloudflare API token (Workers AI and AI Gateway)
368
368
  CLOUDFLARE_ACCOUNT_ID - Cloudflare account id (required for both)
369
369
  CLOUDFLARE_GATEWAY_ID - Cloudflare AI Gateway slug (required for AI Gateway)
370
+ QWEN_TOKEN_PLAN_API_KEY - Qwen Token Plan API key (international region)
371
+ QWEN_TOKEN_PLAN_CN_API_KEY - Qwen Token Plan API key (China region)
370
372
  XIAOMI_API_KEY - Xiaomi MiMo API key (api.xiaomimimo.com billing)
371
373
  XIAOMI_TOKEN_PLAN_CN_API_KEY - Xiaomi MiMo Token Plan API key (China region)
372
374
  XIAOMI_TOKEN_PLAN_AMS_API_KEY - Xiaomi MiMo Token Plan API key (Amsterdam region)