@earendil-works/pi-durable 1.2.0 → 1.4.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 (142) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +128 -3
  3. package/dist/codemode/codemode.d.ts.map +1 -1
  4. package/dist/codemode/codemode.js +12 -4
  5. package/dist/codemode/codemode.js.map +1 -1
  6. package/dist/codemode/models.d.ts.map +1 -1
  7. package/dist/codemode/models.js +2 -0
  8. package/dist/codemode/models.js.map +1 -1
  9. package/dist/documents.d.ts +1 -1
  10. package/dist/documents.d.ts.map +1 -1
  11. package/dist/documents.js.map +1 -1
  12. package/dist/env/index.d.ts +1 -0
  13. package/dist/env/index.d.ts.map +1 -1
  14. package/dist/env/index.js.map +1 -1
  15. package/dist/env/node.d.ts.map +1 -1
  16. package/dist/env/node.js +11 -3
  17. package/dist/env/node.js.map +1 -1
  18. package/dist/harness/agent.d.ts +13 -2
  19. package/dist/harness/agent.d.ts.map +1 -1
  20. package/dist/harness/agent.js +39 -5
  21. package/dist/harness/agent.js.map +1 -1
  22. package/dist/harness/compaction.d.ts +3 -1
  23. package/dist/harness/compaction.d.ts.map +1 -1
  24. package/dist/harness/compaction.js +19 -4
  25. package/dist/harness/compaction.js.map +1 -1
  26. package/dist/harness/context.d.ts +5 -0
  27. package/dist/harness/context.d.ts.map +1 -1
  28. package/dist/harness/context.js +46 -12
  29. package/dist/harness/context.js.map +1 -1
  30. package/dist/harness/generation.d.ts.map +1 -1
  31. package/dist/harness/generation.js +67 -27
  32. package/dist/harness/generation.js.map +1 -1
  33. package/dist/harness/harness.d.ts +5 -2
  34. package/dist/harness/harness.d.ts.map +1 -1
  35. package/dist/harness/harness.js +78 -13
  36. package/dist/harness/harness.js.map +1 -1
  37. package/dist/harness/inbox.d.ts +2 -2
  38. package/dist/harness/inbox.d.ts.map +1 -1
  39. package/dist/harness/inbox.js +3 -3
  40. package/dist/harness/inbox.js.map +1 -1
  41. package/dist/harness/prompt.d.ts +1 -1
  42. package/dist/harness/prompt.d.ts.map +1 -1
  43. package/dist/harness/prompt.js +1 -1
  44. package/dist/harness/prompt.js.map +1 -1
  45. package/dist/harness/scheduler.d.ts +55 -10
  46. package/dist/harness/scheduler.d.ts.map +1 -1
  47. package/dist/harness/scheduler.js +617 -124
  48. package/dist/harness/scheduler.js.map +1 -1
  49. package/dist/harness/submissions.d.ts +7 -2
  50. package/dist/harness/submissions.d.ts.map +1 -1
  51. package/dist/harness/submissions.js +48 -17
  52. package/dist/harness/submissions.js.map +1 -1
  53. package/dist/harness/task-graph.d.ts +18 -1
  54. package/dist/harness/task-graph.d.ts.map +1 -1
  55. package/dist/harness/task-graph.js +50 -11
  56. package/dist/harness/task-graph.js.map +1 -1
  57. package/dist/harness/telemetry.d.ts +307 -0
  58. package/dist/harness/telemetry.d.ts.map +1 -0
  59. package/dist/harness/telemetry.js +136 -0
  60. package/dist/harness/telemetry.js.map +1 -0
  61. package/dist/harness/tool.d.ts.map +1 -1
  62. package/dist/harness/tool.js +54 -8
  63. package/dist/harness/tool.js.map +1 -1
  64. package/dist/harness/types.d.ts +110 -15
  65. package/dist/harness/types.d.ts.map +1 -1
  66. package/dist/harness/types.js.map +1 -1
  67. package/dist/harness/util.d.ts +4 -0
  68. package/dist/harness/util.d.ts.map +1 -1
  69. package/dist/harness/util.js +4 -0
  70. package/dist/harness/util.js.map +1 -1
  71. package/dist/index.d.ts +6 -4
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +3 -2
  74. package/dist/index.js.map +1 -1
  75. package/dist/session/session.d.ts +17 -6
  76. package/dist/session/session.d.ts.map +1 -1
  77. package/dist/session/session.js +64 -32
  78. package/dist/session/session.js.map +1 -1
  79. package/dist/session/transaction.d.ts +5 -1
  80. package/dist/session/transaction.d.ts.map +1 -1
  81. package/dist/session/transaction.js +26 -1
  82. package/dist/session/transaction.js.map +1 -1
  83. package/dist/storage/indexeddb.d.ts +60 -0
  84. package/dist/storage/indexeddb.d.ts.map +1 -0
  85. package/dist/storage/indexeddb.js +831 -0
  86. package/dist/storage/indexeddb.js.map +1 -0
  87. package/dist/storage/jsonl/storage.d.ts +16 -0
  88. package/dist/storage/jsonl/storage.d.ts.map +1 -1
  89. package/dist/storage/memory.js +1 -1
  90. package/dist/storage/memory.js.map +1 -1
  91. package/dist/storage/sqlite/cloudflare.d.ts +6 -43
  92. package/dist/storage/sqlite/cloudflare.d.ts.map +1 -1
  93. package/dist/storage/sqlite/cloudflare.js +6 -101
  94. package/dist/storage/sqlite/cloudflare.js.map +1 -1
  95. package/dist/storage/sqlite/database.d.ts +1 -36
  96. package/dist/storage/sqlite/database.d.ts.map +1 -1
  97. package/dist/storage/sqlite/database.js.map +1 -1
  98. package/dist/storage/sqlite/index.d.ts +2 -2
  99. package/dist/storage/sqlite/index.d.ts.map +1 -1
  100. package/dist/storage/sqlite/index.js.map +1 -1
  101. package/dist/storage/sqlite/migrations.d.ts +7 -6
  102. package/dist/storage/sqlite/migrations.d.ts.map +1 -1
  103. package/dist/storage/sqlite/migrations.js +116 -106
  104. package/dist/storage/sqlite/migrations.js.map +1 -1
  105. package/dist/storage/sqlite/node.d.ts +6 -39
  106. package/dist/storage/sqlite/node.d.ts.map +1 -1
  107. package/dist/storage/sqlite/node.js +8 -175
  108. package/dist/storage/sqlite/node.js.map +1 -1
  109. package/dist/storage/sqlite/schema.d.ts +45 -0
  110. package/dist/storage/sqlite/schema.d.ts.map +1 -0
  111. package/dist/storage/sqlite/schema.js +50 -0
  112. package/dist/storage/sqlite/schema.js.map +1 -0
  113. package/dist/storage/sqlite/storage.d.ts +10 -2
  114. package/dist/storage/sqlite/storage.d.ts.map +1 -1
  115. package/dist/storage/sqlite/storage.js +46 -43
  116. package/dist/storage/sqlite/storage.js.map +1 -1
  117. package/dist/testing/storage-conformance.d.ts.map +1 -1
  118. package/dist/testing/storage-conformance.js +17 -0
  119. package/dist/testing/storage-conformance.js.map +1 -1
  120. package/dist/timers.d.ts +21 -0
  121. package/dist/timers.d.ts.map +1 -0
  122. package/dist/timers.js +72 -0
  123. package/dist/timers.js.map +1 -0
  124. package/dist/tools/image-processor.d.ts +4 -1
  125. package/dist/tools/image-processor.d.ts.map +1 -1
  126. package/dist/tools/image-processor.js +8 -18
  127. package/dist/tools/image-processor.js.map +1 -1
  128. package/dist/tools/read.d.ts.map +1 -1
  129. package/dist/tools/read.js +1 -1
  130. package/dist/tools/read.js.map +1 -1
  131. package/dist/truncate.d.ts +3 -2
  132. package/dist/truncate.d.ts.map +1 -1
  133. package/dist/truncate.js +4 -34
  134. package/dist/truncate.js.map +1 -1
  135. package/dist/types.d.ts +130 -9
  136. package/dist/types.d.ts.map +1 -1
  137. package/dist/types.js.map +1 -1
  138. package/package.json +15 -5
  139. package/dist/harness/output.d.ts +0 -69
  140. package/dist/harness/output.d.ts.map +0 -1
  141. package/dist/harness/output.js +0 -318
  142. package/dist/harness/output.js.map +0 -1
