@agentswf/engine 0.1.0-beta.4 → 0.1.0

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 (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +16 -0
  3. package/package.json +13 -9
  4. package/src/accounting/format.ts +4 -3
  5. package/src/accounting/spent.ts +128 -0
  6. package/src/accounting/summary.ts +40 -32
  7. package/src/agent-cli/cli.ts +35 -22
  8. package/src/agent-cli/client.ts +1 -27
  9. package/src/allowance-command.ts +8 -10
  10. package/src/attempt-ending.ts +5 -7
  11. package/src/attempt-output.ts +15 -32
  12. package/src/attempt-view.ts +34 -33
  13. package/src/author-typebox.ts +13 -0
  14. package/src/client/checks.ts +94 -0
  15. package/src/client/exported.ts +17 -0
  16. package/src/client/index.ts +122 -0
  17. package/src/client/locate.ts +34 -0
  18. package/src/client/published.ts +3 -0
  19. package/src/client/runs.ts +337 -0
  20. package/src/command-line.ts +64 -0
  21. package/src/commands.ts +7 -1
  22. package/src/control-plane.ts +41 -11
  23. package/src/coordinator-prompt.ts +4 -3
  24. package/src/coordinator-socket.ts +41 -33
  25. package/src/deadlines.ts +40 -7
  26. package/src/decisions/directory.ts +51 -40
  27. package/src/decisions/fake.ts +1 -1
  28. package/src/decisions/openrouter.ts +4 -2
  29. package/src/decisions/seam.ts +4 -4
  30. package/src/display-path.ts +3 -3
  31. package/src/duration.ts +43 -27
  32. package/src/emit-command.ts +88 -58
  33. package/src/emit.ts +254 -56
  34. package/src/event-ids.ts +31 -0
  35. package/src/files.ts +44 -4
  36. package/src/hand-over.ts +150 -0
  37. package/src/help/allowance.txt +4 -3
  38. package/src/help/emit.txt +18 -6
  39. package/src/help/inbox.txt +6 -4
  40. package/src/help/logs.txt +9 -6
  41. package/src/help/open.txt +29 -0
  42. package/src/help/reply.txt +6 -8
  43. package/src/help/run.txt +30 -11
  44. package/src/help/runs.txt +4 -2
  45. package/src/help/tick.txt +9 -4
  46. package/src/herdr-placement.ts +3 -33
  47. package/src/herdr-run-session.ts +7 -15
  48. package/src/herdr-workspace-marks.ts +7 -17
  49. package/src/holder-command.ts +56 -133
  50. package/src/in-lines.ts +28 -0
  51. package/src/inbox-command.ts +40 -57
  52. package/src/index.ts +1 -1
  53. package/src/init-command.ts +8 -17
  54. package/src/init-template/hello/workflow.test.ts.template +3 -3
  55. package/src/init-template/hello/workflow.ts.template +5 -4
  56. package/src/jsonl.ts +10 -6
  57. package/src/keep-alive.ts +15 -12
  58. package/src/logs-command.ts +128 -47
  59. package/src/message-operation.ts +6 -3
  60. package/src/messaging/limits.ts +4 -4
  61. package/src/messaging/messaging.ts +31 -28
  62. package/src/messaging/routes.ts +1 -1
  63. package/src/messaging/text.ts +9 -7
  64. package/src/open-command.ts +770 -0
  65. package/src/operation-events.ts +4 -6
  66. package/src/operation-liveness.ts +19 -4
  67. package/src/operator-cli.ts +224 -94
  68. package/src/operator-runtime.ts +29 -7
  69. package/src/ops.ts +270 -0
  70. package/src/pane-layout.ts +105 -59
  71. package/src/progress-view.ts +10 -10
  72. package/src/project-engine.ts +79 -0
  73. package/src/projects.ts +13 -2
  74. package/src/refusals.ts +119 -0
  75. package/src/result-slots.ts +11 -31
  76. package/src/result-validation.ts +2 -2
  77. package/src/run-command.ts +45 -28
  78. package/src/run-commands.ts +43 -115
  79. package/src/run-event-log.ts +1 -1
  80. package/src/run-lines.ts +159 -0
  81. package/src/run-lock.ts +57 -1
  82. package/src/{stage-plan.ts → run-policy/stage-plan.ts} +46 -42
  83. package/src/run-policy/stages.ts +113 -0
  84. package/src/run-policy/waits.ts +452 -0
  85. package/src/run-prepare.ts +205 -43
  86. package/src/run-read.ts +109 -41
  87. package/src/run-state.ts +170 -50
  88. package/src/run-text.ts +54 -0
  89. package/src/run-unreachable.ts +18 -0
  90. package/src/run-usage.ts +18 -12
  91. package/src/run-view.ts +81 -17
  92. package/src/runs-command.ts +83 -63
  93. package/src/runs.ts +310 -212
  94. package/src/sandbox-homes.ts +65 -13
  95. package/src/sandboxes.ts +182 -28
  96. package/src/session-lines.ts +93 -0
  97. package/src/skills/run-skills.ts +8 -1
  98. package/src/sources.ts +28 -29
  99. package/src/spend.ts +333 -0
  100. package/src/stage-ledger.ts +119 -131
  101. package/src/stop-crashed.ts +6 -5
  102. package/src/stopped.ts +4 -4
  103. package/src/test-command.ts +36 -14
  104. package/src/testing/operation-events.ts +3 -23
  105. package/src/testing.ts +73 -26
  106. package/src/tick-command.ts +145 -15
  107. package/src/tools.ts +25 -16
  108. package/src/turn-ends.ts +37 -0
  109. package/src/waits.ts +651 -0
  110. package/src/wake.ts +84 -54
  111. package/src/workflow-loader.ts +54 -4
  112. package/src/workflow-runner.ts +805 -580
  113. package/src/workflow-test-preload.ts +4 -1
  114. package/src/workflow-testing/coordinators.ts +3 -3
  115. package/src/workflow-testing/fake-client.ts +387 -0
  116. package/src/workflow-testing/host.ts +121 -53
  117. package/src/workflow-testing/index.ts +33 -842
  118. package/src/workflow-testing/run-test.ts +1128 -0
  119. package/src/workflow-testing/script.ts +74 -45
  120. package/src/hold-run-lock.fixture.ts +0 -8
  121. package/src/mailbox.ts +0 -990
  122. package/src/workflow-testing/coordinator.typecheck.ts +0 -54
  123. package/src/workflow-testing/workflow-testing.typecheck.ts +0 -64
@@ -1,10 +1,11 @@
1
1
  import { appendFile, mkdir } from "node:fs/promises";
2
- import { dirname, join } from "node:path";
2
+ import { dirname } from "node:path";
3
3
  import {
4
4
  OPERATION_LIVENESS_KINDS,
5
5
  OPERATION_LIVENESS_RECORD_VERSION,
6
6
  type OperationLivenessRecord,
7
7
  } from "@agentswf/contract/records";
8
+ import { liveFile } from "./ops";
8
9
 
9
10
  export type OperationEvent = Pick<
10
11
  OperationLivenessRecord,
@@ -30,7 +31,7 @@ export function createOperationEvents(
30
31
  record(event: OperationEvent): void;
31
32
  close(): Promise<void>;
32
33
  } {
33
- const path = eventFile(runDir, operationId);
34
+ const path = liveFile(runDir, operationId);
34
35
  const write = options.write ?? append;
35
36
  const schedule =
36
37
  options.schedule ??
@@ -144,7 +145,7 @@ export function createOperationEvents(
144
145
  };
145
146
  }
146
147
 
147
- function validEvent(value: OperationEvent): boolean {
148
+ export function validEvent(value: OperationEvent): boolean {
148
149
  return (
149
150
  typeof value.kind === "string" &&
150
151
  (OPERATION_LIVENESS_KINDS as readonly string[]).includes(value.kind) &&
@@ -173,9 +174,6 @@ function bound(value: number | undefined, fallback: number, minimum: number): nu
173
174
  throw new Error(`diagnostic bound must be an integer >= ${minimum}`);
174
175
  return actual;
175
176
  }
176
- function eventFile(runDir: string, operationId: string): string {
177
- return join(runDir, "calls", operationId, "liveness.jsonl");
178
- }
179
177
  async function append(path: string, line: string): Promise<void> {
180
178
  await mkdir(dirname(path), { recursive: true });
181
179
  await appendFile(path, line, { mode: 0o600 });
@@ -79,7 +79,7 @@ export type SupervisedOutcome = {
79
79
  value?: unknown;
80
80
  reason: string;
81
81
  cleanupUnresolved: boolean;
82
- charges: number[];
82
+ reportedCosts: number[];
83
83
  deliveredAt?: number;
84
84
  settledAt: number;
85
85
  /** A failed turn whose harness showed it cannot sign in. */
@@ -91,6 +91,8 @@ export type OperationStop = { kind: "cancelled" | "timed-out"; reason: string };
91
91
  type Options = {
92
92
  operationId: string;
93
93
  agentId: string;
94
+ /** Why its `op.json` wasn't written: the operation fails as it opens, before anything runs. */
95
+ unrecorded?: string;
94
96
  question: string;
95
97
  schema: JsonSchema;
96
98
  /** Absent when nothing bounds it. */
@@ -113,6 +115,8 @@ type Options = {
113
115
  messages?: OperationMessages;
114
116
  /** Once, when the harness first accepts the operation. */
115
117
  delivered?(at: number): void;
118
+ /** Keeps what its turn shows when it ends without an answer, before the turn is released. */
119
+ keepScreen?(turn: HarnessTurn): Promise<void>;
116
120
  policy?: LivenessPolicy;
117
121
  now?: () => number;
118
122
  schedule?: (at: number, action: () => void) => () => void;
@@ -177,7 +181,7 @@ export async function superviseOperation(options: Options): Promise<SupervisedOu
177
181
  | Promise<import("@agentswf/harness/adapter").HarnessReleaseDisposition>
178
182
  | undefined;
179
183
  let answerReleaseDeadline: number | undefined;
180
- const charges: number[] = [];
184
+ const reportedCosts: number[] = [];
181
185
  const emit = (
182
186
  kind: OperationLivenessKind,
183
187
  reason?: string,
@@ -262,6 +266,7 @@ export async function superviseOperation(options: Options): Promise<SupervisedOu
262
266
  });
263
267
  let slot: Awaited<ReturnType<ResultSlotRegistry["open"]>>;
264
268
  try {
269
+ if (options.unrecorded !== undefined) throw new Error(options.unrecorded);
265
270
  slot = await options.slots.open({
266
271
  operationId: options.operationId,
267
272
  agentId: options.agentId,
@@ -327,7 +332,7 @@ export async function superviseOperation(options: Options): Promise<SupervisedOu
327
332
  (outcome) => {
328
333
  if (!valid()) return;
329
334
  native = outcome;
330
- charges.push(...outcome.chargesUsd);
335
+ reportedCosts.push(...outcome.reportedCostsUsd);
331
336
  if (
332
337
  result === undefined &&
333
338
  outcome.state === "completed" &&
@@ -608,6 +613,16 @@ export async function superviseOperation(options: Options): Promise<SupervisedOu
608
613
  }
609
614
  }
610
615
  if (result.kind === "answered" && !held) result.cleanupUnresolved = true;
616
+ if (
617
+ held &&
618
+ options.keepScreen &&
619
+ result.kind !== "answered" &&
620
+ (stop?.kind ?? result.kind) !== "cancelled"
621
+ ) {
622
+ await options.keepScreen(held);
623
+ // The read took from the release's own time; it gets it back.
624
+ releaseDeadline = now() + Math.min(policy.releaseMs, 5000);
625
+ }
611
626
  if (held) {
612
627
  const stopping = stop !== undefined;
613
628
  if (stopping)
@@ -690,7 +705,7 @@ export async function superviseOperation(options: Options): Promise<SupervisedOu
690
705
  kind,
691
706
  reason,
692
707
  cleanupUnresolved: false,
693
- charges,
708
+ reportedCosts,
694
709
  ...(deliveredAt === undefined ? {} : { deliveredAt }),
695
710
  settledAt:
696
711
  kind === "timed-out"