stitchkit 0.102.0 → 0.103.1

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 (103) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/dist/agent-runtime/browser-control-contract.d.ts +1118 -0
  3. package/dist/agent-runtime/browser-control-contract.d.ts.map +1 -0
  4. package/dist/agent-runtime/browser-controller.d.ts +31 -0
  5. package/dist/agent-runtime/browser-controller.d.ts.map +1 -0
  6. package/dist/agent-runtime/harness-control.d.ts.map +1 -1
  7. package/dist/agent-runtime/harness-realtime.d.ts +25 -0
  8. package/dist/agent-runtime/harness-realtime.d.ts.map +1 -0
  9. package/dist/agent-runtime/harness-tools.d.ts +11 -0
  10. package/dist/agent-runtime/harness-tools.d.ts.map +1 -0
  11. package/dist/agent-runtime/react.d.ts +4 -0
  12. package/dist/agent-runtime/react.d.ts.map +1 -0
  13. package/dist/agent-runtime/run-assertions.d.ts +63 -0
  14. package/dist/agent-runtime/run-assertions.d.ts.map +1 -0
  15. package/dist/application/diagnostic-journal-contract.d.ts +46 -7
  16. package/dist/application/diagnostic-journal-contract.d.ts.map +1 -1
  17. package/dist/application/diagnostic-journal-frame.d.ts +9 -0
  18. package/dist/application/diagnostic-journal-frame.d.ts.map +1 -0
  19. package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
  20. package/dist/application/diagnostic-journal-read-contract.d.ts +110 -0
  21. package/dist/application/diagnostic-journal-read-contract.d.ts.map +1 -0
  22. package/dist/application/diagnostic-journal-reader.d.ts +13 -0
  23. package/dist/application/diagnostic-journal-reader.d.ts.map +1 -0
  24. package/dist/application/diagnostic-journal-recovery.d.ts +4 -0
  25. package/dist/application/diagnostic-journal-recovery.d.ts.map +1 -0
  26. package/dist/application/diagnostic-journal-storage.d.ts +2 -0
  27. package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
  28. package/dist/entrypoints/agent-runtime/browser.d.ts +2 -0
  29. package/dist/entrypoints/agent-runtime/browser.d.ts.map +1 -1
  30. package/dist/entrypoints/agent-runtime/browser.js +235 -0
  31. package/dist/entrypoints/agent-runtime/harness-tools.d.ts +2 -0
  32. package/dist/entrypoints/agent-runtime/harness-tools.d.ts.map +1 -0
  33. package/dist/entrypoints/agent-runtime/harness-tools.js +32 -0
  34. package/dist/entrypoints/agent-runtime/harness.js +11 -226
  35. package/dist/entrypoints/agent-runtime/react.d.ts +2 -0
  36. package/dist/entrypoints/agent-runtime/react.d.ts.map +1 -0
  37. package/dist/entrypoints/agent-runtime/react.js +8 -0
  38. package/dist/entrypoints/agent-runtime/realtime.d.ts +2 -0
  39. package/dist/entrypoints/agent-runtime/realtime.d.ts.map +1 -0
  40. package/dist/entrypoints/agent-runtime/realtime.js +159 -0
  41. package/dist/entrypoints/agent-runtime/testing.d.ts +1 -0
  42. package/dist/entrypoints/agent-runtime/testing.d.ts.map +1 -1
  43. package/dist/entrypoints/agent-runtime/testing.js +67 -2
  44. package/dist/entrypoints/agent-runtime.js +23 -18
  45. package/dist/entrypoints/application/diagnostic-journal.d.ts +1 -0
  46. package/dist/entrypoints/application/diagnostic-journal.d.ts.map +1 -1
  47. package/dist/entrypoints/application/diagnostic-journal.js +213 -19
  48. package/dist/entrypoints/application.d.ts +1 -0
  49. package/dist/entrypoints/application.d.ts.map +1 -1
  50. package/dist/entrypoints/application.js +10 -2
  51. package/dist/entrypoints/cli.js +6 -6
  52. package/dist/entrypoints/index.js +15 -226
  53. package/dist/entrypoints/node.js +7 -5
  54. package/dist/entrypoints/observability.js +2 -2
  55. package/dist/entrypoints/react.js +2 -2
  56. package/dist/entrypoints/remote.js +3 -3
  57. package/dist/entrypoints/server.js +10 -8
  58. package/dist/entrypoints/testing.js +3 -3
  59. package/dist/entrypoints/tools/invoker.js +5 -5
  60. package/dist/entrypoints/tools.js +23 -34
  61. package/dist/entrypoints/tracking.js +2 -2
  62. package/dist/{index-d82d3xg4.js → index-0c419yx7.js} +1 -1
  63. package/dist/{index-dvwj1f43.js → index-0efgsyav.js} +1 -1
  64. package/dist/index-20yvtn9a.js +38 -0
  65. package/dist/{index-a9pd417t.js → index-5vyd0fkb.js} +1 -34
  66. package/dist/{index-r1z0rd9c.js → index-7n68nmc6.js} +1 -1
  67. package/dist/index-860vjkgm.js +48 -0
  68. package/dist/index-c9d05kvt.js +11 -0
  69. package/dist/{index-m9fndta6.js → index-ds7jdhep.js} +2 -2
  70. package/dist/index-jn9g8xdt.js +246 -0
  71. package/dist/{index-n9tyz8z3.js → index-kgmh97hf.js} +1 -1
  72. package/dist/{index-c6aagrbd.js → index-kkk1wzsq.js} +3 -3
  73. package/dist/index-nggfa2yn.js +34 -0
  74. package/dist/{index-m79yr938.js → index-pw99k9h5.js} +1 -10
  75. package/dist/index-qapzv4p5.js +54 -0
  76. package/dist/index-r34mvse1.js +225 -0
  77. package/dist/index-srs8hj9c.js +10 -0
  78. package/dist/index-vgkbcnkc.js +29 -0
  79. package/dist/{index-ewbaywk5.js → index-x1dkwx5x.js} +1 -1
  80. package/dist/{index-xkhk5d6g.js → index-xgc94hy6.js} +5 -48
  81. package/dist/{index-3ct7hhq6.js → index-xwq9j1sf.js} +6 -56
  82. package/dist/{index-hby4qhax.js → index-yex7eg1v.js} +4 -10
  83. package/dist/{index-1h6gtdrj.js → index-ygkka6zn.js} +1 -1
  84. package/dist/{index-zs4ms3th.js → index-z3pqcy7r.js} +7 -30
  85. package/dist/index-z94wht4y.js +156 -0
  86. package/dist/index-ze1eph1k.js +20 -0
  87. package/llms/agent-runtime-browser.txt +26 -0
  88. package/llms/agent-runtime-harness-tools.txt +25 -0
  89. package/llms/agent-runtime-harness.txt +140 -1
  90. package/llms/agent-runtime-react.txt +21 -0
  91. package/llms/agent-runtime-realtime.txt +30 -0
  92. package/llms/agent-runtime-testing.txt +6 -0
  93. package/llms/application-diagnostic-journal.txt +2 -0
  94. package/llms/application.2.txt +157 -267
  95. package/llms/application.3.txt +278 -0
  96. package/llms/application.txt +43 -158
  97. package/llms/stitchkit.txt +9 -5
  98. package/llms/{upgrading-0.75.0-0.102.0.txt → upgrading-0.75.0-0.103.0.txt} +32 -3
  99. package/llms/upgrading.txt +1 -1
  100. package/llms-full.txt +289 -9
  101. package/llms.txt +11 -7
  102. package/package.json +13 -1
  103. package/dist/index-h124epcf.js +0 -103
