dsh-opencode-go 0.1.24 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.en.md +66 -12
  2. package/README.md +172 -79
  3. package/THIRD_PARTY_NOTICES.md +6 -2
  4. package/assets/icon.png +0 -0
  5. package/docs/advanced.en.md +32 -35
  6. package/docs/advanced.md +33 -35
  7. package/docs/assets/logo-dark.png +0 -0
  8. package/docs/assets/logo-light.png +0 -0
  9. package/docs/assets/usage-history-desktop.jpg +0 -0
  10. package/docs/assets/usage-history-mobile.jpg +0 -0
  11. package/docs/assets/usage-history-models.jpg +0 -0
  12. package/docs/development.md +61 -119
  13. package/docs/independent-package.md +4 -2
  14. package/docs/usage-analytics.en.md +57 -0
  15. package/docs/usage-analytics.md +57 -0
  16. package/docs/verification.md +51 -917
  17. package/lib/build-info.json +1 -1
  18. package/lib/client.js +3429 -2618
  19. package/lib/free-http-worker.js +32 -0
  20. package/lib/index.js +5135 -3746
  21. package/lib/types/accounts.d.ts +96 -31
  22. package/lib/types/adapter.d.ts +63 -51
  23. package/lib/types/analytics.d.ts +35 -0
  24. package/lib/types/catalog.d.ts +109 -44
  25. package/lib/types/client/AnalyticsDialog.d.ts +18 -0
  26. package/lib/types/client/Section.d.ts +41 -7
  27. package/lib/types/client/UsagePill.d.ts +15 -6
  28. package/lib/types/client/controller.d.ts +178 -0
  29. package/lib/types/client/dashboard-copy.d.ts +58 -0
  30. package/lib/types/client/index.d.ts +18 -12
  31. package/lib/types/client/{locales.d.ts → presentation.d.ts} +97 -9
  32. package/lib/types/config.d.ts +14 -15
  33. package/lib/types/contracts.d.ts +338 -0
  34. package/lib/types/conversion.d.ts +155 -0
  35. package/lib/types/free-channel.d.ts +21 -0
  36. package/lib/types/free-http-worker.d.ts +1 -0
  37. package/lib/types/free-policy.d.ts +4 -0
  38. package/lib/types/free-protocol.d.ts +16 -0
  39. package/lib/types/free-runtime.d.ts +2 -0
  40. package/lib/types/free-socks-tunnel.d.ts +4 -0
  41. package/lib/types/free-transport.d.ts +19 -0
  42. package/lib/types/index.d.ts +8 -40
  43. package/lib/types/pricing.d.ts +29 -0
  44. package/lib/types/sdk-types.d.ts +1540 -2902
  45. package/lib/types/transport.d.ts +71 -0
  46. package/lib/vendor-licenses.txt +55 -31
  47. package/package.json +77 -78
  48. package/docs/assets/usage-panel.png +0 -0
  49. package/docs/fork-review-2026-09-25.md +0 -191
  50. package/docs/native-call-comparison-v020-rc2.md +0 -116
  51. package/lib/types/account-manager.d.ts +0 -25
  52. package/lib/types/account-operations.d.ts +0 -31
  53. package/lib/types/account-policy.d.ts +0 -16
  54. package/lib/types/account-recovery.d.ts +0 -2
  55. package/lib/types/account-selection.d.ts +0 -30
  56. package/lib/types/account-service.d.ts +0 -12
  57. package/lib/types/accounts-contract.d.ts +0 -38
  58. package/lib/types/call-trace.d.ts +0 -54
  59. package/lib/types/catalog-manager.d.ts +0 -20
  60. package/lib/types/client/AccountsCard.d.ts +0 -19
  61. package/lib/types/client/ModelEditor.d.ts +0 -20
  62. package/lib/types/client/accounts-controller.d.ts +0 -71
  63. package/lib/types/client/hint-mark.d.ts +0 -17
  64. package/lib/types/client/host-compat.d.ts +0 -7
  65. package/lib/types/client/host-primitives.d.ts +0 -11
  66. package/lib/types/client/section-controller.d.ts +0 -202
  67. package/lib/types/client/settings.d.ts +0 -18
  68. package/lib/types/client/staged-form.d.ts +0 -201
  69. package/lib/types/client/usage.d.ts +0 -4
  70. package/lib/types/config-contract.d.ts +0 -70
  71. package/lib/types/conversion/config.d.ts +0 -4
  72. package/lib/types/conversion/context.d.ts +0 -56
  73. package/lib/types/conversion/image-offload.d.ts +0 -13
  74. package/lib/types/conversion/image-pool.d.ts +0 -24
  75. package/lib/types/conversion/index.d.ts +0 -5
  76. package/lib/types/conversion/replay.d.ts +0 -66
  77. package/lib/types/conversion/stream.d.ts +0 -44
  78. package/lib/types/gateway-diagnostics.d.ts +0 -23
  79. package/lib/types/gateway-error.d.ts +0 -2
  80. package/lib/types/gateway-url.d.ts +0 -6
  81. package/lib/types/google-fetch.d.ts +0 -6
  82. package/lib/types/host-settings.d.ts +0 -11
  83. package/lib/types/json-response.d.ts +0 -14
  84. package/lib/types/metadata-cache.d.ts +0 -12
  85. package/lib/types/model-metadata.d.ts +0 -21
  86. package/lib/types/models-contract.d.ts +0 -66
  87. package/lib/types/models.d.ts +0 -13
  88. package/lib/types/protocol-contract.d.ts +0 -5
  89. package/lib/types/protocol-policy.d.ts +0 -4
  90. package/lib/types/provider-identity.d.ts +0 -4
  91. package/lib/types/proxy-url.d.ts +0 -2
  92. package/lib/types/proxy.d.ts +0 -11
  93. package/lib/types/reasoning.d.ts +0 -40
  94. package/lib/types/remote-contract.d.ts +0 -3
  95. package/lib/types/remotes.d.ts +0 -3
  96. package/lib/types/request-budget.d.ts +0 -12
  97. package/lib/types/request-control.d.ts +0 -2
  98. package/lib/types/settings-bridge.d.ts +0 -22
  99. package/lib/types/usage-contract.d.ts +0 -35
  100. package/lib/types/usage-display.d.ts +0 -4
  101. package/lib/types/usage.d.ts +0 -27
  102. /package/lib/types/{google-generative-ai.d.ts → google.d.ts} +0 -0
