New:Socket for Asana Is Now Available.Learn more
Get Started

@opencode-ai/ai

Package Overview
Dependencies
Maintainers
2
Versions
1035
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@opencode-ai/ai - npm Package Compare versions

Comparing version
0.0.0-dev-18545
to
0.0.0-dev-18548
+2
-0
dist/llm.d.ts

@@ -48,2 +48,3 @@ import { Effect, JsonSchema, Schema } from "effect";

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -74,2 +75,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -76,0 +78,0 @@ readonly [x: string]: {

@@ -832,2 +832,3 @@ import { Effect, Schema } from "effect";

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -858,2 +859,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -860,0 +862,0 @@ readonly [x: string]: {

+6
-2

@@ -13,4 +13,8 @@ import { LLMEvent, type FinishReasonDetails, type ProviderMetadata, type Usage } from "../../schema/index.js";

export declare const reasoningDelta: (state: State, events: LLMEvent[], id: string, text: string, providerMetadata?: ProviderMetadata) => State;
export declare const reasoningEnd: (state: State, events: LLMEvent[], id: string, providerMetadata?: ProviderMetadata) => State;
export declare const textEnd: (state: State, events: LLMEvent[], id: string, providerMetadata?: ProviderMetadata) => State;
export declare const reasoningEnd: (state: State, events: LLMEvent[], id: string, providerMetadata?: ProviderMetadata,
/** Authoritative complete value; replaces accumulated deltas when present. */
text?: string) => State;
export declare const textEnd: (state: State, events: LLMEvent[], id: string, providerMetadata?: ProviderMetadata,
/** Authoritative complete value; replaces accumulated deltas when present. */
text?: string) => State;
export declare const finish: (state: State, events: LLMEvent[], input: {

@@ -17,0 +21,0 @@ readonly reason: FinishReasonDetails;

@@ -33,7 +33,9 @@ import { LLMEvent } from "../../schema/index.js";

};
export const reasoningEnd = (state, events, id, providerMetadata) => {
export const reasoningEnd = (state, events, id, providerMetadata,
/** Authoritative complete value; replaces accumulated deltas when present. */
text) => {
if (!state.reasoning.has(id))
return state;
const stepped = stepStart(state, events);
events.push(LLMEvent.reasoningEnd({ id, providerMetadata }));
events.push(LLMEvent.reasoningEnd({ id, text, providerMetadata }));
const reasoning = new Set(stepped.reasoning);

@@ -43,10 +45,12 @@ reasoning.delete(id);

};
export const textEnd = (state, events, id, providerMetadata) => {
export const textEnd = (state, events, id, providerMetadata,
/** Authoritative complete value; replaces accumulated deltas when present. */
text) => {
if (!state.text.has(id))
return state;
const stepped = stepStart(state, events);
events.push(LLMEvent.textEnd({ id, providerMetadata }));
const text = new Set(stepped.text);
text.delete(id);
return { ...stepped, text };
events.push(LLMEvent.textEnd({ id, text, providerMetadata }));
const open = new Set(stepped.text);
open.delete(id);
return { ...stepped, text: open };
};

@@ -53,0 +57,0 @@ const closeOpenBlocks = (state, events) => {

@@ -96,2 +96,3 @@ import { Effect } from "effect";

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -122,2 +123,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -292,2 +294,3 @@ readonly [x: string]: {

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -318,2 +321,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -485,2 +489,3 @@ readonly [x: string]: {

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -511,2 +516,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -513,0 +519,0 @@ readonly [x: string]: {

@@ -27,2 +27,3 @@ import { Option, Schema } from "effect";

/model_context_window_exceeded/i,
/range of input length should be/i,
/too many tokens/i,

@@ -42,2 +43,3 @@ /token limit exceeded/i,

const QUOTA_CODES = new Set(["insufficient_quota", "usage_not_included", "billing_error"]);
const AUTH_CODES = new Set(["authentication_error", "permission_error"]);
const SERVER_CODES = new Set([

@@ -58,5 +60,8 @@ "api_error",

const CONTENT_POLICY_TEXT = /content[-_\s]?policy|content_filter|safety/i;
const NETWORK_ERROR_TEXT = /network[-_\s]error/i;
// Keep HTTP failures and provider-reported stream failures on one typed path so
// session retry policy never needs provider-specific string matching.
// Classification records affirmative evidence about a failure. Deterministic
// failures need positive identification (a 4xx status, quota/auth/policy
// signals); anything unrecognized stays UnknownProvider, which the session
// retry policy treats as retry-eligible because transient failures arrive in
// unpredictable shapes while deterministic rejections almost always carry a
// status or known code.
export function classifyProviderFailure(input) {

@@ -82,11 +87,7 @@ const details = { message: input.message, body: input.rawBody, http: input.http, cause: input.cause };

return new QuotaExceededError(details);
if (input.status === 401)
return new AuthenticationError({ ...details, kind: "invalid" });
if (input.status === 403)
return new AuthenticationError({ ...details, kind: "insufficient-permissions" });
if (codes.includes("authentication_error"))
return new AuthenticationError({ ...details, kind: "invalid" });
if (codes.includes("permission_error"))
return new AuthenticationError({ ...details, kind: "insufficient-permissions" });
if (codes.some((code) => code.includes("rate_limit") || code === "too_many_requests" || code === "throttlingexception"))
if (input.status === 401 || input.status === 403 || codes.some((code) => AUTH_CODES.has(code)))
return new AuthenticationError(details);
if (input.status === 429 ||
codes.some((code) => code.includes("rate_limit") || code === "too_many_requests" || code === "throttlingexception") ||
RATE_LIMIT_TEXT.test(text))
return new RateLimitError({

@@ -97,11 +98,6 @@ ...details,

});
if (RATE_LIMIT_TEXT.test(text))
return new RateLimitError({
...details,
retryAfterMs: input.retryAfterMs,
rateLimit: input.rateLimit,
});
if (NETWORK_ERROR_TEXT.test(text))
return new ProviderInternalError(details);
if (codes.some((code) => SERVER_CODES.has(code) || code.includes("exhausted") || code.includes("unavailable")))
if (input.status === 408 ||
input.status === 409 ||
(input.status !== undefined && input.status >= 500) ||
codes.some((code) => SERVER_CODES.has(code) || code.includes("exhausted") || code.includes("unavailable")))
return new ProviderInternalError({

@@ -111,17 +107,6 @@ ...details,

});
if (input.status === 429) {
return new RateLimitError({
...details,
retryAfterMs: input.retryAfterMs,
rateLimit: input.rateLimit,
});
}
if (input.status === 408 || input.status === 409 || (input.status !== undefined && input.status >= 500))
return new ProviderInternalError({
...details,
retryAfterMs: input.retryAfterMs,
});
if (codes.some((code) => INVALID_REQUEST_CODES.has(code)))
return new InvalidRequestError(details);
if (input.status === 400 || input.status === 404 || input.status === 413 || input.status === 422)
// Any remaining 4xx is a deterministic rejection of this request.
if (input.status !== undefined && input.status >= 400 && input.status < 500)
return new InvalidRequestError(details);

@@ -128,0 +113,0 @@ return new UnknownProviderError(details);

@@ -80,3 +80,3 @@ import { Config, Effect, Redacted } from "effect";

reason: error instanceof MissingCredentialError
? new AuthenticationError({ message: error.message, cause: error, kind: "missing" })
? new AuthenticationError({ message: error.message, cause: error })
: new InvalidRequestError({ message: `Failed to resolve auth config: ${error.message}`, cause: error }),

@@ -83,0 +83,0 @@ });

@@ -176,2 +176,3 @@ import { Context, Effect, Layer, Schema, Stream } from "effect";

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -202,2 +203,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -204,0 +206,0 @@ readonly [x: string]: {

@@ -42,7 +42,6 @@ import { Schema } from "effect";

declare const AuthenticationError_base: Schema.Class<AuthenticationError, Schema.TaggedStruct<"Authentication", {
readonly kind: Schema.Literals<readonly ["missing", "invalid", "expired", "insufficient-permissions", "unknown"]>;
readonly message: Schema.String;
readonly body: Schema.optional<Schema.String>;
readonly http: Schema.optional<typeof HttpContext>;
readonly cause: Schema.optional<Schema.Defect>;
message: Schema.String;
body: Schema.optional<Schema.String>;
http: Schema.optional<typeof HttpContext>;
cause: Schema.optional<Schema.Defect>;
}>, import("effect/Cause").YieldableError>;

@@ -49,0 +48,0 @@ export declare class AuthenticationError extends AuthenticationError_base {

@@ -38,6 +38,3 @@ import { Schema } from "effect";

}
export class AuthenticationError extends Schema.TaggedError("AI.Error.Authentication")("Authentication", {
...ReasonFields,
kind: Schema.Literals(["missing", "invalid", "expired", "insufficient-permissions", "unknown"]),
}) {
export class AuthenticationError extends Schema.TaggedError("AI.Error.Authentication")("Authentication", ReasonFields) {
}

@@ -44,0 +41,0 @@ export class RateLimitError extends Schema.TaggedError("AI.Error.RateLimit")("RateLimit", {

@@ -94,2 +94,4 @@ import { Schema } from "effect";

id: ContentBlockID,
/** Authoritative complete value; replaces accumulated deltas when present. */
text: Schema.optional(Schema.String),
providerMetadata: Schema.optional(ProviderMetadata),

@@ -111,2 +113,4 @@ }).annotate({ identifier: "LLM.Event.TextEnd" });

id: ContentBlockID,
/** Authoritative complete value; replaces accumulated deltas when present. */
text: Schema.optional(Schema.String),
providerMetadata: Schema.optional(ProviderMetadata),

@@ -264,10 +268,22 @@ }).annotate({ identifier: "LLM.Event.ReasoningEnd" });

});
const responseText = (events) => events
.filter(LLMEvent.is.textDelta)
.map((event) => event.text)
.join("");
const responseReasoning = (events) => events
.filter(LLMEvent.is.reasoningDelta)
.map((event) => event.text)
.join("");
/** Joins deltas per fragment, letting an authoritative end value replace that fragment's accumulated deltas. */
const joinFragments = (events, isDelta, isEnd) => {
const order = [];
const parts = new Map();
for (const event of events) {
if (isDelta(event)) {
if (!parts.has(event.id))
order.push(event.id);
parts.set(event.id, (parts.get(event.id) ?? "") + event.text);
}
if (isEnd(event) && event.text !== undefined) {
if (!parts.has(event.id))
order.push(event.id);
parts.set(event.id, event.text);
}
}
return order.map((id) => parts.get(id)).join("");
};
const responseText = (events) => joinFragments(events, LLMEvent.is.textDelta, LLMEvent.is.textEnd);
const responseReasoning = (events) => joinFragments(events, LLMEvent.is.reasoningDelta, LLMEvent.is.reasoningEnd);
const responseUsage = (events) => events.reduce((usage, event) => ("usage" in event && event.usage !== undefined ? event.usage : usage), undefined);

@@ -339,6 +355,7 @@ const emptyResponseState = () => ({

return state;
const text = event.text ?? current.text;
const providerMetadata = event.providerMetadata ?? current.providerMetadata;
return {
...replaceContent(state, current.contentIndex, textContent(current.text, providerMetadata)),
textParts: { ...state.textParts, [event.id]: { ...current, providerMetadata } },
...replaceContent(state, current.contentIndex, textContent(text, providerMetadata)),
textParts: { ...state.textParts, [event.id]: { ...current, text, providerMetadata } },
};

@@ -373,6 +390,7 @@ };

return state;
const text = event.text ?? current.text;
const providerMetadata = event.providerMetadata ?? current.providerMetadata;
return {
...replaceContent(state, current.contentIndex, reasoningContent(current.text, providerMetadata)),
reasoningParts: { ...state.reasoningParts, [event.id]: { ...current, providerMetadata } },
...replaceContent(state, current.contentIndex, reasoningContent(text, providerMetadata)),
reasoningParts: { ...state.reasoningParts, [event.id]: { ...current, text, providerMetadata } },
};

@@ -465,7 +483,7 @@ };

}) {
/** Concatenated assistant text assembled from streamed `text-delta` events. */
/** Concatenated assistant text; each fragment's `text-end` value replaces its accumulated deltas when present. */
get text() {
return responseText(this.events);
}
/** Concatenated reasoning text assembled from streamed `reasoning-delta` events. */
/** Concatenated reasoning text; each fragment's `reasoning-end` value replaces its accumulated deltas when present. */
get reasoning() {

@@ -472,0 +490,0 @@ return responseReasoning(this.events);

@@ -53,2 +53,3 @@ export * as TestLLM from "./testing.js";

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -79,2 +80,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -238,2 +240,3 @@ readonly [x: string]: {

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -264,2 +267,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -423,2 +427,3 @@ readonly [x: string]: {

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -449,2 +454,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -608,2 +614,3 @@ readonly [x: string]: {

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -634,2 +641,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -793,2 +801,3 @@ readonly [x: string]: {

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -819,2 +828,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -978,2 +988,3 @@ readonly [x: string]: {

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -1004,2 +1015,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -1163,2 +1175,3 @@ readonly [x: string]: {

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -1189,2 +1202,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -1348,2 +1362,3 @@ readonly [x: string]: {

readonly type: "text-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -1374,2 +1389,3 @@ readonly [x: string]: {

readonly type: "reasoning-end";
readonly text?: string | undefined;
readonly providerMetadata?: {

@@ -1376,0 +1392,0 @@ readonly [x: string]: {

{
"$schema": "https://json.schemastore.org/package.json",
"version": "0.0.0-dev-18545",
"version": "0.0.0-dev-18548",
"name": "@opencode-ai/ai",

@@ -33,3 +33,3 @@ "type": "module",

"@effect/platform-node": "4.0.0-rc.112",
"@opencode-ai/http-recorder": "0.0.0-dev-18545",
"@opencode-ai/http-recorder": "0.0.0-dev-18548",
"@tsconfig/bun": "1.0.9",

@@ -43,3 +43,3 @@ "@types/bun": "1.3.13",

"@smithy/util-utf8": "4.2.2",
"@opencode-ai/schema": "0.0.0-dev-18545",
"@opencode-ai/schema": "0.0.0-dev-18548",
"aws4fetch": "1.0.20",

@@ -46,0 +46,0 @@ "effect": "4.0.0-rc.112",

Sorry, the diff of this file is too big to display