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.
Files changed (87) hide show
  1. package/README.en.md +59 -7
  2. package/README.md +164 -79
  3. package/THIRD_PARTY_NOTICES.md +1 -1
  4. package/assets/icon.png +0 -0
  5. package/docs/advanced.en.md +15 -22
  6. package/docs/advanced.md +15 -22
  7. package/docs/assets/logo-dark.png +0 -0
  8. package/docs/assets/logo-light.png +0 -0
  9. package/docs/development.md +47 -119
  10. package/docs/independent-package.md +4 -2
  11. package/docs/usage-analytics.en.md +108 -0
  12. package/docs/usage-analytics.md +108 -0
  13. package/docs/verification.md +25 -928
  14. package/lib/client.js +3430 -2473
  15. package/lib/index.js +2650 -2440
  16. package/lib/types/accounts.d.ts +96 -31
  17. package/lib/types/adapter.d.ts +45 -48
  18. package/lib/types/analytics.d.ts +345 -0
  19. package/lib/types/catalog.d.ts +112 -6
  20. package/lib/types/client/AnalyticsDialog.d.ts +25 -0
  21. package/lib/types/client/Section.d.ts +51 -7
  22. package/lib/types/client/UsagePill.d.ts +6 -4
  23. package/lib/types/client/controller.d.ts +176 -0
  24. package/lib/types/client/index.d.ts +9 -12
  25. package/lib/types/client/{locales.d.ts → presentation.d.ts} +124 -0
  26. package/lib/types/config.d.ts +9 -14
  27. package/lib/types/contracts.d.ts +283 -0
  28. package/lib/types/conversion.d.ts +147 -0
  29. package/lib/types/index.d.ts +7 -39
  30. package/lib/types/sdk-types.d.ts +5 -54
  31. package/lib/types/transport.d.ts +63 -0
  32. package/lib/vendor-licenses.txt +36 -36
  33. package/package.json +76 -77
  34. package/docs/fork-review-2026-09-25.md +0 -191
  35. package/docs/native-call-comparison-v020-rc2.md +0 -116
  36. package/lib/types/account-manager.d.ts +0 -25
  37. package/lib/types/account-operations.d.ts +0 -31
  38. package/lib/types/account-policy.d.ts +0 -16
  39. package/lib/types/account-recovery.d.ts +0 -2
  40. package/lib/types/account-selection.d.ts +0 -30
  41. package/lib/types/account-service.d.ts +0 -12
  42. package/lib/types/accounts-contract.d.ts +0 -38
  43. package/lib/types/call-trace.d.ts +0 -54
  44. package/lib/types/catalog-manager.d.ts +0 -20
  45. package/lib/types/client/AccountsCard.d.ts +0 -19
  46. package/lib/types/client/ModelEditor.d.ts +0 -20
  47. package/lib/types/client/accounts-controller.d.ts +0 -71
  48. package/lib/types/client/hint-mark.d.ts +0 -17
  49. package/lib/types/client/host-compat.d.ts +0 -7
  50. package/lib/types/client/host-primitives.d.ts +0 -11
  51. package/lib/types/client/section-controller.d.ts +0 -202
  52. package/lib/types/client/settings.d.ts +0 -18
  53. package/lib/types/client/staged-form.d.ts +0 -201
  54. package/lib/types/client/usage.d.ts +0 -4
  55. package/lib/types/config-contract.d.ts +0 -70
  56. package/lib/types/conversion/config.d.ts +0 -4
  57. package/lib/types/conversion/context.d.ts +0 -56
  58. package/lib/types/conversion/image-offload.d.ts +0 -13
  59. package/lib/types/conversion/image-pool.d.ts +0 -24
  60. package/lib/types/conversion/index.d.ts +0 -5
  61. package/lib/types/conversion/replay.d.ts +0 -66
  62. package/lib/types/conversion/stream.d.ts +0 -44
  63. package/lib/types/gateway-diagnostics.d.ts +0 -23
  64. package/lib/types/gateway-error.d.ts +0 -2
  65. package/lib/types/gateway-url.d.ts +0 -6
  66. package/lib/types/google-fetch.d.ts +0 -6
  67. package/lib/types/host-settings.d.ts +0 -11
  68. package/lib/types/json-response.d.ts +0 -14
  69. package/lib/types/metadata-cache.d.ts +0 -12
  70. package/lib/types/model-metadata.d.ts +0 -21
  71. package/lib/types/models-contract.d.ts +0 -66
  72. package/lib/types/models.d.ts +0 -13
  73. package/lib/types/protocol-contract.d.ts +0 -5
  74. package/lib/types/protocol-policy.d.ts +0 -4
  75. package/lib/types/provider-identity.d.ts +0 -4
  76. package/lib/types/proxy-url.d.ts +0 -2
  77. package/lib/types/proxy.d.ts +0 -11
  78. package/lib/types/reasoning.d.ts +0 -40
  79. package/lib/types/remote-contract.d.ts +0 -3
  80. package/lib/types/remotes.d.ts +0 -3
  81. package/lib/types/request-budget.d.ts +0 -12
  82. package/lib/types/request-control.d.ts +0 -2
  83. package/lib/types/settings-bridge.d.ts +0 -22
  84. package/lib/types/usage-contract.d.ts +0 -35
  85. package/lib/types/usage-display.d.ts +0 -4
  86. package/lib/types/usage.d.ts +0 -27
  87. /package/lib/types/{google-generative-ai.d.ts → google.d.ts} +0 -0