@@ -0,0 +1,338 @@
1
+ /** Browser-safe configuration, account metadata and RPC wire contracts. */
2
+ import type { RemoteResult, TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol';
3
+ /** Public DSH route and the private SDK transport have separate identities. */
4
+ export declare const PROVIDER_ID = "dsh-opencode-go";
5
+ export declare const DISPLAY_NAME = "DSH OpenCode Go";
6
+ export declare const FREE_PROVIDER_ID = "dsh-opencode-free";
7
+ export declare const FREE_DISPLAY_NAME = "DSH OpenCode Free";
8
+ export type ModelSource = 'go' | 'free';
9
+ /** Go keeps its legacy keys; Free owns a separate settings namespace. */
10
+ export declare function modelSettingsKey(model: {
11
+ id: string;
12
+ source?: ModelSource;
13
+ }): string;
14
+ export declare const SDK_PROVIDER_ID = "opencode-go";
15
+ /** Public Go discovery/usage base; inference uses the documented protocol-specific siblings. */
16
+ export declare const DEFAULT_BASE_URL = "https://opencode.ai/inference/go/v1";
17
+ export declare const DEFAULT_FREE_BASE_URL = "https://opencode.ai/inference/v1";
18
+ /**
19
+ * Migrate the legacy official address before any request is constructed.
20
+ */
21
+ export declare function migrateGatewayBaseURL(baseURL: string): string;
22
+ /** Shared by Host validation and the browser form; never echo proxy credentials. */
23
+ export declare function assertProxyURL(raw: string | undefined): string;
24
+ /** Usage visibility shared by the Host schema and the browser settings. */
25
+ export declare const USAGE_DISPLAY_MODES: readonly ["auto", "always", "off"];
26
+ export type UsageDisplayMode = typeof USAGE_DISPLAY_MODES[number];
27
+ export declare const DEFAULT_USAGE_DISPLAY: UsageDisplayMode;
28
+ export declare const USAGE_PILL_STYLES: readonly ["badge", "plain"];
29
+ export type UsagePillStyle = typeof USAGE_PILL_STYLES[number];
30
+ export declare const DEFAULT_USAGE_PILL_STYLE: UsagePillStyle;
31
+ /** Client-safe account metadata. Secrets stay in the host credential service. */
32
+ export type GoAccount = {
33
+ id: string;
34
+ name: string;
35
+ apiKeyEnv: string;
36
+ };
37
+ export declare const MAX_ACCOUNTS = 20;
38
+ export declare const ACCOUNT_REF_PREFIX = "DSH_OPENCODE_GO_ACCOUNT_";
39
+ export declare const DEFAULT_ACCOUNT_REF = "OPENCODE_API_KEY";
40
+ /** A credential reference is a bare environment variable name, never empty or decorated. */
41
+ export declare const ACCOUNT_REF_PATTERN: RegExp;
42
+ export interface AccountSettings {
43
+ apiKeyEnv?: string;
44
+ /** Omission/null preserves legacy credentials; an explicit empty list removes all accounts. */
45
+ accounts?: readonly GoAccount[] | null;
46
+ autoSwitch?: boolean;
47
+ }
48
+ export declare function accountRefOf(settings: AccountSettings): string;
49
+ /** Promote one account while preserving every other account's relative order. */
50
+ export declare function moveAccountFirst(accounts: readonly GoAccount[], ref: string): readonly GoAccount[];
51
+ /** Read legacy selections as the first account until the host persists their order. */
52
+ export declare function accountsOf(settings: AccountSettings): readonly GoAccount[];
53
+ export declare function assertAccounts(accounts: readonly GoAccount[] | null | undefined, selectedRef?: string): void;
54
+ /** Safe UI notice for a successful request using a fallback account. */
55
+ export interface GoAccountSwitch {
56
+ fromRef: string;
57
+ toRef: string;
58
+ reason: 'quota' | 'credential';
59
+ at: number;
60
+ }
61
+ export declare const SETTINGS_NAMESPACE = "llm-opencode-go";
62
+ export declare const PROFILE_ENTRY_ID = "opencode-go";
63
+ /**
64
+ * One model's configured capacities. Every field is optional so a deployment
65
+ * can override only the value it needs. Null explicitly selects the catalog
66
+ * value even when a lower profile/settings layer supplies an override.
67
+ */
68
+ export interface OpencodeGoModelLimit {
69
+ /** Context window in tokens, overriding what the catalog advertised. */
70
+ contextWindow?: number | null;
71
+ /** Output cap per request, overriding what the catalog advertised. */
72
+ maxTokens?: number | null;
73
+ /** Additional selectable thinking budgets, in tokens; null keeps the standard presets. */
74
+ thinkingBudgets?: number[] | null;
75
+ }
76
+ /** Per-model capacities; a null entry selects both original catalog values. */
77
+ export type OpencodeGoModelLimits = Record<string, OpencodeGoModelLimit | null>;
78
+ /** Runtime configuration for one plugin mount. */
79
+ export interface OpencodeGoConfig {
80
+ /**
81
+ * Whether this plugin serves Go and Free. False withdraws both routes and
82
+ * their models without unloading the settings page. Go additionally requires
83
+ * a usable configured key; Free supports public access.
84
+ */
85
+ enabled: boolean;
86
+ /** Usage pill visibility; auto follows only the selected Go route. */
87
+ usageDisplay: UsageDisplayMode;
88
+ /** Show quota in the sidebar independently of the selected conversation model. */
89
+ showSidebarQuota: boolean;
90
+ /** Appearance of the conversation input's quota trigger. */
91
+ usagePillStyle: UsagePillStyle;
92
+ /** Per-model picker switches; absent entries default to enabled unless deprecated. */
93
+ modelVisibility?: Record<string, boolean>;
94
+ /** Legacy credential reference, kept in sync with the first/current account. */
95
+ apiKeyEnv: string;
96
+ /** The first account is current; subsequent accounts are tried in order. */
97
+ accounts?: GoAccount[] | null;
98
+ /** Try other saved accounts on quota/credential rejection before any content is emitted. */
99
+ autoSwitch?: boolean;
100
+ /** Discovery/usage base; the official Go gateway selects inference endpoints by protocol. */
101
+ baseURL: string;
102
+ /** Platform discovery base; only explicitly free chat models are served. */
103
+ freeBaseURL: string;
104
+ /** Optional HTTP(S) or SOCKS5 proxy; blank uses the default network transport. */
105
+ proxyURL: string;
106
+ /** Request/picker cache lifetime in minutes; explicit discovery bypasses it. */
107
+ refreshMinutes: number;
108
+ /** Largest idle gap between stream events before the request fails. */
109
+ streamIdleTimeoutMs: number;
110
+ /** Bound discovery and each attempt's credential/image preparation. */
111
+ requestPreparationTimeoutMs?: number;
112
+ /** Whole dispatch deadline, including discovery and account fallback. */
113
+ requestTimeoutMs?: number;
114
+ /** Optional retained image occurrence cap per request; omission or null leaves the count unlimited. */
115
+ maxImages?: number | null;
116
+ /** Request-level bound on base64-encoded image payload, in bytes. */
117
+ maxRequestImageBytes: number;
118
+ /** Total-pixel budget for one request image. */
119
+ requestImagePixelBudget: number;
120
+ /** Raw encoded-byte target for one request image before base64 expansion. */
121
+ requestImageMaxBytes: number;
122
+ /** Per-model capacity overrides; an absent field inherits the catalog value. */
123
+ modelLimits: OpencodeGoModelLimits;
124
+ }
125
+ /** Settings snapshots may omit fields inherited from their base layer. */
126
+ export type OpencodeGoSettings = Partial<OpencodeGoConfig>;
127
+ export interface GoModel {
128
+ id: string;
129
+ source?: ModelSource;
130
+ name?: string;
131
+ contextWindow?: number;
132
+ maxTokens?: number;
133
+ /** Token budget controls available to this model, including their catalog bounds. */
134
+ reasoningBudget?: ThinkingBudgetRange;
135
+ deprecated?: boolean;
136
+ releaseDate?: string;
137
+ /** Input modalities the gateway declares, in {@link INPUT_MODALITIES} order. */
138
+ inputModalities?: readonly InputModality[];
139
+ /** Advertised by the gateway but lacking a usable protocol and capability configuration. */
140
+ configurationMissing?: boolean;
141
+ }
142
+ export interface ThinkingBudgetRange {
143
+ min: number;
144
+ max: number;
145
+ }
146
+ /**
147
+ * Input modalities this page can name; MIME types are normalized to these tokens.
148
+ */
149
+ export declare const INPUT_MODALITIES: readonly ["text", "image", "audio", "video", "pdf"];
150
+ export type InputModality = typeof INPUT_MODALITIES[number];
151
+ /**
152
+ * Normalize one `modalities.input` array into display order.
153
+ * @param value - the raw gateway declaration or Host response.
154
+ * @returns the declared modalities in {@link INPUT_MODALITIES} order, or
155
+ * `undefined` when nothing recognizable was declared.
156
+ */
157
+ export declare function normalizeInputModalities(value: unknown): readonly InputModality[] | undefined;
158
+ /** Last successful check of one catalog source, plus any current refresh failure. */
159
+ export interface GoCatalogSourceStatus {
160
+ readonly updatedAt?: number;
161
+ readonly error?: string;
162
+ readonly warning?: string;
163
+ }
164
+ /** A failed refresh retains the Host's usable data with an explicit diagnostic. */
165
+ export interface GoModelCatalog {
166
+ readonly models: readonly GoModel[];
167
+ readonly stale: boolean;
168
+ readonly error?: string;
169
+ /** Optional for clients reading an older Host response. Timestamps are Unix milliseconds. */
170
+ readonly sources?: {
171
+ readonly go: GoCatalogSourceStatus;
172
+ readonly free: GoCatalogSourceStatus;
173
+ };
174
+ }
175
+ /** Missing configuration cannot be enabled; configured models follow explicit switches or lifecycle defaults. */
176
+ export declare function isModelEnabled(model: Pick<GoModel, 'id' | 'source' | 'deprecated' | 'configurationMissing'>, modelVisibility?: Readonly<Record<string, boolean>>): boolean;
177
+ export declare function validReleaseDate(value: unknown): value is string;
178
+ /** Calendar dates are supplied without a timezone; compare UTC dates consistently. */
179
+ export declare function isNewModel(model: GoModel, now?: number): boolean;
180
+ export declare function sortModels(models: readonly GoModel[], now?: number): GoModel[];
181
+ export declare function parseGoModels(value: unknown): GoModel[];
182
+ export declare function parseGoModelCatalog(value: unknown): GoModelCatalog;
183
+ declare module '@deepseek-ai/dsh-typert-protocol' {
184
+ interface TypertRemoteNamespaceMap {
185
+ opencodeGoModels: {
186
+ read(): Promise<RemoteResult<GoModelCatalog>>;
187
+ };
188
+ }
189
+ }
190
+ export declare const modelsRemote: TypertRemoteContribution;
191
+ export interface UsageWindow {
192
+ status: 'ok' | 'rate-limited';
193
+ percent: number;
194
+ resetsAt: string;
195
+ }
196
+ export interface GoUsage {
197
+ /** Opaque Host identity for this endpoint/account; never a credential or its hash. */
198
+ source?: string;
199
+ lastSwitch?: GoAccountSwitch;
200
+ rolling: UsageWindow;
201
+ weekly: UsageWindow;
202
+ monthly: UsageWindow;
203
+ }
204
+ export declare function parseAccountSwitch(value: unknown): GoAccountSwitch;
205
+ /** Reject missing statistics rather than turning unavailable data into zero. */
206
+ export declare function parseGoUsage(value: unknown): GoUsage;
207
+ declare module '@deepseek-ai/dsh-typert-protocol' {
208
+ interface RemoteErrorDetailsMap {
209
+ 'opencode-go/usage-unavailable': {
210
+ readonly retryable: boolean;
211
+ readonly retainPrevious: boolean;
212
+ readonly source?: string;
213
+ readonly lastSwitch?: GoAccountSwitch;
214
+ };
215
+ }
216
+ interface TypertRemoteNamespaceMap {
217
+ opencodeGoUsage: {
218
+ read(): Promise<RemoteResult<GoUsage>>;
219
+ readAccount(ref: string): Promise<RemoteResult<GoUsage>>;
220
+ };
221
+ }
222
+ }
223
+ export declare const usageRemote: TypertRemoteContribution;
224
+ export type AccountCommand = {
225
+ kind: 'add';
226
+ id: string;
227
+ name: string;
228
+ key: string;
229
+ } | {
230
+ kind: 'remove';
231
+ ref: string;
232
+ } | {
233
+ kind: 'select';
234
+ ref: string;
235
+ } | {
236
+ kind: 'rename';
237
+ ref: string;
238
+ name: string;
239
+ } | {
240
+ kind: 'replace-key';
241
+ ref: string;
242
+ key: string;
243
+ } | {
244
+ kind: 'move';
245
+ ref: string;
246
+ toIndex: number;
247
+ } | {
248
+ kind: 'auto-switch';
249
+ value: boolean;
250
+ };
251
+ export declare function parseAccountCommand(value: unknown): AccountCommand;
252
+ declare module '@deepseek-ai/dsh-typert-protocol' {
253
+ interface TypertRemoteNamespaceMap {
254
+ opencodeGoAccounts: {
255
+ execute(command: AccountCommand): Promise<RemoteResult<SettingsWriteResult>>;
256
+ };
257
+ }
258
+ }
259
+ export declare const accountsRemote: TypertRemoteContribution;
260
+ export type SettingsWriteResult = 'applied' | 'rejected' | 'unknown';
261
+ export type AnalyticsRange = 'today' | '7d' | '30d' | '90d';
262
+ export interface AnalyticsQuery {
263
+ accountRef: string;
264
+ range: AnalyticsRange;
265
+ refresh?: boolean;
266
+ }
267
+ /** Exact nonnegative integers on the wire; one USD is 100,000,000 micro cents. */
268
+ export interface AnalyticsTotals {
269
+ requests: string;
270
+ inputTokens: string;
271
+ outputTokens: string;
272
+ cacheReadTokens: string;
273
+ cacheWrite5mTokens: string;
274
+ cacheWrite1hTokens: string;
275
+ cacheWriteTokens: string;
276
+ tokens: string;
277
+ costMicroCents: string;
278
+ }
279
+ export interface AnalyticsModelRow extends AnalyticsTotals {
280
+ provider: string;
281
+ model: string;
282
+ }
283
+ export interface AnalyticsDayRow extends AnalyticsTotals {
284
+ day: string;
285
+ }
286
+ export interface AnalyticsReport {
287
+ accountRef: string;
288
+ /** Opaque account, credential and network identity; contains no credential material. */
289
+ source: string;
290
+ generatedAt: number;
291
+ period: AnalyticsRange;
292
+ range: {
293
+ from: number;
294
+ to: number;
295
+ };
296
+ timeZone: 'UTC';
297
+ totals: AnalyticsTotals;
298
+ byModel: AnalyticsModelRow[];
299
+ byDay: AnalyticsDayRow[];
300
+ }
301
+ export interface AnalyticsExport {
302
+ filename: string;
303
+ csv: string;
304
+ }
305
+ export type AnalyticsFailureReason = 'invalid-query' | 'unknown-account' | 'missing-credential' | 'credential-unavailable' | 'unsupported-gateway' | 'invalid-proxy' | 'permission-denied' | 'upstream' | 'network' | 'timeout' | 'invalid-response';
306
+ /**
307
+ * Validate one account-scoped official history query.
308
+ * @param value - raw RPC argument.
309
+ * @returns the validated query.
310
+ */
311
+ export declare function parseAnalyticsQuery(value: unknown): AnalyticsQuery;
312
+ /** Keep the browser wire response limited to validated aggregate fields. */
313
+ export declare function parseAnalyticsReport(value: unknown): AnalyticsReport;
314
+ export declare function parseAnalyticsExport(value: unknown): AnalyticsExport;
315
+ declare module '@deepseek-ai/dsh-typert-protocol' {
316
+ interface RemoteErrorDetailsMap {
317
+ 'opencode-go/analytics-unavailable': {
318
+ readonly reason: AnalyticsFailureReason;
319
+ readonly retryable: boolean;
320
+ readonly retainPrevious?: boolean;
321
+ readonly source?: string;
322
+ };
323
+ }
324
+ interface TypertRemoteNamespaceMap {
325
+ opencodeGoAnalytics: {
326
+ read(query: AnalyticsQuery, signal?: AbortSignal): Promise<RemoteResult<AnalyticsReport>>;
327
+ exportCsv(query: AnalyticsQuery, signal?: AbortSignal): Promise<RemoteResult<AnalyticsExport>>;
328
+ };
329
+ }
330
+ }
331
+ /** The dashboard endpoint, mounted with the other plugin remotes. */
332
+ export declare const analyticsRemote: TypertRemoteContribution;
333
+ /** A registry owns one contribution per package; mount all plugin endpoints together. */
334
+ export declare const goRemote: TypertRemoteContribution;
335
+ /** Default image budgets, overridable through the adapter configuration. */
336
+ export declare const DEFAULT_MAX_REQUEST_IMAGE_BYTES: number;
337
+ export declare const DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET: number;
338
+ export declare const DEFAULT_REQUEST_IMAGE_MAX_BYTES: number;
@@ -0,0 +1,155 @@
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
+ /** Measured context footprint for the next turn's SDK output-token clamp. */
35
+ usage?: Pick<PiUsage, 'input' | 'output' | 'cacheRead' | 'cacheWrite' | 'totalTokens'>;
36
+ /** Fingerprint of the request prefix and this reply that the usage measured. */
37
+ usageContext?: string;
38
+ }
39
+ /** Capture one converted request before the SDK can mutate it while streaming. */
40
+ export declare function piContextUsageKey(context: PiContext, provider: string, model: string): string;
41
+ /**
42
+ * Project a successful pi-ai response into the minimal durable replay state.
43
+ * The per-block half is index-aligned with the streamed blocks (pi-ai content
44
+ * order), so `BlockAssembler` prunes an entry with its block whenever assembly
45
+ * removes one.
46
+ * @param message - completed native pi-ai assistant response.
47
+ * @param requestedModel - request identity stored in the assistant source; defaults to the native model.
48
+ * @param requestedProvider - DSH route stored in the assistant source; defaults to the native provider.
49
+ * @param usageContext - fingerprint of the request that produced this response.
50
+ * @returns the versioned lossless-JSON replay projection.
51
+ */
52
+ export declare function toPiReplayState(message: AssistantMessage, requestedModel?: string, requestedProvider?: string, usageContext?: string): ReplayEnvelope;
53
+ /**
54
+ * Convert one durable Harness assistant message into pi-ai history.
55
+ *
56
+ * Durable content is the authoritative record; replay metadata only restores
57
+ * native fidelity (ids, signatures). A replay state this build cannot use —
58
+ * another adapter's kind, another version, a malformed value, or metadata that
59
+ * no longer matches the content — therefore degrades the one message to
60
+ * provider-neutral history instead of failing the request.
61
+ * @param message - assistant content with required source and optional adapter-owned replay metadata.
62
+ * @param onDegrade - called with the diagnostic reason when an unusable replay
63
+ * state falls back to provider-neutral conversion.
64
+ * @returns a native pi-ai assistant message reconstructed from durable content.
65
+ */
66
+ export declare function toPiAssistant(message: HistoryMessage, onDegrade?: (reason: string) => void): AssistantMessage;
67
+ interface ImageProjectionPolicy {
68
+ maxImages?: number;
69
+ maxBytes?: number;
70
+ byteLength: (ref: ImageAttachmentRef) => number;
71
+ placeholder: (ref: ImageAttachmentRef) => string;
72
+ exact: boolean;
73
+ }
74
+ export declare function projectRequestImages(messages: readonly Message[], policy: ImageProjectionPolicy): readonly Message[];
75
+ /** Inputs that bind deterministic request images to one current tool execution world. */
76
+ export interface PiImageRequestContext {
77
+ /** Durable provider that resolves request-image bytes and provider-owned host objects. */
78
+ attachments: AttachmentStore;
79
+ /** Resolve current tool access separately from deterministic request-image versions. */
80
+ resolveImageAccess: ImageAttachmentAccessResolver;
81
+ /** Maximum retained image occurrences across request history; omission leaves the count unlimited. */
82
+ maxImages?: number;
83
+ /** Request-level bound on the base64-encoded payload of retained images; omission leaves the bound unchecked. */
84
+ maxRequestImageBytes?: number;
85
+ /** Route pixel and raw encoded-byte budgets. */
86
+ requestImagePolicy?: PiImageRequestBudget;
87
+ }
88
+ /** Per-route budgets from which each request image's target is derived. */
89
+ export interface PiImageRequestBudget {
90
+ /** Total-pixel budget; larger sources are downscaled proportionally. */
91
+ maxPixels: number;
92
+ /** Encoded-byte target for one request image. */
93
+ maxBytes: number;
94
+ }
95
+ /**
96
+ * Convert text-only harness history to a synchronous pi-ai Context. Tool
97
+ * result names are recovered from preceding assistant tool calls.
98
+ * @param options - the harness request; `options.system`, else a leading `system` message, maps to pi-ai's single `systemPrompt` slot.
99
+ * @param images - absent; selects the synchronous conversion.
100
+ * @param onReplayDegrade - forwarded to {@link toPiAssistant} for each assistant message.
101
+ * @returns the pi-ai context; `tools` is omitted when the request declares none.
102
+ * @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.
103
+ */
104
+ export declare function toPiContext(options: GenerateOptions, images?: undefined, onReplayDegrade?: (reason: string) => void): PiContext;
105
+ /**
106
+ * Convert harness history to a pi-ai Context while resolving durable images.
107
+ * Tool result names are recovered from preceding assistant tool calls.
108
+ * Occurrences the surface marks offloaded become placeholders; when the
109
+ * retained occurrences exceed `maxImages` or their exact base64 payload exceeds
110
+ * `maxRequestImageBytes`, the call fails with `IMAGE_OFFLOAD_REQUIRED` naming
111
+ * how many more oldest occurrences must be offloaded.
112
+ * @param options - the harness request; `options.system`, else a leading `system` message, maps to pi-ai's single `systemPrompt` slot.
113
+ * @param images - attachment provider, current path resolver, and request limits.
114
+ * @param onReplayDegrade - forwarded to {@link toPiAssistant} for each assistant message.
115
+ * @returns the asynchronously resolved pi-ai context.
116
+ */
117
+ export declare function toPiContext(options: GenerateOptions, images: PiImageRequestContext, onReplayDegrade?: (reason: string) => void): Promise<PiContext>;
118
+ /**
119
+ * Map pi-ai usage (reasoning folded into output by pi-ai).
120
+ * @param usage - cumulative usage from the terminal pi-ai event.
121
+ * @returns harness counts with pi-ai's exact total; cache fields appear only
122
+ * when non-zero (pi-ai reports zeros, not absence).
123
+ */
124
+ export declare function mapUsage(usage: PiUsage): TokenUsage;
125
+ /**
126
+ * Map a terminal pi-ai event to the harness finish reason.
127
+ * @param message - the assistant message carried by the `done` or `error` event.
128
+ * @param contextWindow - resolved catalog capacity for usage-based overflow detection.
129
+ * @param reservedMaxTokens - requested output allowance before SDK context clamping.
130
+ * @returns the mapped harness reason. Recognized error text, `stop` usage above
131
+ * `contextWindow`, and zero-output `length` usage that fills the window map
132
+ * to `CONTEXT_WINDOW_EXCEEDED`; a `stop` with no content blocks maps to an
133
+ * `EMPTY_RESPONSE` error. Other empty `length` responses map to `INVALID_REQUEST`
134
+ * with output-limit or compaction guidance. Terminal `pending` and `deferred`
135
+ * states map to non-retryable `PI_AI_ERROR` failures.
136
+ */
137
+ export declare function mapStopReason(message: AssistantMessage, contextWindow?: number, reservedMaxTokens?: number): FinishReason;
138
+ /**
139
+ * Translate the pi-ai event stream into StreamChunks. pi-ai never throws
140
+ * mid-stream — failures arrive as `error` events, which become error/aborted
141
+ * `finish` chunks (the harness protocol's other error-delivery style).
142
+ * @param events - one assistant turn's pi-ai event stream.
143
+ * @param contextWindow - resolved catalog capacity for usage-based overflow detection.
144
+ * @param callerSignal - caller cancellation state; an aborted caller makes any
145
+ * in-band terminal error an aborted finish.
146
+ * @param requestedModel - request model identity recorded for durable replay.
147
+ * @param requestedProvider - DSH provider identity recorded for durable replay.
148
+ * @param reservedMaxTokens - requested output allowance before SDK context clamping.
149
+ * @param usageContext - fingerprint of the request whose usage may budget a later turn.
150
+ * @returns the harness chunks, ending with measured `usage` then `finish`;
151
+ * failures with no measured tokens omit usage to preserve context pressure. Throws
152
+ * `LlmError` (`STREAM_CLOSED`) if the source ends without a terminal event.
153
+ */
154
+ export declare function toStreamChunks(events: AsyncIterable<AssistantMessageEvent>, contextWindow?: number, callerSignal?: AbortSignal, requestedModel?: string, requestedProvider?: string, reservedMaxTokens?: number, usageContext?: string): AsyncGenerator<StreamChunk>;
155
+ export { DEFAULT_MAX_REQUEST_IMAGE_BYTES, DEFAULT_REQUEST_IMAGE_MAX_BYTES, DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET, } from './contracts.ts';
@@ -0,0 +1,21 @@
1
+ import type { OpencodeGoConfig } from './contracts.ts';
2
+ type Network = Pick<OpencodeGoConfig, 'freeBaseURL' | 'proxyURL'>;
3
+ export interface FreeAttemptTicket {
4
+ key: string;
5
+ sequence: number;
6
+ }
7
+ export interface FreeAttemptResult {
8
+ outcome: 'success' | 'error' | 'aborted';
9
+ code?: string;
10
+ retryAt?: number;
11
+ }
12
+ export declare class FreeChannelState {
13
+ private readonly entries;
14
+ private sequence;
15
+ private key;
16
+ cooldownUntil(config: Network): number | undefined;
17
+ assertReady(config: Network): void;
18
+ begin(config: Network): FreeAttemptTicket;
19
+ finish(ticket: FreeAttemptTicket, result: FreeAttemptResult): void;
20
+ }
21
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ /** Free-specific error semantics; Go account classification remains unchanged. */
2
+ export declare function classifyFreeGatewayError(status: number, body: string): string | undefined;
3
+ /** Parse delta-seconds or HTTP-date, accounting for a server clock when supplied. */
4
+ export declare function retryAfterDeadline(value: string | null, now?: number, serverDate?: string | null): number | undefined;
@@ -0,0 +1,16 @@
1
+ /** Private stdin/stdout protocol; request credentials never enter argv or files. */
2
+ export interface FreeHttpRequest {
3
+ url: string;
4
+ method: string;
5
+ headers: [string, string][];
6
+ body?: string;
7
+ redirect: RequestRedirect;
8
+ proxy?: string;
9
+ }
10
+ export interface FreeHttpResponse {
11
+ status: number;
12
+ statusText: string;
13
+ headers: [string, string][];
14
+ url: string;
15
+ redirected: boolean;
16
+ }
@@ -0,0 +1,2 @@
1
+ export declare function resolveFreeRuntime(): string;
2
+ export declare function freeWorkerPath(): string;
@@ -0,0 +1,4 @@
1
+ export declare function openSocksTunnel(raw: string, signal: AbortSignal): Promise<{
2
+ url: string;
3
+ close(): Promise<void>;
4
+ }>;
@@ -0,0 +1,19 @@
1
+ export declare const OPENCODE_FREE_USER_AGENT = "opencode/latest/2.2.5/cli";
2
+ export declare class FreeBunTransport {
3
+ private readonly options;
4
+ private readonly shutdown;
5
+ private readonly workers;
6
+ private readonly requests;
7
+ private readonly waiters;
8
+ private active;
9
+ constructor(options?: {
10
+ executable?: () => string;
11
+ workerPath?: () => string;
12
+ maxConcurrent?: number;
13
+ });
14
+ forProxy(raw?: string): typeof globalThis.fetch;
15
+ private acquire;
16
+ private fetchRequest;
17
+ private response;
18
+ dispose(): Promise<void>;
19
+ }
@@ -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 { LiveConfig, OpencodeGoConfig } from './config.ts';
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, GoCallTrace } from './adapter.ts';
42
- export { DEFAULT_BASE_URL, DISPLAY_NAME, PROVIDER_ID, OpencodeGoCatalog, discoverCatalogModels, readLiveModelIds, } from './catalog.ts';
9
+ export type { OpencodeGoAdapterOptions, OpencodeGoImageAccess, GoAccountSettlement } from './adapter.ts';
10
+ export { DEFAULT_BASE_URL, DEFAULT_FREE_BASE_URL, DISPLAY_NAME, PROVIDER_ID, FREE_DISPLAY_NAME, FREE_PROVIDER_ID, OpencodeGoCatalog, discoverCatalogModels, readLiveModelIds, } from './catalog.ts';
43
11
  export { Config, PlainConfig, assertBaseURL } from './config.ts';
