@ai-sdk/harness-opencode 1.0.95 → 1.0.97

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,26 @@
1
1
  # @ai-sdk/harness-opencode
2
2
 
3
+ ## 1.0.97
4
+
5
+ ### Patch Changes
6
+
7
+ - c1941f0: fix(harness-opencode): emit per-step token usage and cost for task-linked OpenCode subagent sessions as raw stream events
8
+ - 371e954: feat(harness): add `createBridgeToken()` and `withBridgeToken()` helpers for bridge backed harness adapters
9
+ - 62f481f: fix(harness): fix bridge resolution to no longer look for an alternative path which could cause Turbopack errors
10
+ - Updated dependencies [371e954]
11
+ - Updated dependencies [87b4858]
12
+ - @ai-sdk/harness@1.0.95
13
+
14
+ ## 1.0.96
15
+
16
+ ### Patch Changes
17
+
18
+ - 8961fde: feat(harness): allow changing `model` between turns via call options
19
+ - Updated dependencies [8961fde]
20
+ - Updated dependencies [eb59f2a]
21
+ - @ai-sdk/harness@1.0.94
22
+ - @ai-sdk/provider-utils@5.0.34
23
+
3
24
  ## 1.0.95
4
25
 
5
26
  ### Patch Changes
@@ -1713,6 +1713,7 @@ async function runTurn(start, turn) {
1713
1713
  await client.instance.dispose({ directory: workdir });
1714
1714
  }
1715
1715
  const sessionId = await ensureSession({ client, start, emit });
1716
+ await switchSessionModel({ client, sessionId, start });
1716
1717
  if (start.operation === "compact") {
1717
1718
  await runCompaction({ client, sessionId, start, turn, emit });
1718
1719
  } else {
@@ -1729,6 +1730,22 @@ async function runTurn(start, turn) {
1729
1730
  });
1730
1731
  }
1731
1732
  }
1733
+ async function switchSessionModel({
1734
+ client,
1735
+ sessionId,
1736
+ start
1737
+ }) {
1738
+ const model = modelRefFromStart(start);
1739
+ if (model == null) return;
1740
+ const response = await client.v2.session.switchModel({
1741
+ sessionID: sessionId,
1742
+ model: {
1743
+ id: model.modelID,
1744
+ providerID: model.providerID
1745
+ }
1746
+ });
1747
+ if (response.error != null) throw response.error;
1748
+ }
1732
1749
  async function ensureRuntime({
1733
1750
  start,
1734
1751
  turn,
@@ -2354,9 +2371,33 @@ async function consumeEvents({
2354
2371
  let processEvent = descendantEventProcessors.get(descendantSessionId);
2355
2372
  if (!processEvent) {
2356
2373
  const descendantState = createTranslationState();
2374
+ let currentEvent;
2375
+ let modelId;
2376
+ const emittedUsageStepIds = /* @__PURE__ */ new Set();
2357
2377
  processEvent = createEmitStreamEvent({
2358
2378
  state: descendantState,
2359
- emit: () => void 0,
2379
+ emit: (message) => {
2380
+ if (message.type !== "finish-step") return;
2381
+ const stepId = getSubagentStepId(currentEvent);
2382
+ if (!stepId || emittedUsageStepIds.has(stepId)) return;
2383
+ emittedUsageStepIds.add(stepId);
2384
+ const opencodeMetadata = asOpenCodeObject(
2385
+ message.harnessMetadata
2386
+ )?.opencode;
2387
+ const cost = asOpenCodeObject(opencodeMetadata)?.cost;
2388
+ emit({
2389
+ type: "raw",
2390
+ rawValue: {
2391
+ type: "opencode.subagent-usage",
2392
+ version: 1,
2393
+ sessionId: descendantSessionId,
2394
+ stepId,
2395
+ ...modelId ? { modelId } : {},
2396
+ usage: message.usage,
2397
+ ...typeof cost === "number" ? { cost } : {}
2398
+ }
2399
+ });
2400
+ },
2360
2401
  emitWarning: () => void 0,
2361
2402
  emitError: () => void 0,
2362
2403
  toWireToolName,
@@ -2368,6 +2409,19 @@ async function consumeEvents({
2368
2409
  stripWorkDir,
2369
2410
  formatError
2370
2411
  });
2412
+ const emitDescendantEvent = processEvent;
2413
+ processEvent = (descendantEvent) => {
2414
+ currentEvent = descendantEvent;
2415
+ if (descendantEvent.type === "message.updated") {
2416
+ const info = openCodeMessageInfoFromValue(
2417
+ descendantEvent.properties?.info
2418
+ );
2419
+ const providerID = stringValue2(info?.providerID);
2420
+ const modelID = stringValue2(info?.modelID);
2421
+ if (providerID && modelID) modelId = `${providerID}/${modelID}`;
2422
+ }
2423
+ emitDescendantEvent(descendantEvent);
2424
+ };
2371
2425
  descendantEventProcessors.set(descendantSessionId, processEvent);
2372
2426
  }
2373
2427
  processEvent(event);
@@ -2409,6 +2463,15 @@ async function consumeEvents({
2409
2463
  if (onEvent?.(event)) break;
2410
2464
  }
2411
2465
  }
2466
+ function getSubagentStepId(event) {
2467
+ if (event?.type === "message.part.updated") {
2468
+ const part = asOpenCodeObject(event.properties?.part);
2469
+ if (part?.type !== "step-finish") return void 0;
2470
+ return stringValue2(part.id) ?? stringValue2(part.messageID) ?? event.id;
2471
+ }
2472
+ if (event?.type !== "session.next.step.ended") return void 0;
2473
+ return stringValue2(event.properties?.stepID) ?? event.id;
2474
+ }
2412
2475
  function sanitizeMcpToolName(value) {
2413
2476
  return value.replace(/[^a-zA-Z0-9_-]/g, "_");
2414
2477
  }