@@ -1,9 +1,89 @@
1
- import type { Api, Model, Provider } from './sdk-types.ts';
2
- import type { LlmDiscoveredModel } from '@deepseek-ai/dsh-llm';
3
- import { type GoModelCatalog } from './models-contract.ts';
4
- import type { ModelMetadata } from './model-metadata.ts';
5
- export { PROVIDER_ID, DISPLAY_NAME } from './provider-identity.ts';
6
- export { DEFAULT_BASE_URL } from './gateway-url.ts';
1
+ import { type LlmDiscoveredModel } from '@deepseek-ai/dsh-llm';
2
+ import type { Api, Model, ModelThinkingLevel, ThinkingBudgets, ThinkingLevelMap, Provider } from './sdk-types.ts';
3
+ import { type ThinkingBudgetRange, type GoModel, type OpencodeGoConfig, type GoModelCatalog } from './contracts.ts';
4
+ import { type ProxyTransport } from './transport.ts';
5
+ import type { Context } from '@deepseek-ai/cordis';
6
+ import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
7
+ export declare const THINKING_LEVELS: readonly ModelThinkingLevel[];
8
+ /** Protocol formats whose switch/budget is understood by pi-ai. */
9
+ export declare const NATIVE_THINKING_FLAGS: ReadonlySet<string>;
10
+ /** Expose budgets only when the SDK knows where to serialize a numeric limit. */
11
+ export declare function supportsThinkingBudget(api: Api, compat: Model<Api>['compat']): boolean;
12
+ export declare function reasoningBudgetRange(model: Model<Api>): ThinkingBudgetRange | undefined;
13
+ export declare function unsupportedThinkingLevels(): ThinkingLevelMap;
14
+ /** Exact model/protocol controls verified against OpenCode Go. */
15
+ export declare function withGatewayReasoning(model: Model<Api>): Model<Api>;
16
+ export declare function reasoningChoices(model: Model<Api>): readonly {
17
+ id: string;
18
+ name: string;
19
+ }[];
20
+ export type ReasoningIntent = {
21
+ kind: 'default';
22
+ } | {
23
+ kind: 'off';
24
+ } | {
25
+ kind: 'on';
26
+ } | {
27
+ kind: 'effort';
28
+ level: Exclude<ModelThinkingLevel, 'off'>;
29
+ } | {
30
+ kind: 'budget';
31
+ tokens: number;
32
+ min: number;
33
+ };
34
+ /** Called after validation against the model's choices. */
35
+ export declare function reasoningIntent(model: Model<Api>, level: string | undefined): ReasoningIntent;
36
+ /**
37
+ * The SDK serializes explicit choices. Default must leave all thinking controls
38
+ * to the service; a switch's On must not acquire an invented effort spelling.
39
+ */
40
+ export declare function reasoningRequest(intent: ReasoningIntent): {
41
+ reasoning?: Exclude<ModelThinkingLevel, 'off'>;
42
+ thinkingBudgets?: ThinkingBudgets;
43
+ onPayload: (payload: unknown) => unknown;
44
+ };
45
+ export declare const MODEL_METADATA_URL = "https://models.dev/api.json";
46
+ /** Lifecycle and capability data the online catalog adds to a gateway listing. */
47
+ export type ModelDetails = Pick<GoModel, 'deprecated' | 'releaseDate' | 'inputModalities'> & {
48
+ /**
49
+ * Present only when the upstream cost block is missing or carries a malformed
50
+ * component: its zeros are then indistinguishable from a genuinely free model,
51
+ * so analytics must treat the model as unpriced instead of pricing it at 0.
52
+ * A published block with legal components stays unmarked even when all zero.
53
+ */
54
+ readonly costKnown?: false;
55
+ };
56
+ export interface ModelMetadata {
57
+ readonly models: ReadonlyMap<string, Model<Api>>;
58
+ readonly details: ReadonlyMap<string, ModelDetails>;
59
+ readonly errors: ReadonlyMap<string, string>;
60
+ }
61
+ /** Select documented official protocol endpoints while preserving custom gateway prefixes. */
62
+ export declare function modelBaseURL(api: Api, baseURL: string): string;
63
+ /** Shared Responses defaults for declared models and explicit protocol overrides. */
64
+ export declare function responsesCompatibility(): NonNullable<Model<'openai-responses'>['compat']>;
65
+ /**
66
+ * Only read the opencode-go record. Online endpoints, headers and credentials
67
+ * are deliberately ignored: protocol endpoints are selected on the configured gateway.
68
+ * A bad entry is isolated instead of discarding every other model.
69
+ */
70
+ export declare function readModelMetadata(body: unknown, baseURL: string, builtin: ReadonlyMap<string, Model<Api>>): ModelMetadata;
71
+ export declare const MODEL_METADATA_MAX_BYTES: number;
72
+ export interface CachedMetadata {
73
+ readonly body: unknown;
74
+ readonly etag?: string;
75
+ /** Last successful download or HTTP 304 verification. */
76
+ readonly savedAtMs: number;
77
+ }
78
+ export declare function metadataCachePath(): string;
79
+ /** Only persist validators that can safely become an HTTP request header. */
80
+ export declare function metadataETag(value: unknown): string | undefined;
81
+ export declare function readMetadataCache(path: string): Promise<CachedMetadata | undefined>;
82
+ export declare function writeMetadataCache(path: string, value: CachedMetadata): Promise<boolean>;
83
+ /** Resolve a request's wire model without mutating the shared metadata catalog. */
84
+ export declare function withProtocolOverride(model: Model<Api>, config: OpencodeGoConfig): Model<Api>;
85
+ export { PROVIDER_ID, DISPLAY_NAME } from './contracts.ts';
86
+ export { DEFAULT_BASE_URL } from './contracts.ts';
7
87
  export interface CatalogSnapshot {
8
88
  readonly details: ModelMetadata['details'];
9
89
  readonly models: ReadonlyMap<string, Model<Api>>;
@@ -69,3 +149,29 @@ export declare class OpencodeGoCatalog {
69
149
  export declare function discoverCatalogModels(catalog: OpencodeGoCatalog): Promise<readonly LlmDiscoveredModel[]>;
70
150
  /** Settings expose the same retained catalog as requests, with a failed-refresh diagnostic. */
71
151
  export declare function discoverSettingsModels(catalog: OpencodeGoCatalog): Promise<GoModelCatalog>;
152
+ /** One mount owns discovery; inference, settings and pickers share its snapshots. */
153
+ export declare class GoCatalogManager {
154
+ private readonly options;
155
+ private current;
156
+ constructor(options: {
157
+ transport: ProxyTransport;
158
+ onFallback?: (detail: {
159
+ url: string;
160
+ error: unknown;
161
+ kept: number;
162
+ }) => void;
163
+ onOmitted?: (ids: readonly string[]) => void;
164
+ onRefresh?: () => void;
165
+ onWarning?: (warning: string) => void;
166
+ });
167
+ forConfig(config: OpencodeGoConfig): OpencodeGoCatalog;
168
+ }
169
+ /** Uses the same gateway snapshot as the adapter, including models hidden from pickers. */
170
+ export declare class GoModelsService extends TypertRemoteService {
171
+ private readonly options;
172
+ constructor(ctx: Context, options: {
173
+ catalog: () => OpencodeGoCatalog;
174
+ onRefresh?: () => void;
175
+ });
176
+ read(): Promise<GoModelCatalog>;
177
+ }
@@ -0,0 +1,25 @@
1
+ import type { AnalyticsQuery, AnalyticsReport, GoUsage } from '../contracts.ts';
2
+ import { type en } from './presentation.ts';
3
+ type AnalyticsKey = keyof typeof en;
4
+ export interface AnalyticsDialogProps {
5
+ open: boolean;
6
+ onClose: () => void;
7
+ /** The signal reaches the Host's cancellation parameter (review M4). */
8
+ readAnalytics: (query: AnalyticsQuery, signal?: AbortSignal) => Promise<AnalyticsReport>;
9
+ readQuota?: () => Promise<GoUsage>;
10
+ t: (key: AnalyticsKey) => string;
11
+ getLocale?: () => string;
12
+ }
13
+ /**
14
+ * Shared usage dashboard, opened from the composer pill and the settings card.
15
+ * It scans only when opened or when the range asks for it; closing the modal
16
+ * aborts the request. The window end is frozen once per open, so repeated
17
+ * requests inside one open share the Host's dedup key (review P5/S5), a range
18
+ * already seen in this open renders instantly and revalidates in the
19
+ * background (review P17), and while a scan runs the previous results stay
20
+ * visible under the newly selected range with an explicit annotation
21
+ * (review P19). Every number shown here comes from the same Host report as
22
+ * before; only the presentation and the palette are new.
23
+ */
24
+ export declare function AnalyticsDialog({ open, onClose, readAnalytics, readQuota, t, getLocale }: AnalyticsDialogProps): import("react").JSX.Element;
25
+ export {};
@@ -1,12 +1,56 @@
1
+ import { type en } from './presentation.ts';
2
+ import { type ReactNode } from 'react';
3
+ import type { GoAccountsActions, GoAccountsState, OpencodeGoModelLimit, OpencodeGoModelLimits, OpencodeGoModels, OpencodeGoSectionFace } from './controller.ts';
4
+ import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots';
5
+ export declare function HintMark(props: {
6
+ hint: string;
7
+ }): import("react").JSX.Element;
8
+ export declare function HintText(props: {
9
+ id: string;
10
+ hint: string;
11
+ }): import("react").JSX.Element;
1
12
  /**
2
- * The OpenCode Go settings page: provider activation, accounts and credentials,
3
- * available models and capacities, then advanced tuning. Account operations
4
- * apply immediately; tuning fields use the page's save/discard actions.
13
+ * The one place a style is chosen: four previews, each a miniature of the
14
+ * surface it selects, on the Settings page. The picker lives here rather than in
15
+ * the pill or the dashboard so a working session never changes its own look.
16
+ * @param props.t - copy lookup.
5
17
  */
6
- import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots';
7
- import type { OpencodeGoSectionFace } from './section-controller.ts';
8
- import type { en } from './locales.ts';
9
- export type { OpencodeGoSectionState } from './section-controller.ts';
18
+ export declare function ThemePicker({ t }: {
19
+ t: (key: keyof typeof en) => string;
20
+ }): import("react").JSX.Element;
21
+ type AccountTranslate = (key: keyof typeof en, params?: Record<string, unknown>) => string;
22
+ /**
23
+ * The account card: a folded header that summarizes the set, and one row per
24
+ * account inside. Rows keep the identity, key state, rolling quota and its reset
25
+ * countdown; everything else opens under the row. The handle is the drag source —
26
+ * dragging it, or the arrow keys on it, reorders the list, and the first row is
27
+ * the preferred account. Every row is read in the same pass, so the one refresh
28
+ * stamp belongs to the card and sits in its header.
29
+ */
30
+ export declare function AccountsCard({ state, actions, writable, t, locale }: {
31
+ state: GoAccountsState;
32
+ actions: GoAccountsActions;
33
+ writable: boolean;
34
+ t: AccountTranslate;
35
+ locale?: string;
36
+ }): import("react").JSX.Element;
37
+ type ModelTranslate = (key: keyof typeof en, params?: Record<string, unknown>) => string;
38
+ export declare function hasCapacityOverride(limit: OpencodeGoModelLimit | null | undefined): boolean;
39
+ /** Per-model switches apply immediately; capacity edits stay in the staged form. */
40
+ export declare function ModelEditor({ models, draft, modelVisibility, t, locale, disabled, visibilitySaving, filterAction, onEdit, onModelEnabled }: {
41
+ models: OpencodeGoModels;
42
+ draft: OpencodeGoModelLimits;
43
+ modelVisibility: Readonly<Record<string, boolean>>;
44
+ t: ModelTranslate;
45
+ locale?: string;
46
+ disabled: boolean;
47
+ visibilitySaving: boolean;
48
+ /** Optional control pinned to the right of the filter row, such as a refresh. */
49
+ filterAction?: ReactNode;
50
+ onEdit: (next: OpencodeGoModelLimits) => void;
51
+ onModelEnabled: (id: string, enabled: boolean) => void;
52
+ }): import("react").JSX.Element;
53
+ export type { OpencodeGoSectionState } from './controller.ts';
10
54
  /** Section copy lookup, including the optional `{name}` template params. */
11
55
  type SectionTranslate = (key: keyof typeof en, params?: Record<string, unknown>) => string;
12
56
  /** Injected dependencies of {@link OpencodeGoSection} (slot `inject`). */
@@ -1,12 +1,14 @@
1
1
  import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
2
2
  import type { ModelDirectoryState } from '@deepseek-ai/dsh-client-ui-model-selection/client';
3
- import { type GoUsage } from '../usage-contract.ts';
4
- import type { SettingsScope } from './settings.ts';
5
- import type { OpencodeGoSettings } from './section-controller.ts';
3
+ import { type GoUsage, type AnalyticsQuery, type AnalyticsReport } from '../contracts.ts';
4
+ import type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client';
5
+ import type { OpencodeGoSettings } from './controller.ts';
6
6
  export interface UsagePillProps {
7
7
  directory: SnapshotStore<ModelDirectoryState>;
8
- settings: SettingsScope<OpencodeGoSettings>;
8
+ settings: ConfigForm<OpencodeGoSettings>;
9
9
  readUsage: () => Promise<GoUsage>;
10
+ /** Optional so an embedded/test render can omit the dashboard. */
11
+ readAnalytics?: (query: AnalyticsQuery, signal?: AbortSignal) => Promise<AnalyticsReport>;
10
12
  t: (key: string) => string;
11
13
  getLocale?: () => string;
12
14
  credentialChanges?: SnapshotStore<number>;
@@ -0,0 +1,176 @@
1
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
2
+ import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
3
+ import { type SnapshotStore } from '@deepseek-ai/dsh-client-store';
4
+ import type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client';
5
+ import { type OpencodeGoSettings, type OpencodeGoModelLimits, type GoAccount, type GoModel, type GoModelCatalog, type GoUsage, type AnalyticsQuery, type AnalyticsReport, type AccountCommand, type SettingsWriteResult } from '../contracts.ts';
6
+ export type { OpencodeGoSettings, OpencodeGoModelLimit, OpencodeGoModelLimits } from '../contracts.ts';
7
+ export declare const OPENCODE_GO_NS = "llm-opencode-go";
8
+ export declare const TEXT_FIELDS: readonly ["usageDisplay", "protocolOverrides", "baseURL", "proxyURL", "refreshMinutes", "streamIdleTimeoutMs", "maxImages", "maxRequestImageBytes", "requestImagePixelBudget", "requestImageMaxBytes"];
9
+ export type TextField = typeof TEXT_FIELDS[number];
10
+ export type EditableField = TextField | 'modelLimits';
11
+ export interface FieldState {
12
+ text: string;
13
+ overridden: boolean;
14
+ invalid: boolean;
15
+ }
16
+ export interface FormActions {
17
+ edit(field: TextField, text: string): void;
18
+ editModelLimits(value: OpencodeGoModelLimits): void;
19
+ resetField(field: EditableField): void;
20
+ save(): void;
21
+ discard(): void;
22
+ }
23
+ interface FormShell {
24
+ available: boolean;
25
+ writable: boolean;
26
+ dirty: boolean;
27
+ invalid: boolean;
28
+ saving: boolean;
29
+ failed: boolean;
30
+ }
31
+ /** The gateway's model listing as the page reports it. */
32
+ export type OpencodeGoModels =
33
+ /** Not asked for yet; the page asks once it mounts. */
34
+ {
35
+ readonly status: 'idle';
36
+ }
37
+ /** A listing request is outstanding. */
38
+ | {
39
+ readonly status: 'loading';
40
+ }
41
+ /**
42
+ * The gateway answered: a count/preview for the compact summary plus every
43
+ * discovered entry used by the capacity editor.
44
+ */
45
+ | {
46
+ readonly status: 'ready';
47
+ readonly count: number;
48
+ readonly preview: readonly string[];
49
+ readonly entries: readonly GoModel[];
50
+ readonly stale?: boolean;
51
+ readonly message?: string;
52
+ readonly refreshing?: boolean;
53
+ readonly sources?: GoModelCatalog['sources'];
54
+ }
55
+ /** The listing could not be read; `message` is the Host's own diagnostic. */
56
+ | {
57
+ readonly status: 'failed';
58
+ readonly message?: string;
59
+ readonly sources?: GoModelCatalog['sources'];
60
+ };
61
+ export type ExecuteAccountCommand = (command: AccountCommand) => Promise<SettingsWriteResult>;
62
+ export interface GoAccountView extends GoAccount {
63
+ configured?: boolean;
64
+ writable?: boolean;
65
+ usage?: GoUsage;
66
+ updatedAt?: number;
67
+ stale?: boolean;
68
+ loading?: boolean;
69
+ failed?: boolean;
70
+ /** Why the last quota read failed, safe to show: it carries no credential value. */
71
+ problem?: string;
72
+ }
73
+ export interface GoAccountsState {
74
+ entries: readonly GoAccountView[];
75
+ activeRef: string;
76
+ autoSwitch: boolean;
77
+ busy: boolean;
78
+ blocked: boolean;
79
+ refreshing: boolean;
80
+ failure?: 'write' | 'cleanup' | 'remove' | 'read';
81
+ }
82
+ export interface GoAccountsActions {
83
+ loadAccounts: () => void;
84
+ addAccount: (name: string, key: string) => Promise<boolean>;
85
+ /** A newly opened addition form owns a fresh ID; retries keep its existing ID. */
86
+ resetAddition?: () => void;
87
+ renameAccount: (ref: string, name: string) => Promise<boolean>;
88
+ removeAccount: (ref: string) => Promise<boolean>;
89
+ selectAccount: (ref: string) => Promise<boolean>;
90
+ setAutoSwitch: (next: boolean) => Promise<boolean>;
91
+ replaceAccountKey: (ref: string, key: string) => Promise<boolean>;
92
+ /** Move one account to a new position; the first row becomes the preferred account. */
93
+ moveAccount: (ref: string, toIndex: number) => Promise<boolean>;
94
+ }
95
+ export interface OpencodeGoSectionState extends FormShell {
96
+ accounts: GoAccountsState;
97
+ enabled: boolean;
98
+ usageDisplay: FieldState;
99
+ protocolOverrides: FieldState;
100
+ modelVisibility: Readonly<Record<string, boolean>>;
101
+ pickerSaving: boolean;
102
+ pickerFailed: boolean;
103
+ baseURL: FieldState;
104
+ proxyURL: FieldState;
105
+ refreshMinutes: FieldState;
106
+ streamIdleTimeoutMs: FieldState;
107
+ maxImages: FieldState;
108
+ maxRequestImageBytes: FieldState;
109
+ requestImagePixelBudget: FieldState;
110
+ requestImageMaxBytes: FieldState;
111
+ models: OpencodeGoModels;
112
+ modelLimits: Omit<FieldState, 'text'>;
113
+ modelLimitDraft: OpencodeGoModelLimits;
114
+ }
115
+ export interface OpencodeGoSectionFace extends FormActions, GoAccountsActions {
116
+ hooks: {
117
+ opencodeGo: SnapshotStore<OpencodeGoSectionState>;
118
+ };
119
+ loadModels(): void;
120
+ readAnalytics(query: AnalyticsQuery, signal?: AbortSignal): Promise<AnalyticsReport>;
121
+ readQuota(ref: string): Promise<GoUsage>;
122
+ setEnabled(next: boolean): void;
123
+ setModelEnabled(id: string, next: boolean): void;
124
+ }
125
+ /** One controller owns the page's typed drafts and immediate account operations. */
126
+ export declare class OpencodeGoSectionController {
127
+ private readonly scope;
128
+ private readonly ctx;
129
+ private readonly readModels;
130
+ private readonly readUsage;
131
+ private readonly executeAccountCommand;
132
+ private readonly readAnalytics;
133
+ private readonly drafts;
134
+ private readonly store;
135
+ private readonly unsubscribe;
136
+ private saving;
137
+ private failed;
138
+ private pickerSaving;
139
+ private pickerFailed;
140
+ private models;
141
+ private modelsRequest;
142
+ private face;
143
+ private accountRows;
144
+ private accountBusy;
145
+ private accountRefreshing;
146
+ private accountFailure;
147
+ private accountEpoch;
148
+ private accountsIdentity;
149
+ private accountsLoaded;
150
+ private disposed;
151
+ private addition;
152
+ constructor(scope: ConfigForm<OpencodeGoSettings>, ctx: ClientContext, readModels?: () => Promise<RemoteResult<GoModelCatalog>>, readUsage?: (ref: string) => Promise<GoUsage>, executeAccountCommand?: ExecuteAccountCommand, readAnalytics?: (query: AnalyticsQuery, signal?: AbortSignal) => Promise<AnalyticsReport>);
153
+ dispose(): void;
154
+ private publish;
155
+ private blocked;
156
+ private stored;
157
+ private value;
158
+ private field;
159
+ private plan;
160
+ private projection;
161
+ private edit;
162
+ save(): Promise<void>;
163
+ setEnabled(next: boolean): Promise<void>;
164
+ setModelEnabled(id: string, next: boolean): Promise<void>;
165
+ private writePickerSetting;
166
+ inject(): OpencodeGoSectionFace;
167
+ loadModels(): void;
168
+ accountState(): GoAccountsState;
169
+ syncAccounts(): void;
170
+ refreshCredential(ref: string): void;
171
+ refreshAccounts(): Promise<void>;
172
+ /** Mark every account row as unreadable with the Host's own diagnostic. */
173
+ private markUnreadable;
174
+ accountActions(): GoAccountsActions;
175
+ private runAccountAction;
176
+ }
@@ -1,12 +1,7 @@
1
- /**
2
- * OpenCode Go settings plugin, browser half. Registers the "OpenCode Go"
3
- * settings page over the `llm-opencode-go` namespace: the API key (stored
4
- * write-only through the credentials domain), the gateway's current model
5
- * listing, and the adapter knobs behind the page's advanced disclosure. The
6
- * Host settings and credential contracts stay behind their existing wire APIs.
7
- */
8
- import type { Context as ClientContext } from '@deepseek-ai/cordis';
9
- import { en } from './locales.ts';
1
+ import type { Context as ClientContext, Context } from '@deepseek-ai/cordis';
2
+ import type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client';
3
+ import { type OpencodeGoSettings, type ExecuteAccountCommand } from './controller.ts';
4
+ import { en } from './presentation.ts';
10
5
  declare module '@deepseek-ai/dsh-client-ui-slots' {
11
6
  interface LocaleNamespaceMap {
12
7
  /** The OpenCode Go settings page copy. */
@@ -14,9 +9,9 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
14
9
  }
15
10
  }
16
11
  export type { OpencodeGoSectionProps } from './Section.tsx';
17
- export type { OpencodeGoSectionState, OpencodeGoSettings } from './section-controller.ts';
18
- export { OPENCODE_GO_NS } from './section-controller.ts';
19
- export type { OpencodeGoKey } from './locales.ts';
12
+ export type { OpencodeGoSectionState, OpencodeGoSettings } from './controller.ts';
13
+ export { OPENCODE_GO_NS } from './controller.ts';
14
+ export type { OpencodeGoKey } from './presentation.ts';
20
15
  /**
21
16
  * Required services (cordis fiber inject). The target slot is declared by
22
17
  * ui-settings' apply, whose activation order relative to this one is NOT
@@ -32,3 +27,5 @@ export declare const inject: string[];
32
27
  * @param ctx - client root context.
33
28
  */
34
29
  export declare function apply(ctx: ClientContext): void;
30
+ export declare function accountCommands(ctx: Context): ExecuteAccountCommand;
31
+ export declare function registerUsagePill(ctx: Context, settings: ConfigForm<OpencodeGoSettings>, selectAccount?: (ref: string) => Promise<boolean>): void;
@@ -1,3 +1,5 @@
1
+ /** English and Chinese copy, palette tokens and local theme preferences. */
2
+ import { type CSSProperties } from 'react';
1
3
  /** Copy dictionaries for the OpenCode Go settings page. English is the key-set source of truth. */
2
4
  export declare const en: {
3
5
  accountsTitle: string;
@@ -59,6 +61,77 @@ export declare const en: {
59
61
  usageLastUpdated: string;
60
62
  usageRetry: string;
61
63
  usageRefreshing: string;
64
+ analyticsOpen: string;
65
+ analyticsTitle: string;
66
+ analyticsSubtitle: string;
67
+ analyticsClose: string;
68
+ analyticsRange: string;
69
+ analyticsRangeToday: string;
70
+ analyticsRange7d: string;
71
+ analyticsRange30d: string;
72
+ analyticsRange90d: string;
73
+ analyticsRefresh: string;
74
+ analyticsRetry: string;
75
+ analyticsLoading: string;
76
+ analyticsEmpty: string;
77
+ analyticsUnsupported: string;
78
+ analyticsFailed: string;
79
+ analyticsRequests: string;
80
+ analyticsTokens: string;
81
+ analyticsSpend: string;
82
+ analyticsCoverage: string;
83
+ analyticsSessions: string;
84
+ analyticsSeconds: string;
85
+ analyticsSummaries: string;
86
+ analyticsUnsettled: string;
87
+ analyticsByModel: string;
88
+ analyticsByDay: string;
89
+ analyticsInput: string;
90
+ analyticsOutput: string;
91
+ analyticsCacheRead: string;
92
+ analyticsPriced: string;
93
+ analyticsUnpriced: string;
94
+ analyticsMissing: string;
95
+ analyticsFailedSessions: string;
96
+ analyticsUnattributed: string;
97
+ analyticsUnread: string;
98
+ analyticsScanSegments: string;
99
+ analyticsStaleResults: string;
100
+ analyticsTruncated: string;
101
+ analyticsScanMore: string;
102
+ analyticsPriceSource: string;
103
+ analyticsNotInvoice: string;
104
+ analyticsPricingUnavailable: string;
105
+ analyticsLegacy: string;
106
+ analyticsCardTitle: string;
107
+ analyticsCardHint: string;
108
+ analyticsBoardLabel: string;
109
+ analyticsOpenBoard: string;
110
+ analyticsQuota: string;
111
+ analyticsQuotaHint: string;
112
+ analyticsQuotaFailed: string;
113
+ analyticsChartSpend: string;
114
+ analyticsChartTokens: string;
115
+ analyticsKicker: string;
116
+ analyticsLead: string;
117
+ analyticsLeadTop: string;
118
+ analyticsComposition: string;
119
+ analyticsCompositionHint: string;
120
+ analyticsCompositionOther: string;
121
+ analyticsCompositionFree: string;
122
+ analyticsModel: string;
123
+ analyticsCost: string;
124
+ analyticsShare: string;
125
+ analyticsCacheHit: string;
126
+ analyticsDailyAverage: string;
127
+ analyticsPeak: string;
128
+ analyticsTotal: string;
129
+ themeLabel: string;
130
+ themeSilentBlack: string;
131
+ themeGraphite: string;
132
+ themeSeaSalt: string;
133
+ themeWarmSand: string;
134
+ themeHint: string;
62
135
  nav: string;
63
136
  title: string;
64
137
  titleLabel: string;
@@ -183,3 +256,54 @@ export declare const en: {
183
256
  export declare const zh: typeof en;
184
257
  /** Every copy key this page's dictionaries must supply. */
185
258
  export type OpencodeGoKey = keyof typeof en;
259
+ /** One palette's six theme colors plus the neutral surface steps. */
260
+ export interface GoThemeTokens {
261
+ readonly bg: string;
262
+ readonly surface: string;
263
+ readonly surface2: string;
264
+ readonly border: string;
265
+ readonly text: string;
266
+ readonly muted: string;
267
+ readonly accent: string;
268
+ readonly accent2: string;
269
+ readonly success: string;
270
+ readonly warning: string;
271
+ readonly danger: string;
272
+ }
273
+ /** The four selectable styles. */
274
+ export declare const GO_THEMES: readonly ["silent-black", "graphite", "sea-salt", "warm-sand"];
275
+ export type GoThemeId = typeof GO_THEMES[number];
276
+ /** Graphite is the default: it is the quietest match for the Host chrome. */
277
+ export declare const DEFAULT_GO_THEME: GoThemeId;
278
+ /** Locale key carrying each theme's display name. */
279
+ export declare const GO_THEME_LABELS: Record<GoThemeId, keyof typeof en>;
280
+ /** Each style in both Host color schemes. */
281
+ export declare const GO_THEME_TOKENS: Record<GoThemeId, {
282
+ dark: GoThemeTokens;
283
+ light: GoThemeTokens;
284
+ }>;
285
+ /** The selected style, stable until the next write. */
286
+ export declare function getGoTheme(): GoThemeId;
287
+ /**
288
+ * Select a style and persist it for this browser.
289
+ * @param id - one of {@link GO_THEMES}; unknown ids are ignored.
290
+ */
291
+ export declare function setGoTheme(id: GoThemeId): void;
292
+ /** Subscribe to style changes (for useSyncExternalStore). */
293
+ export declare function subscribeGoTheme(listener: () => void): () => void;
294
+ /** Read the selected style in a component. */
295
+ export declare function useGoTheme(): GoThemeId;
296
+ /**
297
+ * Follow the Host's light/dark scheme. The layout presenter marks a dark body
298
+ * with `data-ds-dark-theme`; the attribute is observed so switching the Host
299
+ * theme updates the surfaces without a reload.
300
+ */
301
+ export declare function useHostScheme(): 'dark' | 'light';
302
+ /** The active style's tokens for the Host's current scheme. */
303
+ export declare function useGoThemeTokens(): GoThemeTokens;
304
+ /**
305
+ * Inline custom properties consumed by the pill and dialog styles.
306
+ * @param tokens - the active palette.
307
+ * @returns a style object carrying every `--go-*` variable.
308
+ */
309
+ export declare function themeStyle(tokens: GoThemeTokens): CSSProperties;
@@ -1,16 +1,8 @@
1
- /**
2
- * Configuration schema for the OpenCode Go adapter plugin. The section is
3
- * installed under the `llm-opencode-go` settings namespace on DSH 0.1.5/0.1.6.
4
- * DSH 0.1.7 edits the `opencode-go` profile entry through live references.
5
- * Both paths update field by field without a restart. Self-contained constraints
6
- * (URL shape, numeric bounds) fail at load for the composition layer and
7
- * refuse the write for the settings layer.
8
- *
9
- * @module dsh-llm-opencode-go/config
10
- */
1
+ /** Live profile configuration, validation and settings presentation. */
11
2
  import z from '@deepseek-ai/schemastery';
12
- import type { OpencodeGoConfig } from './config-contract.ts';
13
- export type { OpencodeGoConfig, OpencodeGoModelLimit, OpencodeGoModelLimits } from './config-contract.ts';
3
+ import { type OpencodeGoConfig } from './contracts.ts';
4
+ import type { Context } from '@deepseek-ai/cordis';
5
+ export type { OpencodeGoConfig, OpencodeGoModelLimit, OpencodeGoModelLimits } from './contracts.ts';
14
6
  /** Environment variable resolving the OpenCode API key. */
15
7
  export declare const DEFAULT_API_KEY_ENV = "OPENCODE_API_KEY";
16
8
  /** Successful refresh lifetime; failed refreshes retry sooner and explicit discovery revalidates immediately. */
@@ -19,9 +11,9 @@ export declare const DEFAULT_REFRESH_MINUTES = 60;
19
11
  export declare const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300000;
20
12
  export declare const DEFAULT_REQUEST_PREPARATION_TIMEOUT_MS = 60000;
21
13
  export declare const DEFAULT_REQUEST_TIMEOUT_MS: number;
22
- /** Plain values used by the adapter and by pre-0.1.7 settings documents. */
14
+ /** Plain configuration values used by validation and direct adapter consumers. */
23
15
  export declare const PlainConfig: z<OpencodeGoConfig>;
24
- /** 0.1.7's Loader retains these references when profile fields change. */
16
+ /** The Loader retains these references when profile fields change. */
25
17
  export type LiveConfig = {
26
18
  [K in keyof OpencodeGoConfig]-?: {
27
19
  get(): OpencodeGoConfig[K];
@@ -46,3 +38,6 @@ export declare function assertBaseURL(raw: string): string;
46
38
  * @param raw - the configured credential reference.
47
39
  */
48
40
  export declare function assertApiKeyEnv(raw: string): void;
41
+ export declare function validateGoConfig(value: OpencodeGoConfig): void;
42
+ /** DSH profile forms edit the plugin's live Config fields directly. */
43
+ export declare function installHostSettings(ctx: Context): void;