From c6bb154c224c209ca467b3d54330daaaf9f110ed Mon Sep 17 00:00:00 2001 From: flyingcoding <54491871+flyingcoding@users.noreply.github.com> Date: Fri, 28 Aug 2026 12:35:15 +0800 Subject: [PATCH] Adapt to DeepSeek Harness 0.1.2-alpha.1 --- AGENTS.md | 10 +++----- CHANGELOG.md | 4 +++ package-lock.json | 40 ++++++++++++++++++----------- package.json | 44 +++++++++++++++++++------------- src/adapter.ts | 10 +++++--- src/client-store.d.ts | 15 +++++++++++ src/client/index.ts | 49 ++++++++++++++++++++--------------- src/client/settings.ts | 58 +++++++++++++++++++++++++++++++----------- tests/card.test.ts | 12 ++++----- tests/settings.test.ts | 28 +++++++++----------- tsdown.config.ts | 2 +- 11 files changed, 172 insertions(+), 100 deletions(-) create mode 100644 src/client-store.d.ts diff --git a/AGENTS.md b/AGENTS.md index 4b0a421..d31ca54 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,8 +30,7 @@ src/usage-remote.ts Host half of the usage Remote: `commandcodeUsage` src/client/index.ts Browser client entry: registers the "Command Code" settings page (settings.section, id `commandcode`) and the Models-page provider card - (settings.models.provider-card, key `llm-commandcode`), - and installs the friendly image-gate error wrapper. + (settings.models.provider-card, key `llm-commandcode`). src/client/settings.ts Settings-page controller (scope + credentials + staged form; React-free so node tests can drive it). src/client/usage.ts Account-card controller (Remote fetch lifecycle + @@ -56,7 +55,6 @@ src/client/locales.ts zh/en copy + LocaleNamespaceMap augmentation. tests/adapter.test.ts Core adapter unit tests (node:test + tsx). tests/accounts.test.ts Account-pool rotation tests. tests/commands.test.ts getUsage + command tests (stubbed fetch, no network). -tests/client.test.ts sessions-wrapper tests. tests/settings.test.ts settings-page controller tests. tests/card.test.ts Models-page provider-card tests (posture logic, key write path, login affordance parity). @@ -80,10 +78,10 @@ tsdown.config.ts Build config (tsdown -> lib/, ESM, .d.ts + client.js). `react/jsx-runtime`, `@deepseek-ai/cordis`, `@deepseek-ai/dsh-client-ui-slots`, `@deepseek-ai/dsh-client-web-react`, `@deepseek-ai/dsh-client-ui-primitives`, `@deepseek-ai/dsh-client-schema-form`, `@deepseek-ai/dsh-client-ui-attachment`) - and host-shipped client bundles resolvable from the loader's module table - (e.g. `@deepseek-ai/dsh-client-runtime/client`). The settings page binds the + and host-shipped platform modules resolvable from the loader's module table + (e.g. `@deepseek-ai/dsh-client-store`). The settings page binds the `llm-commandcode` namespace through `ctx.settingsScope` and writes the API - key through `connection.api.credentials` under the `COMMANDCODE_API_KEY` + key through `ctx.remote.credentials` under the `COMMANDCODE_API_KEY` reference — never through the settings section, so the key literal cannot leak into a settings document. `tests/settings.test.ts` pins this contract. - **Models-page provider card (`settings.models.provider-card`)**: a keyed diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a4ae0c..0aef9b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [Unreleased] +### Changed + +- **Adapted the provider to DeepSeek Harness 0.1.2-alpha.1.** Tool-call IDs now use the current branded chunk vocabulary, credential operations use Typert Remotes, the browser client consumes the new `dsh-client-store` platform module, and package metadata no longer references the removed `dsh-client-runtime` package. + ## [0.9.1] - 2026-08-28 ### Added diff --git a/package-lock.json b/package-lock.json index 5644d01..e5dd8c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", @@ -24,6 +23,7 @@ "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6", + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6", "@deepseek-ai/schemastery": "^3.18.1", "@types/node": "^22.0.0", "@types/react": "^18.3.1", @@ -36,22 +36,32 @@ }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6", - "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6", + "@deepseek-ai/dsh-api-remotes": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-attachment": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-connection": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-store": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-commands": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-credentials": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-launch-environment": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-llm": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-settings": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-timeout": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-typert-protocol": "^0.1.2-alpha.1", "@deepseek-ai/schemastery": "^3.18.1", "react": "^18.2.0" + }, + "peerDependenciesMeta": { + "@deepseek-ai/dsh-client-store": { + "optional": true + }, + "@deepseek-ai/dsh-client-ui-renderer": { + "optional": true + } } }, "node_modules/@deepseek-ai/cordis": { diff --git a/package.json b/package.json index d19cfa3..679f832 100644 --- a/package.json +++ b/package.json @@ -23,13 +23,13 @@ "client": { "inject": [ "@deepseek-ai/dsh-client-connection", - "@deepseek-ai/dsh-client-runtime", "@deepseek-ai/dsh-client-locale", + "@deepseek-ai/dsh-client-ui-renderer", "@deepseek-ai/dsh-client-ui-settings", "@deepseek-ai/dsh-api-remotes" ], "external": [ - "@deepseek-ai/dsh-client-runtime/client" + "@deepseek-ai/dsh-client-store" ], "platform": "web" } @@ -78,31 +78,39 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6 || ^0.1.1-rc.1", - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6 || ^0.1.1-rc.1", + "@deepseek-ai/dsh-api-remotes": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-attachment": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-connection": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-store": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-commands": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-credentials": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-launch-environment": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-llm": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-settings": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-timeout": "^0.1.2-alpha.1", + "@deepseek-ai/dsh-typert-protocol": "^0.1.2-alpha.1", "@deepseek-ai/schemastery": "^3.18.1", "react": "^18.2.0" }, + "peerDependenciesMeta": { + "@deepseek-ai/dsh-client-store": { + "optional": true + }, + "@deepseek-ai/dsh-client-ui-renderer": { + "optional": true + } + }, "devDependencies": { "@deepseek-ai/cordis": "^4.0.1", "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", diff --git a/src/adapter.ts b/src/adapter.ts index 970ac86..a120192 100644 --- a/src/adapter.ts +++ b/src/adapter.ts @@ -30,7 +30,6 @@ import type { AttachmentStore, ImageAttachmentRef } from '@deepseek-ai/dsh-attac import { attributionHeaders, - CallId, LlmAdapter, LlmError, ReasoningEffortId, @@ -49,6 +48,11 @@ import { } from '@deepseek-ai/dsh-llm' import { RETRY_MAX_DELAY_MS } from './accounts.ts' +/** Brand a provider-issued tool-call id through the active harness chunk vocabulary. */ +function toolCallId(id: string): Extract['id'] { + return id as Extract['id'] +} + // --------------------------------------------------------------------------- // Static capability snapshot (from the official command-code@1.37.0 bundled // model catalog, dist/cli.mjs). The Provider API does not expose reasoning @@ -1782,11 +1786,11 @@ export class CommandCodeAdapter { + getSnapshot(): T + subscribe(listener: () => void): () => void + set(value: T): void + } + + /** Create one observable snapshot store. */ + export function createSnapshotStore(initial: T): SnapshotStore +} + +/** Type-only module marker for the 0.1.2 renderer service augmentation. */ +declare module '@deepseek-ai/dsh-client-ui-renderer/client' diff --git a/src/client/index.ts b/src/client/index.ts index 3d0e013..d10aec0 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -8,31 +8,31 @@ * unknown-adapter-family card for the `commandcode` provider and disables * its submit, so the API key cannot be configured there; this page is the * dedicated surface. It writes the API key through the credentials domain - * (the `COMMANDCODE_API_KEY` reference the plugin resolves) and the - * connection facts through the `llm-commandcode` settings namespace, so a - * saved key or endpoint reaches the very next request. + * (the `COMMANDCODE_API_KEY` reference the plugin resolves via + * `ctx.remote.credentials`) and the connection facts through the + * `llm-commandcode` settings namespace, so a saved key or endpoint reaches + * the very next request. * - * 2. The friendly-error wrapper for the harness's image-session gate — see - * `./sessions.ts`. The wrapper is deliberately narrow: only the - * `model-unavailable` code is rewritten, only when the message matches the - * image-session gate, and only the message text changes. - * - * The wire types are spelled structurally in `./sessions.ts` (not imported - * from `@deepseek-ai/dsh-host-apiproxy`) so this client bundle does not drag - * an extra peer dependency into the package; the shapes are stable and the - * client build inlines them anyway. + * 2. The Models-page provider card (settings.models.provider-card) and the + * friendly image-gate error wrapper — see `./card.tsx` / `./sessions.ts`. + * The wrapper is deliberately narrow: only the `model-unavailable` code is + * rewritten, only when the message matches the image-session gate, and only + * the message text changes. */ import type { Context } from '@deepseek-ai/cordis' -import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client' +import { createSnapshotStore } from '@deepseek-ai/dsh-client-store' // Type-only imports that pull in the client-service augmentations // (`slots`/`remote`/`locale` on Context) and the `settings.section` SlotMap // entry (`settingsScope` arrives through dsh-client-ui-settings). import type {} from '@deepseek-ai/dsh-api-remotes/client' import type {} from '@deepseek-ai/dsh-client-locale/client' +import type {} from '@deepseek-ai/dsh-client-ui-renderer/client' import type {} from '@deepseek-ai/dsh-client-ui-settings/client' import { installFriendlyImageError } from './sessions.ts' +import type { ConnectionLike } from './sessions.ts' import { CommandCodeSettingsController, COMMANDCODE_NS, type SettingsPageState } from './settings.ts' +import type { SettingsPageApi } from './settings.ts' import { CommandCodeUsageController, type UsagePageState, type UsageRemote } from './usage.ts' import { CommandCodeLoginController, type LoginPageState, type LoginRemote } from './login.ts' import { USAGE_REMOTE_CONTRIBUTION } from '../usage-wire.ts' @@ -43,7 +43,6 @@ import { CommandCodeProviderCard } from './card.tsx' import { zh, en } from './locales.ts' export { isImageSessionRejection, withFriendlyImageError } from './sessions.ts' -import type { ConnectionLike } from './sessions.ts' /** CSS for the settings page, injected once (harness bundle convention). */ const PAGE_CSS = ` @@ -165,9 +164,9 @@ function injectPageCss(): void { /** * Client plugin body. Gates on the services the settings page needs - * (`slots`, `locale`, `connection`, `remote`, `settingsScope`) plus the - * `connection` used by the friendly-error wrapper — the same inject list the - * harness's own settings-surface plugins declare. + * (`slots`, `locale`, `connection`, `remote`, `remote.credentials`, + * `settingsScope`) — the same inject list the harness's own settings-surface + * plugins declare, plus the credential Remote that 0.1.2 introduces. */ export function apply(ctx: Context): void { injectPageCss() @@ -188,13 +187,22 @@ export function apply(ctx: Context): void { // `slots.inject` waits for the declaration). ctx.effect(() => ctx.locale.register('settings.commandcode', { zh, en }), 'dsh-commandcode-provider: page copy') - const api = ctx.get('connection').api - const hostDescription = ctx.get('connection').hostDescription const scope = ctx.settingsScope.bind>({ namespace: COMMANDCODE_NS }) - const controller = new CommandCodeSettingsController(scope, { credentials: api.credentials }, hostDescription) + const credentialRemote = (ctx.remote as unknown as { credentials: SettingsPageApi['credentials'] }).credentials + // Preserve hostDescription (cwd placeholder) when the Host still exposes it; + // 0.1.2 may no longer provide it, so the field is optional and the page + // degrades to no placeholder. + const hostDescription = (ctx.get('connection') as unknown as { hostDescription?: { getSnapshot(): { cwd?: string } | undefined; subscribe(fn: () => void): () => void } } | undefined)?.hostDescription + const controller = new CommandCodeSettingsController(scope, { credentials: credentialRemote }, hostDescription) ctx.effect(() => () => controller.dispose(), 'dsh-commandcode-provider: settings controller') const store = createSnapshotStore(controller.state()) controller.subscribe(() => store.set(controller.state())) + ctx.effect( + () => (ctx.remote as unknown as { + $on(event: 'credentials/reference-updated', listener: (ref: string) => void): () => void + }).$on('credentials/reference-updated', () => { controller.refreshCredentials() }), + 'dsh-commandcode-provider: credential invalidations', + ) // The account-usage card + login panel: mount the shared Remote contribution // (one mount carries every endpoint this plugin serves — report and login — @@ -355,5 +363,6 @@ export const inject: readonly string[] = [ 'locale', 'connection', 'remote', + 'remote.credentials', 'settingsScope', ] diff --git a/src/client/settings.ts b/src/client/settings.ts index dfb3bb9..f6c1e10 100644 --- a/src/client/settings.ts +++ b/src/client/settings.ts @@ -26,22 +26,50 @@ * the React component renders. */ -import type { SettingsScope } from '@deepseek-ai/dsh-client-runtime/client' - /** The settings namespace the plugin registers (host half, src/index.ts). */ export const COMMANDCODE_NS = 'llm-commandcode' /** Default credential reference the plugin resolves when none is named. */ export const DEFAULT_API_KEY_REF = 'COMMANDCODE_API_KEY' +/** The settings-scope snapshot fields consumed by this controller. */ +export interface SettingsScopeSnapshot { + status: 'loading' | 'ready' | 'unavailable' + value: T | undefined + base: unknown + user: unknown + revision: number | undefined + writable: boolean + mode: 'host' | 'memory' +} + +/** Current settings-scope service face used without importing a browser plugin value. */ +export interface SettingsScope { + getSnapshot(): SettingsScopeSnapshot + subscribe(listener: () => void): () => void + set(field: string, value: unknown): Promise + unset(field: string): Promise +} + +/** Result envelope returned by one current Typert Remote call. */ +interface RemoteResult { + ok: boolean + value?: T + error?: { message: string } +} + +/** Credential facts returned without exposing the credential value. */ +interface CredentialInfo { + configured: boolean + writable: boolean +} + /** The narrow slice of the wire face this controller needs. */ export interface SettingsPageApi { + /** Credential methods exposed by the current Typert Remote namespace. */ credentials: { - describe(request: { refs: string[] }): Promise<{ - result: { ok: true; value: { credentials: Record } } | { ok: false; error: { message: string } } - }> - set(request: { ref: string; value: string }): Promise<{ result: { ok: true; value?: unknown } | { ok: false; error: { message: string } } }> - /** Remove one stored credential entirely (the Host's `credentials.unset`). */ - unset(request: { ref: string }): Promise<{ result: { ok: true; value?: unknown } | { ok: false; error: { message: string } } }> + describe(refs: string[]): Promise>> + set(ref: string, value: string): Promise> + unset(ref: string): Promise> } } @@ -664,8 +692,8 @@ export class CommandCodeSettingsController { /** Write one account's key, then re-read the Host's credential states. */ private async writeKeyTo(ref: string, value: string): Promise { try { - const response = await this.api.credentials.set({ ref, value }) - if (!response.result.ok) return false + const response = await this.api.credentials.set(ref, value) + if (!response.ok) return false } catch { return false } @@ -682,14 +710,14 @@ export class CommandCodeSettingsController { ] let response: Awaited> try { - response = await this.api.credentials.describe({ refs }) + response = await this.api.credentials.describe(refs) } catch { return } - if (!response.result.ok) return + if (!response.ok) return let changed = false for (const ref of refs) { - const view = response.result.value.credentials[ref] + const view = response.value?.[ref] const next = { configured: view?.configured ?? false, writable: view?.writable ?? true, @@ -780,8 +808,8 @@ export class CommandCodeSettingsController { /** Unset one stored credential, then re-read the Host's credential states. */ private async unsetKey(ref: string): Promise { try { - const response = await this.api.credentials.unset({ ref }) - if (!response.result.ok) return false + const response = await this.api.credentials.unset(ref) + if (!response.ok) return false } catch { return false } diff --git a/tests/card.test.ts b/tests/card.test.ts index 8121005..3d1daca 100644 --- a/tests/card.test.ts +++ b/tests/card.test.ts @@ -78,20 +78,20 @@ function makeScope(init: { function makeApi(init: { store?: Map }) { const store = init.store ?? new Map() const credentials = { - describe: async ({ refs }: { refs: string[] }) => { + describe: async (refs: string[]) => { const map: Record = {} for (const ref of refs) { map[ref] = { configured: store.has(ref), writable: true } } - return { result: { ok: true as const, value: { credentials: map } } } + return { ok: true as const, value: map } }, - set: async ({ ref, value }: { ref: string; value: string }) => { + set: async (ref: string, value: string) => { store.set(ref, value) - return { result: { ok: true as const, value: {} } } + return { ok: true as const, value: undefined } }, - unset: async ({ ref }: { ref: string }) => { + unset: async (ref: string) => { store.delete(ref) - return { result: { ok: true as const, value: {} } } + return { ok: true as const, value: undefined } }, } return { credentials, store } diff --git a/tests/settings.test.ts b/tests/settings.test.ts index 0a32d7b..c2daa53 100644 --- a/tests/settings.test.ts +++ b/tests/settings.test.ts @@ -78,7 +78,7 @@ function makeApi(init: { configured?: boolean; writable?: boolean; store?: Map { + describe: async (refs: string[]) => { const credentialsMap: Record = {} for (const ref of refs) { credentialsMap[ref] = { @@ -86,17 +86,17 @@ function makeApi(init: { configured?: boolean; writable?: boolean; store?: Map { - if (init.failSet === true) return { result: { ok: false as const, error: { message: 'write refused' } } } + set: async (ref: string, value: string) => { + if (init.failSet === true) return { ok: false as const, error: { message: 'write refused' } } store.set(ref, value) - return { result: { ok: true as const, value: {} } } + return { ok: true as const, value: undefined } }, - unset: async ({ ref }: { ref: string }) => { - if (init.failUnset === true) return { result: { ok: false as const, error: { message: 'unset refused' } } } + unset: async (ref: string) => { + if (init.failUnset === true) return { ok: false as const, error: { message: 'unset refused' } } store.delete(ref) - return { result: { ok: true as const, value: {} } } + return { ok: true as const, value: undefined } }, } return { credential, credentials, store } @@ -593,16 +593,12 @@ test('a failed key write aborts the save before the accounts list lands', async const store = new Map() const api = { credentials: { - describe: async ({ refs }: { refs: string[] }) => ({ - result: { - ok: true as const, - value: { - credentials: Object.fromEntries(refs.map((ref) => [ref, { configured: store.has(ref), writable: true }])), - }, - }, + describe: async (refs: string[]) => ({ + ok: true as const, + value: Object.fromEntries(refs.map((ref) => [ref, { configured: store.has(ref), writable: true }])), }), // The credentials domain rejects every write. - set: async () => ({ result: { ok: false as const, error: { message: 'read-only' } } }), + set: async () => ({ ok: false as const, error: { message: 'read-only' } }), }, } const { controller } = makeController({ scope, api: api as unknown as ReturnType }) diff --git a/tsdown.config.ts b/tsdown.config.ts index 1db527a..c050359 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -50,7 +50,7 @@ const client = defineConfig({ '@deepseek-ai/cordis', 'react', 'react/jsx-runtime', - '@deepseek-ai/dsh-client-runtime/client', + '@deepseek-ai/dsh-client-store', '@deepseek-ai/dsh-client-ui-primitives', ], outputOptions: {