zidane 9.1.3 → 9.1.4

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.
Files changed (73) hide show
  1. package/dist/{acp-CeCavNlg.js → acp-Cl4gCZN6.js} +3 -3
  2. package/dist/{acp-CeCavNlg.js.map → acp-Cl4gCZN6.js.map} +1 -1
  3. package/dist/acp-cli.js +4 -4
  4. package/dist/acp.js +1 -1
  5. package/dist/{auth-store-port-BKpjlJ8a.js → auth-store-port-DBl2JUC6.js} +2 -2
  6. package/dist/{auth-store-port-BKpjlJ8a.js.map → auth-store-port-DBl2JUC6.js.map} +1 -1
  7. package/dist/{auto-update-restart-CQJtndMG.js → auto-update-restart-CF_kjcJd.js} +10 -10
  8. package/dist/{auto-update-restart-CQJtndMG.js.map → auto-update-restart-CF_kjcJd.js.map} +1 -1
  9. package/dist/chat.js +9 -9
  10. package/dist/{cli-shared-DeRHgYvl.js → cli-shared-DIV9c5Nr.js} +3 -3
  11. package/dist/{cli-shared-DeRHgYvl.js.map → cli-shared-DIV9c5Nr.js.map} +1 -1
  12. package/dist/{credentials-Bqg-qNBM.js → credentials-D71duF64.js} +2 -2
  13. package/dist/{credentials-Bqg-qNBM.js.map → credentials-D71duF64.js.map} +1 -1
  14. package/dist/daemon-cli.js +2 -2
  15. package/dist/{discovery-CX7nbMCn.js → discovery-DD4wPWKS.js} +4 -4
  16. package/dist/{discovery-CX7nbMCn.js.map → discovery-DD4wPWKS.js.map} +1 -1
  17. package/dist/{engine-CxBGgU94.js → engine-BDmtgr2O.js} +3 -3
  18. package/dist/{engine-CxBGgU94.js.map → engine-BDmtgr2O.js.map} +1 -1
  19. package/dist/{executor-j_LFRBwS.js → executor-EWOhLyd9.js} +2 -2
  20. package/dist/{executor-j_LFRBwS.js.map → executor-EWOhLyd9.js.map} +1 -1
  21. package/dist/extensions/testing.js +2 -2
  22. package/dist/{extensions-ADlhBQ_1.js → extensions-DklXPjiq.js} +6 -6
  23. package/dist/{extensions-ADlhBQ_1.js.map → extensions-DklXPjiq.js.map} +1 -1
  24. package/dist/extensions.js +5 -5
  25. package/dist/{google-B-Dhmzzf.js → google-BtMW9KzL.js} +2 -2
  26. package/dist/{google-B-Dhmzzf.js.map → google-BtMW9KzL.js.map} +1 -1
  27. package/dist/{host-signals-Cb2TlGtN.js → host-signals-91zyko_i.js} +5 -5
  28. package/dist/{host-signals-Cb2TlGtN.js.map → host-signals-91zyko_i.js.map} +1 -1
  29. package/dist/{host-C61ntFBC.js → host-uP3t08w8.js} +9 -9
  30. package/dist/{host-C61ntFBC.js.map → host-uP3t08w8.js.map} +1 -1
  31. package/dist/{host-version-BIx4CuBM.js → host-version-_RHlAB29.js} +2 -2
  32. package/dist/{host-version-BIx4CuBM.js.map → host-version-_RHlAB29.js.map} +1 -1
  33. package/dist/index.js +5 -5
  34. package/dist/ipc/remote.js +3 -3
  35. package/dist/{ipc-DiH_P-wr.js → ipc-CatnsVEd.js} +4 -4
  36. package/dist/{ipc-DiH_P-wr.js.map → ipc-CatnsVEd.js.map} +1 -1
  37. package/dist/ipc.js +4 -4
  38. package/dist/{links-BbC_lOnn.js → links-a8C9eby4.js} +8 -8
  39. package/dist/{links-BbC_lOnn.js.map → links-a8C9eby4.js.map} +1 -1
  40. package/dist/{loaded-entry-C0vkCVNQ.js → loaded-entry-D6jzt5HQ.js} +2 -2
  41. package/dist/{loaded-entry-C0vkCVNQ.js.map → loaded-entry-D6jzt5HQ.js.map} +1 -1
  42. package/dist/{memory-C3w8nO8f.js → memory-CJy52DNi.js} +15 -15
  43. package/dist/{memory-C3w8nO8f.js.map → memory-CJy52DNi.js.map} +1 -1
  44. package/dist/{path-display-DRAEpKOU.js → path-display-CAWz-sMq.js} +3 -3
  45. package/dist/{path-display-DRAEpKOU.js.map → path-display-CAWz-sMq.js.map} +1 -1
  46. package/dist/providers/google.js +1 -1
  47. package/dist/{providers-CpXV_uLE.js → providers-zVRxiJDv.js} +2 -2
  48. package/dist/{providers-CpXV_uLE.js.map → providers-zVRxiJDv.js.map} +1 -1
  49. package/dist/providers.js +1 -1
  50. package/dist/{registry-CJHvmvaP.js → registry-CBoYDIND.js} +2 -2
  51. package/dist/{registry-CJHvmvaP.js.map → registry-CBoYDIND.js.map} +1 -1
  52. package/dist/{registry-CN6JlZKj.js → registry-CQOU5jvF.js} +2 -2
  53. package/dist/{registry-CN6JlZKj.js.map → registry-CQOU5jvF.js.map} +1 -1
  54. package/dist/{registry-CnnKaY9s.js → registry-YUUqbYGr.js} +2 -2
  55. package/dist/{registry-CnnKaY9s.js.map → registry-YUUqbYGr.js.map} +1 -1
  56. package/dist/{remote-hosts-DoO9CJUQ.js → remote-hosts-CT8Q95dR.js} +4 -4
  57. package/dist/{remote-hosts-DoO9CJUQ.js.map → remote-hosts-CT8Q95dR.js.map} +1 -1
  58. package/dist/{setting-D_FpKFMw.js → setting-_jh2OtiL.js} +2 -2
  59. package/dist/{setting-D_FpKFMw.js.map → setting-_jh2OtiL.js.map} +1 -1
  60. package/dist/{settings-keys-CW2UgHgb.js → settings-keys-BT0_oKjO.js} +2 -2
  61. package/dist/{settings-keys-CW2UgHgb.js.map → settings-keys-BT0_oKjO.js.map} +1 -1
  62. package/dist/{system-freeze-XgDPIwQS.js → system-freeze-DxJ-lRhu.js} +2 -2
  63. package/dist/{system-freeze-XgDPIwQS.js.map → system-freeze-DxJ-lRhu.js.map} +1 -1
  64. package/dist/tui.js +15 -15
  65. package/dist/{version-szdW1Od9.js → version-DwQI12WA.js} +2 -2
  66. package/dist/{version-szdW1Od9.js.map → version-DwQI12WA.js.map} +1 -1
  67. package/dist/{wire-C3l9jl9x.js → wire-Dxwxb7QQ.js} +2 -2
  68. package/dist/{wire-C3l9jl9x.js.map → wire-Dxwxb7QQ.js.map} +1 -1
  69. package/dist/{ws-CEHi0CiB.js → ws-CA3o2nie.js} +4 -4
  70. package/dist/{ws-CEHi0CiB.js.map → ws-CA3o2nie.js.map} +1 -1
  71. package/dist/{ws-client-t8XNWxcq.js → ws-client-C0iPAAzc.js} +2 -2
  72. package/dist/{ws-client-t8XNWxcq.js.map → ws-client-C0iPAAzc.js.map} +1 -1
  73. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"registry-CnnKaY9s.js","names":["SETTING_TYPES","isRecord","fromStandard"],"sources":["../src/extensions/api/core.ts","../src/extensions/settings/validate.ts","../src/extensions/runtime/validate-definition.ts","../src/chat/keybindings.ts","../src/extensions/commands/keymap.ts","../src/extensions/settings/wire.ts","../src/extensions/host-runtime.ts","../src/extensions/runtime/owner.ts","../src/extensions/api/ui.ts","../src/extensions/ui/settings-form.ts","../src/extensions/ui/wire.ts","../src/extensions/runtime/facets.ts","../src/extensions/storage/port.ts","../src/extensions/storage/cache.ts","../src/extensions/storage/paths.ts","../src/extensions/rpc/json-schema.ts","../src/extensions/rpc/schema.ts","../src/extensions/storage/validate.ts","../src/extensions/storage/store.ts","../src/extensions/storage/domain.ts","../src/extensions/storage/file-port.ts","../src/extensions/storage/memory.ts","../src/extensions/storage/index.ts","../src/extensions/runtime/memory-ports.ts","../src/extensions/runtime/settings-wire.ts","../src/extensions/ui/bindable.ts","../src/extensions/ui/callbacks.ts","../src/extensions/ui/clock.ts","../src/extensions/ui/registry.ts"],"sourcesContent":["/**\n * Extension API: core primitives shared by every domain.\n *\n * Every registration returns a {@link Disposable}. Registrations belong to an\n * {@link Owner}: the extension's root owner, or a child made with\n * `ctx.scope()`. Disposing an owner disposes everything registered through\n * it, in reverse order, and aborts its `signal`.\n */\n\nimport type { StandardSchemaLike } from '../../zod'\n\n/** Something that can be withdrawn. Calling `dispose` twice is a no-op. */\nexport interface Disposable {\n /** Withdraws the registration. Safe to call more than once. */\n dispose: () => void\n}\n\n/** A cleanup function returned from `setup` or passed to `ctx.onCleanup`. */\nexport type Cleanup = () => void | Promise<void>\n\n/**\n * A group of registrations with one lifetime. The extension's root owner\n * lives until the extension unloads. `scope()` makes a child that can end\n * earlier (for example \"while connected\").\n */\nexport interface Owner extends Disposable {\n /** Aborts when the owner is disposed. */\n readonly signal: AbortSignal\n /** `true` once the owner was disposed. Registrations through a disposed owner throw. */\n readonly disposed: boolean\n /** Runs `cleanup` when the owner is disposed. Returns a Disposable that cancels it. */\n onCleanup: (cleanup: Cleanup) => Disposable\n}\n\n/**\n * A live UI contribution. `update` patches the item and pushes it to every\n * host. `dispose` withdraws it.\n */\nexport interface Handle<T> extends Disposable {\n /** The item as the hosts see it now. */\n readonly current: Readonly<T>\n /** Merges `patch` into the item, or replaces it with the function's result. */\n update: (patch: Partial<T> | ((current: Readonly<T>) => T)) => void\n}\n\n/** A value that changes over time. Stores and selectors implement it. */\nexport interface Readable<T> {\n /** The current value. */\n get: () => T\n /** Calls `listener` after each change. Returns the unsubscribe. */\n subscribe: (listener: (value: T) => void) => () => void\n}\n\n/**\n * A field of a UI item that may be a fixed value or a {@link Readable}. A\n * bound field re-pushes the item to the hosts when the readable changes.\n */\nexport type Bindable<T> = T | Readable<T>\n\n/**\n * The state of something another extension provides (a contract, a\n * registry owner, an RPC). Read it where you use it: it changes as the\n * provider starts, stops and reloads.\n */\nexport type Live<T>\n = | { readonly status: 'pending' }\n | { readonly status: 'active', readonly value: T, readonly generation: number }\n | { readonly status: 'inactive', readonly reason?: string }\n\n/** A {@link Live} value you can read and watch. */\nexport interface LiveAccessor<T> extends Readable<Live<T>> {\n /** The value when active, else `undefined`. */\n value: () => T | undefined\n}\n\n/** A plain JSON Schema object. Values validated by it are typed `unknown`. */\nexport type JsonSchema = Readonly<Record<string, unknown>>\n\n/** Either a Standard Schema (zod, valibot, arktype) or a plain JSON Schema. */\nexport type Schema<T = unknown> = StandardSchemaLike<T> | JsonSchema\n\n/** The value type a {@link Schema} accepts: inferred for Standard Schema, `unknown` for JSON Schema. */\nexport type Infer<S> = S extends StandardSchemaLike<infer O> ? O : unknown\n\n/**\n * A reference to a component the extension exports from its `ui` entry\n * (desktop and web) or its `tui` entry (terminal). A host without the\n * named component draws the item's data, or its `fallback`.\n */\nexport interface ComponentRef {\n /** Name of the export in the extension's `ui` / `tui` entry. */\n component: string\n /** JSON props passed to the component. */\n props?: Readonly<Record<string, unknown>>\n}\n\n/**\n * The least client token scope a remote caller needs: the same scopes as\n * every protocol method (`chat` ⊂ `approve` ⊂ `admin`). In-process callers,\n * local connections and other extensions are never limited by it.\n */\nexport type AccessScope = 'chat' | 'approve' | 'admin'\n\n/** Where an extension was found. */\nexport type ExtensionSource = 'project' | 'user' | 'config' | 'inline' | 'builtin'\n\n/** The host process the extension runs in. */\nexport type ExtensionHostKind = 'tui' | 'desktop' | 'daemon' | 'server' | 'sdk'\n\n/** What `ctx.app` tells about the running app. */\nexport interface AppInfo {\n /** Always `'zidane'`. */\n readonly name: 'zidane'\n /** zidane version, semver. */\n readonly version: string\n /** The host process running the extension. */\n readonly host: ExtensionHostKind\n /** `process.platform`. */\n readonly platform: string\n}\n\n/** Filesystem locations given to an extension. */\nexport interface ExtensionPaths {\n /** Working directory of the host. */\n readonly cwd: string\n /** Project root, when the host resolved one. */\n readonly projectRoot?: string\n /** Directory for persistent application data. */\n readonly dataDir: string\n /** Directory for disposable cached files. */\n readonly cacheDir: string\n /** Directory for user configuration. */\n readonly configDir?: string\n /** Directory for runtime state. */\n readonly stateDir?: string\n}\n\n/** Thrown by a ctx call made through a disposed owner. */\nexport class DisposedError extends Error {\n /** @param what - The call that was refused. */\n constructor(what: string) {\n super(`${what}: the extension or scope was disposed`)\n this.name = 'DisposedError'\n }\n}\n","/**\n * Pure checks for the extension settings schema: the static schema of a definition\n * (read without running `setup`) and the values a setting accepts. No host\n * code, no callbacks run except an item's own `validate` when the caller\n * passes it through.\n *\n * Mirrors the legacy config items' read-time rules in `src/extensions/config.ts`\n * (`isValidExtensionConfigValue`): a broken author pattern means \"no\n * constraint\", `step` is a UI hint and never enforced, model ids are not\n * checked against a catalog.\n */\n\nimport type { AccessScope } from '../api/core'\nimport type { ExtensionDefinition } from '../api/define'\nimport type { ActionSetting, Setting, SettingsCategory, SettingScope, SettingsPageSpec, SettingsSchema } from '../api/settings'\n\n/** A value a setting can hold once resolved. Multi model settings hold a list. */\nexport type StoredSettingValue = boolean | number | string | readonly string[]\n\n/** The settings that hold a value (everything but `action`). */\nexport type ValueSetting = Exclude<Setting, ActionSetting>\n\n/** Scopes a setting may be set at when it names none. */\nexport const DEFAULT_SETTING_SCOPES: readonly SettingScope[] = ['user', 'project']\n\nconst ALL_SCOPES: readonly SettingScope[] = ['user', 'project', 'session']\n/**\n * Settings keys: a letter or `_`, then letters, digits, `_`, `.` or `-`\n * (`baseUrl`, `record-mentions`, `API_KEY`). Safe as record keys and in\n * config files once the reserved names are refused (see {@link isSettingKey}).\n */\nexport const SETTING_KEY_PATTERN = /^[A-Z_][\\w.-]*$/i\nconst RESERVED_KEYS = new Set(['__proto__', 'constructor', 'prototype'])\n\n/**\n * Whether `key` may name a setting. The definition validator, the schema\n * cleaner and the config-file reader all use it, so they agree.\n *\n * @param key - A candidate key.\n * @returns `true` for a key matching {@link SETTING_KEY_PATTERN} that is not a reserved name.\n */\nexport function isSettingKey(key: string): boolean {\n return SETTING_KEY_PATTERN.test(key) && !RESERVED_KEYS.has(key)\n}\nconst SETTING_TYPES = new Set(['boolean', 'number', 'string', 'enum', 'model', 'action'])\n\n/** The id of the one page an extension gets when its schema declares no `pages`. */\nexport const DEFAULT_SETTINGS_PAGE_ID = 'main'\n\n/** Settings page ids: the local id rule of UI items (`[A-Za-z0-9_.:-]{1,64}`). */\nexport const SETTINGS_PAGE_ID_PATTERN = /^[\\w.:-]{1,64}$/\n\n/** The token scopes an action may ask for, least first. */\nexport const ACCESS_SCOPES: readonly AccessScope[] = ['chat', 'approve', 'admin']\n\n/** The scope an action needs when it names none. */\nexport const DEFAULT_ACTION_SCOPE: AccessScope = 'admin'\n\n/**\n * The page ids items and sections may name: the declared pages' ids, or\n * {@link DEFAULT_SETTINGS_PAGE_ID} when the schema declares none.\n *\n * @param pages - The declared pages (cleaned or raw ids).\n * @returns The ids a `page` field may hold.\n */\nexport function settingsPageIds(pages: readonly { id: string }[] | undefined): ReadonlySet<string> {\n return new Set(pages && pages.length > 0 ? pages.map(p => p.id) : [DEFAULT_SETTINGS_PAGE_ID])\n}\n\n/**\n * Whether `value` is a settings icon: an object whose `gui` and `tui`, when\n * present, are strings.\n *\n * @param value - A candidate icon.\n */\nexport function isSettingsIcon(value: unknown): value is { gui?: string, tui?: string } {\n if (typeof value !== 'object' || value === null || Array.isArray(value))\n return false\n const icon = value as Record<string, unknown>\n return (icon.gui === undefined || typeof icon.gui === 'string') && (icon.tui === undefined || typeof icon.tui === 'string')\n}\n\n/**\n * The token scope an action needs.\n *\n * @param setting - An action.\n * @returns Its `scope`, or {@link DEFAULT_ACTION_SCOPE}.\n */\nexport function actionScope(setting: ActionSetting): AccessScope {\n return setting.scope ?? DEFAULT_ACTION_SCOPE\n}\n\n/**\n * Whether `setting` holds a value.\n *\n * @param setting - Any setting.\n * @returns `false` for an action.\n */\nexport function isValueSetting(setting: Setting): setting is ValueSetting {\n return setting.type !== 'action'\n}\n\n/**\n * The scopes `setting` may be set at.\n *\n * @param setting - A value setting.\n * @returns Its `scopes`, or {@link DEFAULT_SETTING_SCOPES}.\n */\nexport function settingScopes(setting: ValueSetting): readonly SettingScope[] {\n return setting.scopes ?? DEFAULT_SETTING_SCOPES\n}\n\n/**\n * Splits a stored model list. The Settings UIs store a multi model value as\n * `'a, b'` (see `ExtConfigModelRow` in zidane-ui), so both shapes read.\n *\n * @param value - Comma-separated model ids.\n * @returns The trimmed, non-empty ids.\n */\nexport function parseModelList(value: string): string[] {\n return value.split(',').map(s => s.trim()).filter(s => s.length > 0)\n}\n\n/**\n * Brings a raw stored value into the shape the setting holds: a multi model\n * setting accepts a comma-separated string. Anything else passes unchanged.\n *\n * @param setting - The setting.\n * @param value - The raw value.\n * @returns The value to check.\n */\nexport function normalizeSettingValue(setting: ValueSetting, value: unknown): unknown {\n if (setting.type === 'model' && setting.multi === true && typeof value === 'string')\n return parseModelList(value)\n return value\n}\n\nfunction safeRegExp(pattern: string): RegExp | null {\n try {\n return new RegExp(pattern)\n }\n catch {\n return null\n }\n}\n\n/**\n * Runs an author `validate` callback. Default: called directly, a throw\n * refuses the value with its message.\n */\nexport type ValidateRunner = (validate: (value: string) => string | undefined, value: string) => string | undefined\n\nconst runValidateDirect: ValidateRunner = (validate, value) => {\n try {\n const out = validate(value)\n return typeof out === 'string' && out.length > 0 ? out : undefined\n }\n catch (err) {\n return err instanceof Error && err.message ? err.message : 'invalid value'\n }\n}\n\n/**\n * Checks the type and constraints of a value, without the author\n * `validate` and the string `pattern` (the rules a default must meet).\n */\nfunction checkShape(setting: ValueSetting, value: unknown): string | undefined {\n switch (setting.type) {\n case 'boolean':\n return typeof value === 'boolean' ? undefined : 'expected true or false'\n case 'number':\n if (typeof value !== 'number' || !Number.isFinite(value))\n return 'expected a number'\n if (setting.min !== undefined && value < setting.min)\n return `must be at least ${setting.min}`\n if (setting.max !== undefined && value > setting.max)\n return `must be at most ${setting.max}`\n return undefined\n case 'string':\n return typeof value === 'string' ? undefined : 'expected text'\n case 'enum':\n if (typeof value !== 'string' || !setting.options.some(o => o.value === value))\n return `must be one of: ${setting.options.map(o => o.value).join(', ')}`\n return undefined\n case 'model':\n if (setting.multi === true)\n return Array.isArray(value) && value.every(v => typeof v === 'string') ? undefined : 'expected a list of model ids'\n return typeof value === 'string' ? undefined : 'expected a model id'\n }\n}\n\n/**\n * Checks `value` against `setting`: type, number range, enum membership,\n * string pattern, then the author `validate`. Normalize first\n * ({@link normalizeSettingValue}).\n *\n * @param setting - The setting.\n * @param value - The normalized value.\n * @param runValidate - How to call the author `validate` (the domain passes its guard).\n * @returns An error message, or `undefined` when the value is accepted.\n */\nexport function checkSettingValue(setting: ValueSetting, value: unknown, runValidate: ValidateRunner = runValidateDirect): string | undefined {\n const shape = checkShape(setting, value)\n if (shape !== undefined)\n return shape\n if (setting.type !== 'string')\n return undefined\n const text = value as string\n if (setting.pattern) {\n const re = safeRegExp(setting.pattern)\n if (re && !re.test(text))\n return `does not match ${setting.pattern}`\n }\n if (typeof setting.validate === 'function')\n return runValidate(setting.validate, text)\n return undefined\n}\n\n/**\n * The declared default of a setting, in the shape it holds. A multi model\n * default given as a string is split. An unusable default is `undefined`\n * ({@link settingsForDefinition} reports it).\n *\n * @param setting - A value setting.\n * @returns The default, or `undefined` when none is declared.\n */\nexport function settingDefault(setting: ValueSetting): StoredSettingValue | undefined {\n if (setting.default === undefined)\n return undefined\n const value = normalizeSettingValue(setting, setting.default)\n return checkShape(setting, value) === undefined ? value as StoredSettingValue : undefined\n}\n\n/** The static settings of a definition, cleaned. */\nexport interface StaticSettings {\n /** The extension id. */\n readonly extensionId: string\n /** The schema with malformed sections and items removed. Empty when the definition declares none. */\n readonly schema: SettingsSchema\n /** What was removed or ignored, one line each. */\n readonly issues: readonly string[]\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null\n}\n\n/** Checks one authored item. Returns the cleaned item, or `null` to drop it. */\nfunction cleanItem(key: string, raw: unknown, sectionPages: ReadonlyMap<string, string | undefined>, pageIds: ReadonlySet<string>, issue: (msg: string) => void): Setting | null {\n if (!isSettingKey(key)) {\n issue(`setting \"${key}\": the key is not a safe identifier`)\n return null\n }\n if (!isObject(raw) || typeof raw.type !== 'string' || !SETTING_TYPES.has(raw.type)) {\n issue(`setting \"${key}\": unknown type`)\n return null\n }\n if (typeof raw.label !== 'string') {\n issue(`setting \"${key}\": label must be a string`)\n return null\n }\n let item = { ...raw } as unknown as Setting\n if (item.section !== undefined && !sectionPages.has(item.section)) {\n issue(`setting \"${key}\": unknown section \"${item.section}\", shown ungrouped`)\n const { section: _section, ...rest } = item\n item = rest as Setting\n }\n if (item.page !== undefined && (typeof item.page !== 'string' || !pageIds.has(item.page))) {\n issue(`setting \"${key}\": unknown page \"${String(item.page)}\", shown on the first page`)\n const { page: _page, ...rest } = item\n item = rest as Setting\n }\n if (item.page !== undefined && item.section !== undefined && item.page !== (sectionPages.get(item.section) ?? [...pageIds][0])) {\n issue(`setting \"${key}\": section \"${item.section}\" is not on page \"${item.page}\", shown ungrouped`)\n const { section: _section, ...rest } = item\n item = rest as Setting\n }\n if (item.type === 'action') {\n if (typeof item.run !== 'function') {\n issue(`setting \"${key}\": an action needs a run function`)\n return null\n }\n if (item.status !== undefined && typeof item.status !== 'function') {\n issue(`setting \"${key}\": status must be a function, ignored`)\n const { status: _status, ...rest } = item\n item = rest as ActionSetting\n }\n if (item.scope !== undefined && !ACCESS_SCOPES.includes(item.scope)) {\n issue(`setting \"${key}\": scope must be chat, approve or admin, using admin`)\n const { scope: _scope, ...rest } = item\n item = rest as ActionSetting\n }\n return item\n }\n if (item.type === 'enum') {\n const options = Array.isArray(item.options) ? item.options : []\n const values = options.map(o => isObject(o) ? o.value : undefined)\n if (options.length === 0 || !options.every(o => isObject(o) && typeof o.value === 'string' && typeof o.label === 'string') || new Set(values).size !== values.length) {\n issue(`setting \"${key}\": an enum needs options with unique string values and labels`)\n return null\n }\n }\n if (item.type === 'number' && item.min !== undefined && item.max !== undefined && item.min > item.max) {\n issue(`setting \"${key}\": min is greater than max`)\n return null\n }\n if (item.scopes !== undefined) {\n const scopes = Array.isArray(item.scopes) ? item.scopes.filter(s => ALL_SCOPES.includes(s)) : []\n if (scopes.length !== (Array.isArray(item.scopes) ? item.scopes.length : -1) || scopes.length === 0) {\n issue(`setting \"${key}\": invalid scopes, using the default`)\n const { scopes: _scopes, ...rest } = item\n item = rest as ValueSetting\n }\n }\n if (item.default !== undefined && settingDefault(item) === undefined) {\n issue(`setting \"${key}\": the default does not fit the setting, ignored`)\n const { default: _default, ...rest } = item\n item = rest as ValueSetting\n }\n return item\n}\n\n/**\n * Reads the settings a definition declares, without running `setup`. A\n * disabled extension shows these in Settings. Never calls author code.\n * Malformed categories, pages, sections and items are dropped, and unknown\n * page or section references removed (reported in `issues`), so the rest\n * of the schema still shows.\n *\n * @param def - The definition (only `id` and `settings` are read).\n * @returns The cleaned schema and what was dropped.\n */\nexport function settingsForDefinition(def: Pick<ExtensionDefinition, 'id' | 'settings'>): StaticSettings {\n const issues: string[] = []\n const issue = (msg: string): void => {\n issues.push(msg)\n }\n const raw: unknown = def.settings\n if (raw === undefined)\n return { extensionId: def.id, schema: { sections: [], items: {} }, issues }\n if (!isObject(raw) || !isObject(raw.items)) {\n issue('settings: expected { items }')\n return { extensionId: def.id, schema: { sections: [], items: {} }, issues }\n }\n let category: SettingsCategory | undefined\n if (raw.category !== undefined) {\n if (isObject(raw.category) && typeof raw.category.label === 'string' && raw.category.label.length > 0) {\n category = { label: raw.category.label }\n if (isSettingsIcon(raw.category.icon))\n category.icon = { ...raw.category.icon }\n else if (raw.category.icon !== undefined)\n issue('settings.category: icon must be { gui?, tui? } strings, ignored')\n }\n else {\n issue('settings.category: needs a label, ignored')\n }\n }\n const pages: SettingsPageSpec[] = []\n for (const p of Array.isArray(raw.pages) ? raw.pages as unknown[] : []) {\n if (!isObject(p) || typeof p.id !== 'string' || !SETTINGS_PAGE_ID_PATTERN.test(p.id) || typeof p.label !== 'string') {\n issue('settings: a page needs an id ([A-Za-z0-9_.:-]{1,64}) and a label')\n continue\n }\n if (pages.some(x => x.id === p.id)) {\n issue(`settings: duplicate page \"${p.id}\"`)\n continue\n }\n pages.push({\n id: p.id,\n label: p.label,\n ...(typeof p.description === 'string' ? { description: p.description } : {}),\n ...(isSettingsIcon(p.icon) ? { icon: { ...p.icon } } : {}),\n })\n }\n const pageIds = settingsPageIds(pages)\n const sections: { id: string, label: string, description?: string, page?: string }[] = []\n for (const s of Array.isArray(raw.sections) ? raw.sections as unknown[] : []) {\n if (!isObject(s) || typeof s.id !== 'string' || typeof s.label !== 'string') {\n issue('settings: a section needs an id and a label')\n continue\n }\n if (sections.some(x => x.id === s.id)) {\n issue(`settings: duplicate section \"${s.id}\"`)\n continue\n }\n let page: string | undefined\n if (s.page !== undefined) {\n if (typeof s.page === 'string' && pageIds.has(s.page))\n page = s.page\n else\n issue(`settings: section \"${s.id}\": unknown page \"${String(s.page)}\", shown on the first page`)\n }\n sections.push({ id: s.id, label: s.label, ...(typeof s.description === 'string' ? { description: s.description } : {}), ...(page !== undefined ? { page } : {}) })\n }\n const sectionPages = new Map(sections.map(s => [s.id, s.page]))\n const items: Record<string, Setting> = {}\n for (const [key, value] of Object.entries(raw.items)) {\n const item = cleanItem(key, value, sectionPages, pageIds, issue)\n if (item)\n items[key] = item\n }\n const schema: SettingsSchema = {\n ...(category ? { category } : {}),\n ...(pages.length > 0 ? { pages } : {}),\n sections,\n items,\n }\n return { extensionId: def.id, schema, issues }\n}\n","/**\n * Checks an extension module's default export against the extension\n * definition (`src/extensions/api/define.ts`) before the runtime touches it.\n *\n * Problems that would make the extension misbehave are errors and refuse the\n * load; fields the definition does not have are warnings. Every problem names the\n * field it is about, so the Settings row can say what to fix.\n */\n\nimport type { ExtensionDefinition } from '../api/define'\nimport type { Setting } from '../api/settings'\nimport { satisfiesVersionRange } from '../host-version'\nimport { ACCESS_SCOPES, isSettingKey, isSettingsIcon, SETTINGS_PAGE_ID_PATTERN, settingsPageIds } from '../settings/validate'\n\n/** Lowercase words of letters and digits joined by `-`, starting with a letter: `git-flow`, `s3-sync`. */\nexport const EXTENSION_ID_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/\n\n/** Where the error of an extension written for zidane 9's API sends its author. */\nconst EXTENSION_DOCS_URL = 'https://zidane.si/docs/extensions'\n\nconst SETTING_TYPES = new Set(['boolean', 'number', 'string', 'enum', 'model', 'action'])\nconst SETTING_SCOPES = new Set(['user', 'project', 'session'])\nconst SETTING_APPLY = new Set(['live', 'agent-rebuild', 'restart'])\nconst KNOWN_FIELDS = new Set(['apiVersion', 'id', 'displayName', 'icon', 'version', 'description', 'dependencies', 'settings', 'ui', 'tui', 'setup'])\n/** Fields the definition does not have, with what to use instead. */\nconst REMOVED_FIELDS: Readonly<Record<string, string>> = {\n name: 'use `id`',\n teardown: 'return a cleanup function from `setup`',\n permissions: 'permissions were removed; extensions are trusted on install',\n capabilities: 'capabilities were removed',\n}\n\n/** One problem found in a definition. */\nexport interface DefinitionIssue {\n /** The field it is about, as a dotted path (`settings.items.token.default`), or `''` for the whole value. */\n path: string\n /** What is wrong and, when it helps, what to do. */\n message: string\n}\n\n/** What {@link validateDefinition} found. */\nexport type DefinitionValidation\n = | { ok: true, definition: ExtensionDefinition, warnings: readonly DefinitionIssue[] }\n | { ok: false, errors: readonly DefinitionIssue[], warnings: readonly DefinitionIssue[] }\n\n/** Options for {@link validateDefinition}. */\nexport interface ValidateDefinitionOptions {\n /** The folder the extension was discovered in. The id must equal it. */\n folderName?: string\n}\n\n/**\n * Whether `value` claims to be an extension definition: an object with\n * `apiVersion: 1`. The loader prefers such an export over other objects;\n * {@link validateDefinition} then checks the rest.\n *\n * @param value - A module's default export.\n */\nexport function looksLikeDefinition(value: unknown): value is ExtensionDefinition {\n return isRecord(value) && value.apiVersion === 1\n}\n\n/**\n * Checks `value` against the extension definition: `apiVersion: 1`, a valid\n * `id` (equal to `folderName` when given), a `setup` function, string\n * metadata, a valid semver `version`, `dependencies` with valid ids and\n * semver ranges, and a sane `settings` schema.\n *\n * @param value - A module's default export.\n * @param options - The folder name, for discovered extensions.\n * @returns The definition and warnings, or the errors.\n */\nexport function validateDefinition(value: unknown, options: ValidateDefinitionOptions = {}): DefinitionValidation {\n const errors: DefinitionIssue[] = []\n const warnings: DefinitionIssue[] = []\n const error = (path: string, message: string): void => { errors.push({ path, message }) }\n const warn = (path: string, message: string): void => { warnings.push({ path, message }) }\n\n if (!isRecord(value)) {\n error('', 'The default export must be an extension definition object.')\n return { ok: false, errors, warnings }\n }\n\n if (value.apiVersion !== 1) {\n error('apiVersion', value.apiVersion === undefined\n ? 'Missing `apiVersion: 1`.'\n : `Unsupported apiVersion ${JSON.stringify(value.apiVersion)}. This zidane runs apiVersion 1.`)\n }\n\n if ((typeof value.id !== 'string' || !value.id) && typeof value.name === 'string')\n error('id', `Missing \\`id\\`. This looks like an extension written for zidane 9 (\\`name\\`, no \\`id\\`): zidane 10 replaced that extension API. Port it to the current one: ${EXTENSION_DOCS_URL}`)\n else if (typeof value.id !== 'string' || !value.id)\n error('id', 'Missing `id`.')\n else if (!EXTENSION_ID_PATTERN.test(value.id))\n error('id', `Invalid id \"${value.id}\": use lowercase words joined by \"-\" (e.g. \"git-flow\").`)\n else if (options.folderName !== undefined && value.id !== options.folderName)\n error('id', `The id \"${value.id}\" must equal its folder name \"${options.folderName}\".`)\n\n if (typeof value.setup !== 'function')\n error('setup', 'Missing `setup` function.')\n\n for (const field of ['displayName', 'description', 'ui', 'tui'] as const) {\n if (value[field] !== undefined && typeof value[field] !== 'string')\n error(field, `\\`${field}\\` must be a string.`)\n }\n if (value.icon !== undefined && !isSettingsIcon(value.icon))\n error('icon', '`icon` must be { gui?, tui? } with string values.')\n if (value.version !== undefined) {\n // `*` accepts every version that parses, so this is a parse check that reuses the host's semver reader.\n if (typeof value.version !== 'string' || satisfiesVersionRange(value.version, '*') === undefined)\n error('version', `\\`version\\` must be a semver version like \"1.2.3\", got ${JSON.stringify(value.version)}.`)\n }\n\n checkDependencies(value.dependencies, typeof value.id === 'string' ? value.id : undefined, error)\n if (value.settings !== undefined)\n checkSettings(value.settings, error, warn)\n\n for (const key of Object.keys(value)) {\n if (key in REMOVED_FIELDS)\n warn(key, `\\`${key}\\` is not part of the extension definition and is ignored: ${REMOVED_FIELDS[key]}.`)\n else if (!KNOWN_FIELDS.has(key))\n warn(key, `Unknown field \\`${key}\\` is ignored.`)\n }\n\n return errors.length > 0\n ? { ok: false, errors, warnings }\n : { ok: true, definition: value as unknown as ExtensionDefinition, warnings }\n}\n\ntype Report = (path: string, message: string) => void\n\nfunction checkDependencies(dependencies: unknown, selfId: string | undefined, error: Report): void {\n if (dependencies === undefined)\n return\n if (!isRecord(dependencies)) {\n error('dependencies', '`dependencies` must be an object of { id: semver range }.')\n return\n }\n for (const [id, range] of Object.entries(dependencies)) {\n const path = `dependencies.${id}`\n if (!EXTENSION_ID_PATTERN.test(id))\n error(path, `Invalid dependency id \"${id}\".`)\n else if (id === selfId)\n error(path, 'An extension cannot depend on itself.')\n // Any version checks the range parses: `satisfiesVersionRange` is `undefined` only when it doesn't.\n if (typeof range !== 'string' || satisfiesVersionRange('0.0.0', range) === undefined)\n error(path, `Invalid semver range ${JSON.stringify(range)} (e.g. \"^1.2.0\", \">=2\", \"*\").`)\n }\n}\n\nfunction checkSettings(settings: unknown, error: Report, warn: Report): void {\n if (!isRecord(settings) || !isRecord(settings.items)) {\n error('settings', '`settings` must be an object with an `items` record.')\n return\n }\n if (settings.category !== undefined) {\n const category = settings.category\n if (!isRecord(category) || typeof category.label !== 'string' || !category.label)\n error('settings.category', '`category` needs a string `label`.')\n else if (category.icon !== undefined && !isSettingsIcon(category.icon))\n error('settings.category.icon', '`icon` must be { gui?, tui? } with string values.')\n }\n const declaredPages: { id: string }[] = []\n if (settings.pages !== undefined) {\n if (!Array.isArray(settings.pages)) {\n error('settings.pages', '`pages` must be an array.')\n }\n else {\n settings.pages.forEach((page: unknown, i) => {\n const path = `settings.pages.${i}`\n if (!isRecord(page) || typeof page.id !== 'string' || !SETTINGS_PAGE_ID_PATTERN.test(page.id) || typeof page.label !== 'string' || !page.label)\n error(path, 'A page needs an `id` ([A-Za-z0-9_.:-], 64 at most) and a string `label`.')\n else if (declaredPages.some(p => p.id === page.id))\n error(path, `Duplicate page id \"${page.id}\".`)\n else\n declaredPages.push({ id: page.id })\n if (isRecord(page) && page.description !== undefined && typeof page.description !== 'string')\n error(`${path}.description`, '`description` must be a string.')\n if (isRecord(page) && page.icon !== undefined && !isSettingsIcon(page.icon))\n error(`${path}.icon`, '`icon` must be { gui?, tui? } with string values.')\n })\n }\n }\n const pageIds = settingsPageIds(declaredPages)\n const pageList = [...pageIds].join(', ')\n // Section id → the page it sits on (the first page when it names none).\n const sectionIds = new Map<string, string>()\n if (settings.sections !== undefined) {\n if (!Array.isArray(settings.sections)) {\n error('settings.sections', '`sections` must be an array.')\n }\n else {\n settings.sections.forEach((section: unknown, i) => {\n const path = `settings.sections.${i}`\n if (!isRecord(section) || typeof section.id !== 'string' || !section.id || typeof section.label !== 'string')\n error(path, 'A section needs a string `id` and `label`.')\n else if (sectionIds.has(section.id))\n error(path, `Duplicate section id \"${section.id}\".`)\n else if (section.page !== undefined && (typeof section.page !== 'string' || !pageIds.has(section.page)))\n error(`${path}.page`, `Unknown page ${JSON.stringify(section.page)} (pages: ${pageList}).`)\n else\n sectionIds.set(section.id, typeof section.page === 'string' ? section.page : [...pageIds][0]!)\n })\n }\n }\n for (const [key, item] of Object.entries(settings.items)) {\n const path = `settings.items.${key}`\n if (!isSettingKey(key)) {\n error(path, `Invalid settings key \"${key}\": start with a letter or _, then use letters, digits, _, . or - (\"baseUrl\", \"record-mentions\").`)\n continue\n }\n checkSetting(item, path, sectionIds, pageIds, error, warn)\n }\n}\n\nfunction checkSetting(item: unknown, path: string, sectionIds: ReadonlyMap<string, string>, pageIds: ReadonlySet<string>, error: Report, warn: Report): void {\n if (!isRecord(item) || typeof item.type !== 'string' || !SETTING_TYPES.has(item.type)) {\n error(path, `A setting needs a \\`type\\` (${[...SETTING_TYPES].join(', ')}).`)\n return\n }\n const setting = item as unknown as Setting\n if (typeof setting.label !== 'string' || !setting.label)\n error(`${path}.label`, 'A setting needs a `label`.')\n if (setting.section !== undefined && !sectionIds.has(setting.section))\n warn(`${path}.section`, `Unknown section \"${setting.section}\"; the setting shows ungrouped.`)\n if (setting.page !== undefined) {\n if (typeof setting.page !== 'string' || !pageIds.has(setting.page))\n error(`${path}.page`, `Unknown page ${JSON.stringify(setting.page)} (pages: ${[...pageIds].join(', ')}).`)\n else if (setting.section !== undefined && sectionIds.has(setting.section) && sectionIds.get(setting.section) !== setting.page)\n error(`${path}.page`, `Section \"${setting.section}\" is on page \"${sectionIds.get(setting.section)}\", not \"${setting.page}\".`)\n }\n if (setting.scopes !== undefined && (!Array.isArray(setting.scopes) || setting.scopes.length === 0 || !setting.scopes.every(s => SETTING_SCOPES.has(s))))\n error(`${path}.scopes`, '`scopes` must be a non-empty list of user, project, session.')\n if (setting.apply !== undefined && !SETTING_APPLY.has(setting.apply))\n error(`${path}.apply`, '`apply` must be live, agent-rebuild or restart.')\n\n const badDefault = (expected: string): void => error(`${path}.default`, `\\`default\\` must be ${expected}.`)\n switch (setting.type) {\n case 'boolean':\n if (setting.default !== undefined && typeof setting.default !== 'boolean')\n badDefault('a boolean')\n break\n case 'number': {\n const { min, max, default: d } = setting\n for (const [name, v] of [['min', min], ['max', max], ['step', setting.step]] as const) {\n if (v !== undefined && (typeof v !== 'number' || !Number.isFinite(v)))\n error(`${path}.${name}`, `\\`${name}\\` must be a finite number.`)\n }\n if (typeof min === 'number' && typeof max === 'number' && min > max)\n error(path, '`min` is greater than `max`.')\n if (d !== undefined && (typeof d !== 'number' || !Number.isFinite(d)))\n badDefault('a finite number')\n else if (typeof d === 'number' && ((typeof min === 'number' && d < min) || (typeof max === 'number' && d > max)))\n badDefault('within min and max')\n break\n }\n case 'string':\n if (setting.default !== undefined && typeof setting.default !== 'string')\n badDefault('a string')\n if (setting.pattern !== undefined) {\n try {\n // eslint-disable-next-line no-new\n new RegExp(setting.pattern)\n }\n catch {\n error(`${path}.pattern`, `Invalid regular expression ${JSON.stringify(setting.pattern)}.`)\n }\n }\n if (setting.validate !== undefined && typeof setting.validate !== 'function')\n error(`${path}.validate`, '`validate` must be a function.')\n if (setting.secret && setting.default !== undefined)\n warn(`${path}.default`, 'A secret setting should not ship a default.')\n break\n case 'enum': {\n const options = setting.options as unknown\n if (!Array.isArray(options) || options.length === 0 || !options.every(o => isRecord(o) && typeof o.value === 'string' && typeof o.label === 'string')) {\n error(`${path}.options`, '`options` must be a non-empty list of { value, label }.')\n break\n }\n const values = options.map(o => o.value as string)\n if (new Set(values).size !== values.length)\n error(`${path}.options`, 'Option values must be unique.')\n if (setting.default !== undefined && !values.includes(setting.default))\n badDefault(`one of the option values (${values.join(', ')})`)\n break\n }\n case 'model':\n if (setting.default !== undefined) {\n const ok = setting.multi\n ? Array.isArray(setting.default) && setting.default.every(v => typeof v === 'string')\n : typeof setting.default === 'string'\n if (!ok)\n badDefault(setting.multi ? 'a list of model ids' : 'a model id')\n }\n break\n case 'action':\n if (typeof setting.button !== 'string' || !setting.button)\n error(`${path}.button`, 'An action needs a `button` label.')\n if (typeof setting.run !== 'function')\n error(`${path}.run`, 'An action needs a `run` function.')\n if (setting.status !== undefined && typeof setting.status !== 'function')\n error(`${path}.status`, '`status` must be a function.')\n if (setting.scope !== undefined && !ACCESS_SCOPES.includes(setting.scope))\n error(`${path}.scope`, '`scope` must be chat, approve or admin.')\n break\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","/**\n * Keybindings — a single source of truth for the app's global shortcuts.\n *\n * Every customizable action is declared once in {@link KEYBINDING_DEFS}\n * with its default trigger, label, and description. The TUI imports\n * `DEFAULT_KEYBINDINGS` for the baked-in defaults; on launch we load\n * `<userDir>/keybindings.json` (when present) and merge user overrides\n * on top so the user can rebind any action without recompiling.\n *\n * Scope (deliberate):\n *\n * - We expose the **global, action-opening** shortcuts (\"open the\n * Settings modal\", \"cycle agent profile\", \"enter select-turn\n * mode\", etc.), the message-queue keys, and the letter shortcuts of\n * the turn-details and session-details modals (`f` fork, `d` delete,\n * `c` copy). Universal navigation (`↑/↓/↵/⎋`) stays hardcoded — it\n * lives too close to a renderable's input contract to remap safely.\n *\n * - Storage lives at the **user level** (`<userDir>/keybindings.json`),\n * never inside a project's `.{prefix}/`. Shortcut muscle memory is\n * a per-user concern, not a per-repo one.\n *\n * Format on disk: JSON with `//` and `/* … *\\/` comments allowed\n * (parsed via a small JSONC stripper). Each entry maps an action id\n * to a binding spec string. Specs are parsed by {@link parseBindingSpec};\n * unknown / malformed entries fall back to the default for that action,\n * so a syntax slip never bricks the TUI.\n */\n\nimport type { ParsedBinding } from './keybinding-spec'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { writeFileAtomic } from '../atomic-write'\nimport { bindingAlternatives, parseBindingSpec, parseBindingSpecs } from './keybinding-spec'\n\nexport { bindingAlternatives, parseBindingSpec, parseBindingSpecs, type ParsedBinding } from './keybinding-spec'\n\n// ---------------------------------------------------------------------------\n// Action catalog\n// ---------------------------------------------------------------------------\n\n/**\n * Every action the keybindings system can drive. Adding a new action\n * here forces every consumer (TUI keyboard handler, hint rows, settings\n * UI) to handle it, and ships a default that the user can override.\n */\nexport type KeyAction\n // Global action shortcuts — fire from the top-level keyboard\n // handler (`handleAppKey` in `tui/shell/app-keyboard.tsx`), gated on screen / busy state.\n = | 'openSettings'\n | 'openSessionDetails'\n | 'newSession'\n | 'openModelPicker'\n | 'openEffortPicker'\n | 'openTodos'\n | 'openArtifacts'\n | 'panelNext'\n | 'panelPrev'\n | 'nextSpace'\n | 'prevSpace'\n | 'openContextPanel'\n | 'openMainSession'\n | 'openUsagePanel'\n | 'openKeybindings'\n | 'openPalette'\n | 'cycleAgent'\n | 'enterSelectTurnMode'\n | 'cancelToolCall'\n | 'abortRun'\n | 'changeCwd'\n | 'attachClipboardImage'\n | 'openExternalEditor'\n // Sessions list — only on the sessions screen (`handleAppKey`), so\n // its defaults may repeat a chord the chat uses.\n | 'cycleSpaceInList'\n // Message-queue navigation — only meaningful when the user has\n // type-ahead prompts waiting in the queue box above the prompt\n // input. `enterQueueSelection` moves the focus from the textarea\n // into the queue; while there, `pushQueuedMessage` (steers the\n // selected entry into the live run) and `dropQueuedMessage`\n // (removes the entry) act on the highlighted row.\n | 'enterQueueSelection'\n | 'pushQueuedMessage'\n | 'dropQueuedMessage'\n // Turn-details modal actions (`ctrl+s` select-turn mode → enter).\n // Each binding only matches while that modal is mounted, so the\n // single-letter defaults can clash with letters used elsewhere\n // without conflict.\n | 'turnFork'\n | 'turnDelete'\n | 'turnCopy'\n | 'turnEdit'\n // Session-details modal actions (opened via `ctrl+shift+x`).\n | 'sessionDelete'\n | 'sessionCopyId'\n | 'sessionGenerateTitle'\n | 'sessionExportMarkdown'\n | 'sessionExportJson'\n | 'sessionCompact'\n | 'sessionMoveSpace'\n | 'sessionFavorite'\n | 'sessionMoveEnvironment'\n\n/** Resolved keybindings — every action has a current spec string. */\nexport type KeyBindings = Record<KeyAction, string>\n\n/**\n * Resolved spec string for one extension-contributed keybinding. Same\n * shape as a built-in {@link KeyBindings} entry but the `id` is\n * extension-owned (no `KeyAction` union member). The TUI dispatcher\n * iterates these alongside the built-ins; user overrides flow through\n * the same `keybindings.json` file by matching on `id`.\n */\nexport interface ResolvedExtensionKeybinding {\n /** Extension-owned id (matches `ExtensionKeybinding.id`). */\n id: string\n /** Active spec string — user override when present, default otherwise. May be empty (= unbound). */\n spec: string\n}\n\n/**\n * Logical grouping for one action — used by the keybindings panel to\n * render section headers. Stable strings (not an enum) so future\n * groups can be added without churning every existing entry.\n *\n * `Sessions` actions fire on the sessions screen only, and the\n * `… details` ones only while their modal is open, so their defaults\n * may repeat a chord that acts elsewhere.\n */\nexport type KeyBindingGroup\n = | 'Global'\n | 'Sessions'\n | 'Message queue'\n | 'Turn details'\n | 'Session details'\n\n/** Static metadata for one action — used by the loader, hint rows, settings UI. */\nexport interface KeyBindingDef {\n /** Stable identifier — JSON key + TS union member. */\n action: KeyAction\n /** Default trigger spec (e.g. `'ctrl+o'`). */\n default: string\n /** Short label used in shortcut hint rows. */\n label: string\n /** Longer description for the settings UI and the annotated JSON file. */\n description: string\n /**\n * Group label rendered as a section header in the keybindings panel.\n * Items are listed in {@link KEYBINDING_DEFS} order; the panel just\n * inserts a header whenever this field changes between adjacent\n * entries — so groups stay contiguous and the order here is the\n * order on screen.\n */\n group: KeyBindingGroup\n}\n\n/**\n * The canonical action catalog. Order is the source of truth for the\n * generated keybindings file and the settings UI.\n */\nexport const KEYBINDING_DEFS: readonly KeyBindingDef[] = [\n {\n action: 'openSettings',\n default: 'ctrl+o',\n label: 'settings',\n description: 'open settings',\n group: 'Global',\n },\n {\n // ctrl+shift+x keeps ctrl+x free (the conventional \"cut\" key in most\n // editors). Like the context panel, it relies on the kitty keyboard\n // protocol to stay distinct from ctrl+x; on terminals without it\n // (e.g. macOS Terminal.app) shift is dropped and it collapses to\n // ctrl+x — rebind there.\n action: 'openSessionDetails',\n default: 'ctrl+shift+x',\n label: 'session',\n description: 'open session details: stats, export, rename, delete',\n group: 'Global',\n },\n {\n action: 'newSession',\n default: 'ctrl+n',\n label: 'new session',\n description: 'start a new session with the current model',\n group: 'Global',\n },\n {\n action: 'openModelPicker',\n default: 'ctrl+m',\n label: 'model',\n description: 'open the model picker',\n group: 'Global',\n },\n {\n action: 'openEffortPicker',\n default: 'ctrl+l',\n label: 'options',\n description: 'open model options, like reasoning effort and fast mode',\n group: 'Global',\n },\n {\n action: 'openTodos',\n default: 'ctrl+t',\n label: 'todos',\n description: 'open the run\\'s todo list',\n group: 'Global',\n },\n {\n // ctrl+shift+a: \"artifacts\" — what the run produced, next to todos (ctrl+t),\n // what it planned. Kitty-protocol dependent like the other ctrl+shift\n // chords — collapses to ctrl+a on Terminal.app; rebind there.\n action: 'openArtifacts',\n default: 'ctrl+shift+a',\n label: 'panel',\n description: 'show or hide the side panel',\n group: 'Global',\n },\n {\n action: 'panelNext',\n default: 'ctrl+shift+]',\n label: 'next panel',\n description: 'open the next side-panel tab',\n group: 'Global',\n },\n {\n action: 'panelPrev',\n default: 'ctrl+shift+[',\n label: 'previous panel',\n description: 'open the previous side-panel tab',\n group: 'Global',\n },\n // Spaces (opt-in): the arrows of the sessions list's ←/→ and the GUI's ⌥⌘←/→.\n // kitty and WezTerm keep ctrl+shift+arrows for their own tabs / panes by default: rebind there.\n {\n action: 'nextSpace',\n default: 'ctrl+shift+right',\n label: 'next space',\n description: 'show the next space (Spaces on); from a chat, the sessions list opens on it',\n group: 'Global',\n },\n {\n action: 'prevSpace',\n default: 'ctrl+shift+left',\n label: 'previous space',\n description: 'show the previous space (Spaces on); from a chat, the sessions list opens on it',\n group: 'Global',\n },\n {\n // ctrl+shift+g leans on the kitty keyboard protocol (the renderer\n // enables it) to stay distinct from ctrl+g (`openExternalEditor`). On\n // terminals without it — e.g. macOS Terminal.app — shift is dropped and\n // the keypress collapses to ctrl+g (the editor); rebind there.\n action: 'openContextPanel',\n default: 'ctrl+shift+g',\n label: 'context',\n description: 'show what fills the context window',\n group: 'Global',\n },\n {\n // ctrl+shift+m (\"Main\"): one chord for the TUI and the GUI. Leans on the\n // kitty keyboard protocol (the renderer enables it) to stay distinct from\n // ctrl+m (the model picker); on terminals without it — e.g. macOS\n // Terminal.app — shift is dropped and the keypress collapses to ctrl+m;\n // rebind there. NOT ctrl+u: that is the textarea's kill-to-line-start,\n // which is also what several terminals send for ⌃⌫, so deleting a word\n // would jump to the main session.\n action: 'openMainSession',\n default: 'ctrl+shift+m',\n label: 'main session',\n description: 'open the Main session for this directory, or create it. Needs the \"Main session\" and \"Use daemon runtime\" settings',\n group: 'Global',\n },\n {\n // Plain ctrl+p on purpose: free in OpenTUI's textarea keymap (which owns\n // ctrl+a/e/f/b/w/k/u/d) and in every other global binding, so it behaves\n // the same on kitty and legacy terminals. A ctrl+shift+<x> default would\n // collapse to its unshifted chord on Terminal.app and eat a text-editing\n // key.\n action: 'openUsagePanel',\n default: 'ctrl+p',\n label: 'usage',\n description: 'open plan limits and credits for each provider',\n group: 'Global',\n },\n {\n action: 'openKeybindings',\n default: 'ctrl+y',\n label: 'keybindings',\n description: 'list every shortcut',\n group: 'Global',\n },\n {\n action: 'openPalette',\n // Terminals cannot report cmd, and ctrl+k belongs to cancelToolCall;\n // ctrl+shift+p is the palette chord editors made familiar. The GUI\n // catalog binds this to cmd+k (a declared divergence).\n default: 'ctrl+shift+p',\n label: 'palette',\n description: 'search actions, commands, sessions and settings',\n group: 'Global',\n },\n {\n action: 'cycleAgent',\n default: 'shift+tab',\n label: 'cycle agent',\n description: 'switch to the next agent profile',\n group: 'Global',\n },\n {\n action: 'enterSelectTurnMode',\n default: 'ctrl+s',\n label: 'messages',\n description: 'select a previous message',\n group: 'Global',\n },\n {\n action: 'cancelToolCall',\n default: 'ctrl+k',\n label: 'cancel tool',\n description: 'cancel one tool call and keep the run going',\n group: 'Global',\n },\n {\n action: 'abortRun',\n default: 'ctrl+escape',\n label: 'abort',\n description: 'stop the run and deny pending approvals. If your terminal cannot send ctrl+esc, rebind it',\n group: 'Global',\n },\n {\n action: 'changeCwd',\n default: 'ctrl+h',\n label: 'cwd',\n description: 'change the working directory',\n group: 'Global',\n },\n {\n // The id keeps its original name so existing keybindings.json overrides\n // work; the shortcut pastes text as well as images.\n action: 'attachClipboardImage',\n default: 'ctrl+v',\n label: 'paste clipboard',\n description: 'paste text or an image from the system clipboard',\n group: 'Global',\n },\n {\n // Handled inside `PromptBlock`'s onKeyDown (it owns the textarea ref),\n // NOT the App-level keyboard handler — so it only ever fires while the\n // prompt composer is focused. Gated by the `externalEditor` setting:\n // disabled there, the key falls through to its normal textarea behavior.\n // ctrl+g (Claude Code's muscle-memory key) needs no kitty keyboard\n // protocol; the context panel takes ctrl+shift+g to keep it free.\n action: 'openExternalEditor',\n default: 'ctrl+g',\n label: 'edit in $EDITOR',\n description: 'write the prompt in $EDITOR or $VISUAL. Needs the \"Edit prompt in $EDITOR\" setting',\n group: 'Global',\n },\n // Sessions list. shift+tab is free there: `cycleAgent` only acts in the\n // chat, where shift+tab keeps cycling agents. Also fires while the search\n // input has focus (shift+tab edits no text).\n {\n action: 'cycleSpaceInList',\n default: 'shift+tab',\n label: 'next space',\n description: 'show the next space in the sessions list (wraps), also while typing a search. Needs 2 or more spaces. In a chat, shift+tab still cycles agents',\n group: 'Sessions',\n },\n // Message-queue navigation — only matches when the queue box above\n // the prompt has at least one entry. Defaults pick keys the prompt\n // textarea doesn't already claim (no default for enter — see below).\n //\n // `enterQueueSelection` is intentionally unbound by default: the\n // natural way to enter the queue is to press plain `↑` on an empty\n // prompt buffer (handled in `PromptBlock`'s onKeyDown), which doesn't\n // need a global shortcut. The action stays in the catalog so users\n // who want a dedicated key — e.g. for entering the queue WITHOUT\n // emptying their draft first — can rebind it in `keybindings.json`.\n // We don't ship a default because no arrow / modifier combo is both\n // free in OpenTUI's textarea AND forwarded by every common terminal\n // (ctrl+arrow → macOS Mission Control; cmd+arrow → terminal scroll /\n // tab nav; alt+arrow → terminal word-nav).\n {\n action: 'enterQueueSelection',\n default: '',\n label: 'select queue',\n description: 'select the queued messages (or press ↑ on an empty prompt)',\n group: 'Message queue',\n },\n {\n action: 'pushQueuedMessage',\n default: 'ctrl+return',\n label: 'push',\n description: 'send the selected queued message into the running turn',\n group: 'Message queue',\n },\n {\n action: 'dropQueuedMessage',\n default: 'backspace',\n label: 'drop',\n description: 'remove the selected queued message',\n group: 'Message queue',\n },\n // Turn-details modal — only fires while that modal is mounted.\n {\n action: 'turnFork',\n default: 'f',\n label: 'fork',\n description: 'fork the session at this turn (press twice)',\n group: 'Turn details',\n },\n {\n action: 'turnDelete',\n default: 'd',\n label: 'delete',\n description: 'delete this turn (press twice)',\n group: 'Turn details',\n },\n {\n action: 'turnCopy',\n default: 'c',\n label: 'copy',\n description: 'copy this turn',\n group: 'Turn details',\n },\n {\n action: 'turnEdit',\n default: 'e',\n label: 'edit',\n description: 'edit this turn\\'s text',\n group: 'Turn details',\n },\n // Session-details modal — only fires while that modal is mounted.\n {\n action: 'sessionDelete',\n default: 'd',\n label: 'delete',\n description: 'delete the session (press twice)',\n group: 'Session details',\n },\n {\n action: 'sessionCopyId',\n default: 'c',\n label: 'copy id',\n description: 'copy the session id',\n group: 'Session details',\n },\n {\n action: 'sessionGenerateTitle',\n default: 'g',\n label: 'generate title',\n description: 'title the session with the current model',\n group: 'Session details',\n },\n {\n action: 'sessionExportMarkdown',\n default: 'e',\n label: 'export md',\n description: 'export the session as Markdown under .{prefix}/sessions/',\n group: 'Session details',\n },\n {\n action: 'sessionExportJson',\n default: 'j',\n label: 'export json',\n description: 'export the session as JSON under .{prefix}/sessions/',\n group: 'Session details',\n },\n {\n action: 'sessionCompact',\n default: 'k',\n label: 'compact',\n description: 'summarize older turns to free context',\n group: 'Session details',\n },\n {\n action: 'sessionMoveSpace',\n default: 's',\n label: 'space',\n description: 'move the session to the next space (needs Spaces)',\n group: 'Session details',\n },\n {\n action: 'sessionFavorite',\n default: 'f',\n label: 'favorite',\n description: 'add the session to favorites, or remove it',\n group: 'Session details',\n },\n {\n action: 'sessionMoveEnvironment',\n default: 'm',\n label: 'move',\n description: 'move the session to another environment or machine',\n group: 'Session details',\n },\n]\n\n/** Index by action for O(1) lookup of label / description / default. */\nexport const KEYBINDING_DEF_BY_ACTION: Readonly<Record<KeyAction, KeyBindingDef>>\n = KEYBINDING_DEFS.reduce(\n (acc, def) => Object.assign(acc, { [def.action]: def }),\n {} as Record<KeyAction, KeyBindingDef>,\n )\n\n/** Defaults, derived from {@link KEYBINDING_DEFS} so the two never drift. */\nexport const DEFAULT_KEYBINDINGS: KeyBindings\n = KEYBINDING_DEFS.reduce(\n (acc, def) => Object.assign(acc, { [def.action]: def.default }),\n {} as KeyBindings,\n )\n\n// ---------------------------------------------------------------------------\n// Spec parsing + matching\n// ---------------------------------------------------------------------------\n\n/**\n * Test a KeyEvent against a parsed-or-string binding. Accepts either\n * form so callers can pre-parse (hot path) or pass the raw spec for\n * one-off checks.\n *\n * Modifier semantics: ALL declared modifiers must be pressed AND no\n * extra modifiers may be pressed. So `'o'` does NOT match `ctrl+o`,\n * and `'ctrl+o'` does NOT match `ctrl+shift+o`. This avoids surprises\n * where a binding that should be specific accidentally fires for a\n * superset of key combinations.\n *\n * @param event - Key event to test.\n * @param spec - Binding spec string, or a chord already parsed with {@link parseBindingSpec}.\n */\nexport function matchesBinding(\n event: { name?: string, ctrl?: boolean, shift?: boolean, meta?: boolean, option?: boolean, alt?: boolean },\n spec: string | ParsedBinding,\n): boolean {\n if (typeof spec === 'string')\n return parseBindingSpecs(spec).some(parsed => matchesBinding(event, parsed))\n const parsed = spec\n // OpenTUI's `ParsedKey` exposes `option` for Alt; some terminals\n // also report it as `alt`. Accept either.\n const altPressed = !!event.option || !!event.alt\n if (parsed.ctrl !== !!event.ctrl)\n return false\n if (parsed.shift !== !!event.shift)\n return false\n if (parsed.alt !== altPressed)\n return false\n if (parsed.meta !== !!event.meta)\n return false\n if ((event.name ?? '').toLowerCase() !== parsed.name)\n return false\n return true\n}\n\n// ---------------------------------------------------------------------------\n// Display helpers\n// ---------------------------------------------------------------------------\n\n/** Verbose key names → compact single-cell glyphs used by hint rows. */\nconst KEY_GLYPHS: Readonly<Record<string, string>> = {\n up: '↑',\n down: '↓',\n left: '←',\n right: '→',\n return: '↵',\n enter: '↵',\n delete: '⌫',\n backspace: '⌫',\n escape: 'esc',\n space: '␣',\n tab: '⇥',\n}\n\n/**\n * Render a binding spec (`\"ctrl+return\"`, `\"backspace\"`, `\"delete\"`) as a\n * compact display string the user recognizes at a glance. Substitutes\n * arrow / enter / backspace glyphs for their verbose names so the hint\n * row stays narrow; modifier names + plain keys pass through unchanged.\n *\n * Empty / missing specs return an empty string — callers decide whether\n * to render a placeholder (e.g. `'—'` for an unbound action in the\n * keybindings panel) or hide the surface entirely (e.g. hint rows that\n * fall back to a different chord when the binding is empty).\n *\n * @param spec - Binding spec, possibly listing several chords separated by `|`.\n */\nexport function formatBindingForDisplay(spec: string | null | undefined): string {\n return bindingAlternatives(spec).map(formatOneBinding).join(' / ')\n}\n\nfunction formatOneBinding(spec: string): string {\n const segments = spec.toLowerCase().split('+')\n const key = segments.pop() ?? ''\n const modifiers = segments.join('+')\n const glyph = KEY_GLYPHS[key] ?? key\n return modifiers ? `${modifiers}+${glyph}` : glyph\n}\n\n// ---------------------------------------------------------------------------\n// Merge + file IO\n// ---------------------------------------------------------------------------\n\n/**\n * Merge a partial map of user overrides into the defaults. Unknown\n * action keys are dropped (a future TUI version may have retired the\n * action); invalid spec strings (parse fails) fall back to the default\n * for that action.\n *\n * @param overrides - Parsed user overrides keyed by action name.\n */\nexport function mergeKeybindings(\n overrides: Readonly<Record<string, unknown>> | null | undefined,\n): KeyBindings {\n if (!overrides || typeof overrides !== 'object')\n return { ...DEFAULT_KEYBINDINGS }\n const merged: KeyBindings = { ...DEFAULT_KEYBINDINGS }\n for (const def of KEYBINDING_DEFS) {\n const raw = normalizeBindingValue(overrides[def.action])\n if (raw === null)\n continue // invalid spec → keep the default\n merged[def.action] = raw\n }\n return merged\n}\n\n/**\n * A `keybindings.json` value as one spec: a string, or an array of chords\n * (`[\"ctrl+w\", \"cmd+w\"]`) joined as alternatives. Chords that don't parse\n * are dropped; `null` when none is left.\n *\n * @param raw - Raw value from `keybindings.json`: a spec string or an array of them.\n */\nexport function normalizeBindingValue(raw: unknown): string | null {\n const parts = typeof raw === 'string'\n ? bindingAlternatives(raw)\n : Array.isArray(raw) ? raw.filter((r): r is string => typeof r === 'string').flatMap(bindingAlternatives) : []\n const valid = parts.filter(part => parseBindingSpec(part) !== null)\n return valid.length > 0 ? valid.join(' | ') : null\n}\n\n/**\n * Path of the user-level keybindings file.\n *\n * @param userDir - User-level config directory.\n */\nexport function keybindingsPath(userDir: string): string {\n return resolve(userDir, 'keybindings.json')\n}\n\n/**\n * One contiguous section of the catalog — every adjacent action of a single\n * `group` rendered together with the section header inserted once.\n * Non-adjacent runs of the same group are NOT merged: catalog order\n * wins so the on-screen story matches the on-disk file.\n *\n * `rows` may carry built-in `KeyBindingDef`s (the common case) or\n * extension-owned ones (when an extension contributes a keybinding).\n * Both share label / description / spec — see {@link KeyBindingRow}.\n */\nexport interface KeyBindingSection {\n /** Group name shared by every row in the section. */\n group: string\n /** Rows in the section, in catalog order. */\n rows: ReadonlyArray<KeyBindingRow>\n}\n\n/**\n * One row in the keybindings catalog. Either a built-in action (with\n * its `def`) or an extension-contributed one (with `id` instead). The\n * renderer reads `label` / `description` / `spec` uniformly and only\n * needs the `kind` discriminator when offering action-specific UI\n * (e.g. \"edit in keybindings.json\" by action name).\n */\nexport type KeyBindingRow\n = | { kind: 'builtin', def: KeyBindingDef, spec: string }\n | { kind: 'extension', id: string, label: string, description: string, spec: string }\n\n/**\n * Walk {@link KEYBINDING_DEFS} in order and bucket rows into contiguous\n * sections by `group`. Shared between the standalone `KeybindingsModal`\n * and the `Keybindings` tab inside `SettingsModal` so both surfaces\n * render the same catalog with the same ordering rules.\n *\n * Pass `extensionRows` (resolved extension keybindings paired with\n * their definitions) to append an \"Extensions\" section at the end so\n * extension-contributed shortcuts are discoverable in the same UI.\n *\n * @param bindings - Resolved built-in bindings, keyed by action.\n * @param extensionRows - Extension-contributed keybindings to list in a trailing section.\n */\nexport function groupBindings(\n bindings: KeyBindings,\n extensionRows: readonly { id: string, label: string, description: string, spec: string }[] = [],\n): readonly KeyBindingSection[] {\n const sections: Array<{ group: string, rows: KeyBindingRow[] }> = []\n for (const def of KEYBINDING_DEFS) {\n const last = sections[sections.length - 1]\n const spec = bindings[def.action] ?? ''\n const row: KeyBindingRow = { kind: 'builtin', def, spec }\n if (last && last.group === def.group) {\n last.rows.push(row)\n continue\n }\n sections.push({ group: def.group, rows: [row] })\n }\n if (extensionRows.length > 0) {\n sections.push({\n group: 'Extensions',\n rows: extensionRows.map(r => ({\n kind: 'extension',\n id: r.id,\n label: r.label,\n description: r.description,\n spec: r.spec,\n })),\n })\n }\n return sections\n}\n\n/**\n * Width (in cells) of the fixed key column used by every binding-row\n * renderer. Derived once from {@link KEYBINDING_DEFS} so a new action\n * with a wider default spec (`ctrl+shift+x`, …) automatically grows\n * the column instead of truncating the label.\n */\nexport const KEYBINDING_KEY_COL_WIDTH = (() => {\n let max = 8\n for (const def of KEYBINDING_DEFS) {\n const width = formatBindingForDisplay(def.default).length\n if (width > max)\n max = width\n }\n return max + 2 // breathing room before the label column\n})()\n\n/**\n * Load + merge the user's keybindings file (when present). Always\n * returns a fully-resolved {@link KeyBindings} — defaults fill in for\n * any missing / invalid entries so consumers can treat the result as\n * total.\n *\n * Failure modes (all tolerated, all fall back to defaults):\n * - File missing\n * - File not valid JSON / JSONC (after comment stripping)\n * - Top-level is not an object\n * - Individual entries have invalid spec strings\n *\n * @param userDir - User-level config directory that holds `keybindings.json`.\n */\nexport function readKeybindings(userDir: string): KeyBindings {\n return mergeKeybindings(readKeybindingsRaw(userDir))\n}\n\n/**\n * Create the user-level `keybindings.json` if it doesn't exist,\n * prefilled with every default. Returns the absolute file path either\n * way so the caller can open it in `$EDITOR`. Idempotent: an existing\n * user file is NEVER overwritten — the user's customizations are\n * sacred.\n *\n * @param userDir - User-level config directory that holds `keybindings.json`.\n */\nexport function ensureKeybindingsFile(userDir: string): string {\n const path = keybindingsPath(userDir)\n if (existsSync(path))\n return path\n writeFileAtomic(path, renderDefaultFile(), { ensureDir: true })\n return path\n}\n\n/**\n * Read the raw on-disk JSON object from `keybindings.json` after the\n * JSONC stripper. Used by extension-keybinding resolution so the\n * user's overrides for extension-owned ids flow through the same file\n * the built-in actions use.\n *\n * Returns an empty object on missing / malformed / non-object files\n * — same fault-tolerance contract as {@link readKeybindings}.\n *\n * @param userDir - User-level config directory that holds `keybindings.json`.\n */\nexport function readKeybindingsRaw(userDir: string): Readonly<Record<string, unknown>> {\n const path = keybindingsPath(userDir)\n if (!existsSync(path))\n return {}\n try {\n const raw = readFileSync(path, 'utf-8')\n const parsed = JSON.parse(stripJsonComments(raw)) as unknown\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))\n return {}\n return parsed as Readonly<Record<string, unknown>>\n }\n catch {\n return {}\n }\n}\n\n/**\n * Resolve the live spec string for each extension-contributed\n * keybinding. The user's `keybindings.json` is consulted for an\n * override on the binding's `id`; absent / invalid entries fall back\n * to the binding's `default`.\n *\n * A chord that is reserved or a bare printable character\n * (see {@link isReservedExtensionBinding}, {@link isBareCharExtensionBinding})\n * is refused: a user override falls back to the default, and such a default\n * resolves to unbound.\n *\n * Pass the raw object (from {@link readKeybindingsRaw}) — passing\n * `KeyBindings` here wouldn't help because the typed map only carries\n * built-in `KeyAction` entries.\n *\n * Returns one entry per input binding, in source order. Empty `spec`\n * (binding declared `default: ''` and the user didn't bind it) is a\n * legitimate \"unbound\" state — the dispatcher never matches an empty\n * spec, so the action stays accessible via re-binding through\n * `keybindings.json`.\n *\n * @param bindings - Extension keybindings with their ids and default specs.\n * @param raw - Raw object from {@link readKeybindingsRaw}.\n */\nexport function resolveExtensionKeybindings(\n bindings: readonly { id: string, default: string }[],\n raw: Readonly<Record<string, unknown>>,\n): ResolvedExtensionKeybinding[] {\n return bindings.map((binding) => {\n const candidate = raw[binding.id]\n if (\n typeof candidate === 'string'\n && parseBindingSpec(candidate)\n && !isReservedExtensionBinding(candidate)\n && !isBareCharExtensionBinding(candidate)\n ) {\n return { id: binding.id, spec: candidate }\n }\n return {\n id: binding.id,\n spec: isReservedExtensionBinding(binding.default) || isBareCharExtensionBinding(binding.default)\n ? ''\n : binding.default,\n }\n })\n}\n\n/**\n * `true` when `spec` is one of the chords the framework reserves for\n * itself — `escape` (back / exit), `ctrl+escape` (the `abortRun`\n * default — the one built-in that must never be shadowed) and `ctrl+c`\n * (quit). Extensions\n * can never claim these, neither via their declared `default` nor via a\n * user override in `keybindings.json`. Single source of truth shared by\n * `resolveExtensionKeybindings` above and the registration-time refusal\n * in `extensions/register.ts`.\n */\nexport function isReservedExtensionBinding(spec: string): boolean {\n const parsed = parseBindingSpec(spec)\n if (!parsed)\n return false\n const noExtraModifiers = !parsed.shift && !parsed.alt && !parsed.meta\n if (parsed.name === 'escape' && noExtraModifiers)\n return true\n return parsed.name === 'c' && parsed.ctrl && noExtraModifiers\n}\n\n/**\n * `true` when `spec` is a single printable character without a gating\n * modifier (ctrl / alt / meta — shift alone is just a capital letter).\n * Such a chord would fire on every matching keystroke while the user\n * types in the prompt, so extension bindings can't use one; they're\n * registered unbound instead (rebindable to a modified chord via\n * `keybindings.json`).\n */\nexport function isBareCharExtensionBinding(spec: string): boolean {\n const parsed = parseBindingSpec(spec)\n if (!parsed)\n return false\n return parsed.name.length === 1 && !parsed.ctrl && !parsed.alt && !parsed.meta\n}\n\n/**\n * Render the default `keybindings.json` body. JSONC with a header\n * explaining the format + per-action comments derived from\n * {@link KEYBINDING_DEFS}'s descriptions. The user sees the catalog +\n * defaults at a glance the moment they open the file.\n *\n * Extension-contributed bindings live alongside the built-ins in the\n * SAME file (keyed by their `id`, e.g. `\"my-ext.openPanel\"`) — they\n * don't appear in the scaffold because extensions are discovered at\n * runtime, but `resolveExtensionKeybindings` reads the same file so\n * a user-added entry overrides the extension's default. The header of\n * the scaffold tells the user how.\n */\nfunction renderDefaultFile(): string {\n const lines: string[] = []\n lines.push('// Zidane keybindings. Edit the values below to customize.')\n lines.push('//')\n lines.push('// Format:')\n lines.push('// \"<action>\": \"<modifier>+<modifier>+<key>\"')\n lines.push('//')\n lines.push('// Modifiers: ctrl, shift, alt (option), meta (cmd).')\n lines.push('// Keys: a-z, 0-9, tab, return, escape, space, delete, …')\n lines.push('//')\n lines.push('// Comments (`//` line, `/* block */`) are stripped before parsing.')\n lines.push('// Restart the TUI to apply changes.')\n lines.push('//')\n lines.push('// Extensions (.zidane/extensions/<name>/index.ts) can register')\n lines.push('// their own keybindings; rebind any of them by adding a line')\n lines.push('// using the extension binding\\'s id, e.g.')\n lines.push('// \"my-ext.openPanel\": \"ctrl+shift+j\"')\n lines.push('// The Settings → Keybindings tab lists every registered id.')\n lines.push('{')\n KEYBINDING_DEFS.forEach((def, i) => {\n const trailingComma = i < KEYBINDING_DEFS.length - 1 ? ',' : ''\n lines.push(` // ${def.description}`)\n lines.push(` ${JSON.stringify(def.action)}: ${JSON.stringify(def.default)}${trailingComma}`)\n })\n lines.push('}')\n lines.push('')\n return lines.join('\\n')\n}\n\n// ---------------------------------------------------------------------------\n// JSONC parsing — `//` line + `/* block */` comments, single pass\n// ---------------------------------------------------------------------------\n\n/**\n * Strip `//` line comments and `/* … *\\/` block comments from a JSONC\n * source string. Stays out of string literals so a `\"foo // bar\"` value\n * keeps its slashes. Exported for unit-tests; the only runtime caller\n * is {@link readKeybindingsRaw}.\n *\n * Trade-off: this is a tiny state-machine, not a full JSONC parser. It\n * doesn't understand `\\\\` outside strings (irrelevant for JSON) and\n * doesn't track line numbers in error messages. Good enough for a\n * config file — corruption in production gracefully falls back to the\n * defaults via the try/catch in `readKeybindingsRaw`.\n *\n * @param input - JSONC source text.\n */\nexport function stripJsonComments(input: string): string {\n let out = ''\n let i = 0\n let inString = false\n let escape = false\n while (i < input.length) {\n const c = input[i]\n if (inString) {\n out += c\n if (escape)\n escape = false\n else if (c === '\\\\')\n escape = true\n else if (c === '\"')\n inString = false\n i++\n continue\n }\n if (c === '\"') {\n inString = true\n out += c\n i++\n continue\n }\n if (c === '/' && input[i + 1] === '/') {\n while (i < input.length && input[i] !== '\\n')\n i++\n continue\n }\n if (c === '/' && input[i + 1] === '*') {\n i += 2\n while (i < input.length && !(input[i] === '*' && input[i + 1] === '/'))\n i++\n i += 2\n continue\n }\n out += c\n i++\n }\n return out\n}\n","/**\n * The extension keymap: extension command bindings with focus scopes, an\n * `editable` flag, a mode stack and fall-through dispatch.\n *\n * Host-agnostic: a host turns its key event into a chord (a spec string or a\n * {@link ParsedBinding}) and a {@link KeyFocus}, then calls\n * {@link Keymap.dispatch}. Built-in host keys stay with the host; it calls\n * `dispatch` for the keys it did not handle (the TUI already runs extension\n * bindings after its built-ins, `src/tui/shell/app-keyboard.tsx`).\n *\n * The chord grammar is `keybindings.json`'s (`src/chat/keybinding-spec.ts`),\n * plus `mod`: `meta` on macOS, `ctrl` elsewhere. The reserved chords are the\n * ones `isReservedExtensionBinding` refuses (`src/chat/keybindings.ts`).\n */\n\nimport type { KeyBindingGroup, ParsedBinding } from '../../chat/keybindings'\nimport type { Logger } from '../../logger'\nimport type { KeymapEntry, KeyScope } from '../api/commands'\nimport type { Disposable } from '../api/core'\nimport { bindingAlternatives, isBareCharExtensionBinding, isReservedExtensionBinding, KEYBINDING_DEFS, mergeKeybindings, parseBindingSpec } from '../../chat/keybindings'\n\n/** Where focus is when a key arrives, as the host reports it. */\nexport interface KeyFocus {\n /** The focused area. `'global'` when nothing in particular holds focus. */\n scope: KeyScope\n /** A text field has focus: only bindings marked `editable` fire. */\n editable?: boolean\n /** The session the focused window shows. Selects per-session modes. */\n sessionId?: string\n /** A run is in flight on that session (for `when: 'idle'`). */\n busy?: boolean\n}\n\n/** What a binding's trigger receives. */\nexport interface KeyTriggerContext {\n /** The canonical chord that matched (`ctrl+shift+t`). */\n chord: string\n /** The focus the host reported. */\n focus: KeyFocus\n}\n\n/** One command's binding, as the command registry adds it. */\nexport interface KeymapBinding {\n /** Published command id (`<extension>.<id>`); user overrides are keyed by it. */\n commandId: string\n /** Default chords, already canonical (see {@link normalizeChords}). May be empty: unbound until the user binds it. */\n defaults: readonly string[]\n /** Where focus must be. Default `'global'`. */\n scope?: KeyScope\n /** Fires while a text field has focus. */\n editable?: boolean\n /** Fires only while this mode is the current one. */\n mode?: string\n /** Availability: `session` needs a session, `idle` also needs no run in flight. */\n when?: 'always' | 'session' | 'idle'\n /** `false` turns the binding off. Read on every dispatch. */\n enabled?: () => boolean\n /** Runs the command. Returning `false` passes the key on to the next match. */\n trigger: (ctx: KeyTriggerContext) => boolean\n}\n\n/** A binding with its effective chords, as {@link Keymap.list} reports it. */\nexport interface ResolvedKeymapBinding {\n /** Published command id. */\n commandId: string\n /** Chords after user overrides. Empty when unbound. */\n chords: readonly string[]\n /** `true` when a user override replaced the defaults. */\n overridden: boolean\n /** The binding's scope. */\n scope: KeyScope\n /** The binding's `editable` flag. */\n editable: boolean\n /** The binding's mode, when it has one. */\n mode?: string\n}\n\n/** Host side of the keymap: where user overrides come from. */\nexport interface KeymapPort {\n /**\n * The user's chords for a command (`keybindings.json` keyed by command id).\n * `undefined` keeps the defaults; `''` or `[]` unbinds.\n */\n overrides?: (commandId: string) => string | readonly string[] | undefined\n /** Calls `listener` when the overrides change. Returns the unsubscribe. */\n subscribe?: (listener: () => void) => () => void\n}\n\n/** Options for {@link createKeymap}. */\nexport interface KeymapOptions {\n /** User overrides. */\n port?: KeymapPort\n /** `process.platform` of the host; decides what `mod` means. Default `process.platform`. */\n platform?: string\n /** Receives warnings about refused overrides. */\n logger?: Logger\n}\n\n/** Options for {@link Keymap.pushMode}. */\nexport interface ModeOptions {\n /** Higher wins over modes pushed later with a lower priority. Default `0`. */\n priority?: number\n /** Limits the mode to the windows showing this session. */\n sessionId?: string\n}\n\n/** The host-wide keymap. */\nexport interface Keymap {\n /** Adds a binding. Dispose to remove it. */\n add: (binding: KeymapBinding) => Disposable\n /** Activates a mode. Dispose to pop it, wherever it sits in the stack. */\n pushMode: (name: string, opts?: ModeOptions) => Disposable\n /** The current mode for `sessionId` (global modes included), or for global modes only. */\n currentMode: (sessionId?: string) => string | undefined\n /** The active modes for `sessionId` (global modes included), or the global ones only, in precedence order: the current mode last. */\n activeModes: (sessionId?: string) => readonly string[]\n /** Effective chords of a command after user overrides. Empty when unknown or unbound. */\n bindings: (commandId: string) => readonly string[]\n /**\n * Runs the bindings that match `chord` under `focus`, highest precedence\n * first, and stops at the first that does not return `false`. Returns\n * `true` when one claimed the key, `false` when the host should handle it.\n *\n * Precedence: bindings of the current mode, then a binding scoped to the\n * focused area over a `global` one, then registration order.\n */\n dispatch: (chord: string | ParsedBinding, focus: KeyFocus) => boolean\n /** Every binding with its effective chords, in registration order. */\n list: () => readonly ResolvedKeymapBinding[]\n /** Calls `listener` after bindings, modes or overrides change. Returns the unsubscribe. */\n subscribe: (listener: () => void) => () => void\n /** Re-reads every override. Called on its own when the port's `subscribe` fires. */\n refresh: () => void\n /** Stops listening to the port. */\n dispose: () => void\n}\n\n/** Why a chord was refused. */\nexport type ChordRefusal = 'reserved' | 'unparsable' | 'bare'\n\n/** The outcome of {@link normalizeChords}. */\nexport interface NormalizedChords {\n /** Canonical chords that passed. */\n chords: string[]\n /** Chords that were refused, with the reason. */\n refused: { chord: string, reason: ChordRefusal }[]\n}\n\n/**\n * Replaces the `mod` modifier with `meta` (macOS) or `ctrl`.\n *\n * @param spec - One chord, for example `mod+shift+t`.\n * @param platform - `process.platform` of the host.\n */\nexport function resolveMod(spec: string, platform: string): string {\n const mod = platform === 'darwin' ? 'meta' : 'ctrl'\n return spec.replace(/(^|[+\\-\\s])mod(?=\\s*[+\\-])/gi, `$1${mod}`)\n}\n\n/**\n * The canonical text of a parsed chord: modifiers in a fixed order, then the\n * key. Two specs for the same keys give the same text.\n *\n * @param parsed - A parsed chord.\n */\nexport function chordKey(parsed: ParsedBinding): string {\n const name = parsed.name === '-' ? 'minus' : parsed.name\n return `${parsed.ctrl ? 'ctrl+' : ''}${parsed.alt ? 'alt+' : ''}${parsed.shift ? 'shift+' : ''}${parsed.meta ? 'meta+' : ''}${name}`\n}\n\n/**\n * Validates and canonicalizes chords. A spec may list alternatives\n * (`ctrl+w | cmd+w`). Esc and ctrl+c are refused; so is a bare printable\n * key on an `editable` binding, which would fire on every keystroke.\n *\n * @param specs - One spec or several.\n * @param opts - The host platform (for `mod`) and the binding's `editable` flag.\n * @param opts.platform - `process.platform` of the host.\n * @param opts.editable - The binding fires while a text field has focus.\n */\nexport function normalizeChords(\n specs: string | readonly string[] | undefined,\n opts: { platform: string, editable?: boolean },\n): NormalizedChords {\n const out: NormalizedChords = { chords: [], refused: [] }\n const list = specs === undefined ? [] : typeof specs === 'string' ? [specs] : specs\n for (const spec of list) {\n if (typeof spec !== 'string') {\n out.refused.push({ chord: String(spec), reason: 'unparsable' })\n continue\n }\n for (const alternative of bindingAlternatives(spec)) {\n const resolved = resolveMod(alternative, opts.platform)\n const parsed = parseBindingSpec(resolved)\n if (!parsed) {\n out.refused.push({ chord: alternative, reason: 'unparsable' })\n continue\n }\n const key = chordKey(parsed)\n if (isReservedExtensionBinding(key)) {\n out.refused.push({ chord: alternative, reason: 'reserved' })\n continue\n }\n if (opts.editable && isBareCharExtensionBinding(key)) {\n out.refused.push({ chord: alternative, reason: 'bare' })\n continue\n }\n if (!out.chords.includes(key))\n out.chords.push(key)\n }\n }\n return out\n}\n\ninterface BindingSlot {\n binding: KeymapBinding\n chords: readonly string[]\n overridden: boolean\n}\n\ninterface ModeSlot {\n name: string\n priority: number\n sessionId?: string\n seq: number\n}\n\n/**\n * Makes a keymap. One per host process; every extension's commands bind\n * into it.\n *\n * @param opts - User overrides, platform and logger.\n */\nexport function createKeymap(opts: KeymapOptions = {}): Keymap {\n const platform = opts.platform ?? process.platform\n const port = opts.port\n const slots: BindingSlot[] = []\n const modes: ModeSlot[] = []\n const listeners = new Set<() => void>()\n let seq = 0\n\n const notify = () => {\n for (const listener of [...listeners]) {\n try {\n listener()\n }\n catch (error) {\n opts.logger?.warn('keymap: listener threw', { error: String(error) })\n }\n }\n }\n\n const resolve = (binding: KeymapBinding): { chords: readonly string[], overridden: boolean } => {\n let override: string | readonly string[] | undefined\n try {\n override = port?.overrides?.(binding.commandId)\n }\n catch (error) {\n opts.logger?.warn('keymap: overrides lookup threw', { command: binding.commandId, error: String(error) })\n }\n if (override === undefined)\n return { chords: binding.defaults, overridden: false }\n const list = typeof override === 'string' ? [override] : override\n if (list.length === 0 || list.every(s => typeof s === 'string' && s.trim() === ''))\n return { chords: [], overridden: true }\n const normalized = normalizeChords(list, { platform, editable: binding.editable })\n for (const { chord, reason } of normalized.refused)\n opts.logger?.warn('keymap: user binding refused', { command: binding.commandId, chord, reason })\n // Like `resolveExtensionKeybindings`: an override with nothing usable keeps the defaults.\n if (normalized.chords.length === 0)\n return { chords: binding.defaults, overridden: false }\n return { chords: normalized.chords, overridden: true }\n }\n\n // Lowest precedence first: priority, then the later push wins among equals.\n const activeModes = (sessionId?: string): string[] => modes\n .filter(mode => mode.sessionId === undefined || mode.sessionId === sessionId)\n .sort((a, b) => a.priority - b.priority || a.seq - b.seq)\n .map(mode => mode.name)\n const currentMode = (sessionId?: string): string | undefined => activeModes(sessionId).at(-1)\n\n const available = (binding: KeymapBinding, focus: KeyFocus, mode: string | undefined): boolean => {\n if (focus.editable && !binding.editable)\n return false\n const scope = binding.scope ?? 'global'\n if (scope === 'global' ? focus.scope === 'modal' : scope !== focus.scope)\n return false\n if (binding.mode !== undefined && binding.mode !== mode)\n return false\n if (binding.when === 'session' && !focus.sessionId)\n return false\n if (binding.when === 'idle' && (!focus.sessionId || focus.busy))\n return false\n try {\n return binding.enabled?.() !== false\n }\n catch {\n return false\n }\n }\n\n const keymap: Keymap = {\n add(binding) {\n const slot: BindingSlot = { binding, ...resolve(binding) }\n slots.push(slot)\n notify()\n let done = false\n return {\n dispose() {\n if (done)\n return\n done = true\n const at = slots.indexOf(slot)\n if (at >= 0)\n slots.splice(at, 1)\n notify()\n },\n }\n },\n pushMode(name, modeOpts = {}) {\n const slot: ModeSlot = { name, priority: modeOpts.priority ?? 0, seq: ++seq, ...(modeOpts.sessionId !== undefined ? { sessionId: modeOpts.sessionId } : {}) }\n modes.push(slot)\n notify()\n let done = false\n return {\n dispose() {\n if (done)\n return\n done = true\n const at = modes.indexOf(slot)\n if (at >= 0)\n modes.splice(at, 1)\n notify()\n },\n }\n },\n currentMode,\n activeModes,\n bindings(commandId) {\n return slots.find(s => s.binding.commandId === commandId)?.chords ?? []\n },\n dispatch(chord, focus) {\n const parsed = typeof chord === 'string' ? parseBindingSpec(resolveMod(chord, platform)) : chord\n if (!parsed)\n return false\n const key = chordKey(parsed)\n const mode = currentMode(focus.sessionId)\n const rank = (b: KeymapBinding) => (b.mode !== undefined ? 0 : 2) + ((b.scope ?? 'global') === 'global' ? 1 : 0)\n const candidates = slots\n .filter(s => s.chords.includes(key) && available(s.binding, focus, mode))\n .map((s, order) => ({ binding: s.binding, order }))\n .sort((a, b) => rank(a.binding) - rank(b.binding) || a.order - b.order)\n for (const { binding } of candidates) {\n let claimed = true\n try {\n claimed = binding.trigger({ chord: key, focus }) !== false\n }\n catch (error) {\n opts.logger?.warn('keymap: trigger threw', { command: binding.commandId, error: String(error) })\n }\n if (claimed)\n return true\n }\n return false\n },\n list() {\n return slots.map(s => ({\n commandId: s.binding.commandId,\n chords: s.chords,\n overridden: s.overridden,\n scope: s.binding.scope ?? 'global',\n editable: s.binding.editable === true,\n ...(s.binding.mode !== undefined ? { mode: s.binding.mode } : {}),\n }))\n },\n subscribe(listener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n refresh() {\n for (const slot of slots)\n Object.assign(slot, resolve(slot.binding))\n notify()\n },\n dispose() {\n // eslint-disable-next-line ts/no-use-before-define -- assigned right after the object\n unsubscribePort?.()\n },\n }\n const unsubscribePort = port?.subscribe?.(() => keymap.refresh())\n return keymap\n}\n\n/** Where a built-in key's group fires: the sessions screen is the sidebar, the details groups are modals. */\nconst BUILTIN_KEY_SCOPES: Readonly<Record<KeyBindingGroup, KeyScope>> = {\n 'Global': 'global',\n 'Sessions': 'sidebar',\n 'Message queue': 'modal',\n 'Turn details': 'modal',\n 'Session details': 'modal',\n}\n\n/**\n * The built-in key bindings (`KEYBINDING_DEFS`) as `ctx.keymap.list` reports\n * them, with the user's `keybindings.json` applied. What a host passes as\n * `CommandHostPort.keybindings`.\n *\n * @param overrides - The raw `keybindings.json` object (`readKeybindingsRaw`).\n * @returns One entry per built-in action, in catalog order; an unbound action has no bindings.\n */\nexport function builtinKeymapEntries(overrides: Readonly<Record<string, unknown>> | null | undefined): KeymapEntry[] {\n const effective = mergeKeybindings(overrides)\n return KEYBINDING_DEFS.map(def => ({\n id: def.action,\n title: def.description,\n bindings: bindingAlternatives(effective[def.action] ?? '').map(chord => chord.trim()).filter(Boolean),\n scope: BUILTIN_KEY_SCOPES[def.group] ?? 'global',\n editable: false,\n }))\n}\n","/**\n * Converts an extension settings schema to the wire format the Settings UIs render\n * today: `WireExtensionConfigSchema` (`src/extensions/config.ts`), the\n * action rows of `src/extensions/config-actions.ts`, and values shaped like\n * `Settings.extensionConfig`. zidane-ui's `ExtensionOptionsSection` keeps\n * working unchanged.\n */\n\nimport type { AccessScope } from '../api/core'\nimport type { ActionSettingStatus, Setting, SettingsCategory, SettingsSchema } from '../api/settings'\nimport type {\n ExtensionConfigActionStatus,\n ExtensionConfigCategory,\n ExtensionConfigValue,\n StoredExtensionConfigItem,\n WireExtensionConfigItem,\n WireExtensionConfigSchema,\n} from '../config'\nimport type { ExtensionActionSummary } from '../config-actions'\nimport type { ComponentWire } from '../ui/wire'\nimport type { StoredSettingValue, ValueSetting } from './validate'\nimport { actionScope, DEFAULT_SETTINGS_PAGE_ID, isValueSetting, settingDefault } from './validate'\n\n/** An action row: what `listActionSummaries` produces, plus the token scope a remote client needs to run it. */\nexport interface WireSettingsAction extends ExtensionActionSummary {\n /** The least token scope a remote client needs. Apps disable the button below it. */\n scope: AccessScope\n}\n\n/** A group of rows on a settings page, in the order to draw them. */\nexport interface WireSettingsPageSection {\n /** The section id, or `undefined` for the page's ungrouped rows (drawn first, without a sub-header). */\n id?: string\n /** Sub-header. Absent for ungrouped rows. */\n label?: string\n /** Line under the sub-header. */\n description?: string\n /** The wire category id of the rows (`wireCategoryId`). */\n category: string\n /** Keys of the rows, in order: value rows of `schema.items` and action rows of `actions`. */\n keys: string[]\n}\n\n/**\n * One page of an extension's settings in the sidebar. `kind: 'schema'`\n * pages come from the definition's schema and list keys of the wire's own\n * rows; `kind: 'ui'` pages are `SettingsPage` items, drawn from their own\n * `schema` wire or `component`.\n */\nexport interface WireSettingsPage {\n /** The extension the page belongs to. */\n extension: string\n /** Where the page comes from. */\n kind: 'schema' | 'ui'\n /** Unique among the extension's pages: the schema page id, or the item's `<extension>/<id>` for a `ui` page. */\n id: string\n /** Sidebar label (the page title for `ui` pages). */\n label: string\n /** Line under the page title. */\n description?: string\n /** Icon in each app's vocabulary. */\n icon?: { gui?: string, tui?: string }\n /**\n * The page the extension gets when its schema declares none: id `main`,\n * labelled with the extension's name. `settingsSidebar` relabels it with\n * the display name it is given.\n */\n implicit?: true\n /** `kind: 'ui'`: its place among the extension's `ui` pages (lower first, default 100). */\n order?: number\n /** `kind: 'schema'`: the rows of the page, by section. Ungrouped rows first, then sections as declared. */\n sections: WireSettingsPageSection[]\n /** `kind: 'ui'`: the page's settings in this same wire format. */\n schema?: WireSettings\n /** `kind: 'ui'`: drawn instead of the data where the host has it. */\n component?: ComponentWire\n}\n\n/** Everything a Settings UI needs to draw an extension's settings. */\nexport interface WireSettings {\n /** The value rows, as `toWireConfigSchema` produces them. */\n schema: WireExtensionConfigSchema\n /** The action rows, as `listActionSummaries` produces them, with their scope. */\n actions: WireSettingsAction[]\n /** Values by extension then key, the shape of `Settings.extensionConfig`. Secrets are left out. */\n values: Record<string, Record<string, ExtensionConfigValue>>\n /** Locked settings (set by a declarative config entry), as `extension:key`. */\n locked: string[]\n /** One extension's wire: its own sidebar group (`SettingsSchema.category`). Absent on a merged wire (see `extensionCategories`). */\n category?: SettingsCategory\n /** A merged wire: each extension's category, by extension id. */\n extensionCategories?: Record<string, SettingsCategory>\n /**\n * Each extension's display name and icon, by extension id: the settings\n * sidebar's labels and glyphs. Set by `toWireSettings` (its extension),\n * `mergeWireSettings` (every part's) and `runtimeSettingsWire` (the\n * definition's `displayName` and `icon`). Absent on older wires: apps\n * fall back to the implicit page's label, else the id.\n */\n extensions?: Record<string, WireSettingsExtension>\n /**\n * The settings pages in sidebar order: per extension, the schema's pages,\n * then its `ui` pages by `order`. Always set by `toWireSettings` and\n * `mergeWireSettings`; optional so older wires (and hand-built empty ones) still type.\n */\n pages?: WireSettingsPage[]\n}\n\n/** An extension as the settings wire names it (`WireSettings.extensions`). */\nexport interface WireSettingsExtension {\n /** Its display name, else its id. */\n name: string\n /** Its icon in each app's vocabulary (`ExtensionDefinition.icon`). */\n icon?: { gui?: string, tui?: string }\n /** What it does (`ExtensionDefinition.description`): the line under its name atop its settings. */\n description?: string\n}\n\n/** A `SettingsPage` item as {@link withSettingsPages} takes it: the fields of its wire (`SettingsPageWire`). */\nexport interface SettingsPageInput {\n /** `<extension>/<id>`. */\n id: string\n /** Page title. */\n title: string\n /** Icon in the settings sidebar. */\n icon?: { gui?: string, tui?: string }\n /** Place among the extension's `ui` pages, lower first. Default 100. */\n order?: number\n /** The page's settings in the wire format. */\n schema?: WireSettings\n /** Drawn instead of the data where the host has it. */\n component?: ComponentWire\n}\n\n/**\n * The wire category id of a section. Sections belong to one extension, the\n * wire has one flat category list, so the id is namespaced. An ungrouped\n * setting sits in the implicit category whose id is the extension id (the\n * UI draws no sub-header for it).\n *\n * @param extensionId - The extension.\n * @param sectionId - The section, or `undefined` for ungrouped.\n * @returns The category id.\n */\nexport function wireCategoryId(extensionId: string, sectionId: string | undefined): string {\n return sectionId === undefined ? extensionId : `${extensionId}:${sectionId}`\n}\n\n/**\n * A value in its wire shape: a model list joins as `'a, b'`, the shape the\n * UIs write back.\n *\n * @param value - A resolved value.\n * @returns The wire value.\n */\nexport function toWireValue(value: StoredSettingValue): ExtensionConfigValue {\n return Array.isArray(value) ? value.join(', ') : value as ExtensionConfigValue\n}\n\n/**\n * The wire default. Legacy config items always carry one; a setting without a\n * default gets the empty value of its type (false, the number nearest 0 in\n * range, `''`, the first enum option).\n */\nfunction wireDefault(setting: ValueSetting): ExtensionConfigValue {\n const declared = settingDefault(setting)\n if (declared !== undefined)\n return toWireValue(declared)\n switch (setting.type) {\n case 'boolean':\n return false\n case 'number':\n return Math.min(setting.max ?? Infinity, Math.max(setting.min ?? -Infinity, 0))\n case 'enum':\n return setting.options[0]?.value ?? ''\n default:\n return ''\n }\n}\n\nfunction wireItem(extensionId: string, key: string, setting: ValueSetting): WireExtensionConfigItem {\n const base = {\n key,\n label: setting.label,\n ...(setting.description !== undefined ? { description: setting.description } : {}),\n ...(setting.scopes?.[0] !== undefined ? { scope: setting.scopes[0] } : {}),\n ...(setting.apply !== undefined ? { onChange: setting.apply } : {}),\n ...(setting.apply === 'restart' ? { requiresRestart: true } : {}),\n category: wireCategoryId(extensionId, setting.section),\n extension: extensionId,\n }\n switch (setting.type) {\n case 'boolean':\n return { ...base, type: 'boolean', default: wireDefault(setting) as boolean }\n case 'number':\n return {\n ...base,\n type: 'number',\n default: wireDefault(setting) as number,\n ...(setting.min !== undefined ? { min: setting.min } : {}),\n ...(setting.max !== undefined ? { max: setting.max } : {}),\n ...(setting.step !== undefined ? { step: setting.step } : {}),\n }\n case 'string':\n return {\n ...base,\n type: 'string',\n default: wireDefault(setting) as string,\n ...(setting.pattern !== undefined ? { pattern: setting.pattern } : {}),\n ...(setting.multiline !== undefined ? { multiline: setting.multiline } : {}),\n ...(setting.secret !== undefined ? { secret: setting.secret } : {}),\n }\n case 'enum':\n return {\n ...base,\n type: 'enum',\n default: wireDefault(setting) as string,\n options: setting.options.map(o => ({ value: o.value, label: o.label })),\n }\n case 'model':\n return { ...base, type: 'model', default: wireDefault(setting) as string, ...(setting.multi !== undefined ? { multi: setting.multi } : {}) }\n }\n}\n\nfunction sectionRank(schema: SettingsSchema, sectionId: string | undefined): number {\n if (sectionId === undefined)\n return -1\n return (schema.sections ?? []).findIndex(s => s.id === sectionId)\n}\n\n/**\n * The page a setting sits on: its `page`, else its section's page, else\n * the first page. Clean the schema first (`settingsForDefinition`).\n *\n * @param schema - The cleaned schema.\n * @param setting - One of its settings.\n * @returns The page id.\n */\nexport function settingPageId(schema: SettingsSchema, setting: Pick<Setting, 'page' | 'section'>): string {\n const first = schema.pages?.[0]?.id ?? DEFAULT_SETTINGS_PAGE_ID\n if (setting.page !== undefined)\n return setting.page\n const section = setting.section === undefined ? undefined : schema.sections?.find(s => s.id === setting.section)\n return section?.page ?? first\n}\n\n/** The schema's pages with their rows. No pages and no rows: none. */\nfunction wirePages(extensionId: string, schema: SettingsSchema, displayName: string | undefined): WireSettingsPage[] {\n const entries = Object.entries(schema.items)\n const declared = schema.pages ?? []\n if (declared.length === 0 && entries.length === 0)\n return []\n const pages: WireSettingsPage[] = declared.length > 0\n ? declared.map(p => ({\n extension: extensionId,\n kind: 'schema' as const,\n id: p.id,\n label: p.label,\n ...(p.description !== undefined ? { description: p.description } : {}),\n ...(p.icon !== undefined ? { icon: { ...p.icon } } : {}),\n sections: [],\n }))\n : [{ extension: extensionId, kind: 'schema', id: DEFAULT_SETTINGS_PAGE_ID, label: displayName ?? extensionId, implicit: true, sections: [] }]\n const byPage = new Map(pages.map(p => [p.id, p]))\n const sectionOrder = [undefined, ...(schema.sections ?? []).map(s => s.id)]\n for (const sectionId of sectionOrder) {\n const meta = sectionId === undefined ? undefined : schema.sections?.find(s => s.id === sectionId)\n for (const [key, setting] of entries) {\n if (setting.section !== sectionId)\n continue\n const page = byPage.get(settingPageId(schema, setting)) ?? pages[0]!\n let section = page.sections.find(s => s.id === sectionId)\n if (!section) {\n section = {\n ...(sectionId !== undefined ? { id: sectionId } : {}),\n ...(meta ? { label: meta.label } : {}),\n ...(meta?.description !== undefined ? { description: meta.description } : {}),\n category: wireCategoryId(extensionId, sectionId),\n keys: [],\n }\n page.sections.push(section)\n }\n section.keys.push(key)\n }\n }\n return pages\n}\n\n/**\n * Converts one extension's schema and values to the wire format. Rows come\n * ungrouped first, then by section in declared order. Pure: never calls\n * author code.\n *\n * @param extensionId - The extension.\n * @param schema - Its settings (clean it with `settingsForDefinition` first).\n * @param values - Effective values by key; missing keys are left out (the UI shows the default).\n * @param opts - `locked`, `displayName` and `icon`.\n * @param opts.locked - Keys a declarative config entry sets.\n * @param opts.displayName - The extension's name: the label of its implicit page and its `extensions` entry (default: the id).\n * @param opts.icon - The extension's icon, for its `extensions` entry.\n * @returns The wire settings.\n */\nexport function toWireSettings(\n extensionId: string,\n schema: SettingsSchema,\n values: Readonly<Record<string, StoredSettingValue | undefined>> = {},\n opts: { locked?: readonly string[], displayName?: string, icon?: { gui?: string, tui?: string } } = {},\n): WireSettings {\n const entries = Object.entries(schema.items)\n .map((entry, index) => ({ entry, index, rank: sectionRank(schema, entry[1].section) }))\n .sort((a, b) => a.rank - b.rank || a.index - b.index)\n .map(x => x.entry)\n const items: WireExtensionConfigItem[] = []\n const actions: WireSettingsAction[] = []\n const wireValues: Record<string, ExtensionConfigValue> = {}\n const used = new Set<string>()\n for (const [key, setting] of entries) {\n if (setting.section !== undefined)\n used.add(setting.section)\n if (isValueSetting(setting)) {\n items.push(wireItem(extensionId, key, setting))\n const value = values[key]\n if (value !== undefined && !(setting.type === 'string' && setting.secret === true))\n wireValues[key] = toWireValue(value)\n continue\n }\n const section = schema.sections?.find(s => s.id === setting.section)\n actions.push({\n extension: extensionId,\n key,\n label: setting.label,\n ...(setting.description !== undefined ? { description: setting.description } : {}),\n category: wireCategoryId(extensionId, setting.section),\n categoryLabel: section?.label ?? extensionId,\n hasStatus: typeof setting.status === 'function',\n scope: actionScope(setting),\n })\n }\n const categories: ExtensionConfigCategory[] = (schema.sections ?? [])\n .filter(s => used.has(s.id))\n .map(s => ({ id: wireCategoryId(extensionId, s.id), label: s.label, ...(s.description !== undefined ? { description: s.description } : {}) }))\n return {\n schema: { categories, items },\n actions: sortActions(actions),\n values: Object.keys(wireValues).length > 0 ? { [extensionId]: wireValues } : {},\n locked: (opts.locked ?? []).map(key => `${extensionId}:${key}`),\n ...(schema.category ? { category: { ...schema.category } } : {}),\n pages: wirePages(extensionId, schema, opts.displayName),\n extensions: { [extensionId]: wireExtension(extensionId, opts.displayName, opts.icon) },\n }\n}\n\n/**\n * An extension's `WireSettings.extensions` entry.\n *\n * @param extensionId - The extension.\n * @param displayName - Its display name; blank or absent: the id.\n * @param icon - Its icon.\n * @param description - What it does; blank or absent: none.\n * @returns The entry.\n */\nexport function wireExtension(extensionId: string, displayName?: string, icon?: { gui?: string, tui?: string }, description?: string): WireSettingsExtension {\n const gui = icon?.gui?.trim() ? icon.gui : undefined\n const tui = icon?.tui?.trim() ? icon.tui : undefined\n return {\n name: displayName?.trim() ? displayName : extensionId,\n ...(gui !== undefined || tui !== undefined ? { icon: { ...(gui !== undefined ? { gui } : {}), ...(tui !== undefined ? { tui } : {}) } } : {}),\n ...(description?.trim() ? { description: description.trim() } : {}),\n }\n}\n\n/**\n * Adds an extension's `SettingsPage` items to its wire, after the schema's\n * pages, by `order` (default 100; ties keep the given order). Items of\n * other extensions (their id does not start with `<extensionId>/`) are\n * ignored. Pure.\n *\n * @param wire - One extension's wire (`toWireSettings` or the domain's `wire()`).\n * @param extensionId - The extension.\n * @param pages - Its settings-page items, as the UI registry serializes them.\n * @returns A new wire with the pages appended.\n */\nexport function withSettingsPages(wire: WireSettings, extensionId: string, pages: readonly SettingsPageInput[]): WireSettings {\n const own = pages\n .filter(p => p.id.startsWith(`${extensionId}/`))\n .map((p, index) => ({ p, index, order: p.order ?? 100 }))\n .sort((a, b) => a.order - b.order || a.index - b.index)\n .map(({ p }): WireSettingsPage => ({\n extension: extensionId,\n kind: 'ui',\n id: p.id,\n label: p.title,\n ...(p.icon !== undefined ? { icon: { ...p.icon } } : {}),\n ...(p.order !== undefined ? { order: p.order } : {}),\n sections: [],\n ...(p.schema ? { schema: p.schema } : {}),\n ...(p.component ? { component: p.component } : {}),\n }))\n return own.length === 0 ? wire : { ...wire, pages: [...(wire.pages ?? []), ...own] }\n}\n\nfunction sortActions<A extends ExtensionActionSummary>(actions: A[]): A[] {\n return actions.sort((a, b) => a.extension.localeCompare(b.extension) || a.label.localeCompare(b.label))\n}\n\n/**\n * Joins the wire settings of several extensions into the one list the\n * Settings UI reads.\n *\n * @param parts - One {@link WireSettings} per extension.\n * @returns The merged wire settings.\n */\nexport function mergeWireSettings(parts: readonly WireSettings[]): WireSettings {\n const extensionCategories: Record<string, SettingsCategory> = {}\n const extensions: Record<string, WireSettingsExtension> = {}\n for (const part of parts) {\n Object.assign(extensions, part.extensions)\n for (const [id, category] of Object.entries(part.extensionCategories ?? {}))\n extensionCategories[id] = category\n const owner = part.pages?.[0]?.extension\n if (part.category && owner !== undefined)\n extensionCategories[owner] = part.category\n }\n return {\n schema: {\n categories: parts.flatMap(p => p.schema.categories),\n items: parts.flatMap(p => p.schema.items),\n },\n actions: sortActions(parts.flatMap(p => p.actions)),\n values: Object.assign({}, ...parts.map(p => p.values)) as WireSettings['values'],\n locked: parts.flatMap(p => p.locked),\n ...(Object.keys(extensionCategories).length > 0 ? { extensionCategories } : {}),\n pages: parts.flatMap(p => p.pages ?? []),\n ...(Object.keys(extensions).length > 0 ? { extensions } : {}),\n }\n}\n\n/**\n * An action status in the wire shape: `success` is `ok`, `warn` and\n * `error` are `error`, `muted` or no tone is `off`.\n *\n * @param status - The status an action's `status()` returned.\n * @returns The wire status.\n */\nexport function toWireActionStatus(status: ActionSettingStatus): ExtensionConfigActionStatus {\n const state = status.tone === 'success' ? 'ok' : status.tone === 'error' || status.tone === 'warn' ? 'error' : 'off'\n return { state, message: status.text }\n}\n\n/**\n * Builds a settings schema from stored config items (`StoredExtensionConfigItem`).\n * For tests. A `validate` carries over on string items only (the schema has\n * it on strings only); `config` patches become `patch`.\n *\n * @param extensionId - The declaring extension; its implicit category becomes \"ungrouped\".\n * @param categories - The categories by id.\n * @param items - The extension's items by key.\n * @returns The settings schema.\n */\nexport function fromConfigItems(\n extensionId: string,\n categories: Readonly<Record<string, ExtensionConfigCategory>>,\n items: Readonly<Record<string, StoredExtensionConfigItem>>,\n): SettingsSchema {\n const sections: { id: string, label: string, description?: string }[] = []\n const out: Record<string, Setting> = {}\n for (const item of Object.values(items)) {\n const section = item.category === extensionId ? undefined : item.category\n if (section !== undefined && !sections.some(s => s.id === section)) {\n const cat = categories[section]\n sections.push({ id: section, label: cat?.label ?? section, ...(cat?.description !== undefined ? { description: cat.description } : {}) })\n }\n const common = {\n label: item.label,\n ...(item.description !== undefined ? { description: item.description } : {}),\n ...(section !== undefined ? { section } : {}),\n }\n if (item.type === 'action') {\n const { run, status } = item\n out[item.key] = {\n ...common,\n type: 'action',\n button: item.label,\n run: async () => {\n const result = await run()\n if (!result)\n return undefined\n return { ...(result.message !== undefined ? { message: result.message } : {}), ...(result.config ? { patch: result.config } : {}) }\n },\n ...(status\n ? {\n status: async () => {\n const s = await status()\n return s ? { text: s.message, tone: s.state === 'ok' ? 'success' as const : s.state === 'error' ? 'error' as const : 'muted' as const } : { text: '' }\n },\n }\n : {}),\n }\n continue\n }\n const meta = {\n ...common,\n ...(item.scope !== undefined ? { scopes: [item.scope] } : {}),\n ...(item.onChange !== undefined ? { apply: item.onChange } : item.requiresRestart ? { apply: 'restart' as const } : {}),\n }\n switch (item.type) {\n case 'boolean':\n out[item.key] = { ...meta, type: 'boolean', default: item.default }\n break\n case 'number':\n out[item.key] = { ...meta, type: 'number', default: item.default, ...pick(item, ['min', 'max', 'step']) }\n break\n case 'string': {\n const validate = item.validate\n out[item.key] = {\n ...meta,\n type: 'string',\n default: item.default,\n ...pick(item, ['pattern', 'multiline', 'secret']),\n ...(validate ? { validate: (v: string) => validate(v) ? undefined : 'invalid value' } : {}),\n }\n break\n }\n case 'enum':\n out[item.key] = { ...meta, type: 'enum', default: item.default, options: item.options }\n break\n case 'model':\n out[item.key] = { ...meta, type: 'model', default: item.default, ...pick(item, ['multi']) }\n break\n }\n }\n return { sections, items: out }\n}\n\nfunction pick<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Partial<Pick<T, K>> {\n const out: Partial<Pick<T, K>> = {}\n for (const k of keys) {\n if (obj[k] !== undefined)\n out[k] = obj[k]\n }\n return out\n}\n","/**\n * Host runtime bridge — the late-bound capability surface behind\n * `ctx.runtime`, `ctx.sessions`, `ctx.ui`, `ctx.appendNote`, and `ctx.workspace`.\n *\n * Extension contexts are built before the host mounts, so these methods\n * route through a holder the host populates post-mount (the same idiom as\n * the prompt bridge). Detached degradation is split by stakes:\n * queries and toggles (`runtime` / `sessions` / `appendNote`) return\n * honest `null` / `false` — extensions guard on the return value instead\n * of try/catching host plumbing — while `workspace` operations REJECT,\n * because a silent no-op `writeFile` masquerading as success is worse\n * than an error (see {@link ExtensionWorkspaceSurface}).\n *\n * Notes deliberately reuse the command-output vocabulary\n * ({@link CommandOutputBlock}: full markdown or collapsed diff-colorable\n * details, or `custom` blocks bound to a registered view) and persist as\n * display-only turns — excluded from the model by the same wire guard as\n * command output. What you append is what reloads: even `custom` blocks\n * persist DATA + a mandatory markdown fallback, never rendered output —\n * the renderer registry (`ctx.tui.registerRenderer`) is a pure view\n * layer resolved at render time, so a missing/disabled renderer degrades\n * to the fallback instead of corrupting history.\n */\n\nimport type { CommandOutputBlock } from '../chat/commands'\nimport type { InteractionResponse } from '../chat/interactions'\nimport type { ModelInfo } from '../chat/providers'\nimport type { ExecResult, ExecutionContext, ExecutionHandle, ListFilesEntry, ListFilesOptions } from '../contexts'\nimport type { SessionStore } from '../session'\nimport type { SessionArtifact } from '../session/artifacts'\nimport type { JsonValue, ThinkingLevel } from '../types'\nimport type { SessionInfo, SessionListPage, SessionListQuery } from './api/sessions'\nimport type { ExtensionPromptDelivery } from './prompt-bridge'\nimport type { FacetRegistry } from './runtime/facets'\nimport type { ExtensionArtifactsSurface } from './types'\nimport { AsyncLocalStorage } from 'node:async_hooks'\nimport { normalizeArtifactInput } from '../session/artifacts'\n\n/**\n * One row of `ctx.runtime.models()` — a model offered by a provider the\n * user has credentials for. `provider.key` is the registry key (stable id,\n * e.g. `anthropic`); `provider.name` is the display name. `model` mirrors\n * the host's {@link ModelInfo} (id, context window, cost, …).\n */\nexport interface ExtensionModelEntry {\n /** Provider offering the model: registry `key` and display `name`. */\n provider: { key: string, name: string }\n /** Catalog entry for the model. */\n model: ModelInfo\n}\n\n/*\n * The orchestration shapes below mirror the chat host's (`chat/orchestration`,\n * `chat/host/orchestration`) structurally: the SDK core does not import the\n * chat layer, and the host's values are assignable to these.\n */\n\n/** An orchestration tool a session can hold: `sessions` drives sessions, `interactions` answers their prompts. */\nexport type ExtensionOrchestrationTool = 'sessions' | 'interactions'\n\n/** Which sessions a subscriber hears from. Every field narrows; `{}` is every session. */\nexport interface ExtensionSessionScope {\n /** Sessions in this project: its root, or a folder inside it. */\n projectRoot?: string\n /** Sessions on this machine: a lent machine's name, or `local` for the host itself. */\n machine?: string\n /** Only these sessions. */\n sessionIds?: readonly string[]\n}\n\n/** A tool approval's decision. */\nexport type ExtensionApprovalDecision = 'accept-once' | 'accept-session' | 'accept-safelist' | 'deny' | { kind: 'partial', mask: readonly boolean[] }\n\n/** One row of the orchestration `list(limit)` (`ExtensionSessionVerbs.list`), which `ctx.sessions.list` falls back to on a host without the `query` verb. */\nexport interface ExtensionSessionRow {\n /** Session id. */\n sessionId: string\n /** Session title (the id when it has none). */\n title: string\n /** Its folder; `''` for none. */\n cwd: string\n /** A run is in flight. */\n running: boolean\n /** Created by this extension. */\n worker: boolean\n /** Holds the `sessions` tool. */\n orchestrator?: boolean\n /** `blocked`: a question, plan or tool approval waits for an answer. */\n state: 'idle' | 'running' | 'blocked'\n /** Last change, epoch ms. */\n updatedAt: number\n /** Turns in the session. */\n turns: number\n}\n\n/** What `ctx.sessions.read()` returns. */\nexport interface ExtensionSessionDetail extends ExtensionSessionRow {\n /** Its last assistant message, cut to a few hundred characters. */\n lastMessage: string | null\n}\n\n/** What `ctx.sessions.create()` takes. */\nexport interface ExtensionCreateSessionParams {\n /** Folder the session runs in; `''` for none. */\n cwd: string\n /** First prompt, sent at once. Omit to create a session that waits (an orchestrator waiting for events). */\n prompt?: string\n /** Its title. */\n title?: string\n /** Agent profile id. */\n agentId?: string\n /** Provider registry key, with `modelId`. */\n providerKey?: string\n /** Model id. */\n modelId?: string\n /** Orchestration tools it holds: `sessions` (drive sessions), `interactions` (answer their prompts). */\n tools?: readonly ExtensionOrchestrationTool[]\n /** Sessions whose events it receives as `<session-event>` turns. `{}` = every session. */\n subscribe?: ExtensionSessionScope\n}\n\n/** What `ctx.sessions.wait()` returns. */\nexport interface ExtensionWaitResult {\n /** Why it returned: `idle` (was not running), `ended` (a run ended), `blocked` (a prompt waits), `timeout`. */\n reason: 'idle' | 'ended' | 'blocked' | 'timeout'\n /** The session as it is now. */\n session: ExtensionSessionDetail\n}\n\n/** One prompt waiting for an answer, from `ctx.sessions.pending()`. */\nexport interface ExtensionPendingRequest {\n /** The id to answer with. */\n requestId: string\n /** The session waiting. */\n sessionId: string\n /** `question` (ask_user), `plan` (present_plan), `approval` (a tool call). */\n kind: 'question' | 'plan' | 'approval'\n /** One line: what is asked. */\n summary: string\n /** The questions and choices, the plan, or the tool and its input. */\n payload: unknown\n}\n\n/** What `ctx.sessions.events()` searches for. Every field narrows. */\nexport interface ExtensionEventQuery {\n /** Only this session's events. */\n sessionId?: string\n /** Only events of this status. */\n status?: 'done' | 'error' | 'cancelled' | 'needs-attention'\n /** Only events after this `seq`. */\n since?: number\n /** Text in the title, summary, goal, detail or folder. */\n text?: string\n /** How many, newest first (default 20, at most 100). */\n limit?: number\n}\n\n/** The orchestration verbs acting as one extension (docs/ORCHESTRATION.md). */\nexport interface ExtensionSessionVerbs {\n /** Creates a session. Resolves to its id. */\n create: (params: ExtensionCreateSessionParams) => Promise<string>\n /** Other sessions, newest first. Default 30, at most 100. */\n list: (limit?: number) => Promise<readonly ExtensionSessionRow[]>\n /** A session's state and last message. */\n read: (sessionId: string) => Promise<ExtensionSessionDetail>\n /** Queues a prompt as the session's next turn. Resolves to `false` when the host declined it. */\n send: (sessionId: string, prompt: string) => Promise<boolean>\n /** Guidance into the current run, at its next turn boundary. */\n steer: (sessionId: string, message: string) => Promise<void>\n /** Interrupts the run. */\n cancel: (sessionId: string) => Promise<void>\n /** The last turns as plain text, oldest first. Default 10, at most 50. */\n transcript: (sessionId: string, limit?: number) => Promise<string>\n /** Returns once the session is idle or blocked, or after `timeoutSec`. Default 30, at most 50. */\n wait: (sessionId: string, timeoutSec?: number) => Promise<ExtensionWaitResult>\n /** The recent session events (runs ended, sessions blocked), newest first, without the pending request. */\n events: (query?: ExtensionEventQuery) => Promise<readonly ExtensionSessionEvent[]>\n /** Prompts waiting for an answer, of one session or all. */\n pending: (sessionId?: string) => Promise<readonly ExtensionPendingRequest[]>\n /** Answers a question or a plan by its request id. Resolves to `false` when it was already answered. */\n answer: (requestId: string, response: InteractionResponse) => Promise<boolean>\n /** Decides a tool approval by its request id. Resolves to `false` when it was already decided. */\n approve: (requestId: string, decision: ExtensionApprovalDecision) => Promise<boolean>\n}\n\n/**\n * The session lifecycle verbs of `ctx.sessions`. Optional:\n * a host that lacks one keeps type-checking, and the sessions domain rejects the\n * call with a clear error. Every verb acts as the extension the verbs were\n * made for.\n */\nexport interface ExtensionSessionLifecycleVerbs {\n /**\n * Sessions that match a query, as `ctx.sessions.list` answers. The query is\n * validated and its defaults filled (`limit`, `sort`, `archived`) before the\n * call. Rows carry the host's stored facet values. Without it, `list` reads\n * the orchestration `list` (its 100 newest sessions, fields `id`, `title`,\n * `cwd`, `projectName`, `status`, `updatedAt`, no facets, no archived\n * sessions) and filters it in the runtime; a query that needs more (another\n * field, a facet, archived sessions, a filter or sort over a full list, a\n * page cut short by the 100th row) rejects naming why. A page that ends\n * exactly at the 100th row is answered, with no cursor.\n */\n query?: (query: Required<Pick<SessionListQuery, 'limit' | 'sort' | 'archived'>> & Omit<SessionListQuery, 'limit' | 'sort' | 'archived'>) => Promise<SessionListPage>\n /** A session's live settings, or `undefined` for an unknown session. */\n get?: (sessionId: string) => Promise<SessionInfo | undefined>\n /** Deletes a session. Resolves to whether it did. */\n remove?: (sessionId: string) => Promise<boolean>\n /** Compacts a session's history now. Resolves to whether it did. */\n compact?: (sessionId: string) => Promise<boolean>\n /** Changes a session's model. Resolves to whether the host accepted it. */\n switchModel?: (sessionId: string, model: { providerId: string, modelId: string }) => Promise<boolean>\n /** Changes a session's agent profile. Resolves to whether the host accepted it. */\n switchAgent?: (sessionId: string, agentId: string) => Promise<boolean>\n /** Changes a session's thinking level. Resolves to whether the host accepted it. */\n setThinking?: (sessionId: string, level: ThinkingLevel) => Promise<boolean>\n /** Submits text to a session as if the user typed it (commands, interceptors, skills). Resolves to whether it was taken. */\n submit?: (sessionId: string, text: string, opts?: ExtensionPromptDelivery) => Promise<boolean>\n /** Adds a message the model sees on the next turn, without starting a run. */\n synthetic?: (sessionId: string, message: { role: 'user' | 'assistant', text: string }) => Promise<boolean>\n /** Adds display-only blocks to a session's transcript. Persisted, never sent to the model. */\n note?: (sessionId: string, blocks: readonly CommandOutputBlock[]) => Promise<boolean>\n}\n\n/** A session event (a run ended, or a session waits for an answer), as `ctx.sessions.onEvent` handlers get it. */\nexport interface ExtensionSessionEvent {\n /** The session it is about. */\n sessionId: string\n /** Its title at the time. */\n title: string\n /** `done`, `error`, `cancelled`, or `needs-attention` (a question, plan or tool approval waits). */\n status: 'done' | 'error' | 'cancelled' | 'needs-attention'\n /** One line: its last message, the failure, or what it waits for. */\n summary: string\n /** When, epoch ms. */\n at: number\n /** Its place in the event log: pass it as `since` to `ctx.sessions.events`. */\n seq?: number\n /** Created by the caller that reads it. */\n worker?: boolean\n /** Its folder; `''` for none. */\n cwd?: string\n /** The prompt that started the run. */\n goal?: string\n /** For `error`: the failure. */\n error?: string\n /** For `needs-attention`: what is asked, in one line. */\n detail?: string\n /** For `needs-attention`: the request, to answer with `ctx.sessions.answer` / `approve`. */\n request?: { id: string, kind: 'question' | 'plan' | 'approval', payload: unknown }\n /** The run ended abnormally: it hit the length limit, paused, or was filtered. */\n finishReason?: 'length' | 'pause' | 'content-filter'\n /** What the run touched. */\n artifacts?: { changed: readonly string[], commands: number, toolCalls: number }\n /** The run's duration, tokens, turns and cost, when known. */\n durationMs?: number\n /** Tokens the run used. */\n tokens?: number\n /** Turns the run took. */\n turns?: number\n /** Cost of the run in USD. */\n costUsd?: number\n}\n/** Handler registered with `ctx.sessions.onEvent`. */\nexport type ExtensionSessionEventHandler = (event: ExtensionSessionEvent) => void | Promise<void>\n\n/**\n * The live `(execution, handle)` pair behind `ctx.workspace`. Resolved\n * per call — never cached by the facade — because the pair changes on\n * session switch, cwd change, and registry rebuilds; a captured pair\n * would point at a destroyed container.\n */\nexport interface ExtensionWorkspacePair {\n /** Execution context the commands run in. */\n execution: ExecutionContext\n /** Handle to the live execution. */\n handle: ExecutionHandle\n}\n\n/**\n * `ctx.workspace`'s operations already bound to a session, for a host whose\n * execution lives in another process (the TUI in daemon mode reaches the\n * session's workspace over IPC). Same contract as the facade's methods.\n */\nexport type ExtensionWorkspaceOps = Omit<ExtensionWorkspaceSurface, 'available'>\n\n/**\n * What `ctx.artifacts` resolves queries against: the host's artifacts (its\n * session store, or a client's view of a host's) plus the active session's\n * identity, so `scope: 'session'` / `'project'` can be answered without the\n * extension knowing either id.\n */\nexport interface ExtensionArtifactScope {\n /** Store the artifacts are read from and written to. */\n store: Pick<SessionStore, 'listArtifacts' | 'upsertArtifact'>\n /** Active session id. Needed to answer `scope: 'session'` queries. */\n sessionId?: string\n /** Project root of the active session. Needed to answer `scope: 'project'` queries. */\n projectRoot?: string\n /** Active run id, when a run is in flight — stamped on `record`ed artifacts. */\n runId?: string\n /**\n * Host-owned write path for `ctx.artifacts.record`. Defaults to\n * `store.upsertArtifact`; hosts override to route through a daemon RPC or\n * to fan out a change signal after the write.\n */\n record?: (artifact: SessionArtifact) => Promise<SessionArtifact | null>\n}\n\n/** What a host attaches to power the runtime surfaces. */\nexport interface ExtensionHostRuntimeImpl {\n /** Returns the active model id, or `null` when none is selected. */\n model: () => string | null\n /**\n * Model catalog across every provider the user has credentials for.\n * Optional so pre-catalog host impls keep typechecking; the facade\n * treats absence as an empty catalog.\n */\n models?: () => readonly ExtensionModelEntry[]\n /** Returns the active thinking level, or `null` when none applies. */\n thinking: () => ThinkingLevel | null\n /** Sets the thinking level. Returns whether the host accepted it. */\n setThinking: (level: ThinkingLevel) => boolean\n /** Shows session `id` in this window (`ctx.ui.openSession`). Resolves to whether it did. */\n switchSession: (id: string) => Promise<boolean>\n /** Opens a new, empty session in this window (`ctx.ui.newSession`). Resolves to whether one was opened. */\n createSession: () => Promise<boolean>\n /** Appends output blocks to the active transcript. Returns whether the host accepted them. */\n appendNote: (blocks: readonly CommandOutputBlock[]) => boolean\n /**\n * Resolve the ACTIVE session's execution pair, spawning the handle if\n * no run has created it yet (`agent.ensureExecution()`). `null` when\n * no agent/session is live; REJECT when a live agent's spawn fails\n * (daemon down, spawn timeout) so the facade surfaces the real error\n * instead of a generic \"detached\". Optional so pre-workspace host\n * impls keep typechecking; the facade treats absence as detached.\n * A host whose execution lives in another process returns session-bound\n * {@link ExtensionWorkspaceOps} instead of a pair.\n */\n workspace?: () => Promise<ExtensionWorkspacePair | ExtensionWorkspaceOps | null>\n /**\n * Side-effect-free availability signal (\"is there a live agent?\").\n * MUST NOT spawn: `workspace()` may boot a container on first call,\n * and `ctx.workspace.available()` — a guard extensions call casually,\n * even at setup — must never pay that price to answer a boolean.\n * Optional; when absent the facade falls back to `workspace()` (with\n * its side effects — implement this on any host with heavy spawns).\n */\n workspaceAvailable?: () => boolean\n /**\n * Backing for `ctx.artifacts`. Optional so pre-artifact host impls keep\n * typechecking; the facade treats absence (or a store without artifact\n * methods) as an empty store.\n */\n artifacts?: () => ExtensionArtifactScope | null\n}\n\n/**\n * Host-level session control behind `ctx.sessions`: the orchestration verbs\n * and per-session extension state, addressing any session by id, inside a run\n * or not.\n */\nexport interface ExtensionSessionControl {\n /** The orchestration verbs acting as extension `extension`, with the lifecycle verbs the host implements. */\n verbs: (extension: string) => ExtensionSessionVerbs & ExtensionSessionLifecycleVerbs\n /** One value of `extension`'s per-session state (`ctx.session`), live or stored. */\n getData: (sessionId: string, extension: string, key: string) => Promise<JsonValue | undefined>\n /** Write one value of `extension`'s per-session state; `undefined` deletes it. */\n setData: (sessionId: string, extension: string, key: string, value: JsonValue | undefined) => Promise<void>\n /**\n * Starts computing a runtime's facets (`ctx.sessions.facets`): the\n * runtime calls it when an extension registers or refreshes a facet.\n * Idempotent. Optional: a host without it computes no facets.\n */\n attachFacets?: (registry: FacetRegistry) => void\n}\n\n/** Connects a host to the runtime surfaces extensions see as `ctx.runtime`, `ctx.sessions`, `ctx.workspace` and `ctx.artifacts`. */\nexport interface ExtensionHostRuntimeBridge {\n /**\n * Process-wide attachment — a single-session host (the TUI) attaches the\n * active session's impl once and swaps it on session change.\n */\n attach: (impl: ExtensionHostRuntimeImpl) => () => void\n /**\n * Async-scoped attachment — a multi-session host (daemon, GUI) runs a\n * command for session X inside `runWith(implForX, …)`; every\n * `ctx.runtime` / `ctx.sessions` / `ctx.workspace` call made anywhere in\n * that async tree resolves to X, even while another session's command\n * runs concurrently. Takes precedence over `attach` inside the scope.\n */\n runWith: <T>(impl: ExtensionHostRuntimeImpl, fn: () => Promise<T>) => Promise<T>\n /** Returns the implementation in effect: the innermost `runWith` scope, else the attached one, else `null`. */\n current: () => ExtensionHostRuntimeImpl | null\n /** Attach the chat host's session control (one per bridge; the newest wins). Returns a detach. */\n attachSessionControl: (control: ExtensionSessionControl) => () => void\n /** The attached session control, or `null`. */\n sessionControl: () => ExtensionSessionControl | null\n}\n\n/** Creates a bridge that hosts attach their runtime implementation to. */\nexport function createExtensionHostRuntimeBridge(): ExtensionHostRuntimeBridge {\n let impl: ExtensionHostRuntimeImpl | null = null\n let control: ExtensionSessionControl | null = null\n const scoped = new AsyncLocalStorage<ExtensionHostRuntimeImpl>()\n return {\n attachSessionControl(next) {\n control = next\n return () => {\n if (control === next)\n control = null\n }\n },\n sessionControl: () => control,\n attach(next) {\n impl = next\n return () => {\n if (impl === next)\n impl = null\n }\n },\n runWith: (next, fn) => scoped.run(next, fn),\n current: () => scoped.getStore() ?? impl,\n }\n}\n\n/** `ctx.runtime` — reads/controls over the host's active model state. */\nexport interface ExtensionRuntimeSurface {\n /** Active model id, or `null` when detached / none picked. */\n model: () => string | null\n /**\n * Every model available across the user's credentialed providers.\n * Empty when detached (headless, or before the renderer mounts).\n * Use it to build model pickers (e.g. a review command letting the\n * user pin subagents to specific models).\n */\n models: () => readonly ExtensionModelEntry[]\n /** Active thinking level, or `null` when detached / not applicable. */\n thinking: () => ThinkingLevel | null\n /** Set the thinking level. `false` when detached or unsupported by the model. */\n setThinking: (level: ThinkingLevel) => boolean\n}\n\n/**\n * `ctx.sessions` — the orchestration verbs, acting as this extension\n * (docs/ORCHESTRATION.md), plus this extension's state of any session. Every\n * verb rejects without a chat host (a TUI-only window), and when the call is\n * refused (an unknown session).\n */\nexport interface ExtensionSessionsSurface extends ExtensionSessionVerbs {\n /**\n * Hear every session event: a run ended (`done`, `error`) or a session waits\n * for an answer (`needs-attention`, with the request). Register during setup;\n * runs on the chat host (GUI and daemon), outside any run.\n */\n onEvent: (handler: ExtensionSessionEventHandler) => void\n /** This extension's per-session value `key` (`ctx.session`'s store) of any session, inside a run or not. `undefined` when unset. Rejects when detached. */\n getData: (sessionId: string, key: string) => Promise<JsonValue | undefined>\n /** Write this extension's per-session value `key` of any session; `undefined` deletes it. Rejects when detached. */\n setData: (sessionId: string, key: string, value: JsonValue | undefined) => Promise<void>\n}\n\n/** `ctx.ui` — what this window shows. Per window: a daemon or a server has none, and answers `false`. */\nexport interface ExtensionUiSurface {\n /** Show session `id` in this window. `false` when detached or it could not. */\n openSession: (id: string) => Promise<boolean>\n /** Open a new, empty session in this window. `false` when detached. */\n newSession: () => Promise<boolean>\n}\n\n/**\n * `ctx.workspace` — shell + file operations routed through the SESSION'S\n * execution context, so extension work happens wherever the agent's tools\n * run (host process, docker, remote sandbox) with the same transport\n * output caps and containment. The curated \"do work in the workspace\"\n * subset — lifecycle methods (`spawn` / `destroy` / background tasks)\n * are deliberately absent: the pair belongs to the agent.\n *\n * Unlike `ctx.runtime` / `ctx.sessions` (queries and toggles that degrade\n * to `null` / `false`), these are imperative operations whose silent\n * failure would corrupt caller logic — a no-op `writeFile` must not look\n * like success. Detached ⇒ every method REJECTS with a clear error.\n * Guard with {@link ExtensionWorkspaceSurface.available} or try/catch.\n */\nexport interface ExtensionWorkspaceSurface {\n /** `true` when a live session's execution pair is reachable. */\n available: () => Promise<boolean>\n /**\n * Run a shell command in the workspace. Resolves with the full\n * ExecResult (non-zero exits RESOLVE — inspect `exitCode`); rejects\n * only when detached or the transport itself fails. Output is\n * byte-capped by the context's transport (10MB default).\n */\n exec: (command: string, options?: { cwd?: string, env?: Record<string, string>, timeout?: number, signal?: AbortSignal }) => Promise<ExecResult>\n /** Read a file from the workspace's filesystem (whole-file — probe `fileSize` first for anything potentially large). */\n readFile: (path: string) => Promise<string>\n /** Write a file into the workspace's filesystem (parent dirs created). */\n writeFile: (path: string, content: string) => Promise<void>\n /** List a directory in the workspace — `ListFilesOptions` semantics (`glob: true` treats `path` as a pattern). */\n listFiles: (path: string, options?: ListFilesOptions) => Promise<ListFilesEntry[]>\n /** Byte size of a file, or `null` when unknowable — same contract as `ExecutionContext.fileSize`. */\n fileSize: (path: string) => Promise<number | null>\n}\n\n/**\n * Build the `ctx.artifacts` facade over a host-runtime bridge. Read-only;\n * every call re-resolves the scope (session switches swap it). Detached,\n * or a store without artifact support, answers `[]` — the same honest\n * degradation as `ctx.sessions`.\n *\n * @param resolve - Returns the current artifact scope, or `null`/`undefined` when detached. Called on every query.\n */\nexport function createArtifactsSurface(\n resolve: () => ExtensionArtifactScope | null | undefined,\n): ExtensionArtifactsSurface {\n return {\n list: async (query) => {\n const scope = resolve()\n if (!scope?.store.listArtifacts)\n return []\n const mode = query?.scope ?? 'session'\n const base = {\n ...(query?.kind !== undefined ? { kind: query.kind } : {}),\n ...(query?.since !== undefined ? { since: query.since } : {}),\n ...(query?.limit !== undefined ? { limit: query.limit } : {}),\n }\n if (mode === 'session') {\n if (!scope.sessionId)\n return []\n return scope.store.listArtifacts({ ...base, sessionId: scope.sessionId })\n }\n if (mode === 'project') {\n if (!scope.projectRoot)\n return []\n return scope.store.listArtifacts({ ...base, projectRoot: scope.projectRoot })\n }\n return scope.store.listArtifacts(base)\n },\n find: async (kind, uri) => {\n const scope = resolve()\n if (!scope?.store.listArtifacts)\n return []\n return scope.store.listArtifacts({ kind, uri })\n },\n record: async (input) => {\n const scope = resolve()\n if (!scope?.sessionId)\n return undefined\n const write = scope.record ?? scope.store.upsertArtifact?.bind(scope.store)\n if (!write)\n return undefined\n // Extension input is a trust boundary: same normalization the loop\n // applies to tool metadata (kind shape, bounds, meta size).\n const normalized = normalizeArtifactInput(input)\n if (!normalized)\n return undefined\n const now = Date.now()\n const projectRoot = normalized.projectRoot ?? scope.projectRoot\n try {\n const stored = await write({\n id: crypto.randomUUID(),\n sessionId: scope.sessionId,\n ...(scope.runId ? { runId: scope.runId } : {}),\n kind: normalized.kind,\n uri: normalized.uri,\n label: normalized.label,\n ...(projectRoot ? { projectRoot } : {}),\n ...(normalized.meta !== undefined ? { meta: normalized.meta } : {}),\n createdAt: now,\n updatedAt: now,\n })\n return stored ?? undefined\n }\n catch {\n return undefined\n }\n },\n }\n}\n\n/**\n * Build the `ctx.workspace` facade over a host-runtime bridge. Every call\n * re-resolves the live pair (see {@link ExtensionWorkspacePair}); detached\n * calls reject with a message naming the guard.\n *\n * `isAvailable` is the host's side-effect-free availability signal,\n * tri-state by design: `true`/`false` answer directly, `undefined` means\n * \"no light signal wired\" and falls back to `resolve()` — accepting its\n * side effects (a container spawn, on heavy hosts). Wire it wherever\n * spawning is non-trivial.\n *\n * @param resolve - Returns the live execution pair, or `null` when detached. Called on every operation.\n * @param isAvailable - Side-effect-free availability signal. When omitted, availability falls back to `resolve`.\n */\nexport function createWorkspaceSurface(\n resolve: () => Promise<ExtensionWorkspacePair | ExtensionWorkspaceOps | null> | ExtensionWorkspacePair | ExtensionWorkspaceOps | null,\n isAvailable?: () => boolean | undefined,\n): ExtensionWorkspaceSurface {\n const ops = async (): Promise<ExtensionWorkspaceOps> => {\n // Spawn/transport failures from `resolve` propagate as-is — a docker\n // daemon being down must read as that, not as \"detached\".\n const resolved = await resolve()\n if (!resolved)\n throw new Error('ctx.workspace is detached (no live session or host). Guard with `await ctx.workspace.available()`.')\n return 'execution' in resolved ? pairOps(resolved) : resolved\n }\n return {\n available: async () => {\n // Prefer the host's side-effect-free signal — `resolve()` may spawn\n // a container, which a boolean guard must never trigger.\n const light = isAvailable?.()\n if (light !== undefined)\n return light\n try {\n return await resolve() !== null\n }\n catch {\n return false\n }\n },\n exec: async (command, options) => (await ops()).exec(command, options),\n readFile: async path => (await ops()).readFile(path),\n writeFile: async (path, content) => (await ops()).writeFile(path, content),\n listFiles: async (path, options) => (await ops()).listFiles(path, options),\n fileSize: async path => (await ops()).fileSize(path),\n }\n}\n\n/** The workspace operations over an in-process execution pair. */\nfunction pairOps({ execution, handle }: ExtensionWorkspacePair): ExtensionWorkspaceOps {\n return {\n exec: (command, options) => execution.exec(handle, command, options),\n readFile: path => execution.readFile(handle, path),\n writeFile: (path, content) => execution.writeFile(handle, path, content),\n listFiles: (path, options) => execution.listFiles(handle, path, options),\n fileSize: async path => await execution.fileSize?.(handle, path) ?? null,\n }\n}\n","/**\n * Owners: groups of registrations with one lifetime (extension API).\n *\n * The extension's root owner lives until the extension unloads. `scope()`\n * makes a child that is disposed with its parent, or earlier on its own.\n *\n * Disposal has two phases. Withdraw: the owner refuses new registrations\n * and runs its `onCleanup` entries (registrations: nothing new routes to the\n * extension). Teardown: it aborts its signal and runs its `onTeardown`\n * entries (the domains in-flight work uses: storage, the setup cleanup).\n * Without a lease both phases run at once, signal first. A call in flight\n * holds a lease (`lease`): disposing then withdraws at once and defers the\n * teardown until every lease ends, at most until the longest lease's bound\n * (its own timeout, or `drainMs` for a call with none). Each cleanup starts\n * synchronously, so a hung async cleanup never blocks the ones after it;\n * `settled` resolves once all of them finished.\n */\n\nimport type { Cleanup, Disposable, Owner } from '../api/core'\nimport { DisposedError } from '../api/core'\n\n/** How long a disposed owner waits for a call without a bound of its own (a command run, a tool execute), in ms. */\nexport const DEFAULT_DRAIN_MS = 30 * 60_000\n\n/** What {@link OwnerOptions.onDrain} and {@link OwnerOptions.onDrainTimeout} are told. */\nexport interface DrainInfo {\n /** The owner. */\n label: string\n /** The calls still running, by label. */\n active: readonly string[]\n /** `onDrain`: how long the teardown waits at most. `onDrainTimeout`: how long it waited. */\n ms: number\n}\n\n/** Options for {@link createOwner}. */\nexport interface OwnerOptions {\n /**\n * Receives a cleanup that threw or rejected. The rest still run. Defaults\n * to the parent's handler; a root owner without one drops the error.\n */\n onError?: (error: unknown, label: string) => void\n /** Names the owner in errors (`DisposedError`, `onError` labels). Default `'owner'`. */\n label?: string\n /** Bound of a lease taken without a timeout, counted from dispose, in ms. Default {@link DEFAULT_DRAIN_MS}. */\n drainMs?: number\n /** Called once when dispose found calls in flight and deferred the teardown. */\n onDrain?: (info: DrainInfo) => void\n /** Called when the bound passed with calls still running; the teardown runs then. */\n onDrainTimeout?: (info: DrainInfo) => void\n}\n\n/** The runtime side of an {@link Owner}: child scopes, leases and awaitable disposal. */\nexport interface RuntimeOwner extends Owner {\n /** The owner this one is a child of. */\n readonly parent?: RuntimeOwner\n /** The name used in errors. */\n readonly label: string\n /** Resolves once `dispose` ran and every async cleanup settled (both phases). Pending until then. */\n readonly settled: Promise<void>\n /** Resolves once the withdraw phase's async cleanups settled. */\n readonly withdrawn: Promise<void>\n /** Disposed and waiting for its leases: registrations are withdrawn, the domains still work. */\n readonly draining: boolean\n /** The teardown ran: the domains refuse every call. */\n readonly tornDown: boolean\n /** A child owner, disposed with this one or earlier by itself. Throws {@link DisposedError} once this one is disposed. */\n scope: (label?: string) => RuntimeOwner\n /** Adds a cleanup to the teardown phase. Throws {@link DisposedError} once torn down. */\n onTeardown: (cleanup: Cleanup) => Disposable\n /**\n * Marks a call in flight until the returned release runs (calling it again\n * is a no-op). A dispose meanwhile defers the teardown.\n *\n * @param label - Names the call in errors and drain logs.\n * @param opts - The call's bound.\n * @param opts.timeoutMs - The call's own timeout; the teardown waits no longer for it.\n * @throws DisposedError naming `label` when the owner is disposed.\n */\n lease: (label: string, opts?: { timeoutMs?: number }) => () => void\n /** Disposes, then waits for every async cleanup. Same as `dispose()` followed by `await settled`. */\n disposeAsync: () => Promise<void>\n}\n\nconst ON_ERROR = Symbol('owner.onError')\n\ninterface Entry { run: Cleanup }\ninterface LeaseRecord { label: string, start: number, timeoutMs?: number }\ninterface InternalOwner extends RuntimeOwner { [ON_ERROR]?: OwnerOptions['onError'] }\n\n/**\n * Makes an owner.\n *\n * @param parent - The owner this one belongs to. The child is disposed with it, and inherits its `onError`.\n * @param options - Error handler, label and drain bound.\n * @returns A live owner.\n * @throws DisposedError when `parent` is already disposed.\n */\nexport function createOwner(parent?: RuntimeOwner, options: OwnerOptions = {}): RuntimeOwner {\n const label = options.label ?? (parent ? `${parent.label}/scope` : 'owner')\n const onError = options.onError ?? (parent ? (parent as InternalOwner)[ON_ERROR] : undefined)\n const drainMs = options.drainMs ?? DEFAULT_DRAIN_MS\n const controller = new AbortController()\n // Insertion-ordered; a withdrawn cleanup leaves the set, so disposal walks only live ones.\n const entries = new Set<Entry>()\n const teardowns = new Set<Entry>()\n const leases = new Set<LeaseRecord>()\n let disposed = false\n let torn = false\n let draining = false\n let drainTimer: ReturnType<typeof setTimeout> | undefined\n let unlink: (() => void) | undefined\n let unlinkTeardown: (() => void) | undefined\n let resolveSettled!: () => void\n const settled = new Promise<void>((resolve) => { resolveSettled = resolve })\n let resolveWithdrawn!: () => void\n const withdrawn = new Promise<void>((resolve) => { resolveWithdrawn = resolve })\n\n const report = (error: unknown, what: string): void => {\n try {\n onError?.(error, what)\n }\n catch {}\n }\n\n /** Runs `set`'s cleanups in reverse order; resolves once the async ones settled. */\n const runAll = (set: Set<Entry>): Promise<unknown> => {\n const pending: Promise<unknown>[] = []\n for (const entry of [...set].reverse()) {\n set.delete(entry)\n try {\n const result = entry.run()\n if (result && typeof (result as Promise<void>).then === 'function')\n pending.push(Promise.resolve(result).catch(error => report(error, `${label} cleanup`)))\n }\n catch (error) {\n report(error, `${label} cleanup`)\n }\n }\n return Promise.all(pending)\n }\n\n const add = (set: Set<Entry>, cleanup: Cleanup): Disposable => {\n const entry: Entry = { run: cleanup }\n set.add(entry)\n return { dispose: () => { set.delete(entry) } }\n }\n\n let withdrawDone: Promise<unknown> = Promise.resolve()\n\n const finalize = (): void => {\n if (torn)\n return\n torn = true\n draining = false\n clearTimeout(drainTimer)\n leases.clear()\n unlinkTeardown?.()\n if (!controller.signal.aborted)\n controller.abort(new DisposedError(label))\n void Promise.all([withdrawDone, runAll(teardowns)]).then(() => resolveSettled())\n }\n\n const activeLabels = (): string[] => [...leases].map(l => l.label)\n\n const self: InternalOwner = {\n label,\n parent,\n signal: controller.signal,\n settled,\n withdrawn,\n get disposed() { return disposed },\n get draining() { return draining },\n get tornDown() { return torn },\n [ON_ERROR]: onError,\n\n onCleanup(cleanup: Cleanup): Disposable {\n if (disposed)\n throw new DisposedError(`${label}.onCleanup`)\n return add(entries, cleanup)\n },\n\n onTeardown(cleanup: Cleanup): Disposable {\n if (torn)\n throw new DisposedError(`${label}.onCleanup`)\n return add(teardowns, cleanup)\n },\n\n scope(childLabel?: string): RuntimeOwner {\n if (disposed)\n throw new DisposedError(`${label}.scope`)\n return createOwner(self, childLabel ? { label: childLabel } : {})\n },\n\n lease(what: string, opts: { timeoutMs?: number } = {}): () => void {\n if (disposed)\n throw new DisposedError(what)\n const record: LeaseRecord = { label: what, start: Date.now(), ...(opts.timeoutMs !== undefined ? { timeoutMs: opts.timeoutMs } : {}) }\n leases.add(record)\n return () => {\n if (!leases.delete(record))\n return\n if (draining && leases.size === 0)\n finalize()\n }\n },\n\n dispose(): void {\n if (disposed)\n return\n disposed = true\n // Withdrawn by a draining parent: the parent's teardown finishes this one too.\n const parentDrains = parent?.disposed === true && parent.draining\n unlink?.()\n if (!parentDrains)\n unlinkTeardown?.()\n const defer = leases.size > 0 || parentDrains\n if (!defer)\n controller.abort(new DisposedError(label))\n draining = defer\n withdrawDone = runAll(entries)\n void withdrawDone.then(() => resolveWithdrawn())\n if (!defer) {\n finalize()\n return\n }\n if (leases.size === 0)\n return\n const now = Date.now()\n const deadline = Math.max(...[...leases].map(l => l.timeoutMs !== undefined && Number.isFinite(l.timeoutMs) ? l.start + l.timeoutMs : now + drainMs))\n const ms = Math.max(0, deadline - now)\n try {\n options.onDrain?.({ label, active: activeLabels(), ms })\n }\n catch {}\n drainTimer = setTimeout(() => {\n if (torn)\n return\n try {\n options.onDrainTimeout?.({ label, active: activeLabels(), ms: Date.now() - now })\n }\n catch {}\n finalize()\n }, ms)\n drainTimer.unref?.()\n },\n\n async disposeAsync(): Promise<void> {\n self.dispose()\n await settled\n },\n }\n\n if (parent) {\n // The parent disposes the child (and waits for it); the child leaves the parent when it goes first.\n unlink = parent.onCleanup(() => {\n self.dispose()\n return torn ? settled : withdrawn\n }).dispose\n unlinkTeardown = parent.onTeardown(() => {\n finalize()\n return settled\n }).dispose\n }\n return self\n}\n\n/**\n * Ties `disposable` to `owner`: it is disposed when the owner is. The\n * returned Disposable disposes it early and drops it from the owner. Calling\n * it twice is a no-op. Works with any {@link Owner}, so domains can use it on\n * `DomainDeps.owner`.\n *\n * @param owner - The owner the registration belongs to.\n * @param disposable - The registration to withdraw with it.\n * @returns A Disposable for the registration.\n * @throws DisposedError when `owner` is disposed; `disposable` is disposed first so nothing leaks.\n */\nexport function track(owner: Owner, disposable: Disposable): Disposable {\n if (owner.disposed) {\n disposable.dispose()\n throw new DisposedError('register')\n }\n let done = false\n const once = (): void => {\n if (done)\n return\n done = true\n disposable.dispose()\n }\n const link = owner.onCleanup(once)\n return {\n dispose: () => {\n link.dispose()\n once()\n },\n }\n}\n\n/**\n * Throws when `owner` is disposed. Domains call it before a registration\n * creates any effect.\n *\n * @param owner - The owner to check.\n * @param what - The call being made, for the error message (e.g. `'tools.register'`).\n * @throws DisposedError when `owner` is disposed.\n */\nexport function assertAlive(owner: Owner, what: string): void {\n if (owner.disposed)\n throw new DisposedError(what)\n}\n\n/**\n * Whether `owner`'s domains refuse calls: torn down, or for an owner without\n * a teardown phase, disposed. A draining owner still serves its in-flight work.\n *\n * @param owner - The owner to check.\n */\nexport function isTornDown(owner: Owner): boolean {\n const tornDown = (owner as Partial<RuntimeOwner>).tornDown\n return typeof tornDown === 'boolean' ? tornDown : owner.disposed\n}\n\n/**\n * Throws when `owner` is torn down. Domains that in-flight work uses\n * (storage, sessions, generate, workspace) check this instead of\n * {@link assertAlive}, so a call that started before dispose finishes.\n *\n * @param owner - The owner to check.\n * @param what - The call being made, for the error message.\n * @throws DisposedError when `owner` is torn down.\n */\nexport function assertUsable(owner: Owner, what: string): void {\n if (isTornDown(owner))\n throw new DisposedError(what)\n}\n\n/**\n * Adds `cleanup` to `owner`'s teardown phase (`onCleanup` for an owner\n * without one): it runs once the in-flight calls ended.\n *\n * @param owner - The owner.\n * @param cleanup - What to run at teardown.\n */\nexport function onTeardown(owner: Owner, cleanup: Cleanup): Disposable {\n const runtime = owner as Partial<RuntimeOwner>\n return typeof runtime.onTeardown === 'function' ? runtime.onTeardown(cleanup) : owner.onCleanup(cleanup)\n}\n","/**\n * Extension API: UI. Contributions are data the hosts draw natively; any\n * of them may also name a component from the extension's `ui` / `tui`\n * entry. `ctx.add(Token, item)` returns a {@link Handle}.\n */\n\nimport type { CompletionProvider } from '../../chat/completion'\nimport type { ContextBreakdownContributor } from '../../chat/context-breakdown'\nimport type { InlineAutocompleteProvider } from '../../chat/inline-autocomplete'\nimport type { PlanPayload, PlanResponse, QuestionPayload, QuestionResponse } from '../../chat/interactions'\nimport type { FacetPath, SessionGroupBy, SessionQuery, SessionSort } from '../../chat/session-query'\nimport type { Theme } from '../../chat/theme'\nimport type { ThinkingLevel } from '../../thinking-levels'\nimport type { ExtensionBadgeActions } from '../badge-actions'\nimport type { ExtensionPanel, PanelFocus } from '../panels'\nimport type { ExtensionBadgeColor, ExtensionBadgeIcon, ExtensionBadgeTone, ExtensionContextPanelSection, ExtensionReferenceProvider } from '../types'\nimport type { Bindable, ComponentRef, Disposable, Handle } from './core'\nimport type { SettingsSchema } from './settings'\n\nexport { escapeTemplate } from '../../chat/session-query'\n\n/** A token naming a kind of UI contribution. */\nexport interface UiToken<T, K extends string = string> {\n /** Always `'ui'`. */\n readonly kind: 'ui'\n /** The contribution kind, e.g. `'panel'`. */\n readonly name: K\n /** Type-level only. */\n readonly __type?: T\n}\n\nfunction token<T, K extends string>(name: K): UiToken<T, K> {\n return { kind: 'ui', name }\n}\n\n/** A side or home panel: an {@link ExtensionPanel} (load, subscribe, onAction, controls, focus), plus an optional component. */\nexport type PanelItem = ExtensionPanel & { component?: ComponentRef }\n\n/**\n * Named places every app knows. An app without the place ignores the item.\n *\n * The sidebar has three:\n *\n * - `'sidebar.top'`: full-width block rows pinned under the sidebar's search\n * row, above the session list. Desktop and web: between the search well and\n * the list. Terminal: on the sessions screen, between the search box and\n * the list.\n * - `'sidebar.bottom'`: full-width block rows pinned under the session list,\n * above the footer strip. Terminal: right under the sessions list.\n * - `'sidebar.footer'`: compact chips inside the footer strip itself, next to\n * the app's status (terminal: a line under the sessions list).\n *\n * `'sidebar.top'` and `'sidebar.bottom'` never scroll with the list. Each row\n * draws the item's icon (or loader), text, count, tone and highlight, or its\n * component. Each block takes at most part of the sidebar's height (desktop\n * and web: 30%; it scrolls on its own past that), so the list keeps the rest.\n * An empty block draws nothing.\n */\nexport type SlotName\n = | 'app.statusbar'\n | 'app.titlebar'\n | 'session.header'\n | 'composer.above'\n | 'composer.below'\n | 'composer.badges'\n | 'sidebar.top'\n | 'sidebar.bottom'\n | 'sidebar.footer'\n | 'transcript.turn-end'\n | 'home.block'\n | 'settings.section'\n\n/** A small item placed in a slot: a status line, a banner, a composer badge. */\nexport interface SlotItem {\n /** The slot that draws the item. */\n at: SlotName\n /** Limits the item to one session. A session's items go when it is deleted. */\n sessionId?: string\n /**\n * `transcript.turn-end` only: the item draws right after the turn with\n * this id (pair it with `sessionId`). Without it the item draws once, at\n * the end of the transcript. A host whose transcript holds no turn with\n * this id does not draw the item. Other slots refuse it.\n */\n turnId?: string\n /** Main text of the item. */\n text?: Bindable<string>\n /** Lines of a banner (`composer.above`). */\n lines?: Bindable<readonly string[]>\n /** A number or short label shown with the item. */\n count?: Bindable<number | string>\n /** Icon drawn with the item. */\n icon?: ExtensionBadgeIcon\n /** Tone of the item. */\n tone?: Bindable<ExtensionBadgeTone>\n /** Accent color of the item. */\n color?: ExtensionBadgeColor\n /** A running arc in place of the icon. */\n loader?: Bindable<boolean>\n /** Raised and breathing: something waits on the user. */\n highlight?: Bindable<boolean>\n /** Hover text. */\n title?: Bindable<string>\n /** A click opens this panel (`<id>`, `<extension>/<id>`, or a built-in tab). */\n panel?: string\n /** A click runs this command. */\n command?: string\n /** Lower first. Default 100. */\n order?: number\n /** Withdraws the item after this many ms. */\n timeoutMs?: number\n /** Drawn instead of the data where the host has it. */\n component?: ComponentRef\n}\n\n/** A full-screen view, or a modal when `presentation` is `'modal'`. */\nexport interface ScreenItem {\n /** Screen id, unique in the extension. Other extensions use `<extension>/<id>`. */\n id: string\n /** Title of the screen. */\n title: Bindable<string>\n /** `'screen'` fills the window, `'modal'` opens a dialog. */\n presentation?: 'screen' | 'modal'\n /** Required: hosts without the component draw `fallback`. */\n component: ComponentRef\n /** Markdown drawn where the component is missing. */\n fallback?: string\n}\n\n/** What a renderer draws: a custom block id, a code-block language, a tool's result, or an artifact kind's detail. */\nexport type RendererTarget = { block: string } | { language: string } | { tool: string | readonly string[] } | { artifact: string }\n\n/** A renderer: a component per host, with a markdown fallback. */\nexport interface RendererItem {\n /** What the renderer draws. */\n for: RendererTarget\n /** The component that draws it. */\n component: ComponentRef\n /** `true`: the component returns null to let the next renderer (or the default) draw. */\n fallthrough?: boolean\n}\n\n/** A page in Settings under the extension. Data from a settings-like schema, or a component. */\nexport interface SettingsPageItem {\n /** Page id, unique in the extension. */\n id: string\n /** Title of the page. */\n title: Bindable<string>\n /** Icon in the settings sidebar. */\n icon?: { gui?: string, tui?: string }\n /** Place among the extension's pages: after the definition's pages, lower first. Default 100. */\n order?: number\n /** Settings the host draws as a form. */\n schema?: SettingsSchema\n /** Component the page draws. */\n component?: ComponentRef\n}\n\n/** A web page shown in a panel or a screen, sandboxed. It talks to the extension through RPC only. */\nexport interface WebviewItem {\n /** Webview id, unique in the extension. */\n id: string\n /** Title of the panel or screen. */\n title: Bindable<string>\n /** A URL, or a file in the extension folder. */\n src: { url: string } | { file: string }\n /** Shows the page in a panel or a full screen. */\n placement: 'panel' | 'screen'\n /** RPC contract ids the page may call through the injected bridge. */\n rpc?: readonly string[]\n}\n\n/** A native menu entry (desktop). It runs a command. */\nexport interface MenuItem {\n /** The menu that holds the entry. */\n menu: 'app' | 'session' | 'tray'\n /** Text of the entry. */\n label: Bindable<string>\n /** Id of the command it runs. */\n command: string\n /** Keyboard shortcut, as an Electron accelerator string. */\n accelerator?: string\n /** Greys the entry out when `false`. Default `true`. */\n enabled?: Bindable<boolean>\n}\n\n/** A section of the context breakdown or the context panel. */\nexport type ContextSectionItem\n = | { placement: 'breakdown', contributor: ContextBreakdownContributor }\n | { placement: 'panel', section: ExtensionContextPanelSection }\n\n/** What a session started from a space runs with. Each field left out takes the app's default. */\nexport interface SpaceNewSession {\n /** Agent profile id. */\n agentId?: string\n /** Provider registry key, with `modelId`. */\n providerKey?: string\n /** Model id. */\n modelId?: string\n /** Thinking effort. */\n effort?: ThinkingLevel\n}\n\n/**\n * A space: a named view of sessions, listed in the sidebar beside the\n * built-in spaces. Its published id is `<extension>/<id>`.\n *\n * The Bindable rule of every sidebar token (spaces, filters, sorts, groups,\n * decorations, rows): a field is Bindable when it is data that follows the\n * extension's state (names, labels, queries, sorts, groupings, new-session\n * defaults, row state, decoration content). Ids, `kind`, placement (`space`,\n * `spaces`, `group`, `order`, `items`), actions, `open` and components stay\n * fixed: change them with `handle.update`. A Bindable is read whole: bind\n * the list (`options`, `chips`) to change one of its elements.\n */\nexport interface SpaceItem {\n /** Space id, unique in the extension. `default` is the built-in space's and is refused. */\n id: string\n /** Name shown for the space. */\n name: Bindable<string>\n /** Icon drawn with the name. */\n icon?: ExtensionBadgeIcon\n /**\n * Which sessions the space lists, besides the others: a session is in it\n * when it is tagged with the space (started from it, or moved to it),\n * when it is the orchestration Main session, or when it matches this query.\n */\n query: Bindable<SessionQuery>\n /** How the space groups its sessions until the user picks a grouping. Absent: one flat list. */\n groupBy?: Bindable<SessionGroupBy>\n /** How the space sorts its sessions until the user picks a sort. Absent: the app's order. */\n sortBy?: Bindable<readonly SessionSort[]>\n /** What a session started from the space runs with. */\n newSession?: Bindable<SpaceNewSession>\n /** Whether {@link SidebarRowItem}s (any extension's, this one's included) may list in the space. Default `false`. */\n items?: boolean\n /** Lower first among extension spaces. Default 100. */\n order?: number\n}\n\n/** One choice of a `select` or `multi` sidebar filter. Bind the filter's `options` to change its labels or queries. */\nexport interface SidebarFilterOption {\n /** Option id, unique in the filter. */\n id: string\n /** Text of the option. */\n label: string\n /** The sessions the option keeps. */\n query: SessionQuery\n}\n\n/**\n * A filter the user turns on in the sidebar. `toggle` keeps the sessions\n * that match `query` while on; `select` keeps those of the one option\n * picked; `multi` keeps those that match any picked option. Bindable\n * fields follow the sidebar rule ({@link SpaceItem}).\n */\nexport interface SidebarFilterItem {\n /** Filter id, unique in the extension. */\n id: string\n /** Text of the filter. */\n label: Bindable<string>\n /** Icon drawn with the label. */\n icon?: ExtensionBadgeIcon\n /** How the user picks: on or off, one option, or several. */\n kind: 'toggle' | 'select' | 'multi'\n /** `select` and `multi`: the options, 1 to 32. */\n options?: Bindable<readonly SidebarFilterOption[]>\n /** `toggle`: the sessions kept while it is on. */\n query?: Bindable<SessionQuery>\n /** Spaces it is offered in: `'all'` (default), or space ids (`default`, own ids, `<extension>/<id>`). */\n spaces?: 'all' | readonly string[]\n}\n\n/** A sort order the user can pick for the sidebar. Bindable fields follow the sidebar rule ({@link SpaceItem}). */\nexport interface SidebarSortItem {\n /** Sort id, unique in the extension. */\n id: string\n /** Text of the choice. */\n label: Bindable<string>\n /** The sort keys, most significant first (1 to 8). */\n sortBy: Bindable<readonly SessionSort[]>\n}\n\n/** A grouping the user can pick for the sidebar. Bindable fields follow the sidebar rule ({@link SpaceItem}). */\nexport interface SidebarGroupItem {\n /** Grouping id, unique in the extension. */\n id: string\n /** Text of the choice. */\n label: Bindable<string>\n /** The field or facet grouped on, with group labels and order. */\n groupBy: Bindable<SessionGroupBy>\n}\n\n/**\n * A plain string drawn as given (blank or whitespace-only: no text), or\n * `{ template }` with field paths in braces: `'{facet.git.branch} · {modelId}'`.\n */\nexport type SidebarText = string | { template: string }\n\n/**\n * A chip a decoration adds to a session row: literal `text` (blank or\n * whitespace-only: no chip), a `template` (field paths in braces, `{{` and\n * `}}` for a brace; see `escapeTemplate`), or one chip per value of a\n * `facet`.\n */\nexport type SidebarChip\n = | { text: string, tone?: ExtensionBadgeTone, icon?: ExtensionBadgeIcon }\n | { template: string, tone?: ExtensionBadgeTone, icon?: ExtensionBadgeIcon }\n | { facet: FacetPath, tone?: ExtensionBadgeTone, icon?: ExtensionBadgeIcon }\n\n/**\n * Extra data on the sidebar rows of the sessions that match `where`: an\n * icon, a tone, a subtitle, chips, or a component. Only `{ template }`\n * values are read as templates; a plain string is drawn as given. Bindable\n * fields follow the sidebar rule ({@link SpaceItem}).\n */\nexport interface SidebarDecorationItem {\n /** Decoration id, unique in the extension. */\n id: string\n /** The sessions it applies to. Absent: every session. */\n where?: Bindable<SessionQuery>\n /** Icon drawn on the row. */\n icon?: Bindable<ExtensionBadgeIcon>\n /** Tint of the row's icon and chips. */\n tone?: Bindable<ExtensionBadgeTone>\n /** Text drawn under the title: as given, or `{ template }`. */\n subtitle?: Bindable<SidebarText>\n /** Chips drawn on the row, at most 8. */\n chips?: Bindable<readonly SidebarChip[]>\n /** Drawn on the row where the host has it, with `{ sessionId }` added to its props. */\n component?: ComponentRef\n}\n\n/** Run state an extension row shows, like a session's. */\nexport type SidebarRowStatus = 'idle' | 'running' | 'blocked' | 'completed' | 'error'\n\n/** A small label on an extension row. */\nexport interface SidebarBadge {\n /** Badge text. */\n text: string\n /** Tint of the badge. */\n tone?: ExtensionBadgeTone\n /** Icon drawn with the text. */\n icon?: ExtensionBadgeIcon\n}\n\n/** An action in an extension row's menu. */\nexport interface SidebarRowAction {\n /** Action id, unique in the row. */\n id: string\n /** Text of the action. */\n label: string\n /**\n * The command it runs: this extension's own command by that id when it has\n * one (`ack` runs `<extension>.ack`), else the id as written (another\n * extension's `<extension>.<id>`, or a built-in). Its argument is the row's\n * id as the extension gave it (`ticket-1`, not `<extension>/ticket-1`).\n * Without one the host draws it disabled.\n */\n command?: string\n}\n\n/**\n * What opening an extension row does. `command` resolves and gets its\n * argument as a {@link SidebarRowAction}'s does. `panel` and `screen` name\n * this extension's own panel or screen by that id when it has one, else the\n * id as written (`<extension>/<id>`, or a built-in panel such as `todos`).\n */\nexport type SidebarRowOpen = { command: string } | { panel: string } | { screen: string } | { session: string }\n\n/**\n * A row an extension adds to a space's list beside its sessions: a ticket, a\n * job, a pull request. It lists only in a space that allows items. `time`\n * sorts it as a session's `updatedAt`. Bindable fields follow the sidebar\n * rule ({@link SpaceItem}).\n */\nexport interface SidebarRowItem {\n /** Row id, unique in the extension. */\n id: string\n /** The space it lists in: `default`, an own space id, or `<extension>/<id>`. */\n space: string\n /** The group (a group key of the space's grouping) it lists in. Absent: the group of rows without a value. */\n group?: string\n /** Row title. Blank or whitespace-only: the row's `id` stands in. */\n title: Bindable<string>\n /** Text under the title. Blank or whitespace-only: none. */\n subtitle?: Bindable<string>\n /** Icon drawn on the row. */\n icon?: Bindable<ExtensionBadgeIcon>\n /** Tint of the row. */\n tone?: Bindable<ExtensionBadgeTone>\n /** Run state drawn as a session's. */\n status?: Bindable<SidebarRowStatus>\n /** Sorts as a session's `updatedAt`, epoch ms. */\n time?: Bindable<number>\n /** Labels drawn on the row, at most 8. */\n badges?: Bindable<readonly SidebarBadge[]>\n /** Actions in the row's menu, at most 8. */\n actions?: readonly SidebarRowAction[]\n /** What a click does. Absent: nothing. */\n open?: SidebarRowOpen\n /** Sessions listed under the row, as its children. */\n children?: Bindable<SessionQuery>\n}\n\n/**\n * Opens links the extension understands, before the app's own behavior.\n * Every link the apps open goes through it: transcript links, file and\n * reference chips, panel rows, badge menus, terminal links. Holding Alt\n * opens a link the default way.\n */\nexport interface LinkHandlerItem {\n /** Handler id, unique in the extension. */\n id: string\n /** A URL prefix, a pattern, or a test. Runs where the extension runs. */\n match: string | RegExp | ((url: string) => boolean)\n /** Opens the link. Return `false` to let the next handler (or the app) open it. */\n open: (url: string, ctx: { sessionId?: string, source: LinkSource }) => void | boolean | Promise<void | boolean>\n /** Higher first among extensions. Default 0. */\n priority?: number\n}\n\n/** Where a link was clicked. */\nexport type LinkSource = 'transcript' | 'chip' | 'panel' | 'badge' | 'terminal' | 'other'\n\n/** Every UI token. */\nexport const Panel = token<PanelItem, 'panel'>('panel')\n/** A small item in a named slot. */\nexport const Slot = token<SlotItem, 'slot'>('slot')\n/** A full-screen view or modal. */\nexport const Screen = token<ScreenItem, 'screen'>('screen')\n/** A renderer for blocks, code languages, tools or artifacts. */\nexport const Renderer = token<RendererItem, 'renderer'>('renderer')\n/** A Settings page. */\nexport const SettingsPage = token<SettingsPageItem, 'settings-page'>('settings-page')\n/** A webview panel or screen. */\nexport const Webview = token<WebviewItem, 'webview'>('webview')\n/** A native menu entry. */\nexport const Menu = token<MenuItem, 'menu'>('menu')\n/** A color theme. */\nexport const ThemeToken = token<Theme, 'theme'>('theme')\n/** Inline reference chips (ticket ids, URLs). */\nexport const Reference = token<ExtensionReferenceProvider, 'reference'>('reference')\n/** Context-menu actions on badges, links, files and artifacts. */\nexport const BadgeAction = token<ExtensionBadgeActions, 'badge-action'>('badge-action')\n/** Opens matching links. */\nexport const LinkHandler = token<LinkHandlerItem, 'link-handler'>('link-handler')\n/** A context breakdown or context panel section. */\nexport const ContextSection = token<ContextSectionItem, 'context-section'>('context-section')\n/** A space: a named, query-defined view of sessions in the sidebar. */\nexport const Space = token<SpaceItem, 'space'>('space')\n/** A filter the user turns on in the sidebar. */\nexport const SidebarFilter = token<SidebarFilterItem, 'sidebar-filter'>('sidebar-filter')\n/** A sort order the user can pick in the sidebar. */\nexport const SidebarSort = token<SidebarSortItem, 'sidebar-sort'>('sidebar-sort')\n/** A grouping the user can pick in the sidebar. */\nexport const SidebarGroup = token<SidebarGroupItem, 'sidebar-group'>('sidebar-group')\n/** Extra data on the sidebar rows of matching sessions. */\nexport const SidebarDecoration = token<SidebarDecorationItem, 'sidebar-decoration'>('sidebar-decoration')\n/** A row an extension adds to a space, beside its sessions. */\nexport const SidebarRow = token<SidebarRowItem, 'sidebar-row'>('sidebar-row')\n\n/** Thrown by a dialog when no client can show it. */\nexport class NoUiError extends Error {\n /** @param what - The dialog that could not be shown. */\n constructor(what: string) {\n super(`${what}: no client can show it`)\n this.name = 'NoUiError'\n }\n}\n\n/** Thrown by a dialog that got no answer within its `timeoutMs`. */\nexport class DialogTimeoutError extends Error {\n /**\n * @param what - The dialog that timed out.\n * @param timeoutMs - The time it waited.\n */\n constructor(what: string, readonly timeoutMs: number) {\n super(`${what}: no answer within ${timeoutMs} ms`)\n this.name = 'DialogTimeoutError'\n }\n}\n\n/** Options every dialog takes. */\nexport interface DialogOptions {\n /** Routes to the client viewing this session. Without it: the last active client. */\n sessionId?: string\n /** Rejects with a timeout after this many ms. */\n timeoutMs?: number\n /** Cancels the dialog when it aborts. */\n signal?: AbortSignal\n}\n\n/** One option of `select`. */\nexport interface SelectOption {\n /** Value returned in `ids` when picked. */\n id: string\n /** Text of the option. */\n label: string\n /** Text under the label. */\n description?: string\n /** Heading the option is listed under. */\n group?: string\n /** Icon drawn with the option. */\n icon?: ExtensionBadgeIcon\n}\n\n/**\n * `ctx.ui`. Dialogs (`confirm`, `prompt`, `select`, `form`, `askUser`,\n * `presentPlan`) reject with {@link NoUiError} at once when no client can\n * show them. `toast` and `notify` wait for a client instead: up to 20 of\n * them, each for 60 s, delivered in order to the first client that attaches.\n */\nexport interface UiDomain {\n /** Asks a yes or no question. Resolves `true` when the user confirms. */\n confirm: (opts: DialogOptions & { title: string, message?: string, confirmLabel?: string, danger?: boolean }) => Promise<boolean>\n /** Asks for a line of text. Resolves `undefined` when the user cancels. */\n prompt: (opts: DialogOptions & { title: string, message?: string, placeholder?: string, initial?: string, secret?: boolean }) => Promise<string | undefined>\n /** Asks for one or more options. Resolves the picked ids and the clicked action, or `undefined` when the user cancels. */\n select: (opts: DialogOptions & { title: string, options: readonly SelectOption[], multi?: boolean, placeholder?: string, actions?: readonly { id: string, label: string }[] }) => Promise<{ ids: readonly string[], action?: string } | undefined>\n /** Asks for the values of a settings schema. Resolves the values, or `undefined` when the user cancels. */\n form: <S extends SettingsSchema>(opts: DialogOptions & { title: string, schema: S, values?: Readonly<Record<string, unknown>> }) => Promise<Readonly<Record<string, unknown>> | undefined>\n /** Asks the user the questions of `payload`. */\n askUser: (payload: QuestionPayload, opts?: DialogOptions) => Promise<QuestionResponse>\n /** Shows a plan and waits for the user's answer. */\n presentPlan: (payload: PlanPayload, opts?: DialogOptions) => Promise<PlanResponse>\n /**\n * A toast. Resolves with the action the user clicked, or `undefined`\n * (dismissed, timed out, or dropped before any client attached).\n * `timeoutMs` counts from when it is shown.\n */\n toast: (opts: { text: string, tone?: 'info' | 'success' | 'warn' | 'error', actions?: readonly { id: string, label: string }[], timeoutMs?: number, sessionId?: string }) => Promise<string | undefined>\n /** An OS notification on the client that shows it, skipped while the app has focus. Waits for a client like `toast`. */\n notify: (opts: { title: string, body?: string, sound?: boolean, sessionId?: string }) => void\n /** Opens, closes and toggles panels in a client. Each resolves whether the client did it. */\n panel: {\n open: (id: string, opts?: { sessionId?: string, focus?: PanelFocus }) => Promise<boolean>\n close: (id: string, opts?: { sessionId?: string }) => Promise<boolean>\n toggle: (id: string, opts?: { sessionId?: string }) => Promise<boolean>\n /** Panels open in the client viewing `sessionId`. */\n state: (opts?: { sessionId?: string }) => Promise<readonly string[]>\n }\n /** Shows a screen, a session, or a new session. */\n navigate: (to: { screen: string } | { session: string } | { newSession: true }, opts?: DialogOptions) => Promise<boolean>\n}\n\n/** `ctx.composer`. */\nexport interface ComposerDomain {\n /** Inserts text into the composer. Resolves whether a client did it. */\n insert: (text: string, opts?: { sessionId?: string }) => Promise<boolean>\n /** Replaces the composer text. Resolves whether a client did it. */\n setText: (text: string, opts?: { sessionId?: string }) => Promise<boolean>\n /** Attaches files, by path or as bytes with a name and MIME type. Resolves whether a client did it. */\n attach: (files: readonly { path: string }[] | readonly { name: string, mimeType: string, data: Uint8Array }[], opts?: { sessionId?: string }) => Promise<boolean>\n /** Registers a source of composer completions. */\n completions: { register: (provider: CompletionProvider) => Disposable }\n /** Registers a source of inline ghost-text suggestions. */\n autocomplete: { register: (provider: InlineAutocompleteProvider) => Disposable }\n}\n\n/** `ctx.desktop`: present only in the desktop app's main process. */\nexport interface DesktopDomain {\n /** The `electron` module. Type it yourself: `ctx.desktop.electron<typeof import('electron')>()`. */\n electron: <T = unknown>() => T\n /** The open windows and their events. */\n windows: {\n list: () => readonly { id: number, focused: boolean }[]\n on: (event: 'open' | 'close' | 'focus', listener: (window: { id: number }) => void) => Disposable\n }\n}\n\n/** The `add` signature: a token and its item. */\nexport type AddFn = <T>(token: UiToken<T>, item: T) => Handle<T>\n","/**\n * Settings schemas in UI items and form dialogs. The wire format and the\n * value checks are the settings domain's (`src/extensions/settings`): a\n * `ctx.ui.form` and a settings page draw with the same renderer as the\n * extension's own settings.\n */\n\nimport type { SettingsSchema } from '../api/settings'\nimport type { StoredSettingValue, ValidateRunner, WireSettings } from '../settings'\nimport type { UiRegistry } from './registry'\nimport { checkSettingValue, isValueSetting, normalizeSettingValue, settingsForDefinition, toWireSettings, withSettingsPages } from '../settings'\n\n/**\n * The schema with malformed sections and items removed (the settings\n * domain's cleaning). Never calls author code.\n *\n * @param extensionId - The extension the schema belongs to.\n * @param schema - The schema as the extension wrote it.\n */\nexport function cleanSettingsSchema(extensionId: string, schema: SettingsSchema): SettingsSchema {\n return settingsForDefinition({ id: extensionId, settings: schema }).schema\n}\n\n/** What {@link checkSettingsValues} found. */\nexport interface SettingsCheck {\n /** The values of the schema's keys that passed, normalized. Unknown keys are dropped. */\n values: Record<string, StoredSettingValue>\n /** An error message per key that failed. */\n errors: Record<string, string>\n}\n\n/**\n * Checks values a client sent back (or an extension passed as initial\n * values) against `schema`, with the settings domain's rules. Missing keys\n * are left out; action settings carry no value.\n *\n * @param schema - The schema, with its functions.\n * @param raw - Untrusted values.\n * @param runValidate - Runs a setting's `validate` (the caller guards it).\n */\nexport function checkSettingsValues(schema: SettingsSchema, raw: unknown, runValidate?: ValidateRunner): SettingsCheck {\n const values: Record<string, StoredSettingValue> = {}\n const errors: Record<string, string> = {}\n const input = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw as Record<string, unknown> : {}\n for (const [key, setting] of Object.entries(schema.items)) {\n if (!Object.hasOwn(input, key) || !isValueSetting(setting))\n continue\n const value = normalizeSettingValue(setting, input[key])\n const error = checkSettingValue(setting, value, runValidate)\n if (error === undefined)\n values[key] = value as StoredSettingValue\n else\n errors[key] = error\n }\n return { values, errors }\n}\n\n/**\n * The wire form of a schema and its values, as the Settings renderer takes\n * it. Values that do not fit the schema are left out (the renderer shows\n * the default).\n *\n * @param extensionId - The extension (category ids and the `extension` field).\n * @param schema - The schema, cleaned or not.\n * @param values - Values to show.\n */\nexport function settingsWire(extensionId: string, schema: SettingsSchema, values?: unknown): WireSettings {\n const clean = cleanSettingsSchema(extensionId, schema)\n return toWireSettings(extensionId, clean, values === undefined ? {} : checkSettingsValues(clean, values, () => undefined).values)\n}\n\n/**\n * An extension's wire with its `SettingsPage` items appended to its pages\n * (after the schema's pages, by `order`). Hosts call it where they build\n * an extension's settings wire and hold its UI registry.\n *\n * @param wire - The extension's wire (the domain's `wire()`, or `toWireSettings` from the definition).\n * @param extensionId - The extension.\n * @param ui - The registry holding its settings-page items.\n */\nexport function wireWithSettingsPages(wire: WireSettings, extensionId: string, ui: Pick<UiRegistry, 'list'>): WireSettings {\n return withSettingsPages(wire, extensionId, ui.list('settings-page').filter(e => e.extension === extensionId).map(e => e.item))\n}\n","/**\n * The JSON wire form of every UI contribution. Hosts in other processes\n * (the desktop renderer, protocol clients) only ever see these. Functions\n * stay in the backend: a wire item says which callbacks exist, and hosts\n * invoke them through the registry by the item's id (panel `load` /\n * `onAction`, reference `resolve`, badge action `run`, context section\n * `load`, settings actions).\n *\n * Serializers take an item whose bindable fields are already read, check\n * it, and throw a `TypeError` naming the problem when it is unusable.\n */\n\nimport type { SessionGroupBy, SessionQuery, SessionQueryIssue, SessionSort } from '../../chat/session-query'\nimport type { Theme } from '../../chat/theme'\nimport type { ComponentRef } from '../api/core'\nimport type {\n ContextSectionItem,\n LinkHandlerItem,\n MenuItem,\n PanelItem,\n RendererItem,\n RendererTarget,\n ScreenItem,\n SettingsPageItem,\n SidebarBadge,\n SidebarChip,\n SidebarDecorationItem,\n SidebarFilterItem,\n SidebarGroupItem,\n SidebarRowAction,\n SidebarRowItem,\n SidebarRowOpen,\n SidebarRowStatus,\n SidebarSortItem,\n SidebarText,\n SlotItem,\n SlotName,\n SpaceItem,\n SpaceNewSession,\n UiToken,\n WebviewItem,\n} from '../api/ui'\nimport type { BadgeActionsMatch, BadgeTargetKind, ExtensionBadgeActions } from '../badge-actions'\nimport type { PanelHomeLayout, PanelIcon, PanelSurface } from '../panels'\nimport type { ReferenceProviderWire } from '../references'\nimport type { WireSettings } from '../settings'\nimport type { ExtensionBadgeIcon, ExtensionBadgeTone, ExtensionReferenceProvider } from '../types'\nimport type { Resolved } from './bindable'\nimport { parseFieldPath, SessionQueryError, validateGroupBy, validateQuery, validateSort, validateTemplate } from '../../chat/session-query'\nimport { isThinkingLevel } from '../../thinking-levels'\nimport { isExtensionPanelScope, isPanelSurface, normalizePanelHomeLayout } from '../panels'\nimport { referenceProviderWires } from '../references'\nimport { EXTENSION_ID_PATTERN } from '../runtime/validate-definition'\nimport { isSettingsIcon } from '../settings/validate'\nimport { isBadgeColor } from '../types'\nimport { settingsWire } from './settings-form'\n\n/** A component reference on the wire: the export name and JSON props. */\nexport interface ComponentWire {\n /** Export name in the extension's `ui` / `tui` entry. */\n component: string\n /** JSON props handed to the component. */\n props?: Readonly<Record<string, unknown>>\n}\n\n/** A panel on the wire. Its `load` / `onAction` / `subscribe` stay backend-side. */\nexport interface PanelWire {\n /** `<extension>/<id>`. */\n id: string\n /** Tab title. */\n label: string\n /** Per-surface icon. */\n icon?: PanelIcon\n /** Where it shows: beside a session, in a project, or both. Default `session`. */\n scope?: 'session' | 'project' | 'both'\n /** Where it shows. Default `['side']`. */\n surfaces: readonly PanelSurface[]\n /** Layout of the block on the project home. */\n home?: PanelHomeLayout\n /** It has `subscribe`: the registry pushes `panel-changed` when it would load something new. */\n live: boolean\n /** It has `onAction`. */\n actions: boolean\n /** Drawn instead of the data where the host has it. */\n component?: ComponentWire\n}\n\n/** A slot item on the wire, its bindings read. */\nexport interface SlotWire {\n /** The slot it fills. */\n at: SlotName\n /** Limits the item to one session. */\n sessionId?: string\n /** `transcript.turn-end` only: draw after this turn. Absent: once, at the end of the transcript. */\n turnId?: string\n /** Item text. */\n text?: string\n /** Lines of a banner (`composer.above`). */\n lines?: readonly string[]\n /** A number past 999 shows `999+`. */\n count?: string\n /** Per-surface icon. */\n icon?: ExtensionBadgeIcon\n /** Tint of the item. */\n tone?: ExtensionBadgeTone\n /** Exact color, over `tone`. */\n color?: string\n /** A running arc in place of the icon. */\n loader?: true\n /** Raised and breathing: something waits on the user. */\n highlight?: true\n /** Hover text. */\n title?: string\n /** As the extension named it; hosts resolve it with the entry's extension. */\n panel?: string\n /** A click runs this command. */\n command?: string\n /** Lower first. Default 100. */\n order: number\n /** Drawn instead of the data where the host has it. */\n component?: ComponentWire\n}\n\n/** A screen on the wire. */\nexport interface ScreenWire {\n /** `<extension>/<id>`. */\n id: string\n /** Heading of the screen or modal. */\n title: string\n /** `modal` draws a dialog, `screen` a full-screen view. */\n presentation: 'screen' | 'modal'\n /** Required: hosts without the component draw `fallback`. */\n component: ComponentWire\n /** Markdown drawn where the component is missing. */\n fallback?: string\n}\n\n/** A renderer on the wire. */\nexport interface RendererWire {\n /** What it draws: a block id, a code-block language, a tool result or an artifact kind. */\n for: RendererTarget\n /** The component that draws it. */\n component: ComponentWire\n /** The component returns null to let the next renderer (or the default) draw. */\n fallthrough?: true\n}\n\n/** A settings page on the wire. */\nexport interface SettingsPageWire {\n /** `<extension>/<id>`. */\n id: string\n /** Page title. */\n title: string\n /** Icon in the settings sidebar. */\n icon?: { gui?: string, tui?: string }\n /** Place among the extension's pages, after the definition's pages; lower first. Absent: 100. */\n order?: number\n /** The page's settings in the settings renderer's wire format. */\n schema?: WireSettings\n /** Drawn instead of the data where the host has it. */\n component?: ComponentWire\n}\n\n/** A webview on the wire. A `file` source is relative to the extension's folder; the host resolves it. */\nexport interface WebviewWire {\n /** `<extension>/<id>`. */\n id: string\n /** Heading of the panel or screen. */\n title: string\n /** A URL, or a file in the extension folder. */\n src: { url: string } | { file: string }\n /** Shown in a panel or a screen. */\n placement: 'panel' | 'screen'\n /** RPC contract ids the page may call through the injected bridge. */\n rpc?: readonly string[]\n}\n\n/** A native menu entry on the wire. */\nexport interface MenuWire {\n /** Which native menu holds it. */\n menu: 'app' | 'session' | 'tray'\n /** Entry text. */\n label: string\n /** The command it runs. */\n command: string\n /** Keyboard shortcut. */\n accelerator?: string\n /** Whether it can be chosen. Default `true`. */\n enabled: boolean\n}\n\n/** Badge actions on the wire: which badges they apply to. The menu itself is asked for per target. */\nexport interface BadgeActionWire {\n /** The registration's id. */\n id: string\n /** Badges the actions apply to. Absent: every badge. */\n match?: BadgeActionsMatch\n}\n\n/** A context section on the wire. */\nexport type ContextSectionWire\n = | { placement: 'breakdown' }\n | { placement: 'panel', id: string, title: string, accentColor?: string, actions?: readonly { id: string, label: string }[] }\n\n/** A space on the wire. */\nexport interface SpaceWire {\n /** `<extension>/<id>`. */\n id: string\n /** Name shown for the space. */\n name: string\n /** Icon drawn with the name. */\n icon?: ExtensionBadgeIcon\n /** The sessions the space lists, validated. */\n query: SessionQuery\n /** How it groups its sessions. */\n groupBy?: SessionGroupBy\n /** How it sorts its sessions. */\n sortBy?: readonly SessionSort[]\n /** What a session started from it runs with. */\n newSession?: SpaceNewSession\n /** Sidebar items may list in it. */\n items: boolean\n /** Lower first. Default 100. */\n order: number\n}\n\n/** A sidebar filter on the wire. */\nexport interface SidebarFilterWire {\n /** `<extension>/<id>`. */\n id: string\n /** Text of the filter. */\n label: string\n /** Icon drawn with the label. */\n icon?: ExtensionBadgeIcon\n /** How the user picks. */\n kind: 'toggle' | 'select' | 'multi'\n /** `select` / `multi`: the options. */\n options?: readonly { id: string, label: string, query: SessionQuery }[]\n /** `toggle`: the sessions kept while on. */\n query?: SessionQuery\n /** `'all'`, or full space ids (`default`, `<extension>/<id>`). */\n spaces: 'all' | readonly string[]\n}\n\n/** A sidebar sort on the wire. */\nexport interface SidebarSortWire {\n /** `<extension>/<id>`. */\n id: string\n /** Text of the choice. */\n label: string\n /** The sort keys, validated. */\n sortBy: readonly SessionSort[]\n}\n\n/** A sidebar grouping on the wire. */\nexport interface SidebarGroupWire {\n /** `<extension>/<id>`. */\n id: string\n /** Text of the choice. */\n label: string\n /** The grouping, validated. */\n groupBy: SessionGroupBy\n}\n\n/** A sidebar decoration on the wire. */\nexport interface SidebarDecorationWire {\n /** `<extension>/<id>`. */\n id: string\n /** The sessions it applies to. Absent: every session. */\n where?: SessionQuery\n /** Icon drawn on the row. */\n icon?: ExtensionBadgeIcon\n /** Tint of the row's icon and chips. */\n tone?: ExtensionBadgeTone\n /** Text under the title: a string drawn as given, or `{ template }` (validated; render it with `renderTemplate`). */\n subtitle?: SidebarText\n /** Chips, at most 8: `text` drawn as given, `template` validated (render it with `renderTemplate`), or `facet`. */\n chips?: readonly SidebarChip[]\n /** Drawn on the row where the host has it. */\n component?: ComponentWire\n}\n\n/** A sidebar row's action on the wire. */\nexport interface SidebarRowActionWire extends SidebarRowAction {\n /** The full command id to run as is (resolved: `<extension>.<id>` when the extension has that command, else as written), with the row's `args`. */\n command?: string\n}\n\n/** A sidebar row on the wire, its bindings read and its references resolved: hosts use them as is. */\nexport interface SidebarRowWire {\n /** `<extension>/<id>`. */\n id: string\n /** The row's id as the extension gave it: the argument its `command`s run with (actions and `open.command`). */\n args: string\n /** Full space id: `default` or `<extension>/<id>`. */\n space: string\n /** Group key it lists under. */\n group?: string\n /** Row title. */\n title: string\n /** Text under the title. */\n subtitle?: string\n /** Icon drawn on the row. */\n icon?: ExtensionBadgeIcon\n /** Tint of the row. */\n tone?: ExtensionBadgeTone\n /** Run state. */\n status?: SidebarRowStatus\n /** Sorts as `updatedAt`, epoch ms. */\n time?: number\n /** Labels, at most 8. */\n badges?: readonly SidebarBadge[]\n /** Menu actions, at most 8, their commands resolved. */\n actions?: readonly SidebarRowActionWire[]\n /** What a click does: `command` resolved as an action's, `panel` / `screen` as full ids (`<extension>/<id>` when the extension has one by that id, else as written). */\n open?: SidebarRowOpen\n /** Sessions listed under it. */\n children?: SessionQuery\n}\n\n/**\n * A link handler on the wire: which handlers exist and their order. `match`\n * and `open` stay in the backend; hosts open a link through the resolver\n * (`UiRegistry.openLink`, `extensions.links.open`).\n */\nexport interface LinkHandlerWire {\n /** `<extension>/<id>`. */\n id: string\n /** Higher first among extensions. */\n priority: number\n /** The registering extension. */\n extensionId: string\n}\n\n/** The wire form of each token, by token name. */\nexport interface UiWireMap {\n 'panel': PanelWire\n 'slot': SlotWire\n 'screen': ScreenWire\n 'renderer': RendererWire\n 'settings-page': SettingsPageWire\n 'webview': WebviewWire\n 'menu': MenuWire\n 'theme': Theme\n 'reference': ReferenceProviderWire\n 'badge-action': BadgeActionWire\n 'link-handler': LinkHandlerWire\n 'context-section': ContextSectionWire\n 'space': SpaceWire\n 'sidebar-filter': SidebarFilterWire\n 'sidebar-sort': SidebarSortWire\n 'sidebar-group': SidebarGroupWire\n 'sidebar-decoration': SidebarDecorationWire\n 'sidebar-row': SidebarRowWire\n}\n\n/** Every token name the registry knows. */\nexport type UiTokenName = keyof UiWireMap\n\n/** The item type each token takes, by token name. */\nexport interface UiItemMap {\n 'panel': PanelItem\n 'slot': SlotItem\n 'screen': ScreenItem\n 'renderer': RendererItem\n 'settings-page': SettingsPageItem\n 'webview': WebviewItem\n 'menu': MenuItem\n 'theme': Theme\n 'reference': ExtensionReferenceProvider\n 'badge-action': ExtensionBadgeActions\n 'link-handler': LinkHandlerItem\n 'context-section': ContextSectionItem\n 'space': SpaceItem\n 'sidebar-filter': SidebarFilterItem\n 'sidebar-sort': SidebarSortItem\n 'sidebar-group': SidebarGroupItem\n 'sidebar-decoration': SidebarDecorationItem\n 'sidebar-row': SidebarRowItem\n}\n\n/** The token names, in a fixed order. */\nexport const UI_TOKEN_NAMES: readonly UiTokenName[] = ['panel', 'slot', 'screen', 'renderer', 'settings-page', 'webview', 'menu', 'theme', 'reference', 'badge-action', 'link-handler', 'context-section', 'space', 'sidebar-filter', 'sidebar-sort', 'sidebar-group', 'sidebar-decoration', 'sidebar-row']\n\n/**\n * Whether `token` is one the registry knows.\n *\n * @param token - A token passed to `ctx.add`.\n */\nexport function isKnownToken(token: UiToken<unknown>): token is UiToken<unknown, UiTokenName> {\n return !!token && token.kind === 'ui' && (UI_TOKEN_NAMES as readonly string[]).includes(token.name)\n}\n\n/** Every slot name. */\nexport const SLOT_NAMES: readonly SlotName[] = ['app.statusbar', 'app.titlebar', 'session.header', 'composer.above', 'composer.below', 'composer.badges', 'sidebar.top', 'sidebar.bottom', 'sidebar.footer', 'transcript.turn-end', 'home.block', 'settings.section']\n\nconst LOCAL_ID = /^[\\w.:-]{1,64}$/\nconst TONES: readonly ExtensionBadgeTone[] = ['muted', 'subtle', 'accent', 'success', 'warn', 'danger']\n\nfunction cut(value: unknown, max: number): string | undefined {\n if (typeof value !== 'string')\n return undefined\n const t = value.trim()\n if (!t)\n return undefined\n return t.length > max ? `${t.slice(0, max - 1)}…` : t\n}\n\nfunction need(value: unknown, what: string, max: number): string {\n const v = cut(value, max)\n if (!v)\n throw new TypeError(`${what} must be a non-empty string`)\n return v\n}\n\nfunction localId(value: unknown, what: string): string {\n if (typeof value !== 'string' || !LOCAL_ID.test(value))\n throw new TypeError(`${what} must match [A-Za-z0-9_.:-]{1,64}`)\n return value\n}\n\n/**\n * A JSON-safe copy of `value`, or `undefined` when it does not survive\n * JSON (cycles, BigInt). Functions and `undefined` fields are dropped.\n *\n * @param value - Any value.\n */\nexport function toJson<T>(value: T): T | undefined {\n if (value === undefined)\n return undefined\n try {\n return JSON.parse(JSON.stringify(value)) as T\n }\n catch {\n return undefined\n }\n}\n\nfunction icon(raw: unknown): ExtensionBadgeIcon | undefined {\n if (!raw || typeof raw !== 'object')\n return undefined\n const o = raw as Record<string, unknown>\n const gui = cut(o.gui, 128)\n const tui = cut(o.tui, 8)\n return gui || tui ? { ...(gui ? { gui } : {}), ...(tui ? { tui } : {}) } : undefined\n}\n\n/**\n * A component reference on the wire: the name checked, the props made\n * JSON-safe (props that do not survive JSON are dropped).\n *\n * @param raw - A {@link ComponentRef}, or anything.\n * @param required - Throw when it is missing.\n */\nexport function serializeComponent(raw: unknown, required: true): ComponentWire\nexport function serializeComponent(raw: unknown, required?: false): ComponentWire | undefined\nexport function serializeComponent(raw: unknown, required = false): ComponentWire | undefined {\n if (raw === undefined && !required)\n return undefined\n const ref = raw as ComponentRef | undefined\n if (!ref || typeof ref !== 'object' || typeof ref.component !== 'string' || !/^[A-Z_$][\\w$]{0,127}$/i.test(ref.component))\n throw new TypeError('component must be { component: <export name>, props? }')\n const props = ref.props && typeof ref.props === 'object' ? toJson(ref.props) : undefined\n return { component: ref.component, ...(props ? { props } : {}) }\n}\n\n/**\n * What a host draws for an item that names a component: the component when\n * the host has it, else the data (or the item's markdown fallback).\n *\n * @param item - A wire item.\n * @param item.component - The component the item names.\n * @param has - Whether the host has a component by that export name.\n */\nexport function pickComponent(item: { component?: ComponentWire }, has: (name: string) => boolean): ComponentWire | undefined {\n return item.component && has(item.component.component) ? item.component : undefined\n}\n\nfunction serializePanel(item: Resolved<PanelItem>, extension: string): PanelWire {\n const id = localId(item.id, 'Panel id')\n const label = need(item.label, 'Panel label', 80)\n if (typeof item.load !== 'function')\n throw new TypeError('Panel load must be a function')\n const surfaces = Array.isArray(item.surfaces) ? item.surfaces.filter(isPanelSurface) : []\n const home = normalizePanelHomeLayout(item.home)\n const panelIcon = item.icon && typeof item.icon === 'object' ? toJson(item.icon) : undefined\n const component = serializeComponent(item.component)\n return {\n id: `${extension}/${id}`,\n label,\n ...(panelIcon ? { icon: panelIcon } : {}),\n ...(isExtensionPanelScope(item.scope) ? { scope: item.scope } : {}),\n surfaces: surfaces.length > 0 ? [...new Set(surfaces)] : ['side'],\n ...(home ? { home } : {}),\n live: typeof item.subscribe === 'function',\n actions: typeof item.onAction === 'function',\n ...(component ? { component } : {}),\n }\n}\n\n/**\n * Whether a slot holds badges: `composer.badges` and `app.titlebar` take\n * short text (40 characters) and at most {@link MAX_SLOT_BADGES} items per\n * extension (per session for `composer.badges`).\n *\n * @param at - A slot name.\n */\nexport function isBadgeSlot(at: SlotName): boolean {\n return at === 'composer.badges' || at === 'app.titlebar'\n}\n\n/** How many items one extension may show in a badge slot ({@link isBadgeSlot}); per session for `composer.badges`. */\nexport const MAX_SLOT_BADGES = 8\n\nfunction serializeSlot(item: Resolved<SlotItem>): SlotWire {\n if (!SLOT_NAMES.includes(item.at))\n throw new TypeError(`Slot at must be one of ${SLOT_NAMES.join(', ')}`)\n const sessionId = item.sessionId === undefined ? undefined : need(item.sessionId, 'Slot sessionId', 512)\n if (item.at === 'composer.badges' && !sessionId)\n throw new TypeError('A composer.badges item needs a sessionId')\n const turnId = item.turnId === undefined ? undefined : need(item.turnId, 'Slot turnId', 512)\n if (turnId && item.at !== 'transcript.turn-end')\n throw new TypeError('Only a transcript.turn-end item takes a turnId')\n const text = cut(item.text, isBadgeSlot(item.at) ? 40 : 500)\n const lines = Array.isArray(item.lines) ? item.lines.flatMap(l => (typeof l === 'string' && l.length > 0 ? [l.slice(0, 500)] : [])).slice(0, 20) : []\n const count = typeof item.count === 'number' && Number.isFinite(item.count)\n ? (item.count > 999 ? '999+' : String(item.count))\n : cut(item.count, 12)\n const slotIcon = icon(item.icon)\n const tone = TONES.find(t => t === item.tone)\n const color = isBadgeColor(item.color) ? item.color : undefined\n const title = cut(item.title, 200)\n const panel = cut(item.panel, 200)\n const command = cut(item.command, 200)\n const component = serializeComponent(item.component)\n return {\n at: item.at,\n ...(sessionId ? { sessionId } : {}),\n ...(turnId ? { turnId } : {}),\n ...(text ? { text } : {}),\n ...(lines.length > 0 ? { lines } : {}),\n ...(count !== undefined ? { count } : {}),\n ...(slotIcon ? { icon: slotIcon } : {}),\n ...(tone ? { tone } : {}),\n ...(color ? { color } : {}),\n ...(item.loader === true ? { loader: true as const } : {}),\n ...(item.highlight === true ? { highlight: true as const } : {}),\n ...(title ? { title } : {}),\n ...(panel ? { panel } : {}),\n ...(command ? { command } : {}),\n order: typeof item.order === 'number' && Number.isFinite(item.order) ? item.order : 100,\n ...(component ? { component } : {}),\n }\n}\n\nfunction serializeScreen(item: Resolved<ScreenItem>, extension: string): ScreenWire {\n const fallback = typeof item.fallback === 'string' && item.fallback ? item.fallback.slice(0, 20_000) : undefined\n return {\n id: `${extension}/${localId(item.id, 'Screen id')}`,\n title: need(item.title, 'Screen title', 200),\n presentation: item.presentation === 'modal' ? 'modal' : 'screen',\n component: serializeComponent(item.component, true),\n ...(fallback ? { fallback } : {}),\n }\n}\n\nfunction serializeTarget(target: RendererTarget): RendererTarget {\n if (target && typeof target === 'object') {\n if ('block' in target)\n return { block: need(target.block, 'Renderer block', 128) }\n if ('language' in target)\n return { language: need(target.language, 'Renderer language', 64).toLowerCase() }\n if ('artifact' in target)\n return { artifact: need(target.artifact, 'Renderer artifact', 128) }\n if ('tool' in target) {\n const tools = (typeof target.tool === 'string' ? [target.tool] : Array.isArray(target.tool) ? target.tool : []).filter((t): t is string => typeof t === 'string' && t.length > 0)\n if (tools.length === 0)\n throw new TypeError('Renderer tool must name at least one tool')\n return { tool: typeof target.tool === 'string' ? tools[0]! : tools }\n }\n }\n throw new TypeError('Renderer for must be { block } | { language } | { tool } | { artifact }')\n}\n\nfunction serializeRenderer(item: Resolved<RendererItem>): RendererWire {\n return {\n for: serializeTarget(item.for),\n component: serializeComponent(item.component, true),\n ...(item.fallthrough === true ? { fallthrough: true as const } : {}),\n }\n}\n\nfunction serializeSettingsPage(item: Resolved<SettingsPageItem>, extension: string): SettingsPageWire {\n if (!item.schema && !item.component)\n throw new TypeError('A settings page needs a schema or a component')\n const component = serializeComponent(item.component)\n return {\n id: `${extension}/${localId(item.id, 'Settings page id')}`,\n title: need(item.title, 'Settings page title', 200),\n ...(isSettingsIcon(item.icon) ? { icon: { ...(item.icon.gui !== undefined ? { gui: item.icon.gui } : {}), ...(item.icon.tui !== undefined ? { tui: item.icon.tui } : {}) } } : {}),\n ...(typeof item.order === 'number' && Number.isFinite(item.order) ? { order: item.order } : {}),\n ...(item.schema ? { schema: settingsWire(extension, item.schema) } : {}),\n ...(component ? { component } : {}),\n }\n}\n\nfunction serializeWebview(item: Resolved<WebviewItem>, extension: string): WebviewWire {\n const src = item.src as { url?: unknown, file?: unknown } | undefined\n let wireSrc: WebviewWire['src']\n if (src && typeof src.url === 'string' && /^(?:https?|file):\\/\\//i.test(src.url))\n wireSrc = { url: src.url }\n else if (src && typeof src.file === 'string' && src.file && !src.file.startsWith('/') && !src.file.split(/[\\\\/]/).includes('..'))\n wireSrc = { file: src.file }\n else\n throw new TypeError('Webview src must be { url: http(s)/file URL } or { file: <path inside the extension folder> }')\n if (item.placement !== 'panel' && item.placement !== 'screen')\n throw new TypeError('Webview placement must be panel or screen')\n const rpc = Array.isArray(item.rpc) ? item.rpc.filter((r): r is string => typeof r === 'string' && r.length > 0) : undefined\n return {\n id: `${extension}/${localId(item.id, 'Webview id')}`,\n title: need(item.title, 'Webview title', 200),\n src: wireSrc,\n placement: item.placement,\n ...(rpc && rpc.length > 0 ? { rpc } : {}),\n }\n}\n\nfunction serializeMenu(item: Resolved<MenuItem>): MenuWire {\n if (item.menu !== 'app' && item.menu !== 'session' && item.menu !== 'tray')\n throw new TypeError('Menu menu must be app, session or tray')\n const accelerator = cut(item.accelerator, 64)\n return {\n menu: item.menu,\n label: need(item.label, 'Menu label', 120),\n command: need(item.command, 'Menu command', 200),\n ...(accelerator ? { accelerator } : {}),\n enabled: item.enabled !== false,\n }\n}\n\nfunction serializeTheme(item: Theme): Theme {\n localId(item?.id, 'Theme id')\n need(item.label, 'Theme label', 120)\n if (!item.colors || !item.select || !item.surfaces || !item.syntax)\n throw new TypeError('Theme needs colors, select, surfaces and syntax')\n const theme = toJson(item)\n if (!theme)\n throw new TypeError('Theme must be JSON')\n return theme\n}\n\nfunction serializeReference(item: ExtensionReferenceProvider): ReferenceProviderWire {\n need(item?.id, 'Reference id', 128)\n if (!Array.isArray(item.patterns) || item.patterns.length === 0)\n throw new TypeError('Reference patterns must be a non-empty list')\n if (typeof item.resolve !== 'function')\n throw new TypeError('Reference resolve must be a function')\n // The shared wire builder (`referenceProviderWires`): same patterns, same placeholder rules.\n return referenceProviderWires({ references: [{ extensionName: '', source: 'project', value: item }] }, { builtins: false })[0]!\n}\n\nconst TARGET_KINDS: readonly BadgeTargetKind[] = ['link', 'file', 'commit', 'pull_request', 'branch', 'reference', 'artifact']\n\nfunction serializeBadgeAction(item: ExtensionBadgeActions): BadgeActionWire {\n const id = need(item?.id, 'Badge action id', 128)\n if (typeof item.actions !== 'function' || typeof item.run !== 'function')\n throw new TypeError('Badge actions need actions and run functions')\n const strings = (v: unknown): string[] | undefined => (Array.isArray(v) ? v.filter((s): s is string => typeof s === 'string') : undefined)\n const m = item.match\n const kinds = m?.kinds?.filter(k => TARGET_KINDS.includes(k))\n const artifactKinds = strings(m?.artifactKinds)\n const references = strings(m?.references)\n const match: BadgeActionsMatch | undefined = m\n ? { ...(kinds ? { kinds } : {}), ...(artifactKinds ? { artifactKinds } : {}), ...(references ? { references } : {}) }\n : undefined\n return { id, ...(match ? { match } : {}) }\n}\n\nfunction serializeLinkHandler(item: LinkHandlerItem, extension: string): LinkHandlerWire {\n const id = localId(item?.id, 'Link handler id')\n const m = item.match\n if (typeof m !== 'function' && !(m instanceof RegExp) && !(typeof m === 'string' && m.length > 0))\n throw new TypeError('Link handler match must be a non-empty prefix, a RegExp or a function')\n if (typeof item.open !== 'function')\n throw new TypeError('Link handler open must be a function')\n if (item.priority !== undefined && (typeof item.priority !== 'number' || !Number.isFinite(item.priority)))\n throw new TypeError('Link handler priority must be a finite number')\n return { id: `${extension}/${id}`, priority: item.priority ?? 0, extensionId: extension }\n}\n\nfunction serializeContextSection(item: ContextSectionItem): ContextSectionWire {\n if (item?.placement === 'breakdown') {\n if (typeof item.contributor !== 'function')\n throw new TypeError('A breakdown context section needs a contributor function')\n return { placement: 'breakdown' }\n }\n if (item?.placement === 'panel') {\n const s = item.section\n const id = localId(s?.id, 'Context section id')\n const title = need(s.title, 'Context section title', 120)\n if (!s.rows && typeof s.load !== 'function')\n throw new TypeError('A panel context section needs rows or load')\n const accentColor = cut(s.accentColor, 32)\n const actions = Array.isArray(s.actions)\n ? s.actions.flatMap((a) => {\n const actionId = cut(a?.id, 64)\n const label = cut(a?.label, 80)\n return actionId && label ? [{ id: actionId, label }] : []\n })\n : undefined\n return { placement: 'panel', id, title, ...(accentColor ? { accentColor } : {}), ...(actions && actions.length > 0 ? { actions } : {}) }\n }\n throw new TypeError('Context section placement must be breakdown or panel')\n}\n\n/**\n * A sidebar token's query, sort, grouping or template is invalid. Its\n * `issues` paths start at the item's field (`query`, `options[2].query`,\n * `children`, `chips[0].template`).\n */\nexport class UiQueryError extends SessionQueryError {\n /**\n * @param token - The token of the item.\n * @param issues - The problems found.\n */\n constructor(readonly token: UiTokenName, issues: readonly SessionQueryIssue[]) {\n super(issues)\n this.name = 'UiQueryError'\n this.message = `${token}: ${this.message}`\n }\n}\n\n/** What the wire resolves the commands, panels and screens of a sidebar row against. */\nexport interface UiRefs {\n /** Whether a command with this full id (`<extension>.<id>`) exists. */\n hasCommand: (id: string) => boolean\n /** Whether a panel or screen with this full id (`<extension>/<id>`) exists. */\n hasSurface: (kind: 'panel' | 'screen', id: string) => boolean\n}\n\n/** Refs that know nothing: every id stays as written. */\nexport const NO_UI_REFS: UiRefs = { hasCommand: () => false, hasSurface: () => false }\n\nfunction checked<T>(issues: readonly SessionQueryIssue[], value: unknown): T {\n if (issues.length > 0)\n throw new SessionQueryError(issues)\n return toJson(value) as T\n}\n\nconst query = (path: string, value: unknown): SessionQuery => checked(validateQuery(value, path), value)\nconst optionalQuery = (path: string, value: unknown): SessionQuery | undefined => (value === undefined ? undefined : query(path, value))\n\n/** `default`, a full id kept as is, or an own space id made full. */\nfunction spaceRef(value: unknown, extension: string, what: string): string {\n if (value === 'default')\n return value\n if (typeof value === 'string' && value.includes('/')) {\n const [ext, id, ...rest] = value.split('/')\n if (rest.length === 0 && EXTENSION_ID_PATTERN.test(ext!) && LOCAL_ID.test(id!))\n return value\n throw new TypeError(`${what} must be default, an own space id or <extension>/<id>`)\n }\n return `${extension}/${localId(value, what)}`\n}\n\n/** A command id as published: the extension's own `<extension>.<id>` when it has it, else as written. */\nfunction commandRef(id: string, extension: string, refs: UiRefs): string {\n const own = `${extension}.${id}`\n return refs.hasCommand(own) ? own : id\n}\n\n/** A panel or screen id as published: the extension's own `<extension>/<id>` when it has it, else as written. */\nfunction surfaceRef(kind: 'panel' | 'screen', id: string, extension: string, refs: UiRefs): string {\n const own = `${extension}/${id}`\n return refs.hasSurface(kind, own) ? own : id\n}\n\nfunction tone(value: unknown): ExtensionBadgeTone | undefined {\n return TONES.find(t => t === value)\n}\n\nfunction capped(value: unknown, max: number, what: string): readonly unknown[] {\n if (value === undefined)\n return []\n if (!Array.isArray(value))\n throw new TypeError(`${what} must be a list`)\n if (value.length > max)\n throw new TypeError(`${what}: at most ${max}`)\n return value\n}\n\nfunction serializeSpace(item: Resolved<SpaceItem>, extension: string): SpaceWire {\n const id = localId(item.id, 'Space id')\n if (id === 'default')\n throw new TypeError('Space id \"default\" belongs to the built-in space')\n const spaceIcon = icon(item.icon)\n const groupBy = item.groupBy === undefined ? undefined : checked<SessionGroupBy>(validateGroupBy(item.groupBy, 'groupBy'), item.groupBy)\n const sortBy = item.sortBy === undefined ? undefined : checked<SessionSort[]>(validateSort(item.sortBy, 'sortBy'), item.sortBy)\n const ns = item.newSession as Record<string, unknown> | undefined\n let newSession: SpaceNewSession | undefined\n if (ns !== undefined) {\n if (!ns || typeof ns !== 'object')\n throw new TypeError('Space newSession must be { agentId?, providerKey?, modelId?, effort? }')\n if (ns.effort !== undefined && !isThinkingLevel(ns.effort))\n throw new TypeError('Space newSession.effort must be a thinking level')\n const agentId = cut(ns.agentId, 200)\n const providerKey = cut(ns.providerKey, 200)\n const modelId = cut(ns.modelId, 200)\n newSession = { ...(agentId ? { agentId } : {}), ...(providerKey ? { providerKey } : {}), ...(modelId ? { modelId } : {}), ...(ns.effort !== undefined ? { effort: ns.effort as SpaceNewSession['effort'] } : {}) }\n }\n return {\n id: `${extension}/${id}`,\n name: need(item.name, 'Space name', 80),\n ...(spaceIcon ? { icon: spaceIcon } : {}),\n query: query('query', item.query),\n ...(groupBy ? { groupBy } : {}),\n ...(sortBy ? { sortBy } : {}),\n ...(newSession && Object.keys(newSession).length > 0 ? { newSession } : {}),\n items: item.items === true,\n order: typeof item.order === 'number' && Number.isFinite(item.order) ? item.order : 100,\n }\n}\n\nfunction serializeSidebarFilter(item: Resolved<SidebarFilterItem>, extension: string): SidebarFilterWire {\n const id = localId(item.id, 'Sidebar filter id')\n if (item.kind !== 'toggle' && item.kind !== 'select' && item.kind !== 'multi')\n throw new TypeError('Sidebar filter kind must be toggle, select or multi')\n const filterIcon = icon(item.icon)\n let options: SidebarFilterWire['options']\n let filterQuery: SessionQuery | undefined\n if (item.kind === 'toggle') {\n if (item.options !== undefined)\n throw new TypeError('A toggle sidebar filter takes a query, not options')\n filterQuery = query('query', item.query)\n }\n else {\n if (item.query !== undefined)\n throw new TypeError(`A ${item.kind} sidebar filter takes options, not a query`)\n const list = capped(item.options, 32, 'Sidebar filter options') as readonly Record<string, unknown>[]\n if (list.length === 0)\n throw new TypeError(`A ${item.kind} sidebar filter needs 1 to 32 options`)\n const seen = new Set<string>()\n options = list.map((o, i) => {\n const optionId = localId(o?.id, `Sidebar filter option ${i} id`)\n if (seen.has(optionId))\n throw new TypeError(`Sidebar filter option id \"${optionId}\" is used twice`)\n seen.add(optionId)\n return { id: optionId, label: need(o.label, `Sidebar filter option ${optionId} label`, 80), query: query(`options[${i}].query`, o.query) }\n })\n }\n let spaces: SidebarFilterWire['spaces'] = 'all'\n if (item.spaces !== undefined && item.spaces !== 'all') {\n const list = capped(item.spaces, 64, 'Sidebar filter spaces')\n if (list.length === 0)\n throw new TypeError('Sidebar filter spaces must be all or name at least one space')\n spaces = [...new Set(list.map(s => spaceRef(s, extension, 'Sidebar filter space')))]\n }\n return {\n id: `${extension}/${id}`,\n label: need(item.label, 'Sidebar filter label', 80),\n ...(filterIcon ? { icon: filterIcon } : {}),\n kind: item.kind,\n ...(options ? { options } : {}),\n ...(filterQuery ? { query: filterQuery } : {}),\n spaces,\n }\n}\n\nfunction serializeSidebarSort(item: Resolved<SidebarSortItem>, extension: string): SidebarSortWire {\n const id = localId(item.id, 'Sidebar sort id')\n if (!Array.isArray(item.sortBy) || item.sortBy.length === 0)\n throw new TypeError('Sidebar sort needs at least one sort key in sortBy')\n return { id: `${extension}/${id}`, label: need(item.label, 'Sidebar sort label', 80), sortBy: checked(validateSort(item.sortBy, 'sortBy'), item.sortBy) }\n}\n\nfunction serializeSidebarGroup(item: Resolved<SidebarGroupItem>, extension: string): SidebarGroupWire {\n const id = localId(item.id, 'Sidebar group id')\n return { id: `${extension}/${id}`, label: need(item.label, 'Sidebar group label', 80), groupBy: checked(validateGroupBy(item.groupBy, 'groupBy'), item.groupBy) }\n}\n\n/** A string drawn as given (blank: absent), or `{ template }` checked as a template. */\nfunction sidebarText(value: unknown, path: string, max: number): SidebarText | undefined {\n if (value === undefined)\n return undefined\n if (typeof value === 'string')\n return cut(value, max)\n const t = (value && typeof value === 'object' ? value : {}) as Record<string, unknown>\n if (typeof t.template !== 'string' || Object.keys(t).length !== 1)\n throw new TypeError(`${path} must be a string or { template }`)\n return { template: checked<string>(validateTemplate(t.template, `${path}.template`), t.template) }\n}\n\nfunction serializeSidebarDecoration(item: Resolved<SidebarDecorationItem>, extension: string): SidebarDecorationWire {\n const id = localId(item.id, 'Sidebar decoration id')\n const where = optionalQuery('where', item.where)\n const decorationIcon = icon(item.icon)\n const decorationTone = tone(item.tone)\n const subtitle = sidebarText(item.subtitle, 'subtitle', 300)\n const chips = capped(item.chips, 8, 'Sidebar decoration chips').map((raw, i): SidebarChip | undefined => {\n const c = (raw ?? {}) as Record<string, unknown>\n const chipTone = tone(c.tone)\n const chipIcon = icon(c.icon)\n const extra = { ...(chipTone ? { tone: chipTone } : {}), ...(chipIcon ? { icon: chipIcon } : {}) }\n const kinds = (['text', 'template', 'facet'] as const).filter(k => c[k] !== undefined)\n if (kinds.length !== 1)\n throw new TypeError(`chips[${i}] must be one of { text }, { template } or { facet: facet.<extension>.<key> }`)\n if (kinds[0] === 'text') {\n if (typeof c.text !== 'string')\n throw new TypeError(`chips[${i}].text must be a string`)\n // Blank user text (a name cleared) is no chip, not an error.\n const text = cut(c.text, 80)\n return text ? { text, ...extra } : undefined\n }\n if (kinds[0] === 'template') {\n if (typeof c.template !== 'string')\n throw new TypeError(`chips[${i}].template must be a string`)\n return { template: checked<string>(validateTemplate(c.template, `chips[${i}].template`), c.template), ...extra }\n }\n if (parseFieldPath(c.facet)?.kind !== 'facet')\n throw new TypeError(`chips[${i}].facet must be facet.<extension>.<key>`)\n return { facet: c.facet as `facet.${string}`, ...extra }\n }).filter((c): c is SidebarChip => c !== undefined)\n const component = serializeComponent(item.component)\n if (!decorationIcon && !decorationTone && !subtitle && chips.length === 0 && !component)\n throw new TypeError('A sidebar decoration needs an icon, a tone, a subtitle, chips or a component')\n return {\n id: `${extension}/${id}`,\n ...(where ? { where } : {}),\n ...(decorationIcon ? { icon: decorationIcon } : {}),\n ...(decorationTone ? { tone: decorationTone } : {}),\n ...(subtitle ? { subtitle } : {}),\n ...(chips.length > 0 ? { chips } : {}),\n ...(component ? { component } : {}),\n }\n}\n\nconst ROW_STATUSES: readonly SidebarRowStatus[] = ['idle', 'running', 'blocked', 'completed', 'error']\n\nfunction serializeOpen(value: unknown, extension: string, refs: UiRefs): SidebarRowOpen | undefined {\n if (value === undefined)\n return undefined\n const o = (value && typeof value === 'object' ? value : {}) as Record<string, unknown>\n const keys = (['command', 'panel', 'screen', 'session'] as const).filter(k => o[k] !== undefined)\n if (keys.length !== 1)\n throw new TypeError('Sidebar row open must be one of { command }, { panel }, { screen }, { session }')\n const key = keys[0]!\n const id = need(o[key], `Sidebar row open.${key}`, 512)\n switch (key) {\n case 'command':\n return { command: commandRef(id, extension, refs) }\n case 'panel':\n return { panel: surfaceRef('panel', id, extension, refs) }\n case 'screen':\n return { screen: surfaceRef('screen', id, extension, refs) }\n default:\n return { session: id }\n }\n}\n\nfunction serializeSidebarRow(item: Resolved<SidebarRowItem>, extension: string, refs: UiRefs): SidebarRowWire {\n const id = localId(item.id, 'Sidebar row id')\n const group = item.group === undefined ? undefined : need(item.group, 'Sidebar row group', 200)\n const subtitle = cut(item.subtitle, 300)\n const rowIcon = icon(item.icon)\n const rowTone = tone(item.tone)\n if (item.status !== undefined && !ROW_STATUSES.includes(item.status))\n throw new TypeError(`Sidebar row status must be one of ${ROW_STATUSES.join(', ')}`)\n if (item.time !== undefined && (typeof item.time !== 'number' || !Number.isFinite(item.time)))\n throw new TypeError('Sidebar row time must be epoch ms')\n const badges = capped(item.badges, 8, 'Sidebar row badges').map((raw, i): SidebarBadge => {\n const b = (raw ?? {}) as Record<string, unknown>\n const badgeTone = tone(b.tone)\n const badgeIcon = icon(b.icon)\n return { text: need(b.text, `Sidebar row badge ${i} text`, 40), ...(badgeTone ? { tone: badgeTone } : {}), ...(badgeIcon ? { icon: badgeIcon } : {}) }\n })\n const seen = new Set<string>()\n const actions = capped(item.actions, 8, 'Sidebar row actions').map((raw, i): SidebarRowActionWire => {\n const a = (raw ?? {}) as Record<string, unknown>\n const actionId = localId(a.id, `Sidebar row action ${i} id`)\n if (seen.has(actionId))\n throw new TypeError(`Sidebar row action id \"${actionId}\" is used twice`)\n seen.add(actionId)\n const command = cut(a.command, 200)\n return { id: actionId, label: need(a.label, `Sidebar row action ${actionId} label`, 80), ...(command ? { command: commandRef(command, extension, refs) } : {}) }\n })\n const open = serializeOpen(item.open, extension, refs)\n const children = optionalQuery('children', item.children)\n return {\n id: `${extension}/${id}`,\n args: id,\n space: spaceRef(item.space, extension, 'Sidebar row space'),\n ...(group ? { group } : {}),\n // Blank user text (a name cleared) falls back to the row id rather than failing the row.\n title: typeof item.title === 'string' ? (cut(item.title, 200) ?? id) : need(item.title, 'Sidebar row title', 200),\n ...(subtitle ? { subtitle } : {}),\n ...(rowIcon ? { icon: rowIcon } : {}),\n ...(rowTone ? { tone: rowTone } : {}),\n ...(item.status !== undefined ? { status: item.status } : {}),\n ...(item.time !== undefined ? { time: item.time } : {}),\n ...(badges.length > 0 ? { badges } : {}),\n ...(actions.length > 0 ? { actions } : {}),\n ...(open ? { open } : {}),\n ...(children ? { children } : {}),\n }\n}\n\ntype Serializer<N extends UiTokenName> = (item: Resolved<UiItemMap[N]>, extension: string, refs: UiRefs) => UiWireMap[N]\n\nconst SERIALIZERS: { [N in UiTokenName]: Serializer<N> } = {\n 'panel': serializePanel,\n 'slot': serializeSlot,\n 'screen': serializeScreen,\n 'renderer': serializeRenderer,\n 'settings-page': serializeSettingsPage,\n 'webview': serializeWebview,\n 'menu': serializeMenu,\n 'theme': serializeTheme,\n 'reference': serializeReference,\n 'badge-action': serializeBadgeAction,\n 'link-handler': serializeLinkHandler,\n 'context-section': serializeContextSection,\n 'space': serializeSpace,\n 'sidebar-filter': serializeSidebarFilter,\n 'sidebar-sort': serializeSidebarSort,\n 'sidebar-group': serializeSidebarGroup,\n 'sidebar-decoration': serializeSidebarDecoration,\n 'sidebar-row': serializeSidebarRow,\n}\n\n/**\n * The wire form of one item. Throws a `TypeError` when the item is\n * unusable, and a {@link UiQueryError} when one of its queries, sorts,\n * groupings or templates is invalid.\n *\n * @param token - The token name.\n * @param item - The item with its bindable fields read.\n * @param extension - The contributing extension's id (prefixes ids).\n * @param refs - What a sidebar row's commands, panels and screens resolve against. Default: nothing (ids stay as written).\n */\nexport function serializeUiItem<N extends UiTokenName>(token: N, item: Resolved<UiItemMap[N]>, extension: string, refs: UiRefs = NO_UI_REFS): UiWireMap[N] {\n if (!item || typeof item !== 'object')\n throw new TypeError(`${token}: the item must be an object`)\n try {\n return (SERIALIZERS[token] as Serializer<N>)(item, extension, refs)\n }\n catch (err) {\n if (err instanceof SessionQueryError && !(err instanceof UiQueryError))\n throw new UiQueryError(token, err.issues)\n throw err\n }\n}\n\n/**\n * What makes an item the same item across updates: its id; for slots the\n * place and session; for renderers what they render (`for`, as JSON); for\n * breakdown context sections the constant `'breakdown'`. `update` may not\n * change it. `undefined` only for menus, whose items have no identity.\n *\n * @param token - The token name.\n * @param wire - The item's wire form.\n */\nexport function wireIdentity<N extends UiTokenName>(token: N, wire: UiWireMap[N]): string | undefined {\n switch (token) {\n case 'slot': {\n const s = wire as SlotWire\n return `${s.at}\\u0000${s.sessionId ?? ''}`\n }\n case 'renderer':\n return JSON.stringify((wire as RendererWire).for)\n case 'menu':\n return undefined\n case 'context-section': {\n const c = wire as ContextSectionWire\n return c.placement === 'panel' ? c.id : 'breakdown'\n }\n default:\n return (wire as { id: string }).id\n }\n}\n\n/**\n * Whether two items of this token with the same identity\n * ({@link wireIdentity}) may not live side by side in one extension: true\n * for every token but slots, renderers, menus and breakdown context\n * sections.\n *\n * @param token - The token name.\n * @param wire - The item's wire form.\n */\nexport function isUniquePerExtension<N extends UiTokenName>(token: N, wire: UiWireMap[N]): boolean {\n if (token === 'context-section')\n return (wire as ContextSectionWire).placement === 'panel'\n return token !== 'slot' && token !== 'renderer' && token !== 'menu'\n}\n","/**\n * Facets (`ctx.sessions.facets`): JSON values extensions compute per\n * session, which session queries read as `facet.<extensionId>.<key>`. The\n * runtime keeps the registrations and runs them; hosts store the values and\n * decide when to compute (a session created, a run settled, metadata\n * changed, a facet added, a `refresh` asked for).\n */\n\nimport type { JsonValue } from '../../types'\nimport type { Disposable, Owner } from '../api/core'\nimport type { SessionFacetsDomain, SessionFacetSpec, SessionFacetTrigger, SessionSnapshot } from '../api/sessions'\nimport type { DomainDeps } from './deps'\nimport { FACET_KEY } from '../../chat/session-query'\nimport { metadataForExtension } from '../../session/facets'\nimport { toJson } from '../ui/wire'\nimport { assertAlive, track } from './owner'\n\n/** Bound of one facet's `compute`, in ms. */\nexport const FACET_COMPUTE_TIMEOUT_MS = 5_000\n/** The most JSON one facet value may take, in bytes of its JSON text. */\nexport const MAX_FACET_BYTES = 8 * 1024\n/** How many facets one extension may hold. */\nexport const MAX_FACETS_PER_EXTENSION = 32\n/** Every trigger, in a fixed order: what a facet without `on` runs on. */\nexport const SESSION_FACET_TRIGGERS: readonly SessionFacetTrigger[] = ['created', 'settled', 'metadata']\n\n/** A registered facet, as hosts list it. */\nexport interface FacetInfo {\n /** `<extensionId>.<key>`: its key in a row's `facets` and its query path after `facet.`. */\n readonly id: string\n /** The extension that computes it. */\n readonly extension: string\n /** The extension's key. */\n readonly key: string\n /** The triggers it is computed again on. */\n readonly on: readonly SessionFacetTrigger[]\n}\n\n/** A `ctx.sessions.facets.refresh` call, as hosts get it. */\nexport interface FacetRefreshRequest {\n /** The extension whose facets to compute again. */\n readonly extension: string\n /** Only this session. Absent: every session. */\n readonly sessionId?: string\n}\n\n/**\n * A change of a registry's facets, as {@link FacetRegistry.subscribe}\n * reports it. Only an explicit withdrawal or an uninstall asks hosts to\n * delete stored values: an extension disabled, failing or reloaded withdraws\n * its facets with both lists empty, and its stored values stay.\n */\nexport interface FacetChange {\n /** Facet ids their extension disposed while it stayed loaded: hosts delete their stored values. */\n readonly withdrawn: readonly string[]\n /** Extensions uninstalled or forgotten (`unload` with `forget`): hosts delete every stored value of theirs. */\n readonly forgotten: readonly string[]\n}\n\n/** Options of {@link FacetRegistry.compute}. */\nexport interface FacetComputeOptions {\n /** Only this extension's facets. */\n extension?: string\n}\n\n/** The facets every extension registered. Hung on `ExtensionRuntimeOutputs.facets`. */\nexport interface FacetRegistry {\n /** Every facet, in extension load order, then registration order. */\n list: () => readonly FacetInfo[]\n /**\n * Computes the facets that run on `triggers` (one trigger or a set; every\n * facet when absent) for one session, each facet once, in parallel, each\n * under its extension's guard. Each extension's facets see\n * `metadata.extensions` cut down to its own slice. The result holds a key\n * per facet that answered: its JSON value, or `null` to clear it. A facet\n * that threw, timed out, or answered something too big or not JSON has no\n * key: keep its last value.\n */\n compute: (session: SessionSnapshot, triggers?: SessionFacetTrigger | ReadonlySet<SessionFacetTrigger>, options?: FacetComputeOptions) => Promise<Record<string, JsonValue>>\n /** Calls `listener` after a facet is added or withdrawn, or an extension is forgotten, with what was withdrawn on purpose ({@link FacetChange}). Not called once the registry is disposed. Returns the unsubscribe. */\n subscribe: (listener: (change: FacetChange) => void) => () => void\n /** Whether the runtime that owns the registry was disposed: nothing is computed with it again. */\n disposed: () => boolean\n /** Calls `listener` once, when the owning runtime is disposed (at once when it already is). Returns the unsubscribe. */\n onDispose: (listener: () => void) => () => void\n /** Logs a warning on `extension`'s logger (a host refusing its values). Dropped when the extension holds no facet. */\n warn: (extension: string, message: string) => void\n /**\n * Handles `ctx.sessions.facets.refresh`: the host computes the facets again\n * and stores them. `refresh` resolves once every handler did. Returns the\n * unsubscribe. With no handler, `refresh` resolves at once.\n */\n onRefresh: (handler: (request: FacetRefreshRequest) => void | Promise<void>) => () => void\n}\n\n/**\n * The registry together with its per-extension domain factory, its close\n * (the runtime's dispose calls it first), and `forget` (the runtime's\n * `unload` with `forget` calls it, after the extension's facets went).\n */\nexport type FacetsRuntime = FacetRegistry & { domain: (deps: DomainDeps) => SessionFacetsDomain, close: () => void, forget: (extensionId: string) => void }\n\ninterface Entry {\n info: FacetInfo\n spec: SessionFacetSpec\n deps: DomainDeps\n seq: number\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n Object.freeze(value)\n for (const v of Object.values(value)) deepFreeze(v)\n }\n return value\n}\n\n/** Whether the extension behind `owner` (its root owner, past any scope) is still loaded. */\nfunction extensionAlive(owner: Owner): boolean {\n let root = owner\n while ((root as { parent?: Owner }).parent)\n root = (root as { parent?: Owner }).parent!\n return !root.disposed\n}\n\nfunction triggersOf(on: unknown): SessionFacetTrigger[] {\n if (on === undefined)\n return [...SESSION_FACET_TRIGGERS]\n if (!Array.isArray(on) || on.length === 0 || !on.every(t => (SESSION_FACET_TRIGGERS as readonly unknown[]).includes(t)))\n throw new TypeError(`sessions.facets: on must list some of ${SESSION_FACET_TRIGGERS.join(', ')}`)\n return SESSION_FACET_TRIGGERS.filter(t => on.includes(t))\n}\n\n/**\n * Creates an empty facet registry.\n *\n * @param options - `order`: an extension's load-order rank (lower first); `attachHost`: called with the registry when an extension registers or refreshes a facet.\n * @param options.order - The rank of an extension id.\n * @param options.attachHost - Hands the registry to the host that computes facets (`ExtensionSessionControl.attachFacets`), so it hears `refresh` and computes new facets.\n */\nexport function createFacetRegistry(options: { order?: (extensionId: string) => number, attachHost?: (registry: FacetRegistry) => void } = {}): FacetsRuntime {\n const entries = new Map<string, Entry>()\n const listeners = new Set<(change: FacetChange) => void>()\n const refreshers = new Set<(request: FacetRefreshRequest) => void | Promise<void>>()\n const disposeListeners = new Set<() => void>()\n let closed = false\n let seq = 0\n const rank = options.order ?? (() => 0)\n // Assigned once the registry exists; a host that fails to attach computes nothing, which is all it costs.\n let self: FacetRegistry | undefined\n const attachHost = (): void => {\n if (!self || !options.attachHost)\n return\n try {\n options.attachHost(self)\n }\n catch {}\n }\n\n const changed = (change: Partial<FacetChange> = {}): void => {\n if (closed)\n return\n const full: FacetChange = { withdrawn: change.withdrawn ?? [], forgotten: change.forgotten ?? [] }\n for (const listener of [...listeners]) {\n try {\n listener(full)\n }\n catch {}\n }\n }\n const sorted = (): Entry[] => [...entries.values()].sort((a, b) => (rank(a.info.extension) - rank(b.info.extension)) || a.seq - b.seq)\n\n const run = async (entry: Entry, snapshot: SessionSnapshot): Promise<[string, JsonValue] | undefined> => {\n const { deps, spec, info } = entry\n const answer = await deps.guard.call(`sessions.facets.${info.key}`, async () => ({ value: await spec.compute(snapshot) }), { timeoutMs: FACET_COMPUTE_TIMEOUT_MS })\n if (!answer)\n return undefined\n if (answer.value === undefined || answer.value === null)\n return [info.id, null]\n const json = toJson(answer.value)\n const text = json === undefined ? undefined : JSON.stringify(json)\n if (json === undefined || text === undefined) {\n deps.logger.warn(`sessions.facets: ${info.key} answered a value that is not JSON; keeping the last one`)\n return undefined\n }\n if (new TextEncoder().encode(text).length > MAX_FACET_BYTES) {\n deps.logger.warn(`sessions.facets: ${info.key} answered more than ${MAX_FACET_BYTES} bytes; keeping the last one`)\n return undefined\n }\n return [info.id, json as JsonValue]\n }\n\n const register = (deps: DomainDeps, spec: SessionFacetSpec): Disposable => {\n assertAlive(deps.owner, 'sessions.facets.register')\n if (!spec || typeof spec !== 'object')\n throw new TypeError('sessions.facets.register: the spec must be an object')\n if (typeof spec.key !== 'string' || !FACET_KEY.test(spec.key))\n throw new TypeError('sessions.facets.register: key must be a letter or _, then up to 63 letters, digits, _ or -')\n if (typeof spec.compute !== 'function')\n throw new TypeError('sessions.facets.register: compute must be a function')\n const on = triggersOf(spec.on)\n const id = `${deps.extensionId}.${spec.key}`\n if (entries.has(id))\n throw new TypeError(`sessions.facets.register: this extension already has a facet \"${spec.key}\"`)\n if ([...entries.values()].filter(e => e.info.extension === deps.extensionId).length >= MAX_FACETS_PER_EXTENSION)\n throw new RangeError(`sessions.facets.register: at most ${MAX_FACETS_PER_EXTENSION} facets per extension`)\n const entry: Entry = { info: Object.freeze({ id, extension: deps.extensionId, key: spec.key, on: Object.freeze(on) }), spec: { ...spec }, deps, seq: ++seq }\n entries.set(id, entry)\n attachHost()\n changed()\n return track(deps.owner, {\n dispose: () => {\n if (entries.get(id) !== entry)\n return\n entries.delete(id)\n // The extension still loaded (a handle or a scope disposed): withdrawn on purpose. Else it is unloading: values kept.\n changed(extensionAlive(deps.owner) ? { withdrawn: [id] } : {})\n },\n })\n }\n\n const refresh = async (deps: DomainDeps, sessionId: string | undefined): Promise<void> => {\n assertAlive(deps.owner, 'sessions.facets.refresh')\n if (sessionId !== undefined && (typeof sessionId !== 'string' || sessionId.length === 0))\n throw new TypeError('sessions.facets.refresh: sessionId must be a non-empty string')\n const request: FacetRefreshRequest = { extension: deps.extensionId, ...(sessionId !== undefined ? { sessionId } : {}) }\n attachHost()\n await Promise.all([...refreshers].map(async (handler) => {\n try {\n await handler(request)\n }\n catch (err) {\n deps.logger.warn('sessions.facets.refresh: the host failed to refresh', { error: err instanceof Error ? err.message : String(err) })\n }\n }))\n }\n\n const registry: FacetsRuntime = {\n list: () => sorted().map(e => e.info),\n compute: async (session, triggers, opts = {}) => {\n const wanted = triggers === undefined ? undefined : typeof triggers === 'string' ? new Set([triggers]) : triggers\n const due = sorted().filter(e => (wanted === undefined || e.info.on.some(t => wanted.has(t))) && (opts.extension === undefined || e.info.extension === opts.extension))\n if (due.length === 0)\n return {}\n const base = structuredClone(session)\n // One snapshot per extension: its own slice of `metadata.extensions` only.\n const snapshots = new Map<string, SessionSnapshot>()\n const snapshotFor = (extension: string): SessionSnapshot => {\n let snapshot = snapshots.get(extension)\n if (!snapshot)\n snapshots.set(extension, snapshot = deepFreeze({ ...base, metadata: metadataForExtension(base.metadata, extension) }))\n return snapshot\n }\n const results = await Promise.all(due.map(e => run(e, snapshotFor(e.info.extension))))\n return Object.fromEntries(results.filter((r): r is [string, JsonValue] => r !== undefined))\n },\n subscribe: (listener) => {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n onRefresh: (handler) => {\n refreshers.add(handler)\n return () => {\n refreshers.delete(handler)\n }\n },\n disposed: () => closed,\n onDispose: (listener) => {\n if (closed) {\n listener()\n return () => {}\n }\n disposeListeners.add(listener)\n return () => {\n disposeListeners.delete(listener)\n }\n },\n warn: (extension, message) => {\n const entry = [...entries.values()].find(e => e.info.extension === extension)\n entry?.deps.logger.warn(message)\n },\n close: () => {\n if (closed)\n return\n closed = true\n listeners.clear()\n refreshers.clear()\n for (const listener of [...disposeListeners]) {\n try {\n listener()\n }\n catch {}\n }\n disposeListeners.clear()\n },\n forget: (extensionId) => {\n changed({ forgotten: [extensionId] })\n },\n domain: deps => ({\n register: spec => register(deps, spec),\n refresh: sessionId => refresh(deps, sessionId),\n }),\n }\n self = registry\n return registry\n}\n","/**\n * The host port of the extension storage domain: where kv entries and store records\n * live, and how changes made elsewhere (another window, client or process)\n * come back. The domain keeps a synchronous cache over it; the port only\n * moves data.\n */\n\nimport type { Disposable } from '../api/core'\nimport type { Json, StorageScope } from '../api/storage'\n\n/** One storage file: an extension's data in one scope (and session). */\nexport interface StorageLocation {\n /** The owning extension. */\n readonly extensionId: string\n /** `user`, `project` or `session`. */\n readonly scope: StorageScope\n /** Set exactly when `scope` is `'session'`. */\n readonly sessionId?: string\n}\n\n/** The two key spaces of a location: `ctx.storage.kv` entries and typed store records. */\nexport type StorageArea = 'kv' | 'stores'\n\n/** Everything stored at one location. */\nexport interface StorageSnapshot {\n /** kv entries by key. */\n readonly kv: Readonly<Record<string, Json>>\n /** Store records (`{ v, value }`) by store name. */\n readonly stores: Readonly<Record<string, Json>>\n}\n\n/** A change the port saw that this process did not make. `value: undefined` is a delete. */\nexport interface StorageChange {\n /** Which key space changed. */\n readonly area: StorageArea\n /** The kv key or store name. */\n readonly key: string\n /** The new value, or `undefined` when the entry was removed. */\n readonly value: Json | undefined\n}\n\n/** Persistence and sync for the storage domain. Implemented per host (file, IPC, protocol). */\nexport interface StoragePort {\n /** Reads everything at `loc`. A missing location is an empty snapshot. */\n load: (loc: StorageLocation) => Promise<StorageSnapshot>\n /** Writes one entry. */\n save: (loc: StorageLocation, area: StorageArea, key: string, value: Json) => Promise<void>\n /** Removes one entry. Removing a missing entry is a no-op. */\n delete: (loc: StorageLocation, area: StorageArea, key: string) => Promise<void>\n /**\n * Calls `listener` for changes made by others (not through this port's own\n * `save` / `delete`). Echoes are harmless: the domain drops a change that\n * matches what it already holds.\n */\n subscribe: (loc: StorageLocation, listener: (change: StorageChange) => void) => Disposable\n /**\n * The folder this port keeps one extension's data of `scope` in\n * (`project` covers sessions). `storage.path` puts the extension's files\n * under it. Absent (a port with no folders): `<dataDir>/extension-storage`\n * and `<projectRoot>/<prefix>/extension-storage` (`./paths`).\n */\n folderOf?: (extensionId: string, scope: 'user' | 'project') => string\n}\n\n/** A stable string id for a location, for maps and file names. */\nexport function locationKey(loc: StorageLocation): string {\n return loc.scope === 'session' ? `${loc.extensionId}\\u0000session\\u0000${loc.sessionId ?? ''}` : `${loc.extensionId}\\u0000${loc.scope}`\n}\n","/**\n * The synchronous cache behind `ctx.storage`: one state per location,\n * loaded from the {@link StoragePort}, updated by local writes and remote\n * changes. A change equal to what the cache holds is dropped, so each\n * change reaches kv subscribers and store handlers once and the port's\n * echoes of this process's own writes are silent.\n */\n\nimport type { Logger } from '../../logger'\nimport type { Disposable } from '../api/core'\nimport type { Json, StorageScope } from '../api/storage'\nimport type { DomainDeps } from '../runtime/deps'\nimport type { StorageArea, StorageChange, StorageLocation, StoragePort } from './port'\nimport { DisposedError } from '../api/core'\nimport { isTornDown, onTeardown } from '../runtime/owner'\nimport { isSafeRecordKey } from '../shared'\nimport { deepEqual, frozenCopy, isJson } from './json'\nimport { locationKey } from './port'\n\n/** The cached data and listeners of one location. */\nexport interface LocationState {\n /** Where the data lives. */\n readonly loc: StorageLocation\n /** Cached entries (frozen) by area and key. */\n readonly entries: Record<StorageArea, Map<string, Json>>\n /** Local writes not yet confirmed by the port, by area and key. A load must not undo them. */\n readonly pending: Record<StorageArea, Map<string, number>>\n /** `kv.subscribe` listeners. */\n readonly kvListeners: Set<(change: { key: string, value: Json | undefined }) => void>\n /** Store decoders by store name; called with the new record. */\n readonly storeHandlers: Map<string, (raw: Json | undefined) => void>\n /** `true` after the first successful load. */\n loaded: boolean\n /** The load in flight. */\n loading?: Promise<void>\n /** The port subscription for remote changes. */\n subscription?: Disposable\n}\n\n/** The cache shared by kv handles and stores of one extension. */\nexport interface StorageCache {\n /** Logger tagged with the extension and domain. */\n readonly logger: Logger\n /** Throws {@link DisposedError} once the owner is disposed. */\n assertLive: (what: string) => void\n /** The location for `scope`; `'session'` falls back to the current session. */\n resolve: (scope: StorageScope, sessionId: string | undefined, what: string) => StorageLocation\n /** The state of `loc`, created and subscribed to the port on first use. */\n stateFor: (loc: StorageLocation) => LocationState\n /** Loads `state` from the port. `fresh` starts a new read even when one is in flight. */\n load: (state: LocationState, fresh: boolean) => Promise<void>\n /** Starts a background load when the location was never loaded. */\n ensureLoaded: (state: LocationState) => void\n /** Puts one entry in the cache, then saves it through the port; rolls back on failure. */\n write: (state: LocationState, area: StorageArea, key: string, value: Json | undefined, notify: boolean) => Promise<void>\n}\n\n/**\n * Builds the cache of one extension. Disposing the owner drops every\n * listener and port subscription.\n *\n * @param deps - Extension id, owner, guard and logger.\n * @param port - Persistence and remote changes.\n * @param currentSessionId - The session a `'session'` call without an id uses.\n */\nexport function createStorageCache(deps: DomainDeps, port: StoragePort, currentSessionId?: () => string | undefined): StorageCache {\n const { extensionId, owner, guard } = deps\n const logger = deps.logger.with({ extension: extensionId, domain: 'storage' })\n const states = new Map<string, LocationState>()\n\n // Storage serves the calls still in flight after an unload: dropped at teardown.\n onTeardown(owner, () => {\n for (const state of states.values()) {\n state.subscription?.dispose()\n state.kvListeners.clear()\n state.storeHandlers.clear()\n }\n states.clear()\n })\n\n function assertLive(what: string): void {\n if (isTornDown(owner))\n throw new DisposedError(`storage.${what}`)\n }\n\n function resolve(scope: StorageScope, sessionId: string | undefined, what: string): StorageLocation {\n if (scope !== 'session')\n return { extensionId, scope }\n const id = sessionId ?? currentSessionId?.()\n if (typeof id !== 'string' || id.length === 0)\n throw new Error(`storage.${what}('session'): no current session; pass a sessionId`)\n return { extensionId, scope, sessionId: id }\n }\n\n function stateFor(loc: StorageLocation): LocationState {\n const key = locationKey(loc)\n const existing = states.get(key)\n if (existing)\n return existing\n const state: LocationState = {\n loc,\n entries: { kv: new Map(), stores: new Map() },\n pending: { kv: new Map(), stores: new Map() },\n kvListeners: new Set(),\n storeHandlers: new Map(),\n loaded: false,\n }\n states.set(key, state)\n try {\n state.subscription = port.subscribe(loc, change => onRemote(state, change))\n }\n catch (err) {\n logger.warn('storage: port.subscribe failed; remote changes will not arrive', { scope: loc.scope, error: String(err) })\n }\n return state\n }\n\n function onRemote(state: LocationState, change: StorageChange): void {\n if (isTornDown(owner) || !isSafeRecordKey(change.key))\n return\n if (change.value !== undefined && !isJson(change.value)) {\n logger.warn('storage: ignored a non-JSON remote value', { key: change.key })\n return\n }\n apply(state, change.area, change.key, change.value, true)\n }\n\n function apply(state: LocationState, area: StorageArea, key: string, value: Json | undefined, notify: boolean): void {\n const map = state.entries[area]\n if (deepEqual(map.get(key), value))\n return\n if (value === undefined)\n map.delete(key)\n else\n map.set(key, frozenCopy(value))\n if (!notify)\n return\n const stored = map.get(key)\n if (area === 'stores') {\n state.storeHandlers.get(key)?.(stored)\n return\n }\n for (const listener of [...state.kvListeners])\n guard.callSync('storage.kv.subscribe', () => listener({ key, value: stored }))\n }\n\n async function read(state: LocationState): Promise<void> {\n const snapshot = await port.load(state.loc)\n if (isTornDown(owner))\n return\n for (const area of ['kv', 'stores'] as const) {\n const incoming = snapshot[area] ?? {}\n const keys = new Set([...state.entries[area].keys(), ...Object.keys(incoming)])\n for (const key of keys) {\n if (!isSafeRecordKey(key) || state.pending[area].has(key))\n continue\n const value = Object.hasOwn(incoming, key) ? incoming[key] : undefined\n if (value === undefined || isJson(value))\n apply(state, area, key, value, true)\n }\n }\n state.loaded = true\n }\n\n function load(state: LocationState, fresh: boolean): Promise<void> {\n if (state.loading && !fresh)\n return state.loading\n // A fresh load starts after the one in flight, so it sees data written since that one read.\n const loading = (state.loading ? state.loading.catch(() => {}) : Promise.resolve()).then(() => read(state))\n state.loading = loading\n void loading.catch(() => {}).finally(() => {\n if (state.loading === loading)\n state.loading = undefined\n })\n return loading\n }\n\n function ensureLoaded(state: LocationState): void {\n if (state.loaded || state.loading)\n return\n load(state, false).catch((err) => {\n logger.warn('storage: load failed', { scope: state.loc.scope, error: String(err) })\n })\n }\n\n async function write(state: LocationState, area: StorageArea, key: string, value: Json | undefined, notify: boolean): Promise<void> {\n const previous = state.entries[area].get(key)\n apply(state, area, key, value, notify)\n const pending = state.pending[area]\n pending.set(key, (pending.get(key) ?? 0) + 1)\n try {\n if (value === undefined)\n await port.delete(state.loc, area, key)\n else\n await port.save(state.loc, area, key, value)\n }\n catch (err) {\n // Roll back unless a later write already replaced this value.\n if (!isTornDown(owner) && deepEqual(state.entries[area].get(key), value))\n apply(state, area, key, previous, true)\n throw err\n }\n finally {\n const left = (pending.get(key) ?? 1) - 1\n if (left > 0)\n pending.set(key, left)\n else\n pending.delete(key)\n }\n }\n\n return { logger, assertLive, resolve, stateFor, load, ensureLoaded, write }\n}\n","/**\n * Where `ctx.storage.path` puts an extension's files, and the move from the\n * folders earlier builds used.\n *\n * Files live next to the extension's kv entries and stores, in the folders of\n * the storage port (`StoragePort.folderOf`), so every host puts them where\n * it keeps the rest of the extension's data:\n *\n * user, data <dataDir>/extension-storage/<id>/files\n * project, session <projectRoot>/<prefix>/extension-storage/<id>/files\n * cache <cacheDir>/extension-storage/<id>\n *\n * Earlier builds used `<base>/extensions/<id>` ({@link legacyStoragePath}),\n * which is also where extensions are installed (`~/.zidane/extensions/<id>`),\n * or a project's own `extensions/<id>` source folder. A call finds the files\n * it asks for where they were and moves them ({@link resolveStoragePath}):\n * never an install file.\n */\n\nimport type { Logger } from '../../logger'\nimport type { ExtensionPaths } from '../api/core'\nimport type { StoragePathScope } from '../api/storage'\nimport { cpSync, existsSync, mkdirSync, readdirSync, renameSync, rmdirSync, rmSync } from 'node:fs'\nimport { dirname, join, relative, resolve, sep } from 'node:path'\n\n/** The folder a storage port keeps one extension's data of `scope` in (`StoragePort.folderOf`). */\nexport type StorageFolderOf = (extensionId: string, scope: 'user' | 'project') => string\n\n/** What {@link resolveStoragePath} needs to know about the extension. */\nexport interface StoragePathOptions {\n /** The host's paths (`ctx.paths`). */\n readonly paths: ExtensionPaths\n /** The extension id. */\n readonly extensionId: string\n /** The storage port's folders. Default: `<dataDir>/extension-storage` and `<projectRoot>/<prefix>/extension-storage`. */\n readonly folderOf?: StorageFolderOf\n /** The extension's own folder: nothing is ever moved out of it but files it asked for. */\n readonly dir?: string\n /** Receives a move that failed. */\n readonly logger?: Logger\n}\n\n/** The resolved `target` under `root`, or `root` itself when `..` segments would leave it. */\nfunction inside(root: string, segments: readonly string[]): string {\n const target = resolve(root, ...segments)\n return target === root || target.startsWith(root + sep) ? target : root\n}\n\nfunction defaultFolderOf(paths: ExtensionPaths): StorageFolderOf {\n return (extensionId, scope) => {\n const prefix = process.env.ZIDANE_PREFIX ?? '.zidane'\n const base = scope === 'project' && paths.projectRoot ? join(paths.projectRoot, prefix, 'extension-storage') : join(paths.dataDir, 'extension-storage')\n return join(base, encodeURIComponent(extensionId))\n }\n}\n\n/**\n * The folder `storage.path(scope)` resolves in.\n *\n * @param options - The extension and the port's folders.\n * @param scope - The storage area.\n */\nexport function storagePathRoot(options: Pick<StoragePathOptions, 'paths' | 'extensionId' | 'folderOf'>, scope: StoragePathScope): string {\n if (scope === 'cache')\n return resolve(options.paths.cacheDir, 'extension-storage', encodeURIComponent(options.extensionId))\n const folderOf = options.folderOf ?? defaultFolderOf(options.paths)\n return resolve(folderOf(options.extensionId, scope === 'project' || scope === 'session' ? 'project' : 'user'), 'files')\n}\n\n/**\n * Where `storage.path` resolved before it moved to the storage folders:\n * `<base>/extensions/<id>`, `base` the cache dir, the data dir, the project\n * root (project, session) or the config dir (user), else the data dir.\n *\n * @param paths - The host's paths.\n * @param extensionId - The extension id.\n * @param scope - The storage area.\n * @param segments - Path segments under the folder.\n */\nexport function legacyStoragePath(paths: ExtensionPaths, extensionId: string, scope: StoragePathScope, ...segments: string[]): string {\n const base = scope === 'cache'\n ? paths.cacheDir\n : scope === 'data'\n ? paths.dataDir\n : scope === 'project' || scope === 'session'\n ? (paths.projectRoot ?? paths.dataDir)\n : (paths.configDir ?? paths.dataDir)\n return inside(resolve(base, 'extensions', extensionId), segments)\n}\n\n/** Files that make a folder an extension's install (or source) folder. */\nconst INSTALL_MARKERS = ['index.ts', 'index.tsx', 'index.mjs', 'index.js', 'extension.json', 'package.json', '.install.json']\n/** Entries of an install folder that are the extension, not its data. */\nconst INSTALL_ENTRIES = new Set([...INSTALL_MARKERS, 'node_modules', 'src', 'dist', 'tsconfig.json', 'bun.lock', 'bun.lockb', 'package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'README.md', 'LICENSE', 'CHANGELOG.md'])\nconst SOURCE_FILE = /\\.(?:[cm]?[jt]sx?|d\\.ts)$/\n\nfunction isInstallFolder(folder: string, dir: string | undefined): boolean {\n return (dir !== undefined && resolve(dir) === folder) || INSTALL_MARKERS.some(name => existsSync(join(folder, name)))\n}\n\nfunction isInstallEntry(name: string): boolean {\n return INSTALL_ENTRIES.has(name) || SOURCE_FILE.test(name) || name.startsWith('.')\n}\n\n/** Moves a file or folder, copying when it crosses file systems. */\nfunction move(from: string, to: string): void {\n mkdirSync(dirname(to), { recursive: true })\n try {\n renameSync(from, to)\n }\n catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EXDEV')\n throw err\n cpSync(from, to, { recursive: true, errorOnExist: true, force: false })\n rmSync(from, { recursive: true, force: true })\n }\n}\n\n/** Old folders already merged in this process (the ones that hold data only). */\nconst merged = new Set<string>()\n\n/**\n * Moves what the old folder of `scope` holds for this call. An install (or\n * source) folder gives up only the top entry the call names, when it is not\n * part of the extension and the new folder lacks it; any other old folder\n * moves whole, entry by entry, keeping what the new folder already has.\n * Throws when a move fails.\n */\nfunction migrate(options: StoragePathOptions, scope: StoragePathScope, root: string, target: string): void {\n const legacy = legacyStoragePath(options.paths, options.extensionId, scope)\n if (legacy === root || !existsSync(legacy))\n return\n if (isInstallFolder(legacy, options.dir)) {\n const name = target === root ? undefined : relative(root, target).split(sep)[0]\n if (!name || isInstallEntry(name))\n return\n const from = join(legacy, name)\n const to = join(root, name)\n if (!existsSync(to) && existsSync(from))\n move(from, to)\n return\n }\n const key = `${legacy}\\u0000${root}`\n if (merged.has(key))\n return\n merged.add(key)\n for (const name of readdirSync(legacy)) {\n const to = join(root, name)\n if (!existsSync(to))\n move(join(legacy, name), to)\n }\n try {\n rmdirSync(legacy)\n }\n catch {} // Something stayed (an entry the new folder already had): left in place.\n}\n\n/**\n * `storage.path(scope, ...segments)`: a path in the extension's folder for\n * `scope` ({@link storagePathRoot}); `..` cannot leave it. Files an earlier\n * build left in the old folder are moved first. When that fails, the old\n * path is returned while the file is only there, so no data goes missing.\n *\n * @param options - The extension, the port's folders, its own folder and a logger.\n * @param scope - The storage area.\n * @param segments - Path segments under the folder.\n */\nexport function resolveStoragePath(options: StoragePathOptions, scope: StoragePathScope, ...segments: string[]): string {\n const root = storagePathRoot(options, scope)\n const target = inside(root, segments)\n // The cache is disposable: a new folder starts empty.\n if (scope === 'cache')\n return target\n try {\n migrate(options, scope, root, target)\n }\n catch (err) {\n options.logger?.warn('storage.path: could not move files from the old folder', { scope, error: String(err) })\n const old = legacyStoragePath(options.paths, options.extensionId, scope, ...segments)\n if (!existsSync(target) && existsSync(old))\n return old\n }\n return target\n}\n","/**\n * A synchronous validator for plain JSON Schema (draft-07 and 2020-12\n * basics), used by RPC and storage when an extension passes a JSON Schema\n * instead of a Standard Schema. zod's `fromJSONSchema` would need an async\n * import of an optional peer and refuses `not`, so the checks live here.\n *\n * Supported: boolean schemas, `type` (one or a list, `integer`),\n * `enum`, `const`, `properties`, `required`, `additionalProperties`,\n * `patternProperties`, `propertyNames`, `minProperties`/`maxProperties`,\n * `items` (a schema, or a tuple in draft-07), `prefixItems`,\n * `additionalItems`, `contains`, `minItems`/`maxItems`, `uniqueItems`,\n * `minLength`/`maxLength`, `pattern`, `minimum`/`maximum`,\n * `exclusiveMinimum`/`exclusiveMaximum` (number and draft-04 boolean\n * forms), `multipleOf`, `anyOf`/`oneOf`/`allOf`/`not`,\n * `if`/`then`/`else`, local `$ref` (`#`, `#/definitions/…`,\n * `#/$defs/…`). `format` and unknown keywords are ignored.\n */\n\ntype JsonSchemaNode = boolean | Readonly<Record<string, unknown>>\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value))\n return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * The JSON type name of a value (`null`, `array`, `object`, `string`, …).\n *\n * @param value - Any value.\n */\nexport function jsonTypeOf(value: unknown): string {\n if (value === null)\n return 'null'\n if (Array.isArray(value))\n return 'array'\n return typeof value\n}\n\nfunction matchesType(value: unknown, type: string): boolean {\n switch (type) {\n case 'integer': return Number.isInteger(value)\n case 'number': return typeof value === 'number' && Number.isFinite(value)\n case 'object': return isRecord(value)\n default: return jsonTypeOf(value) === type\n }\n}\n\n/**\n * Deep equality over JSON values (`enum`, `const`, `uniqueItems`).\n *\n * @param a - A JSON value.\n * @param b - Another JSON value.\n */\nexport function jsonEqual(a: unknown, b: unknown): boolean {\n if (a === b)\n return true\n if (Array.isArray(a))\n return Array.isArray(b) && a.length === b.length && a.every((item, i) => jsonEqual(item, b[i]))\n if (isRecord(a) && isRecord(b)) {\n const keys = Object.keys(a)\n return keys.length === Object.keys(b).length && keys.every(key => Object.hasOwn(b, key) && jsonEqual(a[key], b[key]))\n }\n return false\n}\n\nfunction codePoints(text: string): number {\n let n = 0\n for (const _ of text)\n n++\n return n\n}\n\nconst patternCache = new Map<string, RegExp | null>()\nfunction compile(pattern: string): RegExp | null {\n let re = patternCache.get(pattern)\n if (re === undefined) {\n try {\n re = new RegExp(pattern, 'u')\n }\n catch {\n re = null\n }\n patternCache.set(pattern, re)\n }\n return re\n}\n\n/** A pattern that does not compile refuses nothing: the schema is at fault, not the value. */\nfunction testPattern(pattern: string, text: string): boolean {\n const re = compile(pattern)\n return re === null || re.test(text)\n}\n\nfunction resolveRef(root: JsonSchemaNode, ref: string): JsonSchemaNode | undefined {\n if (ref === '#')\n return root\n if (!ref.startsWith('#/'))\n return undefined\n let node: unknown = root\n for (const raw of ref.slice(2).split('/')) {\n const part = decodeURIComponent(raw).replace(/~1/g, '/').replace(/~0/g, '~')\n if (!isRecord(node) && !Array.isArray(node))\n return undefined\n node = (node as Record<string, unknown>)[part]\n }\n return typeof node === 'boolean' || isRecord(node) ? node : undefined\n}\n\nconst at = (path: string, key: string | number): string => (path ? `${path}.${key}` : String(key))\nconst prefixed = (path: string, message: string): string => (path ? `${path}: ${message}` : message)\n\ninterface Walk {\n root: JsonSchemaNode\n depth: number\n}\n\nconst MAX_DEPTH = 64\n\nfunction walk(schema: JsonSchemaNode, value: unknown, path: string, w: Walk): string | undefined {\n if (schema === true)\n return undefined\n if (schema === false)\n return prefixed(path, 'no value is allowed here')\n if (w.depth > MAX_DEPTH)\n return prefixed(path, 'the schema nests too deeply')\n const s = schema\n const deeper: Walk = { root: w.root, depth: w.depth + 1 }\n\n if (typeof s.$ref === 'string') {\n const target = resolveRef(w.root, s.$ref)\n if (target === undefined)\n return prefixed(path, `unresolvable $ref \"${s.$ref}\"`)\n const err = walk(target, value, path, deeper)\n if (err)\n return err\n }\n\n if (s.type !== undefined) {\n const types = Array.isArray(s.type) ? s.type.map(String) : [String(s.type)]\n const nullable = s.nullable === true && value === null\n if (!nullable && !types.some(type => matchesType(value, type)))\n return prefixed(path, `expected ${types.join(' or ')}, got ${jsonTypeOf(value)}`)\n }\n if (Array.isArray(s.enum) && !s.enum.some(option => jsonEqual(option, value)))\n return prefixed(path, `expected one of ${JSON.stringify(s.enum)}`)\n if (Object.hasOwn(s, 'const') && !jsonEqual(s.const, value))\n return prefixed(path, `expected ${JSON.stringify(s.const)}`)\n\n if (typeof value === 'number') {\n const err = checkNumber(s, value)\n if (err)\n return prefixed(path, err)\n }\n if (typeof value === 'string') {\n const length = codePoints(value)\n if (typeof s.minLength === 'number' && length < s.minLength)\n return prefixed(path, `must be at least ${s.minLength} characters`)\n if (typeof s.maxLength === 'number' && length > s.maxLength)\n return prefixed(path, `must be at most ${s.maxLength} characters`)\n if (typeof s.pattern === 'string' && !testPattern(s.pattern, value))\n return prefixed(path, `must match ${s.pattern}`)\n }\n if (Array.isArray(value)) {\n const err = checkArray(s, value, path, deeper)\n if (err)\n return err\n }\n if (isRecord(value)) {\n const err = checkObject(s, value, path, deeper)\n if (err)\n return err\n }\n return checkCombinators(s, value, path, deeper)\n}\n\nfunction checkNumber(s: Readonly<Record<string, unknown>>, value: number): string | undefined {\n const exMin = s.exclusiveMinimum\n const exMax = s.exclusiveMaximum\n if (typeof s.minimum === 'number' && (exMin === true ? value <= s.minimum : value < s.minimum))\n return `must be ${exMin === true ? 'greater than' : 'at least'} ${s.minimum}`\n if (typeof s.maximum === 'number' && (exMax === true ? value >= s.maximum : value > s.maximum))\n return `must be ${exMax === true ? 'less than' : 'at most'} ${s.maximum}`\n if (typeof exMin === 'number' && value <= exMin)\n return `must be greater than ${exMin}`\n if (typeof exMax === 'number' && value >= exMax)\n return `must be less than ${exMax}`\n if (typeof s.multipleOf === 'number' && s.multipleOf > 0) {\n const q = value / s.multipleOf\n if (Math.abs(q - Math.round(q)) > 1e-9)\n return `must be a multiple of ${s.multipleOf}`\n }\n return undefined\n}\n\nfunction asNode(value: unknown): JsonSchemaNode | undefined {\n return typeof value === 'boolean' || isRecord(value) ? value : undefined\n}\n\nfunction checkArray(s: Readonly<Record<string, unknown>>, value: readonly unknown[], path: string, w: Walk): string | undefined {\n if (typeof s.minItems === 'number' && value.length < s.minItems)\n return prefixed(path, `must have at least ${s.minItems} items`)\n if (typeof s.maxItems === 'number' && value.length > s.maxItems)\n return prefixed(path, `must have at most ${s.maxItems} items`)\n if (s.uniqueItems === true) {\n for (let i = 0; i < value.length; i++) {\n for (let j = i + 1; j < value.length; j++) {\n if (jsonEqual(value[i], value[j]))\n return prefixed(path, `items ${i} and ${j} are equal`)\n }\n }\n }\n // Tuple: 2020-12 `prefixItems` + `items`, or draft-07 array `items` + `additionalItems`.\n const tuple = Array.isArray(s.prefixItems) ? s.prefixItems : Array.isArray(s.items) ? s.items : undefined\n const rest = Array.isArray(s.prefixItems) ? asNode(s.items) : Array.isArray(s.items) ? asNode(s.additionalItems) : asNode(s.items)\n for (let i = 0; i < value.length; i++) {\n const itemSchema = tuple && i < tuple.length ? asNode(tuple[i]) : rest\n if (itemSchema === undefined)\n continue\n const err = walk(itemSchema, value[i], at(path, i), w)\n if (err)\n return err\n }\n const contains = asNode(s.contains)\n if (contains !== undefined) {\n const hits = value.filter(item => walk(contains, item, '', w) === undefined).length\n const min = typeof s.minContains === 'number' ? s.minContains : 1\n if (hits < min)\n return prefixed(path, min === 1 ? 'no item matches `contains`' : `fewer than ${min} items match \\`contains\\``)\n if (typeof s.maxContains === 'number' && hits > s.maxContains)\n return prefixed(path, `more than ${s.maxContains} items match \\`contains\\``)\n }\n return undefined\n}\n\nfunction checkObject(s: Readonly<Record<string, unknown>>, value: Readonly<Record<string, unknown>>, path: string, w: Walk): string | undefined {\n const keys = Object.keys(value)\n if (Array.isArray(s.required)) {\n for (const key of s.required) {\n if (typeof key === 'string' && !Object.hasOwn(value, key))\n return prefixed(at(path, key), 'is required')\n }\n }\n if (typeof s.minProperties === 'number' && keys.length < s.minProperties)\n return prefixed(path, `must have at least ${s.minProperties} properties`)\n if (typeof s.maxProperties === 'number' && keys.length > s.maxProperties)\n return prefixed(path, `must have at most ${s.maxProperties} properties`)\n const properties = isRecord(s.properties) ? s.properties : {}\n const patterns = isRecord(s.patternProperties) ? Object.entries(s.patternProperties) : []\n const additional = asNode(s.additionalProperties)\n const names = asNode(s.propertyNames)\n for (const key of keys) {\n if (names !== undefined) {\n const err = walk(names, key, '', w)\n if (err)\n return prefixed(at(path, key), `invalid property name: ${err}`)\n }\n let matched = false\n if (Object.hasOwn(properties, key)) {\n matched = true\n const sub = asNode(properties[key])\n const err = sub === undefined ? undefined : walk(sub, value[key], at(path, key), w)\n if (err)\n return err\n }\n for (const [pattern, raw] of patterns) {\n if (!testPattern(pattern, key) || compile(pattern) === null)\n continue\n matched = true\n const sub = asNode(raw)\n const err = sub === undefined ? undefined : walk(sub, value[key], at(path, key), w)\n if (err)\n return err\n }\n if (!matched && additional !== undefined) {\n if (additional === false)\n return prefixed(at(path, key), 'is not allowed')\n const err = walk(additional, value[key], at(path, key), w)\n if (err)\n return err\n }\n }\n return undefined\n}\n\nfunction checkCombinators(s: Readonly<Record<string, unknown>>, value: unknown, path: string, w: Walk): string | undefined {\n const list = (raw: unknown): JsonSchemaNode[] => (Array.isArray(raw) ? raw.map(asNode).filter((n): n is JsonSchemaNode => n !== undefined) : [])\n for (const sub of list(s.allOf)) {\n const err = walk(sub, value, path, w)\n if (err)\n return err\n }\n const anyOf = list(s.anyOf)\n if (anyOf.length > 0) {\n const errors = anyOf.map(sub => walk(sub, value, path, w))\n if (errors.every(Boolean))\n return errors.length === 1 ? errors[0] : prefixed(path, `matches none of anyOf (${errors.map(e => e!).join(' | ')})`)\n }\n const oneOf = list(s.oneOf)\n if (oneOf.length > 0) {\n const errors = oneOf.map(sub => walk(sub, value, path, w))\n const passing = errors.filter(e => e === undefined).length\n if (passing === 0)\n return prefixed(path, `matches none of oneOf (${errors.map(e => e!).join(' | ')})`)\n if (passing > 1)\n return prefixed(path, `matches ${passing} of oneOf, expected exactly one`)\n }\n const not = asNode(s.not)\n if (not !== undefined && walk(not, value, path, w) === undefined)\n return prefixed(path, 'matches a schema it must not match')\n const cond = asNode(s.if)\n if (cond !== undefined) {\n const branch = asNode(walk(cond, value, path, w) === undefined ? s.then : s.else)\n if (branch !== undefined) {\n const err = walk(branch, value, path, w)\n if (err)\n return err\n }\n }\n return undefined\n}\n\n/**\n * Checks `value` against a plain JSON Schema.\n *\n * @param schema - The JSON Schema (an object, or `true`/`false`).\n * @param value - The value to check.\n * @returns The first problem found, as `path: message`, or `undefined` when the value is valid.\n * @example\n * validateJsonSchema({ type: 'object', properties: { name: { type: 'string' } } }, { name: 4 })\n * // 'name: expected string, got number'\n */\nexport function validateJsonSchema(schema: JsonSchemaNode, value: unknown): string | undefined {\n return walk(schema, value, '', { root: schema, depth: 0 })\n}\n","/**\n * Validates RPC inputs, outputs, error data and event data against a\n * {@link Schema}: a Standard Schema (zod, valibot, arktype) through its own\n * `~standard.validate`, or a plain JSON Schema: loosely typed object fields\n * are coerced first (the loop's `validateToolArgs`, `src/tools/validation.ts`),\n * then the value is checked in full (`./json-schema`).\n */\n\nimport type { Schema } from '../api/core'\nimport { validateToolArgs } from '../../tools/validation'\nimport { isStandardSchema } from '../../zod'\nimport { jsonTypeOf, validateJsonSchema } from './json-schema'\n\n/** The outcome of a check. `value` is the validated (possibly transformed or coerced) value. */\nexport type SchemaCheck = { ok: true, value: unknown } | { ok: false, message: string }\n\ninterface StandardIssue { message: string, path?: ReadonlyArray<PropertyKey | { key: PropertyKey }> }\ntype StandardResult = { value: unknown, issues?: undefined } | { issues: readonly StandardIssue[] }\ntype StandardValidate = (value: unknown) => StandardResult | Promise<StandardResult>\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value))\n return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\nfunction formatIssues(issues: readonly StandardIssue[]): string {\n return issues.map((issue) => {\n const path = (issue.path ?? []).map(part => String(typeof part === 'object' ? part.key : part)).join('.')\n return path ? `${path}: ${issue.message}` : issue.message\n }).join('; ')\n}\n\nfunction fromStandard(result: StandardResult): SchemaCheck {\n return result.issues ? { ok: false, message: formatIssues(result.issues) } : { ok: true, value: result.value }\n}\n\n/**\n * Checks `value` against a plain JSON Schema: an object's loosely typed\n * fields (a numeric string for a number) are coerced first, then the whole\n * value is validated (`./json-schema`).\n *\n * @param schema - The JSON Schema.\n * @param value - The value to check.\n * @param opts - `coerceAny`: coerce a value that is not an object too (storage does, RPC does not).\n * @param opts.coerceAny - Coerce a value that is not an object too.\n * @returns The check, with the coerced value when it passes.\n */\nexport function checkJsonSchema(schema: Readonly<Record<string, unknown>>, value: unknown, opts: { coerceAny?: boolean } = {}): SchemaCheck {\n const declared = schema.type\n const types = declared === undefined ? [] : Array.isArray(declared) ? declared.map(String) : [String(declared)]\n const objectLike = types.includes('object') || (types.length === 0 && (schema.properties !== undefined || schema.required !== undefined))\n if (objectLike && types.length === 0 && !isPlainObject(value))\n return { ok: false, message: `expected an object, got ${jsonTypeOf(value)}` }\n const isObject = objectLike && isPlainObject(value)\n const candidate = isObject || opts.coerceAny ? coerceLoosely(schema, value, isObject) : value\n const problem = validateJsonSchema(schema, candidate)\n return problem === undefined ? { ok: true, value: candidate } : { ok: false, message: problem }\n}\n\n/**\n * The value with its unambiguous loose fields coerced, as a tool argument\n * would be. A value is wrapped as the single property of an object when it\n * is not one. Coercion that would drop array items is not taken: the\n * original value is then validated and refused, never silently shortened.\n */\nfunction coerceLoosely(schema: Readonly<Record<string, unknown>>, value: unknown, isObject: boolean): unknown {\n const result = isObject\n ? validateToolArgs(value as Record<string, unknown>, schema as Record<string, unknown>)\n : validateToolArgs({ value }, { type: 'object', properties: { value: schema }, required: ['value'] })\n if (!result.valid || (result.droppedItems && Object.keys(result.droppedItems).length > 0))\n return value\n return isObject ? result.coercedInput ?? value : result.coercedInput?.value\n}\n\n/**\n * Checks `value` against `schema`. With no schema every value passes\n * unchanged. Synchronous unless a Standard Schema validates asynchronously.\n *\n * @param schema - Standard Schema, JSON Schema, or `undefined`.\n * @param value - The value to check.\n * @returns The check, or a promise of it.\n */\nexport function checkSchema(schema: Schema | undefined, value: unknown): SchemaCheck | Promise<SchemaCheck> {\n if (schema === undefined)\n return { ok: true, value }\n if (!isStandardSchema(schema))\n return checkJsonSchema(schema, value)\n const validate = (schema['~standard'] as { validate?: StandardValidate }).validate\n if (typeof validate !== 'function')\n return { ok: false, message: 'the schema has no ~standard.validate' }\n try {\n const result = validate(value)\n return result instanceof Promise\n ? result.then(fromStandard, (error: unknown) => ({ ok: false, message: errorMessage(error) }))\n : fromStandard(result)\n }\n catch (error) {\n return { ok: false, message: errorMessage(error) }\n }\n}\n\n/**\n * Whether `value` is a plain object (`{}` or `Object.create(null)`), as event data must be.\n *\n * @param value - The value to check.\n */\nexport function isPlainRecord(value: unknown): value is Record<string, unknown> {\n return isPlainObject(value)\n}\n\n/**\n * The message of a thrown value.\n *\n * @param error - Anything thrown.\n */\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n","/**\n * Store value validation against either schema kind `ctx.storage.store`\n * accepts: a Standard Schema (through its `~standard.validate`) or a plain\n * JSON Schema (loose fields coerced, then checked in full, as RPC does).\n */\n\nimport type { Schema } from '../api/core'\nimport { isStandardSchema } from '../../zod'\nimport { checkJsonSchema } from '../rpc/schema'\n\n/** The outcome of validating one value. `value` is the parsed (possibly coerced or defaulted) value. */\nexport type StoreValidation\n = | { readonly ok: true, readonly value: unknown }\n | { readonly ok: false, readonly error: string }\n\ninterface StandardIssue { readonly message: string, readonly path?: readonly unknown[] }\ntype StandardResult = { readonly value: unknown, readonly issues?: undefined } | { readonly issues: readonly StandardIssue[] }\ninterface StandardValidator {\n readonly '~standard': { readonly validate: (value: unknown) => StandardResult | Promise<StandardResult> }\n}\n\nfunction issueText(issue: StandardIssue): string {\n const path = issue.path?.map(p => (typeof p === 'object' && p !== null && 'key' in p ? String((p as { key: unknown }).key) : String(p))).join('.')\n return path ? `${path}: ${issue.message}` : issue.message\n}\n\nfunction fromStandard(result: StandardResult): StoreValidation {\n if (result.issues)\n return { ok: false, error: result.issues.map(issueText).join('; ') || 'invalid value' }\n return { ok: true, value: result.value }\n}\n\n/**\n * Validates `value` against `schema`. Synchronous for JSON Schema and for\n * Standard Schemas that validate synchronously (zod without async refinements);\n * a Promise otherwise.\n *\n * A JSON Schema value is coerced as a tool argument would be, then checked\n * in full (`checkJsonSchema`).\n *\n * @param schema - Standard Schema or JSON Schema.\n * @param value - Candidate value.\n */\nexport function validateStoreValue(schema: Schema, value: unknown): StoreValidation | Promise<StoreValidation> {\n if (isStandardSchema(schema)) {\n const validate = (schema as unknown as StandardValidator)['~standard'].validate\n if (typeof validate !== 'function')\n return { ok: false, error: 'schema has no ~standard.validate' }\n let result: StandardResult | Promise<StandardResult>\n try {\n result = validate(value)\n }\n catch (err) {\n return { ok: false, error: err instanceof Error ? err.message : String(err) }\n }\n return result instanceof Promise ? result.then(fromStandard, err => ({ ok: false, error: String(err) })) : fromStandard(result)\n }\n if (value === undefined || value === null)\n return schemaAllowsNull(schema) && value === null ? { ok: true, value } : { ok: false, error: 'value is required' }\n if (schema.type === 'object' || (schema.type === undefined && schema.properties !== undefined)) {\n if (typeof value !== 'object' || Array.isArray(value))\n return { ok: false, error: `expected object, got ${Array.isArray(value) ? 'array' : typeof value}` }\n }\n return fromCheck(checkJsonSchema(schema, value, { coerceAny: true }))\n}\n\nfunction fromCheck(check: ReturnType<typeof checkJsonSchema>): StoreValidation {\n return check.ok ? { ok: true, value: check.value } : { ok: false, error: check.message }\n}\n\nfunction schemaAllowsNull(schema: Readonly<Record<string, unknown>>): boolean {\n const type = schema.type\n return type === 'null' || (Array.isArray(type) && type.includes('null'))\n}\n","/**\n * Typed, versioned stores (`ctx.storage.store`). A store keeps one record\n * `{ v, value }` in the `stores` area of its location. Reads are\n * synchronous; an older record is migrated, validated and written back at\n * the current version; an invalid one yields the initial value.\n */\n\nimport type { Infer, Readable, Schema } from '../api/core'\nimport type { Json, Store, StoreOptions } from '../api/storage'\nimport type { Guard } from '../runtime/deps'\nimport type { LocationState, StorageCache } from './cache'\nimport type { StoreValidation } from './validate'\nimport { deepEqual, frozenCopy, isJson } from './json'\nimport { validateStoreValue } from './validate'\n\n/** A store record as kept by the port. */\ninterface StoreRecord { v: number, value: Json }\n\nfunction isStoreRecord(raw: Json): raw is StoreRecord & Json {\n return typeof raw === 'object' && raw !== null && !Array.isArray(raw)\n && typeof (raw as Record<string, Json>).v === 'number' && 'value' in raw\n}\n\n/** Checks the arguments of `store()` that do not depend on stored data; throws on misuse. */\nexport function checkStoreArgs(name: string, schema: Schema, initial: unknown, version: number): void {\n const label = `storage.store(${JSON.stringify(name)})`\n if (!Number.isInteger(version) || version < 1)\n throw new TypeError(`${label}: version must be an integer >= 1`)\n if (!isJson(initial))\n throw new TypeError(`${label}: initial value is not JSON`)\n const checked = validateStoreValue(schema, initial)\n if (!(checked instanceof Promise) && !checked.ok)\n throw new TypeError(`${label}: initial value is invalid: ${checked.error}`)\n}\n\n/**\n * Creates the store `name` at `state` and registers its decoder. Callers\n * dedupe by location and name and check the arguments first.\n *\n * @param cache - The extension's storage cache.\n * @param guard - Runs `migrate` and listeners with error attribution.\n * @param state - The store's location.\n * @param name - The store name (a safe key).\n * @param schema - Standard Schema or JSON Schema of the value.\n * @param initial - The value when nothing valid is stored.\n * @param opts - Version and migration.\n */\nexport function createStore<S extends Schema>(\n cache: StorageCache,\n guard: Guard,\n state: LocationState,\n name: string,\n schema: S,\n initial: Infer<S>,\n opts: StoreOptions<Infer<S>>,\n): Store<Infer<S>> {\n type T = Infer<S>\n const version = opts.version ?? 1\n const initialValue = frozenCopy(initial as Json) as T\n let current = initialValue\n // Bumped by every decode and set: an async validation that finishes after\n // a newer one started is dropped.\n let seq = 0\n const listeners = new Set<(value: T) => void>()\n\n function setCurrent(next: T): void {\n if (deepEqual(current, next))\n return\n current = next\n for (const listener of [...listeners])\n guard.callSync(`storage.store(${name}).subscribe`, () => listener(next))\n }\n\n function fallback(message: string, attrs: Record<string, unknown> = {}): void {\n cache.logger.warn(`storage: ${message}; using the initial value`, { store: name, ...attrs })\n setCurrent(initialValue)\n }\n\n /** Brings an older record to `version`. `undefined` when `migrate` threw. */\n function upgrade(raw: StoreRecord): { value: unknown } | undefined {\n if (!opts.migrate)\n return { value: raw.value }\n const migrate = opts.migrate\n return guard.callSync(`storage.store(${name}).migrate`, () => ({ value: migrate(raw.value, raw.v) as unknown }))\n }\n\n function decode(raw: Json | undefined): void {\n const mine = ++seq\n if (raw === undefined)\n return setCurrent(initialValue)\n if (!isStoreRecord(raw))\n return fallback('unreadable store record')\n if (raw.v > version)\n return fallback('store was saved by a newer version of the extension', { stored: raw.v, version })\n const upgraded = raw.v < version ? upgrade(raw) : { value: raw.value }\n if (!upgraded)\n return fallback('migration failed')\n const finish = (result: StoreValidation): void => {\n if (mine !== seq)\n return\n if (!result.ok || !isJson(result.value))\n return fallback('stored value is invalid', { error: result.ok ? 'not JSON' : result.error })\n setCurrent(frozenCopy(result.value) as T)\n if (raw.v < version) {\n cache.write(state, 'stores', name, { v: version, value: result.value }, false).catch((err) => {\n cache.logger.warn('storage: could not save the migrated store', { store: name, error: String(err) })\n })\n }\n }\n const checked = validateStoreValue(schema, upgraded.value)\n if (checked instanceof Promise)\n void checked.then(finish)\n else\n finish(checked)\n }\n\n const subscribe = (listener: (value: T) => void): (() => void) => {\n listeners.add(listener)\n return () => void listeners.delete(listener)\n }\n\n const created: Store<T> = {\n get: () => current,\n subscribe,\n set: async (update) => {\n cache.assertLive(`store(${name}).set`)\n const next = typeof update === 'function' ? (update as (value: T) => T)(current) : update\n const checked = await validateStoreValue(schema, next)\n if (!checked.ok)\n throw new TypeError(`storage.store(${JSON.stringify(name)}): invalid value: ${checked.error}`)\n if (!isJson(checked.value))\n throw new TypeError(`storage.store(${JSON.stringify(name)}): value is not JSON`)\n seq++\n setCurrent(frozenCopy(checked.value) as T)\n // On failure `write` restores the previous record and notifies, which\n // decodes it back into `current`.\n await cache.write(state, 'stores', name, { v: version, value: checked.value }, false)\n },\n select: <U>(pick: (value: T) => U): Readable<U> => ({\n get: () => pick(current),\n subscribe: (listener) => {\n let last = pick(current)\n return subscribe((value) => {\n const next = pick(value)\n if (deepEqual(last, next))\n return\n last = next\n listener(next)\n })\n },\n }),\n }\n\n state.storeHandlers.set(name, decode)\n if (state.entries.stores.has(name))\n decode(state.entries.stores.get(name))\n cache.ensureLoaded(state)\n return created\n}\n","/**\n * The extension storage domain (`ctx.storage`): kv data per scope with synchronous\n * reads from a preloaded cache, typed and versioned stores, process memory\n * that survives a reload, and `path` for files.\n *\n * Data in, effects out: persistence and cross-client sync go through a\n * {@link StoragePort}; the domain owns the cache (`./cache`), validation,\n * migrations (`./store`) and change fan-out.\n */\n\nimport type { ExtensionPaths, Infer, Schema } from '../api/core'\nimport type { Json, KeyValue, StorageDomain, StorageScope, Store, StoreOptions } from '../api/storage'\nimport type { DomainDeps } from '../runtime/deps'\nimport type { MemoryRegistry } from './memory'\nimport type { StorageArea, StorageLocation, StoragePort } from './port'\nimport { onTeardown } from '../runtime/owner'\nimport { isSafeRecordKey } from '../shared'\nimport { createStorageCache } from './cache'\nimport { isJson } from './json'\nimport { resolveStoragePath } from './paths'\nimport { locationKey } from './port'\nimport { checkStoreArgs, createStore } from './store'\nimport { validateStoreValue } from './validate'\n\n/** Host data the storage domain needs besides the port. */\nexport interface StorageDomainOptions {\n /** The extension's filesystem locations, for `path`. */\n readonly paths: ExtensionPaths\n /** The extension's own folder: `path` never moves its install files (`./paths`). */\n readonly dir?: string\n /** The process-wide memory shared by every load of the extension. */\n readonly memory: MemoryRegistry\n /** The session the current call runs for; the default of `'session'` scope. */\n readonly currentSessionId?: () => string | undefined\n}\n\n/** What {@link createStorageDomain} returns: `ctx.storage` and the runtime's controls. */\nexport interface StorageRuntime {\n /** The object handed to the extension as `ctx.storage`. */\n readonly storage: StorageDomain\n /**\n * Reads `scope` into the cache so reads are synchronous, after any load in\n * flight. The runtime awaits it for `user` and `project` before setup and\n * for the run's session before each run. Rejects when the port fails.\n */\n preload: (scope: StorageScope, sessionId?: string) => Promise<void>\n /**\n * Checks a write another client wants to make to this extension's\n * storage: for `stores`, a store this extension holds at `loc` under\n * `key` takes only a `{ v, value }` record of its version whose value\n * passes its schema. Resolves with why it is refused, or `undefined`\n * (also for an entry no store of this load holds).\n */\n checkWrite: (loc: StorageLocation, area: StorageArea, key: string, value: Json | undefined) => Promise<string | undefined>\n}\n\nfunction checkKey(key: string, what: string): void {\n if (typeof key !== 'string' || !isSafeRecordKey(key))\n throw new TypeError(`storage.${what}: invalid key ${JSON.stringify(key)}`)\n}\n\n/**\n * Builds the storage domain of one extension. Everything it registers ends\n * with `deps.owner`.\n *\n * @param deps - Extension id, owner, guard and logger.\n * @param port - Where data is kept and how remote changes arrive.\n * @param options - Paths, the process memory registry and the current session.\n */\nexport function createStorageDomain(deps: DomainDeps, port: StoragePort, options: StorageDomainOptions): StorageRuntime {\n const cache = createStorageCache(deps, port, options.currentSessionId)\n const stores = new Map<string, Store<unknown>>()\n const specs = new Map<string, { schema: Schema, version: number }>()\n onTeardown(deps.owner, () => {\n stores.clear()\n specs.clear()\n })\n\n function kv(scope: StorageScope, sessionId?: string): KeyValue {\n cache.assertLive('kv')\n const state = cache.stateFor(cache.resolve(scope, sessionId, 'kv'))\n cache.ensureLoaded(state)\n return {\n ready: async () => {\n if (state.loaded)\n return\n cache.assertLive('kv.ready')\n await cache.load(state, false)\n },\n get: <T extends Json = Json>(key: string) => state.entries.kv.get(key) as T | undefined,\n set: async (key, value) => {\n cache.assertLive('kv.set')\n checkKey(key, 'kv.set')\n if (!isJson(value))\n throw new TypeError(`storage.kv.set: value of ${JSON.stringify(key)} is not JSON`)\n await cache.write(state, 'kv', key, value, true)\n },\n delete: async (key) => {\n cache.assertLive('kv.delete')\n checkKey(key, 'kv.delete')\n await cache.write(state, 'kv', key, undefined, true)\n },\n scan: (prefix = '') => [...state.entries.kv]\n .filter(([key]) => key.startsWith(prefix))\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([key, value]) => ({ key, value })),\n subscribe: (listener) => {\n cache.assertLive('kv.subscribe')\n state.kvListeners.add(listener)\n return { dispose: () => void state.kvListeners.delete(listener) }\n },\n }\n }\n\n function store<S extends Schema>(name: string, schema: S, initial: Infer<S>, opts: StoreOptions<Infer<S>>): Store<Infer<S>> {\n cache.assertLive('store')\n checkKey(name, 'store')\n checkStoreArgs(name, schema, initial, opts.version ?? 1)\n const state = cache.stateFor(cache.resolve(opts.scope, opts.sessionId, 'store'))\n const id = `${locationKey(state.loc)}\\u0000${name}`\n const existing = stores.get(id)\n if (existing)\n return existing as Store<Infer<S>>\n const created = createStore(cache, deps.guard, state, name, schema, initial, opts)\n stores.set(id, created as Store<unknown>)\n specs.set(id, { schema, version: opts.version ?? 1 })\n return created\n }\n\n const storage: StorageDomain = {\n kv,\n store,\n memory: <T>(key: string, init: () => T): T => {\n cache.assertLive('memory')\n if (typeof key !== 'string' || key.length === 0)\n throw new TypeError('storage.memory: key must be a non-empty string')\n return options.memory.getOrInit(deps.extensionId, key, init)\n },\n path: (scope, ...segments) => resolveStoragePath({\n paths: options.paths,\n extensionId: deps.extensionId,\n ...(port.folderOf ? { folderOf: port.folderOf } : {}),\n ...(options.dir !== undefined ? { dir: options.dir } : {}),\n logger: deps.logger,\n }, scope, ...segments),\n }\n\n return {\n storage,\n preload: (scope, sessionId) => {\n cache.assertLive('preload')\n return cache.load(cache.stateFor(cache.resolve(scope, sessionId, 'preload')), true)\n },\n checkWrite: async (loc, area, key, value) => {\n if (area !== 'stores' || value === undefined || loc.extensionId !== deps.extensionId)\n return undefined\n const spec = specs.get(`${locationKey(loc)}\\u0000${key}`)\n if (!spec)\n return undefined\n const record = value as { v?: unknown, value?: unknown }\n if (!record || typeof record !== 'object' || Array.isArray(record) || !Number.isInteger(record.v) || !('value' in record))\n return `store \"${key}\" takes a { v, value } record`\n if (record.v !== spec.version)\n return `store \"${key}\" is at version ${spec.version}, the write is for version ${String(record.v)}`\n const checked = await validateStoreValue(spec.schema, record.value)\n return checked.ok ? undefined : `store \"${key}\": invalid value: ${checked.error}`\n },\n }\n}\n","/**\n * The default {@link StoragePort}: one JSON file per extension, scope and\n * session, written atomically (`src/atomic-write.ts`).\n *\n * Layout, with `base` the `root` for `user` and `projectRoot ?? root` for\n * `project` and `session` (the same split `storage.path` uses):\n *\n * <base>/<extension>/user.json\n * <base>/<extension>/project.json\n * <base>/<extension>/sessions/<sessionId>.json\n *\n * `storage.path` files go in `<base>/<extension>/files` (`folderOf`, `./paths`).\n *\n * Each file is `{ \"version\": 1, \"kv\": {…}, \"stores\": {…} }`. Changes made\n * by other processes are found by re-reading a file (on a directory watch\n * event, or an explicit {@link FileStoragePort.refresh}) and diffing it\n * against the last good read. A file that does not parse is a write still\n * in progress: it is skipped until a later read parses (\"not yet\"), and a\n * save in the meantime builds on the last good read.\n */\n\nimport type { FSWatcher } from 'node:fs'\nimport type { Logger } from '../../logger'\nimport type { Disposable } from '../api/core'\nimport type { Json } from '../api/storage'\nimport type { StorageArea, StorageChange, StorageLocation, StoragePort, StorageSnapshot } from './port'\nimport { mkdirSync, readFileSync, watch } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport { OWNER_ONLY, writeJsonFileAtomic } from '../../atomic-write'\nimport { isSafeRecordKey } from '../shared'\nimport { deepEqual, isJson } from './json'\n\n/** Options of {@link createFileStoragePort}. */\nexport interface FileStoragePortOptions {\n /** Folder for `user` scope files (and the others when `projectRoot` is unset). */\n readonly root: string\n /** Folder for `project` and `session` scope files. */\n readonly projectRoot?: string\n /** Watch the folders for changes by other processes. Default `true`. */\n readonly watch?: boolean\n /** Receives watch and parse problems. */\n readonly logger?: Logger\n}\n\n/** A file-backed {@link StoragePort} with explicit refresh and shutdown. */\nexport interface FileStoragePort extends StoragePort {\n /** Re-reads the files of `loc` (all known files when omitted) and reports what others changed. */\n refresh: (loc?: StorageLocation) => void\n /** The file that holds `loc`. */\n fileOf: (loc: StorageLocation) => string\n /** The folder of one extension's data in `scope`. */\n folderOf: (extensionId: string, scope: 'user' | 'project') => string\n /** Stops the watchers and drops every listener. */\n close: () => void\n}\n\ninterface FileEntry {\n readonly path: string\n /** The last good read, or what this port last wrote. */\n snapshot?: StorageSnapshot\n readonly listeners: Set<(change: StorageChange) => void>\n}\n\nconst EMPTY: StorageSnapshot = Object.freeze({ kv: Object.freeze({}), stores: Object.freeze({}) })\nconst AREAS: readonly StorageArea[] = ['kv', 'stores']\n\n/** A single path segment from an id: encoded, and never `.` or `..`. */\nfunction segment(value: string, what: string): string {\n if (typeof value !== 'string' || value.length === 0)\n throw new TypeError(`file storage: empty ${what}`)\n const encoded = encodeURIComponent(value)\n if (encoded === '.' || encoded === '..')\n throw new TypeError(`file storage: invalid ${what} ${JSON.stringify(value)}`)\n return encoded\n}\n\nfunction cleanArea(raw: unknown): Record<string, Json> {\n const out: Record<string, Json> = Object.create(null)\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw))\n return out\n for (const [key, value] of Object.entries(raw)) {\n if (isSafeRecordKey(key) && isJson(value))\n out[key] = value\n }\n return out\n}\n\n/**\n * Reads a storage file. A missing file is empty. `undefined` means the file\n * is there but does not parse yet (a write in progress).\n */\nfunction readSnapshot(path: string): StorageSnapshot | undefined {\n let text: string\n try {\n text = readFileSync(path, 'utf8')\n }\n catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT')\n return EMPTY\n throw err\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n }\n catch {\n return undefined\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))\n return undefined\n const record = parsed as Record<string, unknown>\n return { kv: cleanArea(record.kv), stores: cleanArea(record.stores) }\n}\n\n/**\n * Makes the default file-backed storage port.\n *\n * @param options - Where the files go and whether to watch them.\n */\nexport function createFileStoragePort(options: FileStoragePortOptions): FileStoragePort {\n const entries = new Map<string, FileEntry>()\n const watchers = new Map<string, FSWatcher>()\n const shouldWatch = options.watch ?? true\n\n function fileOf(loc: StorageLocation): string {\n const ext = segment(loc.extensionId, 'extension id')\n if (loc.scope === 'user')\n return join(options.root, ext, 'user.json')\n const base = options.projectRoot ?? options.root\n if (loc.scope === 'project')\n return join(base, ext, 'project.json')\n return join(base, ext, 'sessions', `${segment(loc.sessionId ?? '', 'session id')}.json`)\n }\n\n function entryOf(loc: StorageLocation): FileEntry {\n const path = fileOf(loc)\n let entry = entries.get(path)\n if (!entry) {\n entry = { path, listeners: new Set() }\n entries.set(path, entry)\n }\n return entry\n }\n\n /** Re-reads one file and reports the differences from the last good read. */\n function refreshEntry(entry: FileEntry): void {\n const next = readSnapshot(entry.path)\n if (!next)\n return\n // With no good read yet, report everything; the domain drops what it already holds.\n const previous = entry.snapshot ?? EMPTY\n entry.snapshot = next\n for (const area of AREAS) {\n const keys = new Set([...Object.keys(previous[area]), ...Object.keys(next[area])])\n for (const key of keys) {\n const value = next[area][key]\n if (deepEqual(previous[area][key], value))\n continue\n for (const listener of [...entry.listeners]) {\n try {\n listener({ area, key, value })\n }\n catch (err) {\n options.logger?.warn('file storage: listener threw', { error: String(err) })\n }\n }\n }\n }\n }\n\n function watchDir(dir: string): void {\n if (!shouldWatch || watchers.has(dir))\n return\n try {\n mkdirSync(dir, { recursive: true })\n const watcher = watch(dir, (_event, filename) => {\n for (const entry of entries.values()) {\n if (dirname(entry.path) !== dir || (filename && basename(entry.path) !== String(filename)))\n continue\n try {\n refreshEntry(entry)\n }\n catch (err) {\n options.logger?.warn('file storage: cannot read', { path: entry.path, error: String(err) })\n }\n }\n })\n watcher.on('error', (err) => {\n options.logger?.warn('file storage: watcher stopped', { dir, error: String(err) })\n watcher.close()\n watchers.delete(dir)\n })\n watchers.set(dir, watcher)\n }\n catch (err) {\n options.logger?.warn('file storage: cannot watch', { dir, error: String(err) })\n }\n }\n\n function update(loc: StorageLocation, area: StorageArea, key: string, value: Json | undefined): void {\n if (!isSafeRecordKey(key))\n throw new TypeError(`file storage: invalid key ${JSON.stringify(key)}`)\n const entry = entryOf(loc)\n // Pick up others' changes first (and report them), so this write keeps them.\n // Not a lock: another process writing between this read and the rename loses its change.\n refreshEntry(entry)\n const base = entry.snapshot ?? EMPTY\n if (value === undefined && !Object.hasOwn(base[area], key))\n return\n const changed: Record<string, Json> = { ...base[area] }\n if (value === undefined)\n delete changed[key]\n else\n changed[key] = value\n const next: StorageSnapshot = { ...base, [area]: changed }\n writeJsonFileAtomic(entry.path, { version: 1, kv: next.kv, stores: next.stores }, OWNER_ONLY)\n entry.snapshot = next\n }\n\n return {\n fileOf,\n folderOf: (extensionId, scope) => dirname(fileOf({ extensionId, scope })),\n load: async (loc) => {\n const entry = entryOf(loc)\n const next = readSnapshot(entry.path)\n if (next)\n entry.snapshot = next\n return entry.snapshot ?? EMPTY\n },\n save: async (loc, area, key, value) => update(loc, area, key, value),\n delete: async (loc, area, key) => update(loc, area, key, undefined),\n subscribe: (loc, listener): Disposable => {\n const entry = entryOf(loc)\n if (!entry.snapshot)\n entry.snapshot = readSnapshot(entry.path)\n entry.listeners.add(listener)\n watchDir(dirname(entry.path))\n return { dispose: () => void entry.listeners.delete(listener) }\n },\n refresh: (loc) => {\n if (loc) {\n refreshEntry(entryOf(loc))\n return\n }\n for (const entry of entries.values())\n refreshEntry(entry)\n },\n close: () => {\n for (const watcher of watchers.values())\n watcher.close()\n watchers.clear()\n for (const entry of entries.values())\n entry.listeners.clear()\n },\n }\n}\n","/**\n * `ctx.storage.memory`: values kept in the process, keyed by extension id,\n * so they outlive a reload of the extension (a new domain for the same id)\n * but not a restart.\n */\n\n/** In-process values shared by every load of an extension. */\nexport interface MemoryRegistry {\n /** The value of `key` for `extensionId`, created with `init` on first use. */\n getOrInit: <T>(extensionId: string, key: string, init: () => T) => T\n /** Forgets every value of `extensionId` (on uninstall or disable). */\n clear: (extensionId: string) => void\n}\n\n/** Makes an empty {@link MemoryRegistry}. A host keeps one for the life of the process. */\nexport function createMemoryRegistry(): MemoryRegistry {\n const byExtension = new Map<string, Map<string, unknown>>()\n return {\n getOrInit<T>(extensionId: string, key: string, init: () => T): T {\n let values = byExtension.get(extensionId)\n if (values?.has(key))\n return values.get(key) as T\n const value = init()\n if (!values) {\n values = new Map()\n byExtension.set(extensionId, values)\n }\n values.set(key, value)\n return value\n },\n clear(extensionId) {\n byExtension.delete(extensionId)\n },\n }\n}\n","/**\n * The extension storage domain: `ctx.storage` and its host port.\n */\n\nexport { createStorageDomain } from './domain'\nexport type { StorageDomainOptions, StorageRuntime } from './domain'\nexport { createFileStoragePort } from './file-port'\nexport type { FileStoragePort, FileStoragePortOptions } from './file-port'\nexport { deepEqual, frozenCopy, isJson } from './json'\nexport { createMemoryRegistry } from './memory'\nexport type { MemoryRegistry } from './memory'\nexport { legacyStoragePath, resolveStoragePath, storagePathRoot } from './paths'\nexport type { StorageFolderOf, StoragePathOptions } from './paths'\nexport { locationKey } from './port'\nexport type { StorageArea, StorageChange, StorageLocation, StoragePort, StorageSnapshot } from './port'\nexport { validateStoreValue } from './validate'\nexport type { StoreValidation } from './validate'\n","/**\n * In-memory host ports for the extension runtime (extension API). The runtime\n * falls back to them for every port a host leaves out, and the testing kit\n * (`src/extensions/testing`) drives them directly. Nothing here touches the\n * disk, the network or a window.\n */\n\nimport type { Json } from '../api/storage'\nimport type { McpCatalogPort } from '../catalog'\nimport type { IntegrationFlowPort } from '../integrations'\nimport type { SettingsLayer, SettingsPort } from '../settings'\nimport type { StorageChange, StorageLocation, StoragePort, StorageSnapshot } from '../storage'\nimport type { DialogPort, DialogRequest, DialogShowContext, UiClientInfo, UiClientPort } from '../ui'\nimport { locationKey } from '../storage'\n\n/** An in-memory {@link StoragePort} with a way to simulate another client's write. */\nexport interface MemoryStoragePort extends StoragePort {\n /** What is stored at `loc` now (a copy). */\n snapshot: (loc: StorageLocation) => StorageSnapshot\n /** Another client wrote: stores the change and tells every subscriber of `loc`. */\n remote: (loc: StorageLocation, change: StorageChange) => void\n}\n\n/**\n * An in-memory storage port. Every save and delete is announced to every\n * subscriber of the location, so two caches in one process stay in sync\n * (the domain drops echoes of its own writes).\n *\n * @returns The port.\n */\nexport function createMemoryStoragePort(): MemoryStoragePort {\n const data = new Map<string, { kv: Record<string, Json>, stores: Record<string, Json> }>()\n const listeners = new Map<string, Set<(change: StorageChange) => void>>()\n const slot = (loc: StorageLocation) => {\n const key = locationKey(loc)\n let entry = data.get(key)\n if (!entry) {\n entry = { kv: {}, stores: {} }\n data.set(key, entry)\n }\n return entry\n }\n const announce = (loc: StorageLocation, change: StorageChange): void => {\n for (const listener of [...listeners.get(locationKey(loc)) ?? []]) {\n try {\n listener(change)\n }\n catch {}\n }\n }\n const apply = (loc: StorageLocation, change: StorageChange): void => {\n const entry = slot(loc)\n if (change.value === undefined)\n delete entry[change.area][change.key]\n else\n entry[change.area][change.key] = structuredClone(change.value) as Json\n announce(loc, change)\n }\n return {\n load: async loc => structuredClone(slot(loc)) as StorageSnapshot,\n save: async (loc, area, key, value) => apply(loc, { area, key, value }),\n delete: async (loc, area, key) => apply(loc, { area, key, value: undefined }),\n subscribe: (loc, listener) => {\n const key = locationKey(loc)\n let set = listeners.get(key)\n if (!set) {\n set = new Set()\n listeners.set(key, set)\n }\n set.add(listener)\n return { dispose: () => void set.delete(listener) }\n },\n snapshot: loc => structuredClone(slot(loc)) as StorageSnapshot,\n remote: apply,\n }\n}\n\n/** An in-memory {@link SettingsPort} whose layers can be set from outside. */\nexport interface MemorySettingsPort extends SettingsPort {\n /** Replaces one layer of an extension (a config edit, another window) and notifies its listeners. */\n put: (extensionId: string, layer: SettingsLayer, values: Readonly<Record<string, unknown>>, sessionId?: string) => void\n}\n\n/**\n * An in-memory settings port.\n *\n * @param initial - Starting values: `{ [extensionId]: { [key]: value } }`, put in the `user` layer.\n * @returns The port.\n */\nexport function createMemorySettingsPort(initial: Readonly<Record<string, Readonly<Record<string, unknown>>>> = {}): MemorySettingsPort {\n const layers = new Map<string, Record<string, unknown>>()\n const secrets = new Map<string, string>()\n const listeners = new Map<string, Set<() => void>>()\n const id = (ext: string, layer: SettingsLayer, sessionId?: string) => `${ext}\\u0000${layer}\\u0000${sessionId ?? ''}`\n const notify = (ext: string): void => {\n for (const listener of [...listeners.get(ext) ?? []]) {\n try {\n listener()\n }\n catch {}\n }\n }\n for (const [ext, values] of Object.entries(initial))\n layers.set(id(ext, 'user'), { ...values })\n return {\n read: (ext, layer, sessionId) => layers.get(id(ext, layer, sessionId)),\n write(ext, scope, key, value, sessionId) {\n const k = id(ext, scope, sessionId)\n const bag = { ...layers.get(k) }\n if (value === undefined)\n delete bag[key]\n else\n bag[key] = value\n layers.set(k, bag)\n notify(ext)\n },\n subscribe(ext, listener) {\n let set = listeners.get(ext)\n if (!set) {\n set = new Set()\n listeners.set(ext, set)\n }\n set.add(listener)\n return () => set.delete(listener)\n },\n secrets: {\n get: (ext, key) => secrets.get(`${ext}\\u0000${key}`),\n set(ext, key, value) {\n if (value === undefined)\n secrets.delete(`${ext}\\u0000${key}`)\n else\n secrets.set(`${ext}\\u0000${key}`, value)\n notify(ext)\n },\n },\n put(ext, layer, values, sessionId) {\n layers.set(id(ext, layer, sessionId), { ...values })\n notify(ext)\n },\n }\n}\n\n/** A scripted answer for one dialog: a value, or a function of the request. */\nexport type DialogAnswer = unknown | ((request: DialogRequest, ctx: DialogShowContext) => unknown)\n\n/** A {@link DialogPort} with one client that answers from a script. */\nexport interface ScriptedDialogPort extends DialogPort {\n /** Queues an answer for the next dialog of `kind`. Unanswered dialogs resolve `undefined`. */\n answer: (kind: DialogRequest['kind'], answer: DialogAnswer) => void\n /** Every dialog shown, oldest first. */\n readonly shown: readonly { request: DialogRequest, extensionId: string, sessionId?: string }[]\n}\n\n/** The client id {@link createScriptedDialogPort} and {@link createRecordingUiClientPort} report. */\nexport const MEMORY_CLIENT_ID = 'memory'\n\n/**\n * A dialog port with one client that answers from queued answers.\n *\n * @param client - The client it reports. Default: one client viewing nothing.\n * @returns The port.\n */\nexport function createScriptedDialogPort(client: UiClientInfo = { id: MEMORY_CLIENT_ID, viewing: [], lastActiveAt: 0 }): ScriptedDialogPort {\n const queues = new Map<DialogRequest['kind'], DialogAnswer[]>()\n const shown: { request: DialogRequest, extensionId: string, sessionId?: string }[] = []\n return {\n clients: () => [client],\n show: async (_clientId, request, ctx) => {\n shown.push({ request, extensionId: ctx.extensionId, ...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}) })\n const answer = queues.get(request.kind)?.shift()\n return typeof answer === 'function' ? (answer as (r: DialogRequest, c: DialogShowContext) => unknown)(request, ctx) : answer\n },\n answer: (kind, answer) => {\n let queue = queues.get(kind)\n if (!queue) {\n queue = []\n queues.set(kind, queue)\n }\n queue.push(answer)\n },\n shown,\n }\n}\n\n/** A dialog port with no client: every dialog rejects with `NoUiError`, toasts resolve `undefined`. */\nexport const NO_CLIENT_DIALOG_PORT: DialogPort = {\n clients: () => [],\n show: async () => undefined,\n}\n\n/** One call a {@link RecordingUiClientPort} received. */\nexport interface UiClientCall {\n /** The port method called. */\n method: keyof UiClientPort\n /** The client the call targeted. */\n clientId: string\n /** The arguments after `clientId`. */\n args: readonly unknown[]\n}\n\n/** A {@link UiClientPort} that records calls and reports success. */\nexport interface RecordingUiClientPort extends UiClientPort {\n /** Every call, oldest first. */\n readonly calls: readonly UiClientCall[]\n}\n\n/**\n * A client port that records each call. Panel, navigate, composer and\n * keymap dispatch calls resolve `true`; `panelState` resolves the panels\n * opened so far.\n *\n * @returns The port.\n */\nexport function createRecordingUiClientPort(): RecordingUiClientPort {\n const calls: UiClientCall[] = []\n const open = new Set<string>()\n return {\n calls,\n panel: async (clientId, request) => {\n calls.push({ method: 'panel', clientId, args: [request] })\n if (request.action === 'open' || (request.action === 'toggle' && !open.has(request.panelId)))\n open.add(request.panelId)\n else\n open.delete(request.panelId)\n return true\n },\n panelState: async (clientId, opts) => {\n calls.push({ method: 'panelState', clientId, args: [opts] })\n return [...open]\n },\n navigate: async (clientId, to) => {\n calls.push({ method: 'navigate', clientId, args: [to] })\n return true\n },\n composer: async (clientId, op, opts) => {\n calls.push({ method: 'composer', clientId, args: [op, opts] })\n return true\n },\n notify: (clientId, notification) => {\n calls.push({ method: 'notify', clientId, args: [notification] })\n },\n keymapDispatch: async (clientId, request) => {\n calls.push({ method: 'keymapDispatch', clientId, args: [request] })\n return true\n },\n }\n}\n\n/** A client port for hosts without clients. Never called: the router finds no client first. */\nexport const NO_UI_CLIENT_PORT: UiClientPort = {\n panel: async () => false,\n panelState: async () => [],\n navigate: async () => false,\n composer: async () => false,\n notify: () => {},\n}\n\n/** An MCP port with no servers. Calls reject. */\nexport const EMPTY_MCP_PORT: McpCatalogPort = {\n servers: () => [],\n status: () => [],\n call: async server => Promise.reject(new Error(`MCP server \"${server}\" is not connected in this host`)),\n}\n\n/** An integration flow port for hosts that cannot show a sign-in flow. */\nexport const NO_INTEGRATION_FLOWS: IntegrationFlowPort = {\n oauthCallbacks: () => {\n throw new Error('Signing in is not available in this host')\n },\n runCommand: async () => Promise.reject(new Error('Running a sign-in command is not available in this host')),\n}\n","/**\n * One runtime's extension settings in the wire format Settings UIs draw:\n * each extension's schema (live values while active, the definition's\n * schema otherwise) with its `SettingsPage` items (`ctx.add(SettingsPage)`)\n * appended to its pages, merged in load order. Every host builds its\n * `extensions.settings` answer from it, and refetches it on\n * {@link onSettingsPagesChanged}.\n */\n\nimport type { WireSettings } from '../settings'\nimport type { UiChange, UiRegistry } from '../ui/registry'\nimport type { RuntimeExtension } from './host'\nimport { mergeWireSettings, settingsForDefinition, toWireSettings, wireExtension } from '../settings'\nimport { wireWithSettingsPages } from '../ui/settings-form'\n\n/** The live wire with its implicit page labelled with the extension's name, as `toWireSettings` labels it from the definition. */\nfunction named(wire: WireSettings, displayName: string): WireSettings {\n return wire.pages?.some(page => page.implicit) ? { ...wire, pages: wire.pages.map(page => page.implicit ? { ...page, label: displayName } : page) } : wire\n}\n\n/**\n * One extension's settings wire with its settings pages, or `undefined`\n * when it has no definition (failed validation) and no page.\n *\n * @param r - The extension (`runtime.get(id)`).\n * @param ui - The runtime's UI registry (`runtime.outputs.ui`).\n * @param opts - `sessionId` adds that session's layer to live values.\n * @param opts.sessionId - The session whose values to read.\n */\nexport function extensionSettingsWire(r: Pick<RuntimeExtension, 'id' | 'definition' | 'info' | 'settings'>, ui: Pick<UiRegistry, 'list'>, opts: { sessionId?: string } = {}): WireSettings | undefined {\n const own = r.settings\n ? named(r.settings.wire(opts.sessionId ? { sessionId: opts.sessionId } : {}), r.info.displayName)\n : r.definition\n ? toWireSettings(r.id, settingsForDefinition(r.definition).schema, {}, { displayName: r.info.displayName })\n : undefined\n const paged = wireWithSettingsPages(own ?? mergeWireSettings([]), r.id, ui)\n if (!own && (paged.pages?.length ?? 0) === 0)\n return undefined\n // Its name and icon (the definition's, else its manifest's) and its description, whichever way the wire was built.\n const icon = r.definition?.icon ?? r.info.icon\n return { ...paged, extensions: { ...paged.extensions, [r.id]: wireExtension(r.id, r.info.displayName, icon, r.definition?.description) } }\n}\n\n/**\n * Every extension's settings wire of a runtime, merged in load order.\n *\n * @param runtime - The runtime: its extensions and UI registry.\n * @param runtime.extensions - Every known extension, in load order.\n * @param runtime.get - One extension's state.\n * @param runtime.outputs - Holds the UI registry.\n * @param runtime.outputs.ui - The UI registry with the settings-page items.\n * @param opts - `sessionId` adds that session's layer to live values.\n * @param opts.sessionId - The session whose values to read.\n */\nexport function runtimeSettingsWire(\n runtime: { extensions: () => readonly { id: string }[], get: (id: string) => Pick<RuntimeExtension, 'id' | 'definition' | 'info' | 'settings'> | undefined, outputs: { ui: Pick<UiRegistry, 'list'> } },\n opts: { sessionId?: string } = {},\n): WireSettings {\n return mergeWireSettings(runtime.extensions().flatMap((info) => {\n const r = runtime.get(info.id)\n const wire = r ? extensionSettingsWire(r, runtime.outputs.ui, opts) : undefined\n return wire ? [wire] : []\n }))\n}\n\n/**\n * Whether a UI change adds, replaces or removes a settings page (`reset`:\n * every item may have gone).\n *\n * @param change - A UI registry change, or a protocol `reset`.\n */\nexport function touchesSettingsPages(change: UiChange | { type: 'reset' }): boolean {\n if (change.type === 'reset')\n return true\n if (change.type === 'upsert')\n return change.entry.token === 'settings-page'\n return change.type === 'remove' && change.token === 'settings-page'\n}\n\n/**\n * Calls `listener` each time a settings page of `ui` is added, replaced or\n * removed: the settings wire changed, read it again. Protocol clients\n * follow the same `extensions:ui` changes (`ExtensionsClient.settings.onChange`).\n *\n * @param ui - The registry (`runtime.outputs.ui`).\n * @param listener - Called once per change.\n * @returns The unsubscribe.\n */\nexport function onSettingsPagesChanged(ui: Pick<UiRegistry, 'subscribe'>, listener: () => void): () => void {\n return ui.subscribe((change) => {\n if (touchesSettingsPages(change))\n listener()\n })\n}\n","/**\n * Bindable fields: a UI item field may hold a fixed value or a\n * {@link Readable}. The registry reads every bound field when it serializes\n * the item, and subscribes to it so a change re-pushes the item.\n */\n\nimport type { Bindable, Readable } from '../api/core'\n\n/**\n * Whether `value` is a {@link Readable}: an object with `get` and\n * `subscribe` functions.\n *\n * @param value - Any field value of a UI item.\n */\nexport function isReadable(value: unknown): value is Readable<unknown> {\n return !!value\n && typeof value === 'object'\n && typeof (value as Readable<unknown>).get === 'function'\n && typeof (value as Readable<unknown>).subscribe === 'function'\n}\n\n/** An item with every {@link Bindable} field replaced by its value type. */\nexport type Resolved<T> = { [K in keyof T]: T[K] extends Bindable<infer U> ? U : T[K] }\n\n/**\n * A shallow copy of `item` with each top-level {@link Readable} field read.\n *\n * @param item - The item as the extension gave it.\n * @param read - Reads one readable (the registry runs it through the guard).\n */\nexport function resolveBindables<T extends object>(item: T, read: (readable: Readable<unknown>) => unknown): Resolved<T> {\n const out: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(item))\n out[key] = isReadable(value) ? read(value) : value\n return out as Resolved<T>\n}\n\n/**\n * The distinct readables among the top-level fields of `item`.\n *\n * @param item - The item as the extension gave it.\n */\nexport function readablesOf(item: object): Readable<unknown>[] {\n const out = new Set<Readable<unknown>>()\n for (const value of Object.values(item)) {\n if (isReadable(value))\n out.add(value)\n }\n return [...out]\n}\n","/**\n * The backend side of UI items: the extension functions hosts invoke by an\n * item's id (panel `load` / `onAction`, reference `resolve`, badge\n * actions, context sections, settings actions, link handlers), each run\n * through the owning extension's guard, and the composer provider lists.\n */\n\nimport type { ContextBreakdownContributionContext, ContextBreakdownContributor, ContextExtensionRow, ContextExtensionSection } from '../../chat/context-breakdown'\nimport type { JsonValue } from '../../types'\nimport type { AccessScope, Disposable } from '../api/core'\nimport type { ActionSetting, ActionSettingContext, ActionSettingResult, ActionSettingStatus, SettingsSchema } from '../api/settings'\nimport type { ContextSectionItem, LinkHandlerItem, LinkSource, PanelItem, SettingsPageItem } from '../api/ui'\nimport type { BadgeActionEffect, BadgeMenuItem, BadgeTarget, ExtensionBadgeActions } from '../badge-actions'\nimport type { PanelContent } from '../panels'\nimport type { DomainDeps } from '../runtime/deps'\nimport type { ExtensionOrderedContribution, ExtensionReferenceProvider, ExtensionReferenceView } from '../types'\nimport { DisposedError } from '../api/core'\nimport { badgeMenu, runBadgeAction } from '../badge-actions'\nimport { normalizePanelContent, normalizePanelLoadContext, resolvePanelLoadContext } from '../panels'\nimport { createReferenceResolver } from '../references'\nimport { actionScope } from '../settings/validate'\nimport { checkSettingsValues } from './settings-form'\n\n/** An item with what is needed to call into it: its extension's deps and the item as given. */\nexport interface UiSource {\n readonly extension: string\n readonly deps: DomainDeps\n readonly raw: object\n}\n\n/** Finds the live items of a token (in order, first of each id winning where that applies). */\nexport interface UiSourceLookup {\n /** The item of `token` whose wire id is `id`. */\n byId: (token: 'panel' | 'settings-page', id: string) => UiSource | undefined\n /** Every item of `token`, in order. */\n all: (token: 'reference' | 'badge-action' | 'context-section' | 'link-handler') => readonly UiSource[]\n /** A number that changes whenever the reference providers change. */\n referencesVersion: () => number\n /** The extension's own settings, for a settings-page action's `get` / `set`. Without it `get` reads nothing and `set` rejects. */\n settingsAccess?: (extensionId: string) => Omit<ActionSettingContext, 'signal'> | undefined\n /**\n * The action rows of an extension's own settings (its definition's schema), for a `setting.action` whose\n * page id is the extension's id, as the settings sidebar sends it. `undefined`: no such action.\n */\n ownActions?: (extensionId: string) => OwnSettingActions | undefined\n}\n\n/** An extension's own settings actions, as {@link UiSourceLookup.ownActions} gives them. */\nexport interface OwnSettingActions {\n /** Runs it; `undefined` when the extension has no action `key`. */\n run: (key: string, signal: AbortSignal) => Promise<ActionSettingResult | undefined>\n /** Its live status, when it has one. */\n status: (key: string) => Promise<ActionSettingStatus | undefined>\n /** The least token scope a remote client needs; `undefined` when there is no such action. */\n scope: (key: string) => AccessScope | undefined\n}\n\n/** Settings access for an extension the lookup has no settings for. */\nfunction noSettingsAccess(extensionId: string): Omit<ActionSettingContext, 'signal'> {\n return {\n get: () => undefined,\n set: async key => Promise.reject(new Error(`setting \"${key}\": \"${extensionId}\" has no settings in this host`)),\n }\n}\n\n/** The registry's callback methods (see {@link UiRegistry}). */\nexport interface UiCallbacks {\n loadPanel: (panelId: string, context: unknown, cwd: string) => Promise<PanelContent>\n panelAction: (panelId: string, actionId: string, payload: JsonValue | undefined, context: unknown, cwd: string) => Promise<boolean>\n resolveReference: (providerId: string, key: string) => Promise<ExtensionReferenceView | null>\n badgeMenu: (target: BadgeTarget) => BadgeMenuItem[]\n runBadgeAction: (source: string, actionId: string, target: BadgeTarget, ctx?: { sessionId?: string, cwd?: string }) => Promise<BadgeActionEffect>\n contextContributors: (placement: 'breakdown' | 'panel') => readonly ContextBreakdownContributor[]\n runSettingAction: (pageId: string, settingKey: string, signal: AbortSignal) => Promise<ActionSettingResult | undefined>\n settingStatus: (pageId: string, settingKey: string) => Promise<ActionSettingStatus | undefined>\n validateSetting: (pageId: string, settingKey: string, value: unknown) => string | undefined\n /** The least token scope a remote client needs to run a settings-page action (`ActionSetting.scope`, default `'admin'`); `undefined` when there is no such action. */\n settingActionScope: (pageId: string, settingKey: string) => AccessScope | undefined\n /**\n * Offers a link to the link handlers whose `match` takes it, higher\n * `priority` first (registration order among equals). A handler that\n * returns `false`, throws or times out passes it to the next.\n * `handled: false`: none took it, the app opens it its own way.\n */\n openLink: (request: LinkOpenRequest) => Promise<{ handled: boolean }>\n}\n\n/** A link to open, as hosts pass it to {@link UiCallbacks.openLink}. */\nexport interface LinkOpenRequest {\n /** The link as clicked. */\n url: string\n /** The session it was clicked in. */\n sessionId?: string\n /** Where it was clicked. Default `'other'`. */\n source?: LinkSource\n}\n\n/** Every {@link LinkSource}. */\nexport const LINK_SOURCES: readonly LinkSource[] = ['transcript', 'chip', 'panel', 'badge', 'terminal', 'other']\n\n/** Longest URL a link handler is offered. */\nexport const MAX_LINK_URL_LENGTH = 8192\n\n/** Whether a link handler's `match` takes `url`. A throwing test counts as no match (and against the extension). */\nfunction linkMatches(s: UiSource, url: string): boolean {\n const { match } = s.raw as LinkHandlerItem\n if (typeof match === 'string')\n return url.startsWith(match)\n if (match instanceof RegExp) {\n match.lastIndex = 0\n return match.test(url)\n }\n return typeof match === 'function' && s.deps.guard.callSync('ui.link.match', () => match(url), { fallback: false }) === true\n}\n\nconst THROWN: unique symbol = Symbol('thrown')\n\n/** Runs `fn` through the guard, but turns a throw back into a throw (callers that must not cache failures). */\nasync function callOrThrow<T>(deps: DomainDeps, label: string, fn: () => T | Promise<T>, timeoutMs: number, message: string): Promise<T> {\n const result = await deps.guard.call<T | typeof THROWN>(label, fn, { timeoutMs, fallback: THROWN })\n if (result === THROWN)\n throw new Error(message)\n return result as T\n}\n\n/**\n * A contributor for a panel context section: static or computed\n * rows, plus `load`.\n *\n * @param section - The section as the extension gave it.\n */\nexport function panelSectionContributor(section: Extract<ContextSectionItem, { placement: 'panel' }>['section']): ContextBreakdownContributor {\n return async (ctx) => {\n const head = { id: section.id, label: section.title, ...(section.accentColor ? { accentColor: section.accentColor } : {}) }\n const sections: ContextExtensionSection[] = []\n const rows = typeof section.rows === 'function' ? section.rows(ctx) : section.rows\n if (rows && rows.length > 0)\n sections.push({ ...head, rows })\n const loaded = section.load ? await section.load(ctx) : undefined\n if (!loaded)\n return sections\n if (Array.isArray(loaded)) {\n if (loaded.every(row => row && typeof row === 'object' && 'value' in row))\n sections.push({ ...head, rows: loaded as readonly ContextExtensionRow[] })\n else\n sections.push(...loaded as readonly ContextExtensionSection[])\n return sections\n }\n sections.push(loaded as ContextExtensionSection)\n return sections\n }\n}\n\nfunction guardedReferences(sources: readonly UiSource[], timeoutMs: number): ExtensionOrderedContribution<ExtensionReferenceProvider>[] {\n return sources.map((s) => {\n const provider = s.raw as ExtensionReferenceProvider\n return {\n extensionName: s.extension,\n source: 'project',\n value: { ...provider, resolve: (key, opts) => callOrThrow(s.deps, 'ui.reference.resolve', () => provider.resolve(key, opts), timeoutMs, 'resolve failed') },\n }\n })\n}\n\nfunction guardedBadgeActions(sources: readonly UiSource[], timeoutMs: number): { badgeActions: ExtensionOrderedContribution<ExtensionBadgeActions>[] } {\n return {\n badgeActions: sources.map((s) => {\n const value = s.raw as ExtensionBadgeActions\n return {\n extensionName: s.extension,\n source: 'project',\n value: {\n ...value,\n actions: target => s.deps.guard.callSync('ui.badge.actions', () => value.actions(target)),\n run: (actionId, target, ctx) => callOrThrow(s.deps, 'ui.badge.run', () => value.run(actionId, target, ctx), timeoutMs, 'The action failed.'),\n },\n }\n }),\n }\n}\n\n/**\n * The callback methods over the registry's live items.\n *\n * @param lookup - Finds items.\n * @param timeoutMs - Deadline per callback.\n */\nexport function createUiCallbacks(lookup: UiSourceLookup, timeoutMs: number): UiCallbacks {\n const loadContext = (context: unknown, cwd: string) => resolvePanelLoadContext(normalizePanelLoadContext(context), cwd)\n let resolver: { version: number, value: ReturnType<typeof createReferenceResolver> } | undefined\n const getResolver = () => {\n const version = lookup.referencesVersion()\n if (!resolver || resolver.version !== version)\n resolver = { version, value: createReferenceResolver({ references: guardedReferences(lookup.all('reference'), timeoutMs) }, { timeoutMs }) }\n return resolver.value\n }\n const accessOf = (s: UiSource): Omit<ActionSettingContext, 'signal'> => lookup.settingsAccess?.(s.extension) ?? noSettingsAccess(s.extension)\n const actionSetting = (pageId: string, settingKey: string): { s: UiSource, setting: ActionSetting } | undefined => {\n const s = lookup.byId('settings-page', pageId)\n const setting = (s?.raw as SettingsPageItem | undefined)?.schema?.items[settingKey]\n return s && setting?.type === 'action' ? { s, setting } : undefined\n }\n\n return {\n loadPanel: async (panelId, context, cwd) => {\n const s = lookup.byId('panel', panelId)\n if (!s)\n return normalizePanelContent(undefined)\n const panel = s.raw as PanelItem\n return normalizePanelContent(await s.deps.guard.call('ui.panel.load', () => panel.load(loadContext(context, cwd)), { timeoutMs }))\n },\n panelAction: async (panelId, actionId, payload, context, cwd) => {\n const s = lookup.byId('panel', panelId)\n const onAction = (s?.raw as PanelItem | undefined)?.onAction\n if (!s || typeof onAction !== 'function' || typeof actionId !== 'string' || !actionId)\n return false\n const ok = await s.deps.guard.call('ui.panel.action', async () => {\n await onAction(actionId, payload, loadContext(context, cwd))\n return true\n }, { timeoutMs, fallback: false })\n return ok === true\n },\n resolveReference: (providerId, key) => getResolver().resolve(providerId, key),\n badgeMenu: target => badgeMenu(target, guardedBadgeActions(lookup.all('badge-action'), timeoutMs)),\n runBadgeAction: (source, actionId, target, ctx = {}) => runBadgeAction(source, actionId, target, guardedBadgeActions(lookup.all('badge-action'), timeoutMs), ctx),\n contextContributors: placement => lookup.all('context-section').flatMap((s) => {\n const item = s.raw as ContextSectionItem\n if (item.placement !== placement)\n return []\n const run: ContextBreakdownContributor = item.placement === 'breakdown' ? item.contributor : panelSectionContributor(item.section)\n const guarded: ContextBreakdownContributor = (ctx: ContextBreakdownContributionContext) =>\n s.deps.guard.call(`ui.context.${placement}`, () => run(ctx), { timeoutMs, fallback: undefined })\n Object.defineProperty(guarded, '__zidaneExtensionName', { value: s.extension, enumerable: false })\n return [guarded]\n }),\n runSettingAction: async (pageId, settingKey, signal) => {\n const found = actionSetting(pageId, settingKey)\n if (!found)\n return lookup.ownActions?.(pageId)?.run(settingKey, signal)\n const result = await found.s.deps.guard.call('ui.settings.action', () => found.setting.run({ ...accessOf(found.s), signal }), { timeoutMs })\n return result && typeof result === 'object' ? result : undefined\n },\n settingStatus: async (pageId, settingKey) => {\n const found = actionSetting(pageId, settingKey)\n if (!found)\n return lookup.ownActions?.(pageId)?.status(settingKey)\n const status = found.setting.status\n if (!status)\n return undefined\n const { get } = accessOf(found.s)\n const result = await found.s.deps.guard.call('ui.settings.status', () => status({ get }), { timeoutMs })\n return result && typeof result === 'object' && typeof result.text === 'string' ? result : undefined\n },\n settingActionScope: (pageId, settingKey) => {\n const found = actionSetting(pageId, settingKey)\n return found ? actionScope(found.setting) : lookup.ownActions?.(pageId)?.scope(settingKey)\n },\n openLink: async ({ url, sessionId, source }) => {\n if (typeof url !== 'string' || !url || url.length > MAX_LINK_URL_LENGTH)\n return { handled: false }\n const where: LinkSource = source !== undefined && LINK_SOURCES.includes(source) ? source : 'other'\n const handlers = lookup.all('link-handler')\n .map((s, at) => ({ s, at, priority: (s.raw as LinkHandlerItem).priority ?? 0 }))\n .sort((a, b) => b.priority - a.priority || a.at - b.at)\n for (const { s } of handlers) {\n if (!linkMatches(s, url))\n continue\n const open = (s.raw as LinkHandlerItem).open\n const result = await s.deps.guard.call<unknown>('ui.link.open', () => open(url, { ...(sessionId ? { sessionId } : {}), source: where }), { timeoutMs, fallback: THROWN })\n if (result !== THROWN && result !== false)\n return { handled: true }\n }\n return { handled: false }\n },\n validateSetting: (pageId, settingKey, value) => {\n const s = lookup.byId('settings-page', pageId)\n const setting = (s?.raw as SettingsPageItem | undefined)?.schema?.items[settingKey]\n if (!s || !setting)\n return 'unknown setting'\n const one: SettingsSchema = { items: { [settingKey]: setting } }\n return checkSettingsValues(one, { [settingKey]: value }, (validate, v) => s.deps.guard.callSync('ui.settings.validate', () => validate(v))).errors[settingKey]\n },\n }\n}\n\n/** A backend-side provider list (composer completions, inline autocomplete). */\nexport interface UiProviderList<P> {\n /** Adds a provider for the extension. Disposed with the extension's owner. */\n register: (deps: DomainDeps, provider: P) => Disposable\n /** The providers with their extension, in registration order; the first of each `id` wins. */\n list: () => readonly { extension: string, provider: P }[]\n}\n\n/**\n * An empty provider list.\n *\n * @param what - Name used in errors (`composer.completions`).\n * @param onChange - Called after each register and dispose.\n */\nexport function createProviderList<P extends { id: string }>(what: string, onChange: () => void): UiProviderList<P> {\n const items: { extension: string, provider: P }[] = []\n return {\n register: (deps, provider) => {\n if (deps.owner.disposed)\n throw new DisposedError(`${what}.register`)\n if (!provider || typeof provider.id !== 'string' || !provider.id)\n throw new TypeError(`${what}: a provider needs an id`)\n const rec = { extension: deps.extensionId, provider }\n items.push(rec)\n onChange()\n let done = false\n const handle: { cleanup?: Disposable } = {}\n const off = (): void => {\n if (done)\n return\n done = true\n handle.cleanup?.dispose()\n items.splice(items.indexOf(rec), 1)\n onChange()\n }\n handle.cleanup = deps.owner.onCleanup(off)\n return { dispose: off }\n },\n list: () => {\n const seen = new Set<string>()\n return items.filter((r) => {\n if (seen.has(r.provider.id))\n return false\n seen.add(r.provider.id)\n return true\n })\n },\n }\n}\n","/**\n * The timer the UI model uses for slot `timeoutMs` and dialog timeouts.\n * Injectable so tests drive time instead of waiting for it.\n */\n\n/** Schedules and cancels one-shot timers. */\nexport interface UiClock {\n /** Runs `fn` once after `ms` milliseconds. Returns a handle for {@link UiClock.clearTimeout}. */\n setTimeout: (fn: () => void, ms: number) => unknown\n /** Cancels a timer made by {@link UiClock.setTimeout}. Unknown handles are ignored. */\n clearTimeout: (handle: unknown) => void\n}\n\n/** The real clock: `setTimeout` / `clearTimeout` of the host. */\nexport const systemClock: UiClock = {\n setTimeout: (fn, ms) => setTimeout(fn, ms),\n clearTimeout: handle => clearTimeout(handle as ReturnType<typeof setTimeout>),\n}\n","/**\n * The UI registry: every extension's UI contributions, per token, as wire\n * items the hosts draw. `ctx.add(token, item)` lands here and returns a\n * {@link Handle}; bound fields re-push on change; hosts subscribe to\n * changes and call back into the extension through the item ids (see\n * {@link UiCallbacks}). Callbacks run through the owning extension's guard.\n *\n * Slot rules: `composer.badges` holds at most {@link MAX_COMPOSER_BADGES}\n * items per extension per session, `app.titlebar` as many per extension; `timeoutMs` withdraws an item (rearmed\n * on each update); deleting a session withdraws its items; lists are ordered\n * by `order` (default 100), then by when the item was added. Spaces are\n * ordered the same way. The sidebar tokens have per-extension caps\n * ({@link SIDEBAR_CAPS}). Sidebar rows' command, panel and screen ids are\n * resolved against the registry and the commands, and resolved again when\n * those change.\n *\n * Pure: no host code, no globals. Time comes from an injectable clock.\n */\n\nimport type { CompletionProvider } from '../../chat/completion'\nimport type { InlineAutocompleteProvider } from '../../chat/inline-autocomplete'\nimport type { Logger } from '../../logger'\nimport type { Disposable, Handle, Readable } from '../api/core'\nimport type { AddFn, PanelItem, UiToken } from '../api/ui'\nimport type { DomainDeps } from '../runtime/deps'\nimport type { UiCallbacks, UiProviderList, UiSource, UiSourceLookup } from './callbacks'\nimport type { UiClock } from './clock'\nimport type { UiRefs, UiTokenName, UiWireMap } from './wire'\nimport { DisposedError } from '../api/core'\nimport { readablesOf, resolveBindables } from './bindable'\nimport { createProviderList, createUiCallbacks } from './callbacks'\nimport { systemClock } from './clock'\nimport { isBadgeSlot, isKnownToken, isUniquePerExtension, MAX_SLOT_BADGES, serializeUiItem, UI_TOKEN_NAMES, wireIdentity } from './wire'\n\n/** How many `composer.badges` items one extension may show in one session, and `app.titlebar` items in the app. */\nexport const MAX_COMPOSER_BADGES = MAX_SLOT_BADGES\n\n/** How many sidebar rows one extension may show. */\nexport const MAX_SIDEBAR_ROWS = 500\n\n/** How many items of each sidebar token one extension may add. */\nexport const SIDEBAR_CAPS: Readonly<Partial<Record<UiTokenName, number>>> = {\n 'space': 32,\n 'sidebar-filter': 64,\n 'sidebar-sort': 32,\n 'sidebar-group': 32,\n 'sidebar-decoration': 64,\n 'sidebar-row': MAX_SIDEBAR_ROWS,\n}\n\n/** One contribution as the hosts see it. */\nexport interface UiEntry<N extends UiTokenName = UiTokenName> {\n /** Unique across the registry; stable for the item's life. Hosts address the item by it. */\n readonly key: string\n /** The token name of the contribution. */\n readonly token: N\n /** The contributing extension. */\n readonly extension: string\n /** The wire form, bindings read. */\n readonly item: UiWireMap[N]\n}\n\n/** What changed, pushed to {@link UiRegistry.subscribe} listeners. */\nexport type UiChange\n = | { type: 'upsert', entry: UiEntry }\n | { type: 'remove', key: string, token: UiTokenName, extension: string }\n /**\n * A panel's `load` would answer something new: its `subscribe` emitted,\n * or its handle was updated. `sessionId`: only that session's content\n * changed. Hosts reload it while visible.\n */\n | { type: 'panel-changed', panelId: string, extension: string, sessionId?: string }\n /** The composer completion or autocomplete providers changed. */\n | { type: 'providers', kind: 'completion' | 'autocomplete' }\n\n/** A panel would load something new (`panel-changed`), as hosts pass it on. */\nexport interface PanelChangedEvent {\n /** The extension that owns the panel. */\n extensionId: string\n /** `<extension>/<id>`. */\n panelId: string\n /** Set when only this session's content changed. */\n sessionId?: string\n}\n\n/**\n * Calls `listener` each time a panel of `ui` would load something new: its\n * `subscribe` emitted, or its handle was updated. What an in-process host\n * builds its `panelChanged` on; protocol clients get the same events as\n * the `extensions:panel` signal.\n *\n * @param ui - The registry (`runtime.outputs.ui`).\n * @param listener - Gets each change.\n * @returns The unsubscribe.\n */\nexport function onPanelChanged(ui: Pick<UiRegistry, 'subscribe'>, listener: (event: PanelChangedEvent) => void): () => void {\n return ui.subscribe((change) => {\n if (change.type === 'panel-changed')\n listener({ extensionId: change.extension, panelId: change.panelId, ...(change.sessionId ? { sessionId: change.sessionId } : {}) })\n })\n}\n\n/** Every token's entries. */\nexport type UiSnapshot = { readonly [N in UiTokenName]: readonly UiEntry<N>[] }\n\n/** Options for {@link createUiRegistry}. */\nexport interface UiRegistryOptions {\n /** Timer for `timeoutMs`. Default: the real clock. */\n clock?: UiClock\n /** Registry-level log (listener failures). Extension problems go to the extension's own logger. */\n logger?: Logger\n /** Deadline for a callback the hosts invoke (load, resolve, run). Default 8 s. */\n callbackTimeoutMs?: number\n /** An extension's own settings, for the `get` / `set` of its settings-page actions (the runtime gives it). */\n settingsAccess?: UiSourceLookup['settingsAccess']\n /** An extension's own settings actions, for `setting.action` with the extension's id as page id (the runtime gives it). */\n ownActions?: UiSourceLookup['ownActions']\n /** The extensions' commands, by full id (`<extension>.<id>`): sidebar rows resolve their command ids against them. */\n commands?: UiCommandLookup\n}\n\n/** The commands a {@link UiRegistry} resolves sidebar row commands against. */\nexport interface UiCommandLookup {\n /** Whether a command with this full id exists. */\n has: (id: string) => boolean\n /** Calls `listener` after the commands changed. Returns the unsubscribe. */\n subscribe: (listener: () => void) => () => void\n}\n\n/** The host-agnostic UI model all extensions contribute to. */\nexport interface UiRegistry extends UiCallbacks {\n /** The `ctx.add` of one extension (or one of its scopes): registrations attach to `deps.owner`. */\n bind: (deps: DomainDeps) => AddFn\n /** A token's entries, in order. For `reference`, `badge-action` and `theme` the first of each id wins. */\n list: <N extends UiTokenName>(token: N | UiToken<unknown, N>) => readonly UiEntry<N>[]\n /** Every token's entries. */\n snapshot: () => UiSnapshot\n /** One entry by key. */\n get: (key: string) => UiEntry | undefined\n /** Calls `listener` after each change. Returns the unsubscribe. */\n subscribe: (listener: (change: UiChange) => void) => () => void\n /**\n * The full id of a panel or screen an extension names: `<extension>/<id>`\n * when that extension has one by that id, else `id` as given (a full id,\n * or a built-in such as `todos`).\n */\n qualify: (kind: 'panel' | 'screen', extension: string, id: string) => string\n /** `ctx.composer.completions` providers. */\n completions: UiProviderList<CompletionProvider>\n /** `ctx.composer.autocomplete` providers. */\n autocomplete: UiProviderList<InlineAutocompleteProvider>\n /** Withdraws every item scoped to `sessionId` (the session was deleted). */\n removeSession: (sessionId: string) => void\n /** Withdraws every item of an extension. */\n removeExtension: (extensionId: string) => void\n}\n\ninterface Entry extends UiSource {\n key: string\n token: UiTokenName\n seq: number\n raw: object\n wire: UiWireMap[UiTokenName]\n json: string\n identity: string | undefined\n unbind: (() => void)[]\n panelSubscribe?: unknown\n panelUnsubscribe?: () => void\n timer?: unknown\n cleanup?: Disposable\n disposed: boolean\n}\n\n/** Tokens where several extensions may use one id and the first wins. */\nconst FIRST_WINS: ReadonlySet<UiTokenName> = new Set(['reference', 'badge-action', 'theme'])\n\nconst errorText = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n\nfunction serializeWith(refs: UiRefs, deps: DomainDeps, token: UiTokenName, raw: object): UiWireMap[UiTokenName] {\n const read = (readable: Readable<unknown>): unknown => deps.guard.callSync('ui.bindable.get', () => readable.get())\n return serializeUiItem(token, resolveBindables(raw, read) as never, deps.extensionId, refs)\n}\n\nfunction order(entries: Entry[], token: UiTokenName): Entry[] {\n const all = entries.filter(e => e.token === token)\n if (token === 'slot' || token === 'space')\n all.sort((a, b) => ((a.wire as { order: number }).order - (b.wire as { order: number }).order) || a.seq - b.seq)\n else\n all.sort((a, b) => a.seq - b.seq)\n if (!FIRST_WINS.has(token))\n return all\n const seen = new Set<string>()\n return all.filter((e) => {\n const id = e.identity ?? e.key\n if (seen.has(id))\n return false\n seen.add(id)\n return true\n })\n}\n\nfunction publicEntry(e: Entry): UiEntry {\n return { key: e.key, token: e.token, extension: e.extension, item: e.wire }\n}\n\n/**\n * Creates an empty UI registry.\n *\n * @param options - Clock, logger and callback deadline.\n */\nexport function createUiRegistry(options: UiRegistryOptions = {}): UiRegistry {\n const clock = options.clock ?? systemClock\n const entries = new Map<string, Entry>()\n const listeners = new Set<(change: UiChange) => void>()\n let seq = 0\n let referencesVersion = 0\n\n const emit = (change: UiChange): void => {\n const token = change.type === 'remove' ? change.token : change.type === 'upsert' ? change.entry.token : undefined\n if (token === 'reference')\n referencesVersion++\n for (const listener of [...listeners]) {\n try {\n listener(change)\n }\n catch (err) {\n options.logger?.warn('ui registry listener failed', { error: errorText(err) })\n }\n }\n }\n\n const sorted = (token: UiTokenName): Entry[] => order([...entries.values()], token)\n const findById = (token: UiTokenName, id: string): Entry | undefined => sorted(token).find(e => (e.wire as { id?: string }).id === id)\n const refs: UiRefs = {\n hasCommand: id => options.commands?.has(id) ?? false,\n hasSurface: (kind, id) => [...entries.values()].some(e => e.token === kind && (e.wire as { id?: string }).id === id),\n }\n const serialize = (deps: DomainDeps, token: UiTokenName, raw: object): UiWireMap[UiTokenName] => serializeWith(refs, deps, token, raw)\n\n const dispose = (e: Entry): void => {\n if (e.disposed)\n return\n e.disposed = true\n for (const off of e.unbind) off()\n if (e.panelUnsubscribe)\n e.deps.guard.callSync('ui.panel.unsubscribe', e.panelUnsubscribe)\n if (e.timer !== undefined)\n clock.clearTimeout(e.timer)\n e.cleanup?.dispose()\n entries.delete(e.key)\n emit({ type: 'remove', key: e.key, token: e.token, extension: e.extension })\n }\n\n /** Stores a new wire form and pushes it when it differs from the last one. */\n const push = (e: Entry, wire: UiWireMap[UiTokenName]): void => {\n const json = JSON.stringify(wire)\n if (json === e.json)\n return\n e.wire = wire\n e.json = json\n emit({ type: 'upsert', entry: publicEntry(e) })\n }\n\n /** Re-reads bound fields after a readable changed. */\n const refresh = (e: Entry): void => {\n if (e.disposed)\n return\n try {\n push(e, serialize(e.deps, e.token, e.raw))\n }\n catch (err) {\n e.deps.logger.warn(`ui: a bound value made the ${e.token} item invalid; keeping the last one`, { error: errorText(err) })\n }\n }\n\n /** Serializes every sidebar row again: a panel, screen or command its ids may resolve to came or went. */\n const resolveRowsAgain = (): void => {\n for (const e of [...entries.values()]) {\n if (e.token === 'sidebar-row')\n refresh(e)\n }\n }\n listeners.add((change) => {\n const token = change.type === 'remove' ? change.token : change.type === 'upsert' ? change.entry.token : undefined\n if (token === 'panel' || token === 'screen')\n resolveRowsAgain()\n })\n options.commands?.subscribe(resolveRowsAgain)\n\n /** (Re)binds readables, the panel's `subscribe` and the slot timeout to the current raw item. */\n const attach = (e: Entry): void => {\n for (const off of e.unbind) off()\n e.unbind = readablesOf(e.raw).map((readable) => {\n const off = e.deps.guard.callSync('ui.bindable.subscribe', () => readable.subscribe(() => refresh(e)))\n return typeof off === 'function' ? off : () => {}\n })\n const subscribe = e.token === 'panel' ? (e.raw as PanelItem).subscribe : undefined\n if (subscribe !== e.panelSubscribe) {\n if (e.panelUnsubscribe)\n e.deps.guard.callSync('ui.panel.unsubscribe', e.panelUnsubscribe)\n e.panelUnsubscribe = undefined\n e.panelSubscribe = subscribe\n if (typeof subscribe === 'function') {\n const panelId = (e.wire as UiWireMap['panel']).id\n const off = e.deps.guard.callSync('ui.panel.subscribe', () => subscribe((change) => {\n if (e.disposed || e.panelSubscribe !== subscribe)\n return\n const sessionId = typeof change?.sessionId === 'string' && change.sessionId ? change.sessionId : undefined\n emit({ type: 'panel-changed', panelId, extension: e.extension, ...(sessionId ? { sessionId } : {}) })\n }))\n e.panelUnsubscribe = typeof off === 'function' ? off : undefined\n }\n }\n if (e.timer !== undefined)\n clock.clearTimeout(e.timer)\n e.timer = undefined\n const ms = e.token === 'slot' ? (e.raw as { timeoutMs?: unknown }).timeoutMs : undefined\n if (typeof ms === 'number' && Number.isFinite(ms) && ms > 0)\n e.timer = clock.setTimeout(() => dispose(e), ms)\n }\n\n /** Refuses a duplicate id within the extension, and a composer badge past the cap. */\n const assertRoom = (deps: DomainDeps, token: UiTokenName, wire: UiWireMap[UiTokenName], identity: string | undefined): void => {\n const mine = [...entries.values()].filter(e => e.token === token && e.extension === deps.extensionId)\n if (identity !== undefined && isUniquePerExtension(token, wire) && mine.some(e => e.identity === identity))\n throw new TypeError(`${token}: this extension already added one with id ${identity}`)\n const slot = wire as UiWireMap['slot']\n // `composer.badges` counts per session (its identity holds the session), `app.titlebar` across the app.\n const sameBlock = (e: Entry): boolean => (slot.at === 'composer.badges' ? e.identity === identity : (e.wire as UiWireMap['slot']).at === slot.at)\n if (token === 'slot' && isBadgeSlot(slot.at) && mine.filter(sameBlock).length >= MAX_SLOT_BADGES)\n throw new RangeError(slot.at === 'composer.badges' ? `composer.badges: at most ${MAX_SLOT_BADGES} per extension per session` : `${slot.at}: at most ${MAX_SLOT_BADGES} per extension`)\n const cap = SIDEBAR_CAPS[token]\n if (cap !== undefined && mine.length >= cap)\n throw new RangeError(`${token}: at most ${cap} per extension`)\n }\n\n const add = <T>(deps: DomainDeps, token: UiToken<T>, item: T): Handle<T> => {\n if (deps.owner.disposed)\n throw new DisposedError('ctx.add')\n if (!isKnownToken(token as UiToken<unknown>))\n throw new TypeError(`ctx.add: unknown UI token ${String((token as UiToken<unknown>)?.name)}`)\n const name = (token as UiToken<unknown, UiTokenName>).name\n if (!item || typeof item !== 'object')\n throw new TypeError(`${name}: the item must be an object`)\n const raw = { ...(item as object) }\n const wire = serialize(deps, name, raw)\n const identity = wireIdentity(name, wire)\n assertRoom(deps, name, wire, identity)\n seq++\n const e: Entry = { key: `${name}:${deps.extensionId}:${seq}`, token: name, extension: deps.extensionId, seq, deps, raw, wire, json: JSON.stringify(wire), identity, unbind: [], disposed: false }\n entries.set(e.key, e)\n e.cleanup = deps.owner.onCleanup(() => dispose(e))\n attach(e)\n emit({ type: 'upsert', entry: publicEntry(e) })\n return {\n get current() {\n return e.raw as Readonly<T>\n },\n update(patch) {\n if (e.disposed)\n return\n const next = typeof patch === 'function' ? (patch as (current: Readonly<T>) => T)(e.raw as Readonly<T>) : { ...e.raw, ...(patch as object) }\n if (!next || typeof next !== 'object')\n throw new TypeError(`${name}: update must give an object`)\n const nextRaw = { ...(next as object) }\n const nextWire = serialize(deps, name, nextRaw)\n if (wireIdentity(name, nextWire) !== identity)\n throw new TypeError(`${name}: update cannot change the item's id, place or session`)\n e.raw = nextRaw\n attach(e)\n push(e, nextWire)\n // A new `load` (or anything it reads from the item) can answer differently: visible hosts reload.\n if (name === 'panel')\n emit({ type: 'panel-changed', panelId: (nextWire as UiWireMap['panel']).id, extension: e.extension })\n },\n dispose: () => dispose(e),\n }\n }\n\n const callbacks = createUiCallbacks({\n byId: findById,\n all: sorted,\n referencesVersion: () => referencesVersion,\n ...(options.settingsAccess ? { settingsAccess: options.settingsAccess } : {}),\n ...(options.ownActions ? { ownActions: options.ownActions } : {}),\n }, options.callbackTimeoutMs ?? 8_000)\n\n return {\n ...callbacks,\n bind: deps => (token, item) => add(deps, token, item),\n list: <N extends UiTokenName>(token: N | UiToken<unknown, N>) => sorted(typeof token === 'string' ? token : token.name).map(publicEntry) as unknown as readonly UiEntry<N>[],\n snapshot: () => Object.fromEntries(UI_TOKEN_NAMES.map(n => [n, sorted(n).map(publicEntry)])) as unknown as UiSnapshot,\n get: (key) => {\n const e = entries.get(key)\n return e ? publicEntry(e) : undefined\n },\n subscribe: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n qualify: (kind, extension, id) => {\n if (id.includes('/'))\n return id\n const full = `${extension}/${id}`\n return findById(kind, full) ? full : id\n },\n completions: createProviderList<CompletionProvider>('composer.completions', () => emit({ type: 'providers', kind: 'completion' })),\n autocomplete: createProviderList<InlineAutocompleteProvider>('composer.autocomplete', () => emit({ type: 'providers', kind: 'autocomplete' })),\n removeSession: (sessionId) => {\n for (const e of [...entries.values()]) {\n if (e.token === 'slot' && (e.wire as UiWireMap['slot']).sessionId === sessionId)\n dispose(e)\n }\n },\n removeExtension: (extensionId) => {\n for (const e of [...entries.values()]) {\n if (e.extension === extensionId)\n dispose(e)\n }\n },\n }\n}\n"],"mappings":"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O;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EAGE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EAOE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CAIA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CAeA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CAEA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CAEA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAA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"}
1
+ {"version":3,"file":"registry-YUUqbYGr.js","names":["SETTING_TYPES","isRecord","fromStandard"],"sources":["../src/extensions/api/core.ts","../src/extensions/settings/validate.ts","../src/extensions/runtime/validate-definition.ts","../src/chat/keybindings.ts","../src/extensions/commands/keymap.ts","../src/extensions/settings/wire.ts","../src/extensions/host-runtime.ts","../src/extensions/runtime/owner.ts","../src/extensions/api/ui.ts","../src/extensions/ui/settings-form.ts","../src/extensions/ui/wire.ts","../src/extensions/runtime/facets.ts","../src/extensions/storage/port.ts","../src/extensions/storage/cache.ts","../src/extensions/storage/paths.ts","../src/extensions/rpc/json-schema.ts","../src/extensions/rpc/schema.ts","../src/extensions/storage/validate.ts","../src/extensions/storage/store.ts","../src/extensions/storage/domain.ts","../src/extensions/storage/file-port.ts","../src/extensions/storage/memory.ts","../src/extensions/storage/index.ts","../src/extensions/runtime/memory-ports.ts","../src/extensions/runtime/settings-wire.ts","../src/extensions/ui/bindable.ts","../src/extensions/ui/callbacks.ts","../src/extensions/ui/clock.ts","../src/extensions/ui/registry.ts"],"sourcesContent":["/**\n * Extension API: core primitives shared by every domain.\n *\n * Every registration returns a {@link Disposable}. Registrations belong to an\n * {@link Owner}: the extension's root owner, or a child made with\n * `ctx.scope()`. Disposing an owner disposes everything registered through\n * it, in reverse order, and aborts its `signal`.\n */\n\nimport type { StandardSchemaLike } from '../../zod'\n\n/** Something that can be withdrawn. Calling `dispose` twice is a no-op. */\nexport interface Disposable {\n /** Withdraws the registration. Safe to call more than once. */\n dispose: () => void\n}\n\n/** A cleanup function returned from `setup` or passed to `ctx.onCleanup`. */\nexport type Cleanup = () => void | Promise<void>\n\n/**\n * A group of registrations with one lifetime. The extension's root owner\n * lives until the extension unloads. `scope()` makes a child that can end\n * earlier (for example \"while connected\").\n */\nexport interface Owner extends Disposable {\n /** Aborts when the owner is disposed. */\n readonly signal: AbortSignal\n /** `true` once the owner was disposed. Registrations through a disposed owner throw. */\n readonly disposed: boolean\n /** Runs `cleanup` when the owner is disposed. Returns a Disposable that cancels it. */\n onCleanup: (cleanup: Cleanup) => Disposable\n}\n\n/**\n * A live UI contribution. `update` patches the item and pushes it to every\n * host. `dispose` withdraws it.\n */\nexport interface Handle<T> extends Disposable {\n /** The item as the hosts see it now. */\n readonly current: Readonly<T>\n /** Merges `patch` into the item, or replaces it with the function's result. */\n update: (patch: Partial<T> | ((current: Readonly<T>) => T)) => void\n}\n\n/** A value that changes over time. Stores and selectors implement it. */\nexport interface Readable<T> {\n /** The current value. */\n get: () => T\n /** Calls `listener` after each change. Returns the unsubscribe. */\n subscribe: (listener: (value: T) => void) => () => void\n}\n\n/**\n * A field of a UI item that may be a fixed value or a {@link Readable}. A\n * bound field re-pushes the item to the hosts when the readable changes.\n */\nexport type Bindable<T> = T | Readable<T>\n\n/**\n * The state of something another extension provides (a contract, a\n * registry owner, an RPC). Read it where you use it: it changes as the\n * provider starts, stops and reloads.\n */\nexport type Live<T>\n = | { readonly status: 'pending' }\n | { readonly status: 'active', readonly value: T, readonly generation: number }\n | { readonly status: 'inactive', readonly reason?: string }\n\n/** A {@link Live} value you can read and watch. */\nexport interface LiveAccessor<T> extends Readable<Live<T>> {\n /** The value when active, else `undefined`. */\n value: () => T | undefined\n}\n\n/** A plain JSON Schema object. Values validated by it are typed `unknown`. */\nexport type JsonSchema = Readonly<Record<string, unknown>>\n\n/** Either a Standard Schema (zod, valibot, arktype) or a plain JSON Schema. */\nexport type Schema<T = unknown> = StandardSchemaLike<T> | JsonSchema\n\n/** The value type a {@link Schema} accepts: inferred for Standard Schema, `unknown` for JSON Schema. */\nexport type Infer<S> = S extends StandardSchemaLike<infer O> ? O : unknown\n\n/**\n * A reference to a component the extension exports from its `ui` entry\n * (desktop and web) or its `tui` entry (terminal). A host without the\n * named component draws the item's data, or its `fallback`.\n */\nexport interface ComponentRef {\n /** Name of the export in the extension's `ui` / `tui` entry. */\n component: string\n /** JSON props passed to the component. */\n props?: Readonly<Record<string, unknown>>\n}\n\n/**\n * The least client token scope a remote caller needs: the same scopes as\n * every protocol method (`chat` ⊂ `approve` ⊂ `admin`). In-process callers,\n * local connections and other extensions are never limited by it.\n */\nexport type AccessScope = 'chat' | 'approve' | 'admin'\n\n/** Where an extension was found. */\nexport type ExtensionSource = 'project' | 'user' | 'config' | 'inline' | 'builtin'\n\n/** The host process the extension runs in. */\nexport type ExtensionHostKind = 'tui' | 'desktop' | 'daemon' | 'server' | 'sdk'\n\n/** What `ctx.app` tells about the running app. */\nexport interface AppInfo {\n /** Always `'zidane'`. */\n readonly name: 'zidane'\n /** zidane version, semver. */\n readonly version: string\n /** The host process running the extension. */\n readonly host: ExtensionHostKind\n /** `process.platform`. */\n readonly platform: string\n}\n\n/** Filesystem locations given to an extension. */\nexport interface ExtensionPaths {\n /** Working directory of the host. */\n readonly cwd: string\n /** Project root, when the host resolved one. */\n readonly projectRoot?: string\n /** Directory for persistent application data. */\n readonly dataDir: string\n /** Directory for disposable cached files. */\n readonly cacheDir: string\n /** Directory for user configuration. */\n readonly configDir?: string\n /** Directory for runtime state. */\n readonly stateDir?: string\n}\n\n/** Thrown by a ctx call made through a disposed owner. */\nexport class DisposedError extends Error {\n /** @param what - The call that was refused. */\n constructor(what: string) {\n super(`${what}: the extension or scope was disposed`)\n this.name = 'DisposedError'\n }\n}\n","/**\n * Pure checks for the extension settings schema: the static schema of a definition\n * (read without running `setup`) and the values a setting accepts. No host\n * code, no callbacks run except an item's own `validate` when the caller\n * passes it through.\n *\n * Mirrors the legacy config items' read-time rules in `src/extensions/config.ts`\n * (`isValidExtensionConfigValue`): a broken author pattern means \"no\n * constraint\", `step` is a UI hint and never enforced, model ids are not\n * checked against a catalog.\n */\n\nimport type { AccessScope } from '../api/core'\nimport type { ExtensionDefinition } from '../api/define'\nimport type { ActionSetting, Setting, SettingsCategory, SettingScope, SettingsPageSpec, SettingsSchema } from '../api/settings'\n\n/** A value a setting can hold once resolved. Multi model settings hold a list. */\nexport type StoredSettingValue = boolean | number | string | readonly string[]\n\n/** The settings that hold a value (everything but `action`). */\nexport type ValueSetting = Exclude<Setting, ActionSetting>\n\n/** Scopes a setting may be set at when it names none. */\nexport const DEFAULT_SETTING_SCOPES: readonly SettingScope[] = ['user', 'project']\n\nconst ALL_SCOPES: readonly SettingScope[] = ['user', 'project', 'session']\n/**\n * Settings keys: a letter or `_`, then letters, digits, `_`, `.` or `-`\n * (`baseUrl`, `record-mentions`, `API_KEY`). Safe as record keys and in\n * config files once the reserved names are refused (see {@link isSettingKey}).\n */\nexport const SETTING_KEY_PATTERN = /^[A-Z_][\\w.-]*$/i\nconst RESERVED_KEYS = new Set(['__proto__', 'constructor', 'prototype'])\n\n/**\n * Whether `key` may name a setting. The definition validator, the schema\n * cleaner and the config-file reader all use it, so they agree.\n *\n * @param key - A candidate key.\n * @returns `true` for a key matching {@link SETTING_KEY_PATTERN} that is not a reserved name.\n */\nexport function isSettingKey(key: string): boolean {\n return SETTING_KEY_PATTERN.test(key) && !RESERVED_KEYS.has(key)\n}\nconst SETTING_TYPES = new Set(['boolean', 'number', 'string', 'enum', 'model', 'action'])\n\n/** The id of the one page an extension gets when its schema declares no `pages`. */\nexport const DEFAULT_SETTINGS_PAGE_ID = 'main'\n\n/** Settings page ids: the local id rule of UI items (`[A-Za-z0-9_.:-]{1,64}`). */\nexport const SETTINGS_PAGE_ID_PATTERN = /^[\\w.:-]{1,64}$/\n\n/** The token scopes an action may ask for, least first. */\nexport const ACCESS_SCOPES: readonly AccessScope[] = ['chat', 'approve', 'admin']\n\n/** The scope an action needs when it names none. */\nexport const DEFAULT_ACTION_SCOPE: AccessScope = 'admin'\n\n/**\n * The page ids items and sections may name: the declared pages' ids, or\n * {@link DEFAULT_SETTINGS_PAGE_ID} when the schema declares none.\n *\n * @param pages - The declared pages (cleaned or raw ids).\n * @returns The ids a `page` field may hold.\n */\nexport function settingsPageIds(pages: readonly { id: string }[] | undefined): ReadonlySet<string> {\n return new Set(pages && pages.length > 0 ? pages.map(p => p.id) : [DEFAULT_SETTINGS_PAGE_ID])\n}\n\n/**\n * Whether `value` is a settings icon: an object whose `gui` and `tui`, when\n * present, are strings.\n *\n * @param value - A candidate icon.\n */\nexport function isSettingsIcon(value: unknown): value is { gui?: string, tui?: string } {\n if (typeof value !== 'object' || value === null || Array.isArray(value))\n return false\n const icon = value as Record<string, unknown>\n return (icon.gui === undefined || typeof icon.gui === 'string') && (icon.tui === undefined || typeof icon.tui === 'string')\n}\n\n/**\n * The token scope an action needs.\n *\n * @param setting - An action.\n * @returns Its `scope`, or {@link DEFAULT_ACTION_SCOPE}.\n */\nexport function actionScope(setting: ActionSetting): AccessScope {\n return setting.scope ?? DEFAULT_ACTION_SCOPE\n}\n\n/**\n * Whether `setting` holds a value.\n *\n * @param setting - Any setting.\n * @returns `false` for an action.\n */\nexport function isValueSetting(setting: Setting): setting is ValueSetting {\n return setting.type !== 'action'\n}\n\n/**\n * The scopes `setting` may be set at.\n *\n * @param setting - A value setting.\n * @returns Its `scopes`, or {@link DEFAULT_SETTING_SCOPES}.\n */\nexport function settingScopes(setting: ValueSetting): readonly SettingScope[] {\n return setting.scopes ?? DEFAULT_SETTING_SCOPES\n}\n\n/**\n * Splits a stored model list. The Settings UIs store a multi model value as\n * `'a, b'` (see `ExtConfigModelRow` in zidane-ui), so both shapes read.\n *\n * @param value - Comma-separated model ids.\n * @returns The trimmed, non-empty ids.\n */\nexport function parseModelList(value: string): string[] {\n return value.split(',').map(s => s.trim()).filter(s => s.length > 0)\n}\n\n/**\n * Brings a raw stored value into the shape the setting holds: a multi model\n * setting accepts a comma-separated string. Anything else passes unchanged.\n *\n * @param setting - The setting.\n * @param value - The raw value.\n * @returns The value to check.\n */\nexport function normalizeSettingValue(setting: ValueSetting, value: unknown): unknown {\n if (setting.type === 'model' && setting.multi === true && typeof value === 'string')\n return parseModelList(value)\n return value\n}\n\nfunction safeRegExp(pattern: string): RegExp | null {\n try {\n return new RegExp(pattern)\n }\n catch {\n return null\n }\n}\n\n/**\n * Runs an author `validate` callback. Default: called directly, a throw\n * refuses the value with its message.\n */\nexport type ValidateRunner = (validate: (value: string) => string | undefined, value: string) => string | undefined\n\nconst runValidateDirect: ValidateRunner = (validate, value) => {\n try {\n const out = validate(value)\n return typeof out === 'string' && out.length > 0 ? out : undefined\n }\n catch (err) {\n return err instanceof Error && err.message ? err.message : 'invalid value'\n }\n}\n\n/**\n * Checks the type and constraints of a value, without the author\n * `validate` and the string `pattern` (the rules a default must meet).\n */\nfunction checkShape(setting: ValueSetting, value: unknown): string | undefined {\n switch (setting.type) {\n case 'boolean':\n return typeof value === 'boolean' ? undefined : 'expected true or false'\n case 'number':\n if (typeof value !== 'number' || !Number.isFinite(value))\n return 'expected a number'\n if (setting.min !== undefined && value < setting.min)\n return `must be at least ${setting.min}`\n if (setting.max !== undefined && value > setting.max)\n return `must be at most ${setting.max}`\n return undefined\n case 'string':\n return typeof value === 'string' ? undefined : 'expected text'\n case 'enum':\n if (typeof value !== 'string' || !setting.options.some(o => o.value === value))\n return `must be one of: ${setting.options.map(o => o.value).join(', ')}`\n return undefined\n case 'model':\n if (setting.multi === true)\n return Array.isArray(value) && value.every(v => typeof v === 'string') ? undefined : 'expected a list of model ids'\n return typeof value === 'string' ? undefined : 'expected a model id'\n }\n}\n\n/**\n * Checks `value` against `setting`: type, number range, enum membership,\n * string pattern, then the author `validate`. Normalize first\n * ({@link normalizeSettingValue}).\n *\n * @param setting - The setting.\n * @param value - The normalized value.\n * @param runValidate - How to call the author `validate` (the domain passes its guard).\n * @returns An error message, or `undefined` when the value is accepted.\n */\nexport function checkSettingValue(setting: ValueSetting, value: unknown, runValidate: ValidateRunner = runValidateDirect): string | undefined {\n const shape = checkShape(setting, value)\n if (shape !== undefined)\n return shape\n if (setting.type !== 'string')\n return undefined\n const text = value as string\n if (setting.pattern) {\n const re = safeRegExp(setting.pattern)\n if (re && !re.test(text))\n return `does not match ${setting.pattern}`\n }\n if (typeof setting.validate === 'function')\n return runValidate(setting.validate, text)\n return undefined\n}\n\n/**\n * The declared default of a setting, in the shape it holds. A multi model\n * default given as a string is split. An unusable default is `undefined`\n * ({@link settingsForDefinition} reports it).\n *\n * @param setting - A value setting.\n * @returns The default, or `undefined` when none is declared.\n */\nexport function settingDefault(setting: ValueSetting): StoredSettingValue | undefined {\n if (setting.default === undefined)\n return undefined\n const value = normalizeSettingValue(setting, setting.default)\n return checkShape(setting, value) === undefined ? value as StoredSettingValue : undefined\n}\n\n/** The static settings of a definition, cleaned. */\nexport interface StaticSettings {\n /** The extension id. */\n readonly extensionId: string\n /** The schema with malformed sections and items removed. Empty when the definition declares none. */\n readonly schema: SettingsSchema\n /** What was removed or ignored, one line each. */\n readonly issues: readonly string[]\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null\n}\n\n/** Checks one authored item. Returns the cleaned item, or `null` to drop it. */\nfunction cleanItem(key: string, raw: unknown, sectionPages: ReadonlyMap<string, string | undefined>, pageIds: ReadonlySet<string>, issue: (msg: string) => void): Setting | null {\n if (!isSettingKey(key)) {\n issue(`setting \"${key}\": the key is not a safe identifier`)\n return null\n }\n if (!isObject(raw) || typeof raw.type !== 'string' || !SETTING_TYPES.has(raw.type)) {\n issue(`setting \"${key}\": unknown type`)\n return null\n }\n if (typeof raw.label !== 'string') {\n issue(`setting \"${key}\": label must be a string`)\n return null\n }\n let item = { ...raw } as unknown as Setting\n if (item.section !== undefined && !sectionPages.has(item.section)) {\n issue(`setting \"${key}\": unknown section \"${item.section}\", shown ungrouped`)\n const { section: _section, ...rest } = item\n item = rest as Setting\n }\n if (item.page !== undefined && (typeof item.page !== 'string' || !pageIds.has(item.page))) {\n issue(`setting \"${key}\": unknown page \"${String(item.page)}\", shown on the first page`)\n const { page: _page, ...rest } = item\n item = rest as Setting\n }\n if (item.page !== undefined && item.section !== undefined && item.page !== (sectionPages.get(item.section) ?? [...pageIds][0])) {\n issue(`setting \"${key}\": section \"${item.section}\" is not on page \"${item.page}\", shown ungrouped`)\n const { section: _section, ...rest } = item\n item = rest as Setting\n }\n if (item.type === 'action') {\n if (typeof item.run !== 'function') {\n issue(`setting \"${key}\": an action needs a run function`)\n return null\n }\n if (item.status !== undefined && typeof item.status !== 'function') {\n issue(`setting \"${key}\": status must be a function, ignored`)\n const { status: _status, ...rest } = item\n item = rest as ActionSetting\n }\n if (item.scope !== undefined && !ACCESS_SCOPES.includes(item.scope)) {\n issue(`setting \"${key}\": scope must be chat, approve or admin, using admin`)\n const { scope: _scope, ...rest } = item\n item = rest as ActionSetting\n }\n return item\n }\n if (item.type === 'enum') {\n const options = Array.isArray(item.options) ? item.options : []\n const values = options.map(o => isObject(o) ? o.value : undefined)\n if (options.length === 0 || !options.every(o => isObject(o) && typeof o.value === 'string' && typeof o.label === 'string') || new Set(values).size !== values.length) {\n issue(`setting \"${key}\": an enum needs options with unique string values and labels`)\n return null\n }\n }\n if (item.type === 'number' && item.min !== undefined && item.max !== undefined && item.min > item.max) {\n issue(`setting \"${key}\": min is greater than max`)\n return null\n }\n if (item.scopes !== undefined) {\n const scopes = Array.isArray(item.scopes) ? item.scopes.filter(s => ALL_SCOPES.includes(s)) : []\n if (scopes.length !== (Array.isArray(item.scopes) ? item.scopes.length : -1) || scopes.length === 0) {\n issue(`setting \"${key}\": invalid scopes, using the default`)\n const { scopes: _scopes, ...rest } = item\n item = rest as ValueSetting\n }\n }\n if (item.default !== undefined && settingDefault(item) === undefined) {\n issue(`setting \"${key}\": the default does not fit the setting, ignored`)\n const { default: _default, ...rest } = item\n item = rest as ValueSetting\n }\n return item\n}\n\n/**\n * Reads the settings a definition declares, without running `setup`. A\n * disabled extension shows these in Settings. Never calls author code.\n * Malformed categories, pages, sections and items are dropped, and unknown\n * page or section references removed (reported in `issues`), so the rest\n * of the schema still shows.\n *\n * @param def - The definition (only `id` and `settings` are read).\n * @returns The cleaned schema and what was dropped.\n */\nexport function settingsForDefinition(def: Pick<ExtensionDefinition, 'id' | 'settings'>): StaticSettings {\n const issues: string[] = []\n const issue = (msg: string): void => {\n issues.push(msg)\n }\n const raw: unknown = def.settings\n if (raw === undefined)\n return { extensionId: def.id, schema: { sections: [], items: {} }, issues }\n if (!isObject(raw) || !isObject(raw.items)) {\n issue('settings: expected { items }')\n return { extensionId: def.id, schema: { sections: [], items: {} }, issues }\n }\n let category: SettingsCategory | undefined\n if (raw.category !== undefined) {\n if (isObject(raw.category) && typeof raw.category.label === 'string' && raw.category.label.length > 0) {\n category = { label: raw.category.label }\n if (isSettingsIcon(raw.category.icon))\n category.icon = { ...raw.category.icon }\n else if (raw.category.icon !== undefined)\n issue('settings.category: icon must be { gui?, tui? } strings, ignored')\n }\n else {\n issue('settings.category: needs a label, ignored')\n }\n }\n const pages: SettingsPageSpec[] = []\n for (const p of Array.isArray(raw.pages) ? raw.pages as unknown[] : []) {\n if (!isObject(p) || typeof p.id !== 'string' || !SETTINGS_PAGE_ID_PATTERN.test(p.id) || typeof p.label !== 'string') {\n issue('settings: a page needs an id ([A-Za-z0-9_.:-]{1,64}) and a label')\n continue\n }\n if (pages.some(x => x.id === p.id)) {\n issue(`settings: duplicate page \"${p.id}\"`)\n continue\n }\n pages.push({\n id: p.id,\n label: p.label,\n ...(typeof p.description === 'string' ? { description: p.description } : {}),\n ...(isSettingsIcon(p.icon) ? { icon: { ...p.icon } } : {}),\n })\n }\n const pageIds = settingsPageIds(pages)\n const sections: { id: string, label: string, description?: string, page?: string }[] = []\n for (const s of Array.isArray(raw.sections) ? raw.sections as unknown[] : []) {\n if (!isObject(s) || typeof s.id !== 'string' || typeof s.label !== 'string') {\n issue('settings: a section needs an id and a label')\n continue\n }\n if (sections.some(x => x.id === s.id)) {\n issue(`settings: duplicate section \"${s.id}\"`)\n continue\n }\n let page: string | undefined\n if (s.page !== undefined) {\n if (typeof s.page === 'string' && pageIds.has(s.page))\n page = s.page\n else\n issue(`settings: section \"${s.id}\": unknown page \"${String(s.page)}\", shown on the first page`)\n }\n sections.push({ id: s.id, label: s.label, ...(typeof s.description === 'string' ? { description: s.description } : {}), ...(page !== undefined ? { page } : {}) })\n }\n const sectionPages = new Map(sections.map(s => [s.id, s.page]))\n const items: Record<string, Setting> = {}\n for (const [key, value] of Object.entries(raw.items)) {\n const item = cleanItem(key, value, sectionPages, pageIds, issue)\n if (item)\n items[key] = item\n }\n const schema: SettingsSchema = {\n ...(category ? { category } : {}),\n ...(pages.length > 0 ? { pages } : {}),\n sections,\n items,\n }\n return { extensionId: def.id, schema, issues }\n}\n","/**\n * Checks an extension module's default export against the extension\n * definition (`src/extensions/api/define.ts`) before the runtime touches it.\n *\n * Problems that would make the extension misbehave are errors and refuse the\n * load; fields the definition does not have are warnings. Every problem names the\n * field it is about, so the Settings row can say what to fix.\n */\n\nimport type { ExtensionDefinition } from '../api/define'\nimport type { Setting } from '../api/settings'\nimport { satisfiesVersionRange } from '../host-version'\nimport { ACCESS_SCOPES, isSettingKey, isSettingsIcon, SETTINGS_PAGE_ID_PATTERN, settingsPageIds } from '../settings/validate'\n\n/** Lowercase words of letters and digits joined by `-`, starting with a letter: `git-flow`, `s3-sync`. */\nexport const EXTENSION_ID_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/\n\n/** Where the error of an extension written for zidane 9's API sends its author. */\nconst EXTENSION_DOCS_URL = 'https://zidane.si/docs/extensions'\n\nconst SETTING_TYPES = new Set(['boolean', 'number', 'string', 'enum', 'model', 'action'])\nconst SETTING_SCOPES = new Set(['user', 'project', 'session'])\nconst SETTING_APPLY = new Set(['live', 'agent-rebuild', 'restart'])\nconst KNOWN_FIELDS = new Set(['apiVersion', 'id', 'displayName', 'icon', 'version', 'description', 'dependencies', 'settings', 'ui', 'tui', 'setup'])\n/** Fields the definition does not have, with what to use instead. */\nconst REMOVED_FIELDS: Readonly<Record<string, string>> = {\n name: 'use `id`',\n teardown: 'return a cleanup function from `setup`',\n permissions: 'permissions were removed; extensions are trusted on install',\n capabilities: 'capabilities were removed',\n}\n\n/** One problem found in a definition. */\nexport interface DefinitionIssue {\n /** The field it is about, as a dotted path (`settings.items.token.default`), or `''` for the whole value. */\n path: string\n /** What is wrong and, when it helps, what to do. */\n message: string\n}\n\n/** What {@link validateDefinition} found. */\nexport type DefinitionValidation\n = | { ok: true, definition: ExtensionDefinition, warnings: readonly DefinitionIssue[] }\n | { ok: false, errors: readonly DefinitionIssue[], warnings: readonly DefinitionIssue[] }\n\n/** Options for {@link validateDefinition}. */\nexport interface ValidateDefinitionOptions {\n /** The folder the extension was discovered in. The id must equal it. */\n folderName?: string\n}\n\n/**\n * Whether `value` claims to be an extension definition: an object with\n * `apiVersion: 1`. The loader prefers such an export over other objects;\n * {@link validateDefinition} then checks the rest.\n *\n * @param value - A module's default export.\n */\nexport function looksLikeDefinition(value: unknown): value is ExtensionDefinition {\n return isRecord(value) && value.apiVersion === 1\n}\n\n/**\n * Checks `value` against the extension definition: `apiVersion: 1`, a valid\n * `id` (equal to `folderName` when given), a `setup` function, string\n * metadata, a valid semver `version`, `dependencies` with valid ids and\n * semver ranges, and a sane `settings` schema.\n *\n * @param value - A module's default export.\n * @param options - The folder name, for discovered extensions.\n * @returns The definition and warnings, or the errors.\n */\nexport function validateDefinition(value: unknown, options: ValidateDefinitionOptions = {}): DefinitionValidation {\n const errors: DefinitionIssue[] = []\n const warnings: DefinitionIssue[] = []\n const error = (path: string, message: string): void => { errors.push({ path, message }) }\n const warn = (path: string, message: string): void => { warnings.push({ path, message }) }\n\n if (!isRecord(value)) {\n error('', 'The default export must be an extension definition object.')\n return { ok: false, errors, warnings }\n }\n\n if (value.apiVersion !== 1) {\n error('apiVersion', value.apiVersion === undefined\n ? 'Missing `apiVersion: 1`.'\n : `Unsupported apiVersion ${JSON.stringify(value.apiVersion)}. This zidane runs apiVersion 1.`)\n }\n\n if ((typeof value.id !== 'string' || !value.id) && typeof value.name === 'string')\n error('id', `Missing \\`id\\`. This looks like an extension written for zidane 9 (\\`name\\`, no \\`id\\`): zidane 10 replaced that extension API. Port it to the current one: ${EXTENSION_DOCS_URL}`)\n else if (typeof value.id !== 'string' || !value.id)\n error('id', 'Missing `id`.')\n else if (!EXTENSION_ID_PATTERN.test(value.id))\n error('id', `Invalid id \"${value.id}\": use lowercase words joined by \"-\" (e.g. \"git-flow\").`)\n else if (options.folderName !== undefined && value.id !== options.folderName)\n error('id', `The id \"${value.id}\" must equal its folder name \"${options.folderName}\".`)\n\n if (typeof value.setup !== 'function')\n error('setup', 'Missing `setup` function.')\n\n for (const field of ['displayName', 'description', 'ui', 'tui'] as const) {\n if (value[field] !== undefined && typeof value[field] !== 'string')\n error(field, `\\`${field}\\` must be a string.`)\n }\n if (value.icon !== undefined && !isSettingsIcon(value.icon))\n error('icon', '`icon` must be { gui?, tui? } with string values.')\n if (value.version !== undefined) {\n // `*` accepts every version that parses, so this is a parse check that reuses the host's semver reader.\n if (typeof value.version !== 'string' || satisfiesVersionRange(value.version, '*') === undefined)\n error('version', `\\`version\\` must be a semver version like \"1.2.3\", got ${JSON.stringify(value.version)}.`)\n }\n\n checkDependencies(value.dependencies, typeof value.id === 'string' ? value.id : undefined, error)\n if (value.settings !== undefined)\n checkSettings(value.settings, error, warn)\n\n for (const key of Object.keys(value)) {\n if (key in REMOVED_FIELDS)\n warn(key, `\\`${key}\\` is not part of the extension definition and is ignored: ${REMOVED_FIELDS[key]}.`)\n else if (!KNOWN_FIELDS.has(key))\n warn(key, `Unknown field \\`${key}\\` is ignored.`)\n }\n\n return errors.length > 0\n ? { ok: false, errors, warnings }\n : { ok: true, definition: value as unknown as ExtensionDefinition, warnings }\n}\n\ntype Report = (path: string, message: string) => void\n\nfunction checkDependencies(dependencies: unknown, selfId: string | undefined, error: Report): void {\n if (dependencies === undefined)\n return\n if (!isRecord(dependencies)) {\n error('dependencies', '`dependencies` must be an object of { id: semver range }.')\n return\n }\n for (const [id, range] of Object.entries(dependencies)) {\n const path = `dependencies.${id}`\n if (!EXTENSION_ID_PATTERN.test(id))\n error(path, `Invalid dependency id \"${id}\".`)\n else if (id === selfId)\n error(path, 'An extension cannot depend on itself.')\n // Any version checks the range parses: `satisfiesVersionRange` is `undefined` only when it doesn't.\n if (typeof range !== 'string' || satisfiesVersionRange('0.0.0', range) === undefined)\n error(path, `Invalid semver range ${JSON.stringify(range)} (e.g. \"^1.2.0\", \">=2\", \"*\").`)\n }\n}\n\nfunction checkSettings(settings: unknown, error: Report, warn: Report): void {\n if (!isRecord(settings) || !isRecord(settings.items)) {\n error('settings', '`settings` must be an object with an `items` record.')\n return\n }\n if (settings.category !== undefined) {\n const category = settings.category\n if (!isRecord(category) || typeof category.label !== 'string' || !category.label)\n error('settings.category', '`category` needs a string `label`.')\n else if (category.icon !== undefined && !isSettingsIcon(category.icon))\n error('settings.category.icon', '`icon` must be { gui?, tui? } with string values.')\n }\n const declaredPages: { id: string }[] = []\n if (settings.pages !== undefined) {\n if (!Array.isArray(settings.pages)) {\n error('settings.pages', '`pages` must be an array.')\n }\n else {\n settings.pages.forEach((page: unknown, i) => {\n const path = `settings.pages.${i}`\n if (!isRecord(page) || typeof page.id !== 'string' || !SETTINGS_PAGE_ID_PATTERN.test(page.id) || typeof page.label !== 'string' || !page.label)\n error(path, 'A page needs an `id` ([A-Za-z0-9_.:-], 64 at most) and a string `label`.')\n else if (declaredPages.some(p => p.id === page.id))\n error(path, `Duplicate page id \"${page.id}\".`)\n else\n declaredPages.push({ id: page.id })\n if (isRecord(page) && page.description !== undefined && typeof page.description !== 'string')\n error(`${path}.description`, '`description` must be a string.')\n if (isRecord(page) && page.icon !== undefined && !isSettingsIcon(page.icon))\n error(`${path}.icon`, '`icon` must be { gui?, tui? } with string values.')\n })\n }\n }\n const pageIds = settingsPageIds(declaredPages)\n const pageList = [...pageIds].join(', ')\n // Section id → the page it sits on (the first page when it names none).\n const sectionIds = new Map<string, string>()\n if (settings.sections !== undefined) {\n if (!Array.isArray(settings.sections)) {\n error('settings.sections', '`sections` must be an array.')\n }\n else {\n settings.sections.forEach((section: unknown, i) => {\n const path = `settings.sections.${i}`\n if (!isRecord(section) || typeof section.id !== 'string' || !section.id || typeof section.label !== 'string')\n error(path, 'A section needs a string `id` and `label`.')\n else if (sectionIds.has(section.id))\n error(path, `Duplicate section id \"${section.id}\".`)\n else if (section.page !== undefined && (typeof section.page !== 'string' || !pageIds.has(section.page)))\n error(`${path}.page`, `Unknown page ${JSON.stringify(section.page)} (pages: ${pageList}).`)\n else\n sectionIds.set(section.id, typeof section.page === 'string' ? section.page : [...pageIds][0]!)\n })\n }\n }\n for (const [key, item] of Object.entries(settings.items)) {\n const path = `settings.items.${key}`\n if (!isSettingKey(key)) {\n error(path, `Invalid settings key \"${key}\": start with a letter or _, then use letters, digits, _, . or - (\"baseUrl\", \"record-mentions\").`)\n continue\n }\n checkSetting(item, path, sectionIds, pageIds, error, warn)\n }\n}\n\nfunction checkSetting(item: unknown, path: string, sectionIds: ReadonlyMap<string, string>, pageIds: ReadonlySet<string>, error: Report, warn: Report): void {\n if (!isRecord(item) || typeof item.type !== 'string' || !SETTING_TYPES.has(item.type)) {\n error(path, `A setting needs a \\`type\\` (${[...SETTING_TYPES].join(', ')}).`)\n return\n }\n const setting = item as unknown as Setting\n if (typeof setting.label !== 'string' || !setting.label)\n error(`${path}.label`, 'A setting needs a `label`.')\n if (setting.section !== undefined && !sectionIds.has(setting.section))\n warn(`${path}.section`, `Unknown section \"${setting.section}\"; the setting shows ungrouped.`)\n if (setting.page !== undefined) {\n if (typeof setting.page !== 'string' || !pageIds.has(setting.page))\n error(`${path}.page`, `Unknown page ${JSON.stringify(setting.page)} (pages: ${[...pageIds].join(', ')}).`)\n else if (setting.section !== undefined && sectionIds.has(setting.section) && sectionIds.get(setting.section) !== setting.page)\n error(`${path}.page`, `Section \"${setting.section}\" is on page \"${sectionIds.get(setting.section)}\", not \"${setting.page}\".`)\n }\n if (setting.scopes !== undefined && (!Array.isArray(setting.scopes) || setting.scopes.length === 0 || !setting.scopes.every(s => SETTING_SCOPES.has(s))))\n error(`${path}.scopes`, '`scopes` must be a non-empty list of user, project, session.')\n if (setting.apply !== undefined && !SETTING_APPLY.has(setting.apply))\n error(`${path}.apply`, '`apply` must be live, agent-rebuild or restart.')\n\n const badDefault = (expected: string): void => error(`${path}.default`, `\\`default\\` must be ${expected}.`)\n switch (setting.type) {\n case 'boolean':\n if (setting.default !== undefined && typeof setting.default !== 'boolean')\n badDefault('a boolean')\n break\n case 'number': {\n const { min, max, default: d } = setting\n for (const [name, v] of [['min', min], ['max', max], ['step', setting.step]] as const) {\n if (v !== undefined && (typeof v !== 'number' || !Number.isFinite(v)))\n error(`${path}.${name}`, `\\`${name}\\` must be a finite number.`)\n }\n if (typeof min === 'number' && typeof max === 'number' && min > max)\n error(path, '`min` is greater than `max`.')\n if (d !== undefined && (typeof d !== 'number' || !Number.isFinite(d)))\n badDefault('a finite number')\n else if (typeof d === 'number' && ((typeof min === 'number' && d < min) || (typeof max === 'number' && d > max)))\n badDefault('within min and max')\n break\n }\n case 'string':\n if (setting.default !== undefined && typeof setting.default !== 'string')\n badDefault('a string')\n if (setting.pattern !== undefined) {\n try {\n // eslint-disable-next-line no-new\n new RegExp(setting.pattern)\n }\n catch {\n error(`${path}.pattern`, `Invalid regular expression ${JSON.stringify(setting.pattern)}.`)\n }\n }\n if (setting.validate !== undefined && typeof setting.validate !== 'function')\n error(`${path}.validate`, '`validate` must be a function.')\n if (setting.secret && setting.default !== undefined)\n warn(`${path}.default`, 'A secret setting should not ship a default.')\n break\n case 'enum': {\n const options = setting.options as unknown\n if (!Array.isArray(options) || options.length === 0 || !options.every(o => isRecord(o) && typeof o.value === 'string' && typeof o.label === 'string')) {\n error(`${path}.options`, '`options` must be a non-empty list of { value, label }.')\n break\n }\n const values = options.map(o => o.value as string)\n if (new Set(values).size !== values.length)\n error(`${path}.options`, 'Option values must be unique.')\n if (setting.default !== undefined && !values.includes(setting.default))\n badDefault(`one of the option values (${values.join(', ')})`)\n break\n }\n case 'model':\n if (setting.default !== undefined) {\n const ok = setting.multi\n ? Array.isArray(setting.default) && setting.default.every(v => typeof v === 'string')\n : typeof setting.default === 'string'\n if (!ok)\n badDefault(setting.multi ? 'a list of model ids' : 'a model id')\n }\n break\n case 'action':\n if (typeof setting.button !== 'string' || !setting.button)\n error(`${path}.button`, 'An action needs a `button` label.')\n if (typeof setting.run !== 'function')\n error(`${path}.run`, 'An action needs a `run` function.')\n if (setting.status !== undefined && typeof setting.status !== 'function')\n error(`${path}.status`, '`status` must be a function.')\n if (setting.scope !== undefined && !ACCESS_SCOPES.includes(setting.scope))\n error(`${path}.scope`, '`scope` must be chat, approve or admin.')\n break\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","/**\n * Keybindings — a single source of truth for the app's global shortcuts.\n *\n * Every customizable action is declared once in {@link KEYBINDING_DEFS}\n * with its default trigger, label, and description. The TUI imports\n * `DEFAULT_KEYBINDINGS` for the baked-in defaults; on launch we load\n * `<userDir>/keybindings.json` (when present) and merge user overrides\n * on top so the user can rebind any action without recompiling.\n *\n * Scope (deliberate):\n *\n * - We expose the **global, action-opening** shortcuts (\"open the\n * Settings modal\", \"cycle agent profile\", \"enter select-turn\n * mode\", etc.), the message-queue keys, and the letter shortcuts of\n * the turn-details and session-details modals (`f` fork, `d` delete,\n * `c` copy). Universal navigation (`↑/↓/↵/⎋`) stays hardcoded — it\n * lives too close to a renderable's input contract to remap safely.\n *\n * - Storage lives at the **user level** (`<userDir>/keybindings.json`),\n * never inside a project's `.{prefix}/`. Shortcut muscle memory is\n * a per-user concern, not a per-repo one.\n *\n * Format on disk: JSON with `//` and `/* … *\\/` comments allowed\n * (parsed via a small JSONC stripper). Each entry maps an action id\n * to a binding spec string. Specs are parsed by {@link parseBindingSpec};\n * unknown / malformed entries fall back to the default for that action,\n * so a syntax slip never bricks the TUI.\n */\n\nimport type { ParsedBinding } from './keybinding-spec'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { writeFileAtomic } from '../atomic-write'\nimport { bindingAlternatives, parseBindingSpec, parseBindingSpecs } from './keybinding-spec'\n\nexport { bindingAlternatives, parseBindingSpec, parseBindingSpecs, type ParsedBinding } from './keybinding-spec'\n\n// ---------------------------------------------------------------------------\n// Action catalog\n// ---------------------------------------------------------------------------\n\n/**\n * Every action the keybindings system can drive. Adding a new action\n * here forces every consumer (TUI keyboard handler, hint rows, settings\n * UI) to handle it, and ships a default that the user can override.\n */\nexport type KeyAction\n // Global action shortcuts — fire from the top-level keyboard\n // handler (`handleAppKey` in `tui/shell/app-keyboard.tsx`), gated on screen / busy state.\n = | 'openSettings'\n | 'openSessionDetails'\n | 'newSession'\n | 'openModelPicker'\n | 'openEffortPicker'\n | 'openTodos'\n | 'openArtifacts'\n | 'panelNext'\n | 'panelPrev'\n | 'nextSpace'\n | 'prevSpace'\n | 'openContextPanel'\n | 'openMainSession'\n | 'openUsagePanel'\n | 'openKeybindings'\n | 'openPalette'\n | 'cycleAgent'\n | 'enterSelectTurnMode'\n | 'cancelToolCall'\n | 'abortRun'\n | 'changeCwd'\n | 'attachClipboardImage'\n | 'openExternalEditor'\n // Sessions list — only on the sessions screen (`handleAppKey`), so\n // its defaults may repeat a chord the chat uses.\n | 'cycleSpaceInList'\n // Message-queue navigation — only meaningful when the user has\n // type-ahead prompts waiting in the queue box above the prompt\n // input. `enterQueueSelection` moves the focus from the textarea\n // into the queue; while there, `pushQueuedMessage` (steers the\n // selected entry into the live run) and `dropQueuedMessage`\n // (removes the entry) act on the highlighted row.\n | 'enterQueueSelection'\n | 'pushQueuedMessage'\n | 'dropQueuedMessage'\n // Turn-details modal actions (`ctrl+s` select-turn mode → enter).\n // Each binding only matches while that modal is mounted, so the\n // single-letter defaults can clash with letters used elsewhere\n // without conflict.\n | 'turnFork'\n | 'turnDelete'\n | 'turnCopy'\n | 'turnEdit'\n // Session-details modal actions (opened via `ctrl+shift+x`).\n | 'sessionDelete'\n | 'sessionCopyId'\n | 'sessionGenerateTitle'\n | 'sessionExportMarkdown'\n | 'sessionExportJson'\n | 'sessionCompact'\n | 'sessionMoveSpace'\n | 'sessionFavorite'\n | 'sessionMoveEnvironment'\n\n/** Resolved keybindings — every action has a current spec string. */\nexport type KeyBindings = Record<KeyAction, string>\n\n/**\n * Resolved spec string for one extension-contributed keybinding. Same\n * shape as a built-in {@link KeyBindings} entry but the `id` is\n * extension-owned (no `KeyAction` union member). The TUI dispatcher\n * iterates these alongside the built-ins; user overrides flow through\n * the same `keybindings.json` file by matching on `id`.\n */\nexport interface ResolvedExtensionKeybinding {\n /** Extension-owned id (matches `ExtensionKeybinding.id`). */\n id: string\n /** Active spec string — user override when present, default otherwise. May be empty (= unbound). */\n spec: string\n}\n\n/**\n * Logical grouping for one action — used by the keybindings panel to\n * render section headers. Stable strings (not an enum) so future\n * groups can be added without churning every existing entry.\n *\n * `Sessions` actions fire on the sessions screen only, and the\n * `… details` ones only while their modal is open, so their defaults\n * may repeat a chord that acts elsewhere.\n */\nexport type KeyBindingGroup\n = | 'Global'\n | 'Sessions'\n | 'Message queue'\n | 'Turn details'\n | 'Session details'\n\n/** Static metadata for one action — used by the loader, hint rows, settings UI. */\nexport interface KeyBindingDef {\n /** Stable identifier — JSON key + TS union member. */\n action: KeyAction\n /** Default trigger spec (e.g. `'ctrl+o'`). */\n default: string\n /** Short label used in shortcut hint rows. */\n label: string\n /** Longer description for the settings UI and the annotated JSON file. */\n description: string\n /**\n * Group label rendered as a section header in the keybindings panel.\n * Items are listed in {@link KEYBINDING_DEFS} order; the panel just\n * inserts a header whenever this field changes between adjacent\n * entries — so groups stay contiguous and the order here is the\n * order on screen.\n */\n group: KeyBindingGroup\n}\n\n/**\n * The canonical action catalog. Order is the source of truth for the\n * generated keybindings file and the settings UI.\n */\nexport const KEYBINDING_DEFS: readonly KeyBindingDef[] = [\n {\n action: 'openSettings',\n default: 'ctrl+o',\n label: 'settings',\n description: 'open settings',\n group: 'Global',\n },\n {\n // ctrl+shift+x keeps ctrl+x free (the conventional \"cut\" key in most\n // editors). Like the context panel, it relies on the kitty keyboard\n // protocol to stay distinct from ctrl+x; on terminals without it\n // (e.g. macOS Terminal.app) shift is dropped and it collapses to\n // ctrl+x — rebind there.\n action: 'openSessionDetails',\n default: 'ctrl+shift+x',\n label: 'session',\n description: 'open session details: stats, export, rename, delete',\n group: 'Global',\n },\n {\n action: 'newSession',\n default: 'ctrl+n',\n label: 'new session',\n description: 'start a new session with the current model',\n group: 'Global',\n },\n {\n action: 'openModelPicker',\n default: 'ctrl+m',\n label: 'model',\n description: 'open the model picker',\n group: 'Global',\n },\n {\n action: 'openEffortPicker',\n default: 'ctrl+l',\n label: 'options',\n description: 'open model options, like reasoning effort and fast mode',\n group: 'Global',\n },\n {\n action: 'openTodos',\n default: 'ctrl+t',\n label: 'todos',\n description: 'open the run\\'s todo list',\n group: 'Global',\n },\n {\n // ctrl+shift+a: \"artifacts\" — what the run produced, next to todos (ctrl+t),\n // what it planned. Kitty-protocol dependent like the other ctrl+shift\n // chords — collapses to ctrl+a on Terminal.app; rebind there.\n action: 'openArtifacts',\n default: 'ctrl+shift+a',\n label: 'panel',\n description: 'show or hide the side panel',\n group: 'Global',\n },\n {\n action: 'panelNext',\n default: 'ctrl+shift+]',\n label: 'next panel',\n description: 'open the next side-panel tab',\n group: 'Global',\n },\n {\n action: 'panelPrev',\n default: 'ctrl+shift+[',\n label: 'previous panel',\n description: 'open the previous side-panel tab',\n group: 'Global',\n },\n // Spaces (opt-in): the arrows of the sessions list's ←/→ and the GUI's ⌥⌘←/→.\n // kitty and WezTerm keep ctrl+shift+arrows for their own tabs / panes by default: rebind there.\n {\n action: 'nextSpace',\n default: 'ctrl+shift+right',\n label: 'next space',\n description: 'show the next space (Spaces on); from a chat, the sessions list opens on it',\n group: 'Global',\n },\n {\n action: 'prevSpace',\n default: 'ctrl+shift+left',\n label: 'previous space',\n description: 'show the previous space (Spaces on); from a chat, the sessions list opens on it',\n group: 'Global',\n },\n {\n // ctrl+shift+g leans on the kitty keyboard protocol (the renderer\n // enables it) to stay distinct from ctrl+g (`openExternalEditor`). On\n // terminals without it — e.g. macOS Terminal.app — shift is dropped and\n // the keypress collapses to ctrl+g (the editor); rebind there.\n action: 'openContextPanel',\n default: 'ctrl+shift+g',\n label: 'context',\n description: 'show what fills the context window',\n group: 'Global',\n },\n {\n // ctrl+shift+m (\"Main\"): one chord for the TUI and the GUI. Leans on the\n // kitty keyboard protocol (the renderer enables it) to stay distinct from\n // ctrl+m (the model picker); on terminals without it — e.g. macOS\n // Terminal.app — shift is dropped and the keypress collapses to ctrl+m;\n // rebind there. NOT ctrl+u: that is the textarea's kill-to-line-start,\n // which is also what several terminals send for ⌃⌫, so deleting a word\n // would jump to the main session.\n action: 'openMainSession',\n default: 'ctrl+shift+m',\n label: 'main session',\n description: 'open the Main session for this directory, or create it. Needs the \"Main session\" and \"Use daemon runtime\" settings',\n group: 'Global',\n },\n {\n // Plain ctrl+p on purpose: free in OpenTUI's textarea keymap (which owns\n // ctrl+a/e/f/b/w/k/u/d) and in every other global binding, so it behaves\n // the same on kitty and legacy terminals. A ctrl+shift+<x> default would\n // collapse to its unshifted chord on Terminal.app and eat a text-editing\n // key.\n action: 'openUsagePanel',\n default: 'ctrl+p',\n label: 'usage',\n description: 'open plan limits and credits for each provider',\n group: 'Global',\n },\n {\n action: 'openKeybindings',\n default: 'ctrl+y',\n label: 'keybindings',\n description: 'list every shortcut',\n group: 'Global',\n },\n {\n action: 'openPalette',\n // Terminals cannot report cmd, and ctrl+k belongs to cancelToolCall;\n // ctrl+shift+p is the palette chord editors made familiar. The GUI\n // catalog binds this to cmd+k (a declared divergence).\n default: 'ctrl+shift+p',\n label: 'palette',\n description: 'search actions, commands, sessions and settings',\n group: 'Global',\n },\n {\n action: 'cycleAgent',\n default: 'shift+tab',\n label: 'cycle agent',\n description: 'switch to the next agent profile',\n group: 'Global',\n },\n {\n action: 'enterSelectTurnMode',\n default: 'ctrl+s',\n label: 'messages',\n description: 'select a previous message',\n group: 'Global',\n },\n {\n action: 'cancelToolCall',\n default: 'ctrl+k',\n label: 'cancel tool',\n description: 'cancel one tool call and keep the run going',\n group: 'Global',\n },\n {\n action: 'abortRun',\n default: 'ctrl+escape',\n label: 'abort',\n description: 'stop the run and deny pending approvals. If your terminal cannot send ctrl+esc, rebind it',\n group: 'Global',\n },\n {\n action: 'changeCwd',\n default: 'ctrl+h',\n label: 'cwd',\n description: 'change the working directory',\n group: 'Global',\n },\n {\n // The id keeps its original name so existing keybindings.json overrides\n // work; the shortcut pastes text as well as images.\n action: 'attachClipboardImage',\n default: 'ctrl+v',\n label: 'paste clipboard',\n description: 'paste text or an image from the system clipboard',\n group: 'Global',\n },\n {\n // Handled inside `PromptBlock`'s onKeyDown (it owns the textarea ref),\n // NOT the App-level keyboard handler — so it only ever fires while the\n // prompt composer is focused. Gated by the `externalEditor` setting:\n // disabled there, the key falls through to its normal textarea behavior.\n // ctrl+g (Claude Code's muscle-memory key) needs no kitty keyboard\n // protocol; the context panel takes ctrl+shift+g to keep it free.\n action: 'openExternalEditor',\n default: 'ctrl+g',\n label: 'edit in $EDITOR',\n description: 'write the prompt in $EDITOR or $VISUAL. Needs the \"Edit prompt in $EDITOR\" setting',\n group: 'Global',\n },\n // Sessions list. shift+tab is free there: `cycleAgent` only acts in the\n // chat, where shift+tab keeps cycling agents. Also fires while the search\n // input has focus (shift+tab edits no text).\n {\n action: 'cycleSpaceInList',\n default: 'shift+tab',\n label: 'next space',\n description: 'show the next space in the sessions list (wraps), also while typing a search. Needs 2 or more spaces. In a chat, shift+tab still cycles agents',\n group: 'Sessions',\n },\n // Message-queue navigation — only matches when the queue box above\n // the prompt has at least one entry. Defaults pick keys the prompt\n // textarea doesn't already claim (no default for enter — see below).\n //\n // `enterQueueSelection` is intentionally unbound by default: the\n // natural way to enter the queue is to press plain `↑` on an empty\n // prompt buffer (handled in `PromptBlock`'s onKeyDown), which doesn't\n // need a global shortcut. The action stays in the catalog so users\n // who want a dedicated key — e.g. for entering the queue WITHOUT\n // emptying their draft first — can rebind it in `keybindings.json`.\n // We don't ship a default because no arrow / modifier combo is both\n // free in OpenTUI's textarea AND forwarded by every common terminal\n // (ctrl+arrow → macOS Mission Control; cmd+arrow → terminal scroll /\n // tab nav; alt+arrow → terminal word-nav).\n {\n action: 'enterQueueSelection',\n default: '',\n label: 'select queue',\n description: 'select the queued messages (or press ↑ on an empty prompt)',\n group: 'Message queue',\n },\n {\n action: 'pushQueuedMessage',\n default: 'ctrl+return',\n label: 'push',\n description: 'send the selected queued message into the running turn',\n group: 'Message queue',\n },\n {\n action: 'dropQueuedMessage',\n default: 'backspace',\n label: 'drop',\n description: 'remove the selected queued message',\n group: 'Message queue',\n },\n // Turn-details modal — only fires while that modal is mounted.\n {\n action: 'turnFork',\n default: 'f',\n label: 'fork',\n description: 'fork the session at this turn (press twice)',\n group: 'Turn details',\n },\n {\n action: 'turnDelete',\n default: 'd',\n label: 'delete',\n description: 'delete this turn (press twice)',\n group: 'Turn details',\n },\n {\n action: 'turnCopy',\n default: 'c',\n label: 'copy',\n description: 'copy this turn',\n group: 'Turn details',\n },\n {\n action: 'turnEdit',\n default: 'e',\n label: 'edit',\n description: 'edit this turn\\'s text',\n group: 'Turn details',\n },\n // Session-details modal — only fires while that modal is mounted.\n {\n action: 'sessionDelete',\n default: 'd',\n label: 'delete',\n description: 'delete the session (press twice)',\n group: 'Session details',\n },\n {\n action: 'sessionCopyId',\n default: 'c',\n label: 'copy id',\n description: 'copy the session id',\n group: 'Session details',\n },\n {\n action: 'sessionGenerateTitle',\n default: 'g',\n label: 'generate title',\n description: 'title the session with the current model',\n group: 'Session details',\n },\n {\n action: 'sessionExportMarkdown',\n default: 'e',\n label: 'export md',\n description: 'export the session as Markdown under .{prefix}/sessions/',\n group: 'Session details',\n },\n {\n action: 'sessionExportJson',\n default: 'j',\n label: 'export json',\n description: 'export the session as JSON under .{prefix}/sessions/',\n group: 'Session details',\n },\n {\n action: 'sessionCompact',\n default: 'k',\n label: 'compact',\n description: 'summarize older turns to free context',\n group: 'Session details',\n },\n {\n action: 'sessionMoveSpace',\n default: 's',\n label: 'space',\n description: 'move the session to the next space (needs Spaces)',\n group: 'Session details',\n },\n {\n action: 'sessionFavorite',\n default: 'f',\n label: 'favorite',\n description: 'add the session to favorites, or remove it',\n group: 'Session details',\n },\n {\n action: 'sessionMoveEnvironment',\n default: 'm',\n label: 'move',\n description: 'move the session to another environment or machine',\n group: 'Session details',\n },\n]\n\n/** Index by action for O(1) lookup of label / description / default. */\nexport const KEYBINDING_DEF_BY_ACTION: Readonly<Record<KeyAction, KeyBindingDef>>\n = KEYBINDING_DEFS.reduce(\n (acc, def) => Object.assign(acc, { [def.action]: def }),\n {} as Record<KeyAction, KeyBindingDef>,\n )\n\n/** Defaults, derived from {@link KEYBINDING_DEFS} so the two never drift. */\nexport const DEFAULT_KEYBINDINGS: KeyBindings\n = KEYBINDING_DEFS.reduce(\n (acc, def) => Object.assign(acc, { [def.action]: def.default }),\n {} as KeyBindings,\n )\n\n// ---------------------------------------------------------------------------\n// Spec parsing + matching\n// ---------------------------------------------------------------------------\n\n/**\n * Test a KeyEvent against a parsed-or-string binding. Accepts either\n * form so callers can pre-parse (hot path) or pass the raw spec for\n * one-off checks.\n *\n * Modifier semantics: ALL declared modifiers must be pressed AND no\n * extra modifiers may be pressed. So `'o'` does NOT match `ctrl+o`,\n * and `'ctrl+o'` does NOT match `ctrl+shift+o`. This avoids surprises\n * where a binding that should be specific accidentally fires for a\n * superset of key combinations.\n *\n * @param event - Key event to test.\n * @param spec - Binding spec string, or a chord already parsed with {@link parseBindingSpec}.\n */\nexport function matchesBinding(\n event: { name?: string, ctrl?: boolean, shift?: boolean, meta?: boolean, option?: boolean, alt?: boolean },\n spec: string | ParsedBinding,\n): boolean {\n if (typeof spec === 'string')\n return parseBindingSpecs(spec).some(parsed => matchesBinding(event, parsed))\n const parsed = spec\n // OpenTUI's `ParsedKey` exposes `option` for Alt; some terminals\n // also report it as `alt`. Accept either.\n const altPressed = !!event.option || !!event.alt\n if (parsed.ctrl !== !!event.ctrl)\n return false\n if (parsed.shift !== !!event.shift)\n return false\n if (parsed.alt !== altPressed)\n return false\n if (parsed.meta !== !!event.meta)\n return false\n if ((event.name ?? '').toLowerCase() !== parsed.name)\n return false\n return true\n}\n\n// ---------------------------------------------------------------------------\n// Display helpers\n// ---------------------------------------------------------------------------\n\n/** Verbose key names → compact single-cell glyphs used by hint rows. */\nconst KEY_GLYPHS: Readonly<Record<string, string>> = {\n up: '↑',\n down: '↓',\n left: '←',\n right: '→',\n return: '↵',\n enter: '↵',\n delete: '⌫',\n backspace: '⌫',\n escape: 'esc',\n space: '␣',\n tab: '⇥',\n}\n\n/**\n * Render a binding spec (`\"ctrl+return\"`, `\"backspace\"`, `\"delete\"`) as a\n * compact display string the user recognizes at a glance. Substitutes\n * arrow / enter / backspace glyphs for their verbose names so the hint\n * row stays narrow; modifier names + plain keys pass through unchanged.\n *\n * Empty / missing specs return an empty string — callers decide whether\n * to render a placeholder (e.g. `'—'` for an unbound action in the\n * keybindings panel) or hide the surface entirely (e.g. hint rows that\n * fall back to a different chord when the binding is empty).\n *\n * @param spec - Binding spec, possibly listing several chords separated by `|`.\n */\nexport function formatBindingForDisplay(spec: string | null | undefined): string {\n return bindingAlternatives(spec).map(formatOneBinding).join(' / ')\n}\n\nfunction formatOneBinding(spec: string): string {\n const segments = spec.toLowerCase().split('+')\n const key = segments.pop() ?? ''\n const modifiers = segments.join('+')\n const glyph = KEY_GLYPHS[key] ?? key\n return modifiers ? `${modifiers}+${glyph}` : glyph\n}\n\n// ---------------------------------------------------------------------------\n// Merge + file IO\n// ---------------------------------------------------------------------------\n\n/**\n * Merge a partial map of user overrides into the defaults. Unknown\n * action keys are dropped (a future TUI version may have retired the\n * action); invalid spec strings (parse fails) fall back to the default\n * for that action.\n *\n * @param overrides - Parsed user overrides keyed by action name.\n */\nexport function mergeKeybindings(\n overrides: Readonly<Record<string, unknown>> | null | undefined,\n): KeyBindings {\n if (!overrides || typeof overrides !== 'object')\n return { ...DEFAULT_KEYBINDINGS }\n const merged: KeyBindings = { ...DEFAULT_KEYBINDINGS }\n for (const def of KEYBINDING_DEFS) {\n const raw = normalizeBindingValue(overrides[def.action])\n if (raw === null)\n continue // invalid spec → keep the default\n merged[def.action] = raw\n }\n return merged\n}\n\n/**\n * A `keybindings.json` value as one spec: a string, or an array of chords\n * (`[\"ctrl+w\", \"cmd+w\"]`) joined as alternatives. Chords that don't parse\n * are dropped; `null` when none is left.\n *\n * @param raw - Raw value from `keybindings.json`: a spec string or an array of them.\n */\nexport function normalizeBindingValue(raw: unknown): string | null {\n const parts = typeof raw === 'string'\n ? bindingAlternatives(raw)\n : Array.isArray(raw) ? raw.filter((r): r is string => typeof r === 'string').flatMap(bindingAlternatives) : []\n const valid = parts.filter(part => parseBindingSpec(part) !== null)\n return valid.length > 0 ? valid.join(' | ') : null\n}\n\n/**\n * Path of the user-level keybindings file.\n *\n * @param userDir - User-level config directory.\n */\nexport function keybindingsPath(userDir: string): string {\n return resolve(userDir, 'keybindings.json')\n}\n\n/**\n * One contiguous section of the catalog — every adjacent action of a single\n * `group` rendered together with the section header inserted once.\n * Non-adjacent runs of the same group are NOT merged: catalog order\n * wins so the on-screen story matches the on-disk file.\n *\n * `rows` may carry built-in `KeyBindingDef`s (the common case) or\n * extension-owned ones (when an extension contributes a keybinding).\n * Both share label / description / spec — see {@link KeyBindingRow}.\n */\nexport interface KeyBindingSection {\n /** Group name shared by every row in the section. */\n group: string\n /** Rows in the section, in catalog order. */\n rows: ReadonlyArray<KeyBindingRow>\n}\n\n/**\n * One row in the keybindings catalog. Either a built-in action (with\n * its `def`) or an extension-contributed one (with `id` instead). The\n * renderer reads `label` / `description` / `spec` uniformly and only\n * needs the `kind` discriminator when offering action-specific UI\n * (e.g. \"edit in keybindings.json\" by action name).\n */\nexport type KeyBindingRow\n = | { kind: 'builtin', def: KeyBindingDef, spec: string }\n | { kind: 'extension', id: string, label: string, description: string, spec: string }\n\n/**\n * Walk {@link KEYBINDING_DEFS} in order and bucket rows into contiguous\n * sections by `group`. Shared between the standalone `KeybindingsModal`\n * and the `Keybindings` tab inside `SettingsModal` so both surfaces\n * render the same catalog with the same ordering rules.\n *\n * Pass `extensionRows` (resolved extension keybindings paired with\n * their definitions) to append an \"Extensions\" section at the end so\n * extension-contributed shortcuts are discoverable in the same UI.\n *\n * @param bindings - Resolved built-in bindings, keyed by action.\n * @param extensionRows - Extension-contributed keybindings to list in a trailing section.\n */\nexport function groupBindings(\n bindings: KeyBindings,\n extensionRows: readonly { id: string, label: string, description: string, spec: string }[] = [],\n): readonly KeyBindingSection[] {\n const sections: Array<{ group: string, rows: KeyBindingRow[] }> = []\n for (const def of KEYBINDING_DEFS) {\n const last = sections[sections.length - 1]\n const spec = bindings[def.action] ?? ''\n const row: KeyBindingRow = { kind: 'builtin', def, spec }\n if (last && last.group === def.group) {\n last.rows.push(row)\n continue\n }\n sections.push({ group: def.group, rows: [row] })\n }\n if (extensionRows.length > 0) {\n sections.push({\n group: 'Extensions',\n rows: extensionRows.map(r => ({\n kind: 'extension',\n id: r.id,\n label: r.label,\n description: r.description,\n spec: r.spec,\n })),\n })\n }\n return sections\n}\n\n/**\n * Width (in cells) of the fixed key column used by every binding-row\n * renderer. Derived once from {@link KEYBINDING_DEFS} so a new action\n * with a wider default spec (`ctrl+shift+x`, …) automatically grows\n * the column instead of truncating the label.\n */\nexport const KEYBINDING_KEY_COL_WIDTH = (() => {\n let max = 8\n for (const def of KEYBINDING_DEFS) {\n const width = formatBindingForDisplay(def.default).length\n if (width > max)\n max = width\n }\n return max + 2 // breathing room before the label column\n})()\n\n/**\n * Load + merge the user's keybindings file (when present). Always\n * returns a fully-resolved {@link KeyBindings} — defaults fill in for\n * any missing / invalid entries so consumers can treat the result as\n * total.\n *\n * Failure modes (all tolerated, all fall back to defaults):\n * - File missing\n * - File not valid JSON / JSONC (after comment stripping)\n * - Top-level is not an object\n * - Individual entries have invalid spec strings\n *\n * @param userDir - User-level config directory that holds `keybindings.json`.\n */\nexport function readKeybindings(userDir: string): KeyBindings {\n return mergeKeybindings(readKeybindingsRaw(userDir))\n}\n\n/**\n * Create the user-level `keybindings.json` if it doesn't exist,\n * prefilled with every default. Returns the absolute file path either\n * way so the caller can open it in `$EDITOR`. Idempotent: an existing\n * user file is NEVER overwritten — the user's customizations are\n * sacred.\n *\n * @param userDir - User-level config directory that holds `keybindings.json`.\n */\nexport function ensureKeybindingsFile(userDir: string): string {\n const path = keybindingsPath(userDir)\n if (existsSync(path))\n return path\n writeFileAtomic(path, renderDefaultFile(), { ensureDir: true })\n return path\n}\n\n/**\n * Read the raw on-disk JSON object from `keybindings.json` after the\n * JSONC stripper. Used by extension-keybinding resolution so the\n * user's overrides for extension-owned ids flow through the same file\n * the built-in actions use.\n *\n * Returns an empty object on missing / malformed / non-object files\n * — same fault-tolerance contract as {@link readKeybindings}.\n *\n * @param userDir - User-level config directory that holds `keybindings.json`.\n */\nexport function readKeybindingsRaw(userDir: string): Readonly<Record<string, unknown>> {\n const path = keybindingsPath(userDir)\n if (!existsSync(path))\n return {}\n try {\n const raw = readFileSync(path, 'utf-8')\n const parsed = JSON.parse(stripJsonComments(raw)) as unknown\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))\n return {}\n return parsed as Readonly<Record<string, unknown>>\n }\n catch {\n return {}\n }\n}\n\n/**\n * Resolve the live spec string for each extension-contributed\n * keybinding. The user's `keybindings.json` is consulted for an\n * override on the binding's `id`; absent / invalid entries fall back\n * to the binding's `default`.\n *\n * A chord that is reserved or a bare printable character\n * (see {@link isReservedExtensionBinding}, {@link isBareCharExtensionBinding})\n * is refused: a user override falls back to the default, and such a default\n * resolves to unbound.\n *\n * Pass the raw object (from {@link readKeybindingsRaw}) — passing\n * `KeyBindings` here wouldn't help because the typed map only carries\n * built-in `KeyAction` entries.\n *\n * Returns one entry per input binding, in source order. Empty `spec`\n * (binding declared `default: ''` and the user didn't bind it) is a\n * legitimate \"unbound\" state — the dispatcher never matches an empty\n * spec, so the action stays accessible via re-binding through\n * `keybindings.json`.\n *\n * @param bindings - Extension keybindings with their ids and default specs.\n * @param raw - Raw object from {@link readKeybindingsRaw}.\n */\nexport function resolveExtensionKeybindings(\n bindings: readonly { id: string, default: string }[],\n raw: Readonly<Record<string, unknown>>,\n): ResolvedExtensionKeybinding[] {\n return bindings.map((binding) => {\n const candidate = raw[binding.id]\n if (\n typeof candidate === 'string'\n && parseBindingSpec(candidate)\n && !isReservedExtensionBinding(candidate)\n && !isBareCharExtensionBinding(candidate)\n ) {\n return { id: binding.id, spec: candidate }\n }\n return {\n id: binding.id,\n spec: isReservedExtensionBinding(binding.default) || isBareCharExtensionBinding(binding.default)\n ? ''\n : binding.default,\n }\n })\n}\n\n/**\n * `true` when `spec` is one of the chords the framework reserves for\n * itself — `escape` (back / exit), `ctrl+escape` (the `abortRun`\n * default — the one built-in that must never be shadowed) and `ctrl+c`\n * (quit). Extensions\n * can never claim these, neither via their declared `default` nor via a\n * user override in `keybindings.json`. Single source of truth shared by\n * `resolveExtensionKeybindings` above and the registration-time refusal\n * in `extensions/register.ts`.\n */\nexport function isReservedExtensionBinding(spec: string): boolean {\n const parsed = parseBindingSpec(spec)\n if (!parsed)\n return false\n const noExtraModifiers = !parsed.shift && !parsed.alt && !parsed.meta\n if (parsed.name === 'escape' && noExtraModifiers)\n return true\n return parsed.name === 'c' && parsed.ctrl && noExtraModifiers\n}\n\n/**\n * `true` when `spec` is a single printable character without a gating\n * modifier (ctrl / alt / meta — shift alone is just a capital letter).\n * Such a chord would fire on every matching keystroke while the user\n * types in the prompt, so extension bindings can't use one; they're\n * registered unbound instead (rebindable to a modified chord via\n * `keybindings.json`).\n */\nexport function isBareCharExtensionBinding(spec: string): boolean {\n const parsed = parseBindingSpec(spec)\n if (!parsed)\n return false\n return parsed.name.length === 1 && !parsed.ctrl && !parsed.alt && !parsed.meta\n}\n\n/**\n * Render the default `keybindings.json` body. JSONC with a header\n * explaining the format + per-action comments derived from\n * {@link KEYBINDING_DEFS}'s descriptions. The user sees the catalog +\n * defaults at a glance the moment they open the file.\n *\n * Extension-contributed bindings live alongside the built-ins in the\n * SAME file (keyed by their `id`, e.g. `\"my-ext.openPanel\"`) — they\n * don't appear in the scaffold because extensions are discovered at\n * runtime, but `resolveExtensionKeybindings` reads the same file so\n * a user-added entry overrides the extension's default. The header of\n * the scaffold tells the user how.\n */\nfunction renderDefaultFile(): string {\n const lines: string[] = []\n lines.push('// Zidane keybindings. Edit the values below to customize.')\n lines.push('//')\n lines.push('// Format:')\n lines.push('// \"<action>\": \"<modifier>+<modifier>+<key>\"')\n lines.push('//')\n lines.push('// Modifiers: ctrl, shift, alt (option), meta (cmd).')\n lines.push('// Keys: a-z, 0-9, tab, return, escape, space, delete, …')\n lines.push('//')\n lines.push('// Comments (`//` line, `/* block */`) are stripped before parsing.')\n lines.push('// Restart the TUI to apply changes.')\n lines.push('//')\n lines.push('// Extensions (.zidane/extensions/<name>/index.ts) can register')\n lines.push('// their own keybindings; rebind any of them by adding a line')\n lines.push('// using the extension binding\\'s id, e.g.')\n lines.push('// \"my-ext.openPanel\": \"ctrl+shift+j\"')\n lines.push('// The Settings → Keybindings tab lists every registered id.')\n lines.push('{')\n KEYBINDING_DEFS.forEach((def, i) => {\n const trailingComma = i < KEYBINDING_DEFS.length - 1 ? ',' : ''\n lines.push(` // ${def.description}`)\n lines.push(` ${JSON.stringify(def.action)}: ${JSON.stringify(def.default)}${trailingComma}`)\n })\n lines.push('}')\n lines.push('')\n return lines.join('\\n')\n}\n\n// ---------------------------------------------------------------------------\n// JSONC parsing — `//` line + `/* block */` comments, single pass\n// ---------------------------------------------------------------------------\n\n/**\n * Strip `//` line comments and `/* … *\\/` block comments from a JSONC\n * source string. Stays out of string literals so a `\"foo // bar\"` value\n * keeps its slashes. Exported for unit-tests; the only runtime caller\n * is {@link readKeybindingsRaw}.\n *\n * Trade-off: this is a tiny state-machine, not a full JSONC parser. It\n * doesn't understand `\\\\` outside strings (irrelevant for JSON) and\n * doesn't track line numbers in error messages. Good enough for a\n * config file — corruption in production gracefully falls back to the\n * defaults via the try/catch in `readKeybindingsRaw`.\n *\n * @param input - JSONC source text.\n */\nexport function stripJsonComments(input: string): string {\n let out = ''\n let i = 0\n let inString = false\n let escape = false\n while (i < input.length) {\n const c = input[i]\n if (inString) {\n out += c\n if (escape)\n escape = false\n else if (c === '\\\\')\n escape = true\n else if (c === '\"')\n inString = false\n i++\n continue\n }\n if (c === '\"') {\n inString = true\n out += c\n i++\n continue\n }\n if (c === '/' && input[i + 1] === '/') {\n while (i < input.length && input[i] !== '\\n')\n i++\n continue\n }\n if (c === '/' && input[i + 1] === '*') {\n i += 2\n while (i < input.length && !(input[i] === '*' && input[i + 1] === '/'))\n i++\n i += 2\n continue\n }\n out += c\n i++\n }\n return out\n}\n","/**\n * The extension keymap: extension command bindings with focus scopes, an\n * `editable` flag, a mode stack and fall-through dispatch.\n *\n * Host-agnostic: a host turns its key event into a chord (a spec string or a\n * {@link ParsedBinding}) and a {@link KeyFocus}, then calls\n * {@link Keymap.dispatch}. Built-in host keys stay with the host; it calls\n * `dispatch` for the keys it did not handle (the TUI already runs extension\n * bindings after its built-ins, `src/tui/shell/app-keyboard.tsx`).\n *\n * The chord grammar is `keybindings.json`'s (`src/chat/keybinding-spec.ts`),\n * plus `mod`: `meta` on macOS, `ctrl` elsewhere. The reserved chords are the\n * ones `isReservedExtensionBinding` refuses (`src/chat/keybindings.ts`).\n */\n\nimport type { KeyBindingGroup, ParsedBinding } from '../../chat/keybindings'\nimport type { Logger } from '../../logger'\nimport type { KeymapEntry, KeyScope } from '../api/commands'\nimport type { Disposable } from '../api/core'\nimport { bindingAlternatives, isBareCharExtensionBinding, isReservedExtensionBinding, KEYBINDING_DEFS, mergeKeybindings, parseBindingSpec } from '../../chat/keybindings'\n\n/** Where focus is when a key arrives, as the host reports it. */\nexport interface KeyFocus {\n /** The focused area. `'global'` when nothing in particular holds focus. */\n scope: KeyScope\n /** A text field has focus: only bindings marked `editable` fire. */\n editable?: boolean\n /** The session the focused window shows. Selects per-session modes. */\n sessionId?: string\n /** A run is in flight on that session (for `when: 'idle'`). */\n busy?: boolean\n}\n\n/** What a binding's trigger receives. */\nexport interface KeyTriggerContext {\n /** The canonical chord that matched (`ctrl+shift+t`). */\n chord: string\n /** The focus the host reported. */\n focus: KeyFocus\n}\n\n/** One command's binding, as the command registry adds it. */\nexport interface KeymapBinding {\n /** Published command id (`<extension>.<id>`); user overrides are keyed by it. */\n commandId: string\n /** Default chords, already canonical (see {@link normalizeChords}). May be empty: unbound until the user binds it. */\n defaults: readonly string[]\n /** Where focus must be. Default `'global'`. */\n scope?: KeyScope\n /** Fires while a text field has focus. */\n editable?: boolean\n /** Fires only while this mode is the current one. */\n mode?: string\n /** Availability: `session` needs a session, `idle` also needs no run in flight. */\n when?: 'always' | 'session' | 'idle'\n /** `false` turns the binding off. Read on every dispatch. */\n enabled?: () => boolean\n /** Runs the command. Returning `false` passes the key on to the next match. */\n trigger: (ctx: KeyTriggerContext) => boolean\n}\n\n/** A binding with its effective chords, as {@link Keymap.list} reports it. */\nexport interface ResolvedKeymapBinding {\n /** Published command id. */\n commandId: string\n /** Chords after user overrides. Empty when unbound. */\n chords: readonly string[]\n /** `true` when a user override replaced the defaults. */\n overridden: boolean\n /** The binding's scope. */\n scope: KeyScope\n /** The binding's `editable` flag. */\n editable: boolean\n /** The binding's mode, when it has one. */\n mode?: string\n}\n\n/** Host side of the keymap: where user overrides come from. */\nexport interface KeymapPort {\n /**\n * The user's chords for a command (`keybindings.json` keyed by command id).\n * `undefined` keeps the defaults; `''` or `[]` unbinds.\n */\n overrides?: (commandId: string) => string | readonly string[] | undefined\n /** Calls `listener` when the overrides change. Returns the unsubscribe. */\n subscribe?: (listener: () => void) => () => void\n}\n\n/** Options for {@link createKeymap}. */\nexport interface KeymapOptions {\n /** User overrides. */\n port?: KeymapPort\n /** `process.platform` of the host; decides what `mod` means. Default `process.platform`. */\n platform?: string\n /** Receives warnings about refused overrides. */\n logger?: Logger\n}\n\n/** Options for {@link Keymap.pushMode}. */\nexport interface ModeOptions {\n /** Higher wins over modes pushed later with a lower priority. Default `0`. */\n priority?: number\n /** Limits the mode to the windows showing this session. */\n sessionId?: string\n}\n\n/** The host-wide keymap. */\nexport interface Keymap {\n /** Adds a binding. Dispose to remove it. */\n add: (binding: KeymapBinding) => Disposable\n /** Activates a mode. Dispose to pop it, wherever it sits in the stack. */\n pushMode: (name: string, opts?: ModeOptions) => Disposable\n /** The current mode for `sessionId` (global modes included), or for global modes only. */\n currentMode: (sessionId?: string) => string | undefined\n /** The active modes for `sessionId` (global modes included), or the global ones only, in precedence order: the current mode last. */\n activeModes: (sessionId?: string) => readonly string[]\n /** Effective chords of a command after user overrides. Empty when unknown or unbound. */\n bindings: (commandId: string) => readonly string[]\n /**\n * Runs the bindings that match `chord` under `focus`, highest precedence\n * first, and stops at the first that does not return `false`. Returns\n * `true` when one claimed the key, `false` when the host should handle it.\n *\n * Precedence: bindings of the current mode, then a binding scoped to the\n * focused area over a `global` one, then registration order.\n */\n dispatch: (chord: string | ParsedBinding, focus: KeyFocus) => boolean\n /** Every binding with its effective chords, in registration order. */\n list: () => readonly ResolvedKeymapBinding[]\n /** Calls `listener` after bindings, modes or overrides change. Returns the unsubscribe. */\n subscribe: (listener: () => void) => () => void\n /** Re-reads every override. Called on its own when the port's `subscribe` fires. */\n refresh: () => void\n /** Stops listening to the port. */\n dispose: () => void\n}\n\n/** Why a chord was refused. */\nexport type ChordRefusal = 'reserved' | 'unparsable' | 'bare'\n\n/** The outcome of {@link normalizeChords}. */\nexport interface NormalizedChords {\n /** Canonical chords that passed. */\n chords: string[]\n /** Chords that were refused, with the reason. */\n refused: { chord: string, reason: ChordRefusal }[]\n}\n\n/**\n * Replaces the `mod` modifier with `meta` (macOS) or `ctrl`.\n *\n * @param spec - One chord, for example `mod+shift+t`.\n * @param platform - `process.platform` of the host.\n */\nexport function resolveMod(spec: string, platform: string): string {\n const mod = platform === 'darwin' ? 'meta' : 'ctrl'\n return spec.replace(/(^|[+\\-\\s])mod(?=\\s*[+\\-])/gi, `$1${mod}`)\n}\n\n/**\n * The canonical text of a parsed chord: modifiers in a fixed order, then the\n * key. Two specs for the same keys give the same text.\n *\n * @param parsed - A parsed chord.\n */\nexport function chordKey(parsed: ParsedBinding): string {\n const name = parsed.name === '-' ? 'minus' : parsed.name\n return `${parsed.ctrl ? 'ctrl+' : ''}${parsed.alt ? 'alt+' : ''}${parsed.shift ? 'shift+' : ''}${parsed.meta ? 'meta+' : ''}${name}`\n}\n\n/**\n * Validates and canonicalizes chords. A spec may list alternatives\n * (`ctrl+w | cmd+w`). Esc and ctrl+c are refused; so is a bare printable\n * key on an `editable` binding, which would fire on every keystroke.\n *\n * @param specs - One spec or several.\n * @param opts - The host platform (for `mod`) and the binding's `editable` flag.\n * @param opts.platform - `process.platform` of the host.\n * @param opts.editable - The binding fires while a text field has focus.\n */\nexport function normalizeChords(\n specs: string | readonly string[] | undefined,\n opts: { platform: string, editable?: boolean },\n): NormalizedChords {\n const out: NormalizedChords = { chords: [], refused: [] }\n const list = specs === undefined ? [] : typeof specs === 'string' ? [specs] : specs\n for (const spec of list) {\n if (typeof spec !== 'string') {\n out.refused.push({ chord: String(spec), reason: 'unparsable' })\n continue\n }\n for (const alternative of bindingAlternatives(spec)) {\n const resolved = resolveMod(alternative, opts.platform)\n const parsed = parseBindingSpec(resolved)\n if (!parsed) {\n out.refused.push({ chord: alternative, reason: 'unparsable' })\n continue\n }\n const key = chordKey(parsed)\n if (isReservedExtensionBinding(key)) {\n out.refused.push({ chord: alternative, reason: 'reserved' })\n continue\n }\n if (opts.editable && isBareCharExtensionBinding(key)) {\n out.refused.push({ chord: alternative, reason: 'bare' })\n continue\n }\n if (!out.chords.includes(key))\n out.chords.push(key)\n }\n }\n return out\n}\n\ninterface BindingSlot {\n binding: KeymapBinding\n chords: readonly string[]\n overridden: boolean\n}\n\ninterface ModeSlot {\n name: string\n priority: number\n sessionId?: string\n seq: number\n}\n\n/**\n * Makes a keymap. One per host process; every extension's commands bind\n * into it.\n *\n * @param opts - User overrides, platform and logger.\n */\nexport function createKeymap(opts: KeymapOptions = {}): Keymap {\n const platform = opts.platform ?? process.platform\n const port = opts.port\n const slots: BindingSlot[] = []\n const modes: ModeSlot[] = []\n const listeners = new Set<() => void>()\n let seq = 0\n\n const notify = () => {\n for (const listener of [...listeners]) {\n try {\n listener()\n }\n catch (error) {\n opts.logger?.warn('keymap: listener threw', { error: String(error) })\n }\n }\n }\n\n const resolve = (binding: KeymapBinding): { chords: readonly string[], overridden: boolean } => {\n let override: string | readonly string[] | undefined\n try {\n override = port?.overrides?.(binding.commandId)\n }\n catch (error) {\n opts.logger?.warn('keymap: overrides lookup threw', { command: binding.commandId, error: String(error) })\n }\n if (override === undefined)\n return { chords: binding.defaults, overridden: false }\n const list = typeof override === 'string' ? [override] : override\n if (list.length === 0 || list.every(s => typeof s === 'string' && s.trim() === ''))\n return { chords: [], overridden: true }\n const normalized = normalizeChords(list, { platform, editable: binding.editable })\n for (const { chord, reason } of normalized.refused)\n opts.logger?.warn('keymap: user binding refused', { command: binding.commandId, chord, reason })\n // Like `resolveExtensionKeybindings`: an override with nothing usable keeps the defaults.\n if (normalized.chords.length === 0)\n return { chords: binding.defaults, overridden: false }\n return { chords: normalized.chords, overridden: true }\n }\n\n // Lowest precedence first: priority, then the later push wins among equals.\n const activeModes = (sessionId?: string): string[] => modes\n .filter(mode => mode.sessionId === undefined || mode.sessionId === sessionId)\n .sort((a, b) => a.priority - b.priority || a.seq - b.seq)\n .map(mode => mode.name)\n const currentMode = (sessionId?: string): string | undefined => activeModes(sessionId).at(-1)\n\n const available = (binding: KeymapBinding, focus: KeyFocus, mode: string | undefined): boolean => {\n if (focus.editable && !binding.editable)\n return false\n const scope = binding.scope ?? 'global'\n if (scope === 'global' ? focus.scope === 'modal' : scope !== focus.scope)\n return false\n if (binding.mode !== undefined && binding.mode !== mode)\n return false\n if (binding.when === 'session' && !focus.sessionId)\n return false\n if (binding.when === 'idle' && (!focus.sessionId || focus.busy))\n return false\n try {\n return binding.enabled?.() !== false\n }\n catch {\n return false\n }\n }\n\n const keymap: Keymap = {\n add(binding) {\n const slot: BindingSlot = { binding, ...resolve(binding) }\n slots.push(slot)\n notify()\n let done = false\n return {\n dispose() {\n if (done)\n return\n done = true\n const at = slots.indexOf(slot)\n if (at >= 0)\n slots.splice(at, 1)\n notify()\n },\n }\n },\n pushMode(name, modeOpts = {}) {\n const slot: ModeSlot = { name, priority: modeOpts.priority ?? 0, seq: ++seq, ...(modeOpts.sessionId !== undefined ? { sessionId: modeOpts.sessionId } : {}) }\n modes.push(slot)\n notify()\n let done = false\n return {\n dispose() {\n if (done)\n return\n done = true\n const at = modes.indexOf(slot)\n if (at >= 0)\n modes.splice(at, 1)\n notify()\n },\n }\n },\n currentMode,\n activeModes,\n bindings(commandId) {\n return slots.find(s => s.binding.commandId === commandId)?.chords ?? []\n },\n dispatch(chord, focus) {\n const parsed = typeof chord === 'string' ? parseBindingSpec(resolveMod(chord, platform)) : chord\n if (!parsed)\n return false\n const key = chordKey(parsed)\n const mode = currentMode(focus.sessionId)\n const rank = (b: KeymapBinding) => (b.mode !== undefined ? 0 : 2) + ((b.scope ?? 'global') === 'global' ? 1 : 0)\n const candidates = slots\n .filter(s => s.chords.includes(key) && available(s.binding, focus, mode))\n .map((s, order) => ({ binding: s.binding, order }))\n .sort((a, b) => rank(a.binding) - rank(b.binding) || a.order - b.order)\n for (const { binding } of candidates) {\n let claimed = true\n try {\n claimed = binding.trigger({ chord: key, focus }) !== false\n }\n catch (error) {\n opts.logger?.warn('keymap: trigger threw', { command: binding.commandId, error: String(error) })\n }\n if (claimed)\n return true\n }\n return false\n },\n list() {\n return slots.map(s => ({\n commandId: s.binding.commandId,\n chords: s.chords,\n overridden: s.overridden,\n scope: s.binding.scope ?? 'global',\n editable: s.binding.editable === true,\n ...(s.binding.mode !== undefined ? { mode: s.binding.mode } : {}),\n }))\n },\n subscribe(listener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n refresh() {\n for (const slot of slots)\n Object.assign(slot, resolve(slot.binding))\n notify()\n },\n dispose() {\n // eslint-disable-next-line ts/no-use-before-define -- assigned right after the object\n unsubscribePort?.()\n },\n }\n const unsubscribePort = port?.subscribe?.(() => keymap.refresh())\n return keymap\n}\n\n/** Where a built-in key's group fires: the sessions screen is the sidebar, the details groups are modals. */\nconst BUILTIN_KEY_SCOPES: Readonly<Record<KeyBindingGroup, KeyScope>> = {\n 'Global': 'global',\n 'Sessions': 'sidebar',\n 'Message queue': 'modal',\n 'Turn details': 'modal',\n 'Session details': 'modal',\n}\n\n/**\n * The built-in key bindings (`KEYBINDING_DEFS`) as `ctx.keymap.list` reports\n * them, with the user's `keybindings.json` applied. What a host passes as\n * `CommandHostPort.keybindings`.\n *\n * @param overrides - The raw `keybindings.json` object (`readKeybindingsRaw`).\n * @returns One entry per built-in action, in catalog order; an unbound action has no bindings.\n */\nexport function builtinKeymapEntries(overrides: Readonly<Record<string, unknown>> | null | undefined): KeymapEntry[] {\n const effective = mergeKeybindings(overrides)\n return KEYBINDING_DEFS.map(def => ({\n id: def.action,\n title: def.description,\n bindings: bindingAlternatives(effective[def.action] ?? '').map(chord => chord.trim()).filter(Boolean),\n scope: BUILTIN_KEY_SCOPES[def.group] ?? 'global',\n editable: false,\n }))\n}\n","/**\n * Converts an extension settings schema to the wire format the Settings UIs render\n * today: `WireExtensionConfigSchema` (`src/extensions/config.ts`), the\n * action rows of `src/extensions/config-actions.ts`, and values shaped like\n * `Settings.extensionConfig`. zidane-ui's `ExtensionOptionsSection` keeps\n * working unchanged.\n */\n\nimport type { AccessScope } from '../api/core'\nimport type { ActionSettingStatus, Setting, SettingsCategory, SettingsSchema } from '../api/settings'\nimport type {\n ExtensionConfigActionStatus,\n ExtensionConfigCategory,\n ExtensionConfigValue,\n StoredExtensionConfigItem,\n WireExtensionConfigItem,\n WireExtensionConfigSchema,\n} from '../config'\nimport type { ExtensionActionSummary } from '../config-actions'\nimport type { ComponentWire } from '../ui/wire'\nimport type { StoredSettingValue, ValueSetting } from './validate'\nimport { actionScope, DEFAULT_SETTINGS_PAGE_ID, isValueSetting, settingDefault } from './validate'\n\n/** An action row: what `listActionSummaries` produces, plus the token scope a remote client needs to run it. */\nexport interface WireSettingsAction extends ExtensionActionSummary {\n /** The least token scope a remote client needs. Apps disable the button below it. */\n scope: AccessScope\n}\n\n/** A group of rows on a settings page, in the order to draw them. */\nexport interface WireSettingsPageSection {\n /** The section id, or `undefined` for the page's ungrouped rows (drawn first, without a sub-header). */\n id?: string\n /** Sub-header. Absent for ungrouped rows. */\n label?: string\n /** Line under the sub-header. */\n description?: string\n /** The wire category id of the rows (`wireCategoryId`). */\n category: string\n /** Keys of the rows, in order: value rows of `schema.items` and action rows of `actions`. */\n keys: string[]\n}\n\n/**\n * One page of an extension's settings in the sidebar. `kind: 'schema'`\n * pages come from the definition's schema and list keys of the wire's own\n * rows; `kind: 'ui'` pages are `SettingsPage` items, drawn from their own\n * `schema` wire or `component`.\n */\nexport interface WireSettingsPage {\n /** The extension the page belongs to. */\n extension: string\n /** Where the page comes from. */\n kind: 'schema' | 'ui'\n /** Unique among the extension's pages: the schema page id, or the item's `<extension>/<id>` for a `ui` page. */\n id: string\n /** Sidebar label (the page title for `ui` pages). */\n label: string\n /** Line under the page title. */\n description?: string\n /** Icon in each app's vocabulary. */\n icon?: { gui?: string, tui?: string }\n /**\n * The page the extension gets when its schema declares none: id `main`,\n * labelled with the extension's name. `settingsSidebar` relabels it with\n * the display name it is given.\n */\n implicit?: true\n /** `kind: 'ui'`: its place among the extension's `ui` pages (lower first, default 100). */\n order?: number\n /** `kind: 'schema'`: the rows of the page, by section. Ungrouped rows first, then sections as declared. */\n sections: WireSettingsPageSection[]\n /** `kind: 'ui'`: the page's settings in this same wire format. */\n schema?: WireSettings\n /** `kind: 'ui'`: drawn instead of the data where the host has it. */\n component?: ComponentWire\n}\n\n/** Everything a Settings UI needs to draw an extension's settings. */\nexport interface WireSettings {\n /** The value rows, as `toWireConfigSchema` produces them. */\n schema: WireExtensionConfigSchema\n /** The action rows, as `listActionSummaries` produces them, with their scope. */\n actions: WireSettingsAction[]\n /** Values by extension then key, the shape of `Settings.extensionConfig`. Secrets are left out. */\n values: Record<string, Record<string, ExtensionConfigValue>>\n /** Locked settings (set by a declarative config entry), as `extension:key`. */\n locked: string[]\n /** One extension's wire: its own sidebar group (`SettingsSchema.category`). Absent on a merged wire (see `extensionCategories`). */\n category?: SettingsCategory\n /** A merged wire: each extension's category, by extension id. */\n extensionCategories?: Record<string, SettingsCategory>\n /**\n * Each extension's display name and icon, by extension id: the settings\n * sidebar's labels and glyphs. Set by `toWireSettings` (its extension),\n * `mergeWireSettings` (every part's) and `runtimeSettingsWire` (the\n * definition's `displayName` and `icon`). Absent on older wires: apps\n * fall back to the implicit page's label, else the id.\n */\n extensions?: Record<string, WireSettingsExtension>\n /**\n * The settings pages in sidebar order: per extension, the schema's pages,\n * then its `ui` pages by `order`. Always set by `toWireSettings` and\n * `mergeWireSettings`; optional so older wires (and hand-built empty ones) still type.\n */\n pages?: WireSettingsPage[]\n}\n\n/** An extension as the settings wire names it (`WireSettings.extensions`). */\nexport interface WireSettingsExtension {\n /** Its display name, else its id. */\n name: string\n /** Its icon in each app's vocabulary (`ExtensionDefinition.icon`). */\n icon?: { gui?: string, tui?: string }\n /** What it does (`ExtensionDefinition.description`): the line under its name atop its settings. */\n description?: string\n}\n\n/** A `SettingsPage` item as {@link withSettingsPages} takes it: the fields of its wire (`SettingsPageWire`). */\nexport interface SettingsPageInput {\n /** `<extension>/<id>`. */\n id: string\n /** Page title. */\n title: string\n /** Icon in the settings sidebar. */\n icon?: { gui?: string, tui?: string }\n /** Place among the extension's `ui` pages, lower first. Default 100. */\n order?: number\n /** The page's settings in the wire format. */\n schema?: WireSettings\n /** Drawn instead of the data where the host has it. */\n component?: ComponentWire\n}\n\n/**\n * The wire category id of a section. Sections belong to one extension, the\n * wire has one flat category list, so the id is namespaced. An ungrouped\n * setting sits in the implicit category whose id is the extension id (the\n * UI draws no sub-header for it).\n *\n * @param extensionId - The extension.\n * @param sectionId - The section, or `undefined` for ungrouped.\n * @returns The category id.\n */\nexport function wireCategoryId(extensionId: string, sectionId: string | undefined): string {\n return sectionId === undefined ? extensionId : `${extensionId}:${sectionId}`\n}\n\n/**\n * A value in its wire shape: a model list joins as `'a, b'`, the shape the\n * UIs write back.\n *\n * @param value - A resolved value.\n * @returns The wire value.\n */\nexport function toWireValue(value: StoredSettingValue): ExtensionConfigValue {\n return Array.isArray(value) ? value.join(', ') : value as ExtensionConfigValue\n}\n\n/**\n * The wire default. Legacy config items always carry one; a setting without a\n * default gets the empty value of its type (false, the number nearest 0 in\n * range, `''`, the first enum option).\n */\nfunction wireDefault(setting: ValueSetting): ExtensionConfigValue {\n const declared = settingDefault(setting)\n if (declared !== undefined)\n return toWireValue(declared)\n switch (setting.type) {\n case 'boolean':\n return false\n case 'number':\n return Math.min(setting.max ?? Infinity, Math.max(setting.min ?? -Infinity, 0))\n case 'enum':\n return setting.options[0]?.value ?? ''\n default:\n return ''\n }\n}\n\nfunction wireItem(extensionId: string, key: string, setting: ValueSetting): WireExtensionConfigItem {\n const base = {\n key,\n label: setting.label,\n ...(setting.description !== undefined ? { description: setting.description } : {}),\n ...(setting.scopes?.[0] !== undefined ? { scope: setting.scopes[0] } : {}),\n ...(setting.apply !== undefined ? { onChange: setting.apply } : {}),\n ...(setting.apply === 'restart' ? { requiresRestart: true } : {}),\n category: wireCategoryId(extensionId, setting.section),\n extension: extensionId,\n }\n switch (setting.type) {\n case 'boolean':\n return { ...base, type: 'boolean', default: wireDefault(setting) as boolean }\n case 'number':\n return {\n ...base,\n type: 'number',\n default: wireDefault(setting) as number,\n ...(setting.min !== undefined ? { min: setting.min } : {}),\n ...(setting.max !== undefined ? { max: setting.max } : {}),\n ...(setting.step !== undefined ? { step: setting.step } : {}),\n }\n case 'string':\n return {\n ...base,\n type: 'string',\n default: wireDefault(setting) as string,\n ...(setting.pattern !== undefined ? { pattern: setting.pattern } : {}),\n ...(setting.multiline !== undefined ? { multiline: setting.multiline } : {}),\n ...(setting.secret !== undefined ? { secret: setting.secret } : {}),\n }\n case 'enum':\n return {\n ...base,\n type: 'enum',\n default: wireDefault(setting) as string,\n options: setting.options.map(o => ({ value: o.value, label: o.label })),\n }\n case 'model':\n return { ...base, type: 'model', default: wireDefault(setting) as string, ...(setting.multi !== undefined ? { multi: setting.multi } : {}) }\n }\n}\n\nfunction sectionRank(schema: SettingsSchema, sectionId: string | undefined): number {\n if (sectionId === undefined)\n return -1\n return (schema.sections ?? []).findIndex(s => s.id === sectionId)\n}\n\n/**\n * The page a setting sits on: its `page`, else its section's page, else\n * the first page. Clean the schema first (`settingsForDefinition`).\n *\n * @param schema - The cleaned schema.\n * @param setting - One of its settings.\n * @returns The page id.\n */\nexport function settingPageId(schema: SettingsSchema, setting: Pick<Setting, 'page' | 'section'>): string {\n const first = schema.pages?.[0]?.id ?? DEFAULT_SETTINGS_PAGE_ID\n if (setting.page !== undefined)\n return setting.page\n const section = setting.section === undefined ? undefined : schema.sections?.find(s => s.id === setting.section)\n return section?.page ?? first\n}\n\n/** The schema's pages with their rows. No pages and no rows: none. */\nfunction wirePages(extensionId: string, schema: SettingsSchema, displayName: string | undefined): WireSettingsPage[] {\n const entries = Object.entries(schema.items)\n const declared = schema.pages ?? []\n if (declared.length === 0 && entries.length === 0)\n return []\n const pages: WireSettingsPage[] = declared.length > 0\n ? declared.map(p => ({\n extension: extensionId,\n kind: 'schema' as const,\n id: p.id,\n label: p.label,\n ...(p.description !== undefined ? { description: p.description } : {}),\n ...(p.icon !== undefined ? { icon: { ...p.icon } } : {}),\n sections: [],\n }))\n : [{ extension: extensionId, kind: 'schema', id: DEFAULT_SETTINGS_PAGE_ID, label: displayName ?? extensionId, implicit: true, sections: [] }]\n const byPage = new Map(pages.map(p => [p.id, p]))\n const sectionOrder = [undefined, ...(schema.sections ?? []).map(s => s.id)]\n for (const sectionId of sectionOrder) {\n const meta = sectionId === undefined ? undefined : schema.sections?.find(s => s.id === sectionId)\n for (const [key, setting] of entries) {\n if (setting.section !== sectionId)\n continue\n const page = byPage.get(settingPageId(schema, setting)) ?? pages[0]!\n let section = page.sections.find(s => s.id === sectionId)\n if (!section) {\n section = {\n ...(sectionId !== undefined ? { id: sectionId } : {}),\n ...(meta ? { label: meta.label } : {}),\n ...(meta?.description !== undefined ? { description: meta.description } : {}),\n category: wireCategoryId(extensionId, sectionId),\n keys: [],\n }\n page.sections.push(section)\n }\n section.keys.push(key)\n }\n }\n return pages\n}\n\n/**\n * Converts one extension's schema and values to the wire format. Rows come\n * ungrouped first, then by section in declared order. Pure: never calls\n * author code.\n *\n * @param extensionId - The extension.\n * @param schema - Its settings (clean it with `settingsForDefinition` first).\n * @param values - Effective values by key; missing keys are left out (the UI shows the default).\n * @param opts - `locked`, `displayName` and `icon`.\n * @param opts.locked - Keys a declarative config entry sets.\n * @param opts.displayName - The extension's name: the label of its implicit page and its `extensions` entry (default: the id).\n * @param opts.icon - The extension's icon, for its `extensions` entry.\n * @returns The wire settings.\n */\nexport function toWireSettings(\n extensionId: string,\n schema: SettingsSchema,\n values: Readonly<Record<string, StoredSettingValue | undefined>> = {},\n opts: { locked?: readonly string[], displayName?: string, icon?: { gui?: string, tui?: string } } = {},\n): WireSettings {\n const entries = Object.entries(schema.items)\n .map((entry, index) => ({ entry, index, rank: sectionRank(schema, entry[1].section) }))\n .sort((a, b) => a.rank - b.rank || a.index - b.index)\n .map(x => x.entry)\n const items: WireExtensionConfigItem[] = []\n const actions: WireSettingsAction[] = []\n const wireValues: Record<string, ExtensionConfigValue> = {}\n const used = new Set<string>()\n for (const [key, setting] of entries) {\n if (setting.section !== undefined)\n used.add(setting.section)\n if (isValueSetting(setting)) {\n items.push(wireItem(extensionId, key, setting))\n const value = values[key]\n if (value !== undefined && !(setting.type === 'string' && setting.secret === true))\n wireValues[key] = toWireValue(value)\n continue\n }\n const section = schema.sections?.find(s => s.id === setting.section)\n actions.push({\n extension: extensionId,\n key,\n label: setting.label,\n ...(setting.description !== undefined ? { description: setting.description } : {}),\n category: wireCategoryId(extensionId, setting.section),\n categoryLabel: section?.label ?? extensionId,\n hasStatus: typeof setting.status === 'function',\n scope: actionScope(setting),\n })\n }\n const categories: ExtensionConfigCategory[] = (schema.sections ?? [])\n .filter(s => used.has(s.id))\n .map(s => ({ id: wireCategoryId(extensionId, s.id), label: s.label, ...(s.description !== undefined ? { description: s.description } : {}) }))\n return {\n schema: { categories, items },\n actions: sortActions(actions),\n values: Object.keys(wireValues).length > 0 ? { [extensionId]: wireValues } : {},\n locked: (opts.locked ?? []).map(key => `${extensionId}:${key}`),\n ...(schema.category ? { category: { ...schema.category } } : {}),\n pages: wirePages(extensionId, schema, opts.displayName),\n extensions: { [extensionId]: wireExtension(extensionId, opts.displayName, opts.icon) },\n }\n}\n\n/**\n * An extension's `WireSettings.extensions` entry.\n *\n * @param extensionId - The extension.\n * @param displayName - Its display name; blank or absent: the id.\n * @param icon - Its icon.\n * @param description - What it does; blank or absent: none.\n * @returns The entry.\n */\nexport function wireExtension(extensionId: string, displayName?: string, icon?: { gui?: string, tui?: string }, description?: string): WireSettingsExtension {\n const gui = icon?.gui?.trim() ? icon.gui : undefined\n const tui = icon?.tui?.trim() ? icon.tui : undefined\n return {\n name: displayName?.trim() ? displayName : extensionId,\n ...(gui !== undefined || tui !== undefined ? { icon: { ...(gui !== undefined ? { gui } : {}), ...(tui !== undefined ? { tui } : {}) } } : {}),\n ...(description?.trim() ? { description: description.trim() } : {}),\n }\n}\n\n/**\n * Adds an extension's `SettingsPage` items to its wire, after the schema's\n * pages, by `order` (default 100; ties keep the given order). Items of\n * other extensions (their id does not start with `<extensionId>/`) are\n * ignored. Pure.\n *\n * @param wire - One extension's wire (`toWireSettings` or the domain's `wire()`).\n * @param extensionId - The extension.\n * @param pages - Its settings-page items, as the UI registry serializes them.\n * @returns A new wire with the pages appended.\n */\nexport function withSettingsPages(wire: WireSettings, extensionId: string, pages: readonly SettingsPageInput[]): WireSettings {\n const own = pages\n .filter(p => p.id.startsWith(`${extensionId}/`))\n .map((p, index) => ({ p, index, order: p.order ?? 100 }))\n .sort((a, b) => a.order - b.order || a.index - b.index)\n .map(({ p }): WireSettingsPage => ({\n extension: extensionId,\n kind: 'ui',\n id: p.id,\n label: p.title,\n ...(p.icon !== undefined ? { icon: { ...p.icon } } : {}),\n ...(p.order !== undefined ? { order: p.order } : {}),\n sections: [],\n ...(p.schema ? { schema: p.schema } : {}),\n ...(p.component ? { component: p.component } : {}),\n }))\n return own.length === 0 ? wire : { ...wire, pages: [...(wire.pages ?? []), ...own] }\n}\n\nfunction sortActions<A extends ExtensionActionSummary>(actions: A[]): A[] {\n return actions.sort((a, b) => a.extension.localeCompare(b.extension) || a.label.localeCompare(b.label))\n}\n\n/**\n * Joins the wire settings of several extensions into the one list the\n * Settings UI reads.\n *\n * @param parts - One {@link WireSettings} per extension.\n * @returns The merged wire settings.\n */\nexport function mergeWireSettings(parts: readonly WireSettings[]): WireSettings {\n const extensionCategories: Record<string, SettingsCategory> = {}\n const extensions: Record<string, WireSettingsExtension> = {}\n for (const part of parts) {\n Object.assign(extensions, part.extensions)\n for (const [id, category] of Object.entries(part.extensionCategories ?? {}))\n extensionCategories[id] = category\n const owner = part.pages?.[0]?.extension\n if (part.category && owner !== undefined)\n extensionCategories[owner] = part.category\n }\n return {\n schema: {\n categories: parts.flatMap(p => p.schema.categories),\n items: parts.flatMap(p => p.schema.items),\n },\n actions: sortActions(parts.flatMap(p => p.actions)),\n values: Object.assign({}, ...parts.map(p => p.values)) as WireSettings['values'],\n locked: parts.flatMap(p => p.locked),\n ...(Object.keys(extensionCategories).length > 0 ? { extensionCategories } : {}),\n pages: parts.flatMap(p => p.pages ?? []),\n ...(Object.keys(extensions).length > 0 ? { extensions } : {}),\n }\n}\n\n/**\n * An action status in the wire shape: `success` is `ok`, `warn` and\n * `error` are `error`, `muted` or no tone is `off`.\n *\n * @param status - The status an action's `status()` returned.\n * @returns The wire status.\n */\nexport function toWireActionStatus(status: ActionSettingStatus): ExtensionConfigActionStatus {\n const state = status.tone === 'success' ? 'ok' : status.tone === 'error' || status.tone === 'warn' ? 'error' : 'off'\n return { state, message: status.text }\n}\n\n/**\n * Builds a settings schema from stored config items (`StoredExtensionConfigItem`).\n * For tests. A `validate` carries over on string items only (the schema has\n * it on strings only); `config` patches become `patch`.\n *\n * @param extensionId - The declaring extension; its implicit category becomes \"ungrouped\".\n * @param categories - The categories by id.\n * @param items - The extension's items by key.\n * @returns The settings schema.\n */\nexport function fromConfigItems(\n extensionId: string,\n categories: Readonly<Record<string, ExtensionConfigCategory>>,\n items: Readonly<Record<string, StoredExtensionConfigItem>>,\n): SettingsSchema {\n const sections: { id: string, label: string, description?: string }[] = []\n const out: Record<string, Setting> = {}\n for (const item of Object.values(items)) {\n const section = item.category === extensionId ? undefined : item.category\n if (section !== undefined && !sections.some(s => s.id === section)) {\n const cat = categories[section]\n sections.push({ id: section, label: cat?.label ?? section, ...(cat?.description !== undefined ? { description: cat.description } : {}) })\n }\n const common = {\n label: item.label,\n ...(item.description !== undefined ? { description: item.description } : {}),\n ...(section !== undefined ? { section } : {}),\n }\n if (item.type === 'action') {\n const { run, status } = item\n out[item.key] = {\n ...common,\n type: 'action',\n button: item.label,\n run: async () => {\n const result = await run()\n if (!result)\n return undefined\n return { ...(result.message !== undefined ? { message: result.message } : {}), ...(result.config ? { patch: result.config } : {}) }\n },\n ...(status\n ? {\n status: async () => {\n const s = await status()\n return s ? { text: s.message, tone: s.state === 'ok' ? 'success' as const : s.state === 'error' ? 'error' as const : 'muted' as const } : { text: '' }\n },\n }\n : {}),\n }\n continue\n }\n const meta = {\n ...common,\n ...(item.scope !== undefined ? { scopes: [item.scope] } : {}),\n ...(item.onChange !== undefined ? { apply: item.onChange } : item.requiresRestart ? { apply: 'restart' as const } : {}),\n }\n switch (item.type) {\n case 'boolean':\n out[item.key] = { ...meta, type: 'boolean', default: item.default }\n break\n case 'number':\n out[item.key] = { ...meta, type: 'number', default: item.default, ...pick(item, ['min', 'max', 'step']) }\n break\n case 'string': {\n const validate = item.validate\n out[item.key] = {\n ...meta,\n type: 'string',\n default: item.default,\n ...pick(item, ['pattern', 'multiline', 'secret']),\n ...(validate ? { validate: (v: string) => validate(v) ? undefined : 'invalid value' } : {}),\n }\n break\n }\n case 'enum':\n out[item.key] = { ...meta, type: 'enum', default: item.default, options: item.options }\n break\n case 'model':\n out[item.key] = { ...meta, type: 'model', default: item.default, ...pick(item, ['multi']) }\n break\n }\n }\n return { sections, items: out }\n}\n\nfunction pick<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Partial<Pick<T, K>> {\n const out: Partial<Pick<T, K>> = {}\n for (const k of keys) {\n if (obj[k] !== undefined)\n out[k] = obj[k]\n }\n return out\n}\n","/**\n * Host runtime bridge — the late-bound capability surface behind\n * `ctx.runtime`, `ctx.sessions`, `ctx.ui`, `ctx.appendNote`, and `ctx.workspace`.\n *\n * Extension contexts are built before the host mounts, so these methods\n * route through a holder the host populates post-mount (the same idiom as\n * the prompt bridge). Detached degradation is split by stakes:\n * queries and toggles (`runtime` / `sessions` / `appendNote`) return\n * honest `null` / `false` — extensions guard on the return value instead\n * of try/catching host plumbing — while `workspace` operations REJECT,\n * because a silent no-op `writeFile` masquerading as success is worse\n * than an error (see {@link ExtensionWorkspaceSurface}).\n *\n * Notes deliberately reuse the command-output vocabulary\n * ({@link CommandOutputBlock}: full markdown or collapsed diff-colorable\n * details, or `custom` blocks bound to a registered view) and persist as\n * display-only turns — excluded from the model by the same wire guard as\n * command output. What you append is what reloads: even `custom` blocks\n * persist DATA + a mandatory markdown fallback, never rendered output —\n * the renderer registry (`ctx.tui.registerRenderer`) is a pure view\n * layer resolved at render time, so a missing/disabled renderer degrades\n * to the fallback instead of corrupting history.\n */\n\nimport type { CommandOutputBlock } from '../chat/commands'\nimport type { InteractionResponse } from '../chat/interactions'\nimport type { ModelInfo } from '../chat/providers'\nimport type { ExecResult, ExecutionContext, ExecutionHandle, ListFilesEntry, ListFilesOptions } from '../contexts'\nimport type { SessionStore } from '../session'\nimport type { SessionArtifact } from '../session/artifacts'\nimport type { JsonValue, ThinkingLevel } from '../types'\nimport type { SessionInfo, SessionListPage, SessionListQuery } from './api/sessions'\nimport type { ExtensionPromptDelivery } from './prompt-bridge'\nimport type { FacetRegistry } from './runtime/facets'\nimport type { ExtensionArtifactsSurface } from './types'\nimport { AsyncLocalStorage } from 'node:async_hooks'\nimport { normalizeArtifactInput } from '../session/artifacts'\n\n/**\n * One row of `ctx.runtime.models()` — a model offered by a provider the\n * user has credentials for. `provider.key` is the registry key (stable id,\n * e.g. `anthropic`); `provider.name` is the display name. `model` mirrors\n * the host's {@link ModelInfo} (id, context window, cost, …).\n */\nexport interface ExtensionModelEntry {\n /** Provider offering the model: registry `key` and display `name`. */\n provider: { key: string, name: string }\n /** Catalog entry for the model. */\n model: ModelInfo\n}\n\n/*\n * The orchestration shapes below mirror the chat host's (`chat/orchestration`,\n * `chat/host/orchestration`) structurally: the SDK core does not import the\n * chat layer, and the host's values are assignable to these.\n */\n\n/** An orchestration tool a session can hold: `sessions` drives sessions, `interactions` answers their prompts. */\nexport type ExtensionOrchestrationTool = 'sessions' | 'interactions'\n\n/** Which sessions a subscriber hears from. Every field narrows; `{}` is every session. */\nexport interface ExtensionSessionScope {\n /** Sessions in this project: its root, or a folder inside it. */\n projectRoot?: string\n /** Sessions on this machine: a lent machine's name, or `local` for the host itself. */\n machine?: string\n /** Only these sessions. */\n sessionIds?: readonly string[]\n}\n\n/** A tool approval's decision. */\nexport type ExtensionApprovalDecision = 'accept-once' | 'accept-session' | 'accept-safelist' | 'deny' | { kind: 'partial', mask: readonly boolean[] }\n\n/** One row of the orchestration `list(limit)` (`ExtensionSessionVerbs.list`), which `ctx.sessions.list` falls back to on a host without the `query` verb. */\nexport interface ExtensionSessionRow {\n /** Session id. */\n sessionId: string\n /** Session title (the id when it has none). */\n title: string\n /** Its folder; `''` for none. */\n cwd: string\n /** A run is in flight. */\n running: boolean\n /** Created by this extension. */\n worker: boolean\n /** Holds the `sessions` tool. */\n orchestrator?: boolean\n /** `blocked`: a question, plan or tool approval waits for an answer. */\n state: 'idle' | 'running' | 'blocked'\n /** Last change, epoch ms. */\n updatedAt: number\n /** Turns in the session. */\n turns: number\n}\n\n/** What `ctx.sessions.read()` returns. */\nexport interface ExtensionSessionDetail extends ExtensionSessionRow {\n /** Its last assistant message, cut to a few hundred characters. */\n lastMessage: string | null\n}\n\n/** What `ctx.sessions.create()` takes. */\nexport interface ExtensionCreateSessionParams {\n /** Folder the session runs in; `''` for none. */\n cwd: string\n /** First prompt, sent at once. Omit to create a session that waits (an orchestrator waiting for events). */\n prompt?: string\n /** Its title. */\n title?: string\n /** Agent profile id. */\n agentId?: string\n /** Provider registry key, with `modelId`. */\n providerKey?: string\n /** Model id. */\n modelId?: string\n /** Orchestration tools it holds: `sessions` (drive sessions), `interactions` (answer their prompts). */\n tools?: readonly ExtensionOrchestrationTool[]\n /** Sessions whose events it receives as `<session-event>` turns. `{}` = every session. */\n subscribe?: ExtensionSessionScope\n}\n\n/** What `ctx.sessions.wait()` returns. */\nexport interface ExtensionWaitResult {\n /** Why it returned: `idle` (was not running), `ended` (a run ended), `blocked` (a prompt waits), `timeout`. */\n reason: 'idle' | 'ended' | 'blocked' | 'timeout'\n /** The session as it is now. */\n session: ExtensionSessionDetail\n}\n\n/** One prompt waiting for an answer, from `ctx.sessions.pending()`. */\nexport interface ExtensionPendingRequest {\n /** The id to answer with. */\n requestId: string\n /** The session waiting. */\n sessionId: string\n /** `question` (ask_user), `plan` (present_plan), `approval` (a tool call). */\n kind: 'question' | 'plan' | 'approval'\n /** One line: what is asked. */\n summary: string\n /** The questions and choices, the plan, or the tool and its input. */\n payload: unknown\n}\n\n/** What `ctx.sessions.events()` searches for. Every field narrows. */\nexport interface ExtensionEventQuery {\n /** Only this session's events. */\n sessionId?: string\n /** Only events of this status. */\n status?: 'done' | 'error' | 'cancelled' | 'needs-attention'\n /** Only events after this `seq`. */\n since?: number\n /** Text in the title, summary, goal, detail or folder. */\n text?: string\n /** How many, newest first (default 20, at most 100). */\n limit?: number\n}\n\n/** The orchestration verbs acting as one extension (docs/ORCHESTRATION.md). */\nexport interface ExtensionSessionVerbs {\n /** Creates a session. Resolves to its id. */\n create: (params: ExtensionCreateSessionParams) => Promise<string>\n /** Other sessions, newest first. Default 30, at most 100. */\n list: (limit?: number) => Promise<readonly ExtensionSessionRow[]>\n /** A session's state and last message. */\n read: (sessionId: string) => Promise<ExtensionSessionDetail>\n /** Queues a prompt as the session's next turn. Resolves to `false` when the host declined it. */\n send: (sessionId: string, prompt: string) => Promise<boolean>\n /** Guidance into the current run, at its next turn boundary. */\n steer: (sessionId: string, message: string) => Promise<void>\n /** Interrupts the run. */\n cancel: (sessionId: string) => Promise<void>\n /** The last turns as plain text, oldest first. Default 10, at most 50. */\n transcript: (sessionId: string, limit?: number) => Promise<string>\n /** Returns once the session is idle or blocked, or after `timeoutSec`. Default 30, at most 50. */\n wait: (sessionId: string, timeoutSec?: number) => Promise<ExtensionWaitResult>\n /** The recent session events (runs ended, sessions blocked), newest first, without the pending request. */\n events: (query?: ExtensionEventQuery) => Promise<readonly ExtensionSessionEvent[]>\n /** Prompts waiting for an answer, of one session or all. */\n pending: (sessionId?: string) => Promise<readonly ExtensionPendingRequest[]>\n /** Answers a question or a plan by its request id. Resolves to `false` when it was already answered. */\n answer: (requestId: string, response: InteractionResponse) => Promise<boolean>\n /** Decides a tool approval by its request id. Resolves to `false` when it was already decided. */\n approve: (requestId: string, decision: ExtensionApprovalDecision) => Promise<boolean>\n}\n\n/**\n * The session lifecycle verbs of `ctx.sessions`. Optional:\n * a host that lacks one keeps type-checking, and the sessions domain rejects the\n * call with a clear error. Every verb acts as the extension the verbs were\n * made for.\n */\nexport interface ExtensionSessionLifecycleVerbs {\n /**\n * Sessions that match a query, as `ctx.sessions.list` answers. The query is\n * validated and its defaults filled (`limit`, `sort`, `archived`) before the\n * call. Rows carry the host's stored facet values. Without it, `list` reads\n * the orchestration `list` (its 100 newest sessions, fields `id`, `title`,\n * `cwd`, `projectName`, `status`, `updatedAt`, no facets, no archived\n * sessions) and filters it in the runtime; a query that needs more (another\n * field, a facet, archived sessions, a filter or sort over a full list, a\n * page cut short by the 100th row) rejects naming why. A page that ends\n * exactly at the 100th row is answered, with no cursor.\n */\n query?: (query: Required<Pick<SessionListQuery, 'limit' | 'sort' | 'archived'>> & Omit<SessionListQuery, 'limit' | 'sort' | 'archived'>) => Promise<SessionListPage>\n /** A session's live settings, or `undefined` for an unknown session. */\n get?: (sessionId: string) => Promise<SessionInfo | undefined>\n /** Deletes a session. Resolves to whether it did. */\n remove?: (sessionId: string) => Promise<boolean>\n /** Compacts a session's history now. Resolves to whether it did. */\n compact?: (sessionId: string) => Promise<boolean>\n /** Changes a session's model. Resolves to whether the host accepted it. */\n switchModel?: (sessionId: string, model: { providerId: string, modelId: string }) => Promise<boolean>\n /** Changes a session's agent profile. Resolves to whether the host accepted it. */\n switchAgent?: (sessionId: string, agentId: string) => Promise<boolean>\n /** Changes a session's thinking level. Resolves to whether the host accepted it. */\n setThinking?: (sessionId: string, level: ThinkingLevel) => Promise<boolean>\n /** Submits text to a session as if the user typed it (commands, interceptors, skills). Resolves to whether it was taken. */\n submit?: (sessionId: string, text: string, opts?: ExtensionPromptDelivery) => Promise<boolean>\n /** Adds a message the model sees on the next turn, without starting a run. */\n synthetic?: (sessionId: string, message: { role: 'user' | 'assistant', text: string }) => Promise<boolean>\n /** Adds display-only blocks to a session's transcript. Persisted, never sent to the model. */\n note?: (sessionId: string, blocks: readonly CommandOutputBlock[]) => Promise<boolean>\n}\n\n/** A session event (a run ended, or a session waits for an answer), as `ctx.sessions.onEvent` handlers get it. */\nexport interface ExtensionSessionEvent {\n /** The session it is about. */\n sessionId: string\n /** Its title at the time. */\n title: string\n /** `done`, `error`, `cancelled`, or `needs-attention` (a question, plan or tool approval waits). */\n status: 'done' | 'error' | 'cancelled' | 'needs-attention'\n /** One line: its last message, the failure, or what it waits for. */\n summary: string\n /** When, epoch ms. */\n at: number\n /** Its place in the event log: pass it as `since` to `ctx.sessions.events`. */\n seq?: number\n /** Created by the caller that reads it. */\n worker?: boolean\n /** Its folder; `''` for none. */\n cwd?: string\n /** The prompt that started the run. */\n goal?: string\n /** For `error`: the failure. */\n error?: string\n /** For `needs-attention`: what is asked, in one line. */\n detail?: string\n /** For `needs-attention`: the request, to answer with `ctx.sessions.answer` / `approve`. */\n request?: { id: string, kind: 'question' | 'plan' | 'approval', payload: unknown }\n /** The run ended abnormally: it hit the length limit, paused, or was filtered. */\n finishReason?: 'length' | 'pause' | 'content-filter'\n /** What the run touched. */\n artifacts?: { changed: readonly string[], commands: number, toolCalls: number }\n /** The run's duration, tokens, turns and cost, when known. */\n durationMs?: number\n /** Tokens the run used. */\n tokens?: number\n /** Turns the run took. */\n turns?: number\n /** Cost of the run in USD. */\n costUsd?: number\n}\n/** Handler registered with `ctx.sessions.onEvent`. */\nexport type ExtensionSessionEventHandler = (event: ExtensionSessionEvent) => void | Promise<void>\n\n/**\n * The live `(execution, handle)` pair behind `ctx.workspace`. Resolved\n * per call — never cached by the facade — because the pair changes on\n * session switch, cwd change, and registry rebuilds; a captured pair\n * would point at a destroyed container.\n */\nexport interface ExtensionWorkspacePair {\n /** Execution context the commands run in. */\n execution: ExecutionContext\n /** Handle to the live execution. */\n handle: ExecutionHandle\n}\n\n/**\n * `ctx.workspace`'s operations already bound to a session, for a host whose\n * execution lives in another process (the TUI in daemon mode reaches the\n * session's workspace over IPC). Same contract as the facade's methods.\n */\nexport type ExtensionWorkspaceOps = Omit<ExtensionWorkspaceSurface, 'available'>\n\n/**\n * What `ctx.artifacts` resolves queries against: the host's artifacts (its\n * session store, or a client's view of a host's) plus the active session's\n * identity, so `scope: 'session'` / `'project'` can be answered without the\n * extension knowing either id.\n */\nexport interface ExtensionArtifactScope {\n /** Store the artifacts are read from and written to. */\n store: Pick<SessionStore, 'listArtifacts' | 'upsertArtifact'>\n /** Active session id. Needed to answer `scope: 'session'` queries. */\n sessionId?: string\n /** Project root of the active session. Needed to answer `scope: 'project'` queries. */\n projectRoot?: string\n /** Active run id, when a run is in flight — stamped on `record`ed artifacts. */\n runId?: string\n /**\n * Host-owned write path for `ctx.artifacts.record`. Defaults to\n * `store.upsertArtifact`; hosts override to route through a daemon RPC or\n * to fan out a change signal after the write.\n */\n record?: (artifact: SessionArtifact) => Promise<SessionArtifact | null>\n}\n\n/** What a host attaches to power the runtime surfaces. */\nexport interface ExtensionHostRuntimeImpl {\n /** Returns the active model id, or `null` when none is selected. */\n model: () => string | null\n /**\n * Model catalog across every provider the user has credentials for.\n * Optional so pre-catalog host impls keep typechecking; the facade\n * treats absence as an empty catalog.\n */\n models?: () => readonly ExtensionModelEntry[]\n /** Returns the active thinking level, or `null` when none applies. */\n thinking: () => ThinkingLevel | null\n /** Sets the thinking level. Returns whether the host accepted it. */\n setThinking: (level: ThinkingLevel) => boolean\n /** Shows session `id` in this window (`ctx.ui.openSession`). Resolves to whether it did. */\n switchSession: (id: string) => Promise<boolean>\n /** Opens a new, empty session in this window (`ctx.ui.newSession`). Resolves to whether one was opened. */\n createSession: () => Promise<boolean>\n /** Appends output blocks to the active transcript. Returns whether the host accepted them. */\n appendNote: (blocks: readonly CommandOutputBlock[]) => boolean\n /**\n * Resolve the ACTIVE session's execution pair, spawning the handle if\n * no run has created it yet (`agent.ensureExecution()`). `null` when\n * no agent/session is live; REJECT when a live agent's spawn fails\n * (daemon down, spawn timeout) so the facade surfaces the real error\n * instead of a generic \"detached\". Optional so pre-workspace host\n * impls keep typechecking; the facade treats absence as detached.\n * A host whose execution lives in another process returns session-bound\n * {@link ExtensionWorkspaceOps} instead of a pair.\n */\n workspace?: () => Promise<ExtensionWorkspacePair | ExtensionWorkspaceOps | null>\n /**\n * Side-effect-free availability signal (\"is there a live agent?\").\n * MUST NOT spawn: `workspace()` may boot a container on first call,\n * and `ctx.workspace.available()` — a guard extensions call casually,\n * even at setup — must never pay that price to answer a boolean.\n * Optional; when absent the facade falls back to `workspace()` (with\n * its side effects — implement this on any host with heavy spawns).\n */\n workspaceAvailable?: () => boolean\n /**\n * Backing for `ctx.artifacts`. Optional so pre-artifact host impls keep\n * typechecking; the facade treats absence (or a store without artifact\n * methods) as an empty store.\n */\n artifacts?: () => ExtensionArtifactScope | null\n}\n\n/**\n * Host-level session control behind `ctx.sessions`: the orchestration verbs\n * and per-session extension state, addressing any session by id, inside a run\n * or not.\n */\nexport interface ExtensionSessionControl {\n /** The orchestration verbs acting as extension `extension`, with the lifecycle verbs the host implements. */\n verbs: (extension: string) => ExtensionSessionVerbs & ExtensionSessionLifecycleVerbs\n /** One value of `extension`'s per-session state (`ctx.session`), live or stored. */\n getData: (sessionId: string, extension: string, key: string) => Promise<JsonValue | undefined>\n /** Write one value of `extension`'s per-session state; `undefined` deletes it. */\n setData: (sessionId: string, extension: string, key: string, value: JsonValue | undefined) => Promise<void>\n /**\n * Starts computing a runtime's facets (`ctx.sessions.facets`): the\n * runtime calls it when an extension registers or refreshes a facet.\n * Idempotent. Optional: a host without it computes no facets.\n */\n attachFacets?: (registry: FacetRegistry) => void\n}\n\n/** Connects a host to the runtime surfaces extensions see as `ctx.runtime`, `ctx.sessions`, `ctx.workspace` and `ctx.artifacts`. */\nexport interface ExtensionHostRuntimeBridge {\n /**\n * Process-wide attachment — a single-session host (the TUI) attaches the\n * active session's impl once and swaps it on session change.\n */\n attach: (impl: ExtensionHostRuntimeImpl) => () => void\n /**\n * Async-scoped attachment — a multi-session host (daemon, GUI) runs a\n * command for session X inside `runWith(implForX, …)`; every\n * `ctx.runtime` / `ctx.sessions` / `ctx.workspace` call made anywhere in\n * that async tree resolves to X, even while another session's command\n * runs concurrently. Takes precedence over `attach` inside the scope.\n */\n runWith: <T>(impl: ExtensionHostRuntimeImpl, fn: () => Promise<T>) => Promise<T>\n /** Returns the implementation in effect: the innermost `runWith` scope, else the attached one, else `null`. */\n current: () => ExtensionHostRuntimeImpl | null\n /** Attach the chat host's session control (one per bridge; the newest wins). Returns a detach. */\n attachSessionControl: (control: ExtensionSessionControl) => () => void\n /** The attached session control, or `null`. */\n sessionControl: () => ExtensionSessionControl | null\n}\n\n/** Creates a bridge that hosts attach their runtime implementation to. */\nexport function createExtensionHostRuntimeBridge(): ExtensionHostRuntimeBridge {\n let impl: ExtensionHostRuntimeImpl | null = null\n let control: ExtensionSessionControl | null = null\n const scoped = new AsyncLocalStorage<ExtensionHostRuntimeImpl>()\n return {\n attachSessionControl(next) {\n control = next\n return () => {\n if (control === next)\n control = null\n }\n },\n sessionControl: () => control,\n attach(next) {\n impl = next\n return () => {\n if (impl === next)\n impl = null\n }\n },\n runWith: (next, fn) => scoped.run(next, fn),\n current: () => scoped.getStore() ?? impl,\n }\n}\n\n/** `ctx.runtime` — reads/controls over the host's active model state. */\nexport interface ExtensionRuntimeSurface {\n /** Active model id, or `null` when detached / none picked. */\n model: () => string | null\n /**\n * Every model available across the user's credentialed providers.\n * Empty when detached (headless, or before the renderer mounts).\n * Use it to build model pickers (e.g. a review command letting the\n * user pin subagents to specific models).\n */\n models: () => readonly ExtensionModelEntry[]\n /** Active thinking level, or `null` when detached / not applicable. */\n thinking: () => ThinkingLevel | null\n /** Set the thinking level. `false` when detached or unsupported by the model. */\n setThinking: (level: ThinkingLevel) => boolean\n}\n\n/**\n * `ctx.sessions` — the orchestration verbs, acting as this extension\n * (docs/ORCHESTRATION.md), plus this extension's state of any session. Every\n * verb rejects without a chat host (a TUI-only window), and when the call is\n * refused (an unknown session).\n */\nexport interface ExtensionSessionsSurface extends ExtensionSessionVerbs {\n /**\n * Hear every session event: a run ended (`done`, `error`) or a session waits\n * for an answer (`needs-attention`, with the request). Register during setup;\n * runs on the chat host (GUI and daemon), outside any run.\n */\n onEvent: (handler: ExtensionSessionEventHandler) => void\n /** This extension's per-session value `key` (`ctx.session`'s store) of any session, inside a run or not. `undefined` when unset. Rejects when detached. */\n getData: (sessionId: string, key: string) => Promise<JsonValue | undefined>\n /** Write this extension's per-session value `key` of any session; `undefined` deletes it. Rejects when detached. */\n setData: (sessionId: string, key: string, value: JsonValue | undefined) => Promise<void>\n}\n\n/** `ctx.ui` — what this window shows. Per window: a daemon or a server has none, and answers `false`. */\nexport interface ExtensionUiSurface {\n /** Show session `id` in this window. `false` when detached or it could not. */\n openSession: (id: string) => Promise<boolean>\n /** Open a new, empty session in this window. `false` when detached. */\n newSession: () => Promise<boolean>\n}\n\n/**\n * `ctx.workspace` — shell + file operations routed through the SESSION'S\n * execution context, so extension work happens wherever the agent's tools\n * run (host process, docker, remote sandbox) with the same transport\n * output caps and containment. The curated \"do work in the workspace\"\n * subset — lifecycle methods (`spawn` / `destroy` / background tasks)\n * are deliberately absent: the pair belongs to the agent.\n *\n * Unlike `ctx.runtime` / `ctx.sessions` (queries and toggles that degrade\n * to `null` / `false`), these are imperative operations whose silent\n * failure would corrupt caller logic — a no-op `writeFile` must not look\n * like success. Detached ⇒ every method REJECTS with a clear error.\n * Guard with {@link ExtensionWorkspaceSurface.available} or try/catch.\n */\nexport interface ExtensionWorkspaceSurface {\n /** `true` when a live session's execution pair is reachable. */\n available: () => Promise<boolean>\n /**\n * Run a shell command in the workspace. Resolves with the full\n * ExecResult (non-zero exits RESOLVE — inspect `exitCode`); rejects\n * only when detached or the transport itself fails. Output is\n * byte-capped by the context's transport (10MB default).\n */\n exec: (command: string, options?: { cwd?: string, env?: Record<string, string>, timeout?: number, signal?: AbortSignal }) => Promise<ExecResult>\n /** Read a file from the workspace's filesystem (whole-file — probe `fileSize` first for anything potentially large). */\n readFile: (path: string) => Promise<string>\n /** Write a file into the workspace's filesystem (parent dirs created). */\n writeFile: (path: string, content: string) => Promise<void>\n /** List a directory in the workspace — `ListFilesOptions` semantics (`glob: true` treats `path` as a pattern). */\n listFiles: (path: string, options?: ListFilesOptions) => Promise<ListFilesEntry[]>\n /** Byte size of a file, or `null` when unknowable — same contract as `ExecutionContext.fileSize`. */\n fileSize: (path: string) => Promise<number | null>\n}\n\n/**\n * Build the `ctx.artifacts` facade over a host-runtime bridge. Read-only;\n * every call re-resolves the scope (session switches swap it). Detached,\n * or a store without artifact support, answers `[]` — the same honest\n * degradation as `ctx.sessions`.\n *\n * @param resolve - Returns the current artifact scope, or `null`/`undefined` when detached. Called on every query.\n */\nexport function createArtifactsSurface(\n resolve: () => ExtensionArtifactScope | null | undefined,\n): ExtensionArtifactsSurface {\n return {\n list: async (query) => {\n const scope = resolve()\n if (!scope?.store.listArtifacts)\n return []\n const mode = query?.scope ?? 'session'\n const base = {\n ...(query?.kind !== undefined ? { kind: query.kind } : {}),\n ...(query?.since !== undefined ? { since: query.since } : {}),\n ...(query?.limit !== undefined ? { limit: query.limit } : {}),\n }\n if (mode === 'session') {\n if (!scope.sessionId)\n return []\n return scope.store.listArtifacts({ ...base, sessionId: scope.sessionId })\n }\n if (mode === 'project') {\n if (!scope.projectRoot)\n return []\n return scope.store.listArtifacts({ ...base, projectRoot: scope.projectRoot })\n }\n return scope.store.listArtifacts(base)\n },\n find: async (kind, uri) => {\n const scope = resolve()\n if (!scope?.store.listArtifacts)\n return []\n return scope.store.listArtifacts({ kind, uri })\n },\n record: async (input) => {\n const scope = resolve()\n if (!scope?.sessionId)\n return undefined\n const write = scope.record ?? scope.store.upsertArtifact?.bind(scope.store)\n if (!write)\n return undefined\n // Extension input is a trust boundary: same normalization the loop\n // applies to tool metadata (kind shape, bounds, meta size).\n const normalized = normalizeArtifactInput(input)\n if (!normalized)\n return undefined\n const now = Date.now()\n const projectRoot = normalized.projectRoot ?? scope.projectRoot\n try {\n const stored = await write({\n id: crypto.randomUUID(),\n sessionId: scope.sessionId,\n ...(scope.runId ? { runId: scope.runId } : {}),\n kind: normalized.kind,\n uri: normalized.uri,\n label: normalized.label,\n ...(projectRoot ? { projectRoot } : {}),\n ...(normalized.meta !== undefined ? { meta: normalized.meta } : {}),\n createdAt: now,\n updatedAt: now,\n })\n return stored ?? undefined\n }\n catch {\n return undefined\n }\n },\n }\n}\n\n/**\n * Build the `ctx.workspace` facade over a host-runtime bridge. Every call\n * re-resolves the live pair (see {@link ExtensionWorkspacePair}); detached\n * calls reject with a message naming the guard.\n *\n * `isAvailable` is the host's side-effect-free availability signal,\n * tri-state by design: `true`/`false` answer directly, `undefined` means\n * \"no light signal wired\" and falls back to `resolve()` — accepting its\n * side effects (a container spawn, on heavy hosts). Wire it wherever\n * spawning is non-trivial.\n *\n * @param resolve - Returns the live execution pair, or `null` when detached. Called on every operation.\n * @param isAvailable - Side-effect-free availability signal. When omitted, availability falls back to `resolve`.\n */\nexport function createWorkspaceSurface(\n resolve: () => Promise<ExtensionWorkspacePair | ExtensionWorkspaceOps | null> | ExtensionWorkspacePair | ExtensionWorkspaceOps | null,\n isAvailable?: () => boolean | undefined,\n): ExtensionWorkspaceSurface {\n const ops = async (): Promise<ExtensionWorkspaceOps> => {\n // Spawn/transport failures from `resolve` propagate as-is — a docker\n // daemon being down must read as that, not as \"detached\".\n const resolved = await resolve()\n if (!resolved)\n throw new Error('ctx.workspace is detached (no live session or host). Guard with `await ctx.workspace.available()`.')\n return 'execution' in resolved ? pairOps(resolved) : resolved\n }\n return {\n available: async () => {\n // Prefer the host's side-effect-free signal — `resolve()` may spawn\n // a container, which a boolean guard must never trigger.\n const light = isAvailable?.()\n if (light !== undefined)\n return light\n try {\n return await resolve() !== null\n }\n catch {\n return false\n }\n },\n exec: async (command, options) => (await ops()).exec(command, options),\n readFile: async path => (await ops()).readFile(path),\n writeFile: async (path, content) => (await ops()).writeFile(path, content),\n listFiles: async (path, options) => (await ops()).listFiles(path, options),\n fileSize: async path => (await ops()).fileSize(path),\n }\n}\n\n/** The workspace operations over an in-process execution pair. */\nfunction pairOps({ execution, handle }: ExtensionWorkspacePair): ExtensionWorkspaceOps {\n return {\n exec: (command, options) => execution.exec(handle, command, options),\n readFile: path => execution.readFile(handle, path),\n writeFile: (path, content) => execution.writeFile(handle, path, content),\n listFiles: (path, options) => execution.listFiles(handle, path, options),\n fileSize: async path => await execution.fileSize?.(handle, path) ?? null,\n }\n}\n","/**\n * Owners: groups of registrations with one lifetime (extension API).\n *\n * The extension's root owner lives until the extension unloads. `scope()`\n * makes a child that is disposed with its parent, or earlier on its own.\n *\n * Disposal has two phases. Withdraw: the owner refuses new registrations\n * and runs its `onCleanup` entries (registrations: nothing new routes to the\n * extension). Teardown: it aborts its signal and runs its `onTeardown`\n * entries (the domains in-flight work uses: storage, the setup cleanup).\n * Without a lease both phases run at once, signal first. A call in flight\n * holds a lease (`lease`): disposing then withdraws at once and defers the\n * teardown until every lease ends, at most until the longest lease's bound\n * (its own timeout, or `drainMs` for a call with none). Each cleanup starts\n * synchronously, so a hung async cleanup never blocks the ones after it;\n * `settled` resolves once all of them finished.\n */\n\nimport type { Cleanup, Disposable, Owner } from '../api/core'\nimport { DisposedError } from '../api/core'\n\n/** How long a disposed owner waits for a call without a bound of its own (a command run, a tool execute), in ms. */\nexport const DEFAULT_DRAIN_MS = 30 * 60_000\n\n/** What {@link OwnerOptions.onDrain} and {@link OwnerOptions.onDrainTimeout} are told. */\nexport interface DrainInfo {\n /** The owner. */\n label: string\n /** The calls still running, by label. */\n active: readonly string[]\n /** `onDrain`: how long the teardown waits at most. `onDrainTimeout`: how long it waited. */\n ms: number\n}\n\n/** Options for {@link createOwner}. */\nexport interface OwnerOptions {\n /**\n * Receives a cleanup that threw or rejected. The rest still run. Defaults\n * to the parent's handler; a root owner without one drops the error.\n */\n onError?: (error: unknown, label: string) => void\n /** Names the owner in errors (`DisposedError`, `onError` labels). Default `'owner'`. */\n label?: string\n /** Bound of a lease taken without a timeout, counted from dispose, in ms. Default {@link DEFAULT_DRAIN_MS}. */\n drainMs?: number\n /** Called once when dispose found calls in flight and deferred the teardown. */\n onDrain?: (info: DrainInfo) => void\n /** Called when the bound passed with calls still running; the teardown runs then. */\n onDrainTimeout?: (info: DrainInfo) => void\n}\n\n/** The runtime side of an {@link Owner}: child scopes, leases and awaitable disposal. */\nexport interface RuntimeOwner extends Owner {\n /** The owner this one is a child of. */\n readonly parent?: RuntimeOwner\n /** The name used in errors. */\n readonly label: string\n /** Resolves once `dispose` ran and every async cleanup settled (both phases). Pending until then. */\n readonly settled: Promise<void>\n /** Resolves once the withdraw phase's async cleanups settled. */\n readonly withdrawn: Promise<void>\n /** Disposed and waiting for its leases: registrations are withdrawn, the domains still work. */\n readonly draining: boolean\n /** The teardown ran: the domains refuse every call. */\n readonly tornDown: boolean\n /** A child owner, disposed with this one or earlier by itself. Throws {@link DisposedError} once this one is disposed. */\n scope: (label?: string) => RuntimeOwner\n /** Adds a cleanup to the teardown phase. Throws {@link DisposedError} once torn down. */\n onTeardown: (cleanup: Cleanup) => Disposable\n /**\n * Marks a call in flight until the returned release runs (calling it again\n * is a no-op). A dispose meanwhile defers the teardown.\n *\n * @param label - Names the call in errors and drain logs.\n * @param opts - The call's bound.\n * @param opts.timeoutMs - The call's own timeout; the teardown waits no longer for it.\n * @throws DisposedError naming `label` when the owner is disposed.\n */\n lease: (label: string, opts?: { timeoutMs?: number }) => () => void\n /** Disposes, then waits for every async cleanup. Same as `dispose()` followed by `await settled`. */\n disposeAsync: () => Promise<void>\n}\n\nconst ON_ERROR = Symbol('owner.onError')\n\ninterface Entry { run: Cleanup }\ninterface LeaseRecord { label: string, start: number, timeoutMs?: number }\ninterface InternalOwner extends RuntimeOwner { [ON_ERROR]?: OwnerOptions['onError'] }\n\n/**\n * Makes an owner.\n *\n * @param parent - The owner this one belongs to. The child is disposed with it, and inherits its `onError`.\n * @param options - Error handler, label and drain bound.\n * @returns A live owner.\n * @throws DisposedError when `parent` is already disposed.\n */\nexport function createOwner(parent?: RuntimeOwner, options: OwnerOptions = {}): RuntimeOwner {\n const label = options.label ?? (parent ? `${parent.label}/scope` : 'owner')\n const onError = options.onError ?? (parent ? (parent as InternalOwner)[ON_ERROR] : undefined)\n const drainMs = options.drainMs ?? DEFAULT_DRAIN_MS\n const controller = new AbortController()\n // Insertion-ordered; a withdrawn cleanup leaves the set, so disposal walks only live ones.\n const entries = new Set<Entry>()\n const teardowns = new Set<Entry>()\n const leases = new Set<LeaseRecord>()\n let disposed = false\n let torn = false\n let draining = false\n let drainTimer: ReturnType<typeof setTimeout> | undefined\n let unlink: (() => void) | undefined\n let unlinkTeardown: (() => void) | undefined\n let resolveSettled!: () => void\n const settled = new Promise<void>((resolve) => { resolveSettled = resolve })\n let resolveWithdrawn!: () => void\n const withdrawn = new Promise<void>((resolve) => { resolveWithdrawn = resolve })\n\n const report = (error: unknown, what: string): void => {\n try {\n onError?.(error, what)\n }\n catch {}\n }\n\n /** Runs `set`'s cleanups in reverse order; resolves once the async ones settled. */\n const runAll = (set: Set<Entry>): Promise<unknown> => {\n const pending: Promise<unknown>[] = []\n for (const entry of [...set].reverse()) {\n set.delete(entry)\n try {\n const result = entry.run()\n if (result && typeof (result as Promise<void>).then === 'function')\n pending.push(Promise.resolve(result).catch(error => report(error, `${label} cleanup`)))\n }\n catch (error) {\n report(error, `${label} cleanup`)\n }\n }\n return Promise.all(pending)\n }\n\n const add = (set: Set<Entry>, cleanup: Cleanup): Disposable => {\n const entry: Entry = { run: cleanup }\n set.add(entry)\n return { dispose: () => { set.delete(entry) } }\n }\n\n let withdrawDone: Promise<unknown> = Promise.resolve()\n\n const finalize = (): void => {\n if (torn)\n return\n torn = true\n draining = false\n clearTimeout(drainTimer)\n leases.clear()\n unlinkTeardown?.()\n if (!controller.signal.aborted)\n controller.abort(new DisposedError(label))\n void Promise.all([withdrawDone, runAll(teardowns)]).then(() => resolveSettled())\n }\n\n const activeLabels = (): string[] => [...leases].map(l => l.label)\n\n const self: InternalOwner = {\n label,\n parent,\n signal: controller.signal,\n settled,\n withdrawn,\n get disposed() { return disposed },\n get draining() { return draining },\n get tornDown() { return torn },\n [ON_ERROR]: onError,\n\n onCleanup(cleanup: Cleanup): Disposable {\n if (disposed)\n throw new DisposedError(`${label}.onCleanup`)\n return add(entries, cleanup)\n },\n\n onTeardown(cleanup: Cleanup): Disposable {\n if (torn)\n throw new DisposedError(`${label}.onCleanup`)\n return add(teardowns, cleanup)\n },\n\n scope(childLabel?: string): RuntimeOwner {\n if (disposed)\n throw new DisposedError(`${label}.scope`)\n return createOwner(self, childLabel ? { label: childLabel } : {})\n },\n\n lease(what: string, opts: { timeoutMs?: number } = {}): () => void {\n if (disposed)\n throw new DisposedError(what)\n const record: LeaseRecord = { label: what, start: Date.now(), ...(opts.timeoutMs !== undefined ? { timeoutMs: opts.timeoutMs } : {}) }\n leases.add(record)\n return () => {\n if (!leases.delete(record))\n return\n if (draining && leases.size === 0)\n finalize()\n }\n },\n\n dispose(): void {\n if (disposed)\n return\n disposed = true\n // Withdrawn by a draining parent: the parent's teardown finishes this one too.\n const parentDrains = parent?.disposed === true && parent.draining\n unlink?.()\n if (!parentDrains)\n unlinkTeardown?.()\n const defer = leases.size > 0 || parentDrains\n if (!defer)\n controller.abort(new DisposedError(label))\n draining = defer\n withdrawDone = runAll(entries)\n void withdrawDone.then(() => resolveWithdrawn())\n if (!defer) {\n finalize()\n return\n }\n if (leases.size === 0)\n return\n const now = Date.now()\n const deadline = Math.max(...[...leases].map(l => l.timeoutMs !== undefined && Number.isFinite(l.timeoutMs) ? l.start + l.timeoutMs : now + drainMs))\n const ms = Math.max(0, deadline - now)\n try {\n options.onDrain?.({ label, active: activeLabels(), ms })\n }\n catch {}\n drainTimer = setTimeout(() => {\n if (torn)\n return\n try {\n options.onDrainTimeout?.({ label, active: activeLabels(), ms: Date.now() - now })\n }\n catch {}\n finalize()\n }, ms)\n drainTimer.unref?.()\n },\n\n async disposeAsync(): Promise<void> {\n self.dispose()\n await settled\n },\n }\n\n if (parent) {\n // The parent disposes the child (and waits for it); the child leaves the parent when it goes first.\n unlink = parent.onCleanup(() => {\n self.dispose()\n return torn ? settled : withdrawn\n }).dispose\n unlinkTeardown = parent.onTeardown(() => {\n finalize()\n return settled\n }).dispose\n }\n return self\n}\n\n/**\n * Ties `disposable` to `owner`: it is disposed when the owner is. The\n * returned Disposable disposes it early and drops it from the owner. Calling\n * it twice is a no-op. Works with any {@link Owner}, so domains can use it on\n * `DomainDeps.owner`.\n *\n * @param owner - The owner the registration belongs to.\n * @param disposable - The registration to withdraw with it.\n * @returns A Disposable for the registration.\n * @throws DisposedError when `owner` is disposed; `disposable` is disposed first so nothing leaks.\n */\nexport function track(owner: Owner, disposable: Disposable): Disposable {\n if (owner.disposed) {\n disposable.dispose()\n throw new DisposedError('register')\n }\n let done = false\n const once = (): void => {\n if (done)\n return\n done = true\n disposable.dispose()\n }\n const link = owner.onCleanup(once)\n return {\n dispose: () => {\n link.dispose()\n once()\n },\n }\n}\n\n/**\n * Throws when `owner` is disposed. Domains call it before a registration\n * creates any effect.\n *\n * @param owner - The owner to check.\n * @param what - The call being made, for the error message (e.g. `'tools.register'`).\n * @throws DisposedError when `owner` is disposed.\n */\nexport function assertAlive(owner: Owner, what: string): void {\n if (owner.disposed)\n throw new DisposedError(what)\n}\n\n/**\n * Whether `owner`'s domains refuse calls: torn down, or for an owner without\n * a teardown phase, disposed. A draining owner still serves its in-flight work.\n *\n * @param owner - The owner to check.\n */\nexport function isTornDown(owner: Owner): boolean {\n const tornDown = (owner as Partial<RuntimeOwner>).tornDown\n return typeof tornDown === 'boolean' ? tornDown : owner.disposed\n}\n\n/**\n * Throws when `owner` is torn down. Domains that in-flight work uses\n * (storage, sessions, generate, workspace) check this instead of\n * {@link assertAlive}, so a call that started before dispose finishes.\n *\n * @param owner - The owner to check.\n * @param what - The call being made, for the error message.\n * @throws DisposedError when `owner` is torn down.\n */\nexport function assertUsable(owner: Owner, what: string): void {\n if (isTornDown(owner))\n throw new DisposedError(what)\n}\n\n/**\n * Adds `cleanup` to `owner`'s teardown phase (`onCleanup` for an owner\n * without one): it runs once the in-flight calls ended.\n *\n * @param owner - The owner.\n * @param cleanup - What to run at teardown.\n */\nexport function onTeardown(owner: Owner, cleanup: Cleanup): Disposable {\n const runtime = owner as Partial<RuntimeOwner>\n return typeof runtime.onTeardown === 'function' ? runtime.onTeardown(cleanup) : owner.onCleanup(cleanup)\n}\n","/**\n * Extension API: UI. Contributions are data the hosts draw natively; any\n * of them may also name a component from the extension's `ui` / `tui`\n * entry. `ctx.add(Token, item)` returns a {@link Handle}.\n */\n\nimport type { CompletionProvider } from '../../chat/completion'\nimport type { ContextBreakdownContributor } from '../../chat/context-breakdown'\nimport type { InlineAutocompleteProvider } from '../../chat/inline-autocomplete'\nimport type { PlanPayload, PlanResponse, QuestionPayload, QuestionResponse } from '../../chat/interactions'\nimport type { FacetPath, SessionGroupBy, SessionQuery, SessionSort } from '../../chat/session-query'\nimport type { Theme } from '../../chat/theme'\nimport type { ThinkingLevel } from '../../thinking-levels'\nimport type { ExtensionBadgeActions } from '../badge-actions'\nimport type { ExtensionPanel, PanelFocus } from '../panels'\nimport type { ExtensionBadgeColor, ExtensionBadgeIcon, ExtensionBadgeTone, ExtensionContextPanelSection, ExtensionReferenceProvider } from '../types'\nimport type { Bindable, ComponentRef, Disposable, Handle } from './core'\nimport type { SettingsSchema } from './settings'\n\nexport { escapeTemplate } from '../../chat/session-query'\n\n/** A token naming a kind of UI contribution. */\nexport interface UiToken<T, K extends string = string> {\n /** Always `'ui'`. */\n readonly kind: 'ui'\n /** The contribution kind, e.g. `'panel'`. */\n readonly name: K\n /** Type-level only. */\n readonly __type?: T\n}\n\nfunction token<T, K extends string>(name: K): UiToken<T, K> {\n return { kind: 'ui', name }\n}\n\n/** A side or home panel: an {@link ExtensionPanel} (load, subscribe, onAction, controls, focus), plus an optional component. */\nexport type PanelItem = ExtensionPanel & { component?: ComponentRef }\n\n/**\n * Named places every app knows. An app without the place ignores the item.\n *\n * The sidebar has three:\n *\n * - `'sidebar.top'`: full-width block rows pinned under the sidebar's search\n * row, above the session list. Desktop and web: between the search well and\n * the list. Terminal: on the sessions screen, between the search box and\n * the list.\n * - `'sidebar.bottom'`: full-width block rows pinned under the session list,\n * above the footer strip. Terminal: right under the sessions list.\n * - `'sidebar.footer'`: compact chips inside the footer strip itself, next to\n * the app's status (terminal: a line under the sessions list).\n *\n * `'sidebar.top'` and `'sidebar.bottom'` never scroll with the list. Each row\n * draws the item's icon (or loader), text, count, tone and highlight, or its\n * component. Each block takes at most part of the sidebar's height (desktop\n * and web: 30%; it scrolls on its own past that), so the list keeps the rest.\n * An empty block draws nothing.\n */\nexport type SlotName\n = | 'app.statusbar'\n | 'app.titlebar'\n | 'session.header'\n | 'composer.above'\n | 'composer.below'\n | 'composer.badges'\n | 'sidebar.top'\n | 'sidebar.bottom'\n | 'sidebar.footer'\n | 'transcript.turn-end'\n | 'home.block'\n | 'settings.section'\n\n/** A small item placed in a slot: a status line, a banner, a composer badge. */\nexport interface SlotItem {\n /** The slot that draws the item. */\n at: SlotName\n /** Limits the item to one session. A session's items go when it is deleted. */\n sessionId?: string\n /**\n * `transcript.turn-end` only: the item draws right after the turn with\n * this id (pair it with `sessionId`). Without it the item draws once, at\n * the end of the transcript. A host whose transcript holds no turn with\n * this id does not draw the item. Other slots refuse it.\n */\n turnId?: string\n /** Main text of the item. */\n text?: Bindable<string>\n /** Lines of a banner (`composer.above`). */\n lines?: Bindable<readonly string[]>\n /** A number or short label shown with the item. */\n count?: Bindable<number | string>\n /** Icon drawn with the item. */\n icon?: ExtensionBadgeIcon\n /** Tone of the item. */\n tone?: Bindable<ExtensionBadgeTone>\n /** Accent color of the item. */\n color?: ExtensionBadgeColor\n /** A running arc in place of the icon. */\n loader?: Bindable<boolean>\n /** Raised and breathing: something waits on the user. */\n highlight?: Bindable<boolean>\n /** Hover text. */\n title?: Bindable<string>\n /** A click opens this panel (`<id>`, `<extension>/<id>`, or a built-in tab). */\n panel?: string\n /** A click runs this command. */\n command?: string\n /** Lower first. Default 100. */\n order?: number\n /** Withdraws the item after this many ms. */\n timeoutMs?: number\n /** Drawn instead of the data where the host has it. */\n component?: ComponentRef\n}\n\n/** A full-screen view, or a modal when `presentation` is `'modal'`. */\nexport interface ScreenItem {\n /** Screen id, unique in the extension. Other extensions use `<extension>/<id>`. */\n id: string\n /** Title of the screen. */\n title: Bindable<string>\n /** `'screen'` fills the window, `'modal'` opens a dialog. */\n presentation?: 'screen' | 'modal'\n /** Required: hosts without the component draw `fallback`. */\n component: ComponentRef\n /** Markdown drawn where the component is missing. */\n fallback?: string\n}\n\n/** What a renderer draws: a custom block id, a code-block language, a tool's result, or an artifact kind's detail. */\nexport type RendererTarget = { block: string } | { language: string } | { tool: string | readonly string[] } | { artifact: string }\n\n/** A renderer: a component per host, with a markdown fallback. */\nexport interface RendererItem {\n /** What the renderer draws. */\n for: RendererTarget\n /** The component that draws it. */\n component: ComponentRef\n /** `true`: the component returns null to let the next renderer (or the default) draw. */\n fallthrough?: boolean\n}\n\n/** A page in Settings under the extension. Data from a settings-like schema, or a component. */\nexport interface SettingsPageItem {\n /** Page id, unique in the extension. */\n id: string\n /** Title of the page. */\n title: Bindable<string>\n /** Icon in the settings sidebar. */\n icon?: { gui?: string, tui?: string }\n /** Place among the extension's pages: after the definition's pages, lower first. Default 100. */\n order?: number\n /** Settings the host draws as a form. */\n schema?: SettingsSchema\n /** Component the page draws. */\n component?: ComponentRef\n}\n\n/** A web page shown in a panel or a screen, sandboxed. It talks to the extension through RPC only. */\nexport interface WebviewItem {\n /** Webview id, unique in the extension. */\n id: string\n /** Title of the panel or screen. */\n title: Bindable<string>\n /** A URL, or a file in the extension folder. */\n src: { url: string } | { file: string }\n /** Shows the page in a panel or a full screen. */\n placement: 'panel' | 'screen'\n /** RPC contract ids the page may call through the injected bridge. */\n rpc?: readonly string[]\n}\n\n/** A native menu entry (desktop). It runs a command. */\nexport interface MenuItem {\n /** The menu that holds the entry. */\n menu: 'app' | 'session' | 'tray'\n /** Text of the entry. */\n label: Bindable<string>\n /** Id of the command it runs. */\n command: string\n /** Keyboard shortcut, as an Electron accelerator string. */\n accelerator?: string\n /** Greys the entry out when `false`. Default `true`. */\n enabled?: Bindable<boolean>\n}\n\n/** A section of the context breakdown or the context panel. */\nexport type ContextSectionItem\n = | { placement: 'breakdown', contributor: ContextBreakdownContributor }\n | { placement: 'panel', section: ExtensionContextPanelSection }\n\n/** What a session started from a space runs with. Each field left out takes the app's default. */\nexport interface SpaceNewSession {\n /** Agent profile id. */\n agentId?: string\n /** Provider registry key, with `modelId`. */\n providerKey?: string\n /** Model id. */\n modelId?: string\n /** Thinking effort. */\n effort?: ThinkingLevel\n}\n\n/**\n * A space: a named view of sessions, listed in the sidebar beside the\n * built-in spaces. Its published id is `<extension>/<id>`.\n *\n * The Bindable rule of every sidebar token (spaces, filters, sorts, groups,\n * decorations, rows): a field is Bindable when it is data that follows the\n * extension's state (names, labels, queries, sorts, groupings, new-session\n * defaults, row state, decoration content). Ids, `kind`, placement (`space`,\n * `spaces`, `group`, `order`, `items`), actions, `open` and components stay\n * fixed: change them with `handle.update`. A Bindable is read whole: bind\n * the list (`options`, `chips`) to change one of its elements.\n */\nexport interface SpaceItem {\n /** Space id, unique in the extension. `default` is the built-in space's and is refused. */\n id: string\n /** Name shown for the space. */\n name: Bindable<string>\n /** Icon drawn with the name. */\n icon?: ExtensionBadgeIcon\n /**\n * Which sessions the space lists, besides the others: a session is in it\n * when it is tagged with the space (started from it, or moved to it),\n * when it is the orchestration Main session, or when it matches this query.\n */\n query: Bindable<SessionQuery>\n /** How the space groups its sessions until the user picks a grouping. Absent: one flat list. */\n groupBy?: Bindable<SessionGroupBy>\n /** How the space sorts its sessions until the user picks a sort. Absent: the app's order. */\n sortBy?: Bindable<readonly SessionSort[]>\n /** What a session started from the space runs with. */\n newSession?: Bindable<SpaceNewSession>\n /** Whether {@link SidebarRowItem}s (any extension's, this one's included) may list in the space. Default `false`. */\n items?: boolean\n /** Lower first among extension spaces. Default 100. */\n order?: number\n}\n\n/** One choice of a `select` or `multi` sidebar filter. Bind the filter's `options` to change its labels or queries. */\nexport interface SidebarFilterOption {\n /** Option id, unique in the filter. */\n id: string\n /** Text of the option. */\n label: string\n /** The sessions the option keeps. */\n query: SessionQuery\n}\n\n/**\n * A filter the user turns on in the sidebar. `toggle` keeps the sessions\n * that match `query` while on; `select` keeps those of the one option\n * picked; `multi` keeps those that match any picked option. Bindable\n * fields follow the sidebar rule ({@link SpaceItem}).\n */\nexport interface SidebarFilterItem {\n /** Filter id, unique in the extension. */\n id: string\n /** Text of the filter. */\n label: Bindable<string>\n /** Icon drawn with the label. */\n icon?: ExtensionBadgeIcon\n /** How the user picks: on or off, one option, or several. */\n kind: 'toggle' | 'select' | 'multi'\n /** `select` and `multi`: the options, 1 to 32. */\n options?: Bindable<readonly SidebarFilterOption[]>\n /** `toggle`: the sessions kept while it is on. */\n query?: Bindable<SessionQuery>\n /** Spaces it is offered in: `'all'` (default), or space ids (`default`, own ids, `<extension>/<id>`). */\n spaces?: 'all' | readonly string[]\n}\n\n/** A sort order the user can pick for the sidebar. Bindable fields follow the sidebar rule ({@link SpaceItem}). */\nexport interface SidebarSortItem {\n /** Sort id, unique in the extension. */\n id: string\n /** Text of the choice. */\n label: Bindable<string>\n /** The sort keys, most significant first (1 to 8). */\n sortBy: Bindable<readonly SessionSort[]>\n}\n\n/** A grouping the user can pick for the sidebar. Bindable fields follow the sidebar rule ({@link SpaceItem}). */\nexport interface SidebarGroupItem {\n /** Grouping id, unique in the extension. */\n id: string\n /** Text of the choice. */\n label: Bindable<string>\n /** The field or facet grouped on, with group labels and order. */\n groupBy: Bindable<SessionGroupBy>\n}\n\n/**\n * A plain string drawn as given (blank or whitespace-only: no text), or\n * `{ template }` with field paths in braces: `'{facet.git.branch} · {modelId}'`.\n */\nexport type SidebarText = string | { template: string }\n\n/**\n * A chip a decoration adds to a session row: literal `text` (blank or\n * whitespace-only: no chip), a `template` (field paths in braces, `{{` and\n * `}}` for a brace; see `escapeTemplate`), or one chip per value of a\n * `facet`.\n */\nexport type SidebarChip\n = | { text: string, tone?: ExtensionBadgeTone, icon?: ExtensionBadgeIcon }\n | { template: string, tone?: ExtensionBadgeTone, icon?: ExtensionBadgeIcon }\n | { facet: FacetPath, tone?: ExtensionBadgeTone, icon?: ExtensionBadgeIcon }\n\n/**\n * Extra data on the sidebar rows of the sessions that match `where`: an\n * icon, a tone, a subtitle, chips, or a component. Only `{ template }`\n * values are read as templates; a plain string is drawn as given. Bindable\n * fields follow the sidebar rule ({@link SpaceItem}).\n */\nexport interface SidebarDecorationItem {\n /** Decoration id, unique in the extension. */\n id: string\n /** The sessions it applies to. Absent: every session. */\n where?: Bindable<SessionQuery>\n /** Icon drawn on the row. */\n icon?: Bindable<ExtensionBadgeIcon>\n /** Tint of the row's icon and chips. */\n tone?: Bindable<ExtensionBadgeTone>\n /** Text drawn under the title: as given, or `{ template }`. */\n subtitle?: Bindable<SidebarText>\n /** Chips drawn on the row, at most 8. */\n chips?: Bindable<readonly SidebarChip[]>\n /** Drawn on the row where the host has it, with `{ sessionId }` added to its props. */\n component?: ComponentRef\n}\n\n/** Run state an extension row shows, like a session's. */\nexport type SidebarRowStatus = 'idle' | 'running' | 'blocked' | 'completed' | 'error'\n\n/** A small label on an extension row. */\nexport interface SidebarBadge {\n /** Badge text. */\n text: string\n /** Tint of the badge. */\n tone?: ExtensionBadgeTone\n /** Icon drawn with the text. */\n icon?: ExtensionBadgeIcon\n}\n\n/** An action in an extension row's menu. */\nexport interface SidebarRowAction {\n /** Action id, unique in the row. */\n id: string\n /** Text of the action. */\n label: string\n /**\n * The command it runs: this extension's own command by that id when it has\n * one (`ack` runs `<extension>.ack`), else the id as written (another\n * extension's `<extension>.<id>`, or a built-in). Its argument is the row's\n * id as the extension gave it (`ticket-1`, not `<extension>/ticket-1`).\n * Without one the host draws it disabled.\n */\n command?: string\n}\n\n/**\n * What opening an extension row does. `command` resolves and gets its\n * argument as a {@link SidebarRowAction}'s does. `panel` and `screen` name\n * this extension's own panel or screen by that id when it has one, else the\n * id as written (`<extension>/<id>`, or a built-in panel such as `todos`).\n */\nexport type SidebarRowOpen = { command: string } | { panel: string } | { screen: string } | { session: string }\n\n/**\n * A row an extension adds to a space's list beside its sessions: a ticket, a\n * job, a pull request. It lists only in a space that allows items. `time`\n * sorts it as a session's `updatedAt`. Bindable fields follow the sidebar\n * rule ({@link SpaceItem}).\n */\nexport interface SidebarRowItem {\n /** Row id, unique in the extension. */\n id: string\n /** The space it lists in: `default`, an own space id, or `<extension>/<id>`. */\n space: string\n /** The group (a group key of the space's grouping) it lists in. Absent: the group of rows without a value. */\n group?: string\n /** Row title. Blank or whitespace-only: the row's `id` stands in. */\n title: Bindable<string>\n /** Text under the title. Blank or whitespace-only: none. */\n subtitle?: Bindable<string>\n /** Icon drawn on the row. */\n icon?: Bindable<ExtensionBadgeIcon>\n /** Tint of the row. */\n tone?: Bindable<ExtensionBadgeTone>\n /** Run state drawn as a session's. */\n status?: Bindable<SidebarRowStatus>\n /** Sorts as a session's `updatedAt`, epoch ms. */\n time?: Bindable<number>\n /** Labels drawn on the row, at most 8. */\n badges?: Bindable<readonly SidebarBadge[]>\n /** Actions in the row's menu, at most 8. */\n actions?: readonly SidebarRowAction[]\n /** What a click does. Absent: nothing. */\n open?: SidebarRowOpen\n /** Sessions listed under the row, as its children. */\n children?: Bindable<SessionQuery>\n}\n\n/**\n * Opens links the extension understands, before the app's own behavior.\n * Every link the apps open goes through it: transcript links, file and\n * reference chips, panel rows, badge menus, terminal links. Holding Alt\n * opens a link the default way.\n */\nexport interface LinkHandlerItem {\n /** Handler id, unique in the extension. */\n id: string\n /** A URL prefix, a pattern, or a test. Runs where the extension runs. */\n match: string | RegExp | ((url: string) => boolean)\n /** Opens the link. Return `false` to let the next handler (or the app) open it. */\n open: (url: string, ctx: { sessionId?: string, source: LinkSource }) => void | boolean | Promise<void | boolean>\n /** Higher first among extensions. Default 0. */\n priority?: number\n}\n\n/** Where a link was clicked. */\nexport type LinkSource = 'transcript' | 'chip' | 'panel' | 'badge' | 'terminal' | 'other'\n\n/** Every UI token. */\nexport const Panel = token<PanelItem, 'panel'>('panel')\n/** A small item in a named slot. */\nexport const Slot = token<SlotItem, 'slot'>('slot')\n/** A full-screen view or modal. */\nexport const Screen = token<ScreenItem, 'screen'>('screen')\n/** A renderer for blocks, code languages, tools or artifacts. */\nexport const Renderer = token<RendererItem, 'renderer'>('renderer')\n/** A Settings page. */\nexport const SettingsPage = token<SettingsPageItem, 'settings-page'>('settings-page')\n/** A webview panel or screen. */\nexport const Webview = token<WebviewItem, 'webview'>('webview')\n/** A native menu entry. */\nexport const Menu = token<MenuItem, 'menu'>('menu')\n/** A color theme. */\nexport const ThemeToken = token<Theme, 'theme'>('theme')\n/** Inline reference chips (ticket ids, URLs). */\nexport const Reference = token<ExtensionReferenceProvider, 'reference'>('reference')\n/** Context-menu actions on badges, links, files and artifacts. */\nexport const BadgeAction = token<ExtensionBadgeActions, 'badge-action'>('badge-action')\n/** Opens matching links. */\nexport const LinkHandler = token<LinkHandlerItem, 'link-handler'>('link-handler')\n/** A context breakdown or context panel section. */\nexport const ContextSection = token<ContextSectionItem, 'context-section'>('context-section')\n/** A space: a named, query-defined view of sessions in the sidebar. */\nexport const Space = token<SpaceItem, 'space'>('space')\n/** A filter the user turns on in the sidebar. */\nexport const SidebarFilter = token<SidebarFilterItem, 'sidebar-filter'>('sidebar-filter')\n/** A sort order the user can pick in the sidebar. */\nexport const SidebarSort = token<SidebarSortItem, 'sidebar-sort'>('sidebar-sort')\n/** A grouping the user can pick in the sidebar. */\nexport const SidebarGroup = token<SidebarGroupItem, 'sidebar-group'>('sidebar-group')\n/** Extra data on the sidebar rows of matching sessions. */\nexport const SidebarDecoration = token<SidebarDecorationItem, 'sidebar-decoration'>('sidebar-decoration')\n/** A row an extension adds to a space, beside its sessions. */\nexport const SidebarRow = token<SidebarRowItem, 'sidebar-row'>('sidebar-row')\n\n/** Thrown by a dialog when no client can show it. */\nexport class NoUiError extends Error {\n /** @param what - The dialog that could not be shown. */\n constructor(what: string) {\n super(`${what}: no client can show it`)\n this.name = 'NoUiError'\n }\n}\n\n/** Thrown by a dialog that got no answer within its `timeoutMs`. */\nexport class DialogTimeoutError extends Error {\n /**\n * @param what - The dialog that timed out.\n * @param timeoutMs - The time it waited.\n */\n constructor(what: string, readonly timeoutMs: number) {\n super(`${what}: no answer within ${timeoutMs} ms`)\n this.name = 'DialogTimeoutError'\n }\n}\n\n/** Options every dialog takes. */\nexport interface DialogOptions {\n /** Routes to the client viewing this session. Without it: the last active client. */\n sessionId?: string\n /** Rejects with a timeout after this many ms. */\n timeoutMs?: number\n /** Cancels the dialog when it aborts. */\n signal?: AbortSignal\n}\n\n/** One option of `select`. */\nexport interface SelectOption {\n /** Value returned in `ids` when picked. */\n id: string\n /** Text of the option. */\n label: string\n /** Text under the label. */\n description?: string\n /** Heading the option is listed under. */\n group?: string\n /** Icon drawn with the option. */\n icon?: ExtensionBadgeIcon\n}\n\n/**\n * `ctx.ui`. Dialogs (`confirm`, `prompt`, `select`, `form`, `askUser`,\n * `presentPlan`) reject with {@link NoUiError} at once when no client can\n * show them. `toast` and `notify` wait for a client instead: up to 20 of\n * them, each for 60 s, delivered in order to the first client that attaches.\n */\nexport interface UiDomain {\n /** Asks a yes or no question. Resolves `true` when the user confirms. */\n confirm: (opts: DialogOptions & { title: string, message?: string, confirmLabel?: string, danger?: boolean }) => Promise<boolean>\n /** Asks for a line of text. Resolves `undefined` when the user cancels. */\n prompt: (opts: DialogOptions & { title: string, message?: string, placeholder?: string, initial?: string, secret?: boolean }) => Promise<string | undefined>\n /** Asks for one or more options. Resolves the picked ids and the clicked action, or `undefined` when the user cancels. */\n select: (opts: DialogOptions & { title: string, options: readonly SelectOption[], multi?: boolean, placeholder?: string, actions?: readonly { id: string, label: string }[] }) => Promise<{ ids: readonly string[], action?: string } | undefined>\n /** Asks for the values of a settings schema. Resolves the values, or `undefined` when the user cancels. */\n form: <S extends SettingsSchema>(opts: DialogOptions & { title: string, schema: S, values?: Readonly<Record<string, unknown>> }) => Promise<Readonly<Record<string, unknown>> | undefined>\n /** Asks the user the questions of `payload`. */\n askUser: (payload: QuestionPayload, opts?: DialogOptions) => Promise<QuestionResponse>\n /** Shows a plan and waits for the user's answer. */\n presentPlan: (payload: PlanPayload, opts?: DialogOptions) => Promise<PlanResponse>\n /**\n * A toast. Resolves with the action the user clicked, or `undefined`\n * (dismissed, timed out, or dropped before any client attached).\n * `timeoutMs` counts from when it is shown.\n */\n toast: (opts: { text: string, tone?: 'info' | 'success' | 'warn' | 'error', actions?: readonly { id: string, label: string }[], timeoutMs?: number, sessionId?: string }) => Promise<string | undefined>\n /** An OS notification on the client that shows it, skipped while the app has focus. Waits for a client like `toast`. */\n notify: (opts: { title: string, body?: string, sound?: boolean, sessionId?: string }) => void\n /** Opens, closes and toggles panels in a client. Each resolves whether the client did it. */\n panel: {\n open: (id: string, opts?: { sessionId?: string, focus?: PanelFocus }) => Promise<boolean>\n close: (id: string, opts?: { sessionId?: string }) => Promise<boolean>\n toggle: (id: string, opts?: { sessionId?: string }) => Promise<boolean>\n /** Panels open in the client viewing `sessionId`. */\n state: (opts?: { sessionId?: string }) => Promise<readonly string[]>\n }\n /** Shows a screen, a session, or a new session. */\n navigate: (to: { screen: string } | { session: string } | { newSession: true }, opts?: DialogOptions) => Promise<boolean>\n}\n\n/** `ctx.composer`. */\nexport interface ComposerDomain {\n /** Inserts text into the composer. Resolves whether a client did it. */\n insert: (text: string, opts?: { sessionId?: string }) => Promise<boolean>\n /** Replaces the composer text. Resolves whether a client did it. */\n setText: (text: string, opts?: { sessionId?: string }) => Promise<boolean>\n /** Attaches files, by path or as bytes with a name and MIME type. Resolves whether a client did it. */\n attach: (files: readonly { path: string }[] | readonly { name: string, mimeType: string, data: Uint8Array }[], opts?: { sessionId?: string }) => Promise<boolean>\n /** Registers a source of composer completions. */\n completions: { register: (provider: CompletionProvider) => Disposable }\n /** Registers a source of inline ghost-text suggestions. */\n autocomplete: { register: (provider: InlineAutocompleteProvider) => Disposable }\n}\n\n/** `ctx.desktop`: present only in the desktop app's main process. */\nexport interface DesktopDomain {\n /** The `electron` module. Type it yourself: `ctx.desktop.electron<typeof import('electron')>()`. */\n electron: <T = unknown>() => T\n /** The open windows and their events. */\n windows: {\n list: () => readonly { id: number, focused: boolean }[]\n on: (event: 'open' | 'close' | 'focus', listener: (window: { id: number }) => void) => Disposable\n }\n}\n\n/** The `add` signature: a token and its item. */\nexport type AddFn = <T>(token: UiToken<T>, item: T) => Handle<T>\n","/**\n * Settings schemas in UI items and form dialogs. The wire format and the\n * value checks are the settings domain's (`src/extensions/settings`): a\n * `ctx.ui.form` and a settings page draw with the same renderer as the\n * extension's own settings.\n */\n\nimport type { SettingsSchema } from '../api/settings'\nimport type { StoredSettingValue, ValidateRunner, WireSettings } from '../settings'\nimport type { UiRegistry } from './registry'\nimport { checkSettingValue, isValueSetting, normalizeSettingValue, settingsForDefinition, toWireSettings, withSettingsPages } from '../settings'\n\n/**\n * The schema with malformed sections and items removed (the settings\n * domain's cleaning). Never calls author code.\n *\n * @param extensionId - The extension the schema belongs to.\n * @param schema - The schema as the extension wrote it.\n */\nexport function cleanSettingsSchema(extensionId: string, schema: SettingsSchema): SettingsSchema {\n return settingsForDefinition({ id: extensionId, settings: schema }).schema\n}\n\n/** What {@link checkSettingsValues} found. */\nexport interface SettingsCheck {\n /** The values of the schema's keys that passed, normalized. Unknown keys are dropped. */\n values: Record<string, StoredSettingValue>\n /** An error message per key that failed. */\n errors: Record<string, string>\n}\n\n/**\n * Checks values a client sent back (or an extension passed as initial\n * values) against `schema`, with the settings domain's rules. Missing keys\n * are left out; action settings carry no value.\n *\n * @param schema - The schema, with its functions.\n * @param raw - Untrusted values.\n * @param runValidate - Runs a setting's `validate` (the caller guards it).\n */\nexport function checkSettingsValues(schema: SettingsSchema, raw: unknown, runValidate?: ValidateRunner): SettingsCheck {\n const values: Record<string, StoredSettingValue> = {}\n const errors: Record<string, string> = {}\n const input = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw as Record<string, unknown> : {}\n for (const [key, setting] of Object.entries(schema.items)) {\n if (!Object.hasOwn(input, key) || !isValueSetting(setting))\n continue\n const value = normalizeSettingValue(setting, input[key])\n const error = checkSettingValue(setting, value, runValidate)\n if (error === undefined)\n values[key] = value as StoredSettingValue\n else\n errors[key] = error\n }\n return { values, errors }\n}\n\n/**\n * The wire form of a schema and its values, as the Settings renderer takes\n * it. Values that do not fit the schema are left out (the renderer shows\n * the default).\n *\n * @param extensionId - The extension (category ids and the `extension` field).\n * @param schema - The schema, cleaned or not.\n * @param values - Values to show.\n */\nexport function settingsWire(extensionId: string, schema: SettingsSchema, values?: unknown): WireSettings {\n const clean = cleanSettingsSchema(extensionId, schema)\n return toWireSettings(extensionId, clean, values === undefined ? {} : checkSettingsValues(clean, values, () => undefined).values)\n}\n\n/**\n * An extension's wire with its `SettingsPage` items appended to its pages\n * (after the schema's pages, by `order`). Hosts call it where they build\n * an extension's settings wire and hold its UI registry.\n *\n * @param wire - The extension's wire (the domain's `wire()`, or `toWireSettings` from the definition).\n * @param extensionId - The extension.\n * @param ui - The registry holding its settings-page items.\n */\nexport function wireWithSettingsPages(wire: WireSettings, extensionId: string, ui: Pick<UiRegistry, 'list'>): WireSettings {\n return withSettingsPages(wire, extensionId, ui.list('settings-page').filter(e => e.extension === extensionId).map(e => e.item))\n}\n","/**\n * The JSON wire form of every UI contribution. Hosts in other processes\n * (the desktop renderer, protocol clients) only ever see these. Functions\n * stay in the backend: a wire item says which callbacks exist, and hosts\n * invoke them through the registry by the item's id (panel `load` /\n * `onAction`, reference `resolve`, badge action `run`, context section\n * `load`, settings actions).\n *\n * Serializers take an item whose bindable fields are already read, check\n * it, and throw a `TypeError` naming the problem when it is unusable.\n */\n\nimport type { SessionGroupBy, SessionQuery, SessionQueryIssue, SessionSort } from '../../chat/session-query'\nimport type { Theme } from '../../chat/theme'\nimport type { ComponentRef } from '../api/core'\nimport type {\n ContextSectionItem,\n LinkHandlerItem,\n MenuItem,\n PanelItem,\n RendererItem,\n RendererTarget,\n ScreenItem,\n SettingsPageItem,\n SidebarBadge,\n SidebarChip,\n SidebarDecorationItem,\n SidebarFilterItem,\n SidebarGroupItem,\n SidebarRowAction,\n SidebarRowItem,\n SidebarRowOpen,\n SidebarRowStatus,\n SidebarSortItem,\n SidebarText,\n SlotItem,\n SlotName,\n SpaceItem,\n SpaceNewSession,\n UiToken,\n WebviewItem,\n} from '../api/ui'\nimport type { BadgeActionsMatch, BadgeTargetKind, ExtensionBadgeActions } from '../badge-actions'\nimport type { PanelHomeLayout, PanelIcon, PanelSurface } from '../panels'\nimport type { ReferenceProviderWire } from '../references'\nimport type { WireSettings } from '../settings'\nimport type { ExtensionBadgeIcon, ExtensionBadgeTone, ExtensionReferenceProvider } from '../types'\nimport type { Resolved } from './bindable'\nimport { parseFieldPath, SessionQueryError, validateGroupBy, validateQuery, validateSort, validateTemplate } from '../../chat/session-query'\nimport { isThinkingLevel } from '../../thinking-levels'\nimport { isExtensionPanelScope, isPanelSurface, normalizePanelHomeLayout } from '../panels'\nimport { referenceProviderWires } from '../references'\nimport { EXTENSION_ID_PATTERN } from '../runtime/validate-definition'\nimport { isSettingsIcon } from '../settings/validate'\nimport { isBadgeColor } from '../types'\nimport { settingsWire } from './settings-form'\n\n/** A component reference on the wire: the export name and JSON props. */\nexport interface ComponentWire {\n /** Export name in the extension's `ui` / `tui` entry. */\n component: string\n /** JSON props handed to the component. */\n props?: Readonly<Record<string, unknown>>\n}\n\n/** A panel on the wire. Its `load` / `onAction` / `subscribe` stay backend-side. */\nexport interface PanelWire {\n /** `<extension>/<id>`. */\n id: string\n /** Tab title. */\n label: string\n /** Per-surface icon. */\n icon?: PanelIcon\n /** Where it shows: beside a session, in a project, or both. Default `session`. */\n scope?: 'session' | 'project' | 'both'\n /** Where it shows. Default `['side']`. */\n surfaces: readonly PanelSurface[]\n /** Layout of the block on the project home. */\n home?: PanelHomeLayout\n /** It has `subscribe`: the registry pushes `panel-changed` when it would load something new. */\n live: boolean\n /** It has `onAction`. */\n actions: boolean\n /** Drawn instead of the data where the host has it. */\n component?: ComponentWire\n}\n\n/** A slot item on the wire, its bindings read. */\nexport interface SlotWire {\n /** The slot it fills. */\n at: SlotName\n /** Limits the item to one session. */\n sessionId?: string\n /** `transcript.turn-end` only: draw after this turn. Absent: once, at the end of the transcript. */\n turnId?: string\n /** Item text. */\n text?: string\n /** Lines of a banner (`composer.above`). */\n lines?: readonly string[]\n /** A number past 999 shows `999+`. */\n count?: string\n /** Per-surface icon. */\n icon?: ExtensionBadgeIcon\n /** Tint of the item. */\n tone?: ExtensionBadgeTone\n /** Exact color, over `tone`. */\n color?: string\n /** A running arc in place of the icon. */\n loader?: true\n /** Raised and breathing: something waits on the user. */\n highlight?: true\n /** Hover text. */\n title?: string\n /** As the extension named it; hosts resolve it with the entry's extension. */\n panel?: string\n /** A click runs this command. */\n command?: string\n /** Lower first. Default 100. */\n order: number\n /** Drawn instead of the data where the host has it. */\n component?: ComponentWire\n}\n\n/** A screen on the wire. */\nexport interface ScreenWire {\n /** `<extension>/<id>`. */\n id: string\n /** Heading of the screen or modal. */\n title: string\n /** `modal` draws a dialog, `screen` a full-screen view. */\n presentation: 'screen' | 'modal'\n /** Required: hosts without the component draw `fallback`. */\n component: ComponentWire\n /** Markdown drawn where the component is missing. */\n fallback?: string\n}\n\n/** A renderer on the wire. */\nexport interface RendererWire {\n /** What it draws: a block id, a code-block language, a tool result or an artifact kind. */\n for: RendererTarget\n /** The component that draws it. */\n component: ComponentWire\n /** The component returns null to let the next renderer (or the default) draw. */\n fallthrough?: true\n}\n\n/** A settings page on the wire. */\nexport interface SettingsPageWire {\n /** `<extension>/<id>`. */\n id: string\n /** Page title. */\n title: string\n /** Icon in the settings sidebar. */\n icon?: { gui?: string, tui?: string }\n /** Place among the extension's pages, after the definition's pages; lower first. Absent: 100. */\n order?: number\n /** The page's settings in the settings renderer's wire format. */\n schema?: WireSettings\n /** Drawn instead of the data where the host has it. */\n component?: ComponentWire\n}\n\n/** A webview on the wire. A `file` source is relative to the extension's folder; the host resolves it. */\nexport interface WebviewWire {\n /** `<extension>/<id>`. */\n id: string\n /** Heading of the panel or screen. */\n title: string\n /** A URL, or a file in the extension folder. */\n src: { url: string } | { file: string }\n /** Shown in a panel or a screen. */\n placement: 'panel' | 'screen'\n /** RPC contract ids the page may call through the injected bridge. */\n rpc?: readonly string[]\n}\n\n/** A native menu entry on the wire. */\nexport interface MenuWire {\n /** Which native menu holds it. */\n menu: 'app' | 'session' | 'tray'\n /** Entry text. */\n label: string\n /** The command it runs. */\n command: string\n /** Keyboard shortcut. */\n accelerator?: string\n /** Whether it can be chosen. Default `true`. */\n enabled: boolean\n}\n\n/** Badge actions on the wire: which badges they apply to. The menu itself is asked for per target. */\nexport interface BadgeActionWire {\n /** The registration's id. */\n id: string\n /** Badges the actions apply to. Absent: every badge. */\n match?: BadgeActionsMatch\n}\n\n/** A context section on the wire. */\nexport type ContextSectionWire\n = | { placement: 'breakdown' }\n | { placement: 'panel', id: string, title: string, accentColor?: string, actions?: readonly { id: string, label: string }[] }\n\n/** A space on the wire. */\nexport interface SpaceWire {\n /** `<extension>/<id>`. */\n id: string\n /** Name shown for the space. */\n name: string\n /** Icon drawn with the name. */\n icon?: ExtensionBadgeIcon\n /** The sessions the space lists, validated. */\n query: SessionQuery\n /** How it groups its sessions. */\n groupBy?: SessionGroupBy\n /** How it sorts its sessions. */\n sortBy?: readonly SessionSort[]\n /** What a session started from it runs with. */\n newSession?: SpaceNewSession\n /** Sidebar items may list in it. */\n items: boolean\n /** Lower first. Default 100. */\n order: number\n}\n\n/** A sidebar filter on the wire. */\nexport interface SidebarFilterWire {\n /** `<extension>/<id>`. */\n id: string\n /** Text of the filter. */\n label: string\n /** Icon drawn with the label. */\n icon?: ExtensionBadgeIcon\n /** How the user picks. */\n kind: 'toggle' | 'select' | 'multi'\n /** `select` / `multi`: the options. */\n options?: readonly { id: string, label: string, query: SessionQuery }[]\n /** `toggle`: the sessions kept while on. */\n query?: SessionQuery\n /** `'all'`, or full space ids (`default`, `<extension>/<id>`). */\n spaces: 'all' | readonly string[]\n}\n\n/** A sidebar sort on the wire. */\nexport interface SidebarSortWire {\n /** `<extension>/<id>`. */\n id: string\n /** Text of the choice. */\n label: string\n /** The sort keys, validated. */\n sortBy: readonly SessionSort[]\n}\n\n/** A sidebar grouping on the wire. */\nexport interface SidebarGroupWire {\n /** `<extension>/<id>`. */\n id: string\n /** Text of the choice. */\n label: string\n /** The grouping, validated. */\n groupBy: SessionGroupBy\n}\n\n/** A sidebar decoration on the wire. */\nexport interface SidebarDecorationWire {\n /** `<extension>/<id>`. */\n id: string\n /** The sessions it applies to. Absent: every session. */\n where?: SessionQuery\n /** Icon drawn on the row. */\n icon?: ExtensionBadgeIcon\n /** Tint of the row's icon and chips. */\n tone?: ExtensionBadgeTone\n /** Text under the title: a string drawn as given, or `{ template }` (validated; render it with `renderTemplate`). */\n subtitle?: SidebarText\n /** Chips, at most 8: `text` drawn as given, `template` validated (render it with `renderTemplate`), or `facet`. */\n chips?: readonly SidebarChip[]\n /** Drawn on the row where the host has it. */\n component?: ComponentWire\n}\n\n/** A sidebar row's action on the wire. */\nexport interface SidebarRowActionWire extends SidebarRowAction {\n /** The full command id to run as is (resolved: `<extension>.<id>` when the extension has that command, else as written), with the row's `args`. */\n command?: string\n}\n\n/** A sidebar row on the wire, its bindings read and its references resolved: hosts use them as is. */\nexport interface SidebarRowWire {\n /** `<extension>/<id>`. */\n id: string\n /** The row's id as the extension gave it: the argument its `command`s run with (actions and `open.command`). */\n args: string\n /** Full space id: `default` or `<extension>/<id>`. */\n space: string\n /** Group key it lists under. */\n group?: string\n /** Row title. */\n title: string\n /** Text under the title. */\n subtitle?: string\n /** Icon drawn on the row. */\n icon?: ExtensionBadgeIcon\n /** Tint of the row. */\n tone?: ExtensionBadgeTone\n /** Run state. */\n status?: SidebarRowStatus\n /** Sorts as `updatedAt`, epoch ms. */\n time?: number\n /** Labels, at most 8. */\n badges?: readonly SidebarBadge[]\n /** Menu actions, at most 8, their commands resolved. */\n actions?: readonly SidebarRowActionWire[]\n /** What a click does: `command` resolved as an action's, `panel` / `screen` as full ids (`<extension>/<id>` when the extension has one by that id, else as written). */\n open?: SidebarRowOpen\n /** Sessions listed under it. */\n children?: SessionQuery\n}\n\n/**\n * A link handler on the wire: which handlers exist and their order. `match`\n * and `open` stay in the backend; hosts open a link through the resolver\n * (`UiRegistry.openLink`, `extensions.links.open`).\n */\nexport interface LinkHandlerWire {\n /** `<extension>/<id>`. */\n id: string\n /** Higher first among extensions. */\n priority: number\n /** The registering extension. */\n extensionId: string\n}\n\n/** The wire form of each token, by token name. */\nexport interface UiWireMap {\n 'panel': PanelWire\n 'slot': SlotWire\n 'screen': ScreenWire\n 'renderer': RendererWire\n 'settings-page': SettingsPageWire\n 'webview': WebviewWire\n 'menu': MenuWire\n 'theme': Theme\n 'reference': ReferenceProviderWire\n 'badge-action': BadgeActionWire\n 'link-handler': LinkHandlerWire\n 'context-section': ContextSectionWire\n 'space': SpaceWire\n 'sidebar-filter': SidebarFilterWire\n 'sidebar-sort': SidebarSortWire\n 'sidebar-group': SidebarGroupWire\n 'sidebar-decoration': SidebarDecorationWire\n 'sidebar-row': SidebarRowWire\n}\n\n/** Every token name the registry knows. */\nexport type UiTokenName = keyof UiWireMap\n\n/** The item type each token takes, by token name. */\nexport interface UiItemMap {\n 'panel': PanelItem\n 'slot': SlotItem\n 'screen': ScreenItem\n 'renderer': RendererItem\n 'settings-page': SettingsPageItem\n 'webview': WebviewItem\n 'menu': MenuItem\n 'theme': Theme\n 'reference': ExtensionReferenceProvider\n 'badge-action': ExtensionBadgeActions\n 'link-handler': LinkHandlerItem\n 'context-section': ContextSectionItem\n 'space': SpaceItem\n 'sidebar-filter': SidebarFilterItem\n 'sidebar-sort': SidebarSortItem\n 'sidebar-group': SidebarGroupItem\n 'sidebar-decoration': SidebarDecorationItem\n 'sidebar-row': SidebarRowItem\n}\n\n/** The token names, in a fixed order. */\nexport const UI_TOKEN_NAMES: readonly UiTokenName[] = ['panel', 'slot', 'screen', 'renderer', 'settings-page', 'webview', 'menu', 'theme', 'reference', 'badge-action', 'link-handler', 'context-section', 'space', 'sidebar-filter', 'sidebar-sort', 'sidebar-group', 'sidebar-decoration', 'sidebar-row']\n\n/**\n * Whether `token` is one the registry knows.\n *\n * @param token - A token passed to `ctx.add`.\n */\nexport function isKnownToken(token: UiToken<unknown>): token is UiToken<unknown, UiTokenName> {\n return !!token && token.kind === 'ui' && (UI_TOKEN_NAMES as readonly string[]).includes(token.name)\n}\n\n/** Every slot name. */\nexport const SLOT_NAMES: readonly SlotName[] = ['app.statusbar', 'app.titlebar', 'session.header', 'composer.above', 'composer.below', 'composer.badges', 'sidebar.top', 'sidebar.bottom', 'sidebar.footer', 'transcript.turn-end', 'home.block', 'settings.section']\n\nconst LOCAL_ID = /^[\\w.:-]{1,64}$/\nconst TONES: readonly ExtensionBadgeTone[] = ['muted', 'subtle', 'accent', 'success', 'warn', 'danger']\n\nfunction cut(value: unknown, max: number): string | undefined {\n if (typeof value !== 'string')\n return undefined\n const t = value.trim()\n if (!t)\n return undefined\n return t.length > max ? `${t.slice(0, max - 1)}…` : t\n}\n\nfunction need(value: unknown, what: string, max: number): string {\n const v = cut(value, max)\n if (!v)\n throw new TypeError(`${what} must be a non-empty string`)\n return v\n}\n\nfunction localId(value: unknown, what: string): string {\n if (typeof value !== 'string' || !LOCAL_ID.test(value))\n throw new TypeError(`${what} must match [A-Za-z0-9_.:-]{1,64}`)\n return value\n}\n\n/**\n * A JSON-safe copy of `value`, or `undefined` when it does not survive\n * JSON (cycles, BigInt). Functions and `undefined` fields are dropped.\n *\n * @param value - Any value.\n */\nexport function toJson<T>(value: T): T | undefined {\n if (value === undefined)\n return undefined\n try {\n return JSON.parse(JSON.stringify(value)) as T\n }\n catch {\n return undefined\n }\n}\n\nfunction icon(raw: unknown): ExtensionBadgeIcon | undefined {\n if (!raw || typeof raw !== 'object')\n return undefined\n const o = raw as Record<string, unknown>\n const gui = cut(o.gui, 128)\n const tui = cut(o.tui, 8)\n return gui || tui ? { ...(gui ? { gui } : {}), ...(tui ? { tui } : {}) } : undefined\n}\n\n/**\n * A component reference on the wire: the name checked, the props made\n * JSON-safe (props that do not survive JSON are dropped).\n *\n * @param raw - A {@link ComponentRef}, or anything.\n * @param required - Throw when it is missing.\n */\nexport function serializeComponent(raw: unknown, required: true): ComponentWire\nexport function serializeComponent(raw: unknown, required?: false): ComponentWire | undefined\nexport function serializeComponent(raw: unknown, required = false): ComponentWire | undefined {\n if (raw === undefined && !required)\n return undefined\n const ref = raw as ComponentRef | undefined\n if (!ref || typeof ref !== 'object' || typeof ref.component !== 'string' || !/^[A-Z_$][\\w$]{0,127}$/i.test(ref.component))\n throw new TypeError('component must be { component: <export name>, props? }')\n const props = ref.props && typeof ref.props === 'object' ? toJson(ref.props) : undefined\n return { component: ref.component, ...(props ? { props } : {}) }\n}\n\n/**\n * What a host draws for an item that names a component: the component when\n * the host has it, else the data (or the item's markdown fallback).\n *\n * @param item - A wire item.\n * @param item.component - The component the item names.\n * @param has - Whether the host has a component by that export name.\n */\nexport function pickComponent(item: { component?: ComponentWire }, has: (name: string) => boolean): ComponentWire | undefined {\n return item.component && has(item.component.component) ? item.component : undefined\n}\n\nfunction serializePanel(item: Resolved<PanelItem>, extension: string): PanelWire {\n const id = localId(item.id, 'Panel id')\n const label = need(item.label, 'Panel label', 80)\n if (typeof item.load !== 'function')\n throw new TypeError('Panel load must be a function')\n const surfaces = Array.isArray(item.surfaces) ? item.surfaces.filter(isPanelSurface) : []\n const home = normalizePanelHomeLayout(item.home)\n const panelIcon = item.icon && typeof item.icon === 'object' ? toJson(item.icon) : undefined\n const component = serializeComponent(item.component)\n return {\n id: `${extension}/${id}`,\n label,\n ...(panelIcon ? { icon: panelIcon } : {}),\n ...(isExtensionPanelScope(item.scope) ? { scope: item.scope } : {}),\n surfaces: surfaces.length > 0 ? [...new Set(surfaces)] : ['side'],\n ...(home ? { home } : {}),\n live: typeof item.subscribe === 'function',\n actions: typeof item.onAction === 'function',\n ...(component ? { component } : {}),\n }\n}\n\n/**\n * Whether a slot holds badges: `composer.badges` and `app.titlebar` take\n * short text (40 characters) and at most {@link MAX_SLOT_BADGES} items per\n * extension (per session for `composer.badges`).\n *\n * @param at - A slot name.\n */\nexport function isBadgeSlot(at: SlotName): boolean {\n return at === 'composer.badges' || at === 'app.titlebar'\n}\n\n/** How many items one extension may show in a badge slot ({@link isBadgeSlot}); per session for `composer.badges`. */\nexport const MAX_SLOT_BADGES = 8\n\nfunction serializeSlot(item: Resolved<SlotItem>): SlotWire {\n if (!SLOT_NAMES.includes(item.at))\n throw new TypeError(`Slot at must be one of ${SLOT_NAMES.join(', ')}`)\n const sessionId = item.sessionId === undefined ? undefined : need(item.sessionId, 'Slot sessionId', 512)\n if (item.at === 'composer.badges' && !sessionId)\n throw new TypeError('A composer.badges item needs a sessionId')\n const turnId = item.turnId === undefined ? undefined : need(item.turnId, 'Slot turnId', 512)\n if (turnId && item.at !== 'transcript.turn-end')\n throw new TypeError('Only a transcript.turn-end item takes a turnId')\n const text = cut(item.text, isBadgeSlot(item.at) ? 40 : 500)\n const lines = Array.isArray(item.lines) ? item.lines.flatMap(l => (typeof l === 'string' && l.length > 0 ? [l.slice(0, 500)] : [])).slice(0, 20) : []\n const count = typeof item.count === 'number' && Number.isFinite(item.count)\n ? (item.count > 999 ? '999+' : String(item.count))\n : cut(item.count, 12)\n const slotIcon = icon(item.icon)\n const tone = TONES.find(t => t === item.tone)\n const color = isBadgeColor(item.color) ? item.color : undefined\n const title = cut(item.title, 200)\n const panel = cut(item.panel, 200)\n const command = cut(item.command, 200)\n const component = serializeComponent(item.component)\n return {\n at: item.at,\n ...(sessionId ? { sessionId } : {}),\n ...(turnId ? { turnId } : {}),\n ...(text ? { text } : {}),\n ...(lines.length > 0 ? { lines } : {}),\n ...(count !== undefined ? { count } : {}),\n ...(slotIcon ? { icon: slotIcon } : {}),\n ...(tone ? { tone } : {}),\n ...(color ? { color } : {}),\n ...(item.loader === true ? { loader: true as const } : {}),\n ...(item.highlight === true ? { highlight: true as const } : {}),\n ...(title ? { title } : {}),\n ...(panel ? { panel } : {}),\n ...(command ? { command } : {}),\n order: typeof item.order === 'number' && Number.isFinite(item.order) ? item.order : 100,\n ...(component ? { component } : {}),\n }\n}\n\nfunction serializeScreen(item: Resolved<ScreenItem>, extension: string): ScreenWire {\n const fallback = typeof item.fallback === 'string' && item.fallback ? item.fallback.slice(0, 20_000) : undefined\n return {\n id: `${extension}/${localId(item.id, 'Screen id')}`,\n title: need(item.title, 'Screen title', 200),\n presentation: item.presentation === 'modal' ? 'modal' : 'screen',\n component: serializeComponent(item.component, true),\n ...(fallback ? { fallback } : {}),\n }\n}\n\nfunction serializeTarget(target: RendererTarget): RendererTarget {\n if (target && typeof target === 'object') {\n if ('block' in target)\n return { block: need(target.block, 'Renderer block', 128) }\n if ('language' in target)\n return { language: need(target.language, 'Renderer language', 64).toLowerCase() }\n if ('artifact' in target)\n return { artifact: need(target.artifact, 'Renderer artifact', 128) }\n if ('tool' in target) {\n const tools = (typeof target.tool === 'string' ? [target.tool] : Array.isArray(target.tool) ? target.tool : []).filter((t): t is string => typeof t === 'string' && t.length > 0)\n if (tools.length === 0)\n throw new TypeError('Renderer tool must name at least one tool')\n return { tool: typeof target.tool === 'string' ? tools[0]! : tools }\n }\n }\n throw new TypeError('Renderer for must be { block } | { language } | { tool } | { artifact }')\n}\n\nfunction serializeRenderer(item: Resolved<RendererItem>): RendererWire {\n return {\n for: serializeTarget(item.for),\n component: serializeComponent(item.component, true),\n ...(item.fallthrough === true ? { fallthrough: true as const } : {}),\n }\n}\n\nfunction serializeSettingsPage(item: Resolved<SettingsPageItem>, extension: string): SettingsPageWire {\n if (!item.schema && !item.component)\n throw new TypeError('A settings page needs a schema or a component')\n const component = serializeComponent(item.component)\n return {\n id: `${extension}/${localId(item.id, 'Settings page id')}`,\n title: need(item.title, 'Settings page title', 200),\n ...(isSettingsIcon(item.icon) ? { icon: { ...(item.icon.gui !== undefined ? { gui: item.icon.gui } : {}), ...(item.icon.tui !== undefined ? { tui: item.icon.tui } : {}) } } : {}),\n ...(typeof item.order === 'number' && Number.isFinite(item.order) ? { order: item.order } : {}),\n ...(item.schema ? { schema: settingsWire(extension, item.schema) } : {}),\n ...(component ? { component } : {}),\n }\n}\n\nfunction serializeWebview(item: Resolved<WebviewItem>, extension: string): WebviewWire {\n const src = item.src as { url?: unknown, file?: unknown } | undefined\n let wireSrc: WebviewWire['src']\n if (src && typeof src.url === 'string' && /^(?:https?|file):\\/\\//i.test(src.url))\n wireSrc = { url: src.url }\n else if (src && typeof src.file === 'string' && src.file && !src.file.startsWith('/') && !src.file.split(/[\\\\/]/).includes('..'))\n wireSrc = { file: src.file }\n else\n throw new TypeError('Webview src must be { url: http(s)/file URL } or { file: <path inside the extension folder> }')\n if (item.placement !== 'panel' && item.placement !== 'screen')\n throw new TypeError('Webview placement must be panel or screen')\n const rpc = Array.isArray(item.rpc) ? item.rpc.filter((r): r is string => typeof r === 'string' && r.length > 0) : undefined\n return {\n id: `${extension}/${localId(item.id, 'Webview id')}`,\n title: need(item.title, 'Webview title', 200),\n src: wireSrc,\n placement: item.placement,\n ...(rpc && rpc.length > 0 ? { rpc } : {}),\n }\n}\n\nfunction serializeMenu(item: Resolved<MenuItem>): MenuWire {\n if (item.menu !== 'app' && item.menu !== 'session' && item.menu !== 'tray')\n throw new TypeError('Menu menu must be app, session or tray')\n const accelerator = cut(item.accelerator, 64)\n return {\n menu: item.menu,\n label: need(item.label, 'Menu label', 120),\n command: need(item.command, 'Menu command', 200),\n ...(accelerator ? { accelerator } : {}),\n enabled: item.enabled !== false,\n }\n}\n\nfunction serializeTheme(item: Theme): Theme {\n localId(item?.id, 'Theme id')\n need(item.label, 'Theme label', 120)\n if (!item.colors || !item.select || !item.surfaces || !item.syntax)\n throw new TypeError('Theme needs colors, select, surfaces and syntax')\n const theme = toJson(item)\n if (!theme)\n throw new TypeError('Theme must be JSON')\n return theme\n}\n\nfunction serializeReference(item: ExtensionReferenceProvider): ReferenceProviderWire {\n need(item?.id, 'Reference id', 128)\n if (!Array.isArray(item.patterns) || item.patterns.length === 0)\n throw new TypeError('Reference patterns must be a non-empty list')\n if (typeof item.resolve !== 'function')\n throw new TypeError('Reference resolve must be a function')\n // The shared wire builder (`referenceProviderWires`): same patterns, same placeholder rules.\n return referenceProviderWires({ references: [{ extensionName: '', source: 'project', value: item }] }, { builtins: false })[0]!\n}\n\nconst TARGET_KINDS: readonly BadgeTargetKind[] = ['link', 'file', 'commit', 'pull_request', 'branch', 'reference', 'artifact']\n\nfunction serializeBadgeAction(item: ExtensionBadgeActions): BadgeActionWire {\n const id = need(item?.id, 'Badge action id', 128)\n if (typeof item.actions !== 'function' || typeof item.run !== 'function')\n throw new TypeError('Badge actions need actions and run functions')\n const strings = (v: unknown): string[] | undefined => (Array.isArray(v) ? v.filter((s): s is string => typeof s === 'string') : undefined)\n const m = item.match\n const kinds = m?.kinds?.filter(k => TARGET_KINDS.includes(k))\n const artifactKinds = strings(m?.artifactKinds)\n const references = strings(m?.references)\n const match: BadgeActionsMatch | undefined = m\n ? { ...(kinds ? { kinds } : {}), ...(artifactKinds ? { artifactKinds } : {}), ...(references ? { references } : {}) }\n : undefined\n return { id, ...(match ? { match } : {}) }\n}\n\nfunction serializeLinkHandler(item: LinkHandlerItem, extension: string): LinkHandlerWire {\n const id = localId(item?.id, 'Link handler id')\n const m = item.match\n if (typeof m !== 'function' && !(m instanceof RegExp) && !(typeof m === 'string' && m.length > 0))\n throw new TypeError('Link handler match must be a non-empty prefix, a RegExp or a function')\n if (typeof item.open !== 'function')\n throw new TypeError('Link handler open must be a function')\n if (item.priority !== undefined && (typeof item.priority !== 'number' || !Number.isFinite(item.priority)))\n throw new TypeError('Link handler priority must be a finite number')\n return { id: `${extension}/${id}`, priority: item.priority ?? 0, extensionId: extension }\n}\n\nfunction serializeContextSection(item: ContextSectionItem): ContextSectionWire {\n if (item?.placement === 'breakdown') {\n if (typeof item.contributor !== 'function')\n throw new TypeError('A breakdown context section needs a contributor function')\n return { placement: 'breakdown' }\n }\n if (item?.placement === 'panel') {\n const s = item.section\n const id = localId(s?.id, 'Context section id')\n const title = need(s.title, 'Context section title', 120)\n if (!s.rows && typeof s.load !== 'function')\n throw new TypeError('A panel context section needs rows or load')\n const accentColor = cut(s.accentColor, 32)\n const actions = Array.isArray(s.actions)\n ? s.actions.flatMap((a) => {\n const actionId = cut(a?.id, 64)\n const label = cut(a?.label, 80)\n return actionId && label ? [{ id: actionId, label }] : []\n })\n : undefined\n return { placement: 'panel', id, title, ...(accentColor ? { accentColor } : {}), ...(actions && actions.length > 0 ? { actions } : {}) }\n }\n throw new TypeError('Context section placement must be breakdown or panel')\n}\n\n/**\n * A sidebar token's query, sort, grouping or template is invalid. Its\n * `issues` paths start at the item's field (`query`, `options[2].query`,\n * `children`, `chips[0].template`).\n */\nexport class UiQueryError extends SessionQueryError {\n /**\n * @param token - The token of the item.\n * @param issues - The problems found.\n */\n constructor(readonly token: UiTokenName, issues: readonly SessionQueryIssue[]) {\n super(issues)\n this.name = 'UiQueryError'\n this.message = `${token}: ${this.message}`\n }\n}\n\n/** What the wire resolves the commands, panels and screens of a sidebar row against. */\nexport interface UiRefs {\n /** Whether a command with this full id (`<extension>.<id>`) exists. */\n hasCommand: (id: string) => boolean\n /** Whether a panel or screen with this full id (`<extension>/<id>`) exists. */\n hasSurface: (kind: 'panel' | 'screen', id: string) => boolean\n}\n\n/** Refs that know nothing: every id stays as written. */\nexport const NO_UI_REFS: UiRefs = { hasCommand: () => false, hasSurface: () => false }\n\nfunction checked<T>(issues: readonly SessionQueryIssue[], value: unknown): T {\n if (issues.length > 0)\n throw new SessionQueryError(issues)\n return toJson(value) as T\n}\n\nconst query = (path: string, value: unknown): SessionQuery => checked(validateQuery(value, path), value)\nconst optionalQuery = (path: string, value: unknown): SessionQuery | undefined => (value === undefined ? undefined : query(path, value))\n\n/** `default`, a full id kept as is, or an own space id made full. */\nfunction spaceRef(value: unknown, extension: string, what: string): string {\n if (value === 'default')\n return value\n if (typeof value === 'string' && value.includes('/')) {\n const [ext, id, ...rest] = value.split('/')\n if (rest.length === 0 && EXTENSION_ID_PATTERN.test(ext!) && LOCAL_ID.test(id!))\n return value\n throw new TypeError(`${what} must be default, an own space id or <extension>/<id>`)\n }\n return `${extension}/${localId(value, what)}`\n}\n\n/** A command id as published: the extension's own `<extension>.<id>` when it has it, else as written. */\nfunction commandRef(id: string, extension: string, refs: UiRefs): string {\n const own = `${extension}.${id}`\n return refs.hasCommand(own) ? own : id\n}\n\n/** A panel or screen id as published: the extension's own `<extension>/<id>` when it has it, else as written. */\nfunction surfaceRef(kind: 'panel' | 'screen', id: string, extension: string, refs: UiRefs): string {\n const own = `${extension}/${id}`\n return refs.hasSurface(kind, own) ? own : id\n}\n\nfunction tone(value: unknown): ExtensionBadgeTone | undefined {\n return TONES.find(t => t === value)\n}\n\nfunction capped(value: unknown, max: number, what: string): readonly unknown[] {\n if (value === undefined)\n return []\n if (!Array.isArray(value))\n throw new TypeError(`${what} must be a list`)\n if (value.length > max)\n throw new TypeError(`${what}: at most ${max}`)\n return value\n}\n\nfunction serializeSpace(item: Resolved<SpaceItem>, extension: string): SpaceWire {\n const id = localId(item.id, 'Space id')\n if (id === 'default')\n throw new TypeError('Space id \"default\" belongs to the built-in space')\n const spaceIcon = icon(item.icon)\n const groupBy = item.groupBy === undefined ? undefined : checked<SessionGroupBy>(validateGroupBy(item.groupBy, 'groupBy'), item.groupBy)\n const sortBy = item.sortBy === undefined ? undefined : checked<SessionSort[]>(validateSort(item.sortBy, 'sortBy'), item.sortBy)\n const ns = item.newSession as Record<string, unknown> | undefined\n let newSession: SpaceNewSession | undefined\n if (ns !== undefined) {\n if (!ns || typeof ns !== 'object')\n throw new TypeError('Space newSession must be { agentId?, providerKey?, modelId?, effort? }')\n if (ns.effort !== undefined && !isThinkingLevel(ns.effort))\n throw new TypeError('Space newSession.effort must be a thinking level')\n const agentId = cut(ns.agentId, 200)\n const providerKey = cut(ns.providerKey, 200)\n const modelId = cut(ns.modelId, 200)\n newSession = { ...(agentId ? { agentId } : {}), ...(providerKey ? { providerKey } : {}), ...(modelId ? { modelId } : {}), ...(ns.effort !== undefined ? { effort: ns.effort as SpaceNewSession['effort'] } : {}) }\n }\n return {\n id: `${extension}/${id}`,\n name: need(item.name, 'Space name', 80),\n ...(spaceIcon ? { icon: spaceIcon } : {}),\n query: query('query', item.query),\n ...(groupBy ? { groupBy } : {}),\n ...(sortBy ? { sortBy } : {}),\n ...(newSession && Object.keys(newSession).length > 0 ? { newSession } : {}),\n items: item.items === true,\n order: typeof item.order === 'number' && Number.isFinite(item.order) ? item.order : 100,\n }\n}\n\nfunction serializeSidebarFilter(item: Resolved<SidebarFilterItem>, extension: string): SidebarFilterWire {\n const id = localId(item.id, 'Sidebar filter id')\n if (item.kind !== 'toggle' && item.kind !== 'select' && item.kind !== 'multi')\n throw new TypeError('Sidebar filter kind must be toggle, select or multi')\n const filterIcon = icon(item.icon)\n let options: SidebarFilterWire['options']\n let filterQuery: SessionQuery | undefined\n if (item.kind === 'toggle') {\n if (item.options !== undefined)\n throw new TypeError('A toggle sidebar filter takes a query, not options')\n filterQuery = query('query', item.query)\n }\n else {\n if (item.query !== undefined)\n throw new TypeError(`A ${item.kind} sidebar filter takes options, not a query`)\n const list = capped(item.options, 32, 'Sidebar filter options') as readonly Record<string, unknown>[]\n if (list.length === 0)\n throw new TypeError(`A ${item.kind} sidebar filter needs 1 to 32 options`)\n const seen = new Set<string>()\n options = list.map((o, i) => {\n const optionId = localId(o?.id, `Sidebar filter option ${i} id`)\n if (seen.has(optionId))\n throw new TypeError(`Sidebar filter option id \"${optionId}\" is used twice`)\n seen.add(optionId)\n return { id: optionId, label: need(o.label, `Sidebar filter option ${optionId} label`, 80), query: query(`options[${i}].query`, o.query) }\n })\n }\n let spaces: SidebarFilterWire['spaces'] = 'all'\n if (item.spaces !== undefined && item.spaces !== 'all') {\n const list = capped(item.spaces, 64, 'Sidebar filter spaces')\n if (list.length === 0)\n throw new TypeError('Sidebar filter spaces must be all or name at least one space')\n spaces = [...new Set(list.map(s => spaceRef(s, extension, 'Sidebar filter space')))]\n }\n return {\n id: `${extension}/${id}`,\n label: need(item.label, 'Sidebar filter label', 80),\n ...(filterIcon ? { icon: filterIcon } : {}),\n kind: item.kind,\n ...(options ? { options } : {}),\n ...(filterQuery ? { query: filterQuery } : {}),\n spaces,\n }\n}\n\nfunction serializeSidebarSort(item: Resolved<SidebarSortItem>, extension: string): SidebarSortWire {\n const id = localId(item.id, 'Sidebar sort id')\n if (!Array.isArray(item.sortBy) || item.sortBy.length === 0)\n throw new TypeError('Sidebar sort needs at least one sort key in sortBy')\n return { id: `${extension}/${id}`, label: need(item.label, 'Sidebar sort label', 80), sortBy: checked(validateSort(item.sortBy, 'sortBy'), item.sortBy) }\n}\n\nfunction serializeSidebarGroup(item: Resolved<SidebarGroupItem>, extension: string): SidebarGroupWire {\n const id = localId(item.id, 'Sidebar group id')\n return { id: `${extension}/${id}`, label: need(item.label, 'Sidebar group label', 80), groupBy: checked(validateGroupBy(item.groupBy, 'groupBy'), item.groupBy) }\n}\n\n/** A string drawn as given (blank: absent), or `{ template }` checked as a template. */\nfunction sidebarText(value: unknown, path: string, max: number): SidebarText | undefined {\n if (value === undefined)\n return undefined\n if (typeof value === 'string')\n return cut(value, max)\n const t = (value && typeof value === 'object' ? value : {}) as Record<string, unknown>\n if (typeof t.template !== 'string' || Object.keys(t).length !== 1)\n throw new TypeError(`${path} must be a string or { template }`)\n return { template: checked<string>(validateTemplate(t.template, `${path}.template`), t.template) }\n}\n\nfunction serializeSidebarDecoration(item: Resolved<SidebarDecorationItem>, extension: string): SidebarDecorationWire {\n const id = localId(item.id, 'Sidebar decoration id')\n const where = optionalQuery('where', item.where)\n const decorationIcon = icon(item.icon)\n const decorationTone = tone(item.tone)\n const subtitle = sidebarText(item.subtitle, 'subtitle', 300)\n const chips = capped(item.chips, 8, 'Sidebar decoration chips').map((raw, i): SidebarChip | undefined => {\n const c = (raw ?? {}) as Record<string, unknown>\n const chipTone = tone(c.tone)\n const chipIcon = icon(c.icon)\n const extra = { ...(chipTone ? { tone: chipTone } : {}), ...(chipIcon ? { icon: chipIcon } : {}) }\n const kinds = (['text', 'template', 'facet'] as const).filter(k => c[k] !== undefined)\n if (kinds.length !== 1)\n throw new TypeError(`chips[${i}] must be one of { text }, { template } or { facet: facet.<extension>.<key> }`)\n if (kinds[0] === 'text') {\n if (typeof c.text !== 'string')\n throw new TypeError(`chips[${i}].text must be a string`)\n // Blank user text (a name cleared) is no chip, not an error.\n const text = cut(c.text, 80)\n return text ? { text, ...extra } : undefined\n }\n if (kinds[0] === 'template') {\n if (typeof c.template !== 'string')\n throw new TypeError(`chips[${i}].template must be a string`)\n return { template: checked<string>(validateTemplate(c.template, `chips[${i}].template`), c.template), ...extra }\n }\n if (parseFieldPath(c.facet)?.kind !== 'facet')\n throw new TypeError(`chips[${i}].facet must be facet.<extension>.<key>`)\n return { facet: c.facet as `facet.${string}`, ...extra }\n }).filter((c): c is SidebarChip => c !== undefined)\n const component = serializeComponent(item.component)\n if (!decorationIcon && !decorationTone && !subtitle && chips.length === 0 && !component)\n throw new TypeError('A sidebar decoration needs an icon, a tone, a subtitle, chips or a component')\n return {\n id: `${extension}/${id}`,\n ...(where ? { where } : {}),\n ...(decorationIcon ? { icon: decorationIcon } : {}),\n ...(decorationTone ? { tone: decorationTone } : {}),\n ...(subtitle ? { subtitle } : {}),\n ...(chips.length > 0 ? { chips } : {}),\n ...(component ? { component } : {}),\n }\n}\n\nconst ROW_STATUSES: readonly SidebarRowStatus[] = ['idle', 'running', 'blocked', 'completed', 'error']\n\nfunction serializeOpen(value: unknown, extension: string, refs: UiRefs): SidebarRowOpen | undefined {\n if (value === undefined)\n return undefined\n const o = (value && typeof value === 'object' ? value : {}) as Record<string, unknown>\n const keys = (['command', 'panel', 'screen', 'session'] as const).filter(k => o[k] !== undefined)\n if (keys.length !== 1)\n throw new TypeError('Sidebar row open must be one of { command }, { panel }, { screen }, { session }')\n const key = keys[0]!\n const id = need(o[key], `Sidebar row open.${key}`, 512)\n switch (key) {\n case 'command':\n return { command: commandRef(id, extension, refs) }\n case 'panel':\n return { panel: surfaceRef('panel', id, extension, refs) }\n case 'screen':\n return { screen: surfaceRef('screen', id, extension, refs) }\n default:\n return { session: id }\n }\n}\n\nfunction serializeSidebarRow(item: Resolved<SidebarRowItem>, extension: string, refs: UiRefs): SidebarRowWire {\n const id = localId(item.id, 'Sidebar row id')\n const group = item.group === undefined ? undefined : need(item.group, 'Sidebar row group', 200)\n const subtitle = cut(item.subtitle, 300)\n const rowIcon = icon(item.icon)\n const rowTone = tone(item.tone)\n if (item.status !== undefined && !ROW_STATUSES.includes(item.status))\n throw new TypeError(`Sidebar row status must be one of ${ROW_STATUSES.join(', ')}`)\n if (item.time !== undefined && (typeof item.time !== 'number' || !Number.isFinite(item.time)))\n throw new TypeError('Sidebar row time must be epoch ms')\n const badges = capped(item.badges, 8, 'Sidebar row badges').map((raw, i): SidebarBadge => {\n const b = (raw ?? {}) as Record<string, unknown>\n const badgeTone = tone(b.tone)\n const badgeIcon = icon(b.icon)\n return { text: need(b.text, `Sidebar row badge ${i} text`, 40), ...(badgeTone ? { tone: badgeTone } : {}), ...(badgeIcon ? { icon: badgeIcon } : {}) }\n })\n const seen = new Set<string>()\n const actions = capped(item.actions, 8, 'Sidebar row actions').map((raw, i): SidebarRowActionWire => {\n const a = (raw ?? {}) as Record<string, unknown>\n const actionId = localId(a.id, `Sidebar row action ${i} id`)\n if (seen.has(actionId))\n throw new TypeError(`Sidebar row action id \"${actionId}\" is used twice`)\n seen.add(actionId)\n const command = cut(a.command, 200)\n return { id: actionId, label: need(a.label, `Sidebar row action ${actionId} label`, 80), ...(command ? { command: commandRef(command, extension, refs) } : {}) }\n })\n const open = serializeOpen(item.open, extension, refs)\n const children = optionalQuery('children', item.children)\n return {\n id: `${extension}/${id}`,\n args: id,\n space: spaceRef(item.space, extension, 'Sidebar row space'),\n ...(group ? { group } : {}),\n // Blank user text (a name cleared) falls back to the row id rather than failing the row.\n title: typeof item.title === 'string' ? (cut(item.title, 200) ?? id) : need(item.title, 'Sidebar row title', 200),\n ...(subtitle ? { subtitle } : {}),\n ...(rowIcon ? { icon: rowIcon } : {}),\n ...(rowTone ? { tone: rowTone } : {}),\n ...(item.status !== undefined ? { status: item.status } : {}),\n ...(item.time !== undefined ? { time: item.time } : {}),\n ...(badges.length > 0 ? { badges } : {}),\n ...(actions.length > 0 ? { actions } : {}),\n ...(open ? { open } : {}),\n ...(children ? { children } : {}),\n }\n}\n\ntype Serializer<N extends UiTokenName> = (item: Resolved<UiItemMap[N]>, extension: string, refs: UiRefs) => UiWireMap[N]\n\nconst SERIALIZERS: { [N in UiTokenName]: Serializer<N> } = {\n 'panel': serializePanel,\n 'slot': serializeSlot,\n 'screen': serializeScreen,\n 'renderer': serializeRenderer,\n 'settings-page': serializeSettingsPage,\n 'webview': serializeWebview,\n 'menu': serializeMenu,\n 'theme': serializeTheme,\n 'reference': serializeReference,\n 'badge-action': serializeBadgeAction,\n 'link-handler': serializeLinkHandler,\n 'context-section': serializeContextSection,\n 'space': serializeSpace,\n 'sidebar-filter': serializeSidebarFilter,\n 'sidebar-sort': serializeSidebarSort,\n 'sidebar-group': serializeSidebarGroup,\n 'sidebar-decoration': serializeSidebarDecoration,\n 'sidebar-row': serializeSidebarRow,\n}\n\n/**\n * The wire form of one item. Throws a `TypeError` when the item is\n * unusable, and a {@link UiQueryError} when one of its queries, sorts,\n * groupings or templates is invalid.\n *\n * @param token - The token name.\n * @param item - The item with its bindable fields read.\n * @param extension - The contributing extension's id (prefixes ids).\n * @param refs - What a sidebar row's commands, panels and screens resolve against. Default: nothing (ids stay as written).\n */\nexport function serializeUiItem<N extends UiTokenName>(token: N, item: Resolved<UiItemMap[N]>, extension: string, refs: UiRefs = NO_UI_REFS): UiWireMap[N] {\n if (!item || typeof item !== 'object')\n throw new TypeError(`${token}: the item must be an object`)\n try {\n return (SERIALIZERS[token] as Serializer<N>)(item, extension, refs)\n }\n catch (err) {\n if (err instanceof SessionQueryError && !(err instanceof UiQueryError))\n throw new UiQueryError(token, err.issues)\n throw err\n }\n}\n\n/**\n * What makes an item the same item across updates: its id; for slots the\n * place and session; for renderers what they render (`for`, as JSON); for\n * breakdown context sections the constant `'breakdown'`. `update` may not\n * change it. `undefined` only for menus, whose items have no identity.\n *\n * @param token - The token name.\n * @param wire - The item's wire form.\n */\nexport function wireIdentity<N extends UiTokenName>(token: N, wire: UiWireMap[N]): string | undefined {\n switch (token) {\n case 'slot': {\n const s = wire as SlotWire\n return `${s.at}\\u0000${s.sessionId ?? ''}`\n }\n case 'renderer':\n return JSON.stringify((wire as RendererWire).for)\n case 'menu':\n return undefined\n case 'context-section': {\n const c = wire as ContextSectionWire\n return c.placement === 'panel' ? c.id : 'breakdown'\n }\n default:\n return (wire as { id: string }).id\n }\n}\n\n/**\n * Whether two items of this token with the same identity\n * ({@link wireIdentity}) may not live side by side in one extension: true\n * for every token but slots, renderers, menus and breakdown context\n * sections.\n *\n * @param token - The token name.\n * @param wire - The item's wire form.\n */\nexport function isUniquePerExtension<N extends UiTokenName>(token: N, wire: UiWireMap[N]): boolean {\n if (token === 'context-section')\n return (wire as ContextSectionWire).placement === 'panel'\n return token !== 'slot' && token !== 'renderer' && token !== 'menu'\n}\n","/**\n * Facets (`ctx.sessions.facets`): JSON values extensions compute per\n * session, which session queries read as `facet.<extensionId>.<key>`. The\n * runtime keeps the registrations and runs them; hosts store the values and\n * decide when to compute (a session created, a run settled, metadata\n * changed, a facet added, a `refresh` asked for).\n */\n\nimport type { JsonValue } from '../../types'\nimport type { Disposable, Owner } from '../api/core'\nimport type { SessionFacetsDomain, SessionFacetSpec, SessionFacetTrigger, SessionSnapshot } from '../api/sessions'\nimport type { DomainDeps } from './deps'\nimport { FACET_KEY } from '../../chat/session-query'\nimport { metadataForExtension } from '../../session/facets'\nimport { toJson } from '../ui/wire'\nimport { assertAlive, track } from './owner'\n\n/** Bound of one facet's `compute`, in ms. */\nexport const FACET_COMPUTE_TIMEOUT_MS = 5_000\n/** The most JSON one facet value may take, in bytes of its JSON text. */\nexport const MAX_FACET_BYTES = 8 * 1024\n/** How many facets one extension may hold. */\nexport const MAX_FACETS_PER_EXTENSION = 32\n/** Every trigger, in a fixed order: what a facet without `on` runs on. */\nexport const SESSION_FACET_TRIGGERS: readonly SessionFacetTrigger[] = ['created', 'settled', 'metadata']\n\n/** A registered facet, as hosts list it. */\nexport interface FacetInfo {\n /** `<extensionId>.<key>`: its key in a row's `facets` and its query path after `facet.`. */\n readonly id: string\n /** The extension that computes it. */\n readonly extension: string\n /** The extension's key. */\n readonly key: string\n /** The triggers it is computed again on. */\n readonly on: readonly SessionFacetTrigger[]\n}\n\n/** A `ctx.sessions.facets.refresh` call, as hosts get it. */\nexport interface FacetRefreshRequest {\n /** The extension whose facets to compute again. */\n readonly extension: string\n /** Only this session. Absent: every session. */\n readonly sessionId?: string\n}\n\n/**\n * A change of a registry's facets, as {@link FacetRegistry.subscribe}\n * reports it. Only an explicit withdrawal or an uninstall asks hosts to\n * delete stored values: an extension disabled, failing or reloaded withdraws\n * its facets with both lists empty, and its stored values stay.\n */\nexport interface FacetChange {\n /** Facet ids their extension disposed while it stayed loaded: hosts delete their stored values. */\n readonly withdrawn: readonly string[]\n /** Extensions uninstalled or forgotten (`unload` with `forget`): hosts delete every stored value of theirs. */\n readonly forgotten: readonly string[]\n}\n\n/** Options of {@link FacetRegistry.compute}. */\nexport interface FacetComputeOptions {\n /** Only this extension's facets. */\n extension?: string\n}\n\n/** The facets every extension registered. Hung on `ExtensionRuntimeOutputs.facets`. */\nexport interface FacetRegistry {\n /** Every facet, in extension load order, then registration order. */\n list: () => readonly FacetInfo[]\n /**\n * Computes the facets that run on `triggers` (one trigger or a set; every\n * facet when absent) for one session, each facet once, in parallel, each\n * under its extension's guard. Each extension's facets see\n * `metadata.extensions` cut down to its own slice. The result holds a key\n * per facet that answered: its JSON value, or `null` to clear it. A facet\n * that threw, timed out, or answered something too big or not JSON has no\n * key: keep its last value.\n */\n compute: (session: SessionSnapshot, triggers?: SessionFacetTrigger | ReadonlySet<SessionFacetTrigger>, options?: FacetComputeOptions) => Promise<Record<string, JsonValue>>\n /** Calls `listener` after a facet is added or withdrawn, or an extension is forgotten, with what was withdrawn on purpose ({@link FacetChange}). Not called once the registry is disposed. Returns the unsubscribe. */\n subscribe: (listener: (change: FacetChange) => void) => () => void\n /** Whether the runtime that owns the registry was disposed: nothing is computed with it again. */\n disposed: () => boolean\n /** Calls `listener` once, when the owning runtime is disposed (at once when it already is). Returns the unsubscribe. */\n onDispose: (listener: () => void) => () => void\n /** Logs a warning on `extension`'s logger (a host refusing its values). Dropped when the extension holds no facet. */\n warn: (extension: string, message: string) => void\n /**\n * Handles `ctx.sessions.facets.refresh`: the host computes the facets again\n * and stores them. `refresh` resolves once every handler did. Returns the\n * unsubscribe. With no handler, `refresh` resolves at once.\n */\n onRefresh: (handler: (request: FacetRefreshRequest) => void | Promise<void>) => () => void\n}\n\n/**\n * The registry together with its per-extension domain factory, its close\n * (the runtime's dispose calls it first), and `forget` (the runtime's\n * `unload` with `forget` calls it, after the extension's facets went).\n */\nexport type FacetsRuntime = FacetRegistry & { domain: (deps: DomainDeps) => SessionFacetsDomain, close: () => void, forget: (extensionId: string) => void }\n\ninterface Entry {\n info: FacetInfo\n spec: SessionFacetSpec\n deps: DomainDeps\n seq: number\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n Object.freeze(value)\n for (const v of Object.values(value)) deepFreeze(v)\n }\n return value\n}\n\n/** Whether the extension behind `owner` (its root owner, past any scope) is still loaded. */\nfunction extensionAlive(owner: Owner): boolean {\n let root = owner\n while ((root as { parent?: Owner }).parent)\n root = (root as { parent?: Owner }).parent!\n return !root.disposed\n}\n\nfunction triggersOf(on: unknown): SessionFacetTrigger[] {\n if (on === undefined)\n return [...SESSION_FACET_TRIGGERS]\n if (!Array.isArray(on) || on.length === 0 || !on.every(t => (SESSION_FACET_TRIGGERS as readonly unknown[]).includes(t)))\n throw new TypeError(`sessions.facets: on must list some of ${SESSION_FACET_TRIGGERS.join(', ')}`)\n return SESSION_FACET_TRIGGERS.filter(t => on.includes(t))\n}\n\n/**\n * Creates an empty facet registry.\n *\n * @param options - `order`: an extension's load-order rank (lower first); `attachHost`: called with the registry when an extension registers or refreshes a facet.\n * @param options.order - The rank of an extension id.\n * @param options.attachHost - Hands the registry to the host that computes facets (`ExtensionSessionControl.attachFacets`), so it hears `refresh` and computes new facets.\n */\nexport function createFacetRegistry(options: { order?: (extensionId: string) => number, attachHost?: (registry: FacetRegistry) => void } = {}): FacetsRuntime {\n const entries = new Map<string, Entry>()\n const listeners = new Set<(change: FacetChange) => void>()\n const refreshers = new Set<(request: FacetRefreshRequest) => void | Promise<void>>()\n const disposeListeners = new Set<() => void>()\n let closed = false\n let seq = 0\n const rank = options.order ?? (() => 0)\n // Assigned once the registry exists; a host that fails to attach computes nothing, which is all it costs.\n let self: FacetRegistry | undefined\n const attachHost = (): void => {\n if (!self || !options.attachHost)\n return\n try {\n options.attachHost(self)\n }\n catch {}\n }\n\n const changed = (change: Partial<FacetChange> = {}): void => {\n if (closed)\n return\n const full: FacetChange = { withdrawn: change.withdrawn ?? [], forgotten: change.forgotten ?? [] }\n for (const listener of [...listeners]) {\n try {\n listener(full)\n }\n catch {}\n }\n }\n const sorted = (): Entry[] => [...entries.values()].sort((a, b) => (rank(a.info.extension) - rank(b.info.extension)) || a.seq - b.seq)\n\n const run = async (entry: Entry, snapshot: SessionSnapshot): Promise<[string, JsonValue] | undefined> => {\n const { deps, spec, info } = entry\n const answer = await deps.guard.call(`sessions.facets.${info.key}`, async () => ({ value: await spec.compute(snapshot) }), { timeoutMs: FACET_COMPUTE_TIMEOUT_MS })\n if (!answer)\n return undefined\n if (answer.value === undefined || answer.value === null)\n return [info.id, null]\n const json = toJson(answer.value)\n const text = json === undefined ? undefined : JSON.stringify(json)\n if (json === undefined || text === undefined) {\n deps.logger.warn(`sessions.facets: ${info.key} answered a value that is not JSON; keeping the last one`)\n return undefined\n }\n if (new TextEncoder().encode(text).length > MAX_FACET_BYTES) {\n deps.logger.warn(`sessions.facets: ${info.key} answered more than ${MAX_FACET_BYTES} bytes; keeping the last one`)\n return undefined\n }\n return [info.id, json as JsonValue]\n }\n\n const register = (deps: DomainDeps, spec: SessionFacetSpec): Disposable => {\n assertAlive(deps.owner, 'sessions.facets.register')\n if (!spec || typeof spec !== 'object')\n throw new TypeError('sessions.facets.register: the spec must be an object')\n if (typeof spec.key !== 'string' || !FACET_KEY.test(spec.key))\n throw new TypeError('sessions.facets.register: key must be a letter or _, then up to 63 letters, digits, _ or -')\n if (typeof spec.compute !== 'function')\n throw new TypeError('sessions.facets.register: compute must be a function')\n const on = triggersOf(spec.on)\n const id = `${deps.extensionId}.${spec.key}`\n if (entries.has(id))\n throw new TypeError(`sessions.facets.register: this extension already has a facet \"${spec.key}\"`)\n if ([...entries.values()].filter(e => e.info.extension === deps.extensionId).length >= MAX_FACETS_PER_EXTENSION)\n throw new RangeError(`sessions.facets.register: at most ${MAX_FACETS_PER_EXTENSION} facets per extension`)\n const entry: Entry = { info: Object.freeze({ id, extension: deps.extensionId, key: spec.key, on: Object.freeze(on) }), spec: { ...spec }, deps, seq: ++seq }\n entries.set(id, entry)\n attachHost()\n changed()\n return track(deps.owner, {\n dispose: () => {\n if (entries.get(id) !== entry)\n return\n entries.delete(id)\n // The extension still loaded (a handle or a scope disposed): withdrawn on purpose. Else it is unloading: values kept.\n changed(extensionAlive(deps.owner) ? { withdrawn: [id] } : {})\n },\n })\n }\n\n const refresh = async (deps: DomainDeps, sessionId: string | undefined): Promise<void> => {\n assertAlive(deps.owner, 'sessions.facets.refresh')\n if (sessionId !== undefined && (typeof sessionId !== 'string' || sessionId.length === 0))\n throw new TypeError('sessions.facets.refresh: sessionId must be a non-empty string')\n const request: FacetRefreshRequest = { extension: deps.extensionId, ...(sessionId !== undefined ? { sessionId } : {}) }\n attachHost()\n await Promise.all([...refreshers].map(async (handler) => {\n try {\n await handler(request)\n }\n catch (err) {\n deps.logger.warn('sessions.facets.refresh: the host failed to refresh', { error: err instanceof Error ? err.message : String(err) })\n }\n }))\n }\n\n const registry: FacetsRuntime = {\n list: () => sorted().map(e => e.info),\n compute: async (session, triggers, opts = {}) => {\n const wanted = triggers === undefined ? undefined : typeof triggers === 'string' ? new Set([triggers]) : triggers\n const due = sorted().filter(e => (wanted === undefined || e.info.on.some(t => wanted.has(t))) && (opts.extension === undefined || e.info.extension === opts.extension))\n if (due.length === 0)\n return {}\n const base = structuredClone(session)\n // One snapshot per extension: its own slice of `metadata.extensions` only.\n const snapshots = new Map<string, SessionSnapshot>()\n const snapshotFor = (extension: string): SessionSnapshot => {\n let snapshot = snapshots.get(extension)\n if (!snapshot)\n snapshots.set(extension, snapshot = deepFreeze({ ...base, metadata: metadataForExtension(base.metadata, extension) }))\n return snapshot\n }\n const results = await Promise.all(due.map(e => run(e, snapshotFor(e.info.extension))))\n return Object.fromEntries(results.filter((r): r is [string, JsonValue] => r !== undefined))\n },\n subscribe: (listener) => {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n onRefresh: (handler) => {\n refreshers.add(handler)\n return () => {\n refreshers.delete(handler)\n }\n },\n disposed: () => closed,\n onDispose: (listener) => {\n if (closed) {\n listener()\n return () => {}\n }\n disposeListeners.add(listener)\n return () => {\n disposeListeners.delete(listener)\n }\n },\n warn: (extension, message) => {\n const entry = [...entries.values()].find(e => e.info.extension === extension)\n entry?.deps.logger.warn(message)\n },\n close: () => {\n if (closed)\n return\n closed = true\n listeners.clear()\n refreshers.clear()\n for (const listener of [...disposeListeners]) {\n try {\n listener()\n }\n catch {}\n }\n disposeListeners.clear()\n },\n forget: (extensionId) => {\n changed({ forgotten: [extensionId] })\n },\n domain: deps => ({\n register: spec => register(deps, spec),\n refresh: sessionId => refresh(deps, sessionId),\n }),\n }\n self = registry\n return registry\n}\n","/**\n * The host port of the extension storage domain: where kv entries and store records\n * live, and how changes made elsewhere (another window, client or process)\n * come back. The domain keeps a synchronous cache over it; the port only\n * moves data.\n */\n\nimport type { Disposable } from '../api/core'\nimport type { Json, StorageScope } from '../api/storage'\n\n/** One storage file: an extension's data in one scope (and session). */\nexport interface StorageLocation {\n /** The owning extension. */\n readonly extensionId: string\n /** `user`, `project` or `session`. */\n readonly scope: StorageScope\n /** Set exactly when `scope` is `'session'`. */\n readonly sessionId?: string\n}\n\n/** The two key spaces of a location: `ctx.storage.kv` entries and typed store records. */\nexport type StorageArea = 'kv' | 'stores'\n\n/** Everything stored at one location. */\nexport interface StorageSnapshot {\n /** kv entries by key. */\n readonly kv: Readonly<Record<string, Json>>\n /** Store records (`{ v, value }`) by store name. */\n readonly stores: Readonly<Record<string, Json>>\n}\n\n/** A change the port saw that this process did not make. `value: undefined` is a delete. */\nexport interface StorageChange {\n /** Which key space changed. */\n readonly area: StorageArea\n /** The kv key or store name. */\n readonly key: string\n /** The new value, or `undefined` when the entry was removed. */\n readonly value: Json | undefined\n}\n\n/** Persistence and sync for the storage domain. Implemented per host (file, IPC, protocol). */\nexport interface StoragePort {\n /** Reads everything at `loc`. A missing location is an empty snapshot. */\n load: (loc: StorageLocation) => Promise<StorageSnapshot>\n /** Writes one entry. */\n save: (loc: StorageLocation, area: StorageArea, key: string, value: Json) => Promise<void>\n /** Removes one entry. Removing a missing entry is a no-op. */\n delete: (loc: StorageLocation, area: StorageArea, key: string) => Promise<void>\n /**\n * Calls `listener` for changes made by others (not through this port's own\n * `save` / `delete`). Echoes are harmless: the domain drops a change that\n * matches what it already holds.\n */\n subscribe: (loc: StorageLocation, listener: (change: StorageChange) => void) => Disposable\n /**\n * The folder this port keeps one extension's data of `scope` in\n * (`project` covers sessions). `storage.path` puts the extension's files\n * under it. Absent (a port with no folders): `<dataDir>/extension-storage`\n * and `<projectRoot>/<prefix>/extension-storage` (`./paths`).\n */\n folderOf?: (extensionId: string, scope: 'user' | 'project') => string\n}\n\n/** A stable string id for a location, for maps and file names. */\nexport function locationKey(loc: StorageLocation): string {\n return loc.scope === 'session' ? `${loc.extensionId}\\u0000session\\u0000${loc.sessionId ?? ''}` : `${loc.extensionId}\\u0000${loc.scope}`\n}\n","/**\n * The synchronous cache behind `ctx.storage`: one state per location,\n * loaded from the {@link StoragePort}, updated by local writes and remote\n * changes. A change equal to what the cache holds is dropped, so each\n * change reaches kv subscribers and store handlers once and the port's\n * echoes of this process's own writes are silent.\n */\n\nimport type { Logger } from '../../logger'\nimport type { Disposable } from '../api/core'\nimport type { Json, StorageScope } from '../api/storage'\nimport type { DomainDeps } from '../runtime/deps'\nimport type { StorageArea, StorageChange, StorageLocation, StoragePort } from './port'\nimport { DisposedError } from '../api/core'\nimport { isTornDown, onTeardown } from '../runtime/owner'\nimport { isSafeRecordKey } from '../shared'\nimport { deepEqual, frozenCopy, isJson } from './json'\nimport { locationKey } from './port'\n\n/** The cached data and listeners of one location. */\nexport interface LocationState {\n /** Where the data lives. */\n readonly loc: StorageLocation\n /** Cached entries (frozen) by area and key. */\n readonly entries: Record<StorageArea, Map<string, Json>>\n /** Local writes not yet confirmed by the port, by area and key. A load must not undo them. */\n readonly pending: Record<StorageArea, Map<string, number>>\n /** `kv.subscribe` listeners. */\n readonly kvListeners: Set<(change: { key: string, value: Json | undefined }) => void>\n /** Store decoders by store name; called with the new record. */\n readonly storeHandlers: Map<string, (raw: Json | undefined) => void>\n /** `true` after the first successful load. */\n loaded: boolean\n /** The load in flight. */\n loading?: Promise<void>\n /** The port subscription for remote changes. */\n subscription?: Disposable\n}\n\n/** The cache shared by kv handles and stores of one extension. */\nexport interface StorageCache {\n /** Logger tagged with the extension and domain. */\n readonly logger: Logger\n /** Throws {@link DisposedError} once the owner is disposed. */\n assertLive: (what: string) => void\n /** The location for `scope`; `'session'` falls back to the current session. */\n resolve: (scope: StorageScope, sessionId: string | undefined, what: string) => StorageLocation\n /** The state of `loc`, created and subscribed to the port on first use. */\n stateFor: (loc: StorageLocation) => LocationState\n /** Loads `state` from the port. `fresh` starts a new read even when one is in flight. */\n load: (state: LocationState, fresh: boolean) => Promise<void>\n /** Starts a background load when the location was never loaded. */\n ensureLoaded: (state: LocationState) => void\n /** Puts one entry in the cache, then saves it through the port; rolls back on failure. */\n write: (state: LocationState, area: StorageArea, key: string, value: Json | undefined, notify: boolean) => Promise<void>\n}\n\n/**\n * Builds the cache of one extension. Disposing the owner drops every\n * listener and port subscription.\n *\n * @param deps - Extension id, owner, guard and logger.\n * @param port - Persistence and remote changes.\n * @param currentSessionId - The session a `'session'` call without an id uses.\n */\nexport function createStorageCache(deps: DomainDeps, port: StoragePort, currentSessionId?: () => string | undefined): StorageCache {\n const { extensionId, owner, guard } = deps\n const logger = deps.logger.with({ extension: extensionId, domain: 'storage' })\n const states = new Map<string, LocationState>()\n\n // Storage serves the calls still in flight after an unload: dropped at teardown.\n onTeardown(owner, () => {\n for (const state of states.values()) {\n state.subscription?.dispose()\n state.kvListeners.clear()\n state.storeHandlers.clear()\n }\n states.clear()\n })\n\n function assertLive(what: string): void {\n if (isTornDown(owner))\n throw new DisposedError(`storage.${what}`)\n }\n\n function resolve(scope: StorageScope, sessionId: string | undefined, what: string): StorageLocation {\n if (scope !== 'session')\n return { extensionId, scope }\n const id = sessionId ?? currentSessionId?.()\n if (typeof id !== 'string' || id.length === 0)\n throw new Error(`storage.${what}('session'): no current session; pass a sessionId`)\n return { extensionId, scope, sessionId: id }\n }\n\n function stateFor(loc: StorageLocation): LocationState {\n const key = locationKey(loc)\n const existing = states.get(key)\n if (existing)\n return existing\n const state: LocationState = {\n loc,\n entries: { kv: new Map(), stores: new Map() },\n pending: { kv: new Map(), stores: new Map() },\n kvListeners: new Set(),\n storeHandlers: new Map(),\n loaded: false,\n }\n states.set(key, state)\n try {\n state.subscription = port.subscribe(loc, change => onRemote(state, change))\n }\n catch (err) {\n logger.warn('storage: port.subscribe failed; remote changes will not arrive', { scope: loc.scope, error: String(err) })\n }\n return state\n }\n\n function onRemote(state: LocationState, change: StorageChange): void {\n if (isTornDown(owner) || !isSafeRecordKey(change.key))\n return\n if (change.value !== undefined && !isJson(change.value)) {\n logger.warn('storage: ignored a non-JSON remote value', { key: change.key })\n return\n }\n apply(state, change.area, change.key, change.value, true)\n }\n\n function apply(state: LocationState, area: StorageArea, key: string, value: Json | undefined, notify: boolean): void {\n const map = state.entries[area]\n if (deepEqual(map.get(key), value))\n return\n if (value === undefined)\n map.delete(key)\n else\n map.set(key, frozenCopy(value))\n if (!notify)\n return\n const stored = map.get(key)\n if (area === 'stores') {\n state.storeHandlers.get(key)?.(stored)\n return\n }\n for (const listener of [...state.kvListeners])\n guard.callSync('storage.kv.subscribe', () => listener({ key, value: stored }))\n }\n\n async function read(state: LocationState): Promise<void> {\n const snapshot = await port.load(state.loc)\n if (isTornDown(owner))\n return\n for (const area of ['kv', 'stores'] as const) {\n const incoming = snapshot[area] ?? {}\n const keys = new Set([...state.entries[area].keys(), ...Object.keys(incoming)])\n for (const key of keys) {\n if (!isSafeRecordKey(key) || state.pending[area].has(key))\n continue\n const value = Object.hasOwn(incoming, key) ? incoming[key] : undefined\n if (value === undefined || isJson(value))\n apply(state, area, key, value, true)\n }\n }\n state.loaded = true\n }\n\n function load(state: LocationState, fresh: boolean): Promise<void> {\n if (state.loading && !fresh)\n return state.loading\n // A fresh load starts after the one in flight, so it sees data written since that one read.\n const loading = (state.loading ? state.loading.catch(() => {}) : Promise.resolve()).then(() => read(state))\n state.loading = loading\n void loading.catch(() => {}).finally(() => {\n if (state.loading === loading)\n state.loading = undefined\n })\n return loading\n }\n\n function ensureLoaded(state: LocationState): void {\n if (state.loaded || state.loading)\n return\n load(state, false).catch((err) => {\n logger.warn('storage: load failed', { scope: state.loc.scope, error: String(err) })\n })\n }\n\n async function write(state: LocationState, area: StorageArea, key: string, value: Json | undefined, notify: boolean): Promise<void> {\n const previous = state.entries[area].get(key)\n apply(state, area, key, value, notify)\n const pending = state.pending[area]\n pending.set(key, (pending.get(key) ?? 0) + 1)\n try {\n if (value === undefined)\n await port.delete(state.loc, area, key)\n else\n await port.save(state.loc, area, key, value)\n }\n catch (err) {\n // Roll back unless a later write already replaced this value.\n if (!isTornDown(owner) && deepEqual(state.entries[area].get(key), value))\n apply(state, area, key, previous, true)\n throw err\n }\n finally {\n const left = (pending.get(key) ?? 1) - 1\n if (left > 0)\n pending.set(key, left)\n else\n pending.delete(key)\n }\n }\n\n return { logger, assertLive, resolve, stateFor, load, ensureLoaded, write }\n}\n","/**\n * Where `ctx.storage.path` puts an extension's files, and the move from the\n * folders earlier builds used.\n *\n * Files live next to the extension's kv entries and stores, in the folders of\n * the storage port (`StoragePort.folderOf`), so every host puts them where\n * it keeps the rest of the extension's data:\n *\n * user, data <dataDir>/extension-storage/<id>/files\n * project, session <projectRoot>/<prefix>/extension-storage/<id>/files\n * cache <cacheDir>/extension-storage/<id>\n *\n * Earlier builds used `<base>/extensions/<id>` ({@link legacyStoragePath}),\n * which is also where extensions are installed (`~/.zidane/extensions/<id>`),\n * or a project's own `extensions/<id>` source folder. A call finds the files\n * it asks for where they were and moves them ({@link resolveStoragePath}):\n * never an install file.\n */\n\nimport type { Logger } from '../../logger'\nimport type { ExtensionPaths } from '../api/core'\nimport type { StoragePathScope } from '../api/storage'\nimport { cpSync, existsSync, mkdirSync, readdirSync, renameSync, rmdirSync, rmSync } from 'node:fs'\nimport { dirname, join, relative, resolve, sep } from 'node:path'\n\n/** The folder a storage port keeps one extension's data of `scope` in (`StoragePort.folderOf`). */\nexport type StorageFolderOf = (extensionId: string, scope: 'user' | 'project') => string\n\n/** What {@link resolveStoragePath} needs to know about the extension. */\nexport interface StoragePathOptions {\n /** The host's paths (`ctx.paths`). */\n readonly paths: ExtensionPaths\n /** The extension id. */\n readonly extensionId: string\n /** The storage port's folders. Default: `<dataDir>/extension-storage` and `<projectRoot>/<prefix>/extension-storage`. */\n readonly folderOf?: StorageFolderOf\n /** The extension's own folder: nothing is ever moved out of it but files it asked for. */\n readonly dir?: string\n /** Receives a move that failed. */\n readonly logger?: Logger\n}\n\n/** The resolved `target` under `root`, or `root` itself when `..` segments would leave it. */\nfunction inside(root: string, segments: readonly string[]): string {\n const target = resolve(root, ...segments)\n return target === root || target.startsWith(root + sep) ? target : root\n}\n\nfunction defaultFolderOf(paths: ExtensionPaths): StorageFolderOf {\n return (extensionId, scope) => {\n const prefix = process.env.ZIDANE_PREFIX ?? '.zidane'\n const base = scope === 'project' && paths.projectRoot ? join(paths.projectRoot, prefix, 'extension-storage') : join(paths.dataDir, 'extension-storage')\n return join(base, encodeURIComponent(extensionId))\n }\n}\n\n/**\n * The folder `storage.path(scope)` resolves in.\n *\n * @param options - The extension and the port's folders.\n * @param scope - The storage area.\n */\nexport function storagePathRoot(options: Pick<StoragePathOptions, 'paths' | 'extensionId' | 'folderOf'>, scope: StoragePathScope): string {\n if (scope === 'cache')\n return resolve(options.paths.cacheDir, 'extension-storage', encodeURIComponent(options.extensionId))\n const folderOf = options.folderOf ?? defaultFolderOf(options.paths)\n return resolve(folderOf(options.extensionId, scope === 'project' || scope === 'session' ? 'project' : 'user'), 'files')\n}\n\n/**\n * Where `storage.path` resolved before it moved to the storage folders:\n * `<base>/extensions/<id>`, `base` the cache dir, the data dir, the project\n * root (project, session) or the config dir (user), else the data dir.\n *\n * @param paths - The host's paths.\n * @param extensionId - The extension id.\n * @param scope - The storage area.\n * @param segments - Path segments under the folder.\n */\nexport function legacyStoragePath(paths: ExtensionPaths, extensionId: string, scope: StoragePathScope, ...segments: string[]): string {\n const base = scope === 'cache'\n ? paths.cacheDir\n : scope === 'data'\n ? paths.dataDir\n : scope === 'project' || scope === 'session'\n ? (paths.projectRoot ?? paths.dataDir)\n : (paths.configDir ?? paths.dataDir)\n return inside(resolve(base, 'extensions', extensionId), segments)\n}\n\n/** Files that make a folder an extension's install (or source) folder. */\nconst INSTALL_MARKERS = ['index.ts', 'index.tsx', 'index.mjs', 'index.js', 'extension.json', 'package.json', '.install.json']\n/** Entries of an install folder that are the extension, not its data. */\nconst INSTALL_ENTRIES = new Set([...INSTALL_MARKERS, 'node_modules', 'src', 'dist', 'tsconfig.json', 'bun.lock', 'bun.lockb', 'package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'README.md', 'LICENSE', 'CHANGELOG.md'])\nconst SOURCE_FILE = /\\.(?:[cm]?[jt]sx?|d\\.ts)$/\n\nfunction isInstallFolder(folder: string, dir: string | undefined): boolean {\n return (dir !== undefined && resolve(dir) === folder) || INSTALL_MARKERS.some(name => existsSync(join(folder, name)))\n}\n\nfunction isInstallEntry(name: string): boolean {\n return INSTALL_ENTRIES.has(name) || SOURCE_FILE.test(name) || name.startsWith('.')\n}\n\n/** Moves a file or folder, copying when it crosses file systems. */\nfunction move(from: string, to: string): void {\n mkdirSync(dirname(to), { recursive: true })\n try {\n renameSync(from, to)\n }\n catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EXDEV')\n throw err\n cpSync(from, to, { recursive: true, errorOnExist: true, force: false })\n rmSync(from, { recursive: true, force: true })\n }\n}\n\n/** Old folders already merged in this process (the ones that hold data only). */\nconst merged = new Set<string>()\n\n/**\n * Moves what the old folder of `scope` holds for this call. An install (or\n * source) folder gives up only the top entry the call names, when it is not\n * part of the extension and the new folder lacks it; any other old folder\n * moves whole, entry by entry, keeping what the new folder already has.\n * Throws when a move fails.\n */\nfunction migrate(options: StoragePathOptions, scope: StoragePathScope, root: string, target: string): void {\n const legacy = legacyStoragePath(options.paths, options.extensionId, scope)\n if (legacy === root || !existsSync(legacy))\n return\n if (isInstallFolder(legacy, options.dir)) {\n const name = target === root ? undefined : relative(root, target).split(sep)[0]\n if (!name || isInstallEntry(name))\n return\n const from = join(legacy, name)\n const to = join(root, name)\n if (!existsSync(to) && existsSync(from))\n move(from, to)\n return\n }\n const key = `${legacy}\\u0000${root}`\n if (merged.has(key))\n return\n merged.add(key)\n for (const name of readdirSync(legacy)) {\n const to = join(root, name)\n if (!existsSync(to))\n move(join(legacy, name), to)\n }\n try {\n rmdirSync(legacy)\n }\n catch {} // Something stayed (an entry the new folder already had): left in place.\n}\n\n/**\n * `storage.path(scope, ...segments)`: a path in the extension's folder for\n * `scope` ({@link storagePathRoot}); `..` cannot leave it. Files an earlier\n * build left in the old folder are moved first. When that fails, the old\n * path is returned while the file is only there, so no data goes missing.\n *\n * @param options - The extension, the port's folders, its own folder and a logger.\n * @param scope - The storage area.\n * @param segments - Path segments under the folder.\n */\nexport function resolveStoragePath(options: StoragePathOptions, scope: StoragePathScope, ...segments: string[]): string {\n const root = storagePathRoot(options, scope)\n const target = inside(root, segments)\n // The cache is disposable: a new folder starts empty.\n if (scope === 'cache')\n return target\n try {\n migrate(options, scope, root, target)\n }\n catch (err) {\n options.logger?.warn('storage.path: could not move files from the old folder', { scope, error: String(err) })\n const old = legacyStoragePath(options.paths, options.extensionId, scope, ...segments)\n if (!existsSync(target) && existsSync(old))\n return old\n }\n return target\n}\n","/**\n * A synchronous validator for plain JSON Schema (draft-07 and 2020-12\n * basics), used by RPC and storage when an extension passes a JSON Schema\n * instead of a Standard Schema. zod's `fromJSONSchema` would need an async\n * import of an optional peer and refuses `not`, so the checks live here.\n *\n * Supported: boolean schemas, `type` (one or a list, `integer`),\n * `enum`, `const`, `properties`, `required`, `additionalProperties`,\n * `patternProperties`, `propertyNames`, `minProperties`/`maxProperties`,\n * `items` (a schema, or a tuple in draft-07), `prefixItems`,\n * `additionalItems`, `contains`, `minItems`/`maxItems`, `uniqueItems`,\n * `minLength`/`maxLength`, `pattern`, `minimum`/`maximum`,\n * `exclusiveMinimum`/`exclusiveMaximum` (number and draft-04 boolean\n * forms), `multipleOf`, `anyOf`/`oneOf`/`allOf`/`not`,\n * `if`/`then`/`else`, local `$ref` (`#`, `#/definitions/…`,\n * `#/$defs/…`). `format` and unknown keywords are ignored.\n */\n\ntype JsonSchemaNode = boolean | Readonly<Record<string, unknown>>\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value))\n return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * The JSON type name of a value (`null`, `array`, `object`, `string`, …).\n *\n * @param value - Any value.\n */\nexport function jsonTypeOf(value: unknown): string {\n if (value === null)\n return 'null'\n if (Array.isArray(value))\n return 'array'\n return typeof value\n}\n\nfunction matchesType(value: unknown, type: string): boolean {\n switch (type) {\n case 'integer': return Number.isInteger(value)\n case 'number': return typeof value === 'number' && Number.isFinite(value)\n case 'object': return isRecord(value)\n default: return jsonTypeOf(value) === type\n }\n}\n\n/**\n * Deep equality over JSON values (`enum`, `const`, `uniqueItems`).\n *\n * @param a - A JSON value.\n * @param b - Another JSON value.\n */\nexport function jsonEqual(a: unknown, b: unknown): boolean {\n if (a === b)\n return true\n if (Array.isArray(a))\n return Array.isArray(b) && a.length === b.length && a.every((item, i) => jsonEqual(item, b[i]))\n if (isRecord(a) && isRecord(b)) {\n const keys = Object.keys(a)\n return keys.length === Object.keys(b).length && keys.every(key => Object.hasOwn(b, key) && jsonEqual(a[key], b[key]))\n }\n return false\n}\n\nfunction codePoints(text: string): number {\n let n = 0\n for (const _ of text)\n n++\n return n\n}\n\nconst patternCache = new Map<string, RegExp | null>()\nfunction compile(pattern: string): RegExp | null {\n let re = patternCache.get(pattern)\n if (re === undefined) {\n try {\n re = new RegExp(pattern, 'u')\n }\n catch {\n re = null\n }\n patternCache.set(pattern, re)\n }\n return re\n}\n\n/** A pattern that does not compile refuses nothing: the schema is at fault, not the value. */\nfunction testPattern(pattern: string, text: string): boolean {\n const re = compile(pattern)\n return re === null || re.test(text)\n}\n\nfunction resolveRef(root: JsonSchemaNode, ref: string): JsonSchemaNode | undefined {\n if (ref === '#')\n return root\n if (!ref.startsWith('#/'))\n return undefined\n let node: unknown = root\n for (const raw of ref.slice(2).split('/')) {\n const part = decodeURIComponent(raw).replace(/~1/g, '/').replace(/~0/g, '~')\n if (!isRecord(node) && !Array.isArray(node))\n return undefined\n node = (node as Record<string, unknown>)[part]\n }\n return typeof node === 'boolean' || isRecord(node) ? node : undefined\n}\n\nconst at = (path: string, key: string | number): string => (path ? `${path}.${key}` : String(key))\nconst prefixed = (path: string, message: string): string => (path ? `${path}: ${message}` : message)\n\ninterface Walk {\n root: JsonSchemaNode\n depth: number\n}\n\nconst MAX_DEPTH = 64\n\nfunction walk(schema: JsonSchemaNode, value: unknown, path: string, w: Walk): string | undefined {\n if (schema === true)\n return undefined\n if (schema === false)\n return prefixed(path, 'no value is allowed here')\n if (w.depth > MAX_DEPTH)\n return prefixed(path, 'the schema nests too deeply')\n const s = schema\n const deeper: Walk = { root: w.root, depth: w.depth + 1 }\n\n if (typeof s.$ref === 'string') {\n const target = resolveRef(w.root, s.$ref)\n if (target === undefined)\n return prefixed(path, `unresolvable $ref \"${s.$ref}\"`)\n const err = walk(target, value, path, deeper)\n if (err)\n return err\n }\n\n if (s.type !== undefined) {\n const types = Array.isArray(s.type) ? s.type.map(String) : [String(s.type)]\n const nullable = s.nullable === true && value === null\n if (!nullable && !types.some(type => matchesType(value, type)))\n return prefixed(path, `expected ${types.join(' or ')}, got ${jsonTypeOf(value)}`)\n }\n if (Array.isArray(s.enum) && !s.enum.some(option => jsonEqual(option, value)))\n return prefixed(path, `expected one of ${JSON.stringify(s.enum)}`)\n if (Object.hasOwn(s, 'const') && !jsonEqual(s.const, value))\n return prefixed(path, `expected ${JSON.stringify(s.const)}`)\n\n if (typeof value === 'number') {\n const err = checkNumber(s, value)\n if (err)\n return prefixed(path, err)\n }\n if (typeof value === 'string') {\n const length = codePoints(value)\n if (typeof s.minLength === 'number' && length < s.minLength)\n return prefixed(path, `must be at least ${s.minLength} characters`)\n if (typeof s.maxLength === 'number' && length > s.maxLength)\n return prefixed(path, `must be at most ${s.maxLength} characters`)\n if (typeof s.pattern === 'string' && !testPattern(s.pattern, value))\n return prefixed(path, `must match ${s.pattern}`)\n }\n if (Array.isArray(value)) {\n const err = checkArray(s, value, path, deeper)\n if (err)\n return err\n }\n if (isRecord(value)) {\n const err = checkObject(s, value, path, deeper)\n if (err)\n return err\n }\n return checkCombinators(s, value, path, deeper)\n}\n\nfunction checkNumber(s: Readonly<Record<string, unknown>>, value: number): string | undefined {\n const exMin = s.exclusiveMinimum\n const exMax = s.exclusiveMaximum\n if (typeof s.minimum === 'number' && (exMin === true ? value <= s.minimum : value < s.minimum))\n return `must be ${exMin === true ? 'greater than' : 'at least'} ${s.minimum}`\n if (typeof s.maximum === 'number' && (exMax === true ? value >= s.maximum : value > s.maximum))\n return `must be ${exMax === true ? 'less than' : 'at most'} ${s.maximum}`\n if (typeof exMin === 'number' && value <= exMin)\n return `must be greater than ${exMin}`\n if (typeof exMax === 'number' && value >= exMax)\n return `must be less than ${exMax}`\n if (typeof s.multipleOf === 'number' && s.multipleOf > 0) {\n const q = value / s.multipleOf\n if (Math.abs(q - Math.round(q)) > 1e-9)\n return `must be a multiple of ${s.multipleOf}`\n }\n return undefined\n}\n\nfunction asNode(value: unknown): JsonSchemaNode | undefined {\n return typeof value === 'boolean' || isRecord(value) ? value : undefined\n}\n\nfunction checkArray(s: Readonly<Record<string, unknown>>, value: readonly unknown[], path: string, w: Walk): string | undefined {\n if (typeof s.minItems === 'number' && value.length < s.minItems)\n return prefixed(path, `must have at least ${s.minItems} items`)\n if (typeof s.maxItems === 'number' && value.length > s.maxItems)\n return prefixed(path, `must have at most ${s.maxItems} items`)\n if (s.uniqueItems === true) {\n for (let i = 0; i < value.length; i++) {\n for (let j = i + 1; j < value.length; j++) {\n if (jsonEqual(value[i], value[j]))\n return prefixed(path, `items ${i} and ${j} are equal`)\n }\n }\n }\n // Tuple: 2020-12 `prefixItems` + `items`, or draft-07 array `items` + `additionalItems`.\n const tuple = Array.isArray(s.prefixItems) ? s.prefixItems : Array.isArray(s.items) ? s.items : undefined\n const rest = Array.isArray(s.prefixItems) ? asNode(s.items) : Array.isArray(s.items) ? asNode(s.additionalItems) : asNode(s.items)\n for (let i = 0; i < value.length; i++) {\n const itemSchema = tuple && i < tuple.length ? asNode(tuple[i]) : rest\n if (itemSchema === undefined)\n continue\n const err = walk(itemSchema, value[i], at(path, i), w)\n if (err)\n return err\n }\n const contains = asNode(s.contains)\n if (contains !== undefined) {\n const hits = value.filter(item => walk(contains, item, '', w) === undefined).length\n const min = typeof s.minContains === 'number' ? s.minContains : 1\n if (hits < min)\n return prefixed(path, min === 1 ? 'no item matches `contains`' : `fewer than ${min} items match \\`contains\\``)\n if (typeof s.maxContains === 'number' && hits > s.maxContains)\n return prefixed(path, `more than ${s.maxContains} items match \\`contains\\``)\n }\n return undefined\n}\n\nfunction checkObject(s: Readonly<Record<string, unknown>>, value: Readonly<Record<string, unknown>>, path: string, w: Walk): string | undefined {\n const keys = Object.keys(value)\n if (Array.isArray(s.required)) {\n for (const key of s.required) {\n if (typeof key === 'string' && !Object.hasOwn(value, key))\n return prefixed(at(path, key), 'is required')\n }\n }\n if (typeof s.minProperties === 'number' && keys.length < s.minProperties)\n return prefixed(path, `must have at least ${s.minProperties} properties`)\n if (typeof s.maxProperties === 'number' && keys.length > s.maxProperties)\n return prefixed(path, `must have at most ${s.maxProperties} properties`)\n const properties = isRecord(s.properties) ? s.properties : {}\n const patterns = isRecord(s.patternProperties) ? Object.entries(s.patternProperties) : []\n const additional = asNode(s.additionalProperties)\n const names = asNode(s.propertyNames)\n for (const key of keys) {\n if (names !== undefined) {\n const err = walk(names, key, '', w)\n if (err)\n return prefixed(at(path, key), `invalid property name: ${err}`)\n }\n let matched = false\n if (Object.hasOwn(properties, key)) {\n matched = true\n const sub = asNode(properties[key])\n const err = sub === undefined ? undefined : walk(sub, value[key], at(path, key), w)\n if (err)\n return err\n }\n for (const [pattern, raw] of patterns) {\n if (!testPattern(pattern, key) || compile(pattern) === null)\n continue\n matched = true\n const sub = asNode(raw)\n const err = sub === undefined ? undefined : walk(sub, value[key], at(path, key), w)\n if (err)\n return err\n }\n if (!matched && additional !== undefined) {\n if (additional === false)\n return prefixed(at(path, key), 'is not allowed')\n const err = walk(additional, value[key], at(path, key), w)\n if (err)\n return err\n }\n }\n return undefined\n}\n\nfunction checkCombinators(s: Readonly<Record<string, unknown>>, value: unknown, path: string, w: Walk): string | undefined {\n const list = (raw: unknown): JsonSchemaNode[] => (Array.isArray(raw) ? raw.map(asNode).filter((n): n is JsonSchemaNode => n !== undefined) : [])\n for (const sub of list(s.allOf)) {\n const err = walk(sub, value, path, w)\n if (err)\n return err\n }\n const anyOf = list(s.anyOf)\n if (anyOf.length > 0) {\n const errors = anyOf.map(sub => walk(sub, value, path, w))\n if (errors.every(Boolean))\n return errors.length === 1 ? errors[0] : prefixed(path, `matches none of anyOf (${errors.map(e => e!).join(' | ')})`)\n }\n const oneOf = list(s.oneOf)\n if (oneOf.length > 0) {\n const errors = oneOf.map(sub => walk(sub, value, path, w))\n const passing = errors.filter(e => e === undefined).length\n if (passing === 0)\n return prefixed(path, `matches none of oneOf (${errors.map(e => e!).join(' | ')})`)\n if (passing > 1)\n return prefixed(path, `matches ${passing} of oneOf, expected exactly one`)\n }\n const not = asNode(s.not)\n if (not !== undefined && walk(not, value, path, w) === undefined)\n return prefixed(path, 'matches a schema it must not match')\n const cond = asNode(s.if)\n if (cond !== undefined) {\n const branch = asNode(walk(cond, value, path, w) === undefined ? s.then : s.else)\n if (branch !== undefined) {\n const err = walk(branch, value, path, w)\n if (err)\n return err\n }\n }\n return undefined\n}\n\n/**\n * Checks `value` against a plain JSON Schema.\n *\n * @param schema - The JSON Schema (an object, or `true`/`false`).\n * @param value - The value to check.\n * @returns The first problem found, as `path: message`, or `undefined` when the value is valid.\n * @example\n * validateJsonSchema({ type: 'object', properties: { name: { type: 'string' } } }, { name: 4 })\n * // 'name: expected string, got number'\n */\nexport function validateJsonSchema(schema: JsonSchemaNode, value: unknown): string | undefined {\n return walk(schema, value, '', { root: schema, depth: 0 })\n}\n","/**\n * Validates RPC inputs, outputs, error data and event data against a\n * {@link Schema}: a Standard Schema (zod, valibot, arktype) through its own\n * `~standard.validate`, or a plain JSON Schema: loosely typed object fields\n * are coerced first (the loop's `validateToolArgs`, `src/tools/validation.ts`),\n * then the value is checked in full (`./json-schema`).\n */\n\nimport type { Schema } from '../api/core'\nimport { validateToolArgs } from '../../tools/validation'\nimport { isStandardSchema } from '../../zod'\nimport { jsonTypeOf, validateJsonSchema } from './json-schema'\n\n/** The outcome of a check. `value` is the validated (possibly transformed or coerced) value. */\nexport type SchemaCheck = { ok: true, value: unknown } | { ok: false, message: string }\n\ninterface StandardIssue { message: string, path?: ReadonlyArray<PropertyKey | { key: PropertyKey }> }\ntype StandardResult = { value: unknown, issues?: undefined } | { issues: readonly StandardIssue[] }\ntype StandardValidate = (value: unknown) => StandardResult | Promise<StandardResult>\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value))\n return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\nfunction formatIssues(issues: readonly StandardIssue[]): string {\n return issues.map((issue) => {\n const path = (issue.path ?? []).map(part => String(typeof part === 'object' ? part.key : part)).join('.')\n return path ? `${path}: ${issue.message}` : issue.message\n }).join('; ')\n}\n\nfunction fromStandard(result: StandardResult): SchemaCheck {\n return result.issues ? { ok: false, message: formatIssues(result.issues) } : { ok: true, value: result.value }\n}\n\n/**\n * Checks `value` against a plain JSON Schema: an object's loosely typed\n * fields (a numeric string for a number) are coerced first, then the whole\n * value is validated (`./json-schema`).\n *\n * @param schema - The JSON Schema.\n * @param value - The value to check.\n * @param opts - `coerceAny`: coerce a value that is not an object too (storage does, RPC does not).\n * @param opts.coerceAny - Coerce a value that is not an object too.\n * @returns The check, with the coerced value when it passes.\n */\nexport function checkJsonSchema(schema: Readonly<Record<string, unknown>>, value: unknown, opts: { coerceAny?: boolean } = {}): SchemaCheck {\n const declared = schema.type\n const types = declared === undefined ? [] : Array.isArray(declared) ? declared.map(String) : [String(declared)]\n const objectLike = types.includes('object') || (types.length === 0 && (schema.properties !== undefined || schema.required !== undefined))\n if (objectLike && types.length === 0 && !isPlainObject(value))\n return { ok: false, message: `expected an object, got ${jsonTypeOf(value)}` }\n const isObject = objectLike && isPlainObject(value)\n const candidate = isObject || opts.coerceAny ? coerceLoosely(schema, value, isObject) : value\n const problem = validateJsonSchema(schema, candidate)\n return problem === undefined ? { ok: true, value: candidate } : { ok: false, message: problem }\n}\n\n/**\n * The value with its unambiguous loose fields coerced, as a tool argument\n * would be. A value is wrapped as the single property of an object when it\n * is not one. Coercion that would drop array items is not taken: the\n * original value is then validated and refused, never silently shortened.\n */\nfunction coerceLoosely(schema: Readonly<Record<string, unknown>>, value: unknown, isObject: boolean): unknown {\n const result = isObject\n ? validateToolArgs(value as Record<string, unknown>, schema as Record<string, unknown>)\n : validateToolArgs({ value }, { type: 'object', properties: { value: schema }, required: ['value'] })\n if (!result.valid || (result.droppedItems && Object.keys(result.droppedItems).length > 0))\n return value\n return isObject ? result.coercedInput ?? value : result.coercedInput?.value\n}\n\n/**\n * Checks `value` against `schema`. With no schema every value passes\n * unchanged. Synchronous unless a Standard Schema validates asynchronously.\n *\n * @param schema - Standard Schema, JSON Schema, or `undefined`.\n * @param value - The value to check.\n * @returns The check, or a promise of it.\n */\nexport function checkSchema(schema: Schema | undefined, value: unknown): SchemaCheck | Promise<SchemaCheck> {\n if (schema === undefined)\n return { ok: true, value }\n if (!isStandardSchema(schema))\n return checkJsonSchema(schema, value)\n const validate = (schema['~standard'] as { validate?: StandardValidate }).validate\n if (typeof validate !== 'function')\n return { ok: false, message: 'the schema has no ~standard.validate' }\n try {\n const result = validate(value)\n return result instanceof Promise\n ? result.then(fromStandard, (error: unknown) => ({ ok: false, message: errorMessage(error) }))\n : fromStandard(result)\n }\n catch (error) {\n return { ok: false, message: errorMessage(error) }\n }\n}\n\n/**\n * Whether `value` is a plain object (`{}` or `Object.create(null)`), as event data must be.\n *\n * @param value - The value to check.\n */\nexport function isPlainRecord(value: unknown): value is Record<string, unknown> {\n return isPlainObject(value)\n}\n\n/**\n * The message of a thrown value.\n *\n * @param error - Anything thrown.\n */\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n","/**\n * Store value validation against either schema kind `ctx.storage.store`\n * accepts: a Standard Schema (through its `~standard.validate`) or a plain\n * JSON Schema (loose fields coerced, then checked in full, as RPC does).\n */\n\nimport type { Schema } from '../api/core'\nimport { isStandardSchema } from '../../zod'\nimport { checkJsonSchema } from '../rpc/schema'\n\n/** The outcome of validating one value. `value` is the parsed (possibly coerced or defaulted) value. */\nexport type StoreValidation\n = | { readonly ok: true, readonly value: unknown }\n | { readonly ok: false, readonly error: string }\n\ninterface StandardIssue { readonly message: string, readonly path?: readonly unknown[] }\ntype StandardResult = { readonly value: unknown, readonly issues?: undefined } | { readonly issues: readonly StandardIssue[] }\ninterface StandardValidator {\n readonly '~standard': { readonly validate: (value: unknown) => StandardResult | Promise<StandardResult> }\n}\n\nfunction issueText(issue: StandardIssue): string {\n const path = issue.path?.map(p => (typeof p === 'object' && p !== null && 'key' in p ? String((p as { key: unknown }).key) : String(p))).join('.')\n return path ? `${path}: ${issue.message}` : issue.message\n}\n\nfunction fromStandard(result: StandardResult): StoreValidation {\n if (result.issues)\n return { ok: false, error: result.issues.map(issueText).join('; ') || 'invalid value' }\n return { ok: true, value: result.value }\n}\n\n/**\n * Validates `value` against `schema`. Synchronous for JSON Schema and for\n * Standard Schemas that validate synchronously (zod without async refinements);\n * a Promise otherwise.\n *\n * A JSON Schema value is coerced as a tool argument would be, then checked\n * in full (`checkJsonSchema`).\n *\n * @param schema - Standard Schema or JSON Schema.\n * @param value - Candidate value.\n */\nexport function validateStoreValue(schema: Schema, value: unknown): StoreValidation | Promise<StoreValidation> {\n if (isStandardSchema(schema)) {\n const validate = (schema as unknown as StandardValidator)['~standard'].validate\n if (typeof validate !== 'function')\n return { ok: false, error: 'schema has no ~standard.validate' }\n let result: StandardResult | Promise<StandardResult>\n try {\n result = validate(value)\n }\n catch (err) {\n return { ok: false, error: err instanceof Error ? err.message : String(err) }\n }\n return result instanceof Promise ? result.then(fromStandard, err => ({ ok: false, error: String(err) })) : fromStandard(result)\n }\n if (value === undefined || value === null)\n return schemaAllowsNull(schema) && value === null ? { ok: true, value } : { ok: false, error: 'value is required' }\n if (schema.type === 'object' || (schema.type === undefined && schema.properties !== undefined)) {\n if (typeof value !== 'object' || Array.isArray(value))\n return { ok: false, error: `expected object, got ${Array.isArray(value) ? 'array' : typeof value}` }\n }\n return fromCheck(checkJsonSchema(schema, value, { coerceAny: true }))\n}\n\nfunction fromCheck(check: ReturnType<typeof checkJsonSchema>): StoreValidation {\n return check.ok ? { ok: true, value: check.value } : { ok: false, error: check.message }\n}\n\nfunction schemaAllowsNull(schema: Readonly<Record<string, unknown>>): boolean {\n const type = schema.type\n return type === 'null' || (Array.isArray(type) && type.includes('null'))\n}\n","/**\n * Typed, versioned stores (`ctx.storage.store`). A store keeps one record\n * `{ v, value }` in the `stores` area of its location. Reads are\n * synchronous; an older record is migrated, validated and written back at\n * the current version; an invalid one yields the initial value.\n */\n\nimport type { Infer, Readable, Schema } from '../api/core'\nimport type { Json, Store, StoreOptions } from '../api/storage'\nimport type { Guard } from '../runtime/deps'\nimport type { LocationState, StorageCache } from './cache'\nimport type { StoreValidation } from './validate'\nimport { deepEqual, frozenCopy, isJson } from './json'\nimport { validateStoreValue } from './validate'\n\n/** A store record as kept by the port. */\ninterface StoreRecord { v: number, value: Json }\n\nfunction isStoreRecord(raw: Json): raw is StoreRecord & Json {\n return typeof raw === 'object' && raw !== null && !Array.isArray(raw)\n && typeof (raw as Record<string, Json>).v === 'number' && 'value' in raw\n}\n\n/** Checks the arguments of `store()` that do not depend on stored data; throws on misuse. */\nexport function checkStoreArgs(name: string, schema: Schema, initial: unknown, version: number): void {\n const label = `storage.store(${JSON.stringify(name)})`\n if (!Number.isInteger(version) || version < 1)\n throw new TypeError(`${label}: version must be an integer >= 1`)\n if (!isJson(initial))\n throw new TypeError(`${label}: initial value is not JSON`)\n const checked = validateStoreValue(schema, initial)\n if (!(checked instanceof Promise) && !checked.ok)\n throw new TypeError(`${label}: initial value is invalid: ${checked.error}`)\n}\n\n/**\n * Creates the store `name` at `state` and registers its decoder. Callers\n * dedupe by location and name and check the arguments first.\n *\n * @param cache - The extension's storage cache.\n * @param guard - Runs `migrate` and listeners with error attribution.\n * @param state - The store's location.\n * @param name - The store name (a safe key).\n * @param schema - Standard Schema or JSON Schema of the value.\n * @param initial - The value when nothing valid is stored.\n * @param opts - Version and migration.\n */\nexport function createStore<S extends Schema>(\n cache: StorageCache,\n guard: Guard,\n state: LocationState,\n name: string,\n schema: S,\n initial: Infer<S>,\n opts: StoreOptions<Infer<S>>,\n): Store<Infer<S>> {\n type T = Infer<S>\n const version = opts.version ?? 1\n const initialValue = frozenCopy(initial as Json) as T\n let current = initialValue\n // Bumped by every decode and set: an async validation that finishes after\n // a newer one started is dropped.\n let seq = 0\n const listeners = new Set<(value: T) => void>()\n\n function setCurrent(next: T): void {\n if (deepEqual(current, next))\n return\n current = next\n for (const listener of [...listeners])\n guard.callSync(`storage.store(${name}).subscribe`, () => listener(next))\n }\n\n function fallback(message: string, attrs: Record<string, unknown> = {}): void {\n cache.logger.warn(`storage: ${message}; using the initial value`, { store: name, ...attrs })\n setCurrent(initialValue)\n }\n\n /** Brings an older record to `version`. `undefined` when `migrate` threw. */\n function upgrade(raw: StoreRecord): { value: unknown } | undefined {\n if (!opts.migrate)\n return { value: raw.value }\n const migrate = opts.migrate\n return guard.callSync(`storage.store(${name}).migrate`, () => ({ value: migrate(raw.value, raw.v) as unknown }))\n }\n\n function decode(raw: Json | undefined): void {\n const mine = ++seq\n if (raw === undefined)\n return setCurrent(initialValue)\n if (!isStoreRecord(raw))\n return fallback('unreadable store record')\n if (raw.v > version)\n return fallback('store was saved by a newer version of the extension', { stored: raw.v, version })\n const upgraded = raw.v < version ? upgrade(raw) : { value: raw.value }\n if (!upgraded)\n return fallback('migration failed')\n const finish = (result: StoreValidation): void => {\n if (mine !== seq)\n return\n if (!result.ok || !isJson(result.value))\n return fallback('stored value is invalid', { error: result.ok ? 'not JSON' : result.error })\n setCurrent(frozenCopy(result.value) as T)\n if (raw.v < version) {\n cache.write(state, 'stores', name, { v: version, value: result.value }, false).catch((err) => {\n cache.logger.warn('storage: could not save the migrated store', { store: name, error: String(err) })\n })\n }\n }\n const checked = validateStoreValue(schema, upgraded.value)\n if (checked instanceof Promise)\n void checked.then(finish)\n else\n finish(checked)\n }\n\n const subscribe = (listener: (value: T) => void): (() => void) => {\n listeners.add(listener)\n return () => void listeners.delete(listener)\n }\n\n const created: Store<T> = {\n get: () => current,\n subscribe,\n set: async (update) => {\n cache.assertLive(`store(${name}).set`)\n const next = typeof update === 'function' ? (update as (value: T) => T)(current) : update\n const checked = await validateStoreValue(schema, next)\n if (!checked.ok)\n throw new TypeError(`storage.store(${JSON.stringify(name)}): invalid value: ${checked.error}`)\n if (!isJson(checked.value))\n throw new TypeError(`storage.store(${JSON.stringify(name)}): value is not JSON`)\n seq++\n setCurrent(frozenCopy(checked.value) as T)\n // On failure `write` restores the previous record and notifies, which\n // decodes it back into `current`.\n await cache.write(state, 'stores', name, { v: version, value: checked.value }, false)\n },\n select: <U>(pick: (value: T) => U): Readable<U> => ({\n get: () => pick(current),\n subscribe: (listener) => {\n let last = pick(current)\n return subscribe((value) => {\n const next = pick(value)\n if (deepEqual(last, next))\n return\n last = next\n listener(next)\n })\n },\n }),\n }\n\n state.storeHandlers.set(name, decode)\n if (state.entries.stores.has(name))\n decode(state.entries.stores.get(name))\n cache.ensureLoaded(state)\n return created\n}\n","/**\n * The extension storage domain (`ctx.storage`): kv data per scope with synchronous\n * reads from a preloaded cache, typed and versioned stores, process memory\n * that survives a reload, and `path` for files.\n *\n * Data in, effects out: persistence and cross-client sync go through a\n * {@link StoragePort}; the domain owns the cache (`./cache`), validation,\n * migrations (`./store`) and change fan-out.\n */\n\nimport type { ExtensionPaths, Infer, Schema } from '../api/core'\nimport type { Json, KeyValue, StorageDomain, StorageScope, Store, StoreOptions } from '../api/storage'\nimport type { DomainDeps } from '../runtime/deps'\nimport type { MemoryRegistry } from './memory'\nimport type { StorageArea, StorageLocation, StoragePort } from './port'\nimport { onTeardown } from '../runtime/owner'\nimport { isSafeRecordKey } from '../shared'\nimport { createStorageCache } from './cache'\nimport { isJson } from './json'\nimport { resolveStoragePath } from './paths'\nimport { locationKey } from './port'\nimport { checkStoreArgs, createStore } from './store'\nimport { validateStoreValue } from './validate'\n\n/** Host data the storage domain needs besides the port. */\nexport interface StorageDomainOptions {\n /** The extension's filesystem locations, for `path`. */\n readonly paths: ExtensionPaths\n /** The extension's own folder: `path` never moves its install files (`./paths`). */\n readonly dir?: string\n /** The process-wide memory shared by every load of the extension. */\n readonly memory: MemoryRegistry\n /** The session the current call runs for; the default of `'session'` scope. */\n readonly currentSessionId?: () => string | undefined\n}\n\n/** What {@link createStorageDomain} returns: `ctx.storage` and the runtime's controls. */\nexport interface StorageRuntime {\n /** The object handed to the extension as `ctx.storage`. */\n readonly storage: StorageDomain\n /**\n * Reads `scope` into the cache so reads are synchronous, after any load in\n * flight. The runtime awaits it for `user` and `project` before setup and\n * for the run's session before each run. Rejects when the port fails.\n */\n preload: (scope: StorageScope, sessionId?: string) => Promise<void>\n /**\n * Checks a write another client wants to make to this extension's\n * storage: for `stores`, a store this extension holds at `loc` under\n * `key` takes only a `{ v, value }` record of its version whose value\n * passes its schema. Resolves with why it is refused, or `undefined`\n * (also for an entry no store of this load holds).\n */\n checkWrite: (loc: StorageLocation, area: StorageArea, key: string, value: Json | undefined) => Promise<string | undefined>\n}\n\nfunction checkKey(key: string, what: string): void {\n if (typeof key !== 'string' || !isSafeRecordKey(key))\n throw new TypeError(`storage.${what}: invalid key ${JSON.stringify(key)}`)\n}\n\n/**\n * Builds the storage domain of one extension. Everything it registers ends\n * with `deps.owner`.\n *\n * @param deps - Extension id, owner, guard and logger.\n * @param port - Where data is kept and how remote changes arrive.\n * @param options - Paths, the process memory registry and the current session.\n */\nexport function createStorageDomain(deps: DomainDeps, port: StoragePort, options: StorageDomainOptions): StorageRuntime {\n const cache = createStorageCache(deps, port, options.currentSessionId)\n const stores = new Map<string, Store<unknown>>()\n const specs = new Map<string, { schema: Schema, version: number }>()\n onTeardown(deps.owner, () => {\n stores.clear()\n specs.clear()\n })\n\n function kv(scope: StorageScope, sessionId?: string): KeyValue {\n cache.assertLive('kv')\n const state = cache.stateFor(cache.resolve(scope, sessionId, 'kv'))\n cache.ensureLoaded(state)\n return {\n ready: async () => {\n if (state.loaded)\n return\n cache.assertLive('kv.ready')\n await cache.load(state, false)\n },\n get: <T extends Json = Json>(key: string) => state.entries.kv.get(key) as T | undefined,\n set: async (key, value) => {\n cache.assertLive('kv.set')\n checkKey(key, 'kv.set')\n if (!isJson(value))\n throw new TypeError(`storage.kv.set: value of ${JSON.stringify(key)} is not JSON`)\n await cache.write(state, 'kv', key, value, true)\n },\n delete: async (key) => {\n cache.assertLive('kv.delete')\n checkKey(key, 'kv.delete')\n await cache.write(state, 'kv', key, undefined, true)\n },\n scan: (prefix = '') => [...state.entries.kv]\n .filter(([key]) => key.startsWith(prefix))\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([key, value]) => ({ key, value })),\n subscribe: (listener) => {\n cache.assertLive('kv.subscribe')\n state.kvListeners.add(listener)\n return { dispose: () => void state.kvListeners.delete(listener) }\n },\n }\n }\n\n function store<S extends Schema>(name: string, schema: S, initial: Infer<S>, opts: StoreOptions<Infer<S>>): Store<Infer<S>> {\n cache.assertLive('store')\n checkKey(name, 'store')\n checkStoreArgs(name, schema, initial, opts.version ?? 1)\n const state = cache.stateFor(cache.resolve(opts.scope, opts.sessionId, 'store'))\n const id = `${locationKey(state.loc)}\\u0000${name}`\n const existing = stores.get(id)\n if (existing)\n return existing as Store<Infer<S>>\n const created = createStore(cache, deps.guard, state, name, schema, initial, opts)\n stores.set(id, created as Store<unknown>)\n specs.set(id, { schema, version: opts.version ?? 1 })\n return created\n }\n\n const storage: StorageDomain = {\n kv,\n store,\n memory: <T>(key: string, init: () => T): T => {\n cache.assertLive('memory')\n if (typeof key !== 'string' || key.length === 0)\n throw new TypeError('storage.memory: key must be a non-empty string')\n return options.memory.getOrInit(deps.extensionId, key, init)\n },\n path: (scope, ...segments) => resolveStoragePath({\n paths: options.paths,\n extensionId: deps.extensionId,\n ...(port.folderOf ? { folderOf: port.folderOf } : {}),\n ...(options.dir !== undefined ? { dir: options.dir } : {}),\n logger: deps.logger,\n }, scope, ...segments),\n }\n\n return {\n storage,\n preload: (scope, sessionId) => {\n cache.assertLive('preload')\n return cache.load(cache.stateFor(cache.resolve(scope, sessionId, 'preload')), true)\n },\n checkWrite: async (loc, area, key, value) => {\n if (area !== 'stores' || value === undefined || loc.extensionId !== deps.extensionId)\n return undefined\n const spec = specs.get(`${locationKey(loc)}\\u0000${key}`)\n if (!spec)\n return undefined\n const record = value as { v?: unknown, value?: unknown }\n if (!record || typeof record !== 'object' || Array.isArray(record) || !Number.isInteger(record.v) || !('value' in record))\n return `store \"${key}\" takes a { v, value } record`\n if (record.v !== spec.version)\n return `store \"${key}\" is at version ${spec.version}, the write is for version ${String(record.v)}`\n const checked = await validateStoreValue(spec.schema, record.value)\n return checked.ok ? undefined : `store \"${key}\": invalid value: ${checked.error}`\n },\n }\n}\n","/**\n * The default {@link StoragePort}: one JSON file per extension, scope and\n * session, written atomically (`src/atomic-write.ts`).\n *\n * Layout, with `base` the `root` for `user` and `projectRoot ?? root` for\n * `project` and `session` (the same split `storage.path` uses):\n *\n * <base>/<extension>/user.json\n * <base>/<extension>/project.json\n * <base>/<extension>/sessions/<sessionId>.json\n *\n * `storage.path` files go in `<base>/<extension>/files` (`folderOf`, `./paths`).\n *\n * Each file is `{ \"version\": 1, \"kv\": {…}, \"stores\": {…} }`. Changes made\n * by other processes are found by re-reading a file (on a directory watch\n * event, or an explicit {@link FileStoragePort.refresh}) and diffing it\n * against the last good read. A file that does not parse is a write still\n * in progress: it is skipped until a later read parses (\"not yet\"), and a\n * save in the meantime builds on the last good read.\n */\n\nimport type { FSWatcher } from 'node:fs'\nimport type { Logger } from '../../logger'\nimport type { Disposable } from '../api/core'\nimport type { Json } from '../api/storage'\nimport type { StorageArea, StorageChange, StorageLocation, StoragePort, StorageSnapshot } from './port'\nimport { mkdirSync, readFileSync, watch } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport { OWNER_ONLY, writeJsonFileAtomic } from '../../atomic-write'\nimport { isSafeRecordKey } from '../shared'\nimport { deepEqual, isJson } from './json'\n\n/** Options of {@link createFileStoragePort}. */\nexport interface FileStoragePortOptions {\n /** Folder for `user` scope files (and the others when `projectRoot` is unset). */\n readonly root: string\n /** Folder for `project` and `session` scope files. */\n readonly projectRoot?: string\n /** Watch the folders for changes by other processes. Default `true`. */\n readonly watch?: boolean\n /** Receives watch and parse problems. */\n readonly logger?: Logger\n}\n\n/** A file-backed {@link StoragePort} with explicit refresh and shutdown. */\nexport interface FileStoragePort extends StoragePort {\n /** Re-reads the files of `loc` (all known files when omitted) and reports what others changed. */\n refresh: (loc?: StorageLocation) => void\n /** The file that holds `loc`. */\n fileOf: (loc: StorageLocation) => string\n /** The folder of one extension's data in `scope`. */\n folderOf: (extensionId: string, scope: 'user' | 'project') => string\n /** Stops the watchers and drops every listener. */\n close: () => void\n}\n\ninterface FileEntry {\n readonly path: string\n /** The last good read, or what this port last wrote. */\n snapshot?: StorageSnapshot\n readonly listeners: Set<(change: StorageChange) => void>\n}\n\nconst EMPTY: StorageSnapshot = Object.freeze({ kv: Object.freeze({}), stores: Object.freeze({}) })\nconst AREAS: readonly StorageArea[] = ['kv', 'stores']\n\n/** A single path segment from an id: encoded, and never `.` or `..`. */\nfunction segment(value: string, what: string): string {\n if (typeof value !== 'string' || value.length === 0)\n throw new TypeError(`file storage: empty ${what}`)\n const encoded = encodeURIComponent(value)\n if (encoded === '.' || encoded === '..')\n throw new TypeError(`file storage: invalid ${what} ${JSON.stringify(value)}`)\n return encoded\n}\n\nfunction cleanArea(raw: unknown): Record<string, Json> {\n const out: Record<string, Json> = Object.create(null)\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw))\n return out\n for (const [key, value] of Object.entries(raw)) {\n if (isSafeRecordKey(key) && isJson(value))\n out[key] = value\n }\n return out\n}\n\n/**\n * Reads a storage file. A missing file is empty. `undefined` means the file\n * is there but does not parse yet (a write in progress).\n */\nfunction readSnapshot(path: string): StorageSnapshot | undefined {\n let text: string\n try {\n text = readFileSync(path, 'utf8')\n }\n catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT')\n return EMPTY\n throw err\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n }\n catch {\n return undefined\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))\n return undefined\n const record = parsed as Record<string, unknown>\n return { kv: cleanArea(record.kv), stores: cleanArea(record.stores) }\n}\n\n/**\n * Makes the default file-backed storage port.\n *\n * @param options - Where the files go and whether to watch them.\n */\nexport function createFileStoragePort(options: FileStoragePortOptions): FileStoragePort {\n const entries = new Map<string, FileEntry>()\n const watchers = new Map<string, FSWatcher>()\n const shouldWatch = options.watch ?? true\n\n function fileOf(loc: StorageLocation): string {\n const ext = segment(loc.extensionId, 'extension id')\n if (loc.scope === 'user')\n return join(options.root, ext, 'user.json')\n const base = options.projectRoot ?? options.root\n if (loc.scope === 'project')\n return join(base, ext, 'project.json')\n return join(base, ext, 'sessions', `${segment(loc.sessionId ?? '', 'session id')}.json`)\n }\n\n function entryOf(loc: StorageLocation): FileEntry {\n const path = fileOf(loc)\n let entry = entries.get(path)\n if (!entry) {\n entry = { path, listeners: new Set() }\n entries.set(path, entry)\n }\n return entry\n }\n\n /** Re-reads one file and reports the differences from the last good read. */\n function refreshEntry(entry: FileEntry): void {\n const next = readSnapshot(entry.path)\n if (!next)\n return\n // With no good read yet, report everything; the domain drops what it already holds.\n const previous = entry.snapshot ?? EMPTY\n entry.snapshot = next\n for (const area of AREAS) {\n const keys = new Set([...Object.keys(previous[area]), ...Object.keys(next[area])])\n for (const key of keys) {\n const value = next[area][key]\n if (deepEqual(previous[area][key], value))\n continue\n for (const listener of [...entry.listeners]) {\n try {\n listener({ area, key, value })\n }\n catch (err) {\n options.logger?.warn('file storage: listener threw', { error: String(err) })\n }\n }\n }\n }\n }\n\n function watchDir(dir: string): void {\n if (!shouldWatch || watchers.has(dir))\n return\n try {\n mkdirSync(dir, { recursive: true })\n const watcher = watch(dir, (_event, filename) => {\n for (const entry of entries.values()) {\n if (dirname(entry.path) !== dir || (filename && basename(entry.path) !== String(filename)))\n continue\n try {\n refreshEntry(entry)\n }\n catch (err) {\n options.logger?.warn('file storage: cannot read', { path: entry.path, error: String(err) })\n }\n }\n })\n watcher.on('error', (err) => {\n options.logger?.warn('file storage: watcher stopped', { dir, error: String(err) })\n watcher.close()\n watchers.delete(dir)\n })\n watchers.set(dir, watcher)\n }\n catch (err) {\n options.logger?.warn('file storage: cannot watch', { dir, error: String(err) })\n }\n }\n\n function update(loc: StorageLocation, area: StorageArea, key: string, value: Json | undefined): void {\n if (!isSafeRecordKey(key))\n throw new TypeError(`file storage: invalid key ${JSON.stringify(key)}`)\n const entry = entryOf(loc)\n // Pick up others' changes first (and report them), so this write keeps them.\n // Not a lock: another process writing between this read and the rename loses its change.\n refreshEntry(entry)\n const base = entry.snapshot ?? EMPTY\n if (value === undefined && !Object.hasOwn(base[area], key))\n return\n const changed: Record<string, Json> = { ...base[area] }\n if (value === undefined)\n delete changed[key]\n else\n changed[key] = value\n const next: StorageSnapshot = { ...base, [area]: changed }\n writeJsonFileAtomic(entry.path, { version: 1, kv: next.kv, stores: next.stores }, OWNER_ONLY)\n entry.snapshot = next\n }\n\n return {\n fileOf,\n folderOf: (extensionId, scope) => dirname(fileOf({ extensionId, scope })),\n load: async (loc) => {\n const entry = entryOf(loc)\n const next = readSnapshot(entry.path)\n if (next)\n entry.snapshot = next\n return entry.snapshot ?? EMPTY\n },\n save: async (loc, area, key, value) => update(loc, area, key, value),\n delete: async (loc, area, key) => update(loc, area, key, undefined),\n subscribe: (loc, listener): Disposable => {\n const entry = entryOf(loc)\n if (!entry.snapshot)\n entry.snapshot = readSnapshot(entry.path)\n entry.listeners.add(listener)\n watchDir(dirname(entry.path))\n return { dispose: () => void entry.listeners.delete(listener) }\n },\n refresh: (loc) => {\n if (loc) {\n refreshEntry(entryOf(loc))\n return\n }\n for (const entry of entries.values())\n refreshEntry(entry)\n },\n close: () => {\n for (const watcher of watchers.values())\n watcher.close()\n watchers.clear()\n for (const entry of entries.values())\n entry.listeners.clear()\n },\n }\n}\n","/**\n * `ctx.storage.memory`: values kept in the process, keyed by extension id,\n * so they outlive a reload of the extension (a new domain for the same id)\n * but not a restart.\n */\n\n/** In-process values shared by every load of an extension. */\nexport interface MemoryRegistry {\n /** The value of `key` for `extensionId`, created with `init` on first use. */\n getOrInit: <T>(extensionId: string, key: string, init: () => T) => T\n /** Forgets every value of `extensionId` (on uninstall or disable). */\n clear: (extensionId: string) => void\n}\n\n/** Makes an empty {@link MemoryRegistry}. A host keeps one for the life of the process. */\nexport function createMemoryRegistry(): MemoryRegistry {\n const byExtension = new Map<string, Map<string, unknown>>()\n return {\n getOrInit<T>(extensionId: string, key: string, init: () => T): T {\n let values = byExtension.get(extensionId)\n if (values?.has(key))\n return values.get(key) as T\n const value = init()\n if (!values) {\n values = new Map()\n byExtension.set(extensionId, values)\n }\n values.set(key, value)\n return value\n },\n clear(extensionId) {\n byExtension.delete(extensionId)\n },\n }\n}\n","/**\n * The extension storage domain: `ctx.storage` and its host port.\n */\n\nexport { createStorageDomain } from './domain'\nexport type { StorageDomainOptions, StorageRuntime } from './domain'\nexport { createFileStoragePort } from './file-port'\nexport type { FileStoragePort, FileStoragePortOptions } from './file-port'\nexport { deepEqual, frozenCopy, isJson } from './json'\nexport { createMemoryRegistry } from './memory'\nexport type { MemoryRegistry } from './memory'\nexport { legacyStoragePath, resolveStoragePath, storagePathRoot } from './paths'\nexport type { StorageFolderOf, StoragePathOptions } from './paths'\nexport { locationKey } from './port'\nexport type { StorageArea, StorageChange, StorageLocation, StoragePort, StorageSnapshot } from './port'\nexport { validateStoreValue } from './validate'\nexport type { StoreValidation } from './validate'\n","/**\n * In-memory host ports for the extension runtime (extension API). The runtime\n * falls back to them for every port a host leaves out, and the testing kit\n * (`src/extensions/testing`) drives them directly. Nothing here touches the\n * disk, the network or a window.\n */\n\nimport type { Json } from '../api/storage'\nimport type { McpCatalogPort } from '../catalog'\nimport type { IntegrationFlowPort } from '../integrations'\nimport type { SettingsLayer, SettingsPort } from '../settings'\nimport type { StorageChange, StorageLocation, StoragePort, StorageSnapshot } from '../storage'\nimport type { DialogPort, DialogRequest, DialogShowContext, UiClientInfo, UiClientPort } from '../ui'\nimport { locationKey } from '../storage'\n\n/** An in-memory {@link StoragePort} with a way to simulate another client's write. */\nexport interface MemoryStoragePort extends StoragePort {\n /** What is stored at `loc` now (a copy). */\n snapshot: (loc: StorageLocation) => StorageSnapshot\n /** Another client wrote: stores the change and tells every subscriber of `loc`. */\n remote: (loc: StorageLocation, change: StorageChange) => void\n}\n\n/**\n * An in-memory storage port. Every save and delete is announced to every\n * subscriber of the location, so two caches in one process stay in sync\n * (the domain drops echoes of its own writes).\n *\n * @returns The port.\n */\nexport function createMemoryStoragePort(): MemoryStoragePort {\n const data = new Map<string, { kv: Record<string, Json>, stores: Record<string, Json> }>()\n const listeners = new Map<string, Set<(change: StorageChange) => void>>()\n const slot = (loc: StorageLocation) => {\n const key = locationKey(loc)\n let entry = data.get(key)\n if (!entry) {\n entry = { kv: {}, stores: {} }\n data.set(key, entry)\n }\n return entry\n }\n const announce = (loc: StorageLocation, change: StorageChange): void => {\n for (const listener of [...listeners.get(locationKey(loc)) ?? []]) {\n try {\n listener(change)\n }\n catch {}\n }\n }\n const apply = (loc: StorageLocation, change: StorageChange): void => {\n const entry = slot(loc)\n if (change.value === undefined)\n delete entry[change.area][change.key]\n else\n entry[change.area][change.key] = structuredClone(change.value) as Json\n announce(loc, change)\n }\n return {\n load: async loc => structuredClone(slot(loc)) as StorageSnapshot,\n save: async (loc, area, key, value) => apply(loc, { area, key, value }),\n delete: async (loc, area, key) => apply(loc, { area, key, value: undefined }),\n subscribe: (loc, listener) => {\n const key = locationKey(loc)\n let set = listeners.get(key)\n if (!set) {\n set = new Set()\n listeners.set(key, set)\n }\n set.add(listener)\n return { dispose: () => void set.delete(listener) }\n },\n snapshot: loc => structuredClone(slot(loc)) as StorageSnapshot,\n remote: apply,\n }\n}\n\n/** An in-memory {@link SettingsPort} whose layers can be set from outside. */\nexport interface MemorySettingsPort extends SettingsPort {\n /** Replaces one layer of an extension (a config edit, another window) and notifies its listeners. */\n put: (extensionId: string, layer: SettingsLayer, values: Readonly<Record<string, unknown>>, sessionId?: string) => void\n}\n\n/**\n * An in-memory settings port.\n *\n * @param initial - Starting values: `{ [extensionId]: { [key]: value } }`, put in the `user` layer.\n * @returns The port.\n */\nexport function createMemorySettingsPort(initial: Readonly<Record<string, Readonly<Record<string, unknown>>>> = {}): MemorySettingsPort {\n const layers = new Map<string, Record<string, unknown>>()\n const secrets = new Map<string, string>()\n const listeners = new Map<string, Set<() => void>>()\n const id = (ext: string, layer: SettingsLayer, sessionId?: string) => `${ext}\\u0000${layer}\\u0000${sessionId ?? ''}`\n const notify = (ext: string): void => {\n for (const listener of [...listeners.get(ext) ?? []]) {\n try {\n listener()\n }\n catch {}\n }\n }\n for (const [ext, values] of Object.entries(initial))\n layers.set(id(ext, 'user'), { ...values })\n return {\n read: (ext, layer, sessionId) => layers.get(id(ext, layer, sessionId)),\n write(ext, scope, key, value, sessionId) {\n const k = id(ext, scope, sessionId)\n const bag = { ...layers.get(k) }\n if (value === undefined)\n delete bag[key]\n else\n bag[key] = value\n layers.set(k, bag)\n notify(ext)\n },\n subscribe(ext, listener) {\n let set = listeners.get(ext)\n if (!set) {\n set = new Set()\n listeners.set(ext, set)\n }\n set.add(listener)\n return () => set.delete(listener)\n },\n secrets: {\n get: (ext, key) => secrets.get(`${ext}\\u0000${key}`),\n set(ext, key, value) {\n if (value === undefined)\n secrets.delete(`${ext}\\u0000${key}`)\n else\n secrets.set(`${ext}\\u0000${key}`, value)\n notify(ext)\n },\n },\n put(ext, layer, values, sessionId) {\n layers.set(id(ext, layer, sessionId), { ...values })\n notify(ext)\n },\n }\n}\n\n/** A scripted answer for one dialog: a value, or a function of the request. */\nexport type DialogAnswer = unknown | ((request: DialogRequest, ctx: DialogShowContext) => unknown)\n\n/** A {@link DialogPort} with one client that answers from a script. */\nexport interface ScriptedDialogPort extends DialogPort {\n /** Queues an answer for the next dialog of `kind`. Unanswered dialogs resolve `undefined`. */\n answer: (kind: DialogRequest['kind'], answer: DialogAnswer) => void\n /** Every dialog shown, oldest first. */\n readonly shown: readonly { request: DialogRequest, extensionId: string, sessionId?: string }[]\n}\n\n/** The client id {@link createScriptedDialogPort} and {@link createRecordingUiClientPort} report. */\nexport const MEMORY_CLIENT_ID = 'memory'\n\n/**\n * A dialog port with one client that answers from queued answers.\n *\n * @param client - The client it reports. Default: one client viewing nothing.\n * @returns The port.\n */\nexport function createScriptedDialogPort(client: UiClientInfo = { id: MEMORY_CLIENT_ID, viewing: [], lastActiveAt: 0 }): ScriptedDialogPort {\n const queues = new Map<DialogRequest['kind'], DialogAnswer[]>()\n const shown: { request: DialogRequest, extensionId: string, sessionId?: string }[] = []\n return {\n clients: () => [client],\n show: async (_clientId, request, ctx) => {\n shown.push({ request, extensionId: ctx.extensionId, ...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}) })\n const answer = queues.get(request.kind)?.shift()\n return typeof answer === 'function' ? (answer as (r: DialogRequest, c: DialogShowContext) => unknown)(request, ctx) : answer\n },\n answer: (kind, answer) => {\n let queue = queues.get(kind)\n if (!queue) {\n queue = []\n queues.set(kind, queue)\n }\n queue.push(answer)\n },\n shown,\n }\n}\n\n/** A dialog port with no client: every dialog rejects with `NoUiError`, toasts resolve `undefined`. */\nexport const NO_CLIENT_DIALOG_PORT: DialogPort = {\n clients: () => [],\n show: async () => undefined,\n}\n\n/** One call a {@link RecordingUiClientPort} received. */\nexport interface UiClientCall {\n /** The port method called. */\n method: keyof UiClientPort\n /** The client the call targeted. */\n clientId: string\n /** The arguments after `clientId`. */\n args: readonly unknown[]\n}\n\n/** A {@link UiClientPort} that records calls and reports success. */\nexport interface RecordingUiClientPort extends UiClientPort {\n /** Every call, oldest first. */\n readonly calls: readonly UiClientCall[]\n}\n\n/**\n * A client port that records each call. Panel, navigate, composer and\n * keymap dispatch calls resolve `true`; `panelState` resolves the panels\n * opened so far.\n *\n * @returns The port.\n */\nexport function createRecordingUiClientPort(): RecordingUiClientPort {\n const calls: UiClientCall[] = []\n const open = new Set<string>()\n return {\n calls,\n panel: async (clientId, request) => {\n calls.push({ method: 'panel', clientId, args: [request] })\n if (request.action === 'open' || (request.action === 'toggle' && !open.has(request.panelId)))\n open.add(request.panelId)\n else\n open.delete(request.panelId)\n return true\n },\n panelState: async (clientId, opts) => {\n calls.push({ method: 'panelState', clientId, args: [opts] })\n return [...open]\n },\n navigate: async (clientId, to) => {\n calls.push({ method: 'navigate', clientId, args: [to] })\n return true\n },\n composer: async (clientId, op, opts) => {\n calls.push({ method: 'composer', clientId, args: [op, opts] })\n return true\n },\n notify: (clientId, notification) => {\n calls.push({ method: 'notify', clientId, args: [notification] })\n },\n keymapDispatch: async (clientId, request) => {\n calls.push({ method: 'keymapDispatch', clientId, args: [request] })\n return true\n },\n }\n}\n\n/** A client port for hosts without clients. Never called: the router finds no client first. */\nexport const NO_UI_CLIENT_PORT: UiClientPort = {\n panel: async () => false,\n panelState: async () => [],\n navigate: async () => false,\n composer: async () => false,\n notify: () => {},\n}\n\n/** An MCP port with no servers. Calls reject. */\nexport const EMPTY_MCP_PORT: McpCatalogPort = {\n servers: () => [],\n status: () => [],\n call: async server => Promise.reject(new Error(`MCP server \"${server}\" is not connected in this host`)),\n}\n\n/** An integration flow port for hosts that cannot show a sign-in flow. */\nexport const NO_INTEGRATION_FLOWS: IntegrationFlowPort = {\n oauthCallbacks: () => {\n throw new Error('Signing in is not available in this host')\n },\n runCommand: async () => Promise.reject(new Error('Running a sign-in command is not available in this host')),\n}\n","/**\n * One runtime's extension settings in the wire format Settings UIs draw:\n * each extension's schema (live values while active, the definition's\n * schema otherwise) with its `SettingsPage` items (`ctx.add(SettingsPage)`)\n * appended to its pages, merged in load order. Every host builds its\n * `extensions.settings` answer from it, and refetches it on\n * {@link onSettingsPagesChanged}.\n */\n\nimport type { WireSettings } from '../settings'\nimport type { UiChange, UiRegistry } from '../ui/registry'\nimport type { RuntimeExtension } from './host'\nimport { mergeWireSettings, settingsForDefinition, toWireSettings, wireExtension } from '../settings'\nimport { wireWithSettingsPages } from '../ui/settings-form'\n\n/** The live wire with its implicit page labelled with the extension's name, as `toWireSettings` labels it from the definition. */\nfunction named(wire: WireSettings, displayName: string): WireSettings {\n return wire.pages?.some(page => page.implicit) ? { ...wire, pages: wire.pages.map(page => page.implicit ? { ...page, label: displayName } : page) } : wire\n}\n\n/**\n * One extension's settings wire with its settings pages, or `undefined`\n * when it has no definition (failed validation) and no page.\n *\n * @param r - The extension (`runtime.get(id)`).\n * @param ui - The runtime's UI registry (`runtime.outputs.ui`).\n * @param opts - `sessionId` adds that session's layer to live values.\n * @param opts.sessionId - The session whose values to read.\n */\nexport function extensionSettingsWire(r: Pick<RuntimeExtension, 'id' | 'definition' | 'info' | 'settings'>, ui: Pick<UiRegistry, 'list'>, opts: { sessionId?: string } = {}): WireSettings | undefined {\n const own = r.settings\n ? named(r.settings.wire(opts.sessionId ? { sessionId: opts.sessionId } : {}), r.info.displayName)\n : r.definition\n ? toWireSettings(r.id, settingsForDefinition(r.definition).schema, {}, { displayName: r.info.displayName })\n : undefined\n const paged = wireWithSettingsPages(own ?? mergeWireSettings([]), r.id, ui)\n if (!own && (paged.pages?.length ?? 0) === 0)\n return undefined\n // Its name and icon (the definition's, else its manifest's) and its description, whichever way the wire was built.\n const icon = r.definition?.icon ?? r.info.icon\n return { ...paged, extensions: { ...paged.extensions, [r.id]: wireExtension(r.id, r.info.displayName, icon, r.definition?.description) } }\n}\n\n/**\n * Every extension's settings wire of a runtime, merged in load order.\n *\n * @param runtime - The runtime: its extensions and UI registry.\n * @param runtime.extensions - Every known extension, in load order.\n * @param runtime.get - One extension's state.\n * @param runtime.outputs - Holds the UI registry.\n * @param runtime.outputs.ui - The UI registry with the settings-page items.\n * @param opts - `sessionId` adds that session's layer to live values.\n * @param opts.sessionId - The session whose values to read.\n */\nexport function runtimeSettingsWire(\n runtime: { extensions: () => readonly { id: string }[], get: (id: string) => Pick<RuntimeExtension, 'id' | 'definition' | 'info' | 'settings'> | undefined, outputs: { ui: Pick<UiRegistry, 'list'> } },\n opts: { sessionId?: string } = {},\n): WireSettings {\n return mergeWireSettings(runtime.extensions().flatMap((info) => {\n const r = runtime.get(info.id)\n const wire = r ? extensionSettingsWire(r, runtime.outputs.ui, opts) : undefined\n return wire ? [wire] : []\n }))\n}\n\n/**\n * Whether a UI change adds, replaces or removes a settings page (`reset`:\n * every item may have gone).\n *\n * @param change - A UI registry change, or a protocol `reset`.\n */\nexport function touchesSettingsPages(change: UiChange | { type: 'reset' }): boolean {\n if (change.type === 'reset')\n return true\n if (change.type === 'upsert')\n return change.entry.token === 'settings-page'\n return change.type === 'remove' && change.token === 'settings-page'\n}\n\n/**\n * Calls `listener` each time a settings page of `ui` is added, replaced or\n * removed: the settings wire changed, read it again. Protocol clients\n * follow the same `extensions:ui` changes (`ExtensionsClient.settings.onChange`).\n *\n * @param ui - The registry (`runtime.outputs.ui`).\n * @param listener - Called once per change.\n * @returns The unsubscribe.\n */\nexport function onSettingsPagesChanged(ui: Pick<UiRegistry, 'subscribe'>, listener: () => void): () => void {\n return ui.subscribe((change) => {\n if (touchesSettingsPages(change))\n listener()\n })\n}\n","/**\n * Bindable fields: a UI item field may hold a fixed value or a\n * {@link Readable}. The registry reads every bound field when it serializes\n * the item, and subscribes to it so a change re-pushes the item.\n */\n\nimport type { Bindable, Readable } from '../api/core'\n\n/**\n * Whether `value` is a {@link Readable}: an object with `get` and\n * `subscribe` functions.\n *\n * @param value - Any field value of a UI item.\n */\nexport function isReadable(value: unknown): value is Readable<unknown> {\n return !!value\n && typeof value === 'object'\n && typeof (value as Readable<unknown>).get === 'function'\n && typeof (value as Readable<unknown>).subscribe === 'function'\n}\n\n/** An item with every {@link Bindable} field replaced by its value type. */\nexport type Resolved<T> = { [K in keyof T]: T[K] extends Bindable<infer U> ? U : T[K] }\n\n/**\n * A shallow copy of `item` with each top-level {@link Readable} field read.\n *\n * @param item - The item as the extension gave it.\n * @param read - Reads one readable (the registry runs it through the guard).\n */\nexport function resolveBindables<T extends object>(item: T, read: (readable: Readable<unknown>) => unknown): Resolved<T> {\n const out: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(item))\n out[key] = isReadable(value) ? read(value) : value\n return out as Resolved<T>\n}\n\n/**\n * The distinct readables among the top-level fields of `item`.\n *\n * @param item - The item as the extension gave it.\n */\nexport function readablesOf(item: object): Readable<unknown>[] {\n const out = new Set<Readable<unknown>>()\n for (const value of Object.values(item)) {\n if (isReadable(value))\n out.add(value)\n }\n return [...out]\n}\n","/**\n * The backend side of UI items: the extension functions hosts invoke by an\n * item's id (panel `load` / `onAction`, reference `resolve`, badge\n * actions, context sections, settings actions, link handlers), each run\n * through the owning extension's guard, and the composer provider lists.\n */\n\nimport type { ContextBreakdownContributionContext, ContextBreakdownContributor, ContextExtensionRow, ContextExtensionSection } from '../../chat/context-breakdown'\nimport type { JsonValue } from '../../types'\nimport type { AccessScope, Disposable } from '../api/core'\nimport type { ActionSetting, ActionSettingContext, ActionSettingResult, ActionSettingStatus, SettingsSchema } from '../api/settings'\nimport type { ContextSectionItem, LinkHandlerItem, LinkSource, PanelItem, SettingsPageItem } from '../api/ui'\nimport type { BadgeActionEffect, BadgeMenuItem, BadgeTarget, ExtensionBadgeActions } from '../badge-actions'\nimport type { PanelContent } from '../panels'\nimport type { DomainDeps } from '../runtime/deps'\nimport type { ExtensionOrderedContribution, ExtensionReferenceProvider, ExtensionReferenceView } from '../types'\nimport { DisposedError } from '../api/core'\nimport { badgeMenu, runBadgeAction } from '../badge-actions'\nimport { normalizePanelContent, normalizePanelLoadContext, resolvePanelLoadContext } from '../panels'\nimport { createReferenceResolver } from '../references'\nimport { actionScope } from '../settings/validate'\nimport { checkSettingsValues } from './settings-form'\n\n/** An item with what is needed to call into it: its extension's deps and the item as given. */\nexport interface UiSource {\n readonly extension: string\n readonly deps: DomainDeps\n readonly raw: object\n}\n\n/** Finds the live items of a token (in order, first of each id winning where that applies). */\nexport interface UiSourceLookup {\n /** The item of `token` whose wire id is `id`. */\n byId: (token: 'panel' | 'settings-page', id: string) => UiSource | undefined\n /** Every item of `token`, in order. */\n all: (token: 'reference' | 'badge-action' | 'context-section' | 'link-handler') => readonly UiSource[]\n /** A number that changes whenever the reference providers change. */\n referencesVersion: () => number\n /** The extension's own settings, for a settings-page action's `get` / `set`. Without it `get` reads nothing and `set` rejects. */\n settingsAccess?: (extensionId: string) => Omit<ActionSettingContext, 'signal'> | undefined\n /**\n * The action rows of an extension's own settings (its definition's schema), for a `setting.action` whose\n * page id is the extension's id, as the settings sidebar sends it. `undefined`: no such action.\n */\n ownActions?: (extensionId: string) => OwnSettingActions | undefined\n}\n\n/** An extension's own settings actions, as {@link UiSourceLookup.ownActions} gives them. */\nexport interface OwnSettingActions {\n /** Runs it; `undefined` when the extension has no action `key`. */\n run: (key: string, signal: AbortSignal) => Promise<ActionSettingResult | undefined>\n /** Its live status, when it has one. */\n status: (key: string) => Promise<ActionSettingStatus | undefined>\n /** The least token scope a remote client needs; `undefined` when there is no such action. */\n scope: (key: string) => AccessScope | undefined\n}\n\n/** Settings access for an extension the lookup has no settings for. */\nfunction noSettingsAccess(extensionId: string): Omit<ActionSettingContext, 'signal'> {\n return {\n get: () => undefined,\n set: async key => Promise.reject(new Error(`setting \"${key}\": \"${extensionId}\" has no settings in this host`)),\n }\n}\n\n/** The registry's callback methods (see {@link UiRegistry}). */\nexport interface UiCallbacks {\n loadPanel: (panelId: string, context: unknown, cwd: string) => Promise<PanelContent>\n panelAction: (panelId: string, actionId: string, payload: JsonValue | undefined, context: unknown, cwd: string) => Promise<boolean>\n resolveReference: (providerId: string, key: string) => Promise<ExtensionReferenceView | null>\n badgeMenu: (target: BadgeTarget) => BadgeMenuItem[]\n runBadgeAction: (source: string, actionId: string, target: BadgeTarget, ctx?: { sessionId?: string, cwd?: string }) => Promise<BadgeActionEffect>\n contextContributors: (placement: 'breakdown' | 'panel') => readonly ContextBreakdownContributor[]\n runSettingAction: (pageId: string, settingKey: string, signal: AbortSignal) => Promise<ActionSettingResult | undefined>\n settingStatus: (pageId: string, settingKey: string) => Promise<ActionSettingStatus | undefined>\n validateSetting: (pageId: string, settingKey: string, value: unknown) => string | undefined\n /** The least token scope a remote client needs to run a settings-page action (`ActionSetting.scope`, default `'admin'`); `undefined` when there is no such action. */\n settingActionScope: (pageId: string, settingKey: string) => AccessScope | undefined\n /**\n * Offers a link to the link handlers whose `match` takes it, higher\n * `priority` first (registration order among equals). A handler that\n * returns `false`, throws or times out passes it to the next.\n * `handled: false`: none took it, the app opens it its own way.\n */\n openLink: (request: LinkOpenRequest) => Promise<{ handled: boolean }>\n}\n\n/** A link to open, as hosts pass it to {@link UiCallbacks.openLink}. */\nexport interface LinkOpenRequest {\n /** The link as clicked. */\n url: string\n /** The session it was clicked in. */\n sessionId?: string\n /** Where it was clicked. Default `'other'`. */\n source?: LinkSource\n}\n\n/** Every {@link LinkSource}. */\nexport const LINK_SOURCES: readonly LinkSource[] = ['transcript', 'chip', 'panel', 'badge', 'terminal', 'other']\n\n/** Longest URL a link handler is offered. */\nexport const MAX_LINK_URL_LENGTH = 8192\n\n/** Whether a link handler's `match` takes `url`. A throwing test counts as no match (and against the extension). */\nfunction linkMatches(s: UiSource, url: string): boolean {\n const { match } = s.raw as LinkHandlerItem\n if (typeof match === 'string')\n return url.startsWith(match)\n if (match instanceof RegExp) {\n match.lastIndex = 0\n return match.test(url)\n }\n return typeof match === 'function' && s.deps.guard.callSync('ui.link.match', () => match(url), { fallback: false }) === true\n}\n\nconst THROWN: unique symbol = Symbol('thrown')\n\n/** Runs `fn` through the guard, but turns a throw back into a throw (callers that must not cache failures). */\nasync function callOrThrow<T>(deps: DomainDeps, label: string, fn: () => T | Promise<T>, timeoutMs: number, message: string): Promise<T> {\n const result = await deps.guard.call<T | typeof THROWN>(label, fn, { timeoutMs, fallback: THROWN })\n if (result === THROWN)\n throw new Error(message)\n return result as T\n}\n\n/**\n * A contributor for a panel context section: static or computed\n * rows, plus `load`.\n *\n * @param section - The section as the extension gave it.\n */\nexport function panelSectionContributor(section: Extract<ContextSectionItem, { placement: 'panel' }>['section']): ContextBreakdownContributor {\n return async (ctx) => {\n const head = { id: section.id, label: section.title, ...(section.accentColor ? { accentColor: section.accentColor } : {}) }\n const sections: ContextExtensionSection[] = []\n const rows = typeof section.rows === 'function' ? section.rows(ctx) : section.rows\n if (rows && rows.length > 0)\n sections.push({ ...head, rows })\n const loaded = section.load ? await section.load(ctx) : undefined\n if (!loaded)\n return sections\n if (Array.isArray(loaded)) {\n if (loaded.every(row => row && typeof row === 'object' && 'value' in row))\n sections.push({ ...head, rows: loaded as readonly ContextExtensionRow[] })\n else\n sections.push(...loaded as readonly ContextExtensionSection[])\n return sections\n }\n sections.push(loaded as ContextExtensionSection)\n return sections\n }\n}\n\nfunction guardedReferences(sources: readonly UiSource[], timeoutMs: number): ExtensionOrderedContribution<ExtensionReferenceProvider>[] {\n return sources.map((s) => {\n const provider = s.raw as ExtensionReferenceProvider\n return {\n extensionName: s.extension,\n source: 'project',\n value: { ...provider, resolve: (key, opts) => callOrThrow(s.deps, 'ui.reference.resolve', () => provider.resolve(key, opts), timeoutMs, 'resolve failed') },\n }\n })\n}\n\nfunction guardedBadgeActions(sources: readonly UiSource[], timeoutMs: number): { badgeActions: ExtensionOrderedContribution<ExtensionBadgeActions>[] } {\n return {\n badgeActions: sources.map((s) => {\n const value = s.raw as ExtensionBadgeActions\n return {\n extensionName: s.extension,\n source: 'project',\n value: {\n ...value,\n actions: target => s.deps.guard.callSync('ui.badge.actions', () => value.actions(target)),\n run: (actionId, target, ctx) => callOrThrow(s.deps, 'ui.badge.run', () => value.run(actionId, target, ctx), timeoutMs, 'The action failed.'),\n },\n }\n }),\n }\n}\n\n/**\n * The callback methods over the registry's live items.\n *\n * @param lookup - Finds items.\n * @param timeoutMs - Deadline per callback.\n */\nexport function createUiCallbacks(lookup: UiSourceLookup, timeoutMs: number): UiCallbacks {\n const loadContext = (context: unknown, cwd: string) => resolvePanelLoadContext(normalizePanelLoadContext(context), cwd)\n let resolver: { version: number, value: ReturnType<typeof createReferenceResolver> } | undefined\n const getResolver = () => {\n const version = lookup.referencesVersion()\n if (!resolver || resolver.version !== version)\n resolver = { version, value: createReferenceResolver({ references: guardedReferences(lookup.all('reference'), timeoutMs) }, { timeoutMs }) }\n return resolver.value\n }\n const accessOf = (s: UiSource): Omit<ActionSettingContext, 'signal'> => lookup.settingsAccess?.(s.extension) ?? noSettingsAccess(s.extension)\n const actionSetting = (pageId: string, settingKey: string): { s: UiSource, setting: ActionSetting } | undefined => {\n const s = lookup.byId('settings-page', pageId)\n const setting = (s?.raw as SettingsPageItem | undefined)?.schema?.items[settingKey]\n return s && setting?.type === 'action' ? { s, setting } : undefined\n }\n\n return {\n loadPanel: async (panelId, context, cwd) => {\n const s = lookup.byId('panel', panelId)\n if (!s)\n return normalizePanelContent(undefined)\n const panel = s.raw as PanelItem\n return normalizePanelContent(await s.deps.guard.call('ui.panel.load', () => panel.load(loadContext(context, cwd)), { timeoutMs }))\n },\n panelAction: async (panelId, actionId, payload, context, cwd) => {\n const s = lookup.byId('panel', panelId)\n const onAction = (s?.raw as PanelItem | undefined)?.onAction\n if (!s || typeof onAction !== 'function' || typeof actionId !== 'string' || !actionId)\n return false\n const ok = await s.deps.guard.call('ui.panel.action', async () => {\n await onAction(actionId, payload, loadContext(context, cwd))\n return true\n }, { timeoutMs, fallback: false })\n return ok === true\n },\n resolveReference: (providerId, key) => getResolver().resolve(providerId, key),\n badgeMenu: target => badgeMenu(target, guardedBadgeActions(lookup.all('badge-action'), timeoutMs)),\n runBadgeAction: (source, actionId, target, ctx = {}) => runBadgeAction(source, actionId, target, guardedBadgeActions(lookup.all('badge-action'), timeoutMs), ctx),\n contextContributors: placement => lookup.all('context-section').flatMap((s) => {\n const item = s.raw as ContextSectionItem\n if (item.placement !== placement)\n return []\n const run: ContextBreakdownContributor = item.placement === 'breakdown' ? item.contributor : panelSectionContributor(item.section)\n const guarded: ContextBreakdownContributor = (ctx: ContextBreakdownContributionContext) =>\n s.deps.guard.call(`ui.context.${placement}`, () => run(ctx), { timeoutMs, fallback: undefined })\n Object.defineProperty(guarded, '__zidaneExtensionName', { value: s.extension, enumerable: false })\n return [guarded]\n }),\n runSettingAction: async (pageId, settingKey, signal) => {\n const found = actionSetting(pageId, settingKey)\n if (!found)\n return lookup.ownActions?.(pageId)?.run(settingKey, signal)\n const result = await found.s.deps.guard.call('ui.settings.action', () => found.setting.run({ ...accessOf(found.s), signal }), { timeoutMs })\n return result && typeof result === 'object' ? result : undefined\n },\n settingStatus: async (pageId, settingKey) => {\n const found = actionSetting(pageId, settingKey)\n if (!found)\n return lookup.ownActions?.(pageId)?.status(settingKey)\n const status = found.setting.status\n if (!status)\n return undefined\n const { get } = accessOf(found.s)\n const result = await found.s.deps.guard.call('ui.settings.status', () => status({ get }), { timeoutMs })\n return result && typeof result === 'object' && typeof result.text === 'string' ? result : undefined\n },\n settingActionScope: (pageId, settingKey) => {\n const found = actionSetting(pageId, settingKey)\n return found ? actionScope(found.setting) : lookup.ownActions?.(pageId)?.scope(settingKey)\n },\n openLink: async ({ url, sessionId, source }) => {\n if (typeof url !== 'string' || !url || url.length > MAX_LINK_URL_LENGTH)\n return { handled: false }\n const where: LinkSource = source !== undefined && LINK_SOURCES.includes(source) ? source : 'other'\n const handlers = lookup.all('link-handler')\n .map((s, at) => ({ s, at, priority: (s.raw as LinkHandlerItem).priority ?? 0 }))\n .sort((a, b) => b.priority - a.priority || a.at - b.at)\n for (const { s } of handlers) {\n if (!linkMatches(s, url))\n continue\n const open = (s.raw as LinkHandlerItem).open\n const result = await s.deps.guard.call<unknown>('ui.link.open', () => open(url, { ...(sessionId ? { sessionId } : {}), source: where }), { timeoutMs, fallback: THROWN })\n if (result !== THROWN && result !== false)\n return { handled: true }\n }\n return { handled: false }\n },\n validateSetting: (pageId, settingKey, value) => {\n const s = lookup.byId('settings-page', pageId)\n const setting = (s?.raw as SettingsPageItem | undefined)?.schema?.items[settingKey]\n if (!s || !setting)\n return 'unknown setting'\n const one: SettingsSchema = { items: { [settingKey]: setting } }\n return checkSettingsValues(one, { [settingKey]: value }, (validate, v) => s.deps.guard.callSync('ui.settings.validate', () => validate(v))).errors[settingKey]\n },\n }\n}\n\n/** A backend-side provider list (composer completions, inline autocomplete). */\nexport interface UiProviderList<P> {\n /** Adds a provider for the extension. Disposed with the extension's owner. */\n register: (deps: DomainDeps, provider: P) => Disposable\n /** The providers with their extension, in registration order; the first of each `id` wins. */\n list: () => readonly { extension: string, provider: P }[]\n}\n\n/**\n * An empty provider list.\n *\n * @param what - Name used in errors (`composer.completions`).\n * @param onChange - Called after each register and dispose.\n */\nexport function createProviderList<P extends { id: string }>(what: string, onChange: () => void): UiProviderList<P> {\n const items: { extension: string, provider: P }[] = []\n return {\n register: (deps, provider) => {\n if (deps.owner.disposed)\n throw new DisposedError(`${what}.register`)\n if (!provider || typeof provider.id !== 'string' || !provider.id)\n throw new TypeError(`${what}: a provider needs an id`)\n const rec = { extension: deps.extensionId, provider }\n items.push(rec)\n onChange()\n let done = false\n const handle: { cleanup?: Disposable } = {}\n const off = (): void => {\n if (done)\n return\n done = true\n handle.cleanup?.dispose()\n items.splice(items.indexOf(rec), 1)\n onChange()\n }\n handle.cleanup = deps.owner.onCleanup(off)\n return { dispose: off }\n },\n list: () => {\n const seen = new Set<string>()\n return items.filter((r) => {\n if (seen.has(r.provider.id))\n return false\n seen.add(r.provider.id)\n return true\n })\n },\n }\n}\n","/**\n * The timer the UI model uses for slot `timeoutMs` and dialog timeouts.\n * Injectable so tests drive time instead of waiting for it.\n */\n\n/** Schedules and cancels one-shot timers. */\nexport interface UiClock {\n /** Runs `fn` once after `ms` milliseconds. Returns a handle for {@link UiClock.clearTimeout}. */\n setTimeout: (fn: () => void, ms: number) => unknown\n /** Cancels a timer made by {@link UiClock.setTimeout}. Unknown handles are ignored. */\n clearTimeout: (handle: unknown) => void\n}\n\n/** The real clock: `setTimeout` / `clearTimeout` of the host. */\nexport const systemClock: UiClock = {\n setTimeout: (fn, ms) => setTimeout(fn, ms),\n clearTimeout: handle => clearTimeout(handle as ReturnType<typeof setTimeout>),\n}\n","/**\n * The UI registry: every extension's UI contributions, per token, as wire\n * items the hosts draw. `ctx.add(token, item)` lands here and returns a\n * {@link Handle}; bound fields re-push on change; hosts subscribe to\n * changes and call back into the extension through the item ids (see\n * {@link UiCallbacks}). Callbacks run through the owning extension's guard.\n *\n * Slot rules: `composer.badges` holds at most {@link MAX_COMPOSER_BADGES}\n * items per extension per session, `app.titlebar` as many per extension; `timeoutMs` withdraws an item (rearmed\n * on each update); deleting a session withdraws its items; lists are ordered\n * by `order` (default 100), then by when the item was added. Spaces are\n * ordered the same way. The sidebar tokens have per-extension caps\n * ({@link SIDEBAR_CAPS}). Sidebar rows' command, panel and screen ids are\n * resolved against the registry and the commands, and resolved again when\n * those change.\n *\n * Pure: no host code, no globals. Time comes from an injectable clock.\n */\n\nimport type { CompletionProvider } from '../../chat/completion'\nimport type { InlineAutocompleteProvider } from '../../chat/inline-autocomplete'\nimport type { Logger } from '../../logger'\nimport type { Disposable, Handle, Readable } from '../api/core'\nimport type { AddFn, PanelItem, UiToken } from '../api/ui'\nimport type { DomainDeps } from '../runtime/deps'\nimport type { UiCallbacks, UiProviderList, UiSource, UiSourceLookup } from './callbacks'\nimport type { UiClock } from './clock'\nimport type { UiRefs, UiTokenName, UiWireMap } from './wire'\nimport { DisposedError } from '../api/core'\nimport { readablesOf, resolveBindables } from './bindable'\nimport { createProviderList, createUiCallbacks } from './callbacks'\nimport { systemClock } from './clock'\nimport { isBadgeSlot, isKnownToken, isUniquePerExtension, MAX_SLOT_BADGES, serializeUiItem, UI_TOKEN_NAMES, wireIdentity } from './wire'\n\n/** How many `composer.badges` items one extension may show in one session, and `app.titlebar` items in the app. */\nexport const MAX_COMPOSER_BADGES = MAX_SLOT_BADGES\n\n/** How many sidebar rows one extension may show. */\nexport const MAX_SIDEBAR_ROWS = 500\n\n/** How many items of each sidebar token one extension may add. */\nexport const SIDEBAR_CAPS: Readonly<Partial<Record<UiTokenName, number>>> = {\n 'space': 32,\n 'sidebar-filter': 64,\n 'sidebar-sort': 32,\n 'sidebar-group': 32,\n 'sidebar-decoration': 64,\n 'sidebar-row': MAX_SIDEBAR_ROWS,\n}\n\n/** One contribution as the hosts see it. */\nexport interface UiEntry<N extends UiTokenName = UiTokenName> {\n /** Unique across the registry; stable for the item's life. Hosts address the item by it. */\n readonly key: string\n /** The token name of the contribution. */\n readonly token: N\n /** The contributing extension. */\n readonly extension: string\n /** The wire form, bindings read. */\n readonly item: UiWireMap[N]\n}\n\n/** What changed, pushed to {@link UiRegistry.subscribe} listeners. */\nexport type UiChange\n = | { type: 'upsert', entry: UiEntry }\n | { type: 'remove', key: string, token: UiTokenName, extension: string }\n /**\n * A panel's `load` would answer something new: its `subscribe` emitted,\n * or its handle was updated. `sessionId`: only that session's content\n * changed. Hosts reload it while visible.\n */\n | { type: 'panel-changed', panelId: string, extension: string, sessionId?: string }\n /** The composer completion or autocomplete providers changed. */\n | { type: 'providers', kind: 'completion' | 'autocomplete' }\n\n/** A panel would load something new (`panel-changed`), as hosts pass it on. */\nexport interface PanelChangedEvent {\n /** The extension that owns the panel. */\n extensionId: string\n /** `<extension>/<id>`. */\n panelId: string\n /** Set when only this session's content changed. */\n sessionId?: string\n}\n\n/**\n * Calls `listener` each time a panel of `ui` would load something new: its\n * `subscribe` emitted, or its handle was updated. What an in-process host\n * builds its `panelChanged` on; protocol clients get the same events as\n * the `extensions:panel` signal.\n *\n * @param ui - The registry (`runtime.outputs.ui`).\n * @param listener - Gets each change.\n * @returns The unsubscribe.\n */\nexport function onPanelChanged(ui: Pick<UiRegistry, 'subscribe'>, listener: (event: PanelChangedEvent) => void): () => void {\n return ui.subscribe((change) => {\n if (change.type === 'panel-changed')\n listener({ extensionId: change.extension, panelId: change.panelId, ...(change.sessionId ? { sessionId: change.sessionId } : {}) })\n })\n}\n\n/** Every token's entries. */\nexport type UiSnapshot = { readonly [N in UiTokenName]: readonly UiEntry<N>[] }\n\n/** Options for {@link createUiRegistry}. */\nexport interface UiRegistryOptions {\n /** Timer for `timeoutMs`. Default: the real clock. */\n clock?: UiClock\n /** Registry-level log (listener failures). Extension problems go to the extension's own logger. */\n logger?: Logger\n /** Deadline for a callback the hosts invoke (load, resolve, run). Default 8 s. */\n callbackTimeoutMs?: number\n /** An extension's own settings, for the `get` / `set` of its settings-page actions (the runtime gives it). */\n settingsAccess?: UiSourceLookup['settingsAccess']\n /** An extension's own settings actions, for `setting.action` with the extension's id as page id (the runtime gives it). */\n ownActions?: UiSourceLookup['ownActions']\n /** The extensions' commands, by full id (`<extension>.<id>`): sidebar rows resolve their command ids against them. */\n commands?: UiCommandLookup\n}\n\n/** The commands a {@link UiRegistry} resolves sidebar row commands against. */\nexport interface UiCommandLookup {\n /** Whether a command with this full id exists. */\n has: (id: string) => boolean\n /** Calls `listener` after the commands changed. Returns the unsubscribe. */\n subscribe: (listener: () => void) => () => void\n}\n\n/** The host-agnostic UI model all extensions contribute to. */\nexport interface UiRegistry extends UiCallbacks {\n /** The `ctx.add` of one extension (or one of its scopes): registrations attach to `deps.owner`. */\n bind: (deps: DomainDeps) => AddFn\n /** A token's entries, in order. For `reference`, `badge-action` and `theme` the first of each id wins. */\n list: <N extends UiTokenName>(token: N | UiToken<unknown, N>) => readonly UiEntry<N>[]\n /** Every token's entries. */\n snapshot: () => UiSnapshot\n /** One entry by key. */\n get: (key: string) => UiEntry | undefined\n /** Calls `listener` after each change. Returns the unsubscribe. */\n subscribe: (listener: (change: UiChange) => void) => () => void\n /**\n * The full id of a panel or screen an extension names: `<extension>/<id>`\n * when that extension has one by that id, else `id` as given (a full id,\n * or a built-in such as `todos`).\n */\n qualify: (kind: 'panel' | 'screen', extension: string, id: string) => string\n /** `ctx.composer.completions` providers. */\n completions: UiProviderList<CompletionProvider>\n /** `ctx.composer.autocomplete` providers. */\n autocomplete: UiProviderList<InlineAutocompleteProvider>\n /** Withdraws every item scoped to `sessionId` (the session was deleted). */\n removeSession: (sessionId: string) => void\n /** Withdraws every item of an extension. */\n removeExtension: (extensionId: string) => void\n}\n\ninterface Entry extends UiSource {\n key: string\n token: UiTokenName\n seq: number\n raw: object\n wire: UiWireMap[UiTokenName]\n json: string\n identity: string | undefined\n unbind: (() => void)[]\n panelSubscribe?: unknown\n panelUnsubscribe?: () => void\n timer?: unknown\n cleanup?: Disposable\n disposed: boolean\n}\n\n/** Tokens where several extensions may use one id and the first wins. */\nconst FIRST_WINS: ReadonlySet<UiTokenName> = new Set(['reference', 'badge-action', 'theme'])\n\nconst errorText = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n\nfunction serializeWith(refs: UiRefs, deps: DomainDeps, token: UiTokenName, raw: object): UiWireMap[UiTokenName] {\n const read = (readable: Readable<unknown>): unknown => deps.guard.callSync('ui.bindable.get', () => readable.get())\n return serializeUiItem(token, resolveBindables(raw, read) as never, deps.extensionId, refs)\n}\n\nfunction order(entries: Entry[], token: UiTokenName): Entry[] {\n const all = entries.filter(e => e.token === token)\n if (token === 'slot' || token === 'space')\n all.sort((a, b) => ((a.wire as { order: number }).order - (b.wire as { order: number }).order) || a.seq - b.seq)\n else\n all.sort((a, b) => a.seq - b.seq)\n if (!FIRST_WINS.has(token))\n return all\n const seen = new Set<string>()\n return all.filter((e) => {\n const id = e.identity ?? e.key\n if (seen.has(id))\n return false\n seen.add(id)\n return true\n })\n}\n\nfunction publicEntry(e: Entry): UiEntry {\n return { key: e.key, token: e.token, extension: e.extension, item: e.wire }\n}\n\n/**\n * Creates an empty UI registry.\n *\n * @param options - Clock, logger and callback deadline.\n */\nexport function createUiRegistry(options: UiRegistryOptions = {}): UiRegistry {\n const clock = options.clock ?? systemClock\n const entries = new Map<string, Entry>()\n const listeners = new Set<(change: UiChange) => void>()\n let seq = 0\n let referencesVersion = 0\n\n const emit = (change: UiChange): void => {\n const token = change.type === 'remove' ? change.token : change.type === 'upsert' ? change.entry.token : undefined\n if (token === 'reference')\n referencesVersion++\n for (const listener of [...listeners]) {\n try {\n listener(change)\n }\n catch (err) {\n options.logger?.warn('ui registry listener failed', { error: errorText(err) })\n }\n }\n }\n\n const sorted = (token: UiTokenName): Entry[] => order([...entries.values()], token)\n const findById = (token: UiTokenName, id: string): Entry | undefined => sorted(token).find(e => (e.wire as { id?: string }).id === id)\n const refs: UiRefs = {\n hasCommand: id => options.commands?.has(id) ?? false,\n hasSurface: (kind, id) => [...entries.values()].some(e => e.token === kind && (e.wire as { id?: string }).id === id),\n }\n const serialize = (deps: DomainDeps, token: UiTokenName, raw: object): UiWireMap[UiTokenName] => serializeWith(refs, deps, token, raw)\n\n const dispose = (e: Entry): void => {\n if (e.disposed)\n return\n e.disposed = true\n for (const off of e.unbind) off()\n if (e.panelUnsubscribe)\n e.deps.guard.callSync('ui.panel.unsubscribe', e.panelUnsubscribe)\n if (e.timer !== undefined)\n clock.clearTimeout(e.timer)\n e.cleanup?.dispose()\n entries.delete(e.key)\n emit({ type: 'remove', key: e.key, token: e.token, extension: e.extension })\n }\n\n /** Stores a new wire form and pushes it when it differs from the last one. */\n const push = (e: Entry, wire: UiWireMap[UiTokenName]): void => {\n const json = JSON.stringify(wire)\n if (json === e.json)\n return\n e.wire = wire\n e.json = json\n emit({ type: 'upsert', entry: publicEntry(e) })\n }\n\n /** Re-reads bound fields after a readable changed. */\n const refresh = (e: Entry): void => {\n if (e.disposed)\n return\n try {\n push(e, serialize(e.deps, e.token, e.raw))\n }\n catch (err) {\n e.deps.logger.warn(`ui: a bound value made the ${e.token} item invalid; keeping the last one`, { error: errorText(err) })\n }\n }\n\n /** Serializes every sidebar row again: a panel, screen or command its ids may resolve to came or went. */\n const resolveRowsAgain = (): void => {\n for (const e of [...entries.values()]) {\n if (e.token === 'sidebar-row')\n refresh(e)\n }\n }\n listeners.add((change) => {\n const token = change.type === 'remove' ? change.token : change.type === 'upsert' ? change.entry.token : undefined\n if (token === 'panel' || token === 'screen')\n resolveRowsAgain()\n })\n options.commands?.subscribe(resolveRowsAgain)\n\n /** (Re)binds readables, the panel's `subscribe` and the slot timeout to the current raw item. */\n const attach = (e: Entry): void => {\n for (const off of e.unbind) off()\n e.unbind = readablesOf(e.raw).map((readable) => {\n const off = e.deps.guard.callSync('ui.bindable.subscribe', () => readable.subscribe(() => refresh(e)))\n return typeof off === 'function' ? off : () => {}\n })\n const subscribe = e.token === 'panel' ? (e.raw as PanelItem).subscribe : undefined\n if (subscribe !== e.panelSubscribe) {\n if (e.panelUnsubscribe)\n e.deps.guard.callSync('ui.panel.unsubscribe', e.panelUnsubscribe)\n e.panelUnsubscribe = undefined\n e.panelSubscribe = subscribe\n if (typeof subscribe === 'function') {\n const panelId = (e.wire as UiWireMap['panel']).id\n const off = e.deps.guard.callSync('ui.panel.subscribe', () => subscribe((change) => {\n if (e.disposed || e.panelSubscribe !== subscribe)\n return\n const sessionId = typeof change?.sessionId === 'string' && change.sessionId ? change.sessionId : undefined\n emit({ type: 'panel-changed', panelId, extension: e.extension, ...(sessionId ? { sessionId } : {}) })\n }))\n e.panelUnsubscribe = typeof off === 'function' ? off : undefined\n }\n }\n if (e.timer !== undefined)\n clock.clearTimeout(e.timer)\n e.timer = undefined\n const ms = e.token === 'slot' ? (e.raw as { timeoutMs?: unknown }).timeoutMs : undefined\n if (typeof ms === 'number' && Number.isFinite(ms) && ms > 0)\n e.timer = clock.setTimeout(() => dispose(e), ms)\n }\n\n /** Refuses a duplicate id within the extension, and a composer badge past the cap. */\n const assertRoom = (deps: DomainDeps, token: UiTokenName, wire: UiWireMap[UiTokenName], identity: string | undefined): void => {\n const mine = [...entries.values()].filter(e => e.token === token && e.extension === deps.extensionId)\n if (identity !== undefined && isUniquePerExtension(token, wire) && mine.some(e => e.identity === identity))\n throw new TypeError(`${token}: this extension already added one with id ${identity}`)\n const slot = wire as UiWireMap['slot']\n // `composer.badges` counts per session (its identity holds the session), `app.titlebar` across the app.\n const sameBlock = (e: Entry): boolean => (slot.at === 'composer.badges' ? e.identity === identity : (e.wire as UiWireMap['slot']).at === slot.at)\n if (token === 'slot' && isBadgeSlot(slot.at) && mine.filter(sameBlock).length >= MAX_SLOT_BADGES)\n throw new RangeError(slot.at === 'composer.badges' ? `composer.badges: at most ${MAX_SLOT_BADGES} per extension per session` : `${slot.at}: at most ${MAX_SLOT_BADGES} per extension`)\n const cap = SIDEBAR_CAPS[token]\n if (cap !== undefined && mine.length >= cap)\n throw new RangeError(`${token}: at most ${cap} per extension`)\n }\n\n const add = <T>(deps: DomainDeps, token: UiToken<T>, item: T): Handle<T> => {\n if (deps.owner.disposed)\n throw new DisposedError('ctx.add')\n if (!isKnownToken(token as UiToken<unknown>))\n throw new TypeError(`ctx.add: unknown UI token ${String((token as UiToken<unknown>)?.name)}`)\n const name = (token as UiToken<unknown, UiTokenName>).name\n if (!item || typeof item !== 'object')\n throw new TypeError(`${name}: the item must be an object`)\n const raw = { ...(item as object) }\n const wire = serialize(deps, name, raw)\n const identity = wireIdentity(name, wire)\n assertRoom(deps, name, wire, identity)\n seq++\n const e: Entry = { key: `${name}:${deps.extensionId}:${seq}`, token: name, extension: deps.extensionId, seq, deps, raw, wire, json: JSON.stringify(wire), identity, unbind: [], disposed: false }\n entries.set(e.key, e)\n e.cleanup = deps.owner.onCleanup(() => dispose(e))\n attach(e)\n emit({ type: 'upsert', entry: publicEntry(e) })\n return {\n get current() {\n return e.raw as Readonly<T>\n },\n update(patch) {\n if (e.disposed)\n return\n const next = typeof patch === 'function' ? (patch as (current: Readonly<T>) => T)(e.raw as Readonly<T>) : { ...e.raw, ...(patch as object) }\n if (!next || typeof next !== 'object')\n throw new TypeError(`${name}: update must give an object`)\n const nextRaw = { ...(next as object) }\n const nextWire = serialize(deps, name, nextRaw)\n if (wireIdentity(name, nextWire) !== identity)\n throw new TypeError(`${name}: update cannot change the item's id, place or session`)\n e.raw = nextRaw\n attach(e)\n push(e, nextWire)\n // A new `load` (or anything it reads from the item) can answer differently: visible hosts reload.\n if (name === 'panel')\n emit({ type: 'panel-changed', panelId: (nextWire as UiWireMap['panel']).id, extension: e.extension })\n },\n dispose: () => dispose(e),\n }\n }\n\n const callbacks = createUiCallbacks({\n byId: findById,\n all: sorted,\n referencesVersion: () => referencesVersion,\n ...(options.settingsAccess ? { settingsAccess: options.settingsAccess } : {}),\n ...(options.ownActions ? { ownActions: options.ownActions } : {}),\n }, options.callbackTimeoutMs ?? 8_000)\n\n return {\n ...callbacks,\n bind: deps => (token, item) => add(deps, token, item),\n list: <N extends UiTokenName>(token: N | UiToken<unknown, N>) => sorted(typeof token === 'string' ? token : token.name).map(publicEntry) as unknown as readonly UiEntry<N>[],\n snapshot: () => Object.fromEntries(UI_TOKEN_NAMES.map(n => [n, sorted(n).map(publicEntry)])) as unknown as UiSnapshot,\n get: (key) => {\n const e = entries.get(key)\n return e ? publicEntry(e) : undefined\n },\n subscribe: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n qualify: (kind, extension, id) => {\n if (id.includes('/'))\n return id\n const full = `${extension}/${id}`\n return findById(kind, full) ? full : id\n },\n completions: createProviderList<CompletionProvider>('composer.completions', () => emit({ type: 'providers', kind: 'completion' })),\n autocomplete: createProviderList<InlineAutocompleteProvider>('composer.autocomplete', () => emit({ type: 'providers', kind: 'autocomplete' })),\n removeSession: (sessionId) => {\n for (const e of [...entries.values()]) {\n if (e.token === 'slot' && (e.wire as UiWireMap['slot']).sessionId === sessionId)\n dispose(e)\n }\n },\n removeExtension: (extensionId) => {\n for (const e of [...entries.values()]) {\n if (e.extension === extensionId)\n dispose(e)\n }\n },\n }\n}\n"],"mappings":"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O;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EAGE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EAOE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CAIA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CAeA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CAEA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CAEA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA;EACE,QAAQ;EACR,SAAS;EACT,OAAO;EACP,aAAa;EACb,OAA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"}