@@ -0,0 +1,307 @@
1
+ /** Durable's content-free span, event, and metric vocabulary. IDs address durable records, never content. */
2
+ export declare const DURABLE_TELEMETRY_SCHEMA: {
3
+ readonly version: 1;
4
+ readonly spans: {
5
+ readonly "pi.durable.submit": {
6
+ readonly description: "Public submission admission and its commit. Inputs start root traces linked to their callers; writes are children. Internal admissions emit phase events only.";
7
+ readonly parents: {
8
+ readonly kind: "any";
9
+ };
10
+ readonly startAttributes: {
11
+ readonly "submission.type": {
12
+ readonly type: "string";
13
+ readonly required: true;
14
+ readonly values: readonly ["input", "write"];
15
+ readonly description: "Submission type.";
16
+ };
17
+ readonly "conversation.id": {
18
+ readonly type: "number";
19
+ readonly required: true;
20
+ readonly description: "Conversation ID.";
21
+ readonly cardinality: "high";
22
+ };
23
+ };
24
+ readonly endAttributes: {
25
+ readonly "submission.id": {
26
+ readonly type: "number";
27
+ readonly description: "Admitted submission ID.";
28
+ readonly cardinality: "high";
29
+ };
30
+ readonly result: {
31
+ readonly type: "string";
32
+ readonly values: readonly ["queued", "placed", "done"];
33
+ readonly description: "Admission result; stale writes report done.";
34
+ };
35
+ };
36
+ readonly events: {
37
+ "pi.durable.entry": {
38
+ readonly description: "A transcript entry was committed; content remains in the transcript.";
39
+ readonly attributes: {
40
+ readonly "entry.id": {
41
+ readonly type: "number";
42
+ readonly required: true;
43
+ readonly description: "Transcript entry ID.";
44
+ readonly cardinality: "high";
45
+ };
46
+ readonly "entry.kind": {
47
+ readonly type: "string";
48
+ readonly required: true;
49
+ readonly description: "Entry kind.";
50
+ };
51
+ };
52
+ };
53
+ "pi.durable.submission": {
54
+ readonly description: "A submission was settled.";
55
+ readonly attributes: {
56
+ readonly "submission.id": {
57
+ readonly type: "number";
58
+ readonly required: true;
59
+ readonly description: "Submission ID.";
60
+ readonly cardinality: "high";
61
+ };
62
+ readonly status: {
63
+ readonly type: "string";
64
+ readonly required: true;
65
+ readonly values: readonly ["done", "unanswered"];
66
+ readonly description: "Settlement.";
67
+ };
68
+ readonly "answer.entry_id": {
69
+ readonly type: "number";
70
+ readonly required: false;
71
+ readonly description: "Answer entry ID.";
72
+ readonly cardinality: "high";
73
+ };
74
+ };
75
+ };
76
+ "pi.durable.report": {
77
+ readonly description: "A report was raised; no error payload is recorded.";
78
+ readonly attributes: {
79
+ readonly type: {
80
+ readonly type: "string";
81
+ readonly required: true;
82
+ readonly description: "ReportInfo type.";
83
+ readonly values: readonly ["session_failed", "task_faulted", "task_parked", "migration_failed", "task_outdated", "task_error", "extension_error", "host_error", "listener_error"];
84
+ };
85
+ readonly reason: {
86
+ readonly type: "string";
87
+ readonly required: false;
88
+ readonly description: "Fixed report reason, when present.";
89
+ readonly values: readonly ["threw", "restart_limit", "missing_task", "incompatible_task"];
90
+ };
91
+ readonly extension: {
92
+ readonly type: "string";
93
+ readonly required: false;
94
+ readonly description: "Registered extension name, when present.";
95
+ };
96
+ readonly "task.id": {
97
+ readonly type: "number";
98
+ readonly required: false;
99
+ readonly description: "Task ID, when present.";
100
+ readonly cardinality: "high";
101
+ };
102
+ };
103
+ };
104
+ };
105
+ readonly status: {
106
+ readonly default: "ok";
107
+ readonly errorWhen: "Admission failed.";
108
+ };
109
+ };
110
+ readonly "pi.durable.phase": {
111
+ readonly description: "One task phase invocation, including its decision commit, never a wait or restart.";
112
+ readonly parents: {
113
+ readonly kind: "any";
114
+ };
115
+ readonly startAttributes: {
116
+ readonly "task.id": {
117
+ readonly type: "number";
118
+ readonly required: true;
119
+ readonly description: "Task ID.";
120
+ readonly cardinality: "high";
121
+ };
122
+ readonly "task.name": {
123
+ readonly type: "string";
124
+ readonly required: true;
125
+ readonly description: "Registered task name.";
126
+ };
127
+ readonly phase: {
128
+ readonly type: "string";
129
+ readonly required: true;
130
+ readonly description: "Invoked checkpoint phase.";
131
+ };
132
+ readonly kind: {
133
+ readonly type: "string";
134
+ readonly required: true;
135
+ readonly values: readonly ["run", "abort"];
136
+ readonly description: "Invocation kind.";
137
+ };
138
+ readonly attempt: {
139
+ readonly type: "number";
140
+ readonly required: false;
141
+ readonly description: "Checkpoint attempt, when present.";
142
+ };
143
+ readonly resumed: {
144
+ readonly type: "boolean";
145
+ readonly required: true;
146
+ readonly description: "First invocation of a task loaded in this process.";
147
+ };
148
+ };
149
+ readonly endAttributes: {
150
+ readonly outcome: {
151
+ readonly type: "string";
152
+ readonly description: "next=<phase>, waiting, sleeping, done, faulted, or aborted.";
153
+ };
154
+ readonly "tool.name": {
155
+ readonly type: "string";
156
+ readonly description: "Called tool name.";
157
+ };
158
+ readonly "tool.call_id": {
159
+ readonly type: "string";
160
+ readonly description: "Transcript tool call ID.";
161
+ readonly cardinality: "high";
162
+ };
163
+ };
164
+ readonly events: {
165
+ readonly "pi.durable.entry": {
166
+ readonly description: "A transcript entry was committed; content remains in the transcript.";
167
+ readonly attributes: {
168
+ readonly "entry.id": {
169
+ readonly type: "number";
170
+ readonly required: true;
171
+ readonly description: "Transcript entry ID.";
172
+ readonly cardinality: "high";
173
+ };
174
+ readonly "entry.kind": {
175
+ readonly type: "string";
176
+ readonly required: true;
177
+ readonly description: "Entry kind.";
178
+ };
179
+ };
180
+ };
181
+ readonly "pi.durable.submission": {
182
+ readonly description: "A submission was settled.";
183
+ readonly attributes: {
184
+ readonly "submission.id": {
185
+ readonly type: "number";
186
+ readonly required: true;
187
+ readonly description: "Submission ID.";
188
+ readonly cardinality: "high";
189
+ };
190
+ readonly status: {
191
+ readonly type: "string";
192
+ readonly required: true;
193
+ readonly values: readonly ["done", "unanswered"];
194
+ readonly description: "Settlement.";
195
+ };
196
+ readonly "answer.entry_id": {
197
+ readonly type: "number";
198
+ readonly required: false;
199
+ readonly description: "Answer entry ID.";
200
+ readonly cardinality: "high";
201
+ };
202
+ };
203
+ };
204
+ readonly "pi.durable.report": {
205
+ readonly description: "A report was raised; no error payload is recorded.";
206
+ readonly attributes: {
207
+ readonly type: {
208
+ readonly type: "string";
209
+ readonly required: true;
210
+ readonly description: "ReportInfo type.";
211
+ readonly values: readonly ["session_failed", "task_faulted", "task_parked", "migration_failed", "task_outdated", "task_error", "extension_error", "host_error", "listener_error"];
212
+ };
213
+ readonly reason: {
214
+ readonly type: "string";
215
+ readonly required: false;
216
+ readonly description: "Fixed report reason, when present.";
217
+ readonly values: readonly ["threw", "restart_limit", "missing_task", "incompatible_task"];
218
+ };
219
+ readonly extension: {
220
+ readonly type: "string";
221
+ readonly required: false;
222
+ readonly description: "Registered extension name, when present.";
223
+ };
224
+ readonly "task.id": {
225
+ readonly type: "number";
226
+ readonly required: false;
227
+ readonly description: "Task ID, when present.";
228
+ readonly cardinality: "high";
229
+ };
230
+ };
231
+ };
232
+ readonly "pi.durable.checkpoint": {
233
+ readonly description: "The running checkpoint's phase changed while the invocation continued.";
234
+ readonly attributes: {
235
+ readonly phase: {
236
+ readonly type: "string";
237
+ readonly required: true;
238
+ readonly description: "Committed checkpoint phase.";
239
+ };
240
+ };
241
+ };
242
+ readonly "pi.durable.replay": {
243
+ readonly description: "A nested tool call was answered from its stored result.";
244
+ readonly attributes: {
245
+ readonly "tool.name": {
246
+ readonly type: "string";
247
+ readonly required: true;
248
+ readonly description: "Called tool name.";
249
+ };
250
+ };
251
+ };
252
+ };
253
+ readonly status: {
254
+ readonly default: "ok";
255
+ readonly errorWhen: "Faulted, failed, and orphaned outcomes use task_faulted, task_failed, and task_orphaned with a diagnostic capped at 500 characters. Aborted outcomes keep status ok.";
256
+ };
257
+ };
258
+ };
259
+ readonly metrics: {
260
+ readonly "pi.durable.reports": {
261
+ readonly kind: "counter";
262
+ readonly description: "Reports raised, grouped by their fixed ReportInfo type.";
263
+ readonly attributes: {
264
+ type: {
265
+ readonly type: "string";
266
+ readonly required: true;
267
+ readonly description: "ReportInfo type.";
268
+ readonly values: readonly ["session_failed", "task_faulted", "task_parked", "migration_failed", "task_outdated", "task_error", "extension_error", "host_error", "listener_error"];
269
+ };
270
+ };
271
+ };
272
+ readonly "pi.durable.phase.duration": {
273
+ readonly kind: "histogram";
274
+ readonly unit: "ms";
275
+ readonly description: "Duration of a phase invocation and its decision commit.";
276
+ readonly attributes: {
277
+ readonly task: {
278
+ readonly type: "string";
279
+ readonly required: true;
280
+ readonly description: "Registered task name.";
281
+ };
282
+ readonly phase: {
283
+ readonly type: "string";
284
+ readonly required: true;
285
+ readonly description: "Invoked checkpoint phase.";
286
+ };
287
+ readonly outcome: {
288
+ readonly type: "string";
289
+ readonly required: true;
290
+ readonly description: "Phase outcome.";
291
+ };
292
+ };
293
+ };
294
+ readonly "pi.durable.tasks.active": {
295
+ readonly kind: "upDownCounter";
296
+ readonly description: "Live tasks held by this Harness; decremented at terminal settlement or close.";
297
+ readonly attributes: {
298
+ readonly task: {
299
+ readonly type: "string";
300
+ readonly required: true;
301
+ readonly description: "Registered task name.";
302
+ };
303
+ };
304
+ };
305
+ };
306
+ };
307
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/harness/telemetry.ts"],"names":[],"mappings":"AAgDA,6GAA6G;AAC7G,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAwBxB,kBAAkB;0CAtEjB,sEAAsE;;iCAElF,UAAU;qCAAI,IAAI,EAAE,QAAQ;qCAAE,QAAQ;qCAAQ,WAAW,EAAE,sBAAsB;qCAAE,WAAW,EAAE,MAAM;;iCACtG,YAAY;qCAAI,IAAI,EAAE,QAAQ;qCAAE,QAAQ;qCAAQ,WAAW,EAAE,aAAa;;;;gBAmEpC,uBAAuB;0CAjCjD,2BAA2B;;iCAEvC,eAAe;qCAAI,IAAI,EAAE,QAAQ;qCAAE,QAAQ;qCAAQ,WAAW,EAAE,gBAAgB;qCAAE,WAAW,EAAE,MAAM;;iCACrG,MAAM;qCAAI,IAAI,EAAE,QAAQ;qCAAE,QAAQ;qCAAQ,MAAM,YAAG,MAAM,EAAE,YAAY;qCAAG,WAAW,EAAE,aAAa;;iCACpG,iBAAiB;qCAAI,IAAI,EAAE,QAAQ;qCAAE,QAAQ;qCAAS,WAAW,EAAE,kBAAkB;qCAAE,WAAW,EAAE,MAAM;;;;gBA6B/B,mBAAmB;0CArClF,oDAAoD;;;qCAzBhE,IAAI,EAAE,QAAQ;qCACd,QAAQ;qCACR,WAAW,EAAE,kBAAkB;qCAC/B,MAAM,YACL,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,gBAAgB;;;qCAIjB,IAAI,EAAE,QAAQ;qCACd,QAAQ;qCACR,WAAW,EAAE,oCAAoC;qCACjD,MAAM,YAAG,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,mBAAmB;;;qCAE1D,IAAI,EAAE,QAAQ;qCAAE,QAAQ;qCAAS,WAAW,EAAE,0CAA0C;;;qCACxF,IAAI,EAAE,QAAQ;qCAAE,QAAQ;qCAAS,WAAW,EAAE,wBAAwB;qCAAE,WAAW,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAuFxF,IAAI;mCA7Gb,QAAQ;;0CAED,kBAAkB;+CAE9B,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmHjB,CAAC"}
@@ -0,0 +1,136 @@
1
+ import { defineTelemetrySchema } from "@earendil-works/pi-telemetry";
2
+ const entry = {
3
+ description: "A transcript entry was committed; content remains in the transcript.",
4
+ attributes: {
5
+ "entry.id": { type: "number", required: true, description: "Transcript entry ID.", cardinality: "high" },
6
+ "entry.kind": { type: "string", required: true, description: "Entry kind." },
7
+ },
8
+ };
9
+ const reportAttributes = {
10
+ type: {
11
+ type: "string",
12
+ required: true,
13
+ description: "ReportInfo type.",
14
+ values: [
15
+ "session_failed",
16
+ "task_faulted",
17
+ "task_parked",
18
+ "migration_failed",
19
+ "task_outdated",
20
+ "task_error",
21
+ "extension_error",
22
+ "host_error",
23
+ "listener_error",
24
+ ],
25
+ },
26
+ reason: {
27
+ type: "string",
28
+ required: false,
29
+ description: "Fixed report reason, when present.",
30
+ values: ["threw", "restart_limit", "missing_task", "incompatible_task"],
31
+ },
32
+ extension: { type: "string", required: false, description: "Registered extension name, when present." },
33
+ "task.id": { type: "number", required: false, description: "Task ID, when present.", cardinality: "high" },
34
+ };
35
+ const report = {
36
+ description: "A report was raised; no error payload is recorded.",
37
+ attributes: reportAttributes,
38
+ };
39
+ const submission = {
40
+ description: "A submission was settled.",
41
+ attributes: {
42
+ "submission.id": { type: "number", required: true, description: "Submission ID.", cardinality: "high" },
43
+ status: { type: "string", required: true, values: ["done", "unanswered"], description: "Settlement." },
44
+ "answer.entry_id": { type: "number", required: false, description: "Answer entry ID.", cardinality: "high" },
45
+ },
46
+ };
47
+ /** Durable's content-free span, event, and metric vocabulary. IDs address durable records, never content. */
48
+ export const DURABLE_TELEMETRY_SCHEMA = defineTelemetrySchema({
49
+ version: 1,
50
+ spans: {
51
+ "pi.durable.submit": {
52
+ description: "Public submission admission and its commit. Inputs start root traces linked to their callers; writes are children. Internal admissions emit phase events only.",
53
+ parents: { kind: "any" },
54
+ startAttributes: {
55
+ "submission.type": {
56
+ type: "string",
57
+ required: true,
58
+ values: ["input", "write"],
59
+ description: "Submission type.",
60
+ },
61
+ "conversation.id": { type: "number", required: true, description: "Conversation ID.", cardinality: "high" },
62
+ },
63
+ endAttributes: {
64
+ "submission.id": { type: "number", description: "Admitted submission ID.", cardinality: "high" },
65
+ result: {
66
+ type: "string",
67
+ values: ["queued", "placed", "done"],
68
+ description: "Admission result; stale writes report done.",
69
+ },
70
+ },
71
+ events: { "pi.durable.entry": entry, "pi.durable.submission": submission, "pi.durable.report": report },
72
+ status: { default: "ok", errorWhen: "Admission failed." },
73
+ },
74
+ "pi.durable.phase": {
75
+ description: "One task phase invocation, including its decision commit, never a wait or restart.",
76
+ parents: { kind: "any" },
77
+ startAttributes: {
78
+ "task.id": { type: "number", required: true, description: "Task ID.", cardinality: "high" },
79
+ "task.name": { type: "string", required: true, description: "Registered task name." },
80
+ phase: { type: "string", required: true, description: "Invoked checkpoint phase." },
81
+ kind: { type: "string", required: true, values: ["run", "abort"], description: "Invocation kind." },
82
+ attempt: { type: "number", required: false, description: "Checkpoint attempt, when present." },
83
+ resumed: {
84
+ type: "boolean",
85
+ required: true,
86
+ description: "First invocation of a task loaded in this process.",
87
+ },
88
+ },
89
+ endAttributes: {
90
+ outcome: { type: "string", description: "next=<phase>, waiting, sleeping, done, faulted, or aborted." },
91
+ "tool.name": { type: "string", description: "Called tool name." },
92
+ "tool.call_id": { type: "string", description: "Transcript tool call ID.", cardinality: "high" },
93
+ },
94
+ events: {
95
+ "pi.durable.entry": entry,
96
+ "pi.durable.submission": submission,
97
+ "pi.durable.report": report,
98
+ "pi.durable.checkpoint": {
99
+ description: "The running checkpoint's phase changed while the invocation continued.",
100
+ attributes: { phase: { type: "string", required: true, description: "Committed checkpoint phase." } },
101
+ },
102
+ "pi.durable.replay": {
103
+ description: "A nested tool call was answered from its stored result.",
104
+ attributes: { "tool.name": { type: "string", required: true, description: "Called tool name." } },
105
+ },
106
+ },
107
+ status: {
108
+ default: "ok",
109
+ errorWhen: "Faulted, failed, and orphaned outcomes use task_faulted, task_failed, and task_orphaned with a diagnostic capped at 500 characters. Aborted outcomes keep status ok.",
110
+ },
111
+ },
112
+ },
113
+ metrics: {
114
+ "pi.durable.reports": {
115
+ kind: "counter",
116
+ description: "Reports raised, grouped by their fixed ReportInfo type.",
117
+ attributes: { type: reportAttributes.type },
118
+ },
119
+ "pi.durable.phase.duration": {
120
+ kind: "histogram",
121
+ unit: "ms",
122
+ description: "Duration of a phase invocation and its decision commit.",
123
+ attributes: {
124
+ task: { type: "string", required: true, description: "Registered task name." },
125
+ phase: { type: "string", required: true, description: "Invoked checkpoint phase." },
126
+ outcome: { type: "string", required: true, description: "Phase outcome." },
127
+ },
128
+ },
129
+ "pi.durable.tasks.active": {
130
+ kind: "upDownCounter",
131
+ description: "Live tasks held by this Harness; decremented at terminal settlement or close.",
132
+ attributes: { task: { type: "string", required: true, description: "Registered task name." } },
133
+ },
134
+ },
135
+ });
136
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/harness/telemetry.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineTelemetrySchema } from \"@earendil-works/pi-telemetry\";\n\nconst entry = {\n\tdescription: \"A transcript entry was committed; content remains in the transcript.\",\n\tattributes: {\n\t\t\"entry.id\": { type: \"number\", required: true, description: \"Transcript entry ID.\", cardinality: \"high\" },\n\t\t\"entry.kind\": { type: \"string\", required: true, description: \"Entry kind.\" },\n\t},\n} as const;\nconst reportAttributes = {\n\ttype: {\n\t\ttype: \"string\",\n\t\trequired: true,\n\t\tdescription: \"ReportInfo type.\",\n\t\tvalues: [\n\t\t\t\"session_failed\",\n\t\t\t\"task_faulted\",\n\t\t\t\"task_parked\",\n\t\t\t\"migration_failed\",\n\t\t\t\"task_outdated\",\n\t\t\t\"task_error\",\n\t\t\t\"extension_error\",\n\t\t\t\"host_error\",\n\t\t\t\"listener_error\",\n\t\t],\n\t},\n\treason: {\n\t\ttype: \"string\",\n\t\trequired: false,\n\t\tdescription: \"Fixed report reason, when present.\",\n\t\tvalues: [\"threw\", \"restart_limit\", \"missing_task\", \"incompatible_task\"],\n\t},\n\textension: { type: \"string\", required: false, description: \"Registered extension name, when present.\" },\n\t\"task.id\": { type: \"number\", required: false, description: \"Task ID, when present.\", cardinality: \"high\" },\n} as const;\nconst report = {\n\tdescription: \"A report was raised; no error payload is recorded.\",\n\tattributes: reportAttributes,\n} as const;\nconst submission = {\n\tdescription: \"A submission was settled.\",\n\tattributes: {\n\t\t\"submission.id\": { type: \"number\", required: true, description: \"Submission ID.\", cardinality: \"high\" },\n\t\tstatus: { type: \"string\", required: true, values: [\"done\", \"unanswered\"], description: \"Settlement.\" },\n\t\t\"answer.entry_id\": { type: \"number\", required: false, description: \"Answer entry ID.\", cardinality: \"high\" },\n\t},\n} as const;\n\n/** Durable's content-free span, event, and metric vocabulary. IDs address durable records, never content. */\nexport const DURABLE_TELEMETRY_SCHEMA = defineTelemetrySchema({\n\tversion: 1,\n\tspans: {\n\t\t\"pi.durable.submit\": {\n\t\t\tdescription:\n\t\t\t\t\"Public submission admission and its commit. Inputs start root traces linked to their callers; writes are children. Internal admissions emit phase events only.\",\n\t\t\tparents: { kind: \"any\" },\n\t\t\tstartAttributes: {\n\t\t\t\t\"submission.type\": {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\trequired: true,\n\t\t\t\t\tvalues: [\"input\", \"write\"],\n\t\t\t\t\tdescription: \"Submission type.\",\n\t\t\t\t},\n\t\t\t\t\"conversation.id\": { type: \"number\", required: true, description: \"Conversation ID.\", cardinality: \"high\" },\n\t\t\t},\n\t\t\tendAttributes: {\n\t\t\t\t\"submission.id\": { type: \"number\", description: \"Admitted submission ID.\", cardinality: \"high\" },\n\t\t\t\tresult: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalues: [\"queued\", \"placed\", \"done\"],\n\t\t\t\t\tdescription: \"Admission result; stale writes report done.\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tevents: { \"pi.durable.entry\": entry, \"pi.durable.submission\": submission, \"pi.durable.report\": report },\n\t\t\tstatus: { default: \"ok\", errorWhen: \"Admission failed.\" },\n\t\t},\n\t\t\"pi.durable.phase\": {\n\t\t\tdescription: \"One task phase invocation, including its decision commit, never a wait or restart.\",\n\t\t\tparents: { kind: \"any\" },\n\t\t\tstartAttributes: {\n\t\t\t\t\"task.id\": { type: \"number\", required: true, description: \"Task ID.\", cardinality: \"high\" },\n\t\t\t\t\"task.name\": { type: \"string\", required: true, description: \"Registered task name.\" },\n\t\t\t\tphase: { type: \"string\", required: true, description: \"Invoked checkpoint phase.\" },\n\t\t\t\tkind: { type: \"string\", required: true, values: [\"run\", \"abort\"], description: \"Invocation kind.\" },\n\t\t\t\tattempt: { type: \"number\", required: false, description: \"Checkpoint attempt, when present.\" },\n\t\t\t\tresumed: {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\trequired: true,\n\t\t\t\t\tdescription: \"First invocation of a task loaded in this process.\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tendAttributes: {\n\t\t\t\toutcome: { type: \"string\", description: \"next=<phase>, waiting, sleeping, done, faulted, or aborted.\" },\n\t\t\t\t\"tool.name\": { type: \"string\", description: \"Called tool name.\" },\n\t\t\t\t\"tool.call_id\": { type: \"string\", description: \"Transcript tool call ID.\", cardinality: \"high\" },\n\t\t\t},\n\t\t\tevents: {\n\t\t\t\t\"pi.durable.entry\": entry,\n\t\t\t\t\"pi.durable.submission\": submission,\n\t\t\t\t\"pi.durable.report\": report,\n\t\t\t\t\"pi.durable.checkpoint\": {\n\t\t\t\t\tdescription: \"The running checkpoint's phase changed while the invocation continued.\",\n\t\t\t\t\tattributes: { phase: { type: \"string\", required: true, description: \"Committed checkpoint phase.\" } },\n\t\t\t\t},\n\t\t\t\t\"pi.durable.replay\": {\n\t\t\t\t\tdescription: \"A nested tool call was answered from its stored result.\",\n\t\t\t\t\tattributes: { \"tool.name\": { type: \"string\", required: true, description: \"Called tool name.\" } },\n\t\t\t\t},\n\t\t\t},\n\t\t\tstatus: {\n\t\t\t\tdefault: \"ok\",\n\t\t\t\terrorWhen:\n\t\t\t\t\t\"Faulted, failed, and orphaned outcomes use task_faulted, task_failed, and task_orphaned with a diagnostic capped at 500 characters. Aborted outcomes keep status ok.\",\n\t\t\t},\n\t\t},\n\t},\n\tmetrics: {\n\t\t\"pi.durable.reports\": {\n\t\t\tkind: \"counter\",\n\t\t\tdescription: \"Reports raised, grouped by their fixed ReportInfo type.\",\n\t\t\tattributes: { type: reportAttributes.type },\n\t\t},\n\t\t\"pi.durable.phase.duration\": {\n\t\t\tkind: \"histogram\",\n\t\t\tunit: \"ms\",\n\t\t\tdescription: \"Duration of a phase invocation and its decision commit.\",\n\t\t\tattributes: {\n\t\t\t\ttask: { type: \"string\", required: true, description: \"Registered task name.\" },\n\t\t\t\tphase: { type: \"string\", required: true, description: \"Invoked checkpoint phase.\" },\n\t\t\t\toutcome: { type: \"string\", required: true, description: \"Phase outcome.\" },\n\t\t\t},\n\t\t},\n\t\t\"pi.durable.tasks.active\": {\n\t\t\tkind: \"upDownCounter\",\n\t\t\tdescription: \"Live tasks held by this Harness; decremented at terminal settlement or close.\",\n\t\t\tattributes: { task: { type: \"string\", required: true, description: \"Registered task name.\" } },\n\t\t},\n\t},\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/harness/tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,kBAAkB,EAAkB,MAAM,uBAAuB,CAAC;AAGpH,OAAO,KAAK,EAA6B,QAAQ,EAAqB,MAAM,uBAAuB,CAAC;AAQpG,OAAO,KAAK,EACX,cAAc,EACd,OAAO,EACP,UAAU,EACV,IAAI,EACJ,MAAM,EAIN,EAAE,EACF,UAAU,EACV,MAAM,aAAa,CAAC;AAarB,OAAO,KAAK,EACX,yBAAyB,EACzB,WAAW,EACX,cAAc,EAEd,mBAAmB,EAEnB,SAAS,EAET,MAAM,YAAY,CAAC;AAGpB;;;GAGG;AACH,MAAM,MAAM,aAAa,GACtB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrD;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;IACf,0GAA0G;IAC1G,QAAQ,CAAC,EAAE,KAAK,CAAC;CAChB,CAAC;AAEL,MAAM,MAAM,kBAAkB,GAC3B;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;AACnB,2FAA2F;GACzF;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAQ7G,kFAAkF;AAClF,MAAM,MAAM,eAAe,GAAG;IAC7B,mGAAmG;IACnG,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAChC,oHAAoH;IACpH,MAAM,CAAC,EAAE,kBAAkB,CAAC,yBAAyB,CAAC,CAAC;CACvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,iEAMxB,CAAC;AAKH;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,oEAuFnB,CAAC;AAukBH,oGAAoG;AACpG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAE/E;AAwCD;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,EAAE,EAAE,EAAE,EACN,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAAC,UAAU,CAAC;IAAE,WAAW,EAAE,cAAc,EAAE,CAAA;CAAE,CAAC,CAAC,CAkBxD"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/harness/tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,kBAAkB,EAAkB,MAAM,uBAAuB,CAAC;AAWpH,OAAO,KAAK,EAA6B,QAAQ,EAAqB,MAAM,uBAAuB,CAAC;AASpG,OAAO,KAAK,EACX,cAAc,EACd,OAAO,EACP,UAAU,EACV,IAAI,EACJ,MAAM,EAIN,EAAE,EACF,UAAU,EACV,MAAM,aAAa,CAAC;AAarB,OAAO,KAAK,EACX,yBAAyB,EACzB,WAAW,EACX,cAAc,EAEd,mBAAmB,EAEnB,SAAS,EAET,MAAM,YAAY,CAAC;AAIpB;;;GAGG;AACH,MAAM,MAAM,aAAa,GACtB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrD;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;IACf,0GAA0G;IAC1G,QAAQ,CAAC,EAAE,KAAK,CAAC;CAChB,CAAC;AAEL,MAAM,MAAM,kBAAkB,GAC3B;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;AACnB,2FAA2F;GACzF;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAQ7G,kFAAkF;AAClF,MAAM,MAAM,eAAe,GAAG;IAC7B,mGAAmG;IACnG,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAChC,oHAAoH;IACpH,MAAM,CAAC,EAAE,kBAAkB,CAAC,yBAAyB,CAAC,CAAC;CACvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,iEAQxB,CAAC;AAKH;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,oEAuFnB,CAAC;AAsnBH,oGAAoG;AACpG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAE/E;AAwCD;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,EAAE,EAAE,EAAE,EACN,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAAC,UAAU,CAAC;IAAE,WAAW,EAAE,cAAc,EAAE,CAAA;CAAE,CAAC,CAAC,CAkBxD"}
@@ -1,6 +1,7 @@
1
1
  import { copyJson } from "@earendil-works/chord";