@@ -1,3 +1,4 @@
1
+ import"../../index-814xpr6d.js";
1
2
  import {
2
3
  AgentRecordIdSchema2,
3
4
  AgentRecordVersionSchema2,
@@ -62,10 +63,242 @@ import {
62
63
  reduceAgentControlSnapshot2,
63
64
  reduceAgentControlEvent2
64
65
  } from "../../index-n5yqxd3d.js";
66
+ import {
67
+ AgentBrowserRequestSchema2,
68
+ agentControlRealtimeContract2
69
+ } from "../../index-20yvtn9a.js";
70
+ import"../../index-n53mswt3.js";
71
+ import"../../index-pw99k9h5.js";
72
+ import"../../index-4s0fep5q.js";
73
+ import {
74
+ bindRealtimeClient2
75
+ } from "../../index-r34mvse1.js";
76
+ // src/agent-runtime/browser-controller.ts
77
+ function refreshed(view, snapshot) {
78
+ const current = view.conversations[snapshot.conversationId];
79
+ if (Math.max(current?.snapshot?.version ?? 0, view.cursor.conversations[snapshot.conversationId]?.snapshotVersion ?? 0) > snapshot.version)
80
+ return view;
81
+ const next = reduceAgentControlSnapshot2(view, snapshot);
82
+ const transientByRun = Object.fromEntries(Object.entries(current?.transientByRun ?? {}).filter(([id]) => snapshot.runs.some((run) => run.id === id && ["running", "interrupt_requested"].includes(run.state))));
83
+ return {
84
+ ...next,
85
+ conversations: {
86
+ ...next.conversations,
87
+ [snapshot.conversationId]: { snapshot, resyncRequired: false, transientByRun }
88
+ }
89
+ };
90
+ }
91
+ function createAgentController(config) {
92
+ return new ConversationController(config);
93
+ }
94
+
95
+ class ConversationController {
96
+ config;
97
+ client;
98
+ timeoutMs;
99
+ maxEvents;
100
+ maxBytes;
101
+ maxPending;
102
+ state = {
103
+ status: "connecting",
104
+ view: createAgentControlView2()
105
+ };
106
+ listeners = new Set;
107
+ generation = 0;
108
+ closed = false;
109
+ busy = false;
110
+ buffered = [];
111
+ bufferedBytes = 0;
112
+ overflowed = false;
113
+ refreshScheduled = false;
114
+ refreshAttempts = 0;
115
+ tail = Promise.resolve();
116
+ pending = new Set;
117
+ offDelivery;
118
+ offConnection;
119
+ constructor(config) {
120
+ this.config = config;
121
+ this.client = bindRealtimeClient2(agentControlRealtimeContract2, config.transport);
122
+ this.timeoutMs = config.timeoutMs ?? 1e4;
123
+ this.maxEvents = config.maxBufferedEvents ?? 256;
124
+ this.maxBytes = config.maxBufferedBytes ?? 1048576;
125
+ this.maxPending = config.maxPendingRequests ?? 32;
126
+ for (const [name, value] of Object.entries({
127
+ timeoutMs: this.timeoutMs,
128
+ maxEvents: this.maxEvents,
129
+ maxBytes: this.maxBytes,
130
+ maxPending: this.maxPending
131
+ })) {
132
+ if (!Number.isSafeInteger(value) || value < 1)
133
+ throw new TypeError(`${name} must be a positive safe integer`);
134
+ }
135
+ if (!config.conversationId)
136
+ throw new TypeError("conversationId must not be empty");
137
+ this.offDelivery = this.client.on("agent:delivery", (delivery) => this.receive(delivery));
138
+ this.offConnection = this.client.onConnectionChange((connected) => this.changed(connected));
139
+ this.changed(this.client.connected);
140
+ }
141
+ getSnapshot = () => this.state;
142
+ subscribe = (listener) => {
143
+ this.listeners.add(listener);
144
+ return () => {
145
+ this.listeners.delete(listener);
146
+ };
147
+ };
148
+ update(next) {
149
+ this.state = next;
150
+ for (const listener of this.listeners)
151
+ listener();
152
+ }
153
+ failure(code, message) {
154
+ this.update({ ...this.state, status: "error", error: { code, message } });
155
+ }
156
+ apply(delivery) {
157
+ if (delivery.type === "event") {
158
+ this.update({
159
+ ...this.state,
160
+ view: reduceAgentControlEvent2(this.state.view, delivery.event)
161
+ });
162
+ } else {
163
+ this.failure("EVENT_OVERFLOW", "Reconnect the transport to restore agent state");
164
+ }
165
+ }
166
+ scheduleRefresh() {
167
+ if (this.refreshScheduled || this.busy || this.pending.size >= this.maxPending || this.state.status !== "ready" || !this.state.view.conversations[this.config.conversationId]?.resyncRequired)
168
+ return;
169
+ this.refreshScheduled = true;
170
+ queueMicrotask(() => {
171
+ this.refreshScheduled = false;
172
+ if (!this.closed && this.state.status === "ready") {
173
+ if (++this.refreshAttempts > 3) {
174
+ this.failure("RESYNC_EXHAUSTED", "Snapshot did not catch up; refresh explicitly to retry");
175
+ return;
176
+ }
177
+ this.request({ operation: "snapshot" }).catch(() => {});
178
+ }
179
+ });
180
+ }
181
+ async execute(command, epoch) {
182
+ if (this.closed || epoch !== this.generation || !this.client.connected)
183
+ throw new Error("Agent controller is disconnected");
184
+ this.busy = true;
185
+ const requestId = crypto.randomUUID();
186
+ try {
187
+ const response = await this.client.request("agent:control", {
188
+ ...command,
189
+ schemaVersion: 1,
190
+ requestId,
191
+ conversationId: this.config.conversationId
192
+ }, { timeoutMs: this.timeoutMs });
193
+ if (this.closed || epoch !== this.generation)
194
+ throw new Error("Agent controller connection changed");
195
+ if (response.requestId !== requestId)
196
+ throw new Error("Agent control acknowledgement identity mismatch");
197
+ if (response.outcome === "error") {
198
+ this.failure(response.error.code, response.error.message);
199
+ return response;
200
+ }
201
+ if (response.snapshot) {
202
+ if (response.snapshot.conversationId !== this.config.conversationId)
203
+ throw new Error("Agent snapshot conversation mismatch");
204
+ this.update({ status: "ready", view: refreshed(this.state.view, response.snapshot) });
205
+ if (!this.state.view.conversations[this.config.conversationId]?.resyncRequired)
206
+ this.refreshAttempts = 0;
207
+ }
208
+ if (command.operation === "detach")
209
+ this.update({ ...this.state, status: "disconnected" });
210
+ return response;
211
+ } catch (error) {
212
+ if (!this.closed && epoch === this.generation)
213
+ this.failure("CONTROL_REQUEST_FAILED", error instanceof Error ? error.message : "Agent request failed");
214
+ throw error;
215
+ } finally {
216
+ if (epoch === this.generation) {
217
+ this.busy = false;
218
+ const deliveries = this.buffered;
219
+ this.buffered = [];
220
+ this.bufferedBytes = 0;
221
+ for (const delivery of deliveries)
222
+ this.apply(delivery);
223
+ if (this.overflowed) {
224
+ this.overflowed = false;
225
+ this.failure("EVENT_OVERFLOW", "Refresh agent state before continuing");
226
+ }
227
+ }
228
+ }
229
+ }
230
+ request(command) {
231
+ if (this.closed || this.pending.size >= this.maxPending)
232
+ return Promise.reject(new Error(this.closed ? "Agent controller is closed" : "Agent request capacity exceeded"));
233
+ const entry = {};
234
+ this.pending.add(entry);
235
+ const epoch = this.generation;
236
+ const result = this.tail.then(() => this.execute(command, epoch)).finally(() => {
237
+ this.pending.delete(entry);
238
+ this.scheduleRefresh();
239
+ });
240
+ this.tail = result.catch(() => {});
241
+ return result;
242
+ }
243
+ receive(delivery) {
244
+ const conversationId = delivery.type === "event" ? delivery.event.conversationId : delivery.conversationId;
245
+ if (this.closed || conversationId !== this.config.conversationId)
246
+ return;
247
+ if (this.busy) {
248
+ const bytes = new TextEncoder().encode(JSON.stringify(delivery)).byteLength;
249
+ if (this.overflowed || this.buffered.length >= this.maxEvents || this.bufferedBytes + bytes > this.maxBytes) {
250
+ this.overflowed = true;
251
+ this.buffered = [];
252
+ this.bufferedBytes = 0;
253
+ } else {
254
+ this.buffered.push(delivery);
255
+ this.bufferedBytes += bytes;
256
+ }
257
+ } else {
258
+ this.apply(delivery);
259
+ this.scheduleRefresh();
260
+ }
261
+ }
262
+ changed(connected) {
263
+ this.generation += 1;
264
+ this.busy = false;
265
+ this.buffered = [];
266
+ this.bufferedBytes = 0;
267
+ this.overflowed = false;
268
+ this.refreshAttempts = 0;
269
+ this.tail = Promise.resolve();
270
+ this.update({
271
+ status: connected ? "connecting" : "disconnected",
272
+ view: createAgentControlView2()
273
+ });
274
+ if (connected)
275
+ this.request({ operation: "attach", access: this.config.access }).catch(() => {});
276
+ }
277
+ async close() {
278
+ if (this.closed)
279
+ return;
280
+ this.closed = true;
281
+ this.generation += 1;
282
+ this.offDelivery();
283
+ this.offConnection();
284
+ this.update({ ...this.state, status: "closed" });
285
+ if (this.client.connected) {
286
+ const response = await this.client.request("agent:control", {
287
+ schemaVersion: 1,
288
+ requestId: crypto.randomUUID(),
289
+ operation: "detach",
290
+ conversationId: this.config.conversationId
291
+ }, { timeoutMs: this.timeoutMs });
292
+ if (response.outcome === "error" && !["CONNECTION_CLOSED", "ACCESS_DENIED"].includes(response.error.code))
293
+ throw new Error(`Agent detach failed: ${response.error.code}`);
294
+ }
295
+ }
296
+ }
65
297
  export {
66
298
  AgentAdmissionEventSchema2 as AgentAdmissionEventSchema,
67
299
  AgentAssistantPlaceholderSchema2 as AgentAssistantPlaceholderSchema,
68
300
  AgentAttemptResetEventSchema2 as AgentAttemptResetEventSchema,
301
+ AgentBrowserRequestSchema2 as AgentBrowserRequestSchema,
69
302
  AgentCheckpointEventSchema2 as AgentCheckpointEventSchema,
70
303
  AgentControlDeliverySchema2 as AgentControlDeliverySchema,
71
304
  AgentControlPartSchema2 as AgentControlPartSchema,
@@ -116,8 +349,10 @@ export {
116
349
  AgentUsageValueSchema2 as AgentUsageValueSchema,
117
350
  advanceAgentMultiSessionCursor2 as advanceAgentMultiSessionCursor,
118
351
  advanceAgentRuntimeEventCursor2 as advanceAgentRuntimeEventCursor,
352
+ agentControlRealtimeContract2 as agentControlRealtimeContract,
119
353
  agentDurableEventId2 as agentDurableEventId,
120
354
  createAgentControlView2 as createAgentControlView,
355
+ createAgentController,
121
356
  reduceAgentControlEvent2 as reduceAgentControlEvent,
122
357
  reduceAgentControlSnapshot2 as reduceAgentControlSnapshot,
123
358
  runStateForTerminalReason2 as runStateForTerminalReason
@@ -0,0 +1,2 @@
1
+ export { type AgentHarnessToolsConfig, createAgentHarnessTools, } from '../../agent-runtime/harness-tools.js';
2
+ //# sourceMappingURL=harness-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-tools.d.ts","sourceRoot":"","sources":["../../../src/entrypoints/agent-runtime/harness-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,uBAAuB,EAC5B,uBAAuB,GACxB,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,32 @@
1
+ import"../../index-nggfa2yn.js";
2
+ import"../../index-n53mswt3.js";
3
+ import"../../index-b2bz0kdm.js";
4
+ import"../../index-yex7eg1v.js";
5
+ import"../../index-9pw0a51a.js";
6
+ import"../../index-ct75c3at.js";
7
+ import"../../index-7z9ym7t8.js";
8
+ import"../../index-0efgsyav.js";
9
+ import"../../index-kgmh97hf.js";
10
+ import {
11
+ mountAgent2
12
+ } from "../../index-xgc94hy6.js";
13
+ import {
14
+ composeToolLifecycle2
15
+ } from "../../index-ze1eph1k.js";
16
+ import"../../index-x1dkwx5x.js";
17
+ import"../../index-7n68nmc6.js";
18
+ import"../../index-jzczzcsb.js";
19
+
20
+ // src/agent-runtime/harness-tools.ts
21
+ function createAgentHarnessTools(resolve) {
22
+ return async (run) => {
23
+ const { services, lifecycle, ...config } = await resolve(run);
24
+ return mountAgent2(services, {
25
+ ...config,
26
+ lifecycle: composeToolLifecycle2(lifecycle, run.toolFenceLifecycle)
27
+ });
28
+ };
29
+ }
30
+ export {
31
+ createAgentHarnessTools
32
+ };
@@ -3,29 +3,30 @@ import {
3
3
  } from "../../index-nx6eazt0.js";
4
4
  import"../../index-8kzct1d6.js";
5
5
  import {
6
- createAgentRuntimeEventSink2,
7
6
  composeAgentPrompt2,
8
7
  createAgentRuntime2
9
- } from "../../index-zs4ms3th.js";
8
+ } from "../../index-z3pqcy7r.js";
10
9
  import"../../index-h97tqqp1.js";
11
10
  import"../../index-mnkk1ffz.js";
12
11
  import"../../index-n53mswt3.js";
13
12
  import"../../index-b2bz0kdm.js";
14
- import"../../index-hby4qhax.js";
13
+ import"../../index-yex7eg1v.js";
15
14
  import"../../index-9pw0a51a.js";
16
15
  import"../../index-ct75c3at.js";
17
16
  import"../../index-7z9ym7t8.js";
18
- import"../../index-dvwj1f43.js";
19
- import"../../index-a9pd417t.js";
17
+ import"../../index-0efgsyav.js";
18
+ import"../../index-5vyd0fkb.js";
19
+ import"../../index-nggfa2yn.js";
20
20
  import"../../index-r5hsgkz5.js";
21
+ import"../../index-n5yqxd3d.js";
21
22
  import {
22
- AgentControlRequestSchema2,
23
- AgentControlResponseSchema2
24
- } from "../../index-n5yqxd3d.js";
23
+ createAgentHarnessControlServer2
24
+ } from "../../index-jn9g8xdt.js";
25
+ import"../../index-vgkbcnkc.js";
25
26
  import {
26
27
  walkContainedFiles
27
28
  } from "../../index-ej331hah.js";
28
- import"../../index-r1z0rd9c.js";
29
+ import"../../index-7n68nmc6.js";
29
30
  import {
30
31
  defineRuntimeTool2
31
32
  } from "../../index-jzczzcsb.js";
@@ -264,222 +265,6 @@ function createAgentHarnessFileResources(config) {
264
265
  });
