@deepstrike/sdk 0.2.52 → 0.2.60
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 +28 -28
- package/dist/agent-ir.d.ts +103 -0
- package/dist/agent-ir.js +134 -0
- package/dist/agent.d.ts +67 -0
- package/dist/agent.js +36 -0
- package/dist/collaboration/harness.js +1 -1
- package/dist/collaboration/modes/creator-verifier.d.ts +2 -7
- package/dist/collaboration/modes/creator-verifier.js +4 -6
- package/dist/collaboration/pool.d.ts +8 -20
- package/dist/collaboration/pool.js +27 -97
- package/dist/compat/anthropic/mcp.d.ts +15 -0
- package/dist/compat/anthropic/mcp.js +10 -0
- package/dist/compat/openai/agent.d.ts +34 -0
- package/dist/compat/openai/agent.js +24 -0
- package/dist/governance.d.ts +1 -17
- package/dist/governance.js +1 -34
- package/dist/guardrail.d.ts +6 -0
- package/dist/guardrail.js +1 -0
- package/dist/handoff-target.d.ts +12 -0
- package/dist/handoff-target.js +1 -0
- package/dist/harness/manifest.js +0 -4
- package/dist/index.d.ts +19 -7
- package/dist/index.js +8 -5
- package/dist/kernel.d.ts +2 -20
- package/dist/knowledge/public.d.ts +29 -0
- package/dist/knowledge/public.js +1 -0
- package/dist/mcp-server.d.ts +28 -0
- package/dist/mcp-server.js +1 -0
- package/dist/memory/agent.d.ts +2 -2
- package/dist/memory/agent.js +2 -2
- package/dist/memory/durable.d.ts +16 -0
- package/dist/memory/durable.js +46 -0
- package/dist/memory/in-memory-store.d.ts +9 -7
- package/dist/memory/in-memory-store.js +8 -2
- package/dist/memory/protocols.d.ts +22 -4
- package/dist/memory/public.d.ts +4 -3
- package/dist/memory/public.js +3 -2
- package/dist/providers/anthropic-adapter.d.ts +47 -0
- package/dist/providers/anthropic-adapter.js +444 -0
- package/dist/providers/anthropic-compatible.d.ts +2 -3
- package/dist/providers/anthropic-compatible.js +8 -5
- package/dist/providers/anthropic.d.ts +19 -23
- package/dist/providers/anthropic.js +169 -395
- package/dist/providers/base.js +43 -3
- package/dist/providers/capability-router.d.ts +29 -0
- package/dist/providers/capability-router.js +43 -0
- package/dist/providers/catalog.d.ts +16 -4
- package/dist/providers/catalog.js +112 -21
- package/dist/providers/content-normalization.d.ts +57 -0
- package/dist/providers/content-normalization.js +238 -0
- package/dist/providers/content-policy.d.ts +16 -0
- package/dist/providers/content-policy.js +39 -0
- package/dist/providers/credentials.d.ts +83 -0
- package/dist/providers/credentials.js +190 -0
- package/dist/providers/endpoints.d.ts +137 -0
- package/dist/providers/endpoints.js +128 -0
- package/dist/providers/factories.js +9 -3
- package/dist/providers/gemini-adapter.d.ts +33 -0
- package/dist/providers/gemini-adapter.js +272 -0
- package/dist/providers/gemini.d.ts +16 -3
- package/dist/providers/gemini.js +97 -195
- package/dist/providers/model-catalog.d.ts +37 -0
- package/dist/providers/model-catalog.js +62 -0
- package/dist/providers/model-registry.d.ts +98 -0
- package/dist/providers/model-registry.js +315 -0
- package/dist/providers/ollama-adapter.d.ts +65 -0
- package/dist/providers/ollama-adapter.js +188 -0
- package/dist/providers/ollama.d.ts +9 -4
- package/dist/providers/ollama.js +96 -109
- package/dist/providers/openai-chat-dialects.d.ts +154 -0
- package/dist/providers/openai-chat-dialects.js +179 -0
- package/dist/providers/openai-chat.d.ts +46 -18
- package/dist/providers/openai-chat.js +418 -51
- package/dist/providers/openai-responses-adapter.d.ts +42 -0
- package/dist/providers/openai-responses-adapter.js +341 -0
- package/dist/providers/openai-responses.d.ts +14 -33
- package/dist/providers/openai-responses.js +131 -264
- package/dist/providers/openai.d.ts +29 -76
- package/dist/providers/openai.js +195 -292
- package/dist/providers/protocol-adapter.d.ts +34 -0
- package/dist/providers/protocol-adapter.js +9 -0
- package/dist/providers/protocol-capabilities.d.ts +34 -0
- package/dist/providers/protocol-capabilities.js +44 -0
- package/dist/providers/provider-error.d.ts +31 -0
- package/dist/providers/provider-error.js +149 -0
- package/dist/providers/public.d.ts +26 -3
- package/dist/providers/public.js +13 -1
- package/dist/providers/registry.d.ts +7 -6
- package/dist/providers/registry.js +47 -20
- package/dist/providers/request-plan.d.ts +86 -0
- package/dist/providers/request-plan.js +175 -0
- package/dist/providers/usage-normalizer.d.ts +48 -0
- package/dist/providers/usage-normalizer.js +96 -0
- package/dist/providers/vendor-profiles.d.ts +2 -15
- package/dist/providers/vendor-profiles.js +14 -60
- package/dist/runtime/canonical-kernel-step.d.ts +1 -2
- package/dist/runtime/canonical-kernel-step.js +47 -12
- package/dist/runtime/context-policy.d.ts +10 -12
- package/dist/runtime/context-policy.js +6 -8
- package/dist/runtime/durable-content.d.ts +50 -0
- package/dist/runtime/durable-content.js +159 -0
- package/dist/runtime/execution-plane.d.ts +2 -2
- package/dist/runtime/execution-plane.js +2 -2
- package/dist/runtime/kernel-event-log.js +0 -1
- package/dist/runtime/kernel-step.d.ts +0 -1
- package/dist/runtime/kernel-step.js +4 -2
- package/dist/runtime/mcp-proxy-plane.d.ts +25 -1
- package/dist/runtime/mcp-proxy-plane.js +44 -6
- package/dist/runtime/output-schema.d.ts +1 -2
- package/dist/runtime/provider-replay.d.ts +1 -1
- package/dist/runtime/provider-replay.js +12 -27
- package/dist/runtime/reactive-session.d.ts +1 -1
- package/dist/runtime/reactive-session.js +2 -3
- package/dist/runtime/run-group.d.ts +1 -1
- package/dist/runtime/runner.d.ts +26 -40
- package/dist/runtime/runner.js +145 -63
- package/dist/runtime/session-log.d.ts +8 -1
- package/dist/runtime/session-log.js +42 -2
- package/dist/runtime/session-repair.d.ts +1 -1
- package/dist/runtime/session-repair.js +1 -1
- package/dist/runtime/sub-agent-orchestrator.d.ts +1 -1
- package/dist/runtime/sub-agent-orchestrator.js +8 -11
- package/dist/runtime/workflow-control-flow.d.ts +0 -4
- package/dist/runtime/workflow-control-flow.js +0 -16
- package/dist/session.d.ts +11 -0
- package/dist/session.js +1 -0
- package/dist/skill.d.ts +17 -0
- package/dist/skill.js +16 -0
- package/dist/skills/loader.d.ts +3 -0
- package/dist/tools/errors.d.ts +1 -3
- package/dist/tools/errors.js +1 -3
- package/dist/tools/index.d.ts +3 -0
- package/dist/types/agent.d.ts +21 -9
- package/dist/types/agent.js +30 -4
- package/dist/types.d.ts +128 -13
- package/package.json +3 -3
- package/dist/providers/deepseek.d.ts +0 -46
- package/dist/providers/deepseek.js +0 -97
- package/dist/providers/glm.d.ts +0 -25
- package/dist/providers/glm.js +0 -48
- package/dist/providers/kimi.d.ts +0 -23
- package/dist/providers/kimi.js +0 -30
- package/dist/providers/minimax.d.ts +0 -49
- package/dist/providers/minimax.js +0 -98
- package/dist/providers/profiles.d.ts +0 -1992
- package/dist/providers/profiles.js +0 -796
- package/dist/providers/qwen.d.ts +0 -38
- package/dist/providers/qwen.js +0 -97
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider serialization policy for canonical content. `bridge` means the protocol has no
|
|
3
|
+
* structured equivalent for that placement, but serializers may send the visible text projection.
|
|
4
|
+
* It never permits dropping a block or replacing it with an empty string.
|
|
5
|
+
*/
|
|
6
|
+
export function contentDispositionFor(protocol, modality, placement) {
|
|
7
|
+
if (modality === "text" || modality === "image") {
|
|
8
|
+
if (protocol === "ollama-chat" && modality === "image" && placement === "tool_result")
|
|
9
|
+
return "bridge";
|
|
10
|
+
return "native";
|
|
11
|
+
}
|
|
12
|
+
if (protocol === "openai-responses" && modality === "file" && placement === "message")
|
|
13
|
+
return "native";
|
|
14
|
+
if (protocol === "openai-responses" && modality === "file" && placement === "tool_result")
|
|
15
|
+
return "bridge";
|
|
16
|
+
if (protocol === "openai-chat" && ["audio", "file", "video"].includes(modality))
|
|
17
|
+
return "bridge";
|
|
18
|
+
if (protocol === "gemini" && ["audio", "file", "video"].includes(modality))
|
|
19
|
+
return "bridge";
|
|
20
|
+
return "unsupported";
|
|
21
|
+
}
|
|
22
|
+
export class ContentPolicyError extends Error {
|
|
23
|
+
protocol;
|
|
24
|
+
modality;
|
|
25
|
+
placement;
|
|
26
|
+
constructor(protocol, modality, placement) {
|
|
27
|
+
super(`Unsupported content policy: ${modality} ${placement} is not supported by ${protocol}`);
|
|
28
|
+
this.protocol = protocol;
|
|
29
|
+
this.modality = modality;
|
|
30
|
+
this.placement = placement;
|
|
31
|
+
this.name = "ContentPolicyError";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function requireContentDisposition(protocol, modality, placement) {
|
|
35
|
+
const disposition = contentDispositionFor(protocol, modality, placement);
|
|
36
|
+
if (disposition === "unsupported")
|
|
37
|
+
throw new ContentPolicyError(protocol, modality, placement);
|
|
38
|
+
return disposition;
|
|
39
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { EndpointProfileId, EndpointProtocol, ProviderId } from "./endpoints.js";
|
|
2
|
+
export type ProviderCredential = {
|
|
3
|
+
type: "api_key";
|
|
4
|
+
value: string;
|
|
5
|
+
} | {
|
|
6
|
+
type: "bearer";
|
|
7
|
+
value: string;
|
|
8
|
+
};
|
|
9
|
+
export interface CredentialRequest {
|
|
10
|
+
providerId: ProviderId;
|
|
11
|
+
modelId: string;
|
|
12
|
+
endpointId: EndpointProfileId;
|
|
13
|
+
protocol: EndpointProtocol;
|
|
14
|
+
}
|
|
15
|
+
export type CredentialResolver = (request: CredentialRequest) => ProviderCredential | undefined | Promise<ProviderCredential | undefined>;
|
|
16
|
+
export interface OAuthAccessToken {
|
|
17
|
+
accessToken: string;
|
|
18
|
+
/** Epoch time on the clock supplied to the resolver. The token is invalid at this instant. */
|
|
19
|
+
expiresAt: number;
|
|
20
|
+
scopes?: readonly string[];
|
|
21
|
+
audience?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface OAuthRefreshRequest {
|
|
24
|
+
providerId: ProviderId;
|
|
25
|
+
audience?: string;
|
|
26
|
+
requiredScopes: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
export interface OAuthCredentialResolverOptions {
|
|
29
|
+
providerId: ProviderId;
|
|
30
|
+
/** Provider-owned refresh/ADC bridge. The Host owns its transport and refresh token. */
|
|
31
|
+
refresh: (request: OAuthRefreshRequest) => OAuthAccessToken | Promise<OAuthAccessToken>;
|
|
32
|
+
requiredScopes?: readonly string[];
|
|
33
|
+
audience?: string;
|
|
34
|
+
clock?: () => number;
|
|
35
|
+
}
|
|
36
|
+
export interface CredentialOptions {
|
|
37
|
+
apiKey?: string;
|
|
38
|
+
bearerToken?: string;
|
|
39
|
+
credentialResolver?: CredentialResolver;
|
|
40
|
+
}
|
|
41
|
+
/** A deliberately non-sensitive credential failure. Never add resolver output to this error. */
|
|
42
|
+
export declare class CredentialResolutionError extends Error {
|
|
43
|
+
readonly code: "credential_unavailable" | "credential_invalid" | "credential_resolver_failed" | "credential_refresh_failed" | "credential_oauth_scope_mismatch" | "credential_oauth_audience_mismatch" | "credential_revoked" | "credential_auth_mode_unsupported";
|
|
44
|
+
readonly providerId: ProviderId;
|
|
45
|
+
readonly retryable: boolean;
|
|
46
|
+
constructor(code: CredentialResolutionError["code"], providerId: ProviderId, retryable?: boolean);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Host-owned OAuth/ADC extension. It retains only a refreshable bearer in process memory,
|
|
50
|
+
* never exposes refresh-token material, and coalesces concurrent refreshes for one provider.
|
|
51
|
+
*/
|
|
52
|
+
export declare class OAuthCredentialResolver {
|
|
53
|
+
private readonly providerId;
|
|
54
|
+
private readonly refresh;
|
|
55
|
+
private readonly requiredScopes;
|
|
56
|
+
private readonly audience?;
|
|
57
|
+
private readonly clock;
|
|
58
|
+
private token?;
|
|
59
|
+
private refreshInFlight?;
|
|
60
|
+
private revoked;
|
|
61
|
+
constructor(options: OAuthCredentialResolverOptions);
|
|
62
|
+
/** An arrow field intentionally remains bound when passed as `credentialResolver`. */
|
|
63
|
+
readonly resolve: CredentialResolver;
|
|
64
|
+
revoke(): void;
|
|
65
|
+
status(): {
|
|
66
|
+
providerId: ProviderId;
|
|
67
|
+
revoked: boolean;
|
|
68
|
+
hasUsableToken: boolean;
|
|
69
|
+
};
|
|
70
|
+
private usable;
|
|
71
|
+
private refreshToken;
|
|
72
|
+
private assertUsable;
|
|
73
|
+
}
|
|
74
|
+
/** Safe for diagnostics and event metadata. It intentionally has no credential value. */
|
|
75
|
+
export declare function redactCredential(credential: ProviderCredential): {
|
|
76
|
+
type: ProviderCredential["type"];
|
|
77
|
+
};
|
|
78
|
+
export declare function resolveCredential(request: CredentialRequest, options: CredentialOptions): Promise<ProviderCredential>;
|
|
79
|
+
/**
|
|
80
|
+
* The synchronous factory remains synchronous. A resolver which performs I/O must use
|
|
81
|
+
* `resolveProviderRuntimeAsync` / `createProviderAsync` instead of risking an implicit request.
|
|
82
|
+
*/
|
|
83
|
+
export declare function resolveCredentialSync(request: CredentialRequest, options: CredentialOptions): ProviderCredential;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/** A deliberately non-sensitive credential failure. Never add resolver output to this error. */
|
|
2
|
+
export class CredentialResolutionError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
providerId;
|
|
5
|
+
retryable;
|
|
6
|
+
constructor(code, providerId, retryable = false) {
|
|
7
|
+
super(messageForCredentialError(code, providerId));
|
|
8
|
+
this.name = "CredentialResolutionError";
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.providerId = providerId;
|
|
11
|
+
this.retryable = retryable;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Host-owned OAuth/ADC extension. It retains only a refreshable bearer in process memory,
|
|
16
|
+
* never exposes refresh-token material, and coalesces concurrent refreshes for one provider.
|
|
17
|
+
*/
|
|
18
|
+
export class OAuthCredentialResolver {
|
|
19
|
+
providerId;
|
|
20
|
+
refresh;
|
|
21
|
+
requiredScopes;
|
|
22
|
+
audience;
|
|
23
|
+
clock;
|
|
24
|
+
token;
|
|
25
|
+
refreshInFlight;
|
|
26
|
+
revoked = false;
|
|
27
|
+
constructor(options) {
|
|
28
|
+
this.providerId = options.providerId;
|
|
29
|
+
this.refresh = options.refresh;
|
|
30
|
+
this.requiredScopes = [...(options.requiredScopes ?? [])];
|
|
31
|
+
this.audience = options.audience;
|
|
32
|
+
this.clock = options.clock ?? Date.now;
|
|
33
|
+
}
|
|
34
|
+
/** An arrow field intentionally remains bound when passed as `credentialResolver`. */
|
|
35
|
+
resolve = async (request) => {
|
|
36
|
+
if (request.providerId !== this.providerId)
|
|
37
|
+
throw unavailable(request.providerId);
|
|
38
|
+
if (this.revoked)
|
|
39
|
+
throw new CredentialResolutionError("credential_revoked", this.providerId);
|
|
40
|
+
const token = this.usable(this.token) ? this.token : await this.refreshToken();
|
|
41
|
+
this.assertUsable(token);
|
|
42
|
+
if (this.revoked)
|
|
43
|
+
throw new CredentialResolutionError("credential_revoked", this.providerId);
|
|
44
|
+
return { type: "bearer", value: token.accessToken };
|
|
45
|
+
};
|
|
46
|
+
revoke() {
|
|
47
|
+
this.revoked = true;
|
|
48
|
+
this.token = undefined;
|
|
49
|
+
}
|
|
50
|
+
status() {
|
|
51
|
+
return {
|
|
52
|
+
providerId: this.providerId,
|
|
53
|
+
revoked: this.revoked,
|
|
54
|
+
hasUsableToken: !this.revoked && this.usable(this.token),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
usable(token) {
|
|
58
|
+
return token !== undefined && Number.isFinite(token.expiresAt) && token.expiresAt > this.clock();
|
|
59
|
+
}
|
|
60
|
+
async refreshToken() {
|
|
61
|
+
if (!this.refreshInFlight) {
|
|
62
|
+
this.refreshInFlight = Promise.resolve()
|
|
63
|
+
.then(() => this.refresh({
|
|
64
|
+
providerId: this.providerId,
|
|
65
|
+
...(this.audience === undefined ? {} : { audience: this.audience }),
|
|
66
|
+
requiredScopes: this.requiredScopes,
|
|
67
|
+
}))
|
|
68
|
+
.then(token => {
|
|
69
|
+
this.assertUsable(token);
|
|
70
|
+
if (this.revoked)
|
|
71
|
+
throw new CredentialResolutionError("credential_revoked", this.providerId);
|
|
72
|
+
this.token = token;
|
|
73
|
+
return token;
|
|
74
|
+
})
|
|
75
|
+
.catch(error => {
|
|
76
|
+
if (error instanceof CredentialResolutionError)
|
|
77
|
+
throw error;
|
|
78
|
+
throw new CredentialResolutionError("credential_refresh_failed", this.providerId, true);
|
|
79
|
+
})
|
|
80
|
+
.finally(() => { this.refreshInFlight = undefined; });
|
|
81
|
+
}
|
|
82
|
+
return this.refreshInFlight;
|
|
83
|
+
}
|
|
84
|
+
assertUsable(token) {
|
|
85
|
+
if (!token
|
|
86
|
+
|| typeof token.accessToken !== "string"
|
|
87
|
+
|| token.accessToken.trim() === ""
|
|
88
|
+
|| !Number.isFinite(token.expiresAt)
|
|
89
|
+
|| token.expiresAt <= this.clock()) {
|
|
90
|
+
throw new CredentialResolutionError("credential_invalid", this.providerId);
|
|
91
|
+
}
|
|
92
|
+
if (this.audience !== undefined && token.audience !== this.audience) {
|
|
93
|
+
throw new CredentialResolutionError("credential_oauth_audience_mismatch", this.providerId);
|
|
94
|
+
}
|
|
95
|
+
const tokenScopes = new Set(token.scopes ?? []);
|
|
96
|
+
if (this.requiredScopes.some(scope => !tokenScopes.has(scope))) {
|
|
97
|
+
throw new CredentialResolutionError("credential_oauth_scope_mismatch", this.providerId);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Safe for diagnostics and event metadata. It intentionally has no credential value. */
|
|
102
|
+
export function redactCredential(credential) {
|
|
103
|
+
return { type: credential.type };
|
|
104
|
+
}
|
|
105
|
+
export async function resolveCredential(request, options) {
|
|
106
|
+
const configured = configuredCredential(request.providerId, options);
|
|
107
|
+
if (configured)
|
|
108
|
+
return configured;
|
|
109
|
+
if (!options.credentialResolver)
|
|
110
|
+
throw unavailable(request.providerId);
|
|
111
|
+
let resolved;
|
|
112
|
+
try {
|
|
113
|
+
resolved = await options.credentialResolver(request);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
if (error instanceof CredentialResolutionError)
|
|
117
|
+
throw error;
|
|
118
|
+
throw new CredentialResolutionError("credential_resolver_failed", request.providerId);
|
|
119
|
+
}
|
|
120
|
+
return validateCredential(resolved, request.providerId);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The synchronous factory remains synchronous. A resolver which performs I/O must use
|
|
124
|
+
* `resolveProviderRuntimeAsync` / `createProviderAsync` instead of risking an implicit request.
|
|
125
|
+
*/
|
|
126
|
+
export function resolveCredentialSync(request, options) {
|
|
127
|
+
const configured = configuredCredential(request.providerId, options);
|
|
128
|
+
if (configured)
|
|
129
|
+
return configured;
|
|
130
|
+
if (!options.credentialResolver)
|
|
131
|
+
throw unavailable(request.providerId);
|
|
132
|
+
let resolved;
|
|
133
|
+
try {
|
|
134
|
+
resolved = options.credentialResolver(request);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (error instanceof CredentialResolutionError)
|
|
138
|
+
throw error;
|
|
139
|
+
throw new CredentialResolutionError("credential_resolver_failed", request.providerId);
|
|
140
|
+
}
|
|
141
|
+
if (isPromise(resolved)) {
|
|
142
|
+
throw new CredentialResolutionError("credential_resolver_failed", request.providerId);
|
|
143
|
+
}
|
|
144
|
+
return validateCredential(resolved, request.providerId);
|
|
145
|
+
}
|
|
146
|
+
function configuredCredential(providerId, options) {
|
|
147
|
+
const sources = [
|
|
148
|
+
options.apiKey === undefined ? undefined : { type: "api_key", value: options.apiKey },
|
|
149
|
+
options.bearerToken === undefined ? undefined : { type: "bearer", value: options.bearerToken },
|
|
150
|
+
].filter((value) => value !== undefined);
|
|
151
|
+
if (sources.length > 1)
|
|
152
|
+
throw new CredentialResolutionError("credential_invalid", providerId);
|
|
153
|
+
return sources.length === 1 ? validateCredential(sources[0], providerId) : undefined;
|
|
154
|
+
}
|
|
155
|
+
function validateCredential(credential, providerId) {
|
|
156
|
+
if (!credential)
|
|
157
|
+
throw unavailable(providerId);
|
|
158
|
+
if ((credential.type !== "api_key" && credential.type !== "bearer")
|
|
159
|
+
|| typeof credential.value !== "string"
|
|
160
|
+
|| credential.value.trim() === "") {
|
|
161
|
+
throw new CredentialResolutionError("credential_invalid", providerId);
|
|
162
|
+
}
|
|
163
|
+
return credential;
|
|
164
|
+
}
|
|
165
|
+
function unavailable(providerId) {
|
|
166
|
+
return new CredentialResolutionError("credential_unavailable", providerId);
|
|
167
|
+
}
|
|
168
|
+
function messageForCredentialError(code, providerId) {
|
|
169
|
+
switch (code) {
|
|
170
|
+
case "credential_unavailable":
|
|
171
|
+
return `Missing credential for provider ${providerId}`;
|
|
172
|
+
case "credential_invalid":
|
|
173
|
+
return `Invalid credential for provider ${providerId}`;
|
|
174
|
+
case "credential_refresh_failed":
|
|
175
|
+
return `Credential refresh failed for provider ${providerId}`;
|
|
176
|
+
case "credential_oauth_scope_mismatch":
|
|
177
|
+
return `Credential scope does not satisfy provider ${providerId}`;
|
|
178
|
+
case "credential_oauth_audience_mismatch":
|
|
179
|
+
return `Credential audience does not match provider ${providerId}`;
|
|
180
|
+
case "credential_revoked":
|
|
181
|
+
return `Credential was revoked for provider ${providerId}`;
|
|
182
|
+
case "credential_auth_mode_unsupported":
|
|
183
|
+
return `Credential authentication mode is unsupported for provider ${providerId}`;
|
|
184
|
+
case "credential_resolver_failed":
|
|
185
|
+
return `Credential resolution failed for provider ${providerId}`;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function isPromise(value) {
|
|
189
|
+
return Boolean(value) && typeof value.then === "function";
|
|
190
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
export type ProviderId = "anthropic" | "openai" | "minimax" | "deepseek" | "kimi" | "qwen" | "gemini" | "glm" | "baai" | "ollama";
|
|
2
|
+
export type EndpointProtocol = "anthropic-messages" | "openai-chat" | "openai-responses" | "openai-embeddings" | "dashscope-multimodal-embeddings" | "gemini" | "gemini-embeddings" | "self-hosted-embeddings" | "ollama-chat";
|
|
3
|
+
export interface EndpointProfile {
|
|
4
|
+
id: string;
|
|
5
|
+
providerId: ProviderId;
|
|
6
|
+
protocol: EndpointProtocol;
|
|
7
|
+
baseURL: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const endpointProfiles: {
|
|
10
|
+
readonly "anthropic.messages": {
|
|
11
|
+
readonly id: "anthropic.messages";
|
|
12
|
+
readonly providerId: "anthropic";
|
|
13
|
+
readonly protocol: "anthropic-messages";
|
|
14
|
+
readonly baseURL: "https://api.anthropic.com";
|
|
15
|
+
};
|
|
16
|
+
readonly "openai.chat": {
|
|
17
|
+
readonly id: "openai.chat";
|
|
18
|
+
readonly providerId: "openai";
|
|
19
|
+
readonly protocol: "openai-chat";
|
|
20
|
+
readonly baseURL: "https://api.openai.com/v1";
|
|
21
|
+
};
|
|
22
|
+
readonly "openai.responses": {
|
|
23
|
+
readonly id: "openai.responses";
|
|
24
|
+
readonly providerId: "openai";
|
|
25
|
+
readonly protocol: "openai-responses";
|
|
26
|
+
readonly baseURL: "https://api.openai.com/v1";
|
|
27
|
+
};
|
|
28
|
+
readonly "openai.embeddings": {
|
|
29
|
+
readonly id: "openai.embeddings";
|
|
30
|
+
readonly providerId: "openai";
|
|
31
|
+
readonly protocol: "openai-embeddings";
|
|
32
|
+
readonly baseURL: "https://api.openai.com/v1";
|
|
33
|
+
};
|
|
34
|
+
readonly "minimax.anthropic": {
|
|
35
|
+
readonly id: "minimax.anthropic";
|
|
36
|
+
readonly providerId: "minimax";
|
|
37
|
+
readonly protocol: "anthropic-messages";
|
|
38
|
+
readonly baseURL: "https://api.minimaxi.com/anthropic";
|
|
39
|
+
};
|
|
40
|
+
readonly "minimax.openai": {
|
|
41
|
+
readonly id: "minimax.openai";
|
|
42
|
+
readonly providerId: "minimax";
|
|
43
|
+
readonly protocol: "openai-chat";
|
|
44
|
+
readonly baseURL: "https://api.minimaxi.com/v1";
|
|
45
|
+
};
|
|
46
|
+
readonly "deepseek.anthropic": {
|
|
47
|
+
readonly id: "deepseek.anthropic";
|
|
48
|
+
readonly providerId: "deepseek";
|
|
49
|
+
readonly protocol: "anthropic-messages";
|
|
50
|
+
readonly baseURL: "https://api.deepseek.com/anthropic";
|
|
51
|
+
};
|
|
52
|
+
readonly "deepseek.openai": {
|
|
53
|
+
readonly id: "deepseek.openai";
|
|
54
|
+
readonly providerId: "deepseek";
|
|
55
|
+
readonly protocol: "openai-chat";
|
|
56
|
+
readonly baseURL: "https://api.deepseek.com";
|
|
57
|
+
};
|
|
58
|
+
readonly "kimi.anthropic": {
|
|
59
|
+
readonly id: "kimi.anthropic";
|
|
60
|
+
readonly providerId: "kimi";
|
|
61
|
+
readonly protocol: "anthropic-messages";
|
|
62
|
+
readonly baseURL: "https://api.moonshot.cn/anthropic";
|
|
63
|
+
};
|
|
64
|
+
readonly "kimi.openai": {
|
|
65
|
+
readonly id: "kimi.openai";
|
|
66
|
+
readonly providerId: "kimi";
|
|
67
|
+
readonly protocol: "openai-chat";
|
|
68
|
+
readonly baseURL: "https://api.moonshot.cn/v1";
|
|
69
|
+
};
|
|
70
|
+
readonly "qwen.anthropic": {
|
|
71
|
+
readonly id: "qwen.anthropic";
|
|
72
|
+
readonly providerId: "qwen";
|
|
73
|
+
readonly protocol: "anthropic-messages";
|
|
74
|
+
readonly baseURL: "https://dashscope-intl.aliyuncs.com/apps/anthropic";
|
|
75
|
+
};
|
|
76
|
+
readonly "qwen.dashscope": {
|
|
77
|
+
readonly id: "qwen.dashscope";
|
|
78
|
+
readonly providerId: "qwen";
|
|
79
|
+
readonly protocol: "openai-chat";
|
|
80
|
+
readonly baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1";
|
|
81
|
+
};
|
|
82
|
+
readonly "qwen.dashscope.embeddings": {
|
|
83
|
+
readonly id: "qwen.dashscope.embeddings";
|
|
84
|
+
readonly providerId: "qwen";
|
|
85
|
+
readonly protocol: "openai-embeddings";
|
|
86
|
+
readonly baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1";
|
|
87
|
+
};
|
|
88
|
+
readonly "qwen.dashscope.multimodal-embeddings": {
|
|
89
|
+
readonly id: "qwen.dashscope.multimodal-embeddings";
|
|
90
|
+
readonly providerId: "qwen";
|
|
91
|
+
readonly protocol: "dashscope-multimodal-embeddings";
|
|
92
|
+
readonly baseURL: "https://dashscope.aliyuncs.com/api/v1/services/embeddings/multimodal-embedding/multimodal-embedding";
|
|
93
|
+
};
|
|
94
|
+
readonly "gemini.google": {
|
|
95
|
+
readonly id: "gemini.google";
|
|
96
|
+
readonly providerId: "gemini";
|
|
97
|
+
readonly protocol: "gemini";
|
|
98
|
+
readonly baseURL: "https://generativelanguage.googleapis.com";
|
|
99
|
+
};
|
|
100
|
+
readonly "gemini.google.embeddings": {
|
|
101
|
+
readonly id: "gemini.google.embeddings";
|
|
102
|
+
readonly providerId: "gemini";
|
|
103
|
+
readonly protocol: "gemini-embeddings";
|
|
104
|
+
readonly baseURL: "https://generativelanguage.googleapis.com";
|
|
105
|
+
};
|
|
106
|
+
readonly "glm.anthropic": {
|
|
107
|
+
readonly id: "glm.anthropic";
|
|
108
|
+
readonly providerId: "glm";
|
|
109
|
+
readonly protocol: "anthropic-messages";
|
|
110
|
+
readonly baseURL: "https://open.bigmodel.cn/api/anthropic";
|
|
111
|
+
};
|
|
112
|
+
readonly "glm.openai": {
|
|
113
|
+
readonly id: "glm.openai";
|
|
114
|
+
readonly providerId: "glm";
|
|
115
|
+
readonly protocol: "openai-chat";
|
|
116
|
+
readonly baseURL: "https://open.bigmodel.cn/api/paas/v4";
|
|
117
|
+
};
|
|
118
|
+
readonly "glm.openai.embeddings": {
|
|
119
|
+
readonly id: "glm.openai.embeddings";
|
|
120
|
+
readonly providerId: "glm";
|
|
121
|
+
readonly protocol: "openai-embeddings";
|
|
122
|
+
readonly baseURL: "https://open.bigmodel.cn/api/paas/v4";
|
|
123
|
+
};
|
|
124
|
+
readonly "baai.self-hosted.embeddings": {
|
|
125
|
+
readonly id: "baai.self-hosted.embeddings";
|
|
126
|
+
readonly providerId: "baai";
|
|
127
|
+
readonly protocol: "self-hosted-embeddings";
|
|
128
|
+
readonly baseURL: "https://huggingface.co/BAAI";
|
|
129
|
+
};
|
|
130
|
+
readonly "ollama.local": {
|
|
131
|
+
readonly id: "ollama.local";
|
|
132
|
+
readonly providerId: "ollama";
|
|
133
|
+
readonly protocol: "ollama-chat";
|
|
134
|
+
readonly baseURL: "http://localhost:11434";
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
export type EndpointProfileId = keyof typeof endpointProfiles;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
export const endpointProfiles = {
|
|
2
|
+
"anthropic.messages": {
|
|
3
|
+
id: "anthropic.messages",
|
|
4
|
+
providerId: "anthropic",
|
|
5
|
+
protocol: "anthropic-messages",
|
|
6
|
+
baseURL: "https://api.anthropic.com",
|
|
7
|
+
},
|
|
8
|
+
"openai.chat": {
|
|
9
|
+
id: "openai.chat",
|
|
10
|
+
providerId: "openai",
|
|
11
|
+
protocol: "openai-chat",
|
|
12
|
+
baseURL: "https://api.openai.com/v1",
|
|
13
|
+
},
|
|
14
|
+
"openai.responses": {
|
|
15
|
+
id: "openai.responses",
|
|
16
|
+
providerId: "openai",
|
|
17
|
+
protocol: "openai-responses",
|
|
18
|
+
baseURL: "https://api.openai.com/v1",
|
|
19
|
+
},
|
|
20
|
+
"openai.embeddings": {
|
|
21
|
+
id: "openai.embeddings",
|
|
22
|
+
providerId: "openai",
|
|
23
|
+
protocol: "openai-embeddings",
|
|
24
|
+
baseURL: "https://api.openai.com/v1",
|
|
25
|
+
},
|
|
26
|
+
"minimax.anthropic": {
|
|
27
|
+
id: "minimax.anthropic",
|
|
28
|
+
providerId: "minimax",
|
|
29
|
+
protocol: "anthropic-messages",
|
|
30
|
+
baseURL: "https://api.minimaxi.com/anthropic",
|
|
31
|
+
},
|
|
32
|
+
"minimax.openai": {
|
|
33
|
+
id: "minimax.openai",
|
|
34
|
+
providerId: "minimax",
|
|
35
|
+
protocol: "openai-chat",
|
|
36
|
+
baseURL: "https://api.minimaxi.com/v1",
|
|
37
|
+
},
|
|
38
|
+
"deepseek.anthropic": {
|
|
39
|
+
id: "deepseek.anthropic",
|
|
40
|
+
providerId: "deepseek",
|
|
41
|
+
protocol: "anthropic-messages",
|
|
42
|
+
baseURL: "https://api.deepseek.com/anthropic",
|
|
43
|
+
},
|
|
44
|
+
"deepseek.openai": {
|
|
45
|
+
id: "deepseek.openai",
|
|
46
|
+
providerId: "deepseek",
|
|
47
|
+
protocol: "openai-chat",
|
|
48
|
+
baseURL: "https://api.deepseek.com",
|
|
49
|
+
},
|
|
50
|
+
"kimi.anthropic": {
|
|
51
|
+
id: "kimi.anthropic",
|
|
52
|
+
providerId: "kimi",
|
|
53
|
+
protocol: "anthropic-messages",
|
|
54
|
+
baseURL: "https://api.moonshot.cn/anthropic",
|
|
55
|
+
},
|
|
56
|
+
"kimi.openai": {
|
|
57
|
+
id: "kimi.openai",
|
|
58
|
+
providerId: "kimi",
|
|
59
|
+
protocol: "openai-chat",
|
|
60
|
+
baseURL: "https://api.moonshot.cn/v1",
|
|
61
|
+
},
|
|
62
|
+
"qwen.anthropic": {
|
|
63
|
+
id: "qwen.anthropic",
|
|
64
|
+
providerId: "qwen",
|
|
65
|
+
protocol: "anthropic-messages",
|
|
66
|
+
baseURL: "https://dashscope-intl.aliyuncs.com/apps/anthropic",
|
|
67
|
+
},
|
|
68
|
+
"qwen.dashscope": {
|
|
69
|
+
id: "qwen.dashscope",
|
|
70
|
+
providerId: "qwen",
|
|
71
|
+
protocol: "openai-chat",
|
|
72
|
+
baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
73
|
+
},
|
|
74
|
+
"qwen.dashscope.embeddings": {
|
|
75
|
+
id: "qwen.dashscope.embeddings",
|
|
76
|
+
providerId: "qwen",
|
|
77
|
+
protocol: "openai-embeddings",
|
|
78
|
+
baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
79
|
+
},
|
|
80
|
+
"qwen.dashscope.multimodal-embeddings": {
|
|
81
|
+
id: "qwen.dashscope.multimodal-embeddings",
|
|
82
|
+
providerId: "qwen",
|
|
83
|
+
protocol: "dashscope-multimodal-embeddings",
|
|
84
|
+
baseURL: "https://dashscope.aliyuncs.com/api/v1/services/embeddings/multimodal-embedding/multimodal-embedding",
|
|
85
|
+
},
|
|
86
|
+
"gemini.google": {
|
|
87
|
+
id: "gemini.google",
|
|
88
|
+
providerId: "gemini",
|
|
89
|
+
protocol: "gemini",
|
|
90
|
+
baseURL: "https://generativelanguage.googleapis.com",
|
|
91
|
+
},
|
|
92
|
+
"gemini.google.embeddings": {
|
|
93
|
+
id: "gemini.google.embeddings",
|
|
94
|
+
providerId: "gemini",
|
|
95
|
+
protocol: "gemini-embeddings",
|
|
96
|
+
baseURL: "https://generativelanguage.googleapis.com",
|
|
97
|
+
},
|
|
98
|
+
"glm.anthropic": {
|
|
99
|
+
id: "glm.anthropic",
|
|
100
|
+
providerId: "glm",
|
|
101
|
+
protocol: "anthropic-messages",
|
|
102
|
+
baseURL: "https://open.bigmodel.cn/api/anthropic",
|
|
103
|
+
},
|
|
104
|
+
"glm.openai": {
|
|
105
|
+
id: "glm.openai",
|
|
106
|
+
providerId: "glm",
|
|
107
|
+
protocol: "openai-chat",
|
|
108
|
+
baseURL: "https://open.bigmodel.cn/api/paas/v4",
|
|
109
|
+
},
|
|
110
|
+
"glm.openai.embeddings": {
|
|
111
|
+
id: "glm.openai.embeddings",
|
|
112
|
+
providerId: "glm",
|
|
113
|
+
protocol: "openai-embeddings",
|
|
114
|
+
baseURL: "https://open.bigmodel.cn/api/paas/v4",
|
|
115
|
+
},
|
|
116
|
+
"baai.self-hosted.embeddings": {
|
|
117
|
+
id: "baai.self-hosted.embeddings",
|
|
118
|
+
providerId: "baai",
|
|
119
|
+
protocol: "self-hosted-embeddings",
|
|
120
|
+
baseURL: "https://huggingface.co/BAAI",
|
|
121
|
+
},
|
|
122
|
+
"ollama.local": {
|
|
123
|
+
id: "ollama.local",
|
|
124
|
+
providerId: "ollama",
|
|
125
|
+
protocol: "ollama-chat",
|
|
126
|
+
baseURL: "http://localhost:11434",
|
|
127
|
+
},
|
|
128
|
+
};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { PROVIDER_REGISTRY } from "./registry.js";
|
|
2
2
|
import { OllamaProvider } from "./ollama.js";
|
|
3
|
+
import { defaultModelForProvider, getRuntimePolicy, isKnownProviderId } from "./model-registry.js";
|
|
3
4
|
function build(providerId, protocol, o) {
|
|
4
|
-
|
|
5
|
+
if (!isKnownProviderId(providerId))
|
|
6
|
+
throw new Error(`Unknown provider: ${providerId}`);
|
|
7
|
+
const model = o.model ?? defaultModelForProvider(providerId);
|
|
8
|
+
return PROVIDER_REGISTRY[`${providerId}:${protocol}`](o.apiKey, model, o.retry, o.baseURL, getRuntimePolicy(providerId, model));
|
|
5
9
|
}
|
|
6
10
|
/** DeepSeek. Defaults to the OpenAI-compatible wire (richer reasoning-replay handling). */
|
|
7
11
|
export function deepseek(o) {
|
|
@@ -25,9 +29,11 @@ export function minimax(o) {
|
|
|
25
29
|
}
|
|
26
30
|
/** Google Gemini (single wire). */
|
|
27
31
|
export function gemini(o) {
|
|
28
|
-
|
|
32
|
+
const model = o.model ?? defaultModelForProvider("gemini");
|
|
33
|
+
return PROVIDER_REGISTRY["gemini:gemini"](o.apiKey, model, o.retry, o.baseURL, getRuntimePolicy("gemini", model));
|
|
29
34
|
}
|
|
30
35
|
/** Local Ollama (single wire, no API key). */
|
|
31
36
|
export function ollama(o = {}) {
|
|
32
|
-
|
|
37
|
+
const model = o.model ?? defaultModelForProvider("ollama");
|
|
38
|
+
return new OllamaProvider(model, o.baseURL, getRuntimePolicy("ollama", model));
|
|
33
39
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Content, GenerateContentRequest, GenerateContentResponse, ModelParams, Tool } from "@google/generative-ai";
|
|
2
|
+
import type { Message, ProviderUsage } from "../types.js";
|
|
3
|
+
import type { CanonicalAdapterInput } from "./content-normalization.js";
|
|
4
|
+
import { type AdapterDecodeInput, type AdapterOutput, type AdapterStreamInput, type CanonicalStopReason, type ProtocolAdapter } from "./protocol-adapter.js";
|
|
5
|
+
export interface GeminiRequestPlan {
|
|
6
|
+
modelParams: ModelParams & Record<string, unknown>;
|
|
7
|
+
request: GenerateContentRequest;
|
|
8
|
+
}
|
|
9
|
+
export interface GeminiStreamState {
|
|
10
|
+
readonly input: CanonicalAdapterInput;
|
|
11
|
+
readonly toolCalls: Array<{
|
|
12
|
+
name: string;
|
|
13
|
+
args: Record<string, unknown>;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export declare function canonicalGeminiContents(context: CanonicalAdapterInput["context"]): Content[];
|
|
17
|
+
export declare function geminiVendorConfig(extensions: Readonly<Record<string, unknown>>): {
|
|
18
|
+
tools?: Tool[];
|
|
19
|
+
generationConfig?: Record<string, unknown>;
|
|
20
|
+
};
|
|
21
|
+
export declare class GeminiAdapter implements ProtocolAdapter<GeminiRequestPlan, GenerateContentResponse, GenerateContentResponse, GeminiStreamState, GenerateContentResponse> {
|
|
22
|
+
readonly protocol: "gemini";
|
|
23
|
+
readonly protocolCapabilities: import("./protocol-capabilities.js").ProtocolRuntimeCapabilities;
|
|
24
|
+
buildRequest(input: CanonicalAdapterInput): GeminiRequestPlan;
|
|
25
|
+
decodeComplete(raw: GenerateContentResponse, _input: AdapterDecodeInput): {
|
|
26
|
+
message: Message;
|
|
27
|
+
};
|
|
28
|
+
createStreamState(input: AdapterStreamInput): GeminiStreamState;
|
|
29
|
+
pushStreamChunk(chunk: GenerateContentResponse, state: GeminiStreamState): AdapterOutput;
|
|
30
|
+
finishStream(state: GeminiStreamState, final: GenerateContentResponse): AdapterOutput;
|
|
31
|
+
normalizeUsage(raw: unknown): ProviderUsage | undefined;
|
|
32
|
+
normalizeStopReason(raw: string | undefined): CanonicalStopReason | undefined;
|
|
33
|
+
}
|