@opencode-ai/ai 0.0.0-dev-18059 → 0.0.0-dev-18062

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.
@@ -461,6 +461,7 @@ type ReasoningSummaryStatus = "active" | "can-conclude" | "concluded";
461
461
  interface ReasoningStreamItem {
462
462
  readonly encryptedContent: string | null | undefined;
463
463
  readonly summaryParts: Readonly<Record<number, ReasoningSummaryStatus>>;
464
+ readonly deltaIndexes: ReadonlySet<number>;
464
465
  }
465
466
  export declare const lowerTool: (protocolName: string, tool: ToolDefinition, inputSchema: {
466
467
  readonly [x: string]: unknown;
@@ -651,7 +652,7 @@ export declare const providerMetadata: (state: ParserState, metadata: Record<str
651
652
  export type StepResult = readonly [ParserState, ReadonlyArray<LLMEvent>];
652
653
  export declare const terminal: (event: Event) => boolean;
653
654
  export declare const onReasoningDelta: (state: ParserState, event: Event, itemID: string) => StepResult;
654
- export declare const onReasoningDone: (state: ParserState, _event: Event) => StepResult;
655
+ export declare const onReasoningDone: (state: ParserState, event: Event, itemID: string) => StepResult;
655
656
  export declare const providerFailure: (id: string, event: Event, fallback: string) => AIError;
656
657
  export declare const step: (state: ParserState, event: Event) => AIError | Effect.Effect<StepResult, never, never> | Effect.Effect<[ParserState, readonly ({
657
658
  readonly type: "step-start";
@@ -595,19 +595,35 @@ const onOutputTextDone = (state, event, id) => {
595
595
  return [{ ...state, lifecycle: Lifecycle.textEnd(state.lifecycle, events, id) }, events];
596
596
  };
597
597
  export const onReasoningDelta = (state, event, itemID) => {
598
- if (!event.delta || !state.reasoningItems[itemID])
598
+ const item = state.reasoningItems[itemID];
599
+ if (!event.delta || !item)
599
600
  return [state, NO_EVENTS];
601
+ const index = event.summary_index ?? 0;
600
602
  const events = [];
601
- const id = `${itemID}:${event.summary_index ?? 0}`;
602
603
  return [
603
604
  {
604
605
  ...state,
605
- lifecycle: Lifecycle.reasoningDelta(state.lifecycle, events, id, event.delta),
606
+ lifecycle: Lifecycle.reasoningDelta(state.lifecycle, events, `${itemID}:${index}`, event.delta),
607
+ reasoningItems: {
608
+ ...state.reasoningItems,
609
+ [itemID]: { ...item, deltaIndexes: new Set([...item.deltaIndexes, index]) },
610
+ },
606
611
  },
607
612
  events,
608
613
  ];
609
614
  };
610
- export const onReasoningDone = (state, _event) => [state, NO_EVENTS];
615
+ // Some compatible gateways emit a reasoning final without streaming any
616
+ // deltas, mirroring `response.output_text.done`. Reconcile the complete text
617
+ // as a single delta unless that summary index already streamed one.
618
+ export const onReasoningDone = (state, event, itemID) => {
619
+ const item = state.reasoningItems[itemID];
620
+ if (!item || typeof event.text !== "string")
621
+ return [state, NO_EVENTS];
622
+ const index = event.summary_index ?? 0;
623
+ if (item.deltaIndexes.has(index))
624
+ return [state, NO_EVENTS];
625
+ return onReasoningDelta(state, { ...event, delta: event.text }, itemID);
626
+ };
611
627
  const reasoningMetadata = (state, item) => providerMetadata(state, { itemId: item.id, reasoningEncryptedContent: item.encrypted_content ?? null });
612
628
  // Responses APIs stream reasoning items in a stable order:
613
629
  // `output_item.added` (reasoning) →
@@ -642,7 +658,11 @@ const onOutputItemAdded = (state, event) => {
642
658
  lifecycle: Lifecycle.reasoningStart(state.lifecycle, events, `${item.id}:0`, reasoningMetadata(state, item)),
643
659
  reasoningItems: {
644
660
  ...state.reasoningItems,
645
- [item.id]: { encryptedContent: item.encrypted_content, summaryParts: { 0: "active" } },
661
+ [item.id]: {
662
+ encryptedContent: item.encrypted_content,
663
+ summaryParts: { 0: "active" },
664
+ deltaIndexes: new Set(),
665
+ },
646
666
  },
647
667
  },
648
668
  events,
@@ -895,6 +915,14 @@ export const step = (state, event) => {
895
915
  return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
896
916
  return Effect.succeed(onReasoningDelta(state, event, event.item_id));
897
917
  }
918
+ if (event.type === "response.reasoning.done" ||
919
+ event.type === "response.reasoning_summary_text.done" ||
920
+ event.type === "response.reasoning_summary.done" ||
921
+ event.type === "response.reasoning_text.done") {
922
+ if (!event.item_id)
923
+ return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
924
+ return Effect.succeed(onReasoningDone(state, event, event.item_id));
925
+ }
898
926
  if (event.type === "response.reasoning_summary_part.added")
899
927
  return event.item_id
900
928
  ? Effect.succeed(onReasoningSummaryPartAdded(state, event))
@@ -139,10 +139,6 @@ const step = (state, event) => {
139
139
  return event.item_id
140
140
  ? Effect.succeed(OpenResponses.onReasoningDelta(state, event, event.item_id))
141
141
  : ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
142
- if (event.type === "response.reasoning_text.done" || event.type === "response.reasoning_summary.done")
143
- return event.item_id
144
- ? Effect.succeed(OpenResponses.onReasoningDone(state, event))
145
- : ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
146
142
  if (event.type === "response.output_item.done" && event.item && ResponsesHostedTools.isItem(event.item, HOSTED_TOOLS))
147
143
  return ResponsesHostedTools.onDone(state, event.item, HOSTED_TOOLS);
148
144
  return OpenResponses.step(state, event);
@@ -1,7 +1,5 @@
1
- import { Effect } from "effect";
2
1
  import { Protocol } from "../route/protocol.js";
3
2
  import { OpenResponses } from "./open-responses.js";
4
- import { ProviderShared } from "./shared.js";
5
3
  import { ResponsesHostedTools } from "./utils/responses-hosted-tools.js";
6
4
  const ADAPTER = "xai-responses";
7
5
  const NAME = "xAI Responses";
@@ -23,15 +21,9 @@ const HOSTED_TOOLS = {
23
21
  input: (item) => ({ server_label: item.server_label, name: item.name, arguments: item.arguments }),
24
22
  },
25
23
  };
24
+ // Grok speaks the standard Responses reasoning dialect (`reasoning_summary_text.*`,
25
+ // handled by the baseline); only its hosted tool vocabulary differs.
26
26
  const step = (state, event) => {
27
- if (event.type === "response.reasoning_text.delta" || event.type === "response.reasoning_summary.delta")
28
- return event.item_id
29
- ? Effect.succeed(OpenResponses.onReasoningDelta(state, event, event.item_id))
30
- : ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
31
- if (event.type === "response.reasoning_text.done" || event.type === "response.reasoning_summary.done")
32
- return event.item_id
33
- ? Effect.succeed(OpenResponses.onReasoningDone(state, event))
34
- : ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
35
27
  if (event.type === "response.output_item.done" && event.item && ResponsesHostedTools.isItem(event.item, HOSTED_TOOLS))
36
28
  return ResponsesHostedTools.onDone(state, event.item, HOSTED_TOOLS);
37
29
  return OpenResponses.step(state, event);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "0.0.0-dev-18059",
3
+ "version": "0.0.0-dev-18062",
4
4
  "name": "@opencode-ai/ai",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "devDependencies": {
31
31
  "@clack/prompts": "1.0.0-alpha.1",
32
32
  "@effect/platform-node": "4.0.0-rc.111",
33
- "@opencode-ai/http-recorder": "0.0.0-dev-18059",
33
+ "@opencode-ai/http-recorder": "0.0.0-dev-18062",
34
34
  "@tsconfig/bun": "1.0.9",
35
35
  "@types/bun": "1.3.13",
36
36
  "@typescript/native-preview": "7.0.0-dev.20251207.1",
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "@smithy/eventstream-codec": "4.2.14",
41
41
  "@smithy/util-utf8": "4.2.2",
42
- "@opencode-ai/schema": "0.0.0-dev-18059",
42
+ "@opencode-ai/schema": "0.0.0-dev-18062",
43
43
  "aws4fetch": "1.0.20",
44
44
  "effect": "4.0.0-rc.111",
45
45
  "google-auth-library": "10.5.0"