44
- export { assertProxyURL } from './proxy-url.ts';
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, its discovery, the settings section, and their
52
- * teardown for one mount. Configuration starts as the cordis.yml entry and is
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;
@@ -0,0 +1,29 @@
1
+ /** Strict gateway tariff validation for model discovery and Free eligibility. */
2
+ import type { ModelCost } from './sdk-types.ts';
3
+ type Comparison<T> = {
4
+ in?: T[];
5
+ eq?: T;
6
+ gt?: T;
7
+ gte?: T;
8
+ lt?: T;
9
+ lte?: T;
10
+ };
11
+ export interface PricingCondition {
12
+ all?: PricingCondition[];
13
+ any?: PricingCondition[];
14
+ utc_days?: Comparison<string>;
15
+ utc_hours?: Comparison<string>;
16
+ date?: Comparison<string>;
17
+ }
18
+ export interface PriceMultiplier {
19
+ when: PricingCondition;
20
+ factor: number;
21
+ }
22
+ export interface ParsedCost {
23
+ cost: ModelCost;
24
+ multipliers?: PriceMultiplier[];
25
+ free: boolean;
26
+ }
27
+ /** Missing base prices or malformed optional components invalidate the entire tariff. */
28
+ export declare function readModelCost(value: unknown): ParsedCost | undefined;
29
+ export {};