Merge remote-tracking branch 'origin/worktree-llm-web-config' into worktree/onboarding-deepseek-config

# Conflicts:
#	packages/client/ui-models/README.i18n.yaml
#	packages/client/ui-models/README.md
#	packages/client/ui-models/README.zh.md
#	packages/client/ui-models/src/client/store.ts
#	packages/client/ui-models/tests/components.spec.tsx
This commit is contained in:
Yichen Jiang
2026-07-30 20:55:12 +08:00
535 changed files with 12376 additions and 4880 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ export type {
ModelCatalogFailure, ModelCatalogModel, ModelProviderGroup, ModelReasoning,
InboxItemId, ModelReasoningEffort, ModelTarget, QueueAction, QueuedInboxItem, SessionModels,
GoalsApi, GoalRef,
SettingsApi, SettingsNamespaceView, SettingsSecretView,
SettingsApi, SettingsNamespaceView, SettingsPathOpView, SettingsSecretView,
CredentialsApi, CredentialView, ConfigurableProviderView, LlmApi,
} from '@deepseek-ai/dsh-host-apiproxy/api'
export type { ToolCallView, ToolResultView } from '@deepseek-ai/dsh-tools/presentation'
@@ -1545,6 +1545,7 @@ export function createFixtureApi(options: FixtureOptions = {}): ApiProxy {
value: { apiKeyEnv: 'DEEPSEEK_API_KEY' },
applies: 'live',
secrets: [{ path: ['apiKey'], set: false }],
revision: 0,
}],
}),
update: request => err(request, {
@@ -1557,6 +1558,11 @@ export function createFixtureApi(options: FixtureOptions = {}): ApiProxy {
message: 'fixture: the minimal readiness settings descriptor is read-only',
details: { ns: request.payload.ns },
}),
mutate: request => err(request, {
code: 'settings-rejected',
message: 'fixture: no settings namespaces are registered',
details: { ns: request.payload.ns },
}),
},
credentials: {
describe: request => ok(request, {
@@ -1680,6 +1686,7 @@ export class FixtureApiClient extends AbstractApiClient {
case 'settings.describe': return this.api.settings.describe(request)
case 'settings.update': return this.api.settings.update(request)
case 'settings.replace': return this.api.settings.replace(request)
case 'settings.mutate': return this.api.settings.mutate(request)
case 'credentials.describe': return this.api.credentials.describe(request)
case 'credentials.set': return this.api.credentials.set(request)
case 'credentials.unset': return this.api.credentials.unset(request)
@@ -22,7 +22,7 @@ export type {
ClientRequest, ServerResponse, ServerRequest, ClientResponse, RpcMessage, RpcReceipt,
IApiClient, SessionId, SessionEvent, ContentBlock, StreamChunk,
GoalsApi, GoalRef,
SettingsApi, SettingsNamespaceView, SettingsSecretView,
SettingsApi, SettingsNamespaceView, SettingsPathOpView, SettingsSecretView,
CredentialsApi, CredentialView, ConfigurableProviderView, LlmApi,
} from './api.ts'
export { RpcId, AbstractApiClient, transportError } from './api.ts'
+14 -4
View File
@@ -35,16 +35,26 @@ export const Config: z<ConnectionConfig> = z.object({
/**
* Methods gated to loopback even on a trusted-host deployment. Native dialogs
* act on the host machine; settings and credential writes mutate the user's
* configuration and secret store. A declared `trustedHosts` authority reaches
* every other method, but these stay loopback-same-origin until a real
* authentication layer exists.
* act on the host machine; the settings and credential domains mutate the
* user's configuration and secret store, and READING them is equally
* privileged — `settings.describe` returns every exposed namespace's
* configuration and `credentials.describe` reports whether an arbitrary
* environment-variable name is configured and where from, which is
* reconnaissance no anonymous caller should have. `trustedHosts` is a
* DNS-rebinding fence, explicitly not authentication, so the whole
* configuration plane stays loopback-same-origin until a real authentication
* layer exists. The model catalog (`llm.providers`, `llm.models`) is
* deliberately NOT here: it carries provider ids, display names, and model
* lists — no endpoints, keys, or key state — and a LAN client's model picker
* legitimately needs it.
*/
const PRIVILEGED_METHODS = new Set([
'host.pickDirectory',
'host.openPath',
'settings.describe',
'settings.update',
'settings.replace',
'credentials.describe',
'credentials.set',
'credentials.unset',
])