2
2
  import { awaitWithContext } from "@earendil-works/chord/context";
3
3
  import { overlap } from "@earendil-works/chord/delta";
4
+ import { boundOutput, OutputBuffer, PROGRESS_BYTES_PER_SECOND, Progress, } from "@earendil-works/chord/output";
4
5
  import { validateToolArguments } from "@earendil-works/pi-ai/utils/validation";
5
6
  import { Compile } from "typebox/compile";
6
7
  import { defineDocFamily } from "../documents.js";
@@ -8,10 +9,11 @@ import { AssistantEntry, ToolResultEntry } from "../entries.js";
8
9
  import { errorMessage } from "../errors.js";
9
10
  import { defineTask } from "../tasks.js";
10
11
  import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, utf8ByteLength } from "../truncate.js";
12
+ import { toolExtension } from "./agent.js";
11
13
  import { assignJson } from "./json.js";
12
14
  import { clearProgress, finishSlot, LiveDoc, removeNestedSlots, toolSlot, } from "./live.js";
13
- import { boundOutput, OutputBuffer, PROGRESS_BYTES_PER_SECOND, Progress } from "./output.js";
14
15
  import { recordUsage } from "./usage.js";
16
+ import { optionalExtension } from "./util.js";
15
17
  /**
16
18
  * Memo of a tool task that made a nested call, in any attempt, committed before the first admission of each attempt:
17
19
  * only then can `pi.live` hold slots below it, which settling removes. A crash between the two only costs a scan.
@@ -28,6 +30,8 @@ export const NestedCallDoc = defineDocFamily({
28
30
  scope: "task",
29
31
  family: true,
30
32
  initial: () => ({}),
33
+ // The document retires with its task.
34
+ checkpointWhen: () => false,
31
35
  });
32
36
  /**
33
37
  * Built-in tool task: resolves the called tool among its phase agent's tools, validates, runs `beforeTool`, records intent,
@@ -137,8 +141,13 @@ async function resolveTool(runtime, input, name, context) {
137
141
  }
138
142
  /** The call: from the input for a nested call, which hooks see with its parent, else from the assistant entry. */
