@coool/opencode-adaptive 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +99 -2
- package/dist/adapters/codex-capacity/index.d.ts +4 -0
- package/dist/adapters/codex-capacity/index.js +5 -0
- package/dist/adapters/codex-capacity/index.js.map +1 -0
- package/dist/adapters/codex-capacity/parse.d.ts +28 -0
- package/dist/adapters/codex-capacity/parse.js +146 -0
- package/dist/adapters/codex-capacity/parse.js.map +1 -0
- package/dist/adapters/codex-capacity/reading.d.ts +9 -0
- package/dist/adapters/codex-capacity/reading.js +45 -0
- package/dist/adapters/codex-capacity/reading.js.map +1 -0
- package/dist/adapters/codex-capacity/sensor.d.ts +23 -0
- package/dist/adapters/codex-capacity/sensor.js +30 -0
- package/dist/adapters/codex-capacity/sensor.js.map +1 -0
- package/dist/adapters/codex-capacity/types.d.ts +31 -0
- package/dist/adapters/codex-capacity/types.js +18 -0
- package/dist/adapters/codex-capacity/types.js.map +1 -0
- package/dist/adapters/opencode/escalation-tool.d.ts +51 -0
- package/dist/adapters/opencode/escalation-tool.js +61 -0
- package/dist/adapters/opencode/escalation-tool.js.map +1 -0
- package/dist/adapters/opencode/events.d.ts +23 -0
- package/dist/adapters/opencode/events.js +68 -0
- package/dist/adapters/opencode/events.js.map +1 -0
- package/dist/adapters/opencode/hooks.d.ts +34 -0
- package/dist/adapters/opencode/hooks.js +29 -0
- package/dist/adapters/opencode/hooks.js.map +1 -0
- package/dist/adapters/opencode/index.d.ts +16 -0
- package/dist/adapters/opencode/index.js +9 -0
- package/dist/adapters/opencode/index.js.map +1 -0
- package/dist/adapters/opencode/inventory.d.ts +30 -0
- package/dist/adapters/opencode/inventory.js +53 -0
- package/dist/adapters/opencode/inventory.js.map +1 -0
- package/dist/adapters/opencode/report.d.ts +91 -0
- package/dist/adapters/opencode/report.js +145 -0
- package/dist/adapters/opencode/report.js.map +1 -0
- package/dist/adapters/opencode/session-ops.d.ts +39 -0
- package/dist/adapters/opencode/session-ops.js +32 -0
- package/dist/adapters/opencode/session-ops.js.map +1 -0
- package/dist/adapters/opencode/storage.d.ts +15 -0
- package/dist/adapters/opencode/storage.js +8 -0
- package/dist/adapters/opencode/storage.js.map +1 -0
- package/dist/adapters/opencode/tier-tool.d.ts +37 -0
- package/dist/adapters/opencode/tier-tool.js +72 -0
- package/dist/adapters/opencode/tier-tool.js.map +1 -0
- package/dist/adapters/opencode/types.d.ts +101 -0
- package/dist/adapters/opencode/types.js +2 -0
- package/dist/adapters/opencode/types.js.map +1 -0
- package/dist/core/compatibility/gate.d.ts +7 -0
- package/dist/core/compatibility/gate.js +51 -0
- package/dist/core/compatibility/gate.js.map +1 -0
- package/dist/core/compatibility/index.d.ts +2 -0
- package/dist/core/compatibility/index.js +3 -0
- package/dist/core/compatibility/index.js.map +1 -0
- package/dist/core/compatibility/types.d.ts +53 -0
- package/dist/core/compatibility/types.js +27 -0
- package/dist/core/compatibility/types.js.map +1 -0
- package/dist/core/scheduler/admit.d.ts +6 -0
- package/dist/core/scheduler/admit.js +154 -0
- package/dist/core/scheduler/admit.js.map +1 -0
- package/dist/core/scheduler/escalate.d.ts +6 -0
- package/dist/core/scheduler/escalate.js +45 -0
- package/dist/core/scheduler/escalate.js.map +1 -0
- package/dist/core/scheduler/index.d.ts +4 -0
- package/dist/core/scheduler/index.js +5 -0
- package/dist/core/scheduler/index.js.map +1 -0
- package/dist/core/scheduler/mode.d.ts +8 -0
- package/dist/core/scheduler/mode.js +10 -0
- package/dist/core/scheduler/mode.js.map +1 -0
- package/dist/core/scheduler/types.d.ts +136 -0
- package/dist/core/scheduler/types.js +75 -0
- package/dist/core/scheduler/types.js.map +1 -0
- package/dist/core/tier-policy/index.d.ts +3 -0
- package/dist/core/tier-policy/index.js +4 -0
- package/dist/core/tier-policy/index.js.map +1 -0
- package/dist/core/tier-policy/resolve.d.ts +18 -0
- package/dist/core/tier-policy/resolve.js +52 -0
- package/dist/core/tier-policy/resolve.js.map +1 -0
- package/dist/core/tier-policy/tier-list.d.ts +10 -0
- package/dist/core/tier-policy/tier-list.js +23 -0
- package/dist/core/tier-policy/tier-list.js.map +1 -0
- package/dist/core/tier-policy/types.d.ts +86 -0
- package/dist/core/tier-policy/types.js +49 -0
- package/dist/core/tier-policy/types.js.map +1 -0
- package/dist/core/work-unit/index.d.ts +3 -0
- package/dist/core/work-unit/index.js +4 -0
- package/dist/core/work-unit/index.js.map +1 -0
- package/dist/core/work-unit/interruption.d.ts +7 -0
- package/dist/core/work-unit/interruption.js +12 -0
- package/dist/core/work-unit/interruption.js.map +1 -0
- package/dist/core/work-unit/tracker.d.ts +53 -0
- package/dist/core/work-unit/tracker.js +156 -0
- package/dist/core/work-unit/tracker.js.map +1 -0
- package/dist/core/work-unit/types.d.ts +151 -0
- package/dist/core/work-unit/types.js +23 -0
- package/dist/core/work-unit/types.js.map +1 -0
- package/dist/execution/continuation/execute.d.ts +18 -0
- package/dist/execution/continuation/execute.js +31 -0
- package/dist/execution/continuation/execute.js.map +1 -0
- package/dist/execution/continuation/index.d.ts +4 -0
- package/dist/execution/continuation/index.js +4 -0
- package/dist/execution/continuation/index.js.map +1 -0
- package/dist/execution/continuation/plan.d.ts +12 -0
- package/dist/execution/continuation/plan.js +18 -0
- package/dist/execution/continuation/plan.js.map +1 -0
- package/dist/execution/continuation/prompts.d.ts +7 -0
- package/dist/execution/continuation/prompts.js +8 -0
- package/dist/execution/continuation/prompts.js.map +1 -0
- package/dist/execution/continuation/types.d.ts +68 -0
- package/dist/execution/continuation/types.js +15 -0
- package/dist/execution/continuation/types.js.map +1 -0
- package/dist/execution/escalation/index.d.ts +1 -0
- package/dist/execution/escalation/index.js +2 -0
- package/dist/execution/escalation/index.js.map +1 -0
- package/dist/execution/escalation/types.d.ts +30 -0
- package/dist/execution/escalation/types.js +49 -0
- package/dist/execution/escalation/types.js.map +1 -0
- package/dist/execution/index.d.ts +4 -0
- package/dist/execution/index.js +5 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/parking/index.d.ts +2 -0
- package/dist/execution/parking/index.js +2 -0
- package/dist/execution/parking/index.js.map +1 -0
- package/dist/execution/parking/plan.d.ts +39 -0
- package/dist/execution/parking/plan.js +34 -0
- package/dist/execution/parking/plan.js.map +1 -0
- package/dist/execution/retry/decide.d.ts +29 -0
- package/dist/execution/retry/decide.js +75 -0
- package/dist/execution/retry/decide.js.map +1 -0
- package/dist/execution/retry/index.d.ts +2 -0
- package/dist/execution/retry/index.js +3 -0
- package/dist/execution/retry/index.js.map +1 -0
- package/dist/execution/retry/types.d.ts +64 -0
- package/dist/execution/retry/types.js +9 -0
- package/dist/execution/retry/types.js.map +1 -0
- package/dist/gui-experimental.cjs +1 -0
- package/dist/gui.d.ts +16 -0
- package/dist/gui.js +73 -0
- package/dist/gui.js.map +1 -0
- package/dist/health/capacity/index.d.ts +3 -0
- package/dist/health/capacity/index.js +4 -0
- package/dist/health/capacity/index.js.map +1 -0
- package/dist/health/capacity/merge.d.ts +57 -0
- package/dist/health/capacity/merge.js +154 -0
- package/dist/health/capacity/merge.js.map +1 -0
- package/dist/health/capacity/registry.d.ts +40 -0
- package/dist/health/capacity/registry.js +106 -0
- package/dist/health/capacity/registry.js.map +1 -0
- package/dist/health/capacity/types.d.ts +73 -0
- package/dist/health/capacity/types.js +6 -0
- package/dist/health/capacity/types.js.map +1 -0
- package/dist/health/circuit-breaker/breaker.d.ts +91 -0
- package/dist/health/circuit-breaker/breaker.js +150 -0
- package/dist/health/circuit-breaker/breaker.js.map +1 -0
- package/dist/health/circuit-breaker/index.d.ts +2 -0
- package/dist/health/circuit-breaker/index.js +3 -0
- package/dist/health/circuit-breaker/index.js.map +1 -0
- package/dist/health/circuit-breaker/types.d.ts +52 -0
- package/dist/health/circuit-breaker/types.js +13 -0
- package/dist/health/circuit-breaker/types.js.map +1 -0
- package/dist/health/classifier/classify.d.ts +8 -0
- package/dist/health/classifier/classify.js +245 -0
- package/dist/health/classifier/classify.js.map +1 -0
- package/dist/health/classifier/index.d.ts +2 -0
- package/dist/health/classifier/index.js +3 -0
- package/dist/health/classifier/index.js.map +1 -0
- package/dist/health/classifier/types.d.ts +71 -0
- package/dist/health/classifier/types.js +27 -0
- package/dist/health/classifier/types.js.map +1 -0
- package/dist/health/index.d.ts +4 -0
- package/dist/health/index.js +5 -0
- package/dist/health/index.js.map +1 -0
- package/dist/health/resource-health/index.d.ts +4 -0
- package/dist/health/resource-health/index.js +5 -0
- package/dist/health/resource-health/index.js.map +1 -0
- package/dist/health/resource-health/key.d.ts +18 -0
- package/dist/health/resource-health/key.js +54 -0
- package/dist/health/resource-health/key.js.map +1 -0
- package/dist/health/resource-health/registry.d.ts +46 -0
- package/dist/health/resource-health/registry.js +276 -0
- package/dist/health/resource-health/registry.js.map +1 -0
- package/dist/health/resource-health/transitions.d.ts +9 -0
- package/dist/health/resource-health/transitions.js +157 -0
- package/dist/health/resource-health/transitions.js.map +1 -0
- package/dist/health/resource-health/types.d.ts +122 -0
- package/dist/health/resource-health/types.js +44 -0
- package/dist/health/resource-health/types.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +105 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin-id.d.ts +2 -0
- package/dist/plugin-id.js +3 -0
- package/dist/plugin-id.js.map +1 -0
- package/dist/rpc/definition.d.ts +123 -0
- package/dist/rpc/definition.js +130 -0
- package/dist/rpc/definition.js.map +1 -0
- package/dist/rpc/handlers.d.ts +53 -0
- package/dist/rpc/handlers.js +125 -0
- package/dist/rpc/handlers.js.map +1 -0
- package/dist/rpc/status.d.ts +42 -0
- package/dist/rpc/status.js +45 -0
- package/dist/rpc/status.js.map +1 -0
- package/dist/rpc.d.ts +10 -0
- package/dist/rpc.js +8 -0
- package/dist/rpc.js.map +1 -0
- package/dist/state/capacity/index.d.ts +3 -0
- package/dist/state/capacity/index.js +4 -0
- package/dist/state/capacity/index.js.map +1 -0
- package/dist/state/capacity/parse.d.ts +2 -0
- package/dist/state/capacity/parse.js +122 -0
- package/dist/state/capacity/parse.js.map +1 -0
- package/dist/state/capacity/store.d.ts +18 -0
- package/dist/state/capacity/store.js +78 -0
- package/dist/state/capacity/store.js.map +1 -0
- package/dist/state/capacity/types.d.ts +37 -0
- package/dist/state/capacity/types.js +11 -0
- package/dist/state/capacity/types.js.map +1 -0
- package/dist/state/health/index.d.ts +4 -0
- package/dist/state/health/index.js +4 -0
- package/dist/state/health/index.js.map +1 -0
- package/dist/state/health/parse.d.ts +2 -0
- package/dist/state/health/parse.js +137 -0
- package/dist/state/health/parse.js.map +1 -0
- package/dist/state/health/store.d.ts +17 -0
- package/dist/state/health/store.js +69 -0
- package/dist/state/health/store.js.map +1 -0
- package/dist/state/health/types.d.ts +23 -0
- package/dist/state/health/types.js +5 -0
- package/dist/state/health/types.js.map +1 -0
- package/dist/state/parked-work/index.d.ts +4 -0
- package/dist/state/parked-work/index.js +4 -0
- package/dist/state/parked-work/index.js.map +1 -0
- package/dist/state/parked-work/parse.d.ts +6 -0
- package/dist/state/parked-work/parse.js +83 -0
- package/dist/state/parked-work/parse.js.map +1 -0
- package/dist/state/parked-work/store.d.ts +17 -0
- package/dist/state/parked-work/store.js +98 -0
- package/dist/state/parked-work/store.js.map +1 -0
- package/dist/state/parked-work/types.d.ts +41 -0
- package/dist/state/parked-work/types.js +7 -0
- package/dist/state/parked-work/types.js.map +1 -0
- package/dist/state/receipts/bound.d.ts +14 -0
- package/dist/state/receipts/bound.js +77 -0
- package/dist/state/receipts/bound.js.map +1 -0
- package/dist/state/receipts/index.d.ts +6 -0
- package/dist/state/receipts/index.js +5 -0
- package/dist/state/receipts/index.js.map +1 -0
- package/dist/state/receipts/parse.d.ts +6 -0
- package/dist/state/receipts/parse.js +226 -0
- package/dist/state/receipts/parse.js.map +1 -0
- package/dist/state/receipts/store.d.ts +34 -0
- package/dist/state/receipts/store.js +148 -0
- package/dist/state/receipts/store.js.map +1 -0
- package/dist/state/receipts/types.d.ts +61 -0
- package/dist/state/receipts/types.js +12 -0
- package/dist/state/receipts/types.js.map +1 -0
- package/dist/state/session-modes/index.d.ts +4 -0
- package/dist/state/session-modes/index.js +4 -0
- package/dist/state/session-modes/index.js.map +1 -0
- package/dist/state/session-modes/parse.d.ts +8 -0
- package/dist/state/session-modes/parse.js +62 -0
- package/dist/state/session-modes/parse.js.map +1 -0
- package/dist/state/session-modes/store.d.ts +20 -0
- package/dist/state/session-modes/store.js +87 -0
- package/dist/state/session-modes/store.js.map +1 -0
- package/dist/state/session-modes/types.d.ts +41 -0
- package/dist/state/session-modes/types.js +7 -0
- package/dist/state/session-modes/types.js.map +1 -0
- package/dist/state/settings/index.d.ts +4 -0
- package/dist/state/settings/index.js +4 -0
- package/dist/state/settings/index.js.map +1 -0
- package/dist/state/settings/parse.d.ts +33 -0
- package/dist/state/settings/parse.js +261 -0
- package/dist/state/settings/parse.js.map +1 -0
- package/dist/state/settings/store.d.ts +21 -0
- package/dist/state/settings/store.js +65 -0
- package/dist/state/settings/store.js.map +1 -0
- package/dist/state/settings/types.d.ts +62 -0
- package/dist/state/settings/types.js +12 -0
- package/dist/state/settings/types.js.map +1 -0
- package/dist/state/tier-requests/index.d.ts +4 -0
- package/dist/state/tier-requests/index.js +4 -0
- package/dist/state/tier-requests/index.js.map +1 -0
- package/dist/state/tier-requests/parse.d.ts +3 -0
- package/dist/state/tier-requests/parse.js +53 -0
- package/dist/state/tier-requests/parse.js.map +1 -0
- package/dist/state/tier-requests/store.d.ts +27 -0
- package/dist/state/tier-requests/store.js +96 -0
- package/dist/state/tier-requests/store.js.map +1 -0
- package/dist/state/tier-requests/types.d.ts +30 -0
- package/dist/state/tier-requests/types.js +7 -0
- package/dist/state/tier-requests/types.js.map +1 -0
- package/dist/supervisor/index.d.ts +4 -0
- package/dist/supervisor/index.js +4 -0
- package/dist/supervisor/index.js.map +1 -0
- package/dist/supervisor/log.d.ts +10 -0
- package/dist/supervisor/log.js +14 -0
- package/dist/supervisor/log.js.map +1 -0
- package/dist/supervisor/supervisor.d.ts +86 -0
- package/dist/supervisor/supervisor.js +1629 -0
- package/dist/supervisor/supervisor.js.map +1 -0
- package/dist/supervisor/types.d.ts +49 -0
- package/dist/supervisor/types.js +3 -0
- package/dist/supervisor/types.js.map +1 -0
- package/dist/supervisor/view.d.ts +3 -0
- package/dist/supervisor/view.js +4 -0
- package/dist/supervisor/view.js.map +1 -0
- package/dist/tui.d.ts +15 -0
- package/dist/tui.js +256 -0
- package/dist/tui.js.map +1 -0
- package/dist/ui/gui/api.d.ts +17 -0
- package/dist/ui/gui/api.js +21 -0
- package/dist/ui/gui/api.js.map +1 -0
- package/dist/ui/gui/view.d.ts +26 -0
- package/dist/ui/gui/view.js +49 -0
- package/dist/ui/gui/view.js.map +1 -0
- package/dist/ui/tui/controller.d.ts +97 -0
- package/dist/ui/tui/controller.js +415 -0
- package/dist/ui/tui/controller.js.map +1 -0
- package/dist/ui/tui/menu.d.ts +55 -0
- package/dist/ui/tui/menu.js +176 -0
- package/dist/ui/tui/menu.js.map +1 -0
- package/dist/ui/tui/options.d.ts +19 -0
- package/dist/ui/tui/options.js +17 -0
- package/dist/ui/tui/options.js.map +1 -0
- package/dist/ui/tui/receipts.d.ts +21 -0
- package/dist/ui/tui/receipts.js +112 -0
- package/dist/ui/tui/receipts.js.map +1 -0
- package/dist/ui/tui/status.d.ts +22 -0
- package/dist/ui/tui/status.js +92 -0
- package/dist/ui/tui/status.js.map +1 -0
- package/dist/ui/tui/tiers.d.ts +51 -0
- package/dist/ui/tui/tiers.js +108 -0
- package/dist/ui/tui/tiers.js.map +1 -0
- package/package.json +85 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../src/state/settings/parse.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Bounded shape validation and migration-on-read (ADP-036). Every parser is\n * total: it accepts `unknown` and either returns a typed value or `undefined`\n * — the read path always falls back to a default rather than throwing, so a\n * corrupted record can never take the plugin (or the host) down (ADP-031).\n *\n * Plain objects are never indexed with untrusted strings beyond own-property\n * checks (`Object.hasOwn`) — prototype-chain keys like \"toString\" must not be\n * mistaken for data (project-wide audit rule).\n */\nimport { OPERATING_MODES } from \"../../core/scheduler/types.js\"\nimport type { OperatingMode } from \"../../core/scheduler/types.js\"\nimport { normalizeTierList } from \"../../core/tier-policy/tier-list.js\"\nimport { TIERS } from \"../../core/tier-policy/types.js\"\nimport type { TierName } from \"../../core/tier-policy/types.js\"\nimport type { ModelRef } from \"../../core/work-unit/types.js\"\nimport { MAX_AGENT_TIERS, MAX_TIER_RESOURCES, SETTINGS_VERSION } from \"./types.js\"\nimport type { SettingsV1 } from \"./types.js\"\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\n/** One field's patch-path parse outcome: a validated value or a field error. */\ntype FieldParse<T> = { ok: true; value: T } | { ok: false; error: string }\n\n/**\n * Quoted, bounded rendering of an untrusted patch value inside an error\n * message (errors travel to surfaces over RPC; JSON.stringify is only ever\n * called on strings here, so a cyclic object cannot make applyPatch throw).\n */\nfunction describePatchValue(value: unknown): string {\n if (typeof value === \"string\") {\n const quoted = JSON.stringify(value)\n return quoted.length > 64 ? `${quoted.slice(0, 64)}…` : quoted\n }\n if (value === null) return \"null\"\n if (typeof value === \"object\") return \"object\"\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value)\n return typeof value\n}\n\nexport function parseMode(raw: unknown): OperatingMode | undefined {\n if (typeof raw !== \"string\") return undefined\n return OPERATING_MODES.find((mode) => mode === raw)\n}\n\n/**\n * Legacy persisted value: v1 settings written before the `control → active`\n * rename store `mode: \"control\"`. Migration-on-read maps it; patches stay\n * strict (wire input must use the current vocabulary).\n */\nfunction parseLegacyMode(raw: unknown): OperatingMode | undefined {\n return raw === \"control\" ? \"active\" : parseMode(raw)\n}\n\nexport function parseTierLists(\n raw: unknown,\n): Readonly<Record<TierName, readonly ModelRef[]>> | undefined {\n if (!isRecord(raw)) return undefined\n const tiers = {} as Record<TierName, readonly ModelRef[]>\n for (const tier of TIERS) {\n tiers[tier] = normalizeTierListValue(raw[tier])\n }\n return tiers\n}\n\n/** Shared per-tier normalization (drop invalid, dedupe, cap) for both paths. */\nfunction normalizeTierListValue(list: unknown): readonly ModelRef[] {\n return Array.isArray(list)\n ? normalizeTierList(\n list.map(parseModelRef).filter((ref): ref is ModelRef => ref !== undefined),\n ).slice(0, MAX_TIER_RESOURCES)\n : []\n}\n\nexport function parseModelRef(raw: unknown): ModelRef | undefined {\n if (!isRecord(raw)) return undefined\n const providerID = raw[\"providerID\"]\n const id = raw[\"id\"]\n const variant = raw[\"variant\"]\n if (typeof providerID !== \"string\" || providerID === \"\") return undefined\n if (typeof id !== \"string\" || id === \"\") return undefined\n return {\n providerID,\n id,\n ...(typeof variant === \"string\" && variant !== \"\" ? { variant } : {}),\n }\n}\n\nexport function parsePin(raw: unknown): ModelRef | null | undefined {\n if (raw === null) return null\n return parseModelRef(raw)\n}\n\nexport function parseAgentTiers(raw: unknown): Readonly<Record<string, TierName>> | undefined {\n if (!isRecord(raw)) return undefined\n const entries: [string, TierName][] = []\n for (const [agent, tier] of Object.entries(raw)) {\n if (agent === \"\") continue\n const parsed = parseModelessTier(tier)\n if (parsed === undefined) continue\n entries.push([agent, parsed])\n if (entries.length === MAX_AGENT_TIERS) break\n }\n // `Object.fromEntries` creates own data properties, so even a \"__proto__\"\n // key from JSON input cannot pollute the prototype here.\n return Object.fromEntries(entries)\n}\n\nfunction parseModelessTier(raw: unknown): TierName | undefined {\n if (typeof raw !== \"string\") return undefined\n return TIERS.find((tier) => tier === raw)\n}\n\n/**\n * Patch-path tier-list validation. Unlike the read path (which fills missing\n * or unusable tiers with `[]`), a patch that names `tiers` REPLACES the whole\n * map — silently filling an omitted key with `[]` would wipe that tier's\n * configured resources, so every key must be present and array-typed. List\n * contents still go through the shared normalization (drop invalid, dedupe,\n * cap), which is repair of user-typed entries rather than data loss.\n */\nfunction parseTierListsPatch(\n raw: unknown,\n): FieldParse<Readonly<Record<TierName, readonly ModelRef[]>>> {\n if (!isRecord(raw)) return { ok: false, error: \"invalid tiers\" }\n const missing = TIERS.filter((tier) => raw[tier] === undefined)\n if (missing.length > 0) {\n const named = missing.map((tier) => JSON.stringify(tier)).join(\", \")\n return { ok: false, error: `invalid tiers: missing ${named}` }\n }\n const tiers = {} as Record<TierName, readonly ModelRef[]>\n for (const tier of TIERS) {\n const list = raw[tier]\n if (!Array.isArray(list)) {\n return { ok: false, error: `invalid tiers: ${JSON.stringify(tier)} must be an array` }\n }\n tiers[tier] = normalizeTierListValue(list)\n }\n return { ok: true, value: tiers }\n}\n\n/**\n * Patch-path agent-tier validation. Unlike the read path (which drops invalid\n * entries as migration-on-read repair), a patch REPLACES the whole map —\n * silently dropping entries would let a single typo wipe the persisted hints,\n * so any invalid entry (and an over-cap patch) is rejected with an error that\n * names the offending field and value.\n */\nfunction parseAgentTiersPatch(raw: unknown): FieldParse<Readonly<Record<string, TierName>>> {\n if (!isRecord(raw)) return { ok: false, error: \"invalid agentTiers\" }\n const entries: [string, TierName][] = []\n for (const [agent, tier] of Object.entries(raw)) {\n if (entries.length === MAX_AGENT_TIERS) {\n return {\n ok: false,\n error: `invalid agentTiers: more than ${String(MAX_AGENT_TIERS)} entries`,\n }\n }\n if (agent === \"\") return { ok: false, error: \"invalid agentTiers: empty agent name\" }\n const parsed = parseModelessTier(tier)\n if (parsed === undefined) {\n return {\n ok: false,\n error: `invalid agentTiers entry ${describePatchValue(agent)}: ${describePatchValue(tier)}`,\n }\n }\n entries.push([agent, parsed])\n }\n // `Object.fromEntries` creates own data properties, so even a \"__proto__\"\n // key from JSON input cannot pollute the prototype here.\n return { ok: true, value: Object.fromEntries(entries) }\n}\n\n/** Settings with nothing configured: OBSERVE, empty tiers, no pin (ADP-029/032). */\nexport function defaultSettings(): SettingsV1 {\n return {\n version: SETTINGS_VERSION,\n mode: \"observe\",\n tiers: { quick: [], standard: [], advanced: [] },\n pin: null,\n agentTiers: {},\n inviteDismissed: false,\n }\n}\n\n/**\n * Migration-on-read. `undefined`/absent record → defaults (first install);\n * versionless (v0 draft) and v1 records are validated field-wise with\n * defaults for unusable fields; a record written by a NEWER version is\n * returned as defaults rather than guessed at (and is only re-persisted once\n * the user changes something, which stamps the current version).\n */\nexport function migrateSettings(raw: unknown): SettingsV1 {\n if (!isRecord(raw)) return defaultSettings()\n const version = raw[\"version\"]\n if (version !== SETTINGS_VERSION && version !== 0 && version !== undefined) {\n return defaultSettings()\n }\n return fieldsFrom(raw)\n}\n\nfunction fieldsFrom(raw: Record<string, unknown>): SettingsV1 {\n const mode = parseLegacyMode(raw[\"mode\"]) ?? \"observe\"\n const tiers = parseTierLists(raw[\"tiers\"]) ?? defaultSettings().tiers\n const pin = parsePin(raw[\"pin\"]) ?? null\n const agentTiers = parseAgentTiers(raw[\"agentTiers\"]) ?? {}\n const inviteDismissed = raw[\"inviteDismissed\"] === true\n return { version: SETTINGS_VERSION, mode, tiers, pin, agentTiers, inviteDismissed }\n}\n\n/**\n * Validate a patch against current settings. The patch is WIRE input (unknown\n * by contract — surfaces send untrusted JSON over RPC; the SettingsPatch type\n * documents the expected shape, the field parsers enforce it). Invalid fields\n * collect error strings (at most one per field, five fields); a valid patch\n * produces a NEW settings object (inputs are never mutated).\n */\nexport function applyPatch(\n current: SettingsV1,\n patch: unknown,\n): { ok: true; settings: SettingsV1 } | { ok: false; errors: string[] } {\n if (!isRecord(patch)) return { ok: false, errors: [\"invalid patch\"] }\n const request = patch as {\n mode?: unknown\n tiers?: unknown\n pin?: unknown\n agentTiers?: unknown\n inviteDismissed?: unknown\n }\n const errors: string[] = []\n let mode = current.mode\n let tiers = current.tiers\n let pin = current.pin\n let agentTiers = current.agentTiers\n let inviteDismissed = current.inviteDismissed\n\n if (request.mode !== undefined) {\n const parsed = parseMode(request.mode)\n if (parsed === undefined) errors.push(\"invalid mode\")\n else mode = parsed\n }\n if (request.tiers !== undefined) {\n const parsed = parseTierListsPatch(request.tiers)\n if (parsed.ok) tiers = parsed.value\n else errors.push(parsed.error)\n }\n // `pin === null` is a meaningful clear and must not read as absence.\n if (request.pin !== undefined) {\n const parsed = parsePin(request.pin)\n if (parsed === undefined) errors.push(\"invalid pin\")\n else pin = parsed\n }\n if (request.agentTiers !== undefined) {\n const parsed = parseAgentTiersPatch(request.agentTiers)\n if (parsed.ok) agentTiers = parsed.value\n else errors.push(parsed.error)\n }\n if (request.inviteDismissed !== undefined) {\n if (typeof request.inviteDismissed !== \"boolean\") errors.push(\"invalid inviteDismissed\")\n else inviteDismissed = request.inviteDismissed\n }\n\n if (errors.length > 0) return { ok: false, errors }\n return {\n ok: true,\n settings: { version: SETTINGS_VERSION, mode, tiers, pin, agentTiers, inviteDismissed },\n }\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PatchResult, SettingsPatch, SettingsStorage, SettingsV1 } from "./types.js";
|
|
2
|
+
export declare class SettingsStore {
|
|
3
|
+
#private;
|
|
4
|
+
private readonly storage;
|
|
5
|
+
constructor(storage: SettingsStorage);
|
|
6
|
+
/** Current snapshot (defaults until the first successful load). */
|
|
7
|
+
get(): SettingsV1;
|
|
8
|
+
/**
|
|
9
|
+
* Read + migrate the persisted record. A storage read failure degrades to
|
|
10
|
+
* defaults instead of breaking setup; the record is not rewritten here, so
|
|
11
|
+
* a later successful patch simply re-stamps the current version.
|
|
12
|
+
*/
|
|
13
|
+
load(): Promise<SettingsV1>;
|
|
14
|
+
/**
|
|
15
|
+
* Validate, persist, then adopt. Invalid patches change nothing. Updates
|
|
16
|
+
* serialize through a promise chain so two concurrent callers cannot both
|
|
17
|
+
* patch the same base snapshot and lose one write (the chain swallows
|
|
18
|
+
* rejections — a failed update must not poison the next one).
|
|
19
|
+
*/
|
|
20
|
+
update(patch: SettingsPatch): Promise<PatchResult>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings store (ADP-036): the server-side single source of truth. Loads
|
|
3
|
+
* once at setup (migration-on-read), serves synchronous snapshots to the
|
|
4
|
+
* scheduler, and persists validated patches. Reads fail open to defaults
|
|
5
|
+
* (ADP-031); write failures propagate to the caller so surfaces can report
|
|
6
|
+
* them — the in-memory snapshot is only advanced after a successful write.
|
|
7
|
+
*/
|
|
8
|
+
import { applyPatch, migrateSettings } from "./parse.js";
|
|
9
|
+
import { defaultSettings } from "./parse.js";
|
|
10
|
+
export class SettingsStore {
|
|
11
|
+
storage;
|
|
12
|
+
#current = defaultSettings();
|
|
13
|
+
/** Tail of the update chain; keeps awaiting updates serialized. */
|
|
14
|
+
#queue = Promise.resolve();
|
|
15
|
+
constructor(storage) {
|
|
16
|
+
this.storage = storage;
|
|
17
|
+
}
|
|
18
|
+
/** Current snapshot (defaults until the first successful load). */
|
|
19
|
+
get() {
|
|
20
|
+
return this.#current;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Read + migrate the persisted record. A storage read failure degrades to
|
|
24
|
+
* defaults instead of breaking setup; the record is not rewritten here, so
|
|
25
|
+
* a later successful patch simply re-stamps the current version.
|
|
26
|
+
*/
|
|
27
|
+
load() {
|
|
28
|
+
// No rejection tail: #load is total (the read is caught and
|
|
29
|
+
// migrateSettings never throws), so run cannot reject and poison the
|
|
30
|
+
// chain — unlike update(), whose write can fail.
|
|
31
|
+
const run = this.#queue.then(() => this.#load());
|
|
32
|
+
this.#queue = run;
|
|
33
|
+
return run;
|
|
34
|
+
}
|
|
35
|
+
async #load() {
|
|
36
|
+
let raw;
|
|
37
|
+
try {
|
|
38
|
+
raw = await this.storage.read();
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
raw = undefined;
|
|
42
|
+
}
|
|
43
|
+
this.#current = migrateSettings(raw);
|
|
44
|
+
return this.#current;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Validate, persist, then adopt. Invalid patches change nothing. Updates
|
|
48
|
+
* serialize through a promise chain so two concurrent callers cannot both
|
|
49
|
+
* patch the same base snapshot and lose one write (the chain swallows
|
|
50
|
+
* rejections — a failed update must not poison the next one).
|
|
51
|
+
*/
|
|
52
|
+
update(patch) {
|
|
53
|
+
const run = this.#queue.then(async () => {
|
|
54
|
+
const result = applyPatch(this.#current, patch);
|
|
55
|
+
if (!result.ok)
|
|
56
|
+
return result;
|
|
57
|
+
await this.storage.write(result.settings);
|
|
58
|
+
this.#current = result.settings;
|
|
59
|
+
return result;
|
|
60
|
+
});
|
|
61
|
+
this.#queue = run.catch(() => undefined);
|
|
62
|
+
return run;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/state/settings/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAExD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,OAAO,aAAa;IAKK;IAJ7B,QAAQ,GAAe,eAAe,EAAE,CAAA;IACxC,mEAAmE;IACnE,MAAM,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAA;IAE5C,YAA6B,OAAwB;QAAxB,YAAO,GAAP,OAAO,CAAiB;IAAG,CAAC;IAEzD,mEAAmE;IACnE,GAAG;QACD,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED;;;;OAIG;IACH,IAAI;QACF,4DAA4D;QAC5D,qEAAqE;QACrE,iDAAiD;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QAChD,IAAI,CAAC,MAAM,GAAG,GAAG,CAAA;QACjB,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,GAAY,CAAA;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,GAAG,SAAS,CAAA;QACjB,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;QACpC,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAoB;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YACtC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;YAC/C,IAAI,CAAC,MAAM,CAAC,EAAE;gBAAE,OAAO,MAAM,CAAA;YAC7B,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YACzC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAA;YAC/B,OAAO,MAAM,CAAA;QACf,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;QACxC,OAAO,GAAG,CAAA;IACZ,CAAC;CACF","sourcesContent":["/**\n * Settings store (ADP-036): the server-side single source of truth. Loads\n * once at setup (migration-on-read), serves synchronous snapshots to the\n * scheduler, and persists validated patches. Reads fail open to defaults\n * (ADP-031); write failures propagate to the caller so surfaces can report\n * them — the in-memory snapshot is only advanced after a successful write.\n */\nimport { applyPatch, migrateSettings } from \"./parse.js\"\nimport type { PatchResult, SettingsPatch, SettingsStorage, SettingsV1 } from \"./types.js\"\nimport { defaultSettings } from \"./parse.js\"\n\nexport class SettingsStore {\n #current: SettingsV1 = defaultSettings()\n /** Tail of the update chain; keeps awaiting updates serialized. */\n #queue: Promise<unknown> = Promise.resolve()\n\n constructor(private readonly storage: SettingsStorage) {}\n\n /** Current snapshot (defaults until the first successful load). */\n get(): SettingsV1 {\n return this.#current\n }\n\n /**\n * Read + migrate the persisted record. A storage read failure degrades to\n * defaults instead of breaking setup; the record is not rewritten here, so\n * a later successful patch simply re-stamps the current version.\n */\n load(): Promise<SettingsV1> {\n // No rejection tail: #load is total (the read is caught and\n // migrateSettings never throws), so run cannot reject and poison the\n // chain — unlike update(), whose write can fail.\n const run = this.#queue.then(() => this.#load())\n this.#queue = run\n return run\n }\n\n async #load(): Promise<SettingsV1> {\n let raw: unknown\n try {\n raw = await this.storage.read()\n } catch {\n raw = undefined\n }\n this.#current = migrateSettings(raw)\n return this.#current\n }\n\n /**\n * Validate, persist, then adopt. Invalid patches change nothing. Updates\n * serialize through a promise chain so two concurrent callers cannot both\n * patch the same base snapshot and lose one write (the chain swallows\n * rejections — a failed update must not poison the next one).\n */\n update(patch: SettingsPatch): Promise<PatchResult> {\n const run = this.#queue.then(async () => {\n const result = applyPatch(this.#current, patch)\n if (!result.ok) return result\n await this.storage.write(result.settings)\n this.#current = result.settings\n return result\n })\n this.#queue = run.catch(() => undefined)\n return run\n }\n}\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable settings (ADP-036): versioned, migrated on read, persisted through
|
|
3
|
+
* `ctx.storage` under a single key. The server plugin owns the store; TUI and
|
|
4
|
+
* GUI surfaces only read snapshots and send patches (ADP-034/036).
|
|
5
|
+
*/
|
|
6
|
+
import type { OperatingMode } from "../../core/scheduler/types.js";
|
|
7
|
+
import type { TierName } from "../../core/tier-policy/types.js";
|
|
8
|
+
import type { ModelRef } from "../../core/work-unit/types.js";
|
|
9
|
+
/** Storage key for the settings record (see architecture "Persistence ownership"). */
|
|
10
|
+
export declare const SETTINGS_KEY = "coool.adaptive/settings";
|
|
11
|
+
/** Current settings schema version. */
|
|
12
|
+
export declare const SETTINGS_VERSION = 1;
|
|
13
|
+
/**
|
|
14
|
+
* Product bounds, not user knobs: they keep a hostile or buggy write from
|
|
15
|
+
* growing state without limit. (Patch error lists need no cap: at most one
|
|
16
|
+
* error per field, and the patch has five fields.)
|
|
17
|
+
*/
|
|
18
|
+
export declare const MAX_TIER_RESOURCES = 32;
|
|
19
|
+
export declare const MAX_AGENT_TIERS = 64;
|
|
20
|
+
export interface SettingsV1 {
|
|
21
|
+
readonly version: typeof SETTINGS_VERSION;
|
|
22
|
+
/** OFF does nothing; OBSERVE is the safe default after install (ADP-029/032). */
|
|
23
|
+
readonly mode: OperatingMode;
|
|
24
|
+
/** Ordered per-tier resource lists; order is user policy and never reordered (ADP-005). */
|
|
25
|
+
readonly tiers: Readonly<Record<TierName, readonly ModelRef[]>>;
|
|
26
|
+
/**
|
|
27
|
+
* Global explicit user pin. `null` = no pin. A pin names a concrete model
|
|
28
|
+
* and outranks every other routing input (ADP-002).
|
|
29
|
+
*/
|
|
30
|
+
readonly pin: ModelRef | null;
|
|
31
|
+
/** User-configured agent → tier hints (role level of the ladder, ADP-002). */
|
|
32
|
+
readonly agentTiers: Readonly<Record<string, TierName>>;
|
|
33
|
+
/** First-install invitation dismissed (ADP-032: shown once, never nagged). */
|
|
34
|
+
readonly inviteDismissed: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Partial update as sent by surfaces over RPC. Field absence means "leave
|
|
38
|
+
* unchanged"; `pin: null` explicitly clears the pin.
|
|
39
|
+
*/
|
|
40
|
+
export interface SettingsPatch {
|
|
41
|
+
readonly mode?: OperatingMode | undefined;
|
|
42
|
+
readonly tiers?: Readonly<Record<TierName, readonly ModelRef[]>> | undefined;
|
|
43
|
+
readonly pin?: ModelRef | null | undefined;
|
|
44
|
+
readonly agentTiers?: Readonly<Record<string, TierName>> | undefined;
|
|
45
|
+
readonly inviteDismissed?: boolean | undefined;
|
|
46
|
+
}
|
|
47
|
+
export type PatchResult = {
|
|
48
|
+
readonly ok: true;
|
|
49
|
+
readonly settings: SettingsV1;
|
|
50
|
+
} | {
|
|
51
|
+
readonly ok: false;
|
|
52
|
+
readonly errors: readonly string[];
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Narrow storage seam so the store stays decoupled from `@opencode/plugin`
|
|
56
|
+
* (only `adapters/opencode` may touch the host API). The adapter binds the
|
|
57
|
+
* settings key and translates `ctx.storage`.
|
|
58
|
+
*/
|
|
59
|
+
export interface SettingsStorage {
|
|
60
|
+
read(): Promise<unknown>;
|
|
61
|
+
write(settings: SettingsV1): Promise<void>;
|
|
62
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Storage key for the settings record (see architecture "Persistence ownership"). */
|
|
2
|
+
export const SETTINGS_KEY = "coool.adaptive/settings";
|
|
3
|
+
/** Current settings schema version. */
|
|
4
|
+
export const SETTINGS_VERSION = 1;
|
|
5
|
+
/**
|
|
6
|
+
* Product bounds, not user knobs: they keep a hostile or buggy write from
|
|
7
|
+
* growing state without limit. (Patch error lists need no cap: at most one
|
|
8
|
+
* error per field, and the patch has five fields.)
|
|
9
|
+
*/
|
|
10
|
+
export const MAX_TIER_RESOURCES = 32;
|
|
11
|
+
export const MAX_AGENT_TIERS = 64;
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/state/settings/types.ts"],"names":[],"mappings":"AASA,sFAAsF;AACtF,MAAM,CAAC,MAAM,YAAY,GAAG,yBAAyB,CAAA;AAErD,uCAAuC;AACvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAA;AAEjC;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAA;AACpC,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAA","sourcesContent":["/**\n * Durable settings (ADP-036): versioned, migrated on read, persisted through\n * `ctx.storage` under a single key. The server plugin owns the store; TUI and\n * GUI surfaces only read snapshots and send patches (ADP-034/036).\n */\nimport type { OperatingMode } from \"../../core/scheduler/types.js\"\nimport type { TierName } from \"../../core/tier-policy/types.js\"\nimport type { ModelRef } from \"../../core/work-unit/types.js\"\n\n/** Storage key for the settings record (see architecture \"Persistence ownership\"). */\nexport const SETTINGS_KEY = \"coool.adaptive/settings\"\n\n/** Current settings schema version. */\nexport const SETTINGS_VERSION = 1\n\n/**\n * Product bounds, not user knobs: they keep a hostile or buggy write from\n * growing state without limit. (Patch error lists need no cap: at most one\n * error per field, and the patch has five fields.)\n */\nexport const MAX_TIER_RESOURCES = 32\nexport const MAX_AGENT_TIERS = 64\n\nexport interface SettingsV1 {\n readonly version: typeof SETTINGS_VERSION\n /** OFF does nothing; OBSERVE is the safe default after install (ADP-029/032). */\n readonly mode: OperatingMode\n /** Ordered per-tier resource lists; order is user policy and never reordered (ADP-005). */\n readonly tiers: Readonly<Record<TierName, readonly ModelRef[]>>\n /**\n * Global explicit user pin. `null` = no pin. A pin names a concrete model\n * and outranks every other routing input (ADP-002).\n */\n readonly pin: ModelRef | null\n /** User-configured agent → tier hints (role level of the ladder, ADP-002). */\n readonly agentTiers: Readonly<Record<string, TierName>>\n /** First-install invitation dismissed (ADP-032: shown once, never nagged). */\n readonly inviteDismissed: boolean\n}\n\n/**\n * Partial update as sent by surfaces over RPC. Field absence means \"leave\n * unchanged\"; `pin: null` explicitly clears the pin.\n */\nexport interface SettingsPatch {\n readonly mode?: OperatingMode | undefined\n readonly tiers?: Readonly<Record<TierName, readonly ModelRef[]>> | undefined\n readonly pin?: ModelRef | null | undefined\n readonly agentTiers?: Readonly<Record<string, TierName>> | undefined\n readonly inviteDismissed?: boolean | undefined\n}\n\nexport type PatchResult =\n | { readonly ok: true; readonly settings: SettingsV1 }\n | {\n readonly ok: false\n readonly errors: readonly string[]\n }\n\n/**\n * Narrow storage seam so the store stays decoupled from `@opencode/plugin`\n * (only `adapters/opencode` may touch the host API). The adapter binds the\n * settings key and translates `ctx.storage`.\n */\nexport interface SettingsStorage {\n read(): Promise<unknown>\n write(settings: SettingsV1): Promise<void>\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { parseTierRequestsPayload, isValidSessionID } from "./parse.js";
|
|
2
|
+
export { TierRequestStore } from "./store.js";
|
|
3
|
+
export { TIER_REQUESTS_KEY, TIER_REQUESTS_VERSION, MAX_TIER_REQUEST_RECORDS, MAX_SESSION_ID_LENGTH, } from "./types.js";
|
|
4
|
+
export type { TierRequestRecord, TierRequestsPayload, TierRequestsStorage } from "./types.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { parseTierRequestsPayload, isValidSessionID } from "./parse.js";
|
|
2
|
+
export { TierRequestStore } from "./store.js";
|
|
3
|
+
export { TIER_REQUESTS_KEY, TIER_REQUESTS_VERSION, MAX_TIER_REQUEST_RECORDS, MAX_SESSION_ID_LENGTH, } from "./types.js";
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/state/tier-requests/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,YAAY,CAAA","sourcesContent":["export { parseTierRequestsPayload, isValidSessionID } from \"./parse.js\"\nexport { TierRequestStore } from \"./store.js\"\nexport {\n TIER_REQUESTS_KEY,\n TIER_REQUESTS_VERSION,\n MAX_TIER_REQUEST_RECORDS,\n MAX_SESSION_ID_LENGTH,\n} from \"./types.js\"\nexport type { TierRequestRecord, TierRequestsPayload, TierRequestsStorage } from \"./types.js\"\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-side parsing for persisted tier requests. Total like every `state/`
|
|
3
|
+
* parser: it accepts `unknown` and returns typed records, dropping anything
|
|
4
|
+
* invalid — a corrupted file can never take the plugin down (ADP-031). A
|
|
5
|
+
* partially corrupted payload keeps its good entries.
|
|
6
|
+
*/
|
|
7
|
+
import { TIERS } from "../../core/tier-policy/types.js";
|
|
8
|
+
import { isValidSessionID } from "../session-modes/parse.js";
|
|
9
|
+
import { TIER_REQUESTS_VERSION } from "./types.js";
|
|
10
|
+
export { isValidSessionID } from "../session-modes/parse.js";
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
function isFiniteNumber(raw) {
|
|
15
|
+
return typeof raw === "number" && Number.isFinite(raw);
|
|
16
|
+
}
|
|
17
|
+
function parseTier(raw) {
|
|
18
|
+
if (typeof raw !== "string")
|
|
19
|
+
return undefined;
|
|
20
|
+
return TIERS.includes(raw) ? raw : undefined;
|
|
21
|
+
}
|
|
22
|
+
function parseRecord(raw) {
|
|
23
|
+
if (!isRecord(raw))
|
|
24
|
+
return undefined;
|
|
25
|
+
const sessionID = isValidSessionID(raw["sessionID"]) ? raw["sessionID"] : undefined;
|
|
26
|
+
const tier = parseTier(raw["tier"]);
|
|
27
|
+
const updatedAt = raw["updatedAt"];
|
|
28
|
+
if (sessionID === undefined || tier === undefined || !isFiniteNumber(updatedAt))
|
|
29
|
+
return undefined;
|
|
30
|
+
return { sessionID, tier, updatedAt };
|
|
31
|
+
}
|
|
32
|
+
export function parseTierRequestsPayload(raw) {
|
|
33
|
+
if (!isRecord(raw))
|
|
34
|
+
return [];
|
|
35
|
+
if (raw["version"] !== TIER_REQUESTS_VERSION)
|
|
36
|
+
return [];
|
|
37
|
+
const list = raw["records"];
|
|
38
|
+
if (!Array.isArray(list))
|
|
39
|
+
return [];
|
|
40
|
+
// A hostile or duplicated payload can carry the same session twice; the
|
|
41
|
+
// most recently updated record wins so `get` is not order-dependent.
|
|
42
|
+
const bySession = new Map();
|
|
43
|
+
for (const entry of list.slice(0, 512)) {
|
|
44
|
+
const record = parseRecord(entry);
|
|
45
|
+
if (record === undefined)
|
|
46
|
+
continue;
|
|
47
|
+
const kept = bySession.get(record.sessionID);
|
|
48
|
+
if (kept === undefined || record.updatedAt > kept.updatedAt)
|
|
49
|
+
bySession.set(record.sessionID, record);
|
|
50
|
+
}
|
|
51
|
+
return [...bySession.values()];
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../src/state/tier-requests/parse.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAA;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAGlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAE5D,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC7E,CAAC;AAED,SAAS,cAAc,CAAC,GAAY;IAClC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;AACxD,CAAC;AAED,SAAS,SAAS,CAAC,GAAY;IAC7B,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAA;IAC7C,OAAQ,KAA2B,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,GAAgB,CAAC,CAAC,CAAC,SAAS,CAAA;AACnF,CAAC;AAED,SAAS,WAAW,CAAC,GAAY;IAC/B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IACpC,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACnF,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;IACnC,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,CAAC,CAAA;IAClC,IAAI,SAAS,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAA;IACjG,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,GAAY;IACnD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAA;IAC7B,IAAI,GAAG,CAAC,SAAS,CAAC,KAAK,qBAAqB;QAAE,OAAO,EAAE,CAAA;IACvD,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,CAAA;IAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAA;IACnC,wEAAwE;IACxE,qEAAqE;IACrE,MAAM,SAAS,GAAG,IAAI,GAAG,EAA6B,CAAA;IACtD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAA;QACjC,IAAI,MAAM,KAAK,SAAS;YAAE,SAAQ;QAClC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAC5C,IAAI,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS;YACzD,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IAC3C,CAAC;IACD,OAAO,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAA;AAChC,CAAC","sourcesContent":["/**\n * Read-side parsing for persisted tier requests. Total like every `state/`\n * parser: it accepts `unknown` and returns typed records, dropping anything\n * invalid — a corrupted file can never take the plugin down (ADP-031). A\n * partially corrupted payload keeps its good entries.\n */\nimport { TIERS } from \"../../core/tier-policy/types.js\"\nimport type { TierName } from \"../../core/tier-policy/types.js\"\nimport { isValidSessionID } from \"../session-modes/parse.js\"\nimport { TIER_REQUESTS_VERSION } from \"./types.js\"\nimport type { TierRequestRecord } from \"./types.js\"\n\nexport { isValidSessionID } from \"../session-modes/parse.js\"\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction isFiniteNumber(raw: unknown): raw is number {\n return typeof raw === \"number\" && Number.isFinite(raw)\n}\n\nfunction parseTier(raw: unknown): TierName | undefined {\n if (typeof raw !== \"string\") return undefined\n return (TIERS as readonly string[]).includes(raw) ? (raw as TierName) : undefined\n}\n\nfunction parseRecord(raw: unknown): TierRequestRecord | undefined {\n if (!isRecord(raw)) return undefined\n const sessionID = isValidSessionID(raw[\"sessionID\"]) ? raw[\"sessionID\"] : undefined\n const tier = parseTier(raw[\"tier\"])\n const updatedAt = raw[\"updatedAt\"]\n if (sessionID === undefined || tier === undefined || !isFiniteNumber(updatedAt)) return undefined\n return { sessionID, tier, updatedAt }\n}\n\nexport function parseTierRequestsPayload(raw: unknown): TierRequestRecord[] {\n if (!isRecord(raw)) return []\n if (raw[\"version\"] !== TIER_REQUESTS_VERSION) return []\n const list = raw[\"records\"]\n if (!Array.isArray(list)) return []\n // A hostile or duplicated payload can carry the same session twice; the\n // most recently updated record wins so `get` is not order-dependent.\n const bySession = new Map<string, TierRequestRecord>()\n for (const entry of list.slice(0, 512)) {\n const record = parseRecord(entry)\n if (record === undefined) continue\n const kept = bySession.get(record.sessionID)\n if (kept === undefined || record.updatedAt > kept.updatedAt)\n bySession.set(record.sessionID, record)\n }\n return [...bySession.values()]\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TierName } from "../../core/tier-policy/types.js";
|
|
2
|
+
import type { TierRequestRecord, TierRequestsStorage } from "./types.js";
|
|
3
|
+
export declare class TierRequestStore {
|
|
4
|
+
#private;
|
|
5
|
+
private readonly storage;
|
|
6
|
+
private readonly clock;
|
|
7
|
+
constructor(storage: TierRequestsStorage, clock: () => number);
|
|
8
|
+
/** Rebuild from storage (restart behavior). A read failure yields an empty store. */
|
|
9
|
+
load(): Promise<void>;
|
|
10
|
+
/** All retained records. */
|
|
11
|
+
snapshot(): readonly TierRequestRecord[];
|
|
12
|
+
/** The session's request, or `null` when it follows the routing ladder. */
|
|
13
|
+
get(sessionID: string): TierName | null;
|
|
14
|
+
/**
|
|
15
|
+
* Set (or with `null`, remove) one session's request. The bound keeps the
|
|
16
|
+
* most recently updated records — requests for long-gone sessions matter
|
|
17
|
+
* less than the ones being actively steered.
|
|
18
|
+
*/
|
|
19
|
+
set(sessionID: string, tier: TierName | null): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Resolve only after every operation queued before this call has committed.
|
|
22
|
+
* The `adaptive_tier` tool records its request fire-and-forget (the tool
|
|
23
|
+
* handler is sync on the RPC surface), so readers — routing and the control
|
|
24
|
+
* surfaces — flush before reading to observe it deterministically.
|
|
25
|
+
*/
|
|
26
|
+
flush(): Promise<void>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded per-session tier-request store. Keeps the most recently updated
|
|
3
|
+
* records (bounded, least-recently-updated evicted) and persists on every
|
|
4
|
+
* change. As everywhere else in `state/`, memory is only advanced after a
|
|
5
|
+
* successful write, so memory and disk never diverge; write failures
|
|
6
|
+
* propagate to the caller — the wiring layer's fail-open wrapper decides how
|
|
7
|
+
* to degrade (ADP-031).
|
|
8
|
+
*/
|
|
9
|
+
import { TIERS, isTierName } from "../../core/tier-policy/types.js";
|
|
10
|
+
import { parseTierRequestsPayload, isValidSessionID } from "./parse.js";
|
|
11
|
+
import { MAX_SESSION_ID_LENGTH, MAX_TIER_REQUEST_RECORDS, TIER_REQUESTS_VERSION } from "./types.js";
|
|
12
|
+
export class TierRequestStore {
|
|
13
|
+
storage;
|
|
14
|
+
clock;
|
|
15
|
+
#records = [];
|
|
16
|
+
#queue = Promise.resolve();
|
|
17
|
+
constructor(storage, clock) {
|
|
18
|
+
this.storage = storage;
|
|
19
|
+
this.clock = clock;
|
|
20
|
+
}
|
|
21
|
+
/** Rebuild from storage (restart behavior). A read failure yields an empty store. */
|
|
22
|
+
load() {
|
|
23
|
+
return this.#serialize(() => this.#load());
|
|
24
|
+
}
|
|
25
|
+
async #load() {
|
|
26
|
+
let raw;
|
|
27
|
+
try {
|
|
28
|
+
raw = await this.storage.read();
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
this.#records = [];
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.#records = parseTierRequestsPayload(raw);
|
|
35
|
+
}
|
|
36
|
+
/** All retained records. */
|
|
37
|
+
snapshot() {
|
|
38
|
+
return this.#records;
|
|
39
|
+
}
|
|
40
|
+
/** The session's request, or `null` when it follows the routing ladder. */
|
|
41
|
+
get(sessionID) {
|
|
42
|
+
return this.#records.find((record) => record.sessionID === sessionID)?.tier ?? null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Set (or with `null`, remove) one session's request. The bound keeps the
|
|
46
|
+
* most recently updated records — requests for long-gone sessions matter
|
|
47
|
+
* less than the ones being actively steered.
|
|
48
|
+
*/
|
|
49
|
+
async set(sessionID, tier) {
|
|
50
|
+
// Defensive re-validation at the persistence boundary: the tool and the
|
|
51
|
+
// RPC handler validate first; these guards keep malformed in-process
|
|
52
|
+
// callers from persisting junk.
|
|
53
|
+
if (!isValidSessionID(sessionID)) {
|
|
54
|
+
throw new Error(`sessionID must be a non-empty string of at most ${String(MAX_SESSION_ID_LENGTH)} characters`);
|
|
55
|
+
}
|
|
56
|
+
if (tier !== null && !isTierName(tier)) {
|
|
57
|
+
throw new Error(`tier must be one of ${TIERS.join(", ")} or null`);
|
|
58
|
+
}
|
|
59
|
+
return this.#serialize(() => this.#set(sessionID, tier));
|
|
60
|
+
}
|
|
61
|
+
async #set(sessionID, tier) {
|
|
62
|
+
const updatedAt = this.clock();
|
|
63
|
+
const kept = this.#records.filter((record) => record.sessionID !== sessionID);
|
|
64
|
+
const next = tier === null
|
|
65
|
+
? kept
|
|
66
|
+
: bound([...kept, { sessionID, tier, updatedAt }], MAX_TIER_REQUEST_RECORDS);
|
|
67
|
+
// Persist BEFORE committing memory: a write failure must leave memory
|
|
68
|
+
// and disk consistent (the caller decides how to fail open).
|
|
69
|
+
const payload = { version: TIER_REQUESTS_VERSION, records: next };
|
|
70
|
+
await this.storage.write(payload);
|
|
71
|
+
this.#records = next;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Resolve only after every operation queued before this call has committed.
|
|
75
|
+
* The `adaptive_tier` tool records its request fire-and-forget (the tool
|
|
76
|
+
* handler is sync on the RPC surface), so readers — routing and the control
|
|
77
|
+
* surfaces — flush before reading to observe it deterministically.
|
|
78
|
+
*/
|
|
79
|
+
flush() {
|
|
80
|
+
return this.#serialize(() => Promise.resolve());
|
|
81
|
+
}
|
|
82
|
+
// Reloads share the mutation queue so stale reads cannot overwrite commits.
|
|
83
|
+
// Recover only the queue tail: the failed operation still rejects its caller.
|
|
84
|
+
#serialize(operation) {
|
|
85
|
+
const run = this.#queue.then(operation);
|
|
86
|
+
this.#queue = run.catch(() => undefined);
|
|
87
|
+
return run;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Keep the newest records when over the cap. */
|
|
91
|
+
function bound(records, max) {
|
|
92
|
+
if (records.length <= max)
|
|
93
|
+
return records;
|
|
94
|
+
return [...records].sort((left, right) => right.updatedAt - left.updatedAt).slice(0, max);
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/state/tier-requests/store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACvE,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAInG,MAAM,OAAO,gBAAgB;IAKR;IACA;IALnB,QAAQ,GAAwB,EAAE,CAAA;IAClC,MAAM,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAA;IAEzC,YACmB,OAA4B,EAC5B,KAAmB;QADnB,YAAO,GAAP,OAAO,CAAqB;QAC5B,UAAK,GAAL,KAAK,CAAc;IACnC,CAAC;IAEJ,qFAAqF;IACrF,IAAI;QACF,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,GAAY,CAAA;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;YAClB,OAAM;QACR,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAA;IAC/C,CAAC;IAED,4BAA4B;IAC5B,QAAQ;QACN,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED,2EAA2E;IAC3E,GAAG,CAAC,SAAiB;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,EAAE,IAAI,IAAI,IAAI,CAAA;IACrF,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,GAAG,CAAC,SAAiB,EAAE,IAAqB;QAChD,wEAAwE;QACxE,qEAAqE;QACrE,gCAAgC;QAChC,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,mDAAmD,MAAM,CAAC,qBAAqB,CAAC,aAAa,CAC9F,CAAA;QACH,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACpE,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAA;IAC1D,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAiB,EAAE,IAAqB;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAA;QAC7E,MAAM,IAAI,GACR,IAAI,KAAK,IAAI;YACX,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,wBAAwB,CAAC,CAAA;QAChF,sEAAsE;QACtE,6DAA6D;QAC7D,MAAM,OAAO,GAAwB,EAAE,OAAO,EAAE,qBAAqB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QACtF,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACjC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;IACtB,CAAC;IAED;;;;;OAKG;IACH,KAAK;QACH,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IACjD,CAAC;IAED,4EAA4E;IAC5E,8EAA8E;IAC9E,UAAU,CAAC,SAA8B;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACvC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;QACxC,OAAO,GAAG,CAAA;IACZ,CAAC;CACF;AAED,iDAAiD;AACjD,SAAS,KAAK,CAAC,OAA4B,EAAE,GAAW;IACtD,IAAI,OAAO,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,OAAO,CAAA;IACzC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAC3F,CAAC","sourcesContent":["/**\n * Bounded per-session tier-request store. Keeps the most recently updated\n * records (bounded, least-recently-updated evicted) and persists on every\n * change. As everywhere else in `state/`, memory is only advanced after a\n * successful write, so memory and disk never diverge; write failures\n * propagate to the caller — the wiring layer's fail-open wrapper decides how\n * to degrade (ADP-031).\n */\nimport { TIERS, isTierName } from \"../../core/tier-policy/types.js\"\nimport { parseTierRequestsPayload, isValidSessionID } from \"./parse.js\"\nimport { MAX_SESSION_ID_LENGTH, MAX_TIER_REQUEST_RECORDS, TIER_REQUESTS_VERSION } from \"./types.js\"\nimport type { TierName } from \"../../core/tier-policy/types.js\"\nimport type { TierRequestRecord, TierRequestsPayload, TierRequestsStorage } from \"./types.js\"\n\nexport class TierRequestStore {\n #records: TierRequestRecord[] = []\n #queue: Promise<void> = Promise.resolve()\n\n constructor(\n private readonly storage: TierRequestsStorage,\n private readonly clock: () => number,\n ) {}\n\n /** Rebuild from storage (restart behavior). A read failure yields an empty store. */\n load(): Promise<void> {\n return this.#serialize(() => this.#load())\n }\n\n async #load(): Promise<void> {\n let raw: unknown\n try {\n raw = await this.storage.read()\n } catch {\n this.#records = []\n return\n }\n this.#records = parseTierRequestsPayload(raw)\n }\n\n /** All retained records. */\n snapshot(): readonly TierRequestRecord[] {\n return this.#records\n }\n\n /** The session's request, or `null` when it follows the routing ladder. */\n get(sessionID: string): TierName | null {\n return this.#records.find((record) => record.sessionID === sessionID)?.tier ?? null\n }\n\n /**\n * Set (or with `null`, remove) one session's request. The bound keeps the\n * most recently updated records — requests for long-gone sessions matter\n * less than the ones being actively steered.\n */\n async set(sessionID: string, tier: TierName | null): Promise<void> {\n // Defensive re-validation at the persistence boundary: the tool and the\n // RPC handler validate first; these guards keep malformed in-process\n // callers from persisting junk.\n if (!isValidSessionID(sessionID)) {\n throw new Error(\n `sessionID must be a non-empty string of at most ${String(MAX_SESSION_ID_LENGTH)} characters`,\n )\n }\n if (tier !== null && !isTierName(tier)) {\n throw new Error(`tier must be one of ${TIERS.join(\", \")} or null`)\n }\n return this.#serialize(() => this.#set(sessionID, tier))\n }\n\n async #set(sessionID: string, tier: TierName | null): Promise<void> {\n const updatedAt = this.clock()\n const kept = this.#records.filter((record) => record.sessionID !== sessionID)\n const next =\n tier === null\n ? kept\n : bound([...kept, { sessionID, tier, updatedAt }], MAX_TIER_REQUEST_RECORDS)\n // Persist BEFORE committing memory: a write failure must leave memory\n // and disk consistent (the caller decides how to fail open).\n const payload: TierRequestsPayload = { version: TIER_REQUESTS_VERSION, records: next }\n await this.storage.write(payload)\n this.#records = next\n }\n\n /**\n * Resolve only after every operation queued before this call has committed.\n * The `adaptive_tier` tool records its request fire-and-forget (the tool\n * handler is sync on the RPC surface), so readers — routing and the control\n * surfaces — flush before reading to observe it deterministically.\n */\n flush(): Promise<void> {\n return this.#serialize(() => Promise.resolve())\n }\n\n // Reloads share the mutation queue so stale reads cannot overwrite commits.\n // Recover only the queue tail: the failed operation still rejects its caller.\n #serialize(operation: () => Promise<void>): Promise<void> {\n const run = this.#queue.then(operation)\n this.#queue = run.catch(() => undefined)\n return run\n }\n}\n\n/** Keep the newest records when over the cap. */\nfunction bound(records: TierRequestRecord[], max: number): TierRequestRecord[] {\n if (records.length <= max) return records\n return [...records].sort((left, right) => right.updatedAt - left.updatedAt).slice(0, max)\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persisted per-session tier requests (ADP-055). The agent declares the tier
|
|
3
|
+
* of the task it is starting through the `adaptive_tier` tool and the request
|
|
4
|
+
* steers the session's admissions until cleared. The host's TUI-mode plugin
|
|
5
|
+
* reconciliation can serve RPC from an instance whose routing hooks live on
|
|
6
|
+
* another instance, and a restart must not silently drop the agent's explicit
|
|
7
|
+
* declaration — the records persist through the storage seam like every other
|
|
8
|
+
* state (mirroring the session-mode overrides, ADP-054).
|
|
9
|
+
*/
|
|
10
|
+
import type { TierName } from "../../core/tier-policy/types.js";
|
|
11
|
+
export declare const TIER_REQUESTS_KEY = "coool.adaptive/tier-requests";
|
|
12
|
+
export declare const TIER_REQUESTS_VERSION = 1;
|
|
13
|
+
/** Product bound — not a user knob. Keeps the most recently updated records. */
|
|
14
|
+
export declare const MAX_TIER_REQUEST_RECORDS = 512;
|
|
15
|
+
/** A session id beyond this bound is not a real host identifier. */
|
|
16
|
+
export declare const MAX_SESSION_ID_LENGTH = 128;
|
|
17
|
+
export interface TierRequestRecord {
|
|
18
|
+
readonly sessionID: string;
|
|
19
|
+
readonly tier: TierName;
|
|
20
|
+
readonly updatedAt: number;
|
|
21
|
+
}
|
|
22
|
+
export interface TierRequestsPayload {
|
|
23
|
+
readonly version: typeof TIER_REQUESTS_VERSION;
|
|
24
|
+
readonly records: readonly TierRequestRecord[];
|
|
25
|
+
}
|
|
26
|
+
/** Storage seam — the adapter binds `TIER_REQUESTS_KEY` to `ctx.storage`. */
|
|
27
|
+
export interface TierRequestsStorage {
|
|
28
|
+
read(): Promise<unknown>;
|
|
29
|
+
write(payload: TierRequestsPayload): Promise<void>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const TIER_REQUESTS_KEY = "coool.adaptive/tier-requests";
|
|
2
|
+
export const TIER_REQUESTS_VERSION = 1;
|
|
3
|
+
/** Product bound — not a user knob. Keeps the most recently updated records. */
|
|
4
|
+
export const MAX_TIER_REQUEST_RECORDS = 512;
|
|
5
|
+
/** A session id beyond this bound is not a real host identifier. */
|
|
6
|
+
export const MAX_SESSION_ID_LENGTH = 128;
|
|
7
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/state/tier-requests/types.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,iBAAiB,GAAG,8BAA8B,CAAA;AAC/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAA;AACtC,gFAAgF;AAChF,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAA;AAC3C,oEAAoE;AACpE,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAA","sourcesContent":["/**\n * Persisted per-session tier requests (ADP-055). The agent declares the tier\n * of the task it is starting through the `adaptive_tier` tool and the request\n * steers the session's admissions until cleared. The host's TUI-mode plugin\n * reconciliation can serve RPC from an instance whose routing hooks live on\n * another instance, and a restart must not silently drop the agent's explicit\n * declaration — the records persist through the storage seam like every other\n * state (mirroring the session-mode overrides, ADP-054).\n */\nimport type { TierName } from \"../../core/tier-policy/types.js\"\n\nexport const TIER_REQUESTS_KEY = \"coool.adaptive/tier-requests\"\nexport const TIER_REQUESTS_VERSION = 1\n/** Product bound — not a user knob. Keeps the most recently updated records. */\nexport const MAX_TIER_REQUEST_RECORDS = 512\n/** A session id beyond this bound is not a real host identifier. */\nexport const MAX_SESSION_ID_LENGTH = 128\n\nexport interface TierRequestRecord {\n readonly sessionID: string\n readonly tier: TierName\n readonly updatedAt: number\n}\n\nexport interface TierRequestsPayload {\n readonly version: typeof TIER_REQUESTS_VERSION\n readonly records: readonly TierRequestRecord[]\n}\n\n/** Storage seam — the adapter binds `TIER_REQUESTS_KEY` to `ctx.storage`. */\nexport interface TierRequestsStorage {\n read(): Promise<unknown>\n write(payload: TierRequestsPayload): Promise<void>\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/supervisor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA","sourcesContent":["export { LOG_ERROR_LENGTH, logFailOpen } from \"./log.js\"\nexport { Supervisor } from \"./supervisor.js\"\nexport { CODEX_PROVIDER_ID } from \"./types.js\"\nexport type { RetryHookInput, SupervisorOptions, SupervisorSessionSource } from \"./types.js\"\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fail-open logging (ADP-031). The supervisor never throws from its public
|
|
3
|
+
* entry points; unexpected failures are logged with a bounded scope line and
|
|
4
|
+
* swallowed. Logging is the degradation path, not a channel for secrets —
|
|
5
|
+
* only the error's string form, bounded, is emitted.
|
|
6
|
+
*/
|
|
7
|
+
/** Bound for the logged error text (bounded diagnostics, ADP-030 spirit). */
|
|
8
|
+
export declare const LOG_ERROR_LENGTH = 200;
|
|
9
|
+
/** Log one swallowed internal failure under the plugin's namespace. */
|
|
10
|
+
export declare function logFailOpen(scope: string, error: unknown): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fail-open logging (ADP-031). The supervisor never throws from its public
|
|
3
|
+
* entry points; unexpected failures are logged with a bounded scope line and
|
|
4
|
+
* swallowed. Logging is the degradation path, not a channel for secrets —
|
|
5
|
+
* only the error's string form, bounded, is emitted.
|
|
6
|
+
*/
|
|
7
|
+
/** Bound for the logged error text (bounded diagnostics, ADP-030 spirit). */
|
|
8
|
+
export const LOG_ERROR_LENGTH = 200;
|
|
9
|
+
/** Log one swallowed internal failure under the plugin's namespace. */
|
|
10
|
+
export function logFailOpen(scope, error) {
|
|
11
|
+
const detail = String(error).slice(0, LOG_ERROR_LENGTH);
|
|
12
|
+
console.error(`[coool.adaptive] ${scope}: ${detail}`);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/supervisor/log.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,6EAA6E;AAC7E,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAA;AAEnC,uEAAuE;AACvE,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,KAAc;IACvD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAA;IACvD,OAAO,CAAC,KAAK,CAAC,oBAAoB,KAAK,KAAK,MAAM,EAAE,CAAC,CAAA;AACvD,CAAC","sourcesContent":["/**\n * Fail-open logging (ADP-031). The supervisor never throws from its public\n * entry points; unexpected failures are logged with a bounded scope line and\n * swallowed. Logging is the degradation path, not a channel for secrets —\n * only the error's string form, bounded, is emitted.\n */\n\n/** Bound for the logged error text (bounded diagnostics, ADP-030 spirit). */\nexport const LOG_ERROR_LENGTH = 200\n\n/** Log one swallowed internal failure under the plugin's namespace. */\nexport function logFailOpen(scope: string, error: unknown): void {\n const detail = String(error).slice(0, LOG_ERROR_LENGTH)\n console.error(`[coool.adaptive] ${scope}: ${detail}`)\n}\n"]}
|