refactor(credentials,llm): remove speculative mutation and route lifecycle

This commit is contained in:
Tianyi Cui
2026-07-31 01:08:54 +08:00
parent 16802cd612
commit f9f8148e79
100 changed files with 559 additions and 2752 deletions

View File

@@ -32,8 +32,6 @@ flowchart LR
cfg --> plugin_tui_settings
plugin_tui_credentials["credentials<br/>@deepseek-ai/dsh-credentials-local"]
cfg --> plugin_tui_credentials
plugin_tui_llm_pi_ai["llm-pi-ai<br/>@deepseek-ai/dsh-llm-pi-ai"]
cfg --> plugin_tui_llm_pi_ai
plugin_tui_session_persistence_jsonl["session-persistence-jsonl<br/>@deepseek-ai/dsh-session-persistence-jsonl"]
cfg --> plugin_tui_session_persistence_jsonl
plugin_tui_session_query_sqlite["session-query-sqlite<br/>@deepseek-ai/dsh-session-query-sqlite"]
@@ -120,7 +118,6 @@ flowchart LR
| `llm-retry` | `@deepseek-ai/dsh-llm-retry` |
| `settings` | `@deepseek-ai/dsh-settings-local` |
| `credentials` | `@deepseek-ai/dsh-credentials-local` |
| `llm-pi-ai` | `@deepseek-ai/dsh-llm-pi-ai` |
| `session-persistence-jsonl` | `@deepseek-ai/dsh-session-persistence-jsonl` |
| `session-query-sqlite` | `@deepseek-ai/dsh-session-query-sqlite` |
| `subprocess` | `@deepseek-ai/dsh-subprocess-local` |

View File

@@ -56,29 +56,20 @@
- id: llm-retry
name: '@deepseek-ai/dsh-llm-retry'
# User-settings document (`$DSH_HOME/settings.yaml`, hot-reloaded): a
# `llm-deepseek:` or `llm-pi-ai:` section there overrides the adapter entries
# below without a restart, and is what the web Models page writes.
# User-settings document (`$DSH_HOME/settings.yaml`, hot-reloaded): the
# `llm-deepseek:` section overrides request-level adapter facts below without
# a restart. Provider routes and retry policy remain composition-owned.
- id: settings
name: '@deepseek-ai/dsh-settings-local'
# Credential store: the live process environment over `$DSH_HOME/.env`
# (owner-only file, hot-reloaded). Adapters resolve their key references
# through it at each request, so no key is inlined in this file — and nothing
# hoists that document into the process environment, which would make every
# stored key read as an unrotatable ambient override.
# Credential reader: the live process environment over `$DSH_HOME/.env`.
# Adapters resolve their key references on demand, so external rotations reach
# the next request without a watcher, cache, or mutation API. Nothing hoists
# that document into the process environment, where it would become an ambient
# override.
- id: credentials
name: '@deepseek-ai/dsh-credentials-local'
# The pi-ai multi-provider twin, mounted dormant: zero routes (and no extra
# models in the picker) until a `llm-pi-ai:` settings section supplies provider
# profiles — then those routes register live, keys resolving per request
# through their apiKeyEnv references, and drop again when the section empties.
# Which adapters exist is composition; which providers run is the user's
# settings document.
- id: llm-pi-ai
name: '@deepseek-ai/dsh-llm-pi-ai'
- id: session-persistence-jsonl
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
@@ -237,7 +228,7 @@
# The native DeepSeek adapter. No key or endpoint is inlined: both resolve per
# request from the `llm-deepseek:` settings section over this entry, with the
# key coming from the credential store below. Thinking defaults are a surface
# key coming from the credential reader below. Thinking defaults are a surface
# choice.
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek'

View File

@@ -66,7 +66,6 @@
"@deepseek-ai/dsh-invariants": "workspace:^",
"@deepseek-ai/dsh-llm": "workspace:^",
"@deepseek-ai/dsh-llm-deepseek": "workspace:^",
"@deepseek-ai/dsh-llm-pi-ai": "workspace:^",
"@deepseek-ai/dsh-llm-retry": "workspace:^",
"@deepseek-ai/dsh-paths": "workspace:^",
"@deepseek-ai/dsh-permission": "workspace:^",

View File

@@ -123,9 +123,9 @@ export async function runTui(
}
installFailLoud(NAME)
// The bin already loaded the invoking directory's .env, and that is the
// whole environment: $DSH_HOME/.env is credentials-local's writable store,
// and hoisting it would make every stored key read as a read-only ambient
// override on the next run — unrotatable from the TUI or the web page.
// whole environment: credentials-local reads $DSH_HOME/.env on demand, and
// hoisting it would make every stored key an ambient override whose later
// file rotations cannot take effect.
// The environment is settled, so switching the workspace here cannot alter
// its precedence. The cwd IS the workspace seam: the shipped config
// resolves the session cwd and the HMR watch root from it, so one chdir moves

View File

@@ -359,10 +359,10 @@ describe('dsh CLI keyless smoke (apps/cli through the same PTY)', () => {
// SURFACE OVERLAY inserted, not one the base declares — proving a later
// patch list reaches a row an earlier one inserted. The single `!!js`
// expression prefers the PERSONAL variable, so the welcome can only render
// the project value while the harness home's .env — the credential store
// of `dsh-credentials-local` — is NOT hoisted into `process.env`; hoisting
// it would make every stored key read as a read-only launch override on
// the next run and hand it to every subprocess the agent starts.
// the project value while the harness home's .env — the document read by
// `dsh-credentials-local` — is NOT hoisted into `process.env`; hoisting it
// would make every stored key a launch override and hand it to every
// subprocess the agent starts.
const output = await smoke({
label: 'dsh personal overlay',
tempDirPrefix: 'dsh-personal-overlay-',