Merge branch 'worktree-llm-dynamic-config' into worktree-llm-web-config

# Conflicts:
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.i18n.yaml
#	docs/event-producer-consumer.md
#	examples/headless-agent/tests/headless.snapshot.ts
#	examples/headless-agent/tests/snapshots/missing-credential/stream-json.expected.jsonl
#	packages/llm/llm-deepseek/README.i18n.yaml
#	packages/llm/llm-deepseek/src/index.ts
#	packages/llm/llm-pi-ai/README.i18n.yaml
#	packages/llm/llm-pi-ai/src/index.ts
#	packages/llm/llm/README.i18n.yaml
#	packages/llm/llm/src/index.ts
This commit is contained in:
Yichen Jiang
2026-07-30 17:22:44 +08:00
60 changed files with 1320 additions and 320 deletions
+21
View File
@@ -590,6 +590,20 @@ export abstract class Settings extends Service {
}
}
/**
* Value mirror of the `FiberState` members {@link isUnloading} compares
* against: a const enum has no runtime object to import, and the value is
* needed at runtime (same rationale as the CLI boot driver's mirror).
*/
const FIBER_DISPOSED = 4
const FIBER_UNLOADING = 5
/** Whether the consumer's own fiber is tearing down (not just losing the settings service). */
function isUnloading(ctx: Context): boolean {
const state: number = ctx.fiber.state
return state === FIBER_UNLOADING || state === FIBER_DISPOSED
}
/** Hooks a consumer hands to {@link installSettingsSection}. */
export interface SettingsSectionHooks<T> {
/**
@@ -630,6 +644,13 @@ export function installSettingsSection<T>(
const scope = sctx.settings.register(ns, schema, { base: entry })
hooks.setSource(() => scope.get())
sctx.effect(() => () => {
// This disposer runs for two different reasons. A settings provider
// detaching leaves the consumer running, so it must fall back to its
// composition entry and re-judge what it derived. The consumer's own
// unload runs it too — and there `onChange` would re-register routes
// and touch resources the teardown is releasing, so the fallback is
// pointless and the notification actively harmful.
if (isUnloading(ctx)) return
hooks.setSource(() => entry)
hooks.onChange()
})