dsh-opencode-go 0.1.24 → 0.2.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.en.md +59 -7
- package/README.md +164 -79
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/assets/icon.png +0 -0
- package/docs/advanced.en.md +15 -22
- package/docs/advanced.md +15 -22
- package/docs/assets/logo-dark.png +0 -0
- package/docs/assets/logo-light.png +0 -0
- package/docs/development.md +47 -119
- package/docs/independent-package.md +4 -2
- package/docs/usage-analytics.en.md +108 -0
- package/docs/usage-analytics.md +108 -0
- package/docs/verification.md +25 -928
- package/lib/client.js +3430 -2473
- package/lib/index.js +2650 -2440
- package/lib/types/accounts.d.ts +96 -31
- package/lib/types/adapter.d.ts +45 -48
- package/lib/types/analytics.d.ts +345 -0
- package/lib/types/catalog.d.ts +112 -6
- package/lib/types/client/AnalyticsDialog.d.ts +25 -0
- package/lib/types/client/Section.d.ts +51 -7
- package/lib/types/client/UsagePill.d.ts +6 -4
- package/lib/types/client/controller.d.ts +176 -0
- package/lib/types/client/index.d.ts +9 -12
- package/lib/types/client/{locales.d.ts → presentation.d.ts} +124 -0
- package/lib/types/config.d.ts +9 -14
- package/lib/types/contracts.d.ts +283 -0
- package/lib/types/conversion.d.ts +147 -0
- package/lib/types/index.d.ts +7 -39
- package/lib/types/sdk-types.d.ts +5 -54
- package/lib/types/transport.d.ts +63 -0
- package/lib/vendor-licenses.txt +36 -36
- package/package.json +76 -77
- package/docs/fork-review-2026-09-25.md +0 -191
- package/docs/native-call-comparison-v020-rc2.md +0 -116
- package/lib/types/account-manager.d.ts +0 -25
- package/lib/types/account-operations.d.ts +0 -31
- package/lib/types/account-policy.d.ts +0 -16
- package/lib/types/account-recovery.d.ts +0 -2
- package/lib/types/account-selection.d.ts +0 -30
- package/lib/types/account-service.d.ts +0 -12
- package/lib/types/accounts-contract.d.ts +0 -38
- package/lib/types/call-trace.d.ts +0 -54
- package/lib/types/catalog-manager.d.ts +0 -20
- package/lib/types/client/AccountsCard.d.ts +0 -19
- package/lib/types/client/ModelEditor.d.ts +0 -20
- package/lib/types/client/accounts-controller.d.ts +0 -71
- package/lib/types/client/hint-mark.d.ts +0 -17
- package/lib/types/client/host-compat.d.ts +0 -7
- package/lib/types/client/host-primitives.d.ts +0 -11
- package/lib/types/client/section-controller.d.ts +0 -202
- package/lib/types/client/settings.d.ts +0 -18
- package/lib/types/client/staged-form.d.ts +0 -201
- package/lib/types/client/usage.d.ts +0 -4
- package/lib/types/config-contract.d.ts +0 -70
- package/lib/types/conversion/config.d.ts +0 -4
- package/lib/types/conversion/context.d.ts +0 -56
- package/lib/types/conversion/image-offload.d.ts +0 -13
- package/lib/types/conversion/image-pool.d.ts +0 -24
- package/lib/types/conversion/index.d.ts +0 -5
- package/lib/types/conversion/replay.d.ts +0 -66
- package/lib/types/conversion/stream.d.ts +0 -44
- package/lib/types/gateway-diagnostics.d.ts +0 -23
- package/lib/types/gateway-error.d.ts +0 -2
- package/lib/types/gateway-url.d.ts +0 -6
- package/lib/types/google-fetch.d.ts +0 -6
- package/lib/types/host-settings.d.ts +0 -11
- package/lib/types/json-response.d.ts +0 -14
- package/lib/types/metadata-cache.d.ts +0 -12
- package/lib/types/model-metadata.d.ts +0 -21
- package/lib/types/models-contract.d.ts +0 -66
- package/lib/types/models.d.ts +0 -13
- package/lib/types/protocol-contract.d.ts +0 -5
- package/lib/types/protocol-policy.d.ts +0 -4
- package/lib/types/provider-identity.d.ts +0 -4
- package/lib/types/proxy-url.d.ts +0 -2
- package/lib/types/proxy.d.ts +0 -11
- package/lib/types/reasoning.d.ts +0 -40
- package/lib/types/remote-contract.d.ts +0 -3
- package/lib/types/remotes.d.ts +0 -3
- package/lib/types/request-budget.d.ts +0 -12
- package/lib/types/request-control.d.ts +0 -2
- package/lib/types/settings-bridge.d.ts +0 -22
- package/lib/types/usage-contract.d.ts +0 -35
- package/lib/types/usage-display.d.ts +0 -4
- package/lib/types/usage.d.ts +0 -27
- /package/lib/types/{google-generative-ai.d.ts → google.d.ts} +0 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/** Browser-safe configuration, account metadata and RPC wire contracts. */
|
|
2
|
+
import type { RemoteResult, TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol';
|
|
3
|
+
import type { AnalyticsFailureReason, AnalyticsQuery, AnalyticsReport } from './analytics.ts';
|
|
4
|
+
/** Public DSH route and the private SDK transport have separate identities. */
|
|
5
|
+
export declare const PROVIDER_ID = "dsh-opencode-go";
|
|
6
|
+
export declare const DISPLAY_NAME = "DSH OpenCode Go";
|
|
7
|
+
export declare const SDK_PROVIDER_ID = "opencode-go";
|
|
8
|
+
/** Public Go discovery/usage base; inference uses the documented protocol-specific siblings. */
|
|
9
|
+
export declare const DEFAULT_BASE_URL = "https://opencode.ai/inference/go/v1";
|
|
10
|
+
/**
|
|
11
|
+
* Migrate the legacy official address before any request is constructed.
|
|
12
|
+
*/
|
|
13
|
+
export declare function migrateGatewayBaseURL(baseURL: string): string;
|
|
14
|
+
/** Shared by Host validation and the browser form; never echo proxy credentials. */
|
|
15
|
+
export declare function assertProxyURL(raw: string | undefined): string;
|
|
16
|
+
/** Usage visibility shared by the Host schema and the browser settings. */
|
|
17
|
+
export declare const USAGE_DISPLAY_MODES: readonly ["auto", "always", "off"];
|
|
18
|
+
export type UsageDisplayMode = typeof USAGE_DISPLAY_MODES[number];
|
|
19
|
+
export declare const DEFAULT_USAGE_DISPLAY: UsageDisplayMode;
|
|
20
|
+
/** Client-safe account metadata. Secrets stay in the host credential service. */
|
|
21
|
+
export type GoAccount = {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
apiKeyEnv: string;
|
|
25
|
+
};
|
|
26
|
+
export declare const MAX_ACCOUNTS = 20;
|
|
27
|
+
export declare const ACCOUNT_REF_PREFIX = "DSH_OPENCODE_GO_ACCOUNT_";
|
|
28
|
+
export declare const DEFAULT_ACCOUNT_REF = "OPENCODE_API_KEY";
|
|
29
|
+
/** A credential reference is a bare environment variable name, never empty or decorated. */
|
|
30
|
+
export declare const ACCOUNT_REF_PATTERN: RegExp;
|
|
31
|
+
export interface AccountSettings {
|
|
32
|
+
apiKeyEnv?: string;
|
|
33
|
+
/** Omission/null preserves legacy credentials; an explicit empty list removes all accounts. */
|
|
34
|
+
accounts?: readonly GoAccount[] | null;
|
|
35
|
+
autoSwitch?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export declare function accountRefOf(settings: AccountSettings): string;
|
|
38
|
+
/** Promote one account while preserving every other account's relative order. */
|
|
39
|
+
export declare function moveAccountFirst(accounts: readonly GoAccount[], ref: string): readonly GoAccount[];
|
|
40
|
+
/** Read legacy selections as the first account until the host persists their order. */
|
|
41
|
+
export declare function accountsOf(settings: AccountSettings): readonly GoAccount[];
|
|
42
|
+
export declare function assertAccounts(accounts: readonly GoAccount[] | null | undefined, selectedRef?: string): void;
|
|
43
|
+
/** Safe UI notice for a successful request using a fallback account. */
|
|
44
|
+
export interface GoAccountSwitch {
|
|
45
|
+
fromRef: string;
|
|
46
|
+
toRef: string;
|
|
47
|
+
reason: 'quota' | 'credential';
|
|
48
|
+
at: number;
|
|
49
|
+
}
|
|
50
|
+
export declare const SETTINGS_NAMESPACE = "llm-opencode-go";
|
|
51
|
+
export declare const PROFILE_ENTRY_ID = "opencode-go";
|
|
52
|
+
/**
|
|
53
|
+
* One model's configured capacities. Every field is optional so a deployment
|
|
54
|
+
* can override only the value it needs. Null explicitly selects the catalog
|
|
55
|
+
* value even when a lower profile/settings layer supplies an override.
|
|
56
|
+
*/
|
|
57
|
+
export interface OpencodeGoModelLimit {
|
|
58
|
+
/** Context window in tokens, overriding what the catalog advertised. */
|
|
59
|
+
contextWindow?: number | null;
|
|
60
|
+
/** Output cap per request, overriding what the catalog advertised. */
|
|
61
|
+
maxTokens?: number | null;
|
|
62
|
+
/** Additional selectable thinking budgets, in tokens; null keeps the standard presets. */
|
|
63
|
+
thinkingBudgets?: number[] | null;
|
|
64
|
+
}
|
|
65
|
+
/** Per-model capacities; a null entry selects both original catalog values. */
|
|
66
|
+
export type OpencodeGoModelLimits = Record<string, OpencodeGoModelLimit | null>;
|
|
67
|
+
/** Runtime configuration for one plugin mount. */
|
|
68
|
+
export interface OpencodeGoConfig {
|
|
69
|
+
/**
|
|
70
|
+
* Whether this adapter serves its route at all. False withdraws the
|
|
71
|
+
* `dsh-opencode-go` route and its models from every picker without unloading the
|
|
72
|
+
* plugin, so the settings page that owns this switch stays reachable to turn
|
|
73
|
+
* it back on. Independent of the credential: a key present while this is
|
|
74
|
+
* false registers nothing.
|
|
75
|
+
*/
|
|
76
|
+
enabled: boolean;
|
|
77
|
+
/** Usage pill visibility; auto follows this plugin's selected provider. */
|
|
78
|
+
usageDisplay: UsageDisplayMode;
|
|
79
|
+
/** Per-model picker switches; absent entries default to enabled unless deprecated. */
|
|
80
|
+
modelVisibility?: Record<string, boolean>;
|
|
81
|
+
/** Experimental opt-in routing; omitted/null entries follow the catalog. */
|
|
82
|
+
protocolOverrides?: GoProtocolOverrides;
|
|
83
|
+
/** Legacy credential reference, kept in sync with the first/current account. */
|
|
84
|
+
apiKeyEnv: string;
|
|
85
|
+
/** The first account is current; subsequent accounts are tried in order. */
|
|
86
|
+
accounts?: GoAccount[] | null;
|
|
87
|
+
/** Try other saved accounts on quota/credential rejection before any content is emitted. */
|
|
88
|
+
autoSwitch?: boolean;
|
|
89
|
+
/** Discovery/usage base; the official Go gateway selects inference endpoints by protocol. */
|
|
90
|
+
baseURL: string;
|
|
91
|
+
/** Optional HTTP(S) or SOCKS5 proxy; blank uses the default network transport. */
|
|
92
|
+
proxyURL: string;
|
|
93
|
+
/** Request/picker cache lifetime in minutes; explicit discovery bypasses it. */
|
|
94
|
+
refreshMinutes: number;
|
|
95
|
+
/** Largest idle gap between stream events before the request fails. */
|
|
96
|
+
streamIdleTimeoutMs: number;
|
|
97
|
+
/** Bound discovery and each attempt's credential/image preparation. */
|
|
98
|
+
requestPreparationTimeoutMs?: number;
|
|
99
|
+
/** Whole dispatch deadline, including discovery and account fallback. */
|
|
100
|
+
requestTimeoutMs?: number;
|
|
101
|
+
/** Optional retained image occurrence cap per request; omission or null leaves the count unlimited. */
|
|
102
|
+
maxImages?: number | null;
|
|
103
|
+
/** Request-level bound on base64-encoded image payload, in bytes. */
|
|
104
|
+
maxRequestImageBytes: number;
|
|
105
|
+
/** Total-pixel budget for one request image. */
|
|
106
|
+
requestImagePixelBudget: number;
|
|
107
|
+
/** Raw encoded-byte target for one request image before base64 expansion. */
|
|
108
|
+
requestImageMaxBytes: number;
|
|
109
|
+
/** Per-model capacity overrides; an absent field inherits the catalog value. */
|
|
110
|
+
modelLimits: OpencodeGoModelLimits;
|
|
111
|
+
}
|
|
112
|
+
/** Settings snapshots may omit fields inherited from their base layer. */
|
|
113
|
+
export type OpencodeGoSettings = Partial<OpencodeGoConfig>;
|
|
114
|
+
/** The supported experimental override surface, shared with the settings UI. */
|
|
115
|
+
export declare const RESPONSES_OVERRIDE_MODEL = "deepseek-v4.1-flash";
|
|
116
|
+
export type GoProtocolOverrides = Partial<Record<typeof RESPONSES_OVERRIDE_MODEL, 'openai-responses' | null>>;
|
|
117
|
+
/** Null selects catalog routing even when a lower settings layer overrides it. */
|
|
118
|
+
export declare function assertProtocolOverrides(value: unknown): asserts value is GoProtocolOverrides | undefined;
|
|
119
|
+
export interface GoModel {
|
|
120
|
+
id: string;
|
|
121
|
+
name?: string;
|
|
122
|
+
contextWindow?: number;
|
|
123
|
+
maxTokens?: number;
|
|
124
|
+
/** Token budget controls available to this model, including their catalog bounds. */
|
|
125
|
+
reasoningBudget?: ThinkingBudgetRange;
|
|
126
|
+
deprecated?: boolean;
|
|
127
|
+
releaseDate?: string;
|
|
128
|
+
/** Input modalities models.dev declares, in {@link INPUT_MODALITIES} order. */
|
|
129
|
+
inputModalities?: readonly InputModality[];
|
|
130
|
+
/** Advertised by the gateway but lacking a usable protocol and capability configuration. */
|
|
131
|
+
configurationMissing?: boolean;
|
|
132
|
+
}
|
|
133
|
+
export interface ThinkingBudgetRange {
|
|
134
|
+
min: number;
|
|
135
|
+
max: number;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Input modalities this page can name. models.dev uses these same five tokens, so
|
|
139
|
+
* an unknown token is dropped rather than rendered as an untranslatable chip.
|
|
140
|
+
*/
|
|
141
|
+
export declare const INPUT_MODALITIES: readonly ["text", "image", "audio", "video", "pdf"];
|
|
142
|
+
export type InputModality = typeof INPUT_MODALITIES[number];
|
|
143
|
+
/**
|
|
144
|
+
* Normalize one `modalities.input` array into display order.
|
|
145
|
+
* @param value - the raw declaration read from models.dev or from a Host response.
|
|
146
|
+
* @returns the declared modalities in {@link INPUT_MODALITIES} order, or
|
|
147
|
+
* `undefined` when nothing recognizable was declared.
|
|
148
|
+
*/
|
|
149
|
+
export declare function normalizeInputModalities(value: unknown): readonly InputModality[] | undefined;
|
|
150
|
+
/** Last successful check of one catalog source, plus any current refresh failure. */
|
|
151
|
+
export interface GoCatalogSourceStatus {
|
|
152
|
+
readonly updatedAt?: number;
|
|
153
|
+
readonly error?: string;
|
|
154
|
+
readonly warning?: string;
|
|
155
|
+
}
|
|
156
|
+
/** A failed refresh retains the Host's usable data with an explicit diagnostic. */
|
|
157
|
+
export interface GoModelCatalog {
|
|
158
|
+
readonly models: readonly GoModel[];
|
|
159
|
+
readonly stale: boolean;
|
|
160
|
+
readonly error?: string;
|
|
161
|
+
/** Optional for clients reading an older Host response. Timestamps are Unix milliseconds. */
|
|
162
|
+
readonly sources?: {
|
|
163
|
+
readonly listing: GoCatalogSourceStatus;
|
|
164
|
+
readonly metadata: GoCatalogSourceStatus;
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/** Missing configuration cannot be enabled; configured models follow explicit switches or lifecycle defaults. */
|
|
168
|
+
export declare function isModelEnabled(model: Pick<GoModel, 'id' | 'deprecated' | 'configurationMissing'>, modelVisibility?: Readonly<Record<string, boolean>>): boolean;
|
|
169
|
+
export declare function validReleaseDate(value: unknown): value is string;
|
|
170
|
+
/** Calendar dates are supplied without a timezone; compare UTC dates consistently. */
|
|
171
|
+
export declare function isNewModel(model: GoModel, now?: number): boolean;
|
|
172
|
+
export declare function sortModels(models: readonly GoModel[], now?: number): GoModel[];
|
|
173
|
+
export declare function parseGoModels(value: unknown): GoModel[];
|
|
174
|
+
export declare function parseGoModelCatalog(value: unknown): GoModelCatalog;
|
|
175
|
+
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
176
|
+
interface TypertRemoteNamespaceMap {
|
|
177
|
+
opencodeGoModels: {
|
|
178
|
+
read(): Promise<RemoteResult<GoModelCatalog>>;
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
export declare const modelsRemote: TypertRemoteContribution;
|
|
183
|
+
export interface UsageWindow {
|
|
184
|
+
status: 'ok' | 'rate-limited';
|
|
185
|
+
percent: number;
|
|
186
|
+
resetsAt: string;
|
|
187
|
+
}
|
|
188
|
+
export interface GoUsage {
|
|
189
|
+
/** Opaque Host identity for this endpoint/account; never a credential or its hash. */
|
|
190
|
+
source?: string;
|
|
191
|
+
lastSwitch?: GoAccountSwitch;
|
|
192
|
+
rolling: UsageWindow;
|
|
193
|
+
weekly: UsageWindow;
|
|
194
|
+
monthly: UsageWindow;
|
|
195
|
+
}
|
|
196
|
+
export declare function parseAccountSwitch(value: unknown): GoAccountSwitch;
|
|
197
|
+
/** Reject missing statistics rather than turning unavailable data into zero. */
|
|
198
|
+
export declare function parseGoUsage(value: unknown): GoUsage;
|
|
199
|
+
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
200
|
+
interface RemoteErrorDetailsMap {
|
|
201
|
+
'opencode-go/usage-unavailable': {
|
|
202
|
+
readonly retryable: boolean;
|
|
203
|
+
readonly retainPrevious: boolean;
|
|
204
|
+
readonly source?: string;
|
|
205
|
+
readonly lastSwitch?: GoAccountSwitch;
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
interface TypertRemoteNamespaceMap {
|
|
209
|
+
opencodeGoUsage: {
|
|
210
|
+
read(): Promise<RemoteResult<GoUsage>>;
|
|
211
|
+
readAccount(ref: string): Promise<RemoteResult<GoUsage>>;
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
export declare const usageRemote: TypertRemoteContribution;
|
|
216
|
+
export type AccountCommand = {
|
|
217
|
+
kind: 'add';
|
|
218
|
+
id: string;
|
|
219
|
+
name: string;
|
|
220
|
+
key: string;
|
|
221
|
+
} | {
|
|
222
|
+
kind: 'remove';
|
|
223
|
+
ref: string;
|
|
224
|
+
} | {
|
|
225
|
+
kind: 'select';
|
|
226
|
+
ref: string;
|
|
227
|
+
} | {
|
|
228
|
+
kind: 'rename';
|
|
229
|
+
ref: string;
|
|
230
|
+
name: string;
|
|
231
|
+
} | {
|
|
232
|
+
kind: 'replace-key';
|
|
233
|
+
ref: string;
|
|
234
|
+
key: string;
|
|
235
|
+
} | {
|
|
236
|
+
kind: 'move';
|
|
237
|
+
ref: string;
|
|
238
|
+
toIndex: number;
|
|
239
|
+
} | {
|
|
240
|
+
kind: 'auto-switch';
|
|
241
|
+
value: boolean;
|
|
242
|
+
};
|
|
243
|
+
export declare function parseAccountCommand(value: unknown): AccountCommand;
|
|
244
|
+
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
245
|
+
interface TypertRemoteNamespaceMap {
|
|
246
|
+
opencodeGoAccounts: {
|
|
247
|
+
execute(command: AccountCommand): Promise<RemoteResult<SettingsWriteResult>>;
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
export declare const accountsRemote: TypertRemoteContribution;
|
|
252
|
+
export type SettingsWriteResult = 'applied' | 'rejected' | 'unknown';
|
|
253
|
+
export type { AnalyticsFailureReason, AnalyticsQuery, AnalyticsTotals, AnalyticsModelRow, AnalyticsDayRow, AnalyticsCoverage, AnalyticsPricing, AnalyticsReport } from './analytics.ts';
|
|
254
|
+
/**
|
|
255
|
+
* Validate one query. Unknown fields are ignored so a newer client can add
|
|
256
|
+
* optional knobs without breaking an older Host.
|
|
257
|
+
* @param value - raw RPC argument.
|
|
258
|
+
* @returns the validated query.
|
|
259
|
+
*/
|
|
260
|
+
export declare function parseAnalyticsQuery(value: unknown): AnalyticsQuery;
|
|
261
|
+
/** Check the response envelope; the host constructs typed aggregate rows. */
|
|
262
|
+
export declare function parseAnalyticsReport(value: unknown): AnalyticsReport;
|
|
263
|
+
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
264
|
+
interface RemoteErrorDetailsMap {
|
|
265
|
+
'opencode-go/analytics-unavailable': {
|
|
266
|
+
readonly reason: AnalyticsFailureReason;
|
|
267
|
+
readonly retryable: boolean;
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
interface TypertRemoteNamespaceMap {
|
|
271
|
+
opencodeGoAnalytics: {
|
|
272
|
+
read(query: AnalyticsQuery, signal?: AbortSignal): Promise<RemoteResult<AnalyticsReport>>;
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/** The dashboard endpoint, mounted with the other plugin remotes. */
|
|
277
|
+
export declare const analyticsRemote: TypertRemoteContribution;
|
|
278
|
+
/** A registry owns one contribution per package; mount all plugin endpoints together. */
|
|
279
|
+
export declare const goRemote: TypertRemoteContribution;
|
|
280
|
+
/** Default image budgets, overridable through the adapter configuration. */
|
|
281
|
+
export declare const DEFAULT_MAX_REQUEST_IMAGE_BYTES: number;
|
|
282
|
+
export declare const DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET: number;
|
|
283
|
+
export declare const DEFAULT_REQUEST_IMAGE_MAX_BYTES: number;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/** Request history, durable images, provider replay and stream conversion. */
|
|
2
|
+
import { type Message as HistoryMessage, type ReplayEnvelope, type RequestMessage as Message, type GenerateOptions, type ImageAttachmentAccessResolver, type FinishReason, type StreamChunk, type TokenUsage } from '@deepseek-ai/dsh-llm';
|
|
3
|
+
import type { Api, AssistantMessage, Usage as PiUsage, Context as PiContext, AssistantMessageEvent } from './sdk-types.ts';
|
|
4
|
+
import { type ImageAttachmentRef, type AttachmentStore } from '@deepseek-ai/dsh-attachment';
|
|
5
|
+
/** Per-block half of the pi-ai replay envelope, one entry per content block. */
|
|
6
|
+
export type PiAiReplayBlock = {
|
|
7
|
+
type: 'text';
|
|
8
|
+
textSignature?: string;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'reasoning';
|
|
11
|
+
thinkingSignature?: string;
|
|
12
|
+
redacted?: boolean;
|
|
13
|
+
} | {
|
|
14
|
+
type: 'tool-call';
|
|
15
|
+
thoughtSignature?: string;
|
|
16
|
+
};
|
|
17
|
+
/** Versioned response-level half of the pi-ai replay envelope. */
|
|
18
|
+
export interface PiAiReplayResponse {
|
|
19
|
+
kind: 'pi-ai';
|
|
20
|
+
version: 2;
|
|
21
|
+
api: Api;
|
|
22
|
+
/** Requested DSH provider identity, matching the durable assistant source. */
|
|
23
|
+
provider: string;
|
|
24
|
+
/** Native SDK provider when it differs from the DSH route. */
|
|
25
|
+
sdkProvider?: string;
|
|
26
|
+
/** Requested model identity, matching the durable assistant source. */
|
|
27
|
+
model: string;
|
|
28
|
+
/** Provider-reported model; informational only, so requested identity still matches replay signatures. */
|
|
29
|
+
responseModel?: string;
|
|
30
|
+
responseId?: string;
|
|
31
|
+
/** Provider-native effort for historical replay; absence is preserved. */
|
|
32
|
+
providerThinkingLevel?: string;
|
|
33
|
+
stopReason: AssistantMessage['stopReason'];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Project a successful pi-ai response into the minimal durable replay state.
|
|
37
|
+
* The per-block half is index-aligned with the streamed blocks (pi-ai content
|
|
38
|
+
* order), so `BlockAssembler` prunes an entry with its block whenever assembly
|
|
39
|
+
* removes one.
|
|
40
|
+
* @param message - completed native pi-ai assistant response.
|
|
41
|
+
* @param requestedModel - request identity stored in the assistant source; defaults to the native model.
|
|
42
|
+
* @param requestedProvider - DSH route stored in the assistant source; defaults to the native provider.
|
|
43
|
+
* @returns the versioned lossless-JSON replay projection.
|
|
44
|
+
*/
|
|
45
|
+
export declare function toPiReplayState(message: AssistantMessage, requestedModel?: string, requestedProvider?: string): ReplayEnvelope;
|
|
46
|
+
/**
|
|
47
|
+
* Convert one durable Harness assistant message into pi-ai history.
|
|
48
|
+
*
|
|
49
|
+
* Durable content is the authoritative record; replay metadata only restores
|
|
50
|
+
* native fidelity (ids, signatures). A replay state this build cannot use —
|
|
51
|
+
* another adapter's kind, another version, a malformed value, or metadata that
|
|
52
|
+
* no longer matches the content — therefore degrades the one message to
|
|
53
|
+
* provider-neutral history instead of failing the request.
|
|
54
|
+
* @param message - assistant content with required source and optional adapter-owned replay metadata.
|
|
55
|
+
* @param onDegrade - called with the diagnostic reason when an unusable replay
|
|
56
|
+
* state falls back to provider-neutral conversion.
|
|
57
|
+
* @returns a native pi-ai assistant message reconstructed from durable content.
|
|
58
|
+
*/
|
|
59
|
+
export declare function toPiAssistant(message: HistoryMessage, onDegrade?: (reason: string) => void): AssistantMessage;
|
|
60
|
+
interface ImageProjectionPolicy {
|
|
61
|
+
maxImages?: number;
|
|
62
|
+
maxBytes?: number;
|
|
63
|
+
byteLength: (ref: ImageAttachmentRef) => number;
|
|
64
|
+
placeholder: (ref: ImageAttachmentRef) => string;
|
|
65
|
+
exact: boolean;
|
|
66
|
+
}
|
|
67
|
+
export declare function projectRequestImages(messages: readonly Message[], policy: ImageProjectionPolicy): readonly Message[];
|
|
68
|
+
/** Inputs that bind deterministic request images to one current tool execution world. */
|
|
69
|
+
export interface PiImageRequestContext {
|
|
70
|
+
/** Durable provider that resolves request-image bytes and provider-owned host objects. */
|
|
71
|
+
attachments: AttachmentStore;
|
|
72
|
+
/** Resolve current tool access separately from deterministic request-image versions. */
|
|
73
|
+
resolveImageAccess: ImageAttachmentAccessResolver;
|
|
74
|
+
/** Maximum retained image occurrences across request history; omission leaves the count unlimited. */
|
|
75
|
+
maxImages?: number;
|
|
76
|
+
/** Request-level bound on the base64-encoded payload of retained images; omission leaves the bound unchecked. */
|
|
77
|
+
maxRequestImageBytes?: number;
|
|
78
|
+
/** Route pixel and raw encoded-byte budgets. */
|
|
79
|
+
requestImagePolicy?: PiImageRequestBudget;
|
|
80
|
+
}
|
|
81
|
+
/** Per-route budgets from which each request image's target is derived. */
|
|
82
|
+
export interface PiImageRequestBudget {
|
|
83
|
+
/** Total-pixel budget; larger sources are downscaled proportionally. */
|
|
84
|
+
maxPixels: number;
|
|
85
|
+
/** Encoded-byte target for one request image. */
|
|
86
|
+
maxBytes: number;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Convert text-only harness history to a synchronous pi-ai Context. Tool
|
|
90
|
+
* result names are recovered from preceding assistant tool calls.
|
|
91
|
+
* @param options - the harness request; `options.system`, else a leading `system` message, maps to pi-ai's single `systemPrompt` slot.
|
|
92
|
+
* @param images - absent; selects the synchronous conversion.
|
|
93
|
+
* @param onReplayDegrade - forwarded to {@link toPiAssistant} for each assistant message.
|
|
94
|
+
* @returns the pi-ai context; `tools` is omitted when the request declares none.
|
|
95
|
+
* @throws {LlmError} `UNSUPPORTED_CONTENT` for a `developer` history message, a tool-change block, a deferred tool, or an image in any history role, including a leading system message.
|
|
96
|
+
*/
|
|
97
|
+
export declare function toPiContext(options: GenerateOptions, images?: undefined, onReplayDegrade?: (reason: string) => void): PiContext;
|
|
98
|
+
/**
|
|
99
|
+
* Convert harness history to a pi-ai Context while resolving durable images.
|
|
100
|
+
* Tool result names are recovered from preceding assistant tool calls.
|
|
101
|
+
* Occurrences the surface marks offloaded become placeholders; when the
|
|
102
|
+
* retained occurrences exceed `maxImages` or their exact base64 payload exceeds
|
|
103
|
+
* `maxRequestImageBytes`, the call fails with `IMAGE_OFFLOAD_REQUIRED` naming
|
|
104
|
+
* how many more oldest occurrences must be offloaded.
|
|
105
|
+
* @param options - the harness request; `options.system`, else a leading `system` message, maps to pi-ai's single `systemPrompt` slot.
|
|
106
|
+
* @param images - attachment provider, current path resolver, and request limits.
|
|
107
|
+
* @param onReplayDegrade - forwarded to {@link toPiAssistant} for each assistant message.
|
|
108
|
+
* @returns the asynchronously resolved pi-ai context.
|
|
109
|
+
*/
|
|
110
|
+
export declare function toPiContext(options: GenerateOptions, images: PiImageRequestContext, onReplayDegrade?: (reason: string) => void): Promise<PiContext>;
|
|
111
|
+
/**
|
|
112
|
+
* Map pi-ai usage (reasoning folded into output by pi-ai).
|
|
113
|
+
* @param usage - cumulative usage from the terminal pi-ai event.
|
|
114
|
+
* @returns harness counts with pi-ai's exact total; cache fields appear only
|
|
115
|
+
* when non-zero (pi-ai reports zeros, not absence).
|
|
116
|
+
*/
|
|
117
|
+
export declare function mapUsage(usage: PiUsage): TokenUsage;
|
|
118
|
+
/**
|
|
119
|
+
* Map a terminal pi-ai event to the harness finish reason.
|
|
120
|
+
* @param message - the assistant message carried by the `done` or `error` event.
|
|
121
|
+
* @param contextWindow - resolved catalog capacity for usage-based overflow detection.
|
|
122
|
+
* @param reservedMaxTokens - requested output allowance before SDK context clamping.
|
|
123
|
+
* @returns the mapped harness reason. Recognized error text, `stop` usage above
|
|
124
|
+
* `contextWindow`, and zero-output `length` usage that fills the window map
|
|
125
|
+
* to `CONTEXT_WINDOW_EXCEEDED`; a `stop` with no content blocks maps to an
|
|
126
|
+
* `EMPTY_RESPONSE` error. Other empty `length` responses map to `INVALID_REQUEST`
|
|
127
|
+
* with output-limit or compaction guidance. Terminal `pending` and `deferred`
|
|
128
|
+
* states map to non-retryable `PI_AI_ERROR` failures.
|
|
129
|
+
*/
|
|
130
|
+
export declare function mapStopReason(message: AssistantMessage, contextWindow?: number, reservedMaxTokens?: number): FinishReason;
|
|
131
|
+
/**
|
|
132
|
+
* Translate the pi-ai event stream into StreamChunks. pi-ai never throws
|
|
133
|
+
* mid-stream — failures arrive as `error` events, which become error/aborted
|
|
134
|
+
* `finish` chunks (the harness protocol's other error-delivery style).
|
|
135
|
+
* @param events - one assistant turn's pi-ai event stream.
|
|
136
|
+
* @param contextWindow - resolved catalog capacity for usage-based overflow detection.
|
|
137
|
+
* @param callerSignal - caller cancellation state; an aborted caller makes any
|
|
138
|
+
* in-band terminal error an aborted finish.
|
|
139
|
+
* @param requestedModel - request model identity recorded for durable replay.
|
|
140
|
+
* @param requestedProvider - DSH provider identity recorded for durable replay.
|
|
141
|
+
* @param reservedMaxTokens - requested output allowance before SDK context clamping.
|
|
142
|
+
* @returns the harness chunks, ending with measured `usage` then `finish`;
|
|
143
|
+
* failures with no measured tokens omit usage to preserve context pressure. Throws
|
|
144
|
+
* `LlmError` (`STREAM_CLOSED`) if the source ends without a terminal event.
|
|
145
|
+
*/
|
|
146
|
+
export declare function toStreamChunks(events: AsyncIterable<AssistantMessageEvent>, contextWindow?: number, callerSignal?: AbortSignal, requestedModel?: string, requestedProvider?: string, reservedMaxTokens?: number): AsyncGenerator<StreamChunk>;
|
|
147
|
+
export { DEFAULT_MAX_REQUEST_IMAGE_BYTES, DEFAULT_REQUEST_IMAGE_MAX_BYTES, DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET, } from './contracts.ts';
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,56 +1,24 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dedicated OpenCode Go adapter plugin. Registers one `dsh-opencode-go` route
|
|
3
|
-
* whose catalog follows the gateway's live model listing and models.dev
|
|
4
|
-
* metadata, and installs the `llm-opencode-go` settings section: the Web UI
|
|
5
|
-
* renders it as its own settings page where the API key and every knob are
|
|
6
|
-
* edited, and a change reaches the next request without a restart. The plugin
|
|
7
|
-
* exists because the gateway has wire requirements a generic pi-ai route
|
|
8
|
-
* cannot express: a mandatory per-conversation `x-opencode-session` routing
|
|
9
|
-
* header and a model list that rotates faster than any shipped catalog.
|
|
10
|
-
*
|
|
11
|
-
* DSH 0.1.5/0.1.6 layer the settings document over the composition entry;
|
|
12
|
-
* 0.1.7 edits live configuration fields on the profile entry directly.
|
|
13
|
-
*
|
|
14
|
-
* ```yaml
|
|
15
|
-
* - id: llm-opencode-go
|
|
16
|
-
* name: 'dsh-opencode-go'
|
|
17
|
-
* config:
|
|
18
|
-
* enabled: true # false withdraws the route; the plugin stays mounted
|
|
19
|
-
* apiKeyEnv: OPENCODE_API_KEY # default
|
|
20
|
-
* baseURL: https://opencode.ai/inference/go/v1 # default
|
|
21
|
-
* refreshMinutes: 60 # live catalog re-resolution interval
|
|
22
|
-
* ```
|
|
23
|
-
*
|
|
24
|
-
* The credential resolves per request through the credentials seam, falling
|
|
25
|
-
* back to the process environment — the same reference semantics the generic
|
|
26
|
-
* pi-ai adapter uses. The route registers atomically: if another adapter
|
|
27
|
-
* mount already owns `dsh-opencode-go`,
|
|
28
|
-
* the refusal is logged with the reason and everything else this plugin does
|
|
29
|
-
* still works.
|
|
30
|
-
*
|
|
31
|
-
* @module dsh-opencode-go
|
|
32
|
-
*/
|
|
33
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
34
|
-
import type
|
|
2
|
+
import { type LiveConfig, type OpencodeGoConfig } from './config.ts';
|
|
35
3
|
declare module '@deepseek-ai/cordis' {
|
|
36
4
|
interface Events {
|
|
37
5
|
'loader/volatile-update'(paths: readonly (readonly string[])[]): void;
|
|
38
6
|
}
|
|
39
7
|
}
|
|
40
8
|
export { OpencodeGoAdapter } from './adapter.ts';
|
|
41
|
-
export type { OpencodeGoAdapterOptions, OpencodeGoImageAccess, GoAccountSettlement
|
|
9
|
+
export type { OpencodeGoAdapterOptions, OpencodeGoImageAccess, GoAccountSettlement } from './adapter.ts';
|
|
42
10
|
export { DEFAULT_BASE_URL, DISPLAY_NAME, PROVIDER_ID, OpencodeGoCatalog, discoverCatalogModels, readLiveModelIds, } from './catalog.ts';
|
|
43
11
|
export { Config, PlainConfig, assertBaseURL } from './config.ts';
|
|
44
|
-
export { assertProxyURL } from './
|
|
12
|
+
export { assertProxyURL } from './contracts.ts';
|
|
45
13
|
export type { OpencodeGoConfig } from './config.ts';
|
|
46
14
|
export declare const name = "llm-opencode-go";
|
|
47
15
|
export declare const inject: string[];
|
|
48
16
|
/** Settings namespace this plugin installs and the Web page edits. */
|
|
49
17
|
export declare const NS = "llm-opencode-go";
|
|
50
18
|
/**
|
|
51
|
-
* Register the route,
|
|
52
|
-
*
|
|
53
|
-
* replaced by the settings section's resolved value once the settings
|
|
54
|
-
* provider attaches; the adapter re-reads it at every operation.
|
|
19
|
+
* Register the route, model discovery and settings presentation for one mount.
|
|
20
|
+
* The adapter re-reads live profile fields at every operation.
|
|
55
21
|
*/
|
|
56
22
|
export declare function apply(ctx: Context, raw?: OpencodeGoConfig | LiveConfig): void;
|
|
23
|
+
/** Register once per plugin mount, after either registry activation order. */
|
|
24
|
+
export declare function registerGoRemotes(ctx: Context): void;
|
package/lib/types/sdk-types.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Anthropic from '@anthropic-ai/sdk';
|
|
2
2
|
import { ResponseCreateParamsStreaming } from 'openai/resources/responses/responses.js';
|
|
3
3
|
import OpenAI from 'openai';
|
|
4
|
-
import { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
|
|
5
4
|
|
|
6
5
|
interface TSchema {
|
|
7
6
|
}
|
|
@@ -3093,63 +3092,15 @@ interface Provider<TApi extends Api = Api> {
|
|
|
3093
3092
|
classify?(model: ClassifierModel<ClassifierApi>, context: ClassifierContext, options?: ClassifierOptions): Promise<ClassifierResult>;
|
|
3094
3093
|
}
|
|
3095
3094
|
|
|
3096
|
-
/**
|
|
3097
|
-
|
|
3098
|
-
interface GoModel {
|
|
3099
|
-
id: string;
|
|
3100
|
-
name?: string;
|
|
3101
|
-
contextWindow?: number;
|
|
3102
|
-
maxTokens?: number;
|
|
3103
|
-
/** Token budget controls available to this model, including their catalog bounds. */
|
|
3104
|
-
reasoningBudget?: ThinkingBudgetRange;
|
|
3105
|
-
deprecated?: boolean;
|
|
3106
|
-
releaseDate?: string;
|
|
3107
|
-
/** Input modalities models.dev declares, in {@link INPUT_MODALITIES} order. */
|
|
3108
|
-
inputModalities?: readonly InputModality[];
|
|
3109
|
-
/** Advertised by the gateway but lacking a usable protocol and capability configuration. */
|
|
3110
|
-
configurationMissing?: boolean;
|
|
3111
|
-
}
|
|
3112
|
-
interface ThinkingBudgetRange {
|
|
3113
|
-
min: number;
|
|
3114
|
-
max: number;
|
|
3115
|
-
}
|
|
3116
|
-
/**
|
|
3117
|
-
* Input modalities this page can name. models.dev uses these same five tokens, so
|
|
3118
|
-
* an unknown token is dropped rather than rendered as an untranslatable chip.
|
|
3119
|
-
*/
|
|
3120
|
-
declare const INPUT_MODALITIES: readonly ["text", "image", "audio", "video", "pdf"];
|
|
3121
|
-
type InputModality = typeof INPUT_MODALITIES[number];
|
|
3122
|
-
/** Last successful check of one catalog source, plus any current refresh failure. */
|
|
3123
|
-
interface GoCatalogSourceStatus {
|
|
3124
|
-
readonly updatedAt?: number;
|
|
3125
|
-
readonly error?: string;
|
|
3126
|
-
readonly warning?: string;
|
|
3127
|
-
}
|
|
3128
|
-
/** A failed refresh retains the Host's usable data with an explicit diagnostic. */
|
|
3129
|
-
interface GoModelCatalog {
|
|
3130
|
-
readonly models: readonly GoModel[];
|
|
3131
|
-
readonly stale: boolean;
|
|
3132
|
-
readonly error?: string;
|
|
3133
|
-
/** Optional for clients reading an older Host response. Timestamps are Unix milliseconds. */
|
|
3134
|
-
readonly sources?: {
|
|
3135
|
-
readonly listing: GoCatalogSourceStatus;
|
|
3136
|
-
readonly metadata: GoCatalogSourceStatus;
|
|
3137
|
-
};
|
|
3138
|
-
}
|
|
3139
|
-
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
3140
|
-
interface TypertRemoteNamespaceMap {
|
|
3141
|
-
opencodeGoModels: {
|
|
3142
|
-
read(): Promise<RemoteResult<GoModelCatalog>>;
|
|
3143
|
-
};
|
|
3144
|
-
}
|
|
3145
|
-
}
|
|
3146
|
-
|
|
3147
|
-
/** Public SDK types are bundled at build time, alongside the private implementation. */
|
|
3095
|
+
/** Public SDK types bundled independently of the private runtime implementation. */
|
|
3148
3096
|
|
|
3149
3097
|
/** User controls are independent of the SDK's internal level used to enable a switch. */
|
|
3150
3098
|
type Model<TApi extends Api> = Model$1<TApi> & {
|
|
3151
3099
|
reasoningControl?: 'toggle' | 'effort' | 'budget';
|
|
3152
|
-
reasoningBudget?:
|
|
3100
|
+
reasoningBudget?: {
|
|
3101
|
+
min: number;
|
|
3102
|
+
max: number;
|
|
3103
|
+
};
|
|
3153
3104
|
reasoningBudgetPresets?: readonly number[];
|
|
3154
3105
|
};
|
|
3155
3106
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Cancel a wait even when an external service does not observe its signal. */
|
|
2
|
+
export declare function waitWithSignal<T>(work: () => PromiseLike<T>, signal?: AbortSignal): Promise<T>;
|
|
3
|
+
/** Per-mount transport. Fetch closures retain their address across settings changes. */
|
|
4
|
+
export declare class ProxyTransport {
|
|
5
|
+
private current;
|
|
6
|
+
private readonly retired;
|
|
7
|
+
private disposed;
|
|
8
|
+
forProxy(raw?: string): typeof globalThis.fetch | undefined;
|
|
9
|
+
/** Close replaced pools after their in-flight response bodies have finished. */
|
|
10
|
+
private retire;
|
|
11
|
+
/** Unloading the mount cancels remaining requests and releases every pool. */
|
|
12
|
+
dispose(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/** Describe transport failures without echoing credentials or upstream response text. */
|
|
15
|
+
export declare function transportFailure(error: unknown): string;
|
|
16
|
+
/** Keep the endpoint useful in diagnostics without user information or query secrets. */
|
|
17
|
+
export declare function diagnosticURL(raw: string): string;
|
|
18
|
+
/** The caller's signal covers both attempts, the retry delay, and all response reads. */
|
|
19
|
+
export declare function fetchJsonResponse(url: string, init: RequestInit, maxBytes: number, encoding?: 'identity' | 'gzip', fetcher?: typeof globalThis.fetch, readError?: (response: Response) => Promise<unknown>): Promise<{
|
|
20
|
+
response: Response;
|
|
21
|
+
body: unknown;
|
|
22
|
+
}>;
|
|
23
|
+
/** Fetch normally decodes HTTP; only negotiated gzip may recover a raw gzip body (#7). */
|
|
24
|
+
export declare function readJsonResponse(response: Response, maxBytes: number, options?: {
|
|
25
|
+
gzip?: boolean;
|
|
26
|
+
signal?: AbortSignal | null;
|
|
27
|
+
}): Promise<unknown>;
|
|
28
|
+
/** Gateway status codes cover several domains; a 401 alone cannot reject a key. */
|
|
29
|
+
export declare function classifyGatewayError(status: number, body: string, fallback: string): string;
|
|
30
|
+
export declare class GatewayDiagnostics {
|
|
31
|
+
private readonly options;
|
|
32
|
+
private evidence;
|
|
33
|
+
private code;
|
|
34
|
+
private readonly secrets;
|
|
35
|
+
constructor(options: {
|
|
36
|
+
provider: string;
|
|
37
|
+
model: string;
|
|
38
|
+
apiKey: string;
|
|
39
|
+
proxyURL?: string;
|
|
40
|
+
fetch?: typeof globalThis.fetch;
|
|
41
|
+
contextWindow?: number;
|
|
42
|
+
maxTokens?: number;
|
|
43
|
+
});
|
|
44
|
+
private redact;
|
|
45
|
+
readonly fetch: typeof globalThis.fetch;
|
|
46
|
+
failureCode(fallback: string): Promise<string>;
|
|
47
|
+
failureMessage(original: string): Promise<string>;
|
|
48
|
+
}
|
|
49
|
+
interface UsageErrorOptions {
|
|
50
|
+
apiKey: string;
|
|
51
|
+
baseURL: string;
|
|
52
|
+
proxyURL: string;
|
|
53
|
+
signal: AbortSignal;
|
|
54
|
+
}
|
|
55
|
+
/** Read only diagnostic text; a slow/broken error body cannot hide its HTTP status. */
|
|
56
|
+
export declare function readUsageError(response: Response, options: UsageErrorOptions): Promise<string | undefined>;
|
|
57
|
+
export declare function withGoogleFetch<T>(options: {
|
|
58
|
+
fetch?: typeof globalThis.fetch;
|
|
59
|
+
headers?: Record<string, string | null>;
|
|
60
|
+
} | undefined, request: () => T): T;
|
|
61
|
+
/** The pinned Google SDK's HTTP call uses this binding in builds and tests. */
|
|
62
|
+
export declare const googleFetch: typeof globalThis.fetch;
|
|
63
|
+
export {};
|