@opencode-ai/ai 0.0.0-dev-17938 → 0.0.0-dev-17945
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.
|
@@ -451,7 +451,6 @@ export interface ParserState {
|
|
|
451
451
|
readonly hasFunctionCall: boolean;
|
|
452
452
|
readonly lifecycle: Lifecycle.State;
|
|
453
453
|
readonly messageItems: ReadonlySet<string>;
|
|
454
|
-
readonly messagePhase: (value: unknown) => MessagePhase | null | undefined;
|
|
455
454
|
readonly messagePhases: Readonly<Record<string, MessagePhase | null>>;
|
|
456
455
|
readonly reasoningItems: Readonly<Record<string, ReasoningStreamItem>>;
|
|
457
456
|
readonly store: boolean | undefined;
|
|
@@ -39,6 +39,11 @@ const OpenResponsesOutputText = Schema.Struct({
|
|
|
39
39
|
text: Schema.String,
|
|
40
40
|
});
|
|
41
41
|
export const MessagePhase = Schema.NullOr(Schema.Literals(["commentary", "final_answer"]));
|
|
42
|
+
const messagePhase = (value) => {
|
|
43
|
+
if (value === null || value === "commentary" || value === "final_answer")
|
|
44
|
+
return value;
|
|
45
|
+
return undefined;
|
|
46
|
+
};
|
|
42
47
|
const OpenResponsesReasoningSummaryText = Schema.Struct({
|
|
43
48
|
type: Schema.tag("summary_text"),
|
|
44
49
|
text: Schema.String,
|
|
@@ -218,19 +223,6 @@ export const Event = Schema.StructWithRest(Schema.Struct({
|
|
|
218
223
|
status_code: Schema.optional(Schema.Unknown),
|
|
219
224
|
headers: Schema.optional(Schema.Unknown),
|
|
220
225
|
}), [Schema.Record(Schema.String, Schema.Unknown)]);
|
|
221
|
-
const RefusalEvent = Schema.Union([
|
|
222
|
-
Schema.Struct({
|
|
223
|
-
type: Schema.tag("response.refusal.delta"),
|
|
224
|
-
item_id: Schema.String,
|
|
225
|
-
delta: Schema.String,
|
|
226
|
-
}),
|
|
227
|
-
Schema.Struct({
|
|
228
|
-
type: Schema.tag("response.refusal.done"),
|
|
229
|
-
item_id: Schema.String,
|
|
230
|
-
refusal: Schema.String,
|
|
231
|
-
}),
|
|
232
|
-
]);
|
|
233
|
-
const isRefusalEvent = Schema.is(RefusalEvent);
|
|
234
226
|
const BASE = { id: ADAPTER, name: NAME };
|
|
235
227
|
// =============================================================================
|
|
236
228
|
// Request Lowering
|
|
@@ -284,9 +276,6 @@ const lowerReasoning = (part, providerMetadataKey) => {
|
|
|
284
276
|
encrypted_content: encryptedContent,
|
|
285
277
|
};
|
|
286
278
|
};
|
|
287
|
-
const hostedToolItemID = (part, providerMetadataKey) => {
|
|
288
|
-
return itemID(part.providerMetadata, providerMetadataKey);
|
|
289
|
-
};
|
|
290
279
|
const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (part, request, extension, target) {
|
|
291
280
|
const media = ProviderShared.normalizeMedia(part);
|
|
292
281
|
const extended = extension.lowerMedia?.({ part, media, request });
|
|
@@ -424,9 +413,9 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (reques
|
|
|
424
413
|
}
|
|
425
414
|
if (part.type === "tool-result" && part.providerExecuted === true) {
|
|
426
415
|
flushText();
|
|
427
|
-
const
|
|
428
|
-
if (store !== false &&
|
|
429
|
-
input.push({ type: "item_reference", id
|
|
416
|
+
const id = itemID(part.providerMetadata, providerMetadataKey);
|
|
417
|
+
if (store !== false && id && !hostedToolReferences.has(id))
|
|
418
|
+
input.push({ type: "item_reference", id });
|
|
430
419
|
if (store === false && part.result.type === "content") {
|
|
431
420
|
const content = part.result.value;
|
|
432
421
|
input.push({
|
|
@@ -434,8 +423,8 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (reques
|
|
|
434
423
|
content: yield* Effect.forEach(content, (item) => lowerHostedToolResultContentItem(item, request, extension)),
|
|
435
424
|
});
|
|
436
425
|
}
|
|
437
|
-
if (
|
|
438
|
-
hostedToolReferences.add(
|
|
426
|
+
if (id)
|
|
427
|
+
hostedToolReferences.add(id);
|
|
439
428
|
continue;
|
|
440
429
|
}
|
|
441
430
|
return yield* ProviderShared.unsupportedContent(extension.name, "assistant", [
|
|
@@ -619,18 +608,17 @@ const reasoningMetadata = (state, item) => providerMetadata(state, { itemId: ite
|
|
|
619
608
|
// best-effort, not guaranteed.
|
|
620
609
|
const onOutputItemAdded = (state, event) => {
|
|
621
610
|
const item = event.item;
|
|
622
|
-
if (item?.type === "message" && item.id)
|
|
611
|
+
if (item?.type === "message" && item.id) {
|
|
612
|
+
const phase = messagePhase(item.phase);
|
|
623
613
|
return [
|
|
624
614
|
{
|
|
625
615
|
...state,
|
|
626
616
|
messageItems: new Set([...state.messageItems, item.id]),
|
|
627
|
-
messagePhases:
|
|
628
|
-
const phase = state.messagePhase(item.phase);
|
|
629
|
-
return phase === undefined ? state.messagePhases : { ...state.messagePhases, [item.id]: phase };
|
|
630
|
-
})(),
|
|
617
|
+
messagePhases: phase === undefined ? state.messagePhases : { ...state.messagePhases, [item.id]: phase },
|
|
631
618
|
},
|
|
632
619
|
NO_EVENTS,
|
|
633
620
|
];
|
|
621
|
+
}
|
|
634
622
|
if (item && isReasoningItem(item)) {
|
|
635
623
|
const events = [];
|
|
636
624
|
return [
|
|
@@ -752,7 +740,7 @@ const onOutputItemDone = Effect.fn("OpenResponses.onOutputItemDone")(function* (
|
|
|
752
740
|
if (!item)
|
|
753
741
|
return [state, NO_EVENTS];
|
|
754
742
|
if (item.type === "message" && item.id) {
|
|
755
|
-
const itemPhase =
|
|
743
|
+
const itemPhase = messagePhase(item.phase);
|
|
756
744
|
const phase = itemPhase === undefined ? state.messagePhases[item.id] : itemPhase;
|
|
757
745
|
const events = [];
|
|
758
746
|
const messageItems = new Set(state.messageItems);
|
|
@@ -843,22 +831,26 @@ const onResponseFinish = Effect.fn("OpenResponses.onResponseFinish")(function* (
|
|
|
843
831
|
});
|
|
844
832
|
return [{ ...state, lifecycle, hasFunctionCall, tools: pending.tools }, events];
|
|
845
833
|
});
|
|
846
|
-
// Build
|
|
834
|
+
// Build the prettiest summary available from whatever the provider supplied.
|
|
847
835
|
// When both code and message are present, prefix the code so consumers see
|
|
848
836
|
// the failure mode (e.g. `rate_limit_exceeded: Slow down`) instead of just
|
|
849
837
|
// the bare message — production rate limits and context-length failures used
|
|
850
|
-
// to be indistinguishable from generic stream drops.
|
|
851
|
-
|
|
852
|
-
|
|
838
|
+
// to be indistinguishable from generic stream drops. Returns undefined when
|
|
839
|
+
// the payload carries no usable summary.
|
|
840
|
+
const providerErrorMessage = (event, nested) => {
|
|
853
841
|
const message = event.message || nested?.message || undefined;
|
|
854
842
|
const code = event.code || nested?.code || undefined;
|
|
855
843
|
if (message && code)
|
|
856
844
|
return `${code}: ${message}`;
|
|
857
|
-
return message || code
|
|
845
|
+
return message || code;
|
|
858
846
|
};
|
|
859
847
|
export const providerFailure = (id, event, fallback) => {
|
|
860
|
-
const
|
|
861
|
-
const
|
|
848
|
+
const nested = event.error ?? event.response?.error ?? undefined;
|
|
849
|
+
const code = event.code || nested?.code || undefined;
|
|
850
|
+
// Keep the full raw payload on the error even when the message is a summary.
|
|
851
|
+
const body = JSON.stringify(nested ?? event) ?? "";
|
|
852
|
+
const summary = providerErrorMessage(event, nested);
|
|
853
|
+
const message = summary ?? (body === "{}" ? fallback : body);
|
|
862
854
|
const status = typeof event.status === "number"
|
|
863
855
|
? event.status
|
|
864
856
|
: typeof event.status_code === "number"
|
|
@@ -867,7 +859,8 @@ export const providerFailure = (id, event, fallback) => {
|
|
|
867
859
|
return new AIError({
|
|
868
860
|
module: id,
|
|
869
861
|
method: "stream",
|
|
870
|
-
|
|
862
|
+
body,
|
|
863
|
+
reason: classifyProviderFailure({ message, code, status, rawBody: body }),
|
|
871
864
|
});
|
|
872
865
|
};
|
|
873
866
|
const providerError = (state, event, fallback) => providerFailure(state.id, event, fallback);
|
|
@@ -880,22 +873,18 @@ export const step = (state, event) => {
|
|
|
880
873
|
: onOutputTextDone(state, event, event.item_id));
|
|
881
874
|
}
|
|
882
875
|
if (event.type === "response.refusal.delta" || event.type === "response.refusal.done") {
|
|
883
|
-
|
|
876
|
+
const value = event.type === "response.refusal.delta" ? event.delta : event.refusal;
|
|
877
|
+
if (!event.item_id || typeof value !== "string")
|
|
884
878
|
return ProviderShared.eventError(state.id, `${event.type} is malformed`);
|
|
885
879
|
return Effect.succeed(event.type === "response.refusal.delta"
|
|
886
880
|
? onOutputTextDelta(state, event, event.item_id)
|
|
887
|
-
: onOutputTextDone(state, { ...event, text:
|
|
881
|
+
: onOutputTextDone(state, { ...event, text: value }, event.item_id));
|
|
888
882
|
}
|
|
889
883
|
if (event.type === "response.reasoning.delta" || event.type === "response.reasoning_summary_text.delta") {
|
|
890
884
|
if (!event.item_id)
|
|
891
885
|
return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
|
|
892
886
|
return Effect.succeed(onReasoningDelta(state, event, event.item_id));
|
|
893
887
|
}
|
|
894
|
-
if (event.type === "response.reasoning.done" || event.type === "response.reasoning_summary_text.done") {
|
|
895
|
-
if (!event.item_id)
|
|
896
|
-
return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
|
|
897
|
-
return Effect.succeed(onReasoningDone(state, event));
|
|
898
|
-
}
|
|
899
888
|
if (event.type === "response.reasoning_summary_part.added")
|
|
900
889
|
return event.item_id
|
|
901
890
|
? Effect.succeed(onReasoningSummaryPartAdded(state, event))
|
|
@@ -939,16 +928,10 @@ export const initial = (request, extension = BASE) => ({
|
|
|
939
928
|
tools: ToolStream.empty(),
|
|
940
929
|
lifecycle: Lifecycle.initial(),
|
|
941
930
|
messageItems: new Set(),
|
|
942
|
-
messagePhase,
|
|
943
931
|
messagePhases: {},
|
|
944
932
|
reasoningItems: {},
|
|
945
933
|
store: OpenResponsesOptions.resolve(request).store,
|
|
946
934
|
});
|
|
947
|
-
const messagePhase = (value) => {
|
|
948
|
-
if (value === null || value === "commentary" || value === "final_answer")
|
|
949
|
-
return value;
|
|
950
|
-
return undefined;
|
|
951
|
-
};
|
|
952
935
|
export const protocol = Protocol.make({
|
|
953
936
|
id: ADAPTER,
|
|
954
937
|
body: {
|
package/dist/provider-error.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface ProviderFailure {
|
|
|
6
6
|
readonly message: string;
|
|
7
7
|
readonly status?: number | undefined;
|
|
8
8
|
readonly code?: string | undefined;
|
|
9
|
+
readonly rawBody?: string | undefined;
|
|
9
10
|
readonly retryAfterMs?: number | undefined;
|
|
10
11
|
readonly rateLimit?: HttpRateLimitDetails | undefined;
|
|
11
12
|
readonly http?: HttpContext | undefined;
|
package/dist/provider-error.js
CHANGED
|
@@ -56,11 +56,13 @@ const NETWORK_ERROR_TEXT = /network[-_\s]error/i;
|
|
|
56
56
|
// Keep HTTP failures and provider-reported stream failures on one typed path so
|
|
57
57
|
// session retry policy never needs provider-specific string matching.
|
|
58
58
|
export function classifyProviderFailure(input) {
|
|
59
|
-
const body = input.http?.body ?? "";
|
|
59
|
+
const body = input.http?.body ?? input.rawBody ?? "";
|
|
60
60
|
const codes = [input.code, ...providerCodes(body), ...providerCodes(input.message)]
|
|
61
61
|
.filter((code) => code !== undefined)
|
|
62
62
|
.map((code) => code.toLowerCase());
|
|
63
|
-
|
|
63
|
+
// Scan the raw payload too so signals missing from the summary message
|
|
64
|
+
// (e.g. overflow phrases nested in a JSON error body) still classify.
|
|
65
|
+
const text = [input.message, body].filter((value) => value.length > 0).join("\n");
|
|
64
66
|
const common = { message: input.message, providerMetadata: input.providerMetadata, http: input.http };
|
|
65
67
|
const clientScoped = input.status === undefined || (input.status >= 400 && input.status < 500);
|
|
66
68
|
if (clientScoped &&
|
package/dist/schema/errors.d.ts
CHANGED
|
@@ -140,6 +140,7 @@ declare const AIError_base: Schema.Class<AIError, Schema.TaggedStruct<"AI.Error"
|
|
|
140
140
|
readonly module: Schema.String;
|
|
141
141
|
readonly method: Schema.String;
|
|
142
142
|
readonly reason: Schema.toTaggedUnion<"_tag", readonly [typeof InvalidRequestReason, typeof NoRouteReason, typeof AuthenticationReason, typeof RateLimitReason, typeof QuotaExceededReason, typeof ContentPolicyReason, typeof ProviderInternalReason, typeof TransportReason, typeof InvalidProviderOutputReason, typeof UnknownProviderReason]>;
|
|
143
|
+
readonly body: Schema.optional<Schema.String>;
|
|
143
144
|
}>, import("effect/Cause").YieldableError>;
|
|
144
145
|
export declare class AIError extends AIError_base {
|
|
145
146
|
readonly cause: InvalidRequestReason | NoRouteReason | AuthenticationReason | RateLimitReason | QuotaExceededReason | ContentPolicyReason | ProviderInternalReason | TransportReason | InvalidProviderOutputReason | UnknownProviderReason;
|
package/dist/schema/errors.js
CHANGED
|
@@ -137,6 +137,9 @@ export class AIError extends Schema.TaggedError()("AI.Error", {
|
|
|
137
137
|
module: Schema.String,
|
|
138
138
|
method: Schema.String,
|
|
139
139
|
reason: AIErrorReason,
|
|
140
|
+
// Raw provider payload as a string, so classified failures never lose the
|
|
141
|
+
// original error detail even when the pretty message is a summary.
|
|
142
|
+
body: Schema.optional(Schema.String),
|
|
140
143
|
}) {
|
|
141
144
|
cause = this.reason;
|
|
142
145
|
get message() {
|
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-
|
|
3
|
+
"version": "0.0.0-dev-17945",
|
|
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.110",
|
|
33
|
-
"@opencode-ai/http-recorder": "0.0.0-dev-
|
|
33
|
+
"@opencode-ai/http-recorder": "0.0.0-dev-17945",
|
|
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-
|
|
42
|
+
"@opencode-ai/schema": "0.0.0-dev-17945",
|
|
43
43
|
"aws4fetch": "1.0.20",
|
|
44
44
|
"effect": "4.0.0-rc.110",
|
|
45
45
|
"google-auth-library": "10.5.0"
|