@ai-sdk/harness-acp 1.0.10 → 1.0.12

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @ai-sdk/harness-acp
2
2
 
3
+ ## 1.0.12
4
+
5
+ ### Patch Changes
6
+
7
+ - @ai-sdk/harness@1.0.74
8
+
9
+ ## 1.0.11
10
+
11
+ ### Patch Changes
12
+
13
+ - 62a9c2a: feat(harness): add support for structured output to `HarnessAgent` via `output` property
14
+ - Updated dependencies [62a9c2a]
15
+ - Updated dependencies [d25cae2]
16
+ - @ai-sdk/harness@1.0.73
17
+
3
18
  ## 1.0.10
4
19
 
5
20
  ### Patch Changes
@@ -12,7 +12,7 @@ import {
12
12
  ListToolsRequestSchema,
13
13
  McpError
14
14
  } from "@modelcontextprotocol/sdk/types.js";
15
- var VERSION = true ? "1.0.10" : "0.0.0-test";
15
+ var VERSION = true ? "1.0.12" : "0.0.0-test";
16
16
  function createHostToolMCPServer({
17
17
  tools: tools2,
18
18
  revision = 1,
@@ -69,7 +69,6 @@ async function runBridge(options) {
69
69
  let currentBoundPort = 0;
70
70
  let currentTurnState = "init";
71
71
  let activeSocket;
72
- let activeSocketReadyForLiveEvents = false;
73
72
  let isFirstTurn = true;
74
73
  let turnAbort;
75
74
  let currentUserMessages;
@@ -153,14 +152,6 @@ async function runBridge(options) {
153
152
  } catch {
154
153
  }
155
154
  };
156
- const sendControl = (msg) => {
157
- if (activeSocket?.readyState === WS_OPEN) {
158
- try {
159
- activeSocket.send(JSON.stringify(msg));
160
- } catch {
161
- }
162
- }
163
- };
164
155
  const emit = (event) => {
165
156
  const seq = ++seqCounter;
166
157
  const line = JSON.stringify({ ...event, seq });
@@ -168,7 +159,7 @@ async function runBridge(options) {
168
159
  diskBuffer += `${line}
169
160
  `;
170
161
  scheduleEventFlush();
171
- if (activeSocketReadyForLiveEvents && activeSocket?.readyState === WS_OPEN) {
162
+ if (activeSocket?.readyState === WS_OPEN) {
172
163
  try {
173
164
  activeSocket.send(line);
174
165
  } catch {
@@ -271,8 +262,7 @@ async function runBridge(options) {
271
262
  const handleInbound = async (msg, ws) => {
272
263
  switch (msg.type) {
273
264
  case "start": {
274
- if (activeSocket !== ws) return;
275
- activeSocketReadyForLiveEvents = true;
265
+ activeSocket = ws;
276
266
  const firstTurn = isFirstTurn;
277
267
  isFirstTurn = false;
278
268
  eventLog = [];
@@ -352,9 +342,8 @@ async function runBridge(options) {
352
342
  turnAbort?.abort();
353
343
  return;
354
344
  case "resume":
355
- if (activeSocket !== ws) return;
345
+ activeSocket = ws;
356
346
  replay(ws, msg.lastSeenEventId);
357
- activeSocketReadyForLiveEvents = true;
358
347
  return;
359
348
  case "destroy":
360
349
  currentTurnState = "done";
@@ -366,7 +355,7 @@ async function runBridge(options) {
366
355
  currentTurnState = "done";
367
356
  void writeBridgeMeta("done");
368
357
  const data = await onStop?.() ?? {};
369
- sendControl({ type: "bridge-stop", data });
358
+ sendControl(ws, { type: "bridge-stop", data });
370
359
  drainThenExit(ws, 1e3, "stop");
371
360
  return;
372
361
  }
@@ -419,9 +408,7 @@ async function runBridge(options) {
419
408
  ws.close(1008, "unauthorized");
420
409
  return;
421
410
  }
422
- activeSocket = ws;
423
- activeSocketReadyForLiveEvents = false;
424
- sendControl({
411
+ sendControl(ws, {
425
412
  type: "bridge-hello",
426
413
  state: currentTurnState,
427
414
  lastSeq: seqCounter
@@ -432,7 +419,7 @@ async function runBridge(options) {
432
419
  const text = typeof raw === "string" ? raw : Buffer.from(raw).toString("utf8");
433
420
  parsed = JSON.parse(text);
434
421
  } catch (err) {
435
- sendControl({
422
+ sendControl(ws, {
436
423
  type: "error",
437
424
  error: `protocol parse error: ${err.message}`
438
425
  });
@@ -443,7 +430,6 @@ async function runBridge(options) {
443
430
  ws.on("close", () => {
444
431
  if (activeSocket === ws) {
445
432
  activeSocket = void 0;
446
- activeSocketReadyForLiveEvents = false;
447
433
  }
448
434
  });
449
435
  ws.on("error", () => {
@@ -470,6 +456,14 @@ async function runBridge(options) {
470
456
  })
471
457
  };
472
458
  }
459
+ function sendControl(socket, message) {
460
+ if (socket?.readyState === WS_OPEN) {
461
+ try {
462
+ socket.send(JSON.stringify(message));
463
+ } catch {
464
+ }
465
+ }
466
+ }
473
467
  function serialiseError(err) {
474
468
  if (err instanceof Error) {
475
469
  return { name: err.name, message: err.message, stack: err.stack };
@@ -2740,6 +2734,27 @@ function createACPRecoveredSession({
2740
2734
  );
2741
2735
  return response;
2742
2736
  },
2737
+ promptWithMeta: async ({ prompt, meta }) => {
2738
+ if (disposed) {
2739
+ throw new Error("Recovered ACP session is disposed.");
2740
+ }
2741
+ updates.clearErrors();
2742
+ const response = agent.request(
2743
+ acp2.methods.agent.session.prompt,
2744
+ { sessionId, prompt, _meta: meta }
2745
+ );
2746
+ void response.then(
2747
+ (value) => {
2748
+ updates.enqueue({
2749
+ kind: "stop",
2750
+ response: value,
2751
+ stopReason: value.stopReason
2752
+ });
2753
+ },
2754
+ (error) => updates.reject(error)
2755
+ );
2756
+ return response;
2757
+ },
2743
2758
  nextUpdate: () => updates.next(),
2744
2759
  dispose: () => {
2745
2760
  if (disposed) return;
@@ -3041,7 +3056,13 @@ async function runTurn(start, turn) {
3041
3056
  };
3042
3057
  hostToolRelay?.bindTurn({ turn: relayTurn });
3043
3058
  try {
3044
- void activeSession.prompt(start.prompt);
3059
+ const promptMeta = createOutputSchemaPromptMeta({ start });
3060
+ void promptActiveSession({
3061
+ session: activeSession,
3062
+ agent: connection.agent,
3063
+ prompt: start.prompt,
3064
+ meta: promptMeta
3065
+ });
3045
3066
  if (turn.abortSignal.aborted) {
3046
3067
  await cancel();
3047
3068
  } else {
@@ -3428,6 +3449,60 @@ function createChildEnvironment({
3428
3449
  function isRecord7(value) {
3429
3450
  return value != null && typeof value === "object" && !Array.isArray(value);
3430
3451
  }
3452
+ function createOutputSchemaPromptMeta({
3453
+ start
3454
+ }) {
3455
+ if (start.responseFormat?.type !== "json" || start.responseFormat.schema == null || start.outputSchemaMapping?.type !== "session-prompt-meta") {
3456
+ return void 0;
3457
+ }
3458
+ const root = {};
3459
+ let target = root;
3460
+ const path = start.outputSchemaMapping.path;
3461
+ for (let index = 0; index < path.length - 1; index++) {
3462
+ const child2 = {};
3463
+ target[path[index]] = child2;
3464
+ target = child2;
3465
+ }
3466
+ target[path[path.length - 1]] = start.responseFormat.schema;
3467
+ return root;
3468
+ }
3469
+ function promptActiveSession({
3470
+ session: session2,
3471
+ agent,
3472
+ prompt,
3473
+ meta
3474
+ }) {
3475
+ if (meta == null) return session2.prompt(prompt);
3476
+ if (session2.promptWithMeta != null) {
3477
+ return session2.promptWithMeta({ prompt, meta });
3478
+ }
3479
+ const updates = session2.updates;
3480
+ if (updates == null) {
3481
+ throw new Error(
3482
+ "The installed ACP SDK cannot send session prompt metadata while preserving streamed updates."
3483
+ );
3484
+ }
3485
+ updates.clearErrors();
3486
+ const response = agent.request(
3487
+ acp4.methods.agent.session.prompt,
3488
+ {
3489
+ sessionId: session2.sessionId,
3490
+ prompt,
3491
+ _meta: meta
3492
+ }
3493
+ );
3494
+ void response.then(
3495
+ (value) => {
3496
+ updates.enqueue({
3497
+ kind: "stop",
3498
+ response: value,
3499
+ stopReason: value.stopReason
3500
+ });
3501
+ },
3502
+ (error) => updates.reject(error)
3503
+ );
3504
+ return response;
3505
+ }
3431
3506
  async function readImplementationDescriptor({
3432
3507
  path
3433
3508
  }) {