265
266
  return { load, runtimeTools: [readResource] };
266
267
  }
267
- // src/agent-runtime/harness-control.ts
268
- async function runControlledOperation(harness, request) {
269
- if (request.operation === "interrupt") {
270
- await harness.interrupt({
271
- conversationId: request.conversationId,
272
- runId: request.runId
273
- });
274
- return AgentControlResponseSchema2.parse({
275
- schemaVersion: 1,
276
- requestId: request.requestId,
277
- outcome: "ok",
278
- snapshot: await harness.snapshot(request.conversationId)
279
- });
280
- }
281
- if (request.operation === "respond-approval") {
282
- const ticket = await harness.respondToApproval({
283
- conversationId: request.conversationId,
284
- approvalId: request.approvalId,
285
- approved: request.approved,
286
- ...request.reason && { reason: request.reason },
287
- context: request.context,
288
- ...request.metadata !== undefined && { metadata: request.metadata }
289
- });
290
- const admission = await ticket.admission;
291
- return AgentControlResponseSchema2.parse({
292
- schemaVersion: 1,
293
- requestId: request.requestId,
294
- outcome: "ok",
295
- runId: admission.runId,
296
- snapshot: await harness.snapshot(request.conversationId)
297
- });
298
- }
299
- const ticket = harness.submit({
300
- conversationId: request.conversationId,
301
- idempotencyKey: request.idempotencyKey,
302
- context: request.context,
303
- parts: request.parts,
304
- ...request.metadata !== undefined && { metadata: request.metadata }
305
- });
306
- const admission = await ticket.admission;
307
- return AgentControlResponseSchema2.parse({
308
- schemaVersion: 1,
309
- requestId: request.requestId,
310
- outcome: "ok",
311
- runId: admission.runId,
312
- snapshot: await harness.snapshot(request.conversationId)
313
- });
314
- }
315
- function createAgentHarnessControlServer(harness, config = {}) {
316
- const maxPendingAttachments = config.maxPendingAttachments ?? 32;
317
- if (!Number.isSafeInteger(maxPendingAttachments) || maxPendingAttachments <= 0) {
318
- throw new TypeError("maxPendingAttachments must be a positive safe integer");
319
- }
320
- const connections = new Map;
321
- const controllers = new Map;
322
- let pendingAttachments = 0;
323
- let closed = false;
324
- const unsubscribe = harness.subscribe((event) => {
325
- for (const connection of connections.values()) {
326
- if (connection.attached.has(event.conversationId) && !connection.overflowed) {
327
- connection.sink.publish(event);
328
- }
329
- }
330
- });
331
- const detach = (connectionId) => {
332
- const connection = connections.get(connectionId);
333
- if (!connection)
334
- return;
335
- for (const conversationId of connection.attached.keys()) {
336
- if (controllers.get(conversationId) === connectionId) {
337
- controllers.delete(conversationId);
338
- }
339
- }
340
- connection.sink.close();
341
- connections.delete(connectionId);
342
- };
343
- return {
344
- connect({ id, deliver, onOverflow }) {
345
- if (closed)
346
- throw new Error("Agent harness control server is closed");
347
- if (connections.has(id))
348
- throw new Error("Agent harness control connection id is duplicate");
349
- const state = {
350
- attached: new Map,
351
- pendingAttachments: new Set,
352
- overflowed: false,
353
- sink: createAgentRuntimeEventSink2({
354
- write: (event) => deliver({ schemaVersion: 1, type: "event", event }),
355
- maxPending: config.maxPendingEvents ?? 128,
356
- onDrop: ({ event }) => {
357
- if (state.overflowed)
358
- return;
359
- state.overflowed = true;
360
- onOverflow({
361
- schemaVersion: 1,
362
- type: "resync-required",
363
- conversationId: event.conversationId,
364
- reason: "overflow"
365
- });
366
- detach(id);
367
- }
368
- })
369
- };
370
- connections.set(id, state);
371
- return {
372
- async request(raw) {
373
- const request = AgentControlRequestSchema2.parse(raw);
374
- const fail = (code, message) => AgentControlResponseSchema2.parse({
375
- schemaVersion: 1,
376
- requestId: request.requestId,
377
- outcome: "error",
378
- error: { code, message }
379
- });
380
- if (closed || connections.get(id) !== state)
381
- return fail("CONNECTION_CLOSED", "Connection is closed");
382
- try {
383
- if (request.operation === "attach") {
384
- if (state.pendingAttachments.has(request.conversationId)) {
385
- return fail("ATTACH_IN_PROGRESS", "Wait for the current attachment request to settle");
386
- }
387
- if (pendingAttachments >= maxPendingAttachments) {
388
- return fail("ATTACHMENT_CAPACITY", "Too many attachment snapshots are pending on this control server");
389
- }
390
- const owner = controllers.get(request.conversationId);
391
- if (request.access === "control" && owner && owner !== id) {
392
- return fail("LEASE_CONFLICT", "Conversation already has a controller");
393
- }
394
- const previousAccess = state.attached.get(request.conversationId);
395
- const previousController = controllers.get(request.conversationId);
396
- pendingAttachments += 1;
397
- state.pendingAttachments.add(request.conversationId);
398
- if (!previousAccess)
399
- state.attached.set(request.conversationId, request.access);
400
- if (request.access === "control")
401
- controllers.set(request.conversationId, id);
402
- let snapshot;
403
- try {
404
- snapshot = await harness.snapshot(request.conversationId);
405
- } catch (error) {
406
- if (connections.get(id) === state) {
407
- if (previousAccess)
408
- state.attached.set(request.conversationId, previousAccess);
409
- else
410
- state.attached.delete(request.conversationId);
411
- if (request.access === "control" && controllers.get(request.conversationId) === id && previousController) {
412
- controllers.set(request.conversationId, previousController);
413
- } else if (request.access === "control" && controllers.get(request.conversationId) === id) {
414
- controllers.delete(request.conversationId);
415
- }
416
- }
417
- throw error;
418
- } finally {
419
- pendingAttachments -= 1;
420
- state.pendingAttachments.delete(request.conversationId);
421
- }
422
- if (closed || connections.get(id) !== state) {
423
- return fail("CONNECTION_CLOSED", "Connection is closed");
424
- }
425
- state.attached.set(request.conversationId, request.access);
426
- if (request.access === "observe" && controllers.get(request.conversationId) === id) {
427
- controllers.delete(request.conversationId);
428
- }
429
- return AgentControlResponseSchema2.parse({
430
- schemaVersion: 1,
431
- requestId: request.requestId,
432
- outcome: "ok",
433
- snapshot
434
- });
435
- }
436
- if (state.pendingAttachments.has(request.conversationId)) {
437
- return fail("ATTACH_IN_PROGRESS", "Wait for the current attachment request to settle");
438
- }
439
- if (request.operation === "detach") {
440
- if (controllers.get(request.conversationId) === id)
441
- controllers.delete(request.conversationId);
442
- state.attached.delete(request.conversationId);
443
- return AgentControlResponseSchema2.parse({
444
- schemaVersion: 1,
445
- requestId: request.requestId,
446
- outcome: "ok"
447
- });
448
- }
449
- if (!state.attached.has(request.conversationId))
450
- return fail("NOT_ATTACHED", "Attach before requesting conversation state");
451
- if (request.operation === "snapshot") {
452
- const snapshot = await harness.snapshot(request.conversationId);
453
- return AgentControlResponseSchema2.parse({
454
- schemaVersion: 1,
455
- requestId: request.requestId,
456
- outcome: "ok",
457
- snapshot
458
- });
459
- }
460
- if (state.attached.get(request.conversationId) !== "control" || controllers.get(request.conversationId) !== id) {
461
- return fail("LEASE_REQUIRED", "An active controller lease is required");
462
- }
463
- return await runControlledOperation(harness, request);
464
- } catch {
465
- return fail("REQUEST_REJECTED", "Control request was rejected");
466
- }
467
- },
468
- close() {
469
- detach(id);
470
- }
471
- };
472
- },
473
- close() {
474
- if (closed)
475
- return;
476
- closed = true;
477
- unsubscribe();
478
- for (const id of [...connections.keys()])
479
- detach(id);
480
- }
481
- };
482
- }
483
268
 
