@ai-sdk/harness-pi 1.0.97 → 1.0.99

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,19 @@
1
1
  # @ai-sdk/harness-pi
2
2
 
3
+ ## 1.0.99
4
+
5
+ ### Patch Changes
6
+
7
+ - e115d16: fix(harness-pi): stream Pi tool input while it is generated
8
+ - @ai-sdk/harness@1.0.97
9
+
10
+ ## 1.0.98
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [c0c7fac]
15
+ - @ai-sdk/harness@1.0.96
16
+
3
17
  ## 1.0.97
4
18
 
5
19
  ### Patch Changes
package/dist/index.js CHANGED
@@ -134,7 +134,7 @@ import {
134
134
  import { access } from "fs/promises";
135
135
 
136
136
  // src/version.ts
137
- var VERSION = true ? "1.0.97" : "0.0.0-test";
137
+ var VERSION = true ? "1.0.99" : "0.0.0-test";
138
138
 
139
139
  // src/pi-auth.ts
140
140
  var DEFAULT_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
@@ -522,7 +522,13 @@ var piSessionEventSchema = z2.looseObject({
522
522
  type: z2.string(),
523
523
  assistantMessageEvent: z2.looseObject({
524
524
  type: z2.string().optional(),
525
- delta: z2.string().optional()
525
+ delta: z2.string().optional(),
526
+ // `toolcall_start` / `toolcall_delta` / `toolcall_end` address a content
527
+ // block by index rather than by tool call id. The id and name live in the
528
+ // partial assistant message at that index, which Pi fills in before the
529
+ // first delta arrives.
530
+ contentIndex: z2.number().optional(),
531
+ partial: z2.looseObject({ content: z2.array(z2.unknown()).optional() }).optional()
526
532
  }).optional(),
527
533
  toolCallId: z2.string().optional(),
528
534
  toolName: z2.string().optional(),
@@ -1047,6 +1053,7 @@ function createPiTranslatorState(options = {}) {
1047
1053
  currentReasoningId: void 0,
1048
1054
  reasoningStarted: false,
1049
1055
  observedToolNames: /* @__PURE__ */ new Map(),
1056
+ streamingToolInputIds: /* @__PURE__ */ new Map(),
1050
1057
  pendingStepToolCallIds: /* @__PURE__ */ new Set(),
1051
1058
  stepToolCallCount: void 0,
1052
1059
  stepOpen: false,
@@ -1091,6 +1098,26 @@ function resolveToolName(state, nativeName) {
1091
1098
  const common = state.nativeToCommonNameMap.get(nativeName);
1092
1099
  return { wire: common ?? nativeName, native: nativeName };
1093
1100
  }
1101
+ function resolveToolDispatch(state, nativeName) {
1102
+ const isMcpTool = !state.hostToolNames.has(nativeName) && (nativeName === "mcp" || nativeName.startsWith("mcp__"));
1103
+ return {
1104
+ isMcpTool,
1105
+ providerExecuted: state.builtinToolNames.has(nativeName) || isMcpTool
1106
+ };
1107
+ }
1108
+ function readStreamingToolCall(event) {
1109
+ const update = event.assistantMessageEvent;
1110
+ const contentIndex = update?.contentIndex;
1111
+ if (typeof contentIndex !== "number") return void 0;
1112
+ const block = update?.partial?.content?.[contentIndex];
1113
+ if (!block || typeof block !== "object") return void 0;
1114
+ const record = block;
1115
+ if (record.type !== "toolCall") return void 0;
1116
+ const { id, name } = record;
1117
+ if (typeof id !== "string" || id.length === 0) return void 0;
1118
+ if (typeof name !== "string" || name.length === 0) return void 0;
1119
+ return { contentIndex, id, name };
1120
+ }
1094
1121
  function finishStep(state) {
1095
1122
  if (!state.stepOpen || state.pendingStepToolCallIds.size > 0) return [];
1096
1123
  state.stepOpen = false;
@@ -1141,6 +1168,7 @@ function translatePiEvent(event, state) {
1141
1168
  state.currentTextId = void 0;
1142
1169
  state.currentReasoningId = void 0;
1143
1170
  state.reasoningStarted = false;
1171
+ state.streamingToolInputIds.clear();
1144
1172
  return [];
1145
1173
  }
1146
1174
  case "message_update": {
@@ -1189,6 +1217,37 @@ function translatePiEvent(event, state) {
1189
1217
  });
1190
1218
  return parts;
1191
1219
  }
1220
+ if (update.type === "toolcall_start") {
1221
+ const call = readStreamingToolCall(event);
1222
+ if (!call) return [];
1223
+ const { wire, native } = resolveToolName(state, call.name);
1224
+ const { isMcpTool, providerExecuted } = resolveToolDispatch(
1225
+ state,
1226
+ native
1227
+ );
1228
+ state.streamingToolInputIds.set(call.contentIndex, call.id);
1229
+ return [
1230
+ {
1231
+ type: "tool-input-start",
1232
+ id: call.id,
1233
+ toolName: wire,
1234
+ ...providerExecuted ? { providerExecuted: true } : {},
1235
+ ...isMcpTool ? { dynamic: true } : {}
1236
+ }
1237
+ ];
1238
+ }
1239
+ if (update.type === "toolcall_delta" || update.type === "toolcall_end") {
1240
+ const contentIndex = update.contentIndex;
1241
+ if (typeof contentIndex !== "number") return [];
1242
+ const id = state.streamingToolInputIds.get(contentIndex);
1243
+ if (id === void 0) return [];
1244
+ if (update.type === "toolcall_end") {
1245
+ state.streamingToolInputIds.delete(contentIndex);
1246
+ return [{ type: "tool-input-end", id }];
1247
+ }
1248
+ if (typeof update.delta !== "string") return [];
1249
+ return [{ type: "tool-input-delta", id, delta: update.delta }];
1250
+ }
1192
1251
  return [];
1193
1252
  }
1194
1253
  case "message_end":
@@ -1231,8 +1290,10 @@ function translatePiEvent(event, state) {
1231
1290
  if (!event.toolCallId || !event.toolName) return [];
1232
1291
  const { wire, native } = resolveToolName(state, event.toolName);
1233
1292
  state.observedToolNames.set(event.toolCallId, wire);
1234
- const isMcpTool = !state.hostToolNames.has(native) && (native === "mcp" || native.startsWith("mcp__"));
1235
- const providerExecuted = state.builtinToolNames.has(native) || isMcpTool;
1293
+ const { isMcpTool, providerExecuted } = resolveToolDispatch(
1294
+ state,
1295
+ native
1296
+ );
1236
1297
  if (isMcpTool) state.dynamicToolCallIds.add(event.toolCallId);
1237
1298
  const input = serializeToolOutput(event.args ?? event.input ?? {});
1238
1299
  return [