@agentswf/engine 0.1.0-beta.2 → 0.1.0-beta.3

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 (68) hide show
  1. package/package.json +5 -5
  2. package/src/allowance-command.ts +29 -7
  3. package/src/attempt-ending.ts +23 -5
  4. package/src/attempt-output.ts +48 -18
  5. package/src/attempt-view.ts +25 -15
  6. package/src/commands.ts +176 -0
  7. package/src/control-plane.ts +72 -21
  8. package/src/coordinator-port.ts +29 -0
  9. package/src/coordinator-prompt.ts +237 -0
  10. package/src/coordinator-socket.ts +236 -0
  11. package/src/deadlines.ts +47 -10
  12. package/src/decisions/directory.ts +8 -6
  13. package/src/duration.ts +29 -0
  14. package/src/emit-command.ts +130 -0
  15. package/src/emit.ts +246 -0
  16. package/src/files.ts +11 -1
  17. package/src/here.ts +8 -2
  18. package/src/hold-run-lock.fixture.ts +8 -0
  19. package/src/holder-command.ts +297 -0
  20. package/src/inbox-command.ts +727 -0
  21. package/src/init-command.ts +27 -0
  22. package/src/init-template/AGENTS.md.template +1 -1
  23. package/src/init-template/hello/workflow.test.ts.template +2 -2
  24. package/src/init-template/hello/workflow.ts.template +16 -20
  25. package/src/keep-alive.ts +40 -0
  26. package/src/logs-command.ts +104 -20
  27. package/src/machine.ts +12 -1
  28. package/src/mailbox.ts +977 -0
  29. package/src/message-operation.ts +26 -3
  30. package/src/messaging/messaging.ts +458 -65
  31. package/src/messaging/routes.ts +10 -3
  32. package/src/messaging/text.ts +8 -5
  33. package/src/operation-liveness.ts +54 -8
  34. package/src/operator-cli.ts +290 -119
  35. package/src/operator-runtime.ts +5 -2
  36. package/src/progress-view.ts +49 -7
  37. package/src/projects.ts +57 -0
  38. package/src/result-slots.ts +43 -19
  39. package/src/result-validation.ts +18 -27
  40. package/src/run-command.ts +36 -32
  41. package/src/run-commands.ts +13 -2
  42. package/src/run-lock.ts +123 -0
  43. package/src/run-prepare.ts +94 -22
  44. package/src/run-state.ts +125 -6
  45. package/src/run-usage.ts +1 -1
  46. package/src/run-view.ts +0 -9
  47. package/src/runs-command.ts +46 -17
  48. package/src/runs.ts +142 -23
  49. package/src/sandboxes.ts +8 -2
  50. package/src/simple-input.ts +258 -0
  51. package/src/socket-exchange.ts +26 -0
  52. package/src/sources.ts +70 -0
  53. package/src/stage-ledger.ts +88 -13
  54. package/src/stage-plan.ts +23 -0
  55. package/src/stop-crashed.ts +39 -0
  56. package/src/test-command.ts +32 -0
  57. package/src/testing.ts +71 -3
  58. package/src/tick-command.ts +87 -0
  59. package/src/tools.ts +636 -0
  60. package/src/wake.ts +264 -0
  61. package/src/workflow-loader.ts +32 -22
  62. package/src/workflow-runner.ts +1210 -77
  63. package/src/workflow-testing/coordinator.typecheck.ts +55 -0
  64. package/src/workflow-testing/coordinators.ts +137 -0
  65. package/src/workflow-testing/host.ts +61 -1
  66. package/src/workflow-testing/index.ts +488 -33
  67. package/src/workflow-testing/script.ts +72 -2
  68. package/src/workflow-testing/workflow-testing.typecheck.ts +19 -2
@@ -2,6 +2,7 @@ import type { HarnessTurn, HarnessTurnOutcome } from "@agentswf/harness/adapter"
2
2
  import { scheduleAt } from "./deadlines";
3
3
  import { messageOf } from "./errors";
