@xandreed/plugin-models 0.14.0 → 0.15.1
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/README.md +1 -1
- package/dist/auth/anthropicOAuth.d.ts +30 -10
- package/dist/auth/anthropicOAuth.js +15 -18
- package/dist/auth/auth-store.conformance.d.ts +63 -0
- package/dist/auth/auth-store.conformance.js +152 -0
- package/dist/auth/credential-input.entity.d.ts +23 -5
- package/dist/auth/credential-input.entity.functions.d.ts +15 -5
- package/dist/auth/credential-input.entity.functions.js +12 -9
- package/dist/auth/credential-input.entity.js +5 -3
- package/dist/auth/credential-refresh.entity.d.ts +11 -3
- package/dist/auth/credential-refresh.entity.functions.d.ts +48 -6
- package/dist/auth/credential-refresh.entity.functions.js +12 -3
- package/dist/auth/localAuth.d.ts +10 -1
- package/dist/auth/localAuth.js +53 -79
- package/dist/auth/memory-auth.adapter.d.ts +12 -4
- package/dist/auth/memory-auth.adapter.js +13 -25
- package/dist/auth/openAiCodexOAuth.d.ts +26 -5
- package/dist/auth/openAiCodexOAuth.js +17 -28
- package/dist/auth/token-response.entity.d.ts +21 -0
- package/dist/auth/token-response.entity.functions.d.ts +20 -0
- package/dist/auth/token-response.entity.functions.js +10 -0
- package/dist/auth/token-response.entity.js +10 -0
- package/dist/compat/index.d.ts +2 -0
- package/dist/compat/index.js +1 -0
- package/dist/conformance/index.d.ts +6 -0
- package/dist/conformance/index.js +3 -0
- package/dist/index.d.ts +19 -19
- package/dist/index.js +17 -69
- package/dist/llm/chat-wire.entity.d.ts +123 -0
- package/dist/llm/chat-wire.entity.functions.d.ts +28 -0
- package/dist/llm/chat-wire.entity.functions.js +10 -0
- package/dist/llm/chat-wire.entity.js +37 -0
- package/dist/llm/compat-telemetry.adapter.d.ts +6 -0
- package/dist/llm/compat-telemetry.adapter.js +21 -0
- package/dist/llm/compat.d.ts +50 -30
- package/dist/llm/compat.js +149 -133
- package/dist/llm/model-completion.adapter.d.ts +49 -0
- package/dist/llm/model-completion.adapter.js +77 -0
- package/dist/llm/model-completion.entity.d.ts +4 -0
- package/dist/llm/model-completion.entity.functions.d.ts +3 -0
- package/dist/llm/model-completion.entity.functions.js +7 -0
- package/dist/llm/model-completion.entity.js +7 -0
- package/dist/llm/model-retry-policy.entity.d.ts +37 -0
- package/dist/llm/model-retry-policy.entity.functions.d.ts +16 -0
- package/dist/llm/model-retry-policy.entity.functions.js +33 -0
- package/dist/llm/model-retry-policy.entity.js +23 -0
- package/dist/llm/model-settings.entity.d.ts +85 -0
- package/dist/llm/model-settings.entity.functions.d.ts +11 -0
- package/dist/llm/model-settings.entity.functions.js +49 -0
- package/dist/llm/model-settings.entity.js +28 -0
- package/dist/llm/model-usage.entity.d.ts +61 -0
- package/dist/llm/model-usage.entity.functions.d.ts +11 -0
- package/dist/llm/model-usage.entity.functions.js +24 -0
- package/dist/llm/model-usage.entity.js +19 -0
- package/dist/llm/modelCatalog.d.ts +29 -8
- package/dist/llm/modelCatalog.js +28 -66
- package/dist/llm/openAiCodex.d.ts +15 -7
- package/dist/llm/openAiCodex.js +57 -45
- package/dist/llm/openAiCodexWebSocket.d.ts +48 -15
- package/dist/llm/openAiCodexWebSocket.js +101 -147
- package/dist/llm/prompt-cache-frame.entity.d.ts +18 -0
- package/dist/llm/prompt-cache-frame.entity.js +10 -0
- package/dist/llm/prompt-cache.entity.d.ts +57 -0
- package/dist/llm/prompt-cache.entity.functions.d.ts +8 -0
- package/dist/llm/prompt-cache.entity.functions.js +73 -0
- package/dist/llm/prompt-cache.entity.js +27 -0
- package/dist/llm/provider-client.adapter.d.ts +9 -0
- package/dist/llm/provider-client.adapter.js +60 -0
- package/dist/llm/provider-failure.entity.d.ts +42 -0
- package/dist/llm/provider-failure.entity.functions.d.ts +8 -0
- package/dist/llm/provider-failure.entity.functions.js +67 -0
- package/dist/llm/provider-failure.entity.js +20 -0
- package/dist/llm/provider-profile.entity.d.ts +79 -0
- package/dist/llm/provider-profile.entity.functions.d.ts +23 -0
- package/dist/llm/provider-profile.entity.functions.js +83 -0
- package/dist/llm/provider-profile.entity.js +10 -0
- package/dist/llm/providers.d.ts +116 -34
- package/dist/llm/providers.js +298 -129
- package/dist/llm/retry.d.ts +11 -47
- package/dist/llm/retry.js +33 -52
- package/dist/llm/router.d.ts +54 -36
- package/dist/llm/router.js +91 -78
- package/dist/llm/sse.d.ts +44 -37
- package/dist/llm/sse.js +43 -35
- package/dist/llm/thinking-binding.entity.d.ts +49 -0
- package/dist/llm/thinking-binding.entity.functions.d.ts +21 -0
- package/dist/llm/thinking-binding.entity.functions.js +16 -0
- package/dist/llm/thinking-binding.entity.js +11 -0
- package/dist/llm/utilityLlm.d.ts +14 -5
- package/dist/llm/utilityLlm.js +18 -13
- package/dist/plugin.adapter.d.ts +94 -6
- package/dist/plugin.adapter.js +18 -13
- package/dist/ports/auth-store.port.d.ts +73 -0
- package/dist/ports/auth-store.port.js +24 -0
- package/dist/ports/host-credentials.port.d.ts +2 -1
- package/dist/ports/model-call-completion.port.d.ts +9 -0
- package/dist/ports/model-call-completion.port.js +2 -0
- package/dist/ports/model-endpoints.port.d.ts +60 -26
- package/dist/ports/model-endpoints.port.js +17 -3
- package/dist/ports/model-retry-policy.port.d.ts +17 -0
- package/dist/ports/model-retry-policy.port.js +3 -0
- package/dist/ports/model-settings.port.d.ts +32 -0
- package/dist/ports/model-settings.port.js +4 -0
- package/dist/ports/models-transport.port.d.ts +9 -2
- package/dist/ports/models-transport.port.js +4 -1
- package/dist/ports/prompt-cache-frame.port.d.ts +21 -0
- package/dist/ports/prompt-cache-frame.port.js +4 -0
- package/dist/ports/settings-store.port.d.ts +70 -0
- package/dist/ports/settings-store.port.js +33 -0
- package/dist/ports/thinking-binding.port.d.ts +7 -0
- package/dist/ports/thinking-binding.port.js +4 -0
- package/dist/settings/localSettings.d.ts +2 -1
- package/dist/settings/localSettings.js +17 -20
- package/dist/settings/memory-settings.adapter.d.ts +3 -1
- package/dist/settings/memory-settings.adapter.js +1 -1
- package/dist/settings/roleView.d.ts +3 -1
- package/dist/settings/roleView.js +1 -1
- package/dist/settings/settings-store.conformance.d.ts +47 -0
- package/dist/settings/settings-store.conformance.js +100 -0
- package/dist/settings/settings-value.entity.d.ts +10 -2
- package/dist/settings/settings-value.entity.functions.d.ts +31 -9
- package/dist/settings/settings-value.entity.functions.js +5 -6
- package/dist/storage/json-file.d.ts +18 -0
- package/dist/storage/json-file.js +26 -0
- package/dist/transport/http-proxy.entity.d.ts +17 -3
- package/dist/transport/model-request.conformance.d.ts +13 -0
- package/dist/transport/model-request.conformance.js +36 -0
- package/dist/transport/models-transport.adapter.d.ts +18 -17
- package/dist/transport/models-transport.adapter.js +28 -31
- package/dist/transport/resilient-http-client.adapter.d.ts +73 -0
- package/dist/transport/resilient-http-client.adapter.js +177 -0
- package/package.json +11 -5
- package/dist/auth/anthropicOAuth.test.d.ts +0 -1
- package/dist/auth/credential-refresh.entity.functions.test.d.ts +0 -1
- package/dist/auth/localAuth.test.d.ts +0 -1
- package/dist/auth/memory-auth.adapter.test.d.ts +0 -1
- package/dist/llm/compat.test.d.ts +0 -1
- package/dist/llm/modelCatalog.test.d.ts +0 -1
- package/dist/llm/openAiCodexWebSocket.test.d.ts +0 -1
- package/dist/llm/providers.test.d.ts +0 -1
- package/dist/llm/retry.test.d.ts +0 -1
- package/dist/llm/router.test.d.ts +0 -1
- package/dist/llm/sse.test.d.ts +0 -1
- package/dist/plugin.adapter.test.d.ts +0 -1
- package/dist/settings/localSettings.test.d.ts +0 -1
- package/dist/settings/memory-settings.adapter.test.d.ts +0 -1
- package/dist/settings/roleView.test.d.ts +0 -1
- package/dist/settings/settings-value.entity.functions.test.d.ts +0 -1
- package/dist/transport/http-proxy.entity.functions.test.d.ts +0 -1
- package/dist/transport/models-transport.adapter.test.d.ts +0 -1
- package/dist/transport/recording-proxy.testing.d.ts +0 -33
package/dist/index.js
CHANGED
|
@@ -1,82 +1,30 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
CLAUDE_CODE_SYSTEM,
|
|
5
|
-
exchangeAnthropicCode,
|
|
6
|
-
generatePkce,
|
|
7
|
-
parseAuthorizationInput,
|
|
8
|
-
refreshAnthropicToken
|
|
9
|
-
} from "./auth/anthropicOAuth.js";
|
|
10
|
-
export {
|
|
11
|
-
beginOpenAiCodexOAuth,
|
|
12
|
-
exchangeOpenAiCodexCode,
|
|
13
|
-
OPENAI_CODEX_CALLBACK_PATH,
|
|
14
|
-
OPENAI_CODEX_CALLBACK_PORT,
|
|
15
|
-
OPENAI_CODEX_CLIENT_ID,
|
|
16
|
-
OPENAI_CODEX_REDIRECT_URI,
|
|
17
|
-
openAiCodexAccountId,
|
|
18
|
-
refreshOpenAiCodexToken
|
|
19
|
-
} from "./auth/openAiCodexOAuth.js";
|
|
20
|
-
export { authPaths, LocalAuthStoreLive } from "./auth/localAuth.js";
|
|
1
|
+
export { beginAnthropicOAuth, exchangeAnthropicCode, parseAuthorizationInput, refreshAnthropicToken } from "./auth/anthropicOAuth.js";
|
|
2
|
+
export { beginOpenAiCodexOAuth, exchangeOpenAiCodexCode, refreshOpenAiCodexToken } from "./auth/openAiCodexOAuth.js";
|
|
3
|
+
export { LocalAuthStoreLive } from "./auth/localAuth.js";
|
|
21
4
|
export { MemoryAuthStoreLive } from "./auth/memory-auth.adapter.js";
|
|
22
|
-
export { CredentialInput, CredentialInputs } from "./auth/credential-input.entity.js";
|
|
23
|
-
export { credentialsOf, toCredential, toCredentialInput } from "./auth/credential-input.entity.functions.js";
|
|
5
|
+
export { AccountId, CredentialInput, CredentialInputs, InstallationId } from "./auth/credential-input.entity.js";
|
|
24
6
|
export { RefreshableProvider } from "./auth/credential-refresh.entity.js";
|
|
25
7
|
export { isUsableAt, REFRESH_SKEW_MS, refreshCredential } from "./auth/credential-refresh.entity.functions.js";
|
|
26
8
|
export { HostCredentials } from "./ports/host-credentials.port.js";
|
|
9
|
+
export { AuthError, AuthStore, Credential } from "./ports/auth-store.port.js";
|
|
10
|
+
export { EngineSettings, SETTINGS_KEYS, SettingsError, SettingsStore } from "./ports/settings-store.port.js";
|
|
27
11
|
export { LocalSettingsStoreLive } from "./settings/localSettings.js";
|
|
28
12
|
export { MemorySettingsStoreLive } from "./settings/memory-settings.adapter.js";
|
|
29
13
|
export { RoleField, SettingValue } from "./settings/settings-value.entity.js";
|
|
30
14
|
export { applyRole, applySetting, coerceSettingValue, ROLE_FIELDS, roleSelection, settingsFromRecord } from "./settings/settings-value.entity.functions.js";
|
|
31
15
|
export { roleModelView } from "./settings/roleView.js";
|
|
32
|
-
export {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
} from "./llm/compat.js";
|
|
39
|
-
export { makeOpenAiCodexLanguageModel, OPENAI_CODEX_API_URL, toOpenAiCodexRequestBody } from "./llm/openAiCodex.js";
|
|
40
|
-
export { makeOpenAiCodexWebSocketHttpClient, normalizeOpenAiCodexWebSocketEvent, openAiCodexRefusal, openAiCodexUuidV7, OpenAiCodexWebSocketHttpClient } from "./llm/openAiCodexWebSocket.js";
|
|
41
|
-
export {
|
|
42
|
-
buildProvider,
|
|
43
|
-
chatCompletionsUrl,
|
|
44
|
-
endpointOwnKey,
|
|
45
|
-
OPENCODE_CHAT_URL,
|
|
46
|
-
OPENCODE_RESPONSES_API_URL,
|
|
47
|
-
prependClaudeCode,
|
|
48
|
-
usesOpenCodeResponses,
|
|
49
|
-
withAnthropicCacheBreakpoints
|
|
50
|
-
} from "./llm/providers.js";
|
|
51
|
-
export {
|
|
52
|
-
classifyLlmError,
|
|
53
|
-
LLM_REQUEST_TIMEOUT_MS,
|
|
54
|
-
MAX_HONORED_RETRY_AFTER_MS,
|
|
55
|
-
rejectEmptyResponse,
|
|
56
|
-
retryableLlm
|
|
57
|
-
} from "./llm/retry.js";
|
|
58
|
-
export { generateWith, LanguageModelLive, LanguageModelSelectionLive } from "./llm/router.js";
|
|
59
|
-
export {
|
|
60
|
-
configuredModelCatalog,
|
|
61
|
-
ConfiguredModelCatalogLive,
|
|
62
|
-
imageInputFor,
|
|
63
|
-
reasoningEffortsFor
|
|
64
|
-
} from "./llm/modelCatalog.js";
|
|
16
|
+
export { makeOpenAiCodexWebSocketHttpClient } from "./llm/openAiCodexWebSocket.js";
|
|
17
|
+
export { LLM_CALL_BUDGET_MS, LLM_REQUEST_TIMEOUT_MS } from "./llm/retry.js";
|
|
18
|
+
export { ModelRetryPolicy, modelRetryDefaults } from "./llm/model-retry-policy.entity.js";
|
|
19
|
+
export { CurrentModelRetryPolicy } from "./ports/model-retry-policy.port.js";
|
|
20
|
+
export { LanguageModelLive, LanguageModelSelectionLive } from "./llm/router.js";
|
|
21
|
+
export { ConfiguredModelCatalogLive, imageInputFor, reasoningEffortsFor } from "./llm/modelCatalog.js";
|
|
65
22
|
export { UtilityLlmLive } from "./llm/utilityLlm.js";
|
|
66
23
|
export { modelsPlugin, default } from "./plugin.adapter.js";
|
|
67
24
|
export { CurrentModelEndpoints, ModelEndpoint, ModelEndpoints } from "./ports/model-endpoints.port.js";
|
|
68
25
|
export { ModelsTransport } from "./ports/models-transport.port.js";
|
|
69
|
-
export { ModelsTransportLive
|
|
70
|
-
export {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
NoProxyRule,
|
|
75
|
-
PROXY_VARIABLES,
|
|
76
|
-
ProxyConfig,
|
|
77
|
-
ProxyEnvironment,
|
|
78
|
-
ProxyInvalid,
|
|
79
|
-
ProxyUnsupported,
|
|
80
|
-
ProxyUrlOption
|
|
81
|
-
} from "./transport/http-proxy.entity.js";
|
|
82
|
-
export { bypassesProxy, isLoopback, parseNoProxy, proxyFor, redactCredentials, resolveProxy } from "./transport/http-proxy.entity.functions.js";
|
|
26
|
+
export { ModelsTransportLive } from "./transport/models-transport.adapter.js";
|
|
27
|
+
export { HttpProxyOptions, ProxyInvalid, ProxyUnsupported, ProxyUrlOption } from "./transport/http-proxy.entity.js";
|
|
28
|
+
export { ModelThinking, ModelSettings, ModelSettingsMap, ModelSettingsError } from "./llm/model-settings.entity.js";
|
|
29
|
+
export { PromptCacheSettings } from "./llm/prompt-cache.entity.js";
|
|
30
|
+
export { CurrentModelSettings } from "./ports/model-settings.port.js";
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** The usage object OpenAI-compatible completions carry (streaming sends it
|
|
3
|
+
* on the last chunk under `stream_options: {include_usage: true}`). */
|
|
4
|
+
export declare const CompletionUsage: Schema.Struct<{
|
|
5
|
+
readonly prompt_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
6
|
+
readonly completion_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
7
|
+
readonly total_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
8
|
+
/** DeepSeek-style cache accounting. */
|
|
9
|
+
readonly prompt_cache_hit_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
10
|
+
/** Moonshot-style cache accounting. */
|
|
11
|
+
readonly cached_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
12
|
+
/** OpenAI-native cache reads; gateways (OpenCode's among them) add the cache writes. */
|
|
13
|
+
readonly prompt_tokens_details: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
14
|
+
readonly cached_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
15
|
+
readonly cache_write_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
16
|
+
}>>>;
|
|
17
|
+
/** OpenAI-native reasoning accounting, counted inside `completion_tokens`. */
|
|
18
|
+
readonly completion_tokens_details: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
19
|
+
readonly reasoning_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
20
|
+
}>>>;
|
|
21
|
+
}>;
|
|
22
|
+
export type CompletionUsage = typeof CompletionUsage.Type;
|
|
23
|
+
/** One non-streaming chat completion. */
|
|
24
|
+
export declare const ChatCompletion: Schema.Struct<{
|
|
25
|
+
readonly choices: Schema.optionalKey<Schema.NullOr<Schema.$Array<Schema.Struct<{
|
|
26
|
+
readonly finish_reason: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
27
|
+
readonly message: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
28
|
+
readonly tool_calls: Schema.optionalKey<Schema.NullOr<Schema.$Array<Schema.Struct<{
|
|
29
|
+
readonly id: Schema.optionalKey<Schema.NullOr<Schema.brand<Schema.String, "ToolCallId">>>;
|
|
30
|
+
readonly function: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
31
|
+
readonly name: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
32
|
+
readonly arguments: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
33
|
+
}>>>;
|
|
34
|
+
}>>>>;
|
|
35
|
+
readonly content: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
36
|
+
readonly reasoning_content: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
37
|
+
readonly reasoning: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
38
|
+
}>>>;
|
|
39
|
+
}>>>>;
|
|
40
|
+
readonly usage: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
41
|
+
readonly prompt_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
42
|
+
readonly completion_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
43
|
+
readonly total_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
44
|
+
/** DeepSeek-style cache accounting. */
|
|
45
|
+
readonly prompt_cache_hit_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
46
|
+
/** Moonshot-style cache accounting. */
|
|
47
|
+
readonly cached_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
48
|
+
/** OpenAI-native cache reads; gateways (OpenCode's among them) add the cache writes. */
|
|
49
|
+
readonly prompt_tokens_details: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
50
|
+
readonly cached_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
51
|
+
readonly cache_write_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
52
|
+
}>>>;
|
|
53
|
+
/** OpenAI-native reasoning accounting, counted inside `completion_tokens`. */
|
|
54
|
+
readonly completion_tokens_details: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
55
|
+
readonly reasoning_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
56
|
+
}>>>;
|
|
57
|
+
}>>>;
|
|
58
|
+
}>;
|
|
59
|
+
export type ChatCompletion = typeof ChatCompletion.Type;
|
|
60
|
+
/** A streamed tool-call fragment: fragments of one call share its `index`. */
|
|
61
|
+
export declare const StreamToolCall: Schema.Struct<{
|
|
62
|
+
readonly index: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
63
|
+
readonly id: Schema.optionalKey<Schema.NullOr<Schema.brand<Schema.String, "ToolCallId">>>;
|
|
64
|
+
readonly function: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
65
|
+
readonly name: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
66
|
+
readonly arguments: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
67
|
+
}>>>;
|
|
68
|
+
}>;
|
|
69
|
+
export type StreamToolCall = typeof StreamToolCall.Type;
|
|
70
|
+
/** One `data:` chunk of a streaming chat completion. */
|
|
71
|
+
export declare const StreamChunk: Schema.Struct<{
|
|
72
|
+
readonly choices: Schema.optionalKey<Schema.NullOr<Schema.$Array<Schema.Struct<{
|
|
73
|
+
readonly finish_reason: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
74
|
+
readonly delta: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
75
|
+
readonly tool_calls: Schema.optionalKey<Schema.NullOr<Schema.$Array<Schema.Struct<{
|
|
76
|
+
readonly index: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
77
|
+
readonly id: Schema.optionalKey<Schema.NullOr<Schema.brand<Schema.String, "ToolCallId">>>;
|
|
78
|
+
readonly function: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
79
|
+
readonly name: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
80
|
+
readonly arguments: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
81
|
+
}>>>;
|
|
82
|
+
}>>>>;
|
|
83
|
+
readonly content: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
84
|
+
readonly reasoning_content: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
85
|
+
readonly reasoning: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
86
|
+
}>>>;
|
|
87
|
+
}>>>>;
|
|
88
|
+
readonly usage: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
89
|
+
readonly prompt_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
90
|
+
readonly completion_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
91
|
+
readonly total_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
92
|
+
/** DeepSeek-style cache accounting. */
|
|
93
|
+
readonly prompt_cache_hit_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
94
|
+
/** Moonshot-style cache accounting. */
|
|
95
|
+
readonly cached_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
96
|
+
/** OpenAI-native cache reads; gateways (OpenCode's among them) add the cache writes. */
|
|
97
|
+
readonly prompt_tokens_details: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
98
|
+
readonly cached_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
99
|
+
readonly cache_write_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
100
|
+
}>>>;
|
|
101
|
+
/** OpenAI-native reasoning accounting, counted inside `completion_tokens`. */
|
|
102
|
+
readonly completion_tokens_details: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
103
|
+
readonly reasoning_tokens: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
|
|
104
|
+
}>>>;
|
|
105
|
+
}>>>;
|
|
106
|
+
readonly error: Schema.optionalKey<Schema.Unknown>;
|
|
107
|
+
}>;
|
|
108
|
+
export type StreamChunk = typeof StreamChunk.Type;
|
|
109
|
+
/** The OpenAI error object a gateway reports a failure with: its type, its code and its message. */
|
|
110
|
+
export declare const GatewayError: Schema.Struct<{
|
|
111
|
+
readonly type: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
112
|
+
readonly code: Schema.optionalKey<Schema.NullOr<Schema.Union<readonly [Schema.String, Schema.Number]>>>;
|
|
113
|
+
readonly message: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
114
|
+
}>;
|
|
115
|
+
export type GatewayError = typeof GatewayError.Type;
|
|
116
|
+
/** A failed request's body in the OpenAI error shape. */
|
|
117
|
+
export declare const GatewayErrorBody: Schema.Struct<{
|
|
118
|
+
readonly error: Schema.Struct<{
|
|
119
|
+
readonly type: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
120
|
+
readonly code: Schema.optionalKey<Schema.NullOr<Schema.Union<readonly [Schema.String, Schema.Number]>>>;
|
|
121
|
+
readonly message: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
122
|
+
}>;
|
|
123
|
+
}>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AiError } from "effect/ai";
|
|
2
|
+
import { Effect, Option, Schema } from "effect";
|
|
3
|
+
import { ChatCompletion, GatewayError, StreamChunk } from "./chat-wire.entity.js";
|
|
4
|
+
/** A completion body, decoded; one that is no JSON or of the wrong shape is the provider's `InvalidResponseError`. */
|
|
5
|
+
export declare const decodeChatCompletion: (moduleName: string, text: string) => Effect.Effect<ChatCompletion, AiError.AiError>;
|
|
6
|
+
/** A `data:` line's chunk, decoded; one that is no JSON object of the chunk's shape (`null` included) is the provider's `InvalidResponseError`. */
|
|
7
|
+
export declare const decodeStreamChunk: (moduleName: string, payload: string) => Effect.Effect<StreamChunk, AiError.AiError>;
|
|
8
|
+
/** A tool call's arguments, parsed: the model's own output, so a failure is the caller's to name. */
|
|
9
|
+
export declare const decodeToolArguments: (text: string) => Effect.Effect<Schema.Json, Schema.SchemaError>;
|
|
10
|
+
/** The OpenAI error object of a failed request's body, when it has one. */
|
|
11
|
+
export declare const gatewayErrorOf: (body: string) => Option.Option<GatewayError>;
|
|
12
|
+
/** The OpenAI error object of a stream's error chunk, when it is one. */
|
|
13
|
+
export declare const chunkErrorOf: (error: unknown) => Option.Option<GatewayError>;
|
|
14
|
+
/**
|
|
15
|
+
* The error types and codes gateways report an exhausted balance or quota
|
|
16
|
+
* with: OpenCode's `CreditsError`, OpenAI's `insufficient_quota` and
|
|
17
|
+
* `billing_insufficient_balance`, Moonshot's `exceeded_current_quota_error`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const QUOTA_ERRORS: ReadonlySet<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Whether a failure is an exhausted balance or quota, which no retry and no
|
|
22
|
+
* fallback model fixes: a 402 (Payment Required), or an error whose type or
|
|
23
|
+
* code names one (`QUOTA_ERRORS`), at any status. A plain 429 is not: it is
|
|
24
|
+
* a rate limit, retried. The message text is not read.
|
|
25
|
+
*/
|
|
26
|
+
export declare const isQuotaExhausted: (status: Option.Option<number>, error: Option.Option<GatewayError>) => boolean;
|
|
27
|
+
/** Whether a gateway rejected the selected model (OpenCode's `ModelError`), whatever status it answered with. */
|
|
28
|
+
export declare const isModelRejection: (error: GatewayError) => boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AiError } from "effect/ai";
|
|
2
|
+
import { Effect, Option, Schema } from "effect";
|
|
3
|
+
import { ChatCompletion, GatewayError, GatewayErrorBody, StreamChunk } from "./chat-wire.entity.js";
|
|
4
|
+
const invalidResponse = (moduleName, method, what) => (error) => AiError.make({ module: moduleName, method, reason: new AiError.InvalidResponseError({ description: `${what}: ${error.message}` }) }), completion = Schema.decodeUnknownEffect(Schema.fromJsonString(ChatCompletion)), chunk = Schema.decodeUnknownEffect(Schema.fromJsonString(StreamChunk)), json = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Json)), errorBody = Schema.decodeUnknownOption(Schema.fromJsonString(GatewayErrorBody)), errorObject = Schema.decodeUnknownOption(GatewayError);
|
|
5
|
+
export const decodeChatCompletion = (moduleName, text) => completion(text).pipe(Effect.mapError(invalidResponse(moduleName, "generateText", "the completion body is not a chat completion"))), decodeStreamChunk = (moduleName, payload) => chunk(payload).pipe(Effect.mapError(invalidResponse(moduleName, "streamText", `a data: line is not a completion chunk (${payload.slice(0, 200)})`))), decodeToolArguments = (text) => json(text), gatewayErrorOf = (body) => Option.map(errorBody(body), (decoded) => decoded.error), chunkErrorOf = (error) => errorObject(error), QUOTA_ERRORS = new Set([
|
|
6
|
+
"CreditsError",
|
|
7
|
+
"insufficient_quota",
|
|
8
|
+
"billing_insufficient_balance",
|
|
9
|
+
"exceeded_current_quota_error"
|
|
10
|
+
]), isQuotaExhausted = (status, error) => Option.contains(status, 402) || Option.exists(error, (found) => [found.type, found.code].some((name) => typeof name === "string" && QUOTA_ERRORS.has(name))), isModelRejection = (error) => error.type === "ModelError" || /model .*not supported/i.test(error.message ?? "");
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { ToolCallId } from "@xandreed/core";
|
|
3
|
+
const Count = Schema.optionalKey(Schema.NullOr(Schema.Number)), Text = Schema.optionalKey(Schema.NullOr(Schema.String));
|
|
4
|
+
export const CompletionUsage = Schema.Struct({
|
|
5
|
+
prompt_tokens: Count,
|
|
6
|
+
completion_tokens: Count,
|
|
7
|
+
total_tokens: Count,
|
|
8
|
+
prompt_cache_hit_tokens: Count,
|
|
9
|
+
cached_tokens: Count,
|
|
10
|
+
prompt_tokens_details: Schema.optionalKey(Schema.NullOr(Schema.Struct({ cached_tokens: Count, cache_write_tokens: Count }))),
|
|
11
|
+
completion_tokens_details: Schema.optionalKey(Schema.NullOr(Schema.Struct({ reasoning_tokens: Count })))
|
|
12
|
+
});
|
|
13
|
+
const WireToolCallId = Schema.optionalKey(Schema.NullOr(ToolCallId)), ToolCallFunction = Schema.optionalKey(Schema.NullOr(Schema.Struct({ name: Text, arguments: Text }))), MessageText = { content: Text, reasoning_content: Text, reasoning: Text };
|
|
14
|
+
export const ChatCompletion = Schema.Struct({
|
|
15
|
+
choices: Schema.optionalKey(Schema.NullOr(Schema.Array(Schema.Struct({
|
|
16
|
+
finish_reason: Text,
|
|
17
|
+
message: Schema.optionalKey(Schema.NullOr(Schema.Struct({
|
|
18
|
+
...MessageText,
|
|
19
|
+
tool_calls: Schema.optionalKey(Schema.NullOr(Schema.Array(Schema.Struct({ id: WireToolCallId, function: ToolCallFunction }))))
|
|
20
|
+
})))
|
|
21
|
+
})))),
|
|
22
|
+
usage: Schema.optionalKey(Schema.NullOr(CompletionUsage))
|
|
23
|
+
}), StreamToolCall = Schema.Struct({ index: Count, id: WireToolCallId, function: ToolCallFunction }), StreamChunk = Schema.Struct({
|
|
24
|
+
choices: Schema.optionalKey(Schema.NullOr(Schema.Array(Schema.Struct({
|
|
25
|
+
finish_reason: Text,
|
|
26
|
+
delta: Schema.optionalKey(Schema.NullOr(Schema.Struct({
|
|
27
|
+
...MessageText,
|
|
28
|
+
tool_calls: Schema.optionalKey(Schema.NullOr(Schema.Array(StreamToolCall)))
|
|
29
|
+
})))
|
|
30
|
+
})))),
|
|
31
|
+
usage: Schema.optionalKey(Schema.NullOr(CompletionUsage)),
|
|
32
|
+
error: Schema.optionalKey(Schema.Unknown)
|
|
33
|
+
}), GatewayError = Schema.Struct({
|
|
34
|
+
type: Text,
|
|
35
|
+
code: Schema.optionalKey(Schema.NullOr(Schema.Union([Schema.String, Schema.Number]))),
|
|
36
|
+
message: Text
|
|
37
|
+
}), GatewayErrorBody = Schema.Struct({ error: GatewayError });
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { Tracer } from "effect";
|
|
3
|
+
/** Annotate the actual native operation, never a routing or engine wrapper. */
|
|
4
|
+
export declare const annotateCompatRequest: (span: Tracer.Span, provider: string, model: string) => Effect.Effect<void>;
|
|
5
|
+
/** Raw cumulative fields replace their own attributes; missing counts never become zero. */
|
|
6
|
+
export declare const observeCompatUsage: (span: Tracer.Span, raw: unknown, final: boolean, reasoning?: boolean) => Effect.Effect<void>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Effect, Option } from "effect";
|
|
2
|
+
import { providerUsageCounts } from "./model-usage.entity.functions.js";
|
|
3
|
+
export const annotateCompatRequest = (span, provider, model) => Effect.sync(() => {
|
|
4
|
+
span.attribute("gen_ai.provider.name", provider);
|
|
5
|
+
span.attribute("gen_ai.request.model", model);
|
|
6
|
+
span.attribute("gen_ai.operation.name", "chat");
|
|
7
|
+
}), observeCompatUsage = (span, raw, final, reasoning = !0) => Option.match(providerUsageCounts("compat", raw, reasoning), {
|
|
8
|
+
onNone: () => Effect.void,
|
|
9
|
+
onSome: (counts) => Effect.sync(() => {
|
|
10
|
+
[
|
|
11
|
+
["gen_ai.usage.input_tokens", counts.inputTokens],
|
|
12
|
+
["gen_ai.usage.output_tokens", !final && counts.outputTokens === 0 ? void 0 : counts.outputTokens],
|
|
13
|
+
["gen_ai.usage.cache_read.input_tokens", counts.cacheReadTokens],
|
|
14
|
+
["gen_ai.usage.cache_write.input_tokens", counts.cacheWriteTokens],
|
|
15
|
+
["gen_ai.usage.reasoning.output_tokens", counts.reasoningTokens]
|
|
16
|
+
].forEach(([name, value]) => {
|
|
17
|
+
if (value !== void 0 && Number.isSafeInteger(value))
|
|
18
|
+
span.attribute(name, value);
|
|
19
|
+
});
|
|
20
|
+
})
|
|
21
|
+
});
|
package/dist/llm/compat.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AiError, LanguageModel, Prompt, Tool } from "effect/ai";
|
|
2
|
-
import { Effect } from "effect";
|
|
3
|
-
import type {
|
|
1
|
+
import { AiError, LanguageModel, Prompt, Tool, type Response as ResponseParts } from "effect/ai";
|
|
2
|
+
import { Effect, Schema } from "effect";
|
|
3
|
+
import type { UsageReading } from "./sse.js";
|
|
4
4
|
import type { ModelsFetch } from "../ports/models-transport.port.js";
|
|
5
5
|
/**
|
|
6
6
|
* A generic OpenAI-compatible `/chat/completions` `LanguageModel` over raw
|
|
@@ -10,10 +10,11 @@ import type { ModelsFetch } from "../ports/models-transport.port.js";
|
|
|
10
10
|
*
|
|
11
11
|
* `generateText` consumes whole turns (`stream: false`); `streamText` runs
|
|
12
12
|
* the same request with `stream: true` through the pure SSE state machine in
|
|
13
|
-
* `sse.ts`.
|
|
14
|
-
*
|
|
13
|
+
* `sse.ts`. Both paths use the same bounded request policy before handing
|
|
14
|
+
* off a successful response; body and SSE failures after handoff are final.
|
|
15
15
|
*/
|
|
16
16
|
type Json = Record<string, unknown>;
|
|
17
|
+
/** @public */
|
|
17
18
|
export interface CompatConfig {
|
|
18
19
|
/** Module name for `AiError` provenance (e.g. "OpenCode"). */
|
|
19
20
|
readonly moduleName: string;
|
|
@@ -37,15 +38,23 @@ export interface CompatConfig {
|
|
|
37
38
|
readonly usage?: UsageReading;
|
|
38
39
|
/** The model reads images: send them as `image_url` parts (default false: label lines; see `toChatMessages`). */
|
|
39
40
|
readonly images?: boolean;
|
|
40
|
-
/** The fetch requests go through (the models plugin
|
|
41
|
+
/** The fetch requests go through (the models plugin supplies its chosen transport); otherwise uses the call-local FetchHttpClient.Fetch reference. */
|
|
41
42
|
readonly fetchImpl?: ModelsFetch;
|
|
42
|
-
/** Host-owned admission (e.g. reserve a worst-case cost) before every
|
|
43
|
+
/** Host-owned admission (e.g. reserve a worst-case cost) before every
|
|
44
|
+
* physical send: the first and each retry the request policy makes. A
|
|
45
|
+
* failure ends the call without that send. */
|
|
43
46
|
readonly beforeRequest?: (body: Readonly<Record<string, unknown>>) => Effect.Effect<void, AiError.AiError>;
|
|
44
|
-
/** Per-call accounting/resource boundary
|
|
45
|
-
*
|
|
47
|
+
/** Per-call accounting/resource boundary around the whole logical call,
|
|
48
|
+
* its retries included: it sees the final response or failure once.
|
|
49
|
+
* Non-streaming responses are fully buffered inside request so
|
|
50
|
+
* interruption also aborts body consumption. */
|
|
46
51
|
readonly aroundRequest?: (body: Readonly<Record<string, unknown>>, request: Effect.Effect<Response, AiError.AiError>) => Effect.Effect<Response, AiError.AiError>;
|
|
47
52
|
}
|
|
48
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* How `toChatMessages` writes a request.
|
|
55
|
+
*
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
49
58
|
export interface ChatMessageOptions {
|
|
50
59
|
/** Send images as `image_url` parts (default false: label lines). */
|
|
51
60
|
readonly images?: boolean;
|
|
@@ -85,28 +94,39 @@ export declare const toChatTools: (tools: ReadonlyArray<Tool.Any>) => ReadonlyAr
|
|
|
85
94
|
* `thinking: {type: "enabled"}`; qwen takes `enable_thinking`. Disabling is
|
|
86
95
|
* never sent (kimi-k2.7+ rejects it outright); unknown families get nothing.
|
|
87
96
|
*/
|
|
88
|
-
export declare const thinkingParams: (model: string) =>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
export declare const thinkingParams: (model: string) => Schema.JsonObject;
|
|
98
|
+
/** Parse one non-streaming completion into `@effect/ai` encoded parts. */
|
|
99
|
+
export declare const fromChatCompletion: (moduleName: string, body: {
|
|
100
|
+
readonly usage?: {
|
|
101
|
+
readonly prompt_tokens_details?: {
|
|
102
|
+
readonly cached_tokens?: number | null;
|
|
103
|
+
readonly cache_write_tokens?: number | null;
|
|
104
|
+
} | null;
|
|
105
|
+
readonly cached_tokens?: number | null;
|
|
106
|
+
readonly completion_tokens_details?: {
|
|
107
|
+
readonly reasoning_tokens?: number | null;
|
|
108
|
+
} | null;
|
|
109
|
+
readonly prompt_tokens?: number | null;
|
|
110
|
+
readonly completion_tokens?: number | null;
|
|
111
|
+
readonly total_tokens?: number | null;
|
|
112
|
+
readonly prompt_cache_hit_tokens?: number | null;
|
|
113
|
+
} | null;
|
|
114
|
+
readonly choices?: readonly {
|
|
92
115
|
readonly message?: {
|
|
93
|
-
readonly content?: string | null;
|
|
94
|
-
/** DeepSeek-native vocabulary (kimi-k2.7-code, deepseek serve this). */
|
|
95
|
-
readonly reasoning_content?: string | null;
|
|
96
|
-
/** OpenRouter-style vocabulary (kimi-k2.6 via Moonshot serves this). */
|
|
97
116
|
readonly reasoning?: string | null;
|
|
98
|
-
readonly
|
|
99
|
-
|
|
117
|
+
readonly content?: string | null;
|
|
118
|
+
readonly tool_calls?: readonly {
|
|
100
119
|
readonly function?: {
|
|
101
|
-
readonly name?: string;
|
|
102
|
-
readonly arguments?: string;
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
120
|
+
readonly name?: string | null;
|
|
121
|
+
readonly arguments?: string | null;
|
|
122
|
+
} | null;
|
|
123
|
+
readonly id?: (string & import("effect/Brand").Brand<"ToolCallId">) | null;
|
|
124
|
+
}[] | null;
|
|
125
|
+
readonly reasoning_content?: string | null;
|
|
126
|
+
} | null;
|
|
127
|
+
readonly finish_reason?: string | null;
|
|
128
|
+
}[] | null;
|
|
129
|
+
}, reading?: UsageReading | undefined) => Effect.Effect<readonly ResponseParts.PartEncoded[], AiError.AiError, never>;
|
|
130
|
+
/** @public */
|
|
111
131
|
export declare const makeCompatLanguageModel: (config: CompatConfig) => Effect.Effect<LanguageModel.LanguageModel>;
|
|
112
132
|
export {};
|