docs: bilingual credentials/settings-consumer documentation, catalogs, and gates

New credentials data-structure page (type-equiv manifested), group README,
rewritten llm-deepseek/llm-pi-ai READMEs (dynamic configuration, dict
profiles, credential chain), capability-seams/service-role registration,
Agent Note (bilingual), demo compositions mounting settings-local +
credentials-local with no inline key plumbing, installSettingsSection
consumer helper on the settings seam (deduplicating both adapters' wiring),
jscpd symmetry markers for the provider twins, runtime-closure additions for
python/sdk-runtime, and doc-budget ceilings AGENTS.md 1750→1755 /
packages/README.md 850→865 for the structural one-line group rows.
This commit is contained in:
Yichen Jiang
2026-07-29 14:20:06 +08:00
parent d77db29f01
commit b0a2011d95
61 changed files with 732 additions and 153 deletions

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/credentials/credentials-local/README.md
README.md: 277c7db02836819e34a5c2db8aaf542c8eeec162
README.zh.md: af1b840142d214b8cd8cf59690cb5773fae2e867

View File

@@ -32,7 +32,7 @@ External edits publish `credentials/updated` per changed reference after the sna
## Model Experience
Indirectly: resolved values authorize LLM adapter requests; the consuming adapter owns every model-visible surface.
Indirectly, through the consuming LLM adapters: stored values authorize their provider requests, and the adapter owns every model-visible surface.
#### KV Cache effect

View File

@@ -2,14 +2,14 @@
[English](README.md) | 中文
文件型[凭据](../credentials/README.zh.md) provider两层来源一条诚实的优先级。
文件型[凭据](../credentials/README.md) provider两层来源一条诚实的优先级。
| 层 | 来源 id | 可写 | 优先 |
|---|---|---|---|
| 活跃进程环境 | `env` | 否 | 恒定优先 |
| `$DSH_HOME/.env` 文档 | `file` | 是(`set`/`unset` | 其余情况 |
环境优先,因为启动时注入`DEEPSEEK_API_KEY=… dsh`、CI secrets、加载了仓库 `.env` 的开发 shell代表本次运行的操作者意图——而它无法从进程内部修改就必须**可见地**只读:`describe()` 报告 `source: 'env', writable: false``set`/`unset` 直接拒绝,而不是写下一个读取方永远看不到的变更。解析实时读取 `process.env`,绝不写回。
环境优先,因为启动时覆盖`DEEPSEEK_API_KEY=… dsh`、CI 机密、加载了仓库 `.env` 的开发 shell代表本次运行的操作者意图——而它无法从进程内部修改就必须*可见地*只读:`describe()` 报告 `source: 'env', writable: false``set`/`unset` 直接拒绝,而不是写下一个读取方永远看不到的变更。解析实时读取 `process.env`,绝不写回。
## 配置
@@ -18,25 +18,25 @@
| `path` | `<harness home>/.env` | 凭据文档位置。 |
| `dshHome` | `$DSH_HOME``~/.dsh` | `path` 缺省时使用的 harness home。 |
| `watch` | `true` | 热发布外部编辑。 |
| `debounceMs` | `100` | watcher 写入沉降窗口。 |
| `debounceMs` | `100` | watcher 写入稳定窗口。 |
## 文档本身
dotenv 格式,用 `dotenv` 解析;写回用行级编辑器,保留一切不属于本次编辑的字节:`set` 原位改写该键的第一条赋值行丢弃后续重复行——dotenv 按最后一条生效,重复行会反过来覆盖这次编辑),`unset` 只删除所属行,注释与无关行逐字保留。落盘经 [`dsh-atomic-write`](../../util/atomic-write/README.zh.md),权限 `0600`
dotenv 格式,用 `dotenv` 解析;写回用行级编辑器,保留一切不属于本次编辑的字节:`set` 原位改写该键的第一条赋值行丢弃后续重复行——dotenv 按最后一条生效,重复行会反过来覆盖这次编辑),`unset` 只删除所属行,注释与无关行逐字保留。落盘经 [`dsh-atomic-write`](../../util/atomic-write/README.md),权限 `0600`
值按 dotenv 能逐字读回的最窄样式渲染——裸值,其次单引号(完全字面),再次双引号(仅限无反斜杠,双引号读取会展开转义)。任何样式都无法表示的值以及已经跨越多个物理行的条目响亮失败而不是被静默破坏。空的存储值等于不存在seam 规则)。
值按 dotenv 能逐字读回的最窄样式渲染——裸值,其次单引号(完全字面),再次双引号(仅限无反斜杠,双引号读取会展开转义)。任何样式都无法表示的值以及已经跨越多个物理行的条目,都会响亮失败而不是被静默破坏。空的存储值等于不存在seam 规则)。
## 热重载
外部编辑在快照**整体替换**后按变更引用逐个发布 `credentials/updated`——磁盘上删掉的条目绝不在内存滞留。provider 自己的写入按内容识别,只发布属于该次提交的一个事件。运行期文档不可读时保留最后一份好快照并告警;文件不存在即空存储;启动时不可读则响亮失败。非 POSIX 标识符的键属于被保留的文件内容seam 无法寻址。
外部编辑在快照**整体替换**后按变更引用逐个发布 `credentials/updated`——磁盘上删掉的条目绝不在内存滞留。provider 自己的写入按内容识别,只发布属于该次提交的一个事件。运行期文档不可读时保留最后可用快照并告警;文件不存在即空存储;启动时不可读则响亮失败。非 POSIX 标识符的键属于被保留的文件内容seam 无法寻址。
## Model Experience
Indirectly: resolved values authorize LLM adapter requests; the consuming adapter owns every model-visible surface.
经由消费它的 LLM 适配器间接生效:存储的值为适配器的提供方请求授权,每个模型可见面都归适配器所有。
#### KV Cache effect
No direct invalidation; credentials never enter a request prefix.
无直接失效;凭据绝不进入请求前缀。
## Known Limitations and Deferred Work

View File

@@ -118,6 +118,9 @@ function upsertLine(text: string | undefined, ref: CredentialRef, line: string |
/** File-backed credentials provider (`$DSH_HOME/.env`). */
export class CredentialsLocal extends Credentials {
/* jscpd:ignore-start -- deliberate config-surface and lifecycle symmetry with
settings-local (prefer symmetry for parallel values); extracting the shared
shape would couple the two providers' teardown semantics across packages. */
static Config: z<Config> = z.object({
path: z.string(),
dshHome: z.string(),
@@ -145,6 +148,7 @@ export class CredentialsLocal extends Credentials {
private isClosed(): boolean {
return this.closed
}
/* jscpd:ignore-end */
constructor(ctx: Context, public config: Config) {
super(ctx)
@@ -162,6 +166,9 @@ export class CredentialsLocal extends Credentials {
}
await this.loadInitial()
if (!this.spec.watch) return
/* jscpd:ignore-start -- same watcher discipline as settings-local by design:
the serialized-refresh and quiesce-on-dispose shape is the reviewed
lifecycle contract, not accidental repetition. */
const watcher = chokidarWatch(this.spec.filename, {
ignoreInitial: true,
awaitWriteFinish: {
@@ -183,6 +190,7 @@ export class CredentialsLocal extends Credentials {
this.ctx.logger.warn('credentials-local: watcher error on %s', this.spec.filename)
this.ctx.logger.warn(error)
})
/* jscpd:ignore-end */
yield async () => {
// Quiesce: stop accepting events, close the watcher, then wait out any
// queued or in-flight refresh so nothing publishes after disposal.