4
4
  import {
5
+ CEILING_GRACE_MS,
5
6
  DEFAULT_LIVENESS_POLICY,
6
7
  type LivenessEvent,
7
8
  type LivenessPolicy,
@@ -20,6 +21,10 @@ import {
20
21
  export async function superviseMessageOperation(options: {
21
22
  /** Moves only later, as the operation takes questions whose askers wait longer. */
22
23
  deadline(): number;
24
+ /** The deadlines around it, which a wait on an outside participant still ends at. */
25
+ ceiling?: number;
26
+ /** A wait on an outside participant ended: its deadline moves out by its length, to `later`. */
27
+ extended?(later: number): void;
23
28
  start(): Promise<HarnessTurn>;
24
29
  messages: OperationMessages;
25
30
  onStop(cancel: (stop: OperationStop) => Promise<void>): () => void;
@@ -60,11 +65,19 @@ export async function superviseMessageOperation(options: {
60
65
  cleanupUnresolved: false,
61
66
  charges,
62
67
  ...(deliveredAt === undefined ? {} : { deliveredAt }),
63
- settledAt: kind === "timed-out" ? Math.min(now(), options.deadline()) : now(),
68
+ settledAt:
69
+ kind === "timed-out"
70
+ ? Math.min(now(), outsideSince === undefined ? options.deadline() : ceiling)
71
+ : now(),
64
72
  });
73
+ const ceiling = options.ceiling ?? Number.POSITIVE_INFINITY;
74
+ /** While it awaits an outside participant: its deadline does not count, only the ceiling. */
75
+ let outsideSince: number | undefined;
76
+ const limit = () =>
77
+ outsideSince === undefined ? options.deadline() : ceiling + CEILING_GRACE_MS;
65
78
  /** Until something changes, a stop, the deadline, or `until`, whichever comes first. */
66
79
  const nextChange = async (until = Number.POSITIVE_INFINITY) => {
67
- const cancel = scheduleAt({ unixMilliseconds: Math.min(options.deadline(), until) }, changed);
80
+ const cancel = scheduleAt({ unixMilliseconds: Math.min(limit(), until) }, changed);
68
81
  try {
69
82
  await wake.promise;
70
83
  } finally {
@@ -72,7 +85,7 @@ export async function superviseMessageOperation(options: {
72
85
  wake = Promise.withResolvers<void>();
73
86
  }
74
87
  };
75
- const stopped = () => stop !== undefined || now() >= options.deadline();
88
+ const stopped = () => stop !== undefined || now() >= limit();
76
89
  /** Aborts a delivery not yet dispatched when the operation is stopped. */
77
90
  let acquisition: AbortController | undefined;
78
91
 
@@ -194,8 +207,16 @@ export async function superviseMessageOperation(options: {
194
207
  while (next.kind === "wait" && !stopped()) {
195
208
  options.phase?.("awaiting-reply", next.peer, next.until);
196
209
  emit("awaiting-reply", undefined, next.until, next.peer);
210
+ if (options.messages.awaiting()?.outside) outsideSince = now();
197
211
  // An answer, a failure or a question continues it; nothing else does.
198
212
  while (!stopped() && options.messages.pending() !== "continues") await nextChange();
213
+ // Stopped while it waited: the reason says the deadline around it ended the wait.
214
+ if (stopped()) break;
215
+ if (outsideSince !== undefined) {
216
+ const waited = now() - outsideSince;
217
+ outsideSince = undefined;
218
+ options.extended?.(Math.min(ceiling, options.deadline() + waited));
219
+ }
199
220
  next = options.messages.turnEnded();
200
221
  }
201
222
  if (stopped()) break;
@@ -217,6 +238,8 @@ export async function superviseMessageOperation(options: {
217
238
  );
218
239
  }
219
240
  if (stop) return ended(stop.kind, stop.reason);
241
+ if (outsideSince !== undefined)
242
+ return ended("timed-out", "a deadline around it passed while it waited");
220
243
  return ended("timed-out", "message operation deadline exceeded");
221
244
  })();
222
245
  } catch (error) {