484
269
  // src/agent-runtime/harness.ts
485
270
  class AgentHarnessApprovalRejectedError extends Error {
@@ -727,7 +512,7 @@ export {
727
512
  AgentHarnessResourceDiagnosticSchema,
728
513
  AgentHarnessResourceKindSchema,
729
514
  AgentHarnessResourceSchema,
730
- createAgentHarnessControlServer,
515
+ createAgentHarnessControlServer2 as createAgentHarnessControlServer,
731
516
  createAgentHarnessFileResources,
732
517
  createHeadlessAgentHarness
733
518
  };
@@ -0,0 +1,2 @@
1
+ export { useAgent } from '../../agent-runtime/react.js';
2
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../../src/entrypoints/agent-runtime/react.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,8 @@
1
+ // src/agent-runtime/react.ts
2
+ import { useSyncExternalStore } from "react";
3
+ function useAgent(controller) {
4
+ return useSyncExternalStore(controller.subscribe, controller.getSnapshot, controller.getSnapshot);
5
+ }
6
+ export {
7
+ useAgent
8
+ };
@@ -0,0 +1,2 @@
1
+ export { type AgentHarnessRealtimeConfig, bindAgentHarnessRealtime, } from '../../agent-runtime/harness-realtime.js';
2
+ //# sourceMappingURL=realtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../../src/entrypoints/agent-runtime/realtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,0BAA0B,EAC/B,wBAAwB,GACzB,MAAM,sCAAsC,CAAC"}