@xandreed/plugin-models 0.13.0 → 0.15.0
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 +45 -11
- package/dist/auth/anthropicOAuth.js +23 -23
- 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 +52 -0
- package/dist/auth/credential-input.entity.functions.d.ts +18 -0
- package/dist/auth/credential-input.entity.functions.js +12 -0
- package/dist/auth/credential-input.entity.js +22 -0
- package/dist/auth/credential-refresh.entity.d.ts +17 -0
- package/dist/auth/credential-refresh.entity.functions.d.ts +57 -0
- package/dist/auth/credential-refresh.entity.functions.js +21 -0
- package/dist/auth/credential-refresh.entity.js +2 -0
- package/dist/auth/localAuth.d.ts +12 -2
- package/dist/auth/localAuth.js +58 -86
- package/dist/auth/memory-auth.adapter.d.ts +35 -0
- package/dist/auth/memory-auth.adapter.js +35 -0
- package/dist/auth/openAiCodexOAuth.d.ts +28 -6
- package/dist/auth/openAiCodexOAuth.js +22 -32
- 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 +30 -13
- package/dist/index.js +25 -50
- 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 +84 -33
- package/dist/llm/compat.js +188 -121
- 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 +47 -7
- package/dist/llm/modelCatalog.js +31 -57
- package/dist/llm/openAiCodex.d.ts +18 -7
- package/dist/llm/openAiCodex.js +57 -45
- package/dist/llm/openAiCodexWebSocket.d.ts +60 -7
- package/dist/llm/openAiCodexWebSocket.js +113 -105
- 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 +125 -29
- package/dist/llm/providers.js +311 -117
- package/dist/llm/retry.d.ts +11 -47
- package/dist/llm/retry.js +33 -52
- package/dist/llm/router.d.ts +56 -28
- package/dist/llm/router.js +125 -88
- package/dist/llm/sse.d.ts +58 -29
- package/dist/llm/sse.js +47 -39
- 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 +154 -6
- package/dist/plugin.adapter.js +53 -10
- 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 +22 -0
- package/dist/ports/host-credentials.port.js +4 -0
- 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 +66 -19
- package/dist/ports/model-endpoints.port.js +22 -4
- 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 +53 -0
- package/dist/ports/models-transport.port.js +7 -0
- 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 +18 -61
- package/dist/settings/memory-settings.adapter.d.ts +12 -0
- package/dist/settings/memory-settings.adapter.js +11 -0
- 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 +15 -0
- package/dist/settings/settings-value.entity.functions.d.ts +51 -0
- package/dist/settings/settings-value.entity.functions.js +42 -0
- package/dist/settings/settings-value.entity.js +2 -0
- 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 +104 -0
- package/dist/transport/http-proxy.entity.functions.d.ts +51 -0
- package/dist/transport/http-proxy.entity.functions.js +112 -0
- package/dist/transport/http-proxy.entity.js +42 -0
- 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 +49 -0
- package/dist/transport/models-transport.adapter.js +99 -0
- package/dist/transport/resilient-http-client.adapter.d.ts +73 -0
- package/dist/transport/resilient-http-client.adapter.js +177 -0
- package/dist/transport/undici-fetch.adapter.d.ts +13 -0
- package/dist/transport/undici-fetch.adapter.js +1 -0
- package/package.json +13 -6
- package/dist/auth/anthropicOAuth.test.d.ts +0 -1
- package/dist/auth/localAuth.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/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/roleView.test.d.ts +0 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Context, Option, Schema } from "effect";
|
|
2
|
+
import type { Effect, Redacted } from "effect";
|
|
3
|
+
import type { ProviderId } from "@xandreed/core";
|
|
4
|
+
/**
|
|
5
|
+
* A stored provider credential: a raw API key, an OAuth subscription (with
|
|
6
|
+
* refresh material and absolute expiry, epoch ms), or a local provider that
|
|
7
|
+
* needs no key. Its secrets (`key`, `access`, `refresh`) are `Redacted`, so
|
|
8
|
+
* they print as `<redacted>` in errors, logs and fingerprints; unwrap one
|
|
9
|
+
* with `Redacted.value` only where a request is built. The encoded form is
|
|
10
|
+
* the on-disk `auth.json` vocabulary the previous line established, secrets
|
|
11
|
+
* in the clear, so existing credentials keep working. Store a credential
|
|
12
|
+
* through `Schema.encodeEffect(Credential)`, never `JSON.stringify`, which
|
|
13
|
+
* writes `"<redacted>"` in place of each secret.
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export declare const Credential: Schema.Union<readonly [Schema.Struct<{
|
|
18
|
+
readonly type: Schema.Literal<"api_key">;
|
|
19
|
+
readonly key: Schema.RedactedFromValue<Schema.String>;
|
|
20
|
+
}>, Schema.Struct<{
|
|
21
|
+
readonly type: Schema.Literal<"oauth">;
|
|
22
|
+
readonly access: Schema.RedactedFromValue<Schema.String>;
|
|
23
|
+
readonly refresh: Schema.RedactedFromValue<Schema.String>;
|
|
24
|
+
readonly expires: Schema.Number;
|
|
25
|
+
readonly accountId: Schema.optionalKey<Schema.String>;
|
|
26
|
+
readonly installationId: Schema.optionalKey<Schema.String>;
|
|
27
|
+
}>, Schema.Struct<{
|
|
28
|
+
readonly type: Schema.Literal<"local">;
|
|
29
|
+
readonly baseUrl: Schema.optionalKey<Schema.String>;
|
|
30
|
+
}>]>;
|
|
31
|
+
export type Credential = typeof Credential.Type;
|
|
32
|
+
declare const AuthError_base: Schema.Class<AuthError, Schema.TaggedStruct<"AuthError", {
|
|
33
|
+
readonly provider: Schema.String;
|
|
34
|
+
readonly message: Schema.String;
|
|
35
|
+
/**
|
|
36
|
+
* `auth.corrupt`: the store's backing data could not be read or decoded.
|
|
37
|
+
* Nothing was read as absent and nothing was written over it.
|
|
38
|
+
*/
|
|
39
|
+
readonly code: Schema.optionalKey<Schema.Literal<"auth.corrupt">>;
|
|
40
|
+
}>, import("effect/Cause").YieldableError>;
|
|
41
|
+
export declare class AuthError extends AuthError_base {
|
|
42
|
+
}
|
|
43
|
+
declare const AuthStore_base: Context.ServiceClass<AuthStore, "@xandreed/core/AuthStore", {
|
|
44
|
+
readonly all: Effect.Effect<ReadonlyMap<string, Credential>, AuthError>;
|
|
45
|
+
readonly get: (p: ProviderId) => Effect.Effect<Option.Option<Credential>, AuthError>;
|
|
46
|
+
readonly resolveKey: (p: ProviderId) => Effect.Effect<Option.Option<Redacted.Redacted<string>>, AuthError>;
|
|
47
|
+
/** Persist a credential (a login). */
|
|
48
|
+
readonly set: (p: ProviderId, credential: Credential) => Effect.Effect<void, AuthError>;
|
|
49
|
+
/** Remove a provider's credential everywhere it is stored (a logout). */
|
|
50
|
+
readonly remove: (p: ProviderId) => Effect.Effect<void, AuthError>;
|
|
51
|
+
}>;
|
|
52
|
+
/**
|
|
53
|
+
* The credential store, read lazily per request: `resolveKey` returns a
|
|
54
|
+
* usable secret (refreshing a near-expiry OAuth token first, and persisting
|
|
55
|
+
* it where the store keeps credentials), so a credential added mid-session
|
|
56
|
+
* takes effect on the next call with no restart. `None` means the provider
|
|
57
|
+
* is not configured. Every secret it hands out, through `get` and `all` as
|
|
58
|
+
* through `resolveKey`, is `Redacted`.
|
|
59
|
+
*
|
|
60
|
+
* One refresh of a credential runs at a time: concurrent calls on one
|
|
61
|
+
* expired token send one token request and share its result. A `set` or
|
|
62
|
+
* `remove` made while that request is in flight wins over the refreshed
|
|
63
|
+
* token. A store whose backing data cannot be read or decoded fails every
|
|
64
|
+
* call with an `AuthError` of code `auth.corrupt` instead of reading it as
|
|
65
|
+
* empty, so no write replaces credentials it could not read.
|
|
66
|
+
* `authStoreConformance` (`@xandreed/plugin-models/conformance`) checks a
|
|
67
|
+
* store against this contract. Its key stays `@xandreed/core/AuthStore`, the
|
|
68
|
+
* package it was first declared in: plugins' `provides` and hosts' bindings
|
|
69
|
+
* name it, so it never changes.
|
|
70
|
+
*/
|
|
71
|
+
export declare class AuthStore extends AuthStore_base {
|
|
72
|
+
}
|
|
73
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Context, Option, Schema } from "effect";
|
|
2
|
+
const Secret = Schema.RedactedFromValue(Schema.String);
|
|
3
|
+
export const Credential = Schema.Union([
|
|
4
|
+
Schema.Struct({ type: Schema.Literal("api_key"), key: Secret }),
|
|
5
|
+
Schema.Struct({
|
|
6
|
+
type: Schema.Literal("oauth"),
|
|
7
|
+
access: Secret,
|
|
8
|
+
refresh: Secret,
|
|
9
|
+
expires: Schema.Number,
|
|
10
|
+
accountId: Schema.optionalKey(Schema.String),
|
|
11
|
+
installationId: Schema.optionalKey(Schema.String)
|
|
12
|
+
}),
|
|
13
|
+
Schema.Struct({ type: Schema.Literal("local"), baseUrl: Schema.optionalKey(Schema.String) })
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
export class AuthError extends Schema.TaggedError()("AuthError", {
|
|
17
|
+
provider: Schema.String,
|
|
18
|
+
message: Schema.String,
|
|
19
|
+
code: Schema.optionalKey(Schema.Literal("auth.corrupt"))
|
|
20
|
+
}) {
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class AuthStore extends Context.Service()("@xandreed/core/AuthStore") {
|
|
24
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
import type { Effect, Option } from "effect";
|
|
3
|
+
import type { ProviderId } from "@xandreed/core";
|
|
4
|
+
import type { AuthError } from "./auth-store.port.js";
|
|
5
|
+
import type { CredentialInput } from "../auth/credential-input.entity.js";
|
|
6
|
+
declare const HostCredentials_base: Context.ServiceClass<HostCredentials, "@xandreed/plugin-models/HostCredentials", {
|
|
7
|
+
readonly load: Effect.Effect<ReadonlyMap<string, CredentialInput>, AuthError>;
|
|
8
|
+
readonly save: (provider: ProviderId, credential: Option.Option<CredentialInput>) => Effect.Effect<void, AuthError>;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Credentials a host keeps itself (a secrets manager, a database, its own
|
|
12
|
+
* session store), for the models plugin with `storage: "memory"`. `load` is
|
|
13
|
+
* read once, when the plugin starts; `save` is called after every change the
|
|
14
|
+
* AuthStore makes — a login (`set`), a logout (`None`), an OAuth token
|
|
15
|
+
* refreshed in memory — so the host can keep the new value. Secrets cross
|
|
16
|
+
* this port `Redacted`. A failed `save` fails a login or logout (memory is
|
|
17
|
+
* left as it was) but not a refresh: the refreshed token is already the
|
|
18
|
+
* only valid one, so it stays in memory and the failure is logged.
|
|
19
|
+
*/
|
|
20
|
+
export declare class HostCredentials extends HostCredentials_base {
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Context, Option } from "effect";
|
|
2
|
+
import type { ModelSelection } from "@xandreed/core";
|
|
3
|
+
/** Private execution-time purpose; utilities provide Helper without recording another call. */
|
|
4
|
+
export declare const CurrentModelCallPurpose: Context.Reference<"Loop" | "Helper">;
|
|
5
|
+
/** Private invocation metadata; a routed object call can use a provider's text implementation. */
|
|
6
|
+
export declare const CurrentModelCallMethod: Context.Reference<"Text" | "Object" | "Stream">;
|
|
7
|
+
export declare const CurrentModelCallSelection: Context.Reference<Option.Option<ModelSelection>>;
|
|
8
|
+
/** Identifies which logical budget owns inherited invocation metadata. */
|
|
9
|
+
export declare const CurrentModelCallMetadataOwner: Context.Reference<Option.Option<string & import("effect/Brand").Brand<"ModelCallId">>>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { Context, Option } from "effect";
|
|
2
|
+
export const CurrentModelCallPurpose = Context.Reference("@xandreed/plugin-models/CurrentModelCallPurpose", { defaultValue: () => "Loop" }), CurrentModelCallMethod = Context.Reference("@xandreed/plugin-models/CurrentModelCallMethod", { defaultValue: () => "Text" }), CurrentModelCallSelection = Context.Reference("@xandreed/plugin-models/CurrentModelCallSelection", { defaultValue: () => Option.none() }), CurrentModelCallMetadataOwner = Context.Reference("@xandreed/plugin-models/CurrentModelCallMetadataOwner", { defaultValue: () => Option.none() });
|
|
@@ -1,33 +1,80 @@
|
|
|
1
1
|
import { Context, Schema } from "effect";
|
|
2
|
+
/** A base URL using chat completions, or an explicit Anthropic Messages protocol. @public */
|
|
3
|
+
export declare const ModelEndpoint: Schema.Union<readonly [Schema.Struct<{
|
|
4
|
+
/** Absent keeps the existing chat-completions protocol. */
|
|
5
|
+
readonly api: Schema.optionalKey<Schema.Literal<"chat-completions">>;
|
|
6
|
+
readonly standardOnly: Schema.optionalKey<Schema.Boolean>;
|
|
7
|
+
readonly url: Schema.String;
|
|
8
|
+
readonly apiKey: Schema.optionalKey<Schema.Union<readonly [Schema.String, Schema.Redacted<Schema.String>]>>;
|
|
9
|
+
readonly apiKeyEnv: Schema.optionalKey<Schema.String>;
|
|
10
|
+
readonly images: Schema.optionalKey<Schema.Boolean>;
|
|
11
|
+
}>, Schema.Struct<{
|
|
12
|
+
readonly api: Schema.Literal<"anthropic-messages">;
|
|
13
|
+
/** The API key is opaque in either header; omission uses x-api-key. */
|
|
14
|
+
readonly auth: Schema.optionalKey<Schema.Literals<readonly ["x-api-key", "bearer"]>>;
|
|
15
|
+
/** False disables framework caching and refuses caller cache controls. */
|
|
16
|
+
readonly cacheControl: Schema.optionalKey<Schema.Boolean>;
|
|
17
|
+
/** Preserve the pinned SDK's version by default; an explicit version is sent verbatim. */
|
|
18
|
+
readonly apiVersion: Schema.optionalKey<Schema.String>;
|
|
19
|
+
/** Added to the SDK's own beta flags, in order with duplicates removed. */
|
|
20
|
+
readonly betas: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
21
|
+
readonly url: Schema.String;
|
|
22
|
+
readonly apiKey: Schema.optionalKey<Schema.Union<readonly [Schema.String, Schema.Redacted<Schema.String>]>>;
|
|
23
|
+
readonly apiKeyEnv: Schema.optionalKey<Schema.String>;
|
|
24
|
+
readonly images: Schema.optionalKey<Schema.Boolean>;
|
|
25
|
+
}>]>;
|
|
26
|
+
export type ModelEndpoint = typeof ModelEndpoint.Type;
|
|
2
27
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* from `apiKey`, then the environment variable `apiKeyEnv` names, then the
|
|
7
|
-
* AuthStore's key for `<name>`; with none, no Authorization header is sent.
|
|
8
|
-
* `standardOnly` (default true) sends only standard chat-completions fields.
|
|
28
|
+
* Endpoints by provider name; a name that matches a built-in provider replaces it.
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
9
31
|
*/
|
|
10
|
-
export declare const
|
|
32
|
+
export declare const ModelEndpoints: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.Struct<{
|
|
33
|
+
/** Absent keeps the existing chat-completions protocol. */
|
|
34
|
+
readonly api: Schema.optionalKey<Schema.Literal<"chat-completions">>;
|
|
35
|
+
readonly standardOnly: Schema.optionalKey<Schema.Boolean>;
|
|
11
36
|
readonly url: Schema.String;
|
|
12
|
-
readonly apiKey: Schema.optionalKey<Schema.String
|
|
37
|
+
readonly apiKey: Schema.optionalKey<Schema.Union<readonly [Schema.String, Schema.Redacted<Schema.String>]>>;
|
|
13
38
|
readonly apiKeyEnv: Schema.optionalKey<Schema.String>;
|
|
14
|
-
readonly
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
|
|
39
|
+
readonly images: Schema.optionalKey<Schema.Boolean>;
|
|
40
|
+
}>, Schema.Struct<{
|
|
41
|
+
readonly api: Schema.Literal<"anthropic-messages">;
|
|
42
|
+
/** The API key is opaque in either header; omission uses x-api-key. */
|
|
43
|
+
readonly auth: Schema.optionalKey<Schema.Literals<readonly ["x-api-key", "bearer"]>>;
|
|
44
|
+
/** False disables framework caching and refuses caller cache controls. */
|
|
45
|
+
readonly cacheControl: Schema.optionalKey<Schema.Boolean>;
|
|
46
|
+
/** Preserve the pinned SDK's version by default; an explicit version is sent verbatim. */
|
|
47
|
+
readonly apiVersion: Schema.optionalKey<Schema.String>;
|
|
48
|
+
/** Added to the SDK's own beta flags, in order with duplicates removed. */
|
|
49
|
+
readonly betas: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
19
50
|
readonly url: Schema.String;
|
|
20
|
-
readonly apiKey: Schema.optionalKey<Schema.String
|
|
51
|
+
readonly apiKey: Schema.optionalKey<Schema.Union<readonly [Schema.String, Schema.Redacted<Schema.String>]>>;
|
|
21
52
|
readonly apiKeyEnv: Schema.optionalKey<Schema.String>;
|
|
22
|
-
readonly
|
|
23
|
-
}>>;
|
|
53
|
+
readonly images: Schema.optionalKey<Schema.Boolean>;
|
|
54
|
+
}>]>>;
|
|
24
55
|
export type ModelEndpoints = typeof ModelEndpoints.Type;
|
|
25
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* The endpoints the models plugin was configured with; none by default.
|
|
58
|
+
*
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
26
61
|
export declare const CurrentModelEndpoints: Context.Reference<{
|
|
27
62
|
readonly [x: string]: {
|
|
28
63
|
readonly url: string;
|
|
29
|
-
readonly
|
|
30
|
-
readonly
|
|
64
|
+
readonly images?: boolean;
|
|
65
|
+
readonly apiKey?: string | import("effect/Redacted").Redacted<string>;
|
|
66
|
+
readonly api?: "chat-completions";
|
|
31
67
|
readonly standardOnly?: boolean;
|
|
68
|
+
readonly apiKeyEnv?: string;
|
|
69
|
+
} | {
|
|
70
|
+
readonly url: string;
|
|
71
|
+
readonly api: "anthropic-messages";
|
|
72
|
+
readonly images?: boolean;
|
|
73
|
+
readonly apiKey?: string | import("effect/Redacted").Redacted<string>;
|
|
74
|
+
readonly auth?: "x-api-key" | "bearer";
|
|
75
|
+
readonly apiKeyEnv?: string;
|
|
76
|
+
readonly cacheControl?: boolean;
|
|
77
|
+
readonly apiVersion?: string;
|
|
78
|
+
readonly betas?: readonly string[];
|
|
32
79
|
};
|
|
33
80
|
}>;
|
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
import { Context, Schema } from "effect";
|
|
2
|
-
|
|
2
|
+
const endpointFields = {
|
|
3
3
|
url: Schema.String,
|
|
4
|
-
apiKey: Schema.optionalKey(Schema.
|
|
4
|
+
apiKey: Schema.optionalKey(Schema.Union([
|
|
5
|
+
Schema.String,
|
|
6
|
+
Schema.Redacted(Schema.String).annotate({ message: "apiKey is a string or a Redacted string" })
|
|
7
|
+
]).annotate({ message: "apiKey is a string or a Redacted string" })),
|
|
5
8
|
apiKeyEnv: Schema.optionalKey(Schema.String),
|
|
6
|
-
|
|
7
|
-
}
|
|
9
|
+
images: Schema.optionalKey(Schema.Boolean)
|
|
10
|
+
};
|
|
11
|
+
export const ModelEndpoint = Schema.Union([
|
|
12
|
+
Schema.Struct({
|
|
13
|
+
...endpointFields,
|
|
14
|
+
api: Schema.optionalKey(Schema.Literal("chat-completions")),
|
|
15
|
+
standardOnly: Schema.optionalKey(Schema.Boolean)
|
|
16
|
+
}).annotate({ messageUnexpectedKey: "not an option of a chat-completions endpoint" }),
|
|
17
|
+
Schema.Struct({
|
|
18
|
+
...endpointFields,
|
|
19
|
+
api: Schema.Literal("anthropic-messages"),
|
|
20
|
+
auth: Schema.optionalKey(Schema.Literals(["x-api-key", "bearer"])),
|
|
21
|
+
cacheControl: Schema.optionalKey(Schema.Boolean),
|
|
22
|
+
apiVersion: Schema.optionalKey(Schema.String.check(Schema.isPattern(/^\d{4}-\d{2}-\d{2}$/))),
|
|
23
|
+
betas: Schema.optionalKey(Schema.Array(Schema.String.check(Schema.isPattern(/^[A-Za-z0-9][A-Za-z0-9._-]*$/))))
|
|
24
|
+
}).annotate({ messageUnexpectedKey: "not an option of an anthropic-messages endpoint" })
|
|
25
|
+
]).annotate({ messageUnexpectedKey: "not an option of a model endpoint" }), ModelEndpoints = Schema.Record(Schema.String, ModelEndpoint), CurrentModelEndpoints = Context.Reference("@xandreed/plugin-models/CurrentModelEndpoints", {
|
|
8
26
|
defaultValue: () => ({})
|
|
9
27
|
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Context, Option } from "effect";
|
|
2
|
+
import type { ModelRequestCall } from "../transport/resilient-http-client.adapter.js";
|
|
3
|
+
/** Read when a logical model call executes; the complete policy overrides the defaults. @public */
|
|
4
|
+
export declare const CurrentModelRetryPolicy: Context.Reference<{
|
|
5
|
+
readonly maxAttempts: number;
|
|
6
|
+
readonly requestTimeoutMs: number;
|
|
7
|
+
readonly bodyIdleTimeoutMs: number;
|
|
8
|
+
readonly totalTimeoutMs: number;
|
|
9
|
+
readonly retryAfterMaxMs: number;
|
|
10
|
+
readonly backoff: {
|
|
11
|
+
readonly initialMs: number;
|
|
12
|
+
readonly maxMs: number;
|
|
13
|
+
readonly jitter: number;
|
|
14
|
+
};
|
|
15
|
+
}>;
|
|
16
|
+
/** Private per-call counter/deadline, shared only by its primary and fallback rung. */
|
|
17
|
+
export declare const CurrentModelRequestCall: Context.Reference<Option.Option<ModelRequestCall>>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Context, Option } from "effect";
|
|
2
|
+
import { modelRetryDefaults } from "../llm/model-retry-policy.entity.js";
|
|
3
|
+
export const CurrentModelRetryPolicy = Context.Reference("@xandreed/plugin-models/CurrentModelRetryPolicy", { defaultValue: () => modelRetryDefaults }), CurrentModelRequestCall = Context.Reference("@xandreed/plugin-models/CurrentModelRequestCall", { defaultValue: () => Option.none() });
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
/** Static per-model settings captured where the models layer is built. @public */
|
|
3
|
+
export declare const CurrentModelSettings: Context.Reference<{
|
|
4
|
+
readonly [x: string]: {
|
|
5
|
+
readonly effort?: "none" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
6
|
+
readonly limits?: {
|
|
7
|
+
readonly maxOutputTokens?: number;
|
|
8
|
+
readonly contextWindow?: number;
|
|
9
|
+
};
|
|
10
|
+
readonly thinking?: {
|
|
11
|
+
readonly _tag: "Off";
|
|
12
|
+
} | {
|
|
13
|
+
readonly _tag: "Adaptive";
|
|
14
|
+
readonly display?: "omitted" | "summarized";
|
|
15
|
+
} | {
|
|
16
|
+
readonly _tag: "Budget";
|
|
17
|
+
readonly budgetTokens: number;
|
|
18
|
+
readonly display?: "omitted" | "summarized";
|
|
19
|
+
} | {
|
|
20
|
+
readonly _tag: "BetweenTools";
|
|
21
|
+
};
|
|
22
|
+
readonly promptCache?: {
|
|
23
|
+
readonly _tag: "Auto";
|
|
24
|
+
readonly ttl: "5m" | "1h";
|
|
25
|
+
} | {
|
|
26
|
+
readonly _tag: "TopLevel";
|
|
27
|
+
readonly ttl: "5m" | "1h";
|
|
28
|
+
} | {
|
|
29
|
+
readonly _tag: "Off";
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Context, Option } from "effect";
|
|
2
|
+
import type { Effect, Redacted } from "effect";
|
|
3
|
+
import type { Agent } from "node:http";
|
|
4
|
+
import type { ProxyUnsupported } from "../transport/http-proxy.entity.js";
|
|
5
|
+
/**
|
|
6
|
+
* A fetch for the models plugin's HTTP calls: a URL (string or `URL`) and a
|
|
7
|
+
* `RequestInit`, as the provider clients, the OpenAI-compatible client and
|
|
8
|
+
* the OAuth token requests call it. Any `fetch` is one.
|
|
9
|
+
*/
|
|
10
|
+
export type ModelsFetch = (input: string | URL, init?: RequestInit) => Promise<Response>;
|
|
11
|
+
/**
|
|
12
|
+
* How a WebSocket reaches its target. `Agent` is for Node only: the agent
|
|
13
|
+
* the `ws` client connects with (one that tunnels through the proxy with
|
|
14
|
+
* CONNECT, or a plain one for a direct connection). `Proxy` is for Bun only:
|
|
15
|
+
* the proxy URL Bun's own `WebSocket` takes as its `proxy` option. A route
|
|
16
|
+
* the runtime cannot use (`Proxy` outside Bun, `Agent` on Bun, whose `ws`
|
|
17
|
+
* stand-in takes neither) fails the call rather than connecting past the
|
|
18
|
+
* proxy.
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export type WebSocketProxy = {
|
|
23
|
+
readonly _tag: "Agent";
|
|
24
|
+
readonly agent: Agent;
|
|
25
|
+
} | {
|
|
26
|
+
readonly _tag: "Proxy";
|
|
27
|
+
readonly url: Redacted.Redacted<string>;
|
|
28
|
+
};
|
|
29
|
+
declare const ModelsTransport_base: Context.ServiceClass<ModelsTransport, "@xandreed/plugin-models/ModelsTransport", {
|
|
30
|
+
readonly fetch: ModelsFetch;
|
|
31
|
+
readonly webSocketAgent?: (target: URL) => Effect.Effect<Option.Option<WebSocketProxy>, ProxyUnsupported>;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* The network path of the models plugin: every HTTP call it makes (the
|
|
35
|
+
* provider SDKs, the OpenAI-compatible client, OAuth token requests) goes
|
|
36
|
+
* through `fetch`, and the OpenAI subscription's WebSocket asks
|
|
37
|
+
* `webSocketAgent` how to reach its target: `None` connects the runtime's
|
|
38
|
+
* default way (direct, unless the runtime applies an environment proxy
|
|
39
|
+
* itself, as Node's global agents do under `NODE_USE_ENV_PROXY`),
|
|
40
|
+
* `ProxyUnsupported` refuses (a proxy applies that this runtime cannot
|
|
41
|
+
* tunnel a WebSocket through). Without `webSocketAgent`, WebSockets connect
|
|
42
|
+
* the default way. `ModelsTransportLive` builds one from a proxy setting and
|
|
43
|
+
* the environment; a host provides its own (a fetch with client
|
|
44
|
+
* certificates, say) through `Agent.define({ services })`.
|
|
45
|
+
*/
|
|
46
|
+
export declare class ModelsTransport extends ModelsTransport_base {
|
|
47
|
+
}
|
|
48
|
+
/** Internal provenance: only this exact managed direct instance yields to an explicit call-local fetch. */
|
|
49
|
+
export declare const CurrentManagedModelsTransport: Context.Reference<Option.Option<{
|
|
50
|
+
readonly fetch: ModelsFetch;
|
|
51
|
+
readonly webSocketAgent?: (target: URL) => Effect.Effect<Option.Option<WebSocketProxy>, ProxyUnsupported>;
|
|
52
|
+
}>>;
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Context, Option } from "effect";
|
|
2
|
+
|
|
3
|
+
export class ModelsTransport extends Context.Service()("@xandreed/plugin-models/ModelsTransport") {
|
|
4
|
+
}
|
|
5
|
+
export const CurrentManagedModelsTransport = Context.Reference("@xandreed/plugin-models/CurrentManagedModelsTransport", {
|
|
6
|
+
defaultValue: Option.none
|
|
7
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
/** A captured SDK client reads this immutable frame in the invoking call's fiber. */
|
|
3
|
+
export declare const CurrentPromptCacheFrame: Context.Reference<{
|
|
4
|
+
readonly candidates: readonly {
|
|
5
|
+
readonly control: {
|
|
6
|
+
readonly type: "ephemeral";
|
|
7
|
+
readonly ttl?: "5m" | "1h";
|
|
8
|
+
};
|
|
9
|
+
readonly priority: number;
|
|
10
|
+
}[];
|
|
11
|
+
readonly policy: {
|
|
12
|
+
readonly _tag: "Auto";
|
|
13
|
+
readonly ttl: "5m" | "1h";
|
|
14
|
+
} | {
|
|
15
|
+
readonly _tag: "TopLevel";
|
|
16
|
+
readonly ttl: "5m" | "1h";
|
|
17
|
+
} | {
|
|
18
|
+
readonly _tag: "Off";
|
|
19
|
+
};
|
|
20
|
+
readonly capability: boolean;
|
|
21
|
+
}>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Context, Effect, Option, Schema } from "effect";
|
|
2
|
+
declare const EngineSettings_base: Schema.Class<EngineSettings, Schema.Struct<{
|
|
3
|
+
readonly model: Schema.withConstructorDefault<Schema.OptionFromOptional<Schema.Codec<string, string, never, never>>>;
|
|
4
|
+
readonly codeModel: Schema.withConstructorDefault<Schema.OptionFromOptional<Schema.Codec<string, string, never, never>>>;
|
|
5
|
+
readonly fastModel: Schema.withConstructorDefault<Schema.OptionFromOptional<Schema.Codec<string, string, never, never>>>;
|
|
6
|
+
readonly fallbackModel: Schema.withConstructorDefault<Schema.OptionFromOptional<Schema.Codec<string, string, never, never>>>;
|
|
7
|
+
readonly maxAttempts: Schema.withConstructorDefault<Schema.OptionFromOptional<Schema.Codec<number, number, never, never>>>;
|
|
8
|
+
readonly budgetMillis: Schema.withConstructorDefault<Schema.OptionFromOptional<Schema.Codec<number, number, never, never>>>;
|
|
9
|
+
/** Selected after the model because the accepted levels are model-specific. */
|
|
10
|
+
readonly reasoningEffort: Schema.withConstructorDefault<Schema.OptionFromOptional<Schema.Codec<"none" | "low" | "medium" | "high" | "xhigh" | "max", "none" | "low" | "medium" | "high" | "xhigh" | "max", never, never>>>;
|
|
11
|
+
readonly codeReasoningEffort: Schema.withConstructorDefault<Schema.OptionFromOptional<Schema.Codec<"none" | "low" | "medium" | "high" | "xhigh" | "max", "none" | "low" | "medium" | "high" | "xhigh" | "max", never, never>>>;
|
|
12
|
+
readonly fastReasoningEffort: Schema.withConstructorDefault<Schema.OptionFromOptional<Schema.Codec<"none" | "low" | "medium" | "high" | "xhigh" | "max", "none" | "low" | "medium" | "high" | "xhigh" | "max", never, never>>>;
|
|
13
|
+
}>, {}>;
|
|
14
|
+
/** @public */
|
|
15
|
+
export declare class EngineSettings extends EngineSettings_base {
|
|
16
|
+
}
|
|
17
|
+
declare const SettingsError_base: Schema.Class<SettingsError, Schema.TaggedStruct<"SettingsError", {
|
|
18
|
+
readonly message: Schema.String;
|
|
19
|
+
/**
|
|
20
|
+
* `settings.corrupt`: the store's backing data could not be read or
|
|
21
|
+
* decoded. Nothing was read as defaults and nothing was written over it.
|
|
22
|
+
*/
|
|
23
|
+
readonly code: Schema.optionalKey<Schema.Literal<"settings.corrupt">>;
|
|
24
|
+
}>, import("effect/Cause").YieldableError>;
|
|
25
|
+
/** @public */
|
|
26
|
+
export declare class SettingsError extends SettingsError_base {
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The three model roles a selection can be persisted under.
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export type ModelRole = "general" | "code" | "fast";
|
|
34
|
+
/** The non-role keys the keyed setter may write — a closed vocabulary, so a
|
|
35
|
+
* typo can never land a dead key in the user's config.
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
export declare const SETTINGS_KEYS: readonly ["fallbackModel", "maxAttempts", "budgetMillis", "reasoningEffort", "codeReasoningEffort", "fastReasoningEffort"];
|
|
40
|
+
/** @public */
|
|
41
|
+
export type SettingsKey = (typeof SETTINGS_KEYS)[number];
|
|
42
|
+
declare const SettingsStore_base: Context.ServiceClass<SettingsStore, "@xandreed/core/SettingsStore", {
|
|
43
|
+
readonly load: Effect.Effect<EngineSettings, SettingsError>;
|
|
44
|
+
/** Persist one role's model selection (a role choice); `None` clears
|
|
45
|
+
* the role so it falls back to its default again. A selection that is
|
|
46
|
+
* not `"<provider>:<modelId>"` fails with a `SettingsError` and writes
|
|
47
|
+
* nothing. */
|
|
48
|
+
readonly setRole: (role: ModelRole, selection: Option.Option<string>) => Effect.Effect<void, SettingsError>;
|
|
49
|
+
/** Persist one non-role key from its STRING form (a settings edit): the
|
|
50
|
+
* adapter validates + coerces per key ("true", "3", "provider:model")
|
|
51
|
+
* and rejects a value that doesn't parse with a `SettingsError`,
|
|
52
|
+
* writing nothing; `None` clears the key. */
|
|
53
|
+
readonly set: (key: SettingsKey, value: Option.Option<string>) => Effect.Effect<void, SettingsError>;
|
|
54
|
+
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Read-through settings port. `load` re-reads the backing store on every call
|
|
57
|
+
* so a value changed mid-session takes effect on the next turn — callers must
|
|
58
|
+
* not cache the result across turns. A store may be read-only: then
|
|
59
|
+
* `setRole` and `set` fail with a `SettingsError` and write nothing. A store
|
|
60
|
+
* whose backing data cannot be read or decoded fails `load` and every write
|
|
61
|
+
* with a `SettingsError` of code `settings.corrupt` instead of reading it as
|
|
62
|
+
* defaults, so no write replaces settings it could not read.
|
|
63
|
+
* `settingsStoreConformance` (`@xandreed/plugin-models/conformance`) checks
|
|
64
|
+
* a store against this contract. Its key stays `@xandreed/core/SettingsStore`,
|
|
65
|
+
* the package it was first declared in: plugins' `provides` and hosts'
|
|
66
|
+
* bindings name it, so it never changes.
|
|
67
|
+
*/
|
|
68
|
+
export declare class SettingsStore extends SettingsStore_base {
|
|
69
|
+
}
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Context, Effect, Option, Schema } from "effect";
|
|
2
|
+
import { ReasoningEffort } from "@xandreed/core";
|
|
3
|
+
const optionField = (schema) => Schema.OptionFromOptional(schema).pipe(Schema.withConstructorDefault(Effect.succeed(Option.none())));
|
|
4
|
+
|
|
5
|
+
export class EngineSettings extends Schema.Class("EngineSettings")({
|
|
6
|
+
model: optionField(Schema.String),
|
|
7
|
+
codeModel: optionField(Schema.String),
|
|
8
|
+
fastModel: optionField(Schema.String),
|
|
9
|
+
fallbackModel: optionField(Schema.String),
|
|
10
|
+
maxAttempts: optionField(Schema.Number),
|
|
11
|
+
budgetMillis: optionField(Schema.Number),
|
|
12
|
+
reasoningEffort: optionField(ReasoningEffort),
|
|
13
|
+
codeReasoningEffort: optionField(ReasoningEffort),
|
|
14
|
+
fastReasoningEffort: optionField(ReasoningEffort)
|
|
15
|
+
}) {
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class SettingsError extends Schema.TaggedError()("SettingsError", {
|
|
19
|
+
message: Schema.String,
|
|
20
|
+
code: Schema.optionalKey(Schema.Literal("settings.corrupt"))
|
|
21
|
+
}) {
|
|
22
|
+
}
|
|
23
|
+
export const SETTINGS_KEYS = [
|
|
24
|
+
"fallbackModel",
|
|
25
|
+
"maxAttempts",
|
|
26
|
+
"budgetMillis",
|
|
27
|
+
"reasoningEffort",
|
|
28
|
+
"codeReasoningEffort",
|
|
29
|
+
"fastReasoningEffort"
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
export class SettingsStore extends Context.Service()("@xandreed/core/SettingsStore") {
|
|
33
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
/**
|
|
3
|
+
* What the models plugin was configured to tell a model that binds thinking
|
|
4
|
+
* to the conversation (`thinkingPrefixMismatch`): `drop_block` for adaptive thinking by default;
|
|
5
|
+
* `provider-default` opts out of the explicit binding field.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CurrentThinkingPrefixMismatch: Context.Reference<"error" | "provider-default" | "drop_block">;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { Layer } from "effect";
|
|
2
|
-
import { SettingsStore } from "
|
|
2
|
+
import { SettingsStore } from "../ports/settings-store.port.js";
|
|
3
|
+
/** @public */
|
|
3
4
|
export declare const LocalSettingsStoreLive: (cwd: string, home: string) => Layer.Layer<SettingsStore, never, never>;
|