139
143
  async function readCall(runtime, input, context) {
140
- if (input.kind === "nested")
144
+ if (input.kind === "nested") {
145
+ context.telemetry.setAttributes({
146
+ "tool.name": input.call.name,
147
+ "tool.call_id": input.call.id,
148
+ });
141
149
  return { ...input.call, parent: { taskId: input.parent, callId: input.parentCallId } };
150
+ }
142
151
  const entry = await runtime.entry(AssistantEntry, input.assistant, context);
143
152
  const message = entry?.model?.[0];
144
153
  const call = message?.role === "assistant"
@@ -146,6 +155,10 @@ async function readCall(runtime, input, context) {
146
155
  : undefined;
147
156
  if (call === undefined)
148
157
  throw new Error(`Entry ${input.assistant} has no tool call ${input.callId}`);
158
+ context.telemetry.setAttributes({
159
+ "tool.name": call.name,
160
+ "tool.call_id": call.id,
161
+ });
149
162
  return call;
150
163
  }
151
164
  /** The call's arguments as repaired by the tool; a throwing repair makes them invalid. */
@@ -195,13 +208,21 @@ async function run(runtime, input, call, tool, args, context) {
195
208
  if (ended)
196
209
  throw new Error(`Tool call ${call.id} has settled`);
197
210
  };
211
+ /** Built for this call, below, so a rerun after recovery gets the conversation's environment at that time. */
212
+ let env;
198
213
  const api = {
199
214
  taskId: runtime.taskId,
200
215
  conversationId: runtime.conversationId,
201
216
  callId: call.id,
202
217
  registry: runtime.registry,
203
218
  agent: runtime.agent,
204
- models: runtime.models,
219
+ get models() {
220
+ return runtime.models;
221
+ },
222
+ get env() {
223
+ return env;
224
+ },
225
+ now: () => runtime.now(),
205
226
  output: (chunk, skipped) => {
206
227
  assertLive();
207
228
  if (reported.output.push(chunk, skipped))
@@ -285,11 +306,10 @@ async function run(runtime, input, call, tool, args, context) {
285
306
  // Execution time of this attempt; a rerun after recovery measures only itself.
286
307
  let durationMs;
287
308
  try {
288
- // Built for this call, so a rerun after recovery gets the conversation's environment at that time.
289
- const env = await runtime.env(context);
309
+ env = await runtime.env(context);
290
310
  const startedAt = performance.now();
291
311
  try {
292
- result = await tool.execute(args, { ...api, env }, context);
312
+ result = await tool.execute(args, api, context);
293
313
  }
294
314
  finally {
295
315
  durationMs = Math.round(performance.now() - startedAt);
@@ -325,6 +345,25 @@ async function run(runtime, input, call, tool, args, context) {
325
345
  for (const waiter of pending)
326
346
  waiter.resolve();
327
347
  }
348
+ /**
349
+ * The Harness clock and timers for progress pacing. After the invocation ends nothing more commits, and the clock
350
+ * answers with the last time it read.
351
+ */
352
+ function progressClock(runtime) {
353
+ let last = 0;
354
+ return {
355
+ now: () => {
356
+ try {
357
+ last = runtime.now();
358
+ }
359
+ catch {
360
+ // The invocation ended.
361
+ }
362
+ return last;
363
+ },
364
+ setTimer: (callback, delayMs) => runtime.setTimer(callback, delayMs),
365
+ };
366
+ }
328
367
  /**
329
368
  * Throttled commits of what the tool reported into its slot, in `pi.live.tools` or `pi.live.nestedTools`, each writing
330
369
  * only what changed since the last one; none when `enabled` is false.
@@ -382,7 +421,7 @@ function publishProgress(runtime, reported, enabled, context) {
382
421
  // Rejections after an abort mark or close are expected; the committed state stays consistent.
383
422
  if (!runtime.signal.aborted)
384
423
  runtime.report(error);
385
- }, runtime.settings.progress.outputIntervalMs);
424
+ }, runtime.settings.progress.outputIntervalMs, progressClock(runtime));
386
425
  }
387
426
  /**
388
427
  * The settled result: the tool's result with the retained output and last details as fallbacks, its diagnostics after
@@ -420,7 +459,9 @@ async function finalResult(runtime, input, call, tool, result, reported, context
420
459
  else {
421
460
  // The model never sees structured output, so its call stands; the host learns of the broken tool.
422
461
  final = rest;
423
- runtime.report(new Error(broken));
462
+ // Only names the extension: a failed resolution leaves the report without the name.
463
+ const extension = await runtime.agent(context).then((agent) => toolExtension(agent, tool.name), () => undefined);
464
+ runtime.report(new Error(broken), { type: "extension", ...optionalExtension(extension) });
424
465
  }
425
466
  }
426
467
  // Programs get the tool's own value: without a schema, its output. The model reads only `output`, so model-issued
@@ -561,6 +602,7 @@ async function startNestedCall(runtime, parentCallId, name, args, options, conte
561
602
  arguments: copyJson(args, { omitUndefinedProperties: true }),
562
603
  };
563
604
  let id;
605
+ let replayed = false;
564
606
  await runtime.commit(async (tx) => {
565
607
  // Opened, or created empty for a key not made yet.
566
608
  const state = await tx.doc(NestedCallDoc, runtime.taskId, key, null);
@@ -573,6 +615,7 @@ async function startNestedCall(runtime, parentCallId, name, args, options, conte
573
615
  if (!same)
574
616
  throw new Error(`Nested call ${call.id} was already made with another tool or other arguments`);
575
617
  id = existing;
618
+ replayed = state.result !== undefined;
576
619
  return undefined;
577
620
  }
578
621
  const input = {
@@ -603,6 +646,9 @@ async function startNestedCall(runtime, parentCallId, name, args, options, conte
603
646
  id = created;
604
647
  return undefined;
605
648
  }, context);
649
+ if (replayed) {
650
+ context.telemetry.addEvent("pi.durable.replay", { "tool.name": name });
651
+ }
606
652
  return id;
607
653
  }
608
654
  /**