@klarkxy/dsh-current-title 0.3.2 → 0.3.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.
- package/README.md +2 -0
- package/docs/README.zh-CN.md +2 -0
- package/lib/client.inner.cjs +567 -88
- package/lib/client.inner.cjs.map +1 -1
- package/lib/client.js +567 -88
- package/lib/index.js +3 -2
- package/lib/index.js.map +1 -1
- package/package.json +14 -10
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../dsh-plugin-kit/src/contracts.ts","../../dsh-plugin-kit/src/host-rpc.ts","../../dsh-plugin-kit/src/model-settings.ts","../../dsh-plugin-kit/src/model-settings-client.ts","../../dsh-plugin-kit/src/model-settings-changes.ts","../../dsh-plugin-kit/src/auxiliary-model.ts","../../dsh-plugin-kit/src/auxiliary-context.ts","../../dsh-plugin-kit/src/llm-call.ts","../src/input.ts","../src/output.ts","../src/messages.ts","../src/generate.ts","../src/ownership.ts","../src/native-slot.ts","../src/storage.ts","../src/service.ts","../src/index.ts"],"sourcesContent":["import type { ContextFormed } from '@deepseek-ai/dsh-llm'\nimport { modelRouteOverride, type ModelRoute } from '@klarkxy/dsh-model-route'\n\n/**\n * The canonical home is @klarkxy/dsh-model-route; re-exported here so existing\n * plugin-kit consumers keep compiling.\n */\nexport type { ModelRoute }\n\n/** Public, browser-safe contracts. Host implementations stay in their owning packages. */\nexport type ProducerSourceKind = `plugin:${string}`\nexport type ProducerMessageSource = { kind: ProducerSourceKind; plugin: string } & ContextFormed\n\n/**\n * V4 sessions persist the producing extension in `kind`; the retired generic\n * `plugin` wrapper is not admitted. Each feature plugin declares its own kind.\n */\ndeclare module '@deepseek-ai/dsh-llm' {\n interface MessageSourceMap {\n [kind: ProducerSourceKind]: ProducerMessageSource\n }\n}\n\nexport function producerMessageSource(plugin: string): ProducerMessageSource {\n return { kind: `plugin:${plugin}`, plugin }\n}\n\nexport type RpcResult<T = unknown> = { ok: true; value: T } | { ok: false; error: { code: string; message: string } }\nexport const CHAT_EVENTS_SLOT = 'dsh-editor.chat.events'\nexport interface EvidenceRef { sessionId: string; seq: number; kind: 'user' | 'tool' | 'turn' | 'manual'; excerpt?: string }\nexport interface TaskContract {\n id: string\n sessionId: string\n sourceVersion: string\n revision: number\n goal: string\n deliverables: string[]\n inScope: string[]\n outOfScope: string[]\n constraints: string[]\n acceptance: string[]\n assumptions: string[]\n questions: string[]\n evidence: EvidenceRef[]\n readiness: 'pending' | 'clear-request' | 'user-confirmed' | 'disclosed-assumptions' | 'cancelled' | 'stale'\n updatedAt: number\n}\nexport interface TaskCheckpoint {\n id: string\n sessionId: string\n sourceVersion: string\n contractVersion?: number\n fromSeq: number\n toSeq: number\n revision: number\n status: 'running' | 'completed' | 'failed' | 'cancelled'\n items: Array<{ label: string; state: 'pending' | 'verified' | 'failed'; evidence: EvidenceRef[] }>\n constraints: string[]\n nextAction: string\n createdAt: number\n}\nexport type KnowledgeScope = { kind: 'global' } | { kind: 'project'; projectId: string }\nexport type KnowledgeKind = 'preference' | 'project-fact' | 'decision' | 'vocabulary' | 'activity' | 'lesson'\n/** Descriptive context, never an executable instruction or authorization. */\nexport interface ContextKnowledge {\n subject: string\n domain: string\n key: string\n aliases: string[]\n observedAt: number\n /** The user's own time expression, not an inferred completion date. */\n eventTime?: string\n activityStatus?: 'planned' | 'in-progress' | 'blocked' | 'paused' | 'completed' | 'cancelled' | 'unknown'\n}\n/** A scoped method. Observations remain candidates until explicitly accepted. */\nexport interface ProcedureKnowledge {\n origin: 'instruction' | 'observation'\n goal: string\n when: string[]\n steps: string[]\n avoid: string[]\n verify: string[]\n}\nexport interface MemoryRecord {\n id: string\n revision: number\n scope: KnowledgeScope\n kind: KnowledgeKind\n status: 'candidate' | 'active' | 'rejected' | 'superseded' | 'revoked' | 'deleted'\n title: string\n content: string\n tags: string[]\n evidence: EvidenceRef[]\n exceptions: string[]\n source: 'user' | 'memory' | 'dream' | 'self-improvement'\n context?: ContextKnowledge\n procedure?: ProcedureKnowledge\n createdAt: number\n updatedAt: number\n expiresAt?: number\n supersedes?: string[]\n /** Exact record revisions behind a derived candidate; revalidated on adoption. */\n basis?: Array<{ id: string; revision: number }>\n}\nexport type NewMemoryRecord = Omit<MemoryRecord, 'id' | 'revision' | 'createdAt' | 'updatedAt'>\nexport interface MemoryQuery { scope: KnowledgeScope; query?: string; kinds?: KnowledgeKind[]; statuses?: MemoryRecord['status'][]; limit?: number }\nexport interface MemoryMutationOptions { signal?: AbortSignal; isCurrent?: () => boolean }\nexport interface MemoryService {\n list(query: MemoryQuery): Promise<MemoryRecord[]>\n create(record: NewMemoryRecord, options?: MemoryMutationOptions): Promise<MemoryRecord>\n update(id: string, patch: Partial<Pick<MemoryRecord, 'title' | 'content' | 'tags' | 'exceptions' | 'status' | 'expiresAt'>>, expectedRevision: number, options?: MemoryMutationOptions): Promise<MemoryRecord>\n /** Explicit user promotion, persisted atomically on the same record; preserves expiry and evidence. */\n promoteToGlobal(id: string, expectedRevision: number, options?: MemoryMutationOptions): Promise<MemoryRecord>\n remove(id: string, expectedRevision: number, options?: MemoryMutationOptions): Promise<void>\n recall(query: MemoryQuery): Promise<MemoryRecord[]>\n}\n\n/**\n * The session creation metadata the host snapshots when it creates a delegated child\n * thread. Mirrors `CreateAgentOptions.meta` in `@deepseek-ai/dsh-agent`; it is durable\n * session data, so it survives a restart and needs no ancestry walk.\n */\nexport interface SubagentSessionLike {\n readonly header?: {\n readonly parentSession?: unknown\n readonly origin?: unknown\n readonly delegationDepth?: unknown\n readonly isSeeded?: unknown\n readonly classification?: unknown\n }\n}\n\n/**\n * True when `session` is a delegated child thread rather than a human-driven top-level\n * conversation.\n *\n * A message's `source.kind === 'user'` cannot answer this: a lead agent's dispatch prompt\n * is delivered as the child's own user message, so delegated work is indistinguishable\n * from a person typing once you only look at the message. Plugins use this to keep\n * automatic writes and derived model calls on top-level sessions.\n */\nexport function isSubagentSession(session: unknown): boolean {\n const header = (session as SubagentSessionLike | null | undefined)?.header\n if (!header || typeof header !== 'object') return false\n if (header.origin === 'subagent' || Number(header.delegationDepth ?? 0) > 0) return true\n // Native human forks also persist parentSession for history lineage. A fork's\n // seeded header distinguishes it from legacy children whose parent is the\n // only marker. Native rc.2 forks omit depth; patched hosts may persist zero.\n // Explicit delegation and unknown metadata still keep the child guard.\n const humanFork = header.isSeeded === true\n && (header.delegationDepth === undefined || header.delegationDepth === 0)\n && header.origin === undefined\n && (header.classification === undefined || header.classification === 'ordinary' || header.classification === 'free')\n return Boolean(header.parentSession) && !humanFork\n}\n\n/** Project keys come only from the host-validated session directory, never client input. */\nexport function projectIdFromCwd(cwd: string | undefined): string | undefined {\n if (typeof cwd !== 'string') return undefined\n const normalized = cwd.trim().replaceAll('\\\\', '/')\n if (!normalized) return undefined\n return normalized === '/' || /^[A-Za-z]:\\/$/.test(normalized) ? normalized : normalized.replace(/\\/+$/, '')\n}\n\n/**\n * One settings owner's Remote stream. Typert accepts either case in an RPC\n * segment, so the Cordis service key and the wire namespace use the same\n * Pascal segment. The scope's first letter stays uppercase.\n */\nexport interface ModelSettingsChangesIdentity {\n readonly service: string\n readonly namespace: string\n}\n\n/** `@klarkxy/dsh-git-commit` becomes `KlarkxyDshGitCommitModelSettingsChanges`. */\nexport function modelSettingsChangesIdentity(packageName: string): ModelSettingsChangesIdentity {\n const scoped = /^@([^/]+)\\/(.+)$/.exec(packageName)\n const body = scoped ? `${scoped[1]}/${scoped[2]}` : packageName\n const parts = body.split(/[^A-Za-z0-9]+/).filter(Boolean)\n if (!parts.length) throw new Error('Model settings package name has no RPC segment')\n const segment = `${parts.map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('')}ModelSettingsChanges`\n if (!/^[A-Z][A-Za-z0-9]*$/.test(segment)) throw new Error(`Model settings sync name is not an RPC segment: ${segment}`)\n return { service: segment, namespace: segment }\n}\n\n/**\n * Repository extension: a native web provider announces that its local\n * availability changed. Kind is `search` or `fetch`; id is the provider id.\n * Listeners refresh management state and must not treat this as a network probe.\n */\nexport const WEB_PROVIDER_AVAILABILITY_EVENT = 'web/provider-availability-updated' as const\n\n/**\n * Optional display metadata a provider may attach when it registers directly\n * with `ctx.web`. Execution and credentials stay with the provider; this object\n * is display-only and must never carry secret values.\n */\nexport interface DshWebManagementDescriptor {\n readonly id: string\n readonly label: string\n readonly description: string\n readonly defaultBaseURL?: string\n readonly credentialRef?: string\n /** True when the key is shared with another surface. The page must not delete it. */\n readonly credentialShared?: boolean\n /** Optional notice naming the settings surface that owns a shared credential. */\n readonly credentialHint?: string\n readonly billing: 'request' | 'model-and-tools' | 'none' | 'unknown'\n /** Optional provider-supplied billing summary. */\n readonly pricing?: string\n /** Public HTTPS page explaining provider charges. */\n readonly pricingUrl?: string\n /** Public HTTPS page where the user can create an API key. */\n readonly signupUrl?: string\n /** Plugin that owns configuration. Native providers keep their settings there. */\n readonly configurationOwner?: string\n /** Explicit settings link supplied by the provider, never inferred from its id. */\n readonly configurationUrl?: string\n /** Fixed legacy route migrated by a bundle-owned adapter; not used by native plugins. */\n readonly legacyId?: string\n}\n\n/**\n * Host Creator agent-preset id (`agentPresets.composedPreset`).\n * Plugins that gate Creator-only tools or prompt sections compare against this.\n */\nexport const CREATOR_PRESET_ID = 'cordis'\n\n/**\n * Shared \"Session Management\" settings section id. The section is provided by\n * shared infrastructure (see `registerSessionSettingsItem` in `client-utils`),\n * not by any one business plugin: every participant registers only a row into\n * {@link SESSION_SETTINGS_ITEM_SLOT}, so any enabled subset yields the same page.\n */\nexport const SESSION_SETTINGS_SECTION_ID = 'session-manager'\n\n/**\n * Child list slot declared by the shared Session Management page. Neutral\n * naming on purpose: participants never import each other, they only\n * contribute `{id, order}` rows into this slot while the page is alive.\n */\nexport const SESSION_SETTINGS_ITEM_SLOT = 'dsh.session-settings.item'\n\n/**\n * Host-owned nav icon seat: a root-scoped list where each entry's `id` must\n * equal the `settings.section` id it decorates. Owner props are\n * `{size, active}`; icons stay `aria-hidden` so the section label remains the\n * accessible name. Contributors into a shared section may register the same\n * icon `id` with different priorities — the ledger keeps every entry while the\n * host renders one icon per section.\n */\nexport const SETTINGS_SECTION_ICON_SLOT = 'settings.section.icon'\n\n/* Shared auxiliary-model default. Feature plugins may store a global default\n * route that fills the tier between their own saved override and the live\n * session model. The durable state is a root-context singleton (like the\n * shared session-settings page): it exists while any participant retains it\n * and is never owned by a business plugin. See `auxiliary-model.ts`. */\n\n/** Root context service key holding the shared auxiliary-model state. */\nexport const AUXILIARY_MODEL_SERVICE = 'dshAuxiliaryModel'\n\n/** Authenticated host-RPC channel for get/set of the shared default. */\nexport const AUXILIARY_MODEL_CHANNEL = '/dsh-auxiliary-model'\n\n/** Model-settings namespace under which the shared default is published. */\nexport const AUXILIARY_MODEL_NS = '@klarkxy/dsh-plugin-kit/auxiliary-model'\n\n/**\n * Typert identity of the shared change stream. Mounted on the root context\n * with ownerNs filtering, so frames only carry {@link AUXILIARY_MODEL_NS}.\n */\nexport const AUXILIARY_MODEL_CHANGES_IDENTITY = modelSettingsChangesIdentity('@klarkxy/dsh-plugin-kit')\n\n/** The value the shared default persists: `model: null` means follow the live session/host model. */\nexport interface AuxiliaryModelDefaults {\n readonly revision: number\n readonly model: ModelRoute | null\n}\n\n/** Shape of the root singleton; produced and owned by `auxiliary-model.ts`. */\nexport interface AuxiliaryModelShared {\n readonly ready: Promise<void>\n snapshot(): AuxiliaryModelDefaults\n}\n\nfunction sharedAuxiliaryModel(host: unknown): AuxiliaryModelShared | undefined {\n const root = (host as { root?: unknown } | undefined)?.root as { get?(name: string, strict?: boolean): unknown } | undefined\n try {\n const shared = root?.get?.(AUXILIARY_MODEL_SERVICE, false) as AuxiliaryModelShared | undefined\n return shared && typeof shared.snapshot === 'function' ? shared : undefined\n } catch { return undefined }\n}\n\n/**\n * Synchronously read the shared auxiliary default; `undefined` only when no\n * participant retains the singleton or the default is legitimately unset.\n * An initialization or snapshot failure propagates: silently falling back to\n * a different model after a storage error would spend the wrong budget.\n */\nexport function getAuxiliaryModel(host: unknown): ModelRoute | undefined {\n const shared = sharedAuxiliaryModel(host)\n if (!shared) return undefined\n return modelRouteOverride(shared.snapshot().model ?? undefined)\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { RpcResult } from './contracts.ts'\n\nexport interface HostRpcContext {\n webServer: { register(route: { kind: 'prefix'; path: string; handler(req: IncomingMessage, res: ServerResponse): void | Promise<void> }): () => void }\n connection: { requestRejection?: (request: IncomingMessage) => number | undefined }\n}\n\ntype Rejection = { status: number; body?: string }\n\nexport interface HostRpcTransportOptions {\n maxBodyBytes?: number\n isEndpoint?: (endpoint: string) => boolean\n caseInsensitiveContentType?: boolean\n emptyBodyAsNull?: boolean\n beforeBody?: (request: IncomingMessage, endpoint: string) => Rejection | undefined\n errorBody?: (status: number, error?: unknown) => string | undefined\n}\n\nexport interface HostRpcOptions extends HostRpcTransportOptions {\n requirePayload?: boolean\n}\n\n/** The shared authenticated HTTP boundary. Each plugin still owns its RPC envelope semantics. */\nexport function registerHostRpcTransport(\n ctx: HostRpcContext,\n channel: string,\n dispatch: (endpoint: string, body: unknown, signal: AbortSignal, response: ServerResponse) => void | Promise<void>,\n options: HostRpcTransportOptions = {},\n): () => void {\n const bodyLimit = options.maxBodyBytes ?? 64 * 1024\n if (!Number.isSafeInteger(bodyLimit) || bodyLimit <= 0) throw new Error('Invalid RPC body limit')\n const isEndpoint = options.isEndpoint ?? ((endpoint: string) => /^[a-z.]+$/.test(endpoint))\n return ctx.webServer.register({ kind: 'prefix', path: channel, handler: async (req, res) => {\n const reject = (status: number, error?: unknown, override?: string) => {\n if (res.destroyed) return\n if (status === 413) res.writeHead(status, { connection: 'close' })\n else res.writeHead(status)\n res.end(override ?? options.errorBody?.(status, error) ?? (status === 500 ? 'rpc request failed' : ''))\n }\n try {\n // Host admission always runs before plugin-specific checks or body reads.\n if (typeof ctx.connection.requestRejection !== 'function') { reject(503); return }\n const rejection = ctx.connection.requestRejection(req)\n if (rejection !== undefined) { reject(rejection); return }\n const pathname = new URL(req.url ?? '/', 'http://dsh.internal').pathname\n const endpoint = pathname.startsWith(`${channel}/`) ? pathname.slice(channel.length + 1) : ''\n if (req.method !== 'POST' || !isEndpoint(endpoint)) { reject(404); return }\n const contentType = String(req.headers['content-type'] ?? '').split(';', 1)[0]?.trim()\n if ((options.caseInsensitiveContentType ? contentType.toLowerCase() : contentType) !== 'application/json') {\n reject(415); return\n }\n const guarded = options.beforeBody?.(req, endpoint)\n if (guarded) { reject(guarded.status, undefined, guarded.body); return }\n\n const controller = new AbortController()\n res.on('close', () => { if (!res.writableEnded) controller.abort() })\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of req) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n size += buffer.length\n if (size > bodyLimit) { reject(413); req.destroy(); return }\n chunks.push(buffer)\n }\n let body: unknown\n try { body = JSON.parse(Buffer.concat(chunks).toString('utf8') || (options.emptyBodyAsNull ? 'null' : '')) }\n catch { reject(400); return }\n await dispatch(endpoint, body, controller.signal, res)\n } catch (error) {\n reject(500, error)\n }\n } })\n}\n\n/** Write the native Connection response envelope after a plugin has handled a request. */\nexport function sendHostRpcResponse(response: ServerResponse, rpcId: string, result: unknown, noStore = true): void {\n if (response.destroyed) return\n response.writeHead(200, { 'content-type': 'application/json', ...(noStore ? { 'cache-control': 'no-store' } : {}) })\n response.end(JSON.stringify({ type: 'server-response', rpcId, result }))\n}\n\n/** Safe host RPC registration. Missing requestRejection fails closed. */\nexport function registerHostRpc<R extends RpcResult = RpcResult>(\n ctx: HostRpcContext,\n channel: string,\n call: (endpoint: string, payload: unknown, signal: AbortSignal) => Promise<R>,\n options: HostRpcOptions = {},\n): () => void {\n return registerHostRpcTransport(ctx, channel, async (endpoint, body, signal, res) => {\n if (!body || typeof body !== 'object' || Array.isArray(body)) { res.writeHead(400); res.end(); return }\n const request = body as Record<string, unknown>\n if (request.type !== 'client-request' || request.method !== endpoint || typeof request.rpcId !== 'string'\n || (options.requirePayload && !Object.hasOwn(request, 'payload'))) {\n res.writeHead(400); res.end(); return\n }\n const raw = await call(endpoint, request.payload, signal)\n const result = raw.ok ? raw : { ...raw, error: { details: {}, ...raw.error } }\n sendHostRpcResponse(res, request.rpcId, result)\n }, options)\n}\n","import type { ModelRoute } from '@klarkxy/dsh-model-route'\n\n/** Built-in display copy; plain strings preserve third-party and user-provided text. */\nexport type ModelSettingsText = string | { zh: string; en: string }\n\n/** Plugin-owned model settings, independent of native volatile Config forms. */\nexport interface ModelSettingsField {\n path: string[]\n label: ModelSettingsText\n description?: ModelSettingsText\n current?: ModelRoute\n editable?: false\n allowFollow?: boolean\n followLabel?: ModelSettingsText\n}\nexport interface ModelSettingsSnapshot {\n revision: number\n fields: ModelSettingsField[]\n /** A separate model domain, e.g. external Codex; never use the DSH catalog here. */\n catalog?: unknown\n catalogError?: ModelSettingsText\n}\nexport interface ModelSettingsProvider {\n ns: string\n title: ModelSettingsText\n instanceId?: string\n read(signal: AbortSignal): ModelSettingsSnapshot | Promise<ModelSettingsSnapshot>\n write(path: readonly string[], route: ModelRoute, expectedRevision: number, signal: AbortSignal): Promise<unknown>\n}\n\nexport const MODEL_SETTINGS_EVENT = 'model-settings/collect'\nexport const MODEL_SETTINGS_CHANGED_EVENT = 'model-settings/changed'\nexport interface ModelSettingsChange { ns: string; revision: number }\n\n/** Publish only after the owner's save commits. A failed observer must never\n * turn an already committed write into an apparent save failure. */\nexport function notifyModelSettingsChanged(ctx: {\n parallel(name: typeof MODEL_SETTINGS_CHANGED_EVENT, change: ModelSettingsChange): Promise<void>\n}, ns: string, revision: number): void {\n try {\n // Cordis emit returns void and cannot contain an async observer rejection.\n void ctx.parallel(MODEL_SETTINGS_CHANGED_EVENT, { ns, revision }).catch(() => {})\n } catch { /* The save has already committed. */ }\n}\ntype Collector = (provider: ModelSettingsProvider) => void\nexport interface ModelSettingsEvents {\n on(name: typeof MODEL_SETTINGS_EVENT, callback: (collect: Collector) => void): () => void\n}\nexport interface ModelSettingsDiscovery {\n parallel(name: typeof MODEL_SETTINGS_EVENT, collect: Collector): Promise<void>\n}\n\n/** Cordis disposes the listener with its fiber. In-flight references also fail closed. */\nexport function registerModelSettings(ctx: ModelSettingsEvents, provider: ModelSettingsProvider): () => void {\n let active = true\n const requireActive = (signal: AbortSignal) => {\n signal.throwIfAborted()\n if (!active) throw new Error('Model settings owner unloaded; refresh and retry')\n }\n const guarded: ModelSettingsProvider = {\n ns: provider.ns, title: provider.title, instanceId: globalThis.crypto.randomUUID(),\n async read(signal) {\n requireActive(signal)\n const value = await provider.read(signal)\n requireActive(signal)\n return value\n },\n async write(path, route, revision, signal) {\n requireActive(signal)\n return provider.write(path, route, revision, signal)\n },\n }\n const off = ctx.on(MODEL_SETTINGS_EVENT, collect => { if (active) collect(guarded) })\n // Call this disposer from ctx.effect as well: listener removal alone does not\n // revoke a reference captured just before the owning plugin was unloaded.\n return () => { active = false; off() }\n}\n\nexport async function collectModelSettings(ctx: ModelSettingsDiscovery): Promise<ModelSettingsProvider[]> {\n const providers: ModelSettingsProvider[] = []\n const duplicates: string[] = []\n await ctx.parallel(MODEL_SETTINGS_EVENT, provider => {\n if (!provider.ns || providers.some(item => item.ns === provider.ns)) { duplicates.push(provider.ns); return }\n providers.push(provider)\n })\n if (duplicates.length) throw new Error(`Duplicate model settings owner: ${duplicates.join(', ')}`)\n return providers.sort((a, b) => a.ns.localeCompare(b.ns))\n}\n","import type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport { modelSettingsChangesIdentity, type ModelSettingsChangesIdentity } from './contracts.ts'\n\nexport type ModelSettingsChangeFrame = { kind: 'ready' } | { kind: 'changed'; ns: string; revision: number }\n\n/** This stream carries invalidations only; ready is never a settings snapshot. */\nexport function parseModelSettingsChangeFrame(value: unknown): ModelSettingsChangeFrame {\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid model settings change frame')\n const frame = value as Record<string, unknown>\n if (frame.kind === 'ready' && Object.keys(frame).length === 1) return { kind: 'ready' }\n if (frame.kind === 'changed' && Object.keys(frame).length === 3 && typeof frame.ns === 'string' && frame.ns.length > 0\n && typeof frame.revision === 'number' && Number.isSafeInteger(frame.revision) && frame.revision >= 0) {\n return { kind: 'changed', ns: frame.ns, revision: frame.revision }\n }\n throw new Error('Invalid model settings change frame')\n}\n\n/** One owner's contribution. Each package mounts only its own endpoint. */\nexport function modelSettingsChangesRemote(packageName: string, identity: ModelSettingsChangesIdentity = modelSettingsChangesIdentity(packageName)): TypertRemoteContribution {\n return {\n package: packageName,\n descriptors: [{\n id: `${identity.namespace}/watch`,\n service: identity.service,\n namespace: identity.namespace,\n method: 'watch',\n mode: 'stream' as const,\n invocation: { kind: 'direct' as const },\n parameters: [],\n cancellation: { parameter: 'signal' as const },\n result: { mode: 'strict' as const, typeSymbol: 'ModelSettings.ChangeFrame', create: () => ({ parse: parseModelSettingsChangeFrame }) },\n }],\n }\n}\n\ninterface RemoteMountScope {\n remote: { $mount(contribution: TypertRemoteContribution): Promise<() => Promise<void>> }\n effect(callback: () => () => void | Promise<void>): unknown\n}\ninterface RemoteMountContext {\n inject(dependencies: string[], callback: (scope: unknown) => void): unknown\n}\n\n/** Mount from a synchronous apply. Disposal waits for an in-flight mount and\n * then withdraws it, so the contribution cannot outlive the plugin. */\nexport function mountModelSettingsChanges(ctx: RemoteMountContext, packageName: string): void {\n const contribution = modelSettingsChangesRemote(packageName)\n ctx.inject(['remote'], injected => {\n const scope = injected as RemoteMountScope\n const mounting = scope.remote.$mount(contribution)\n void mounting.catch(() => {})\n scope.effect(() => async () => {\n const unmount = await mounting.catch(() => undefined)\n await unmount?.()\n })\n })\n}\n\ninterface StreamItem {\n generation: number\n value: unknown\n signal: AbortSignal\n accept(): void\n}\ninterface ChangeStream extends AsyncIterable<StreamItem> { dispose(): Promise<void> }\ntype OpenChangeStream = (options: {\n name: string\n open(signal: AbortSignal): AsyncIterable<unknown>\n ended(accepted: boolean): Error\n}) => ChangeStream\nexport interface ModelSettingsSubscriberScope {\n remote: { $stream: OpenChangeStream } & Record<string, { watch?(signal: AbortSignal): AsyncIterable<unknown> } | OpenChangeStream | undefined>\n effect(callback: () => () => void | Promise<void>): unknown\n}\nexport interface ModelSettingsSubscriberContext {\n inject(dependencies: string[], callback: (scope: unknown) => void): unknown\n}\nexport interface ModelSettingsSubscriber {\n subscribe(onChange: () => void, onError?: (message: string) => void): () => void\n}\n\n/** Native RemoteStream owns carrier reconnects; no timers or browser transport.\n * A factory shares one logical stream while at least one subscriber remains. */\nexport function createModelSettingsSubscriber(\n ctx: ModelSettingsSubscriberContext,\n packageName: string,\n identity: ModelSettingsChangesIdentity = modelSettingsChangesIdentity(packageName),\n accept: (ns: string) => boolean = ns => ns === packageName,\n): ModelSettingsSubscriber {\n const endpoint = identity\n const listeners = new Set<{ change: () => void; error?: (message: string) => void }>()\n let injection: { dispose(): void | Promise<void> } | undefined\n let current: { stream: ChangeStream; active: boolean } | undefined\n let lifecycle = 0\n let failureMessage: string | undefined\n const report = (message: string) => {\n failureMessage = message\n for (const listener of [...listeners]) {\n try { listener.error?.(message) } catch { /* Isolate page callbacks. */ }\n }\n }\n const invalidate = () => {\n for (const listener of [...listeners]) {\n if (!listeners.has(listener)) continue\n try { listener.change() } catch (error) {\n try { listener.error?.(error instanceof Error ? error.message : String(error)) } catch { /* Isolate callbacks. */ }\n }\n }\n }\n const start = () => {\n const life = ++lifecycle\n injection = ctx.inject(['remote', `remote.${endpoint.namespace}`], injected => {\n if (life !== lifecycle || !listeners.size) return\n const scope = injected as ModelSettingsSubscriberScope\n const service = scope.remote[endpoint.namespace]\n if (!service || !('watch' in service) || !service.watch) { report('Model settings sync service unavailable'); return }\n const watch = service.watch\n const stream = scope.remote.$stream({\n name: 'Model settings sync',\n open: signal => watch(signal),\n ended: accepted => new Error(`Model settings sync stream ended ${accepted ? 'after' : 'before'} ready; refresh or reopen the page`),\n })\n const session = { stream, active: true }\n current = session\n scope.effect(() => () => {\n session.active = false\n if (current === session) {\n current = undefined\n if (life === lifecycle && listeners.size) report('Model settings sync service unavailable')\n }\n return stream.dispose()\n })\n void (async () => {\n let generation: number | undefined\n let ready = false\n try {\n for await (const item of stream) {\n if (!session.active || life !== lifecycle || !listeners.size) break\n if (item.signal.aborted) continue\n if (generation !== item.generation) { generation = item.generation; ready = false }\n const frame = parseModelSettingsChangeFrame(item.value)\n if (frame.kind === 'ready') {\n ready = true\n failureMessage = undefined\n // Accept the validated invalidation baseline, not fetched data.\n // Every current listener queues its own latest settings read.\n item.accept()\n invalidate()\n } else {\n if (!ready) throw new Error('Model settings sync change arrived before ready')\n if (accept(frame.ns)) invalidate()\n }\n }\n } catch (error) {\n if (session.active && life === lifecycle) report(error instanceof Error ? error.message : String(error))\n } finally {\n if (current === session) current = undefined\n session.active = false\n await stream.dispose().catch(() => {})\n }\n })()\n }) as { dispose(): void | Promise<void> }\n queueMicrotask(() => {\n if (life === lifecycle && listeners.size && !current) report('Model settings sync service unavailable')\n })\n }\n return Object.freeze({ subscribe(onChange: () => void, onError?: (message: string) => void) {\n const listener = { change: onChange, error: onError }\n listeners.add(listener)\n if (!injection) start()\n else if (failureMessage) queueMicrotask(() => {\n if (listeners.has(listener) && failureMessage) {\n try { listener.error?.(failureMessage) } catch { /* Isolate callbacks. */ }\n }\n })\n return () => {\n if (!listeners.delete(listener) || listeners.size) return\n lifecycle++\n if (current) { current.active = false; void current.stream.dispose().catch(() => {}) }\n current = undefined\n failureMessage = undefined\n const previous = injection\n injection = undefined\n try { void Promise.resolve(previous?.dispose()).catch(() => {}) } catch { /* Already unloaded. */ }\n }\n } })\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport { Remote, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'\nimport type { ModelSettingsChangesIdentity } from './contracts.ts'\nimport { MODEL_SETTINGS_CHANGED_EVENT, type ModelSettingsChange } from './model-settings.ts'\nimport { parseModelSettingsChangeFrame, type ModelSettingsChangeFrame } from './model-settings-client.ts'\n\ninterface ChangeEvents {\n on(name: typeof MODEL_SETTINGS_CHANGED_EVENT, callback: (change: ModelSettingsChange) => void): () => void\n on(name: 'settings/document-updated', callback: (ns: string, revision: number) => void): () => void\n}\n\n/** Attach first, then yield ready: commits during a consumer's baseline read\n * remain queued. Coalescing revisions never invents a settings snapshot.\n * `ownerNs` keeps one plugin's stream to its own settings; omit it to forward every namespace. */\nexport async function* watchModelSettingsChanges(events: ChangeEvents, signal: AbortSignal, ownerNs?: string): AsyncGenerator<ModelSettingsChangeFrame> {\n signal.throwIfAborted()\n const pending = new Map<string, ModelSettingsChangeFrame>()\n let full = false\n let wake: (() => void) | undefined\n const changed = (ns: string, revision: number) => {\n if (ownerNs !== undefined && ns !== ownerNs) return\n let frame: ModelSettingsChangeFrame\n try { frame = parseModelSettingsChangeFrame({ kind: 'changed', ns, revision }) } catch { return }\n if (!full) {\n if (!pending.has(ns) && pending.size >= 256) { pending.clear(); full = true }\n else pending.set(ns, frame)\n }\n wake?.()\n }\n const disposers: (() => void)[] = []\n const cleanup = () => {\n for (const off of disposers.splice(0).reverse()) off()\n pending.clear()\n }\n // Release listeners even if the consumer is paused at a yielded frame.\n const aborted = () => { cleanup(); wake?.() }\n signal.addEventListener('abort', aborted, { once: true })\n try {\n disposers.push(events.on(MODEL_SETTINGS_CHANGED_EVENT, ({ ns, revision }) => changed(ns, revision)))\n disposers.push(events.on('settings/document-updated', changed))\n signal.throwIfAborted()\n yield { kind: 'ready' }\n while (true) {\n signal.throwIfAborted()\n if (full) { full = false; yield { kind: 'ready' }; continue }\n if (pending.size) {\n const [ns, frame] = pending.entries().next().value!\n pending.delete(ns)\n yield frame\n continue\n }\n await new Promise<void>(resolve => {\n wake = resolve\n if (signal.aborted || full || pending.size) resolve()\n })\n wake = undefined\n }\n } finally {\n signal.removeEventListener('abort', aborted)\n cleanup()\n }\n}\n\n/** One owner's invalidation stream, registered on the calling plugin fiber.\n * Nothing here is stored in a module-level singleton. */\nexport class ModelSettingsChangesController extends TypertRemoteService {\n private readonly lifetime = new AbortController()\n private readonly ownerNs: string | undefined\n constructor(ctx: Context, identity: ModelSettingsChangesIdentity, ownerNs?: string) {\n super(ctx, identity.service, { namespace: identity.namespace })\n this.ownerNs = ownerNs\n ctx.effect(() => () => { this.lifetime.abort(new Error('Model settings sync owner unloaded')) })\n }\n\n @Remote({ mode: 'stream' })\n watch(signal: AbortSignal): AsyncIterable<ModelSettingsChangeFrame> {\n return watchModelSettingsChanges(this.ctx as unknown as ChangeEvents, AbortSignal.any([this.lifetime.signal, signal]), this.ownerNs)\n }\n}\n\n/** Register this owner's controller. `ownerNs` limits the stream to that settings namespace. */\nexport function createModelSettingsChanges(ctx: Context, identity: ModelSettingsChangesIdentity, ownerNs?: string): ModelSettingsChangesController {\n return new ModelSettingsChangesController(ctx, identity, ownerNs)\n}\n","/**\n * Shared auxiliary-model default: host-side lifecycle.\n *\n * The default model is repository-shared infrastructure, not one plugin's\n * business state. Its owner is a dedicated Cordis fiber started on the root\n * context by the first participant and disposed by the last release, so the\n * storage domain, the Typert change stream, the RPC channel and the\n * model-settings provider all live and die with the shared owner — never\n * with a business plugin's fiber. Every bundler's own copy of this module\n * rendezvous through `ctx.root`, so no participant depends on another being\n * enabled.\n *\n * Concurrency:\n * - Writes serialize on `state.tail`; the revision check and the bump both\n * happen inside the queued commit, so two callers carrying the same\n * expectedRevision cannot both succeed.\n * - `state.closing` is the single teardown promise: it settles init, drains\n * queued writes, disposes the owner fiber (route, stream, provider,\n * domain) and only then unprovides the state, so a re-entrant retain can\n * always await it and reinstall cleanly.\n * - Initialization and stored-row failures are sticky (`state.error`) and\n * rethrow from `snapshot()`: a storage error must never read as \"no\n * default\" and silently fall back to another model.\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { modelRouteOverride, normalizeModelRoute, type ModelRoute } from '@klarkxy/dsh-model-route'\nimport {\n AUXILIARY_MODEL_CHANNEL, AUXILIARY_MODEL_CHANGES_IDENTITY, AUXILIARY_MODEL_NS,\n AUXILIARY_MODEL_SERVICE, type AuxiliaryModelDefaults, type AuxiliaryModelShared, type RpcResult,\n} from './contracts.ts'\nimport { registerHostRpc, type HostRpcContext } from './host-rpc.ts'\nimport { createModelSettingsChanges } from './model-settings-changes.ts'\nimport { registerModelSettings, notifyModelSettingsChanged, type ModelSettingsEvents } from './model-settings.ts'\n\nconst DOMAIN_NAME = 'dsh_auxiliary'\nconst DOMAIN_VERSION = 1\nconst TABLE = 'settings'\nconst KEY = 'defaults'\nconst INJECT = ['storageDomain', 'webServer', 'connection'] as const\n\ninterface DomainHandle {\n table(name: string): {\n get(key: string): { revision: number; model: ModelRoute | null } | undefined\n put(key: string, value: unknown): Promise<void>\n }\n close(): Promise<void>\n}\n\ninterface Scope extends HostRpcContext, ModelSettingsEvents {\n storageDomain: { open(spec: unknown): Promise<DomainHandle> }\n effect(callback: () => (() => void) | Promise<(() => void) | void>): unknown\n}\n\ninterface RootLike {\n get(name: string, strict?: boolean): unknown\n provide(name: string, value: unknown): () => void\n inject(deps: readonly string[], callback: (scope: Scope) => void): { dispose(): Promise<void> } & PromiseLike<unknown>\n}\n\ninterface SharedState extends AuxiliaryModelShared {\n ready: Promise<void>\n users: number\n closed: boolean\n /** True only while the owner fiber's domain is open; snapshot() gates on it. */\n available: boolean\n /** Generation of the latest scope init; a stale run must not win. */\n generation: number\n /** Sticky init/storage failure; snapshot() rethrows it. */\n error?: unknown\n closing?: Promise<void>\n domain?: DomainHandle\n data: AuxiliaryModelDefaults\n tail: Promise<void>\n fiber?: { dispose(): Promise<void> }\n scopeInit?: Promise<void>\n stopUnprovide?: () => void\n teardown(): Promise<void>\n}\n\n/** Marker on the benign \"released while the domain was still opening\" error. */\nconst RECOVERABLE = Symbol.for('klarkxy.dsh.auxiliary-model.recoverable')\nfunction recoverable<T extends object>(error: T): T & { [RECOVERABLE]?: boolean } {\n (error as Record<symbol, unknown>)[RECOVERABLE] = true\n return error as T & { [RECOVERABLE]?: boolean }\n}\n\nasync function openSharedDomain(scope: Scope): Promise<DomainHandle> {\n const [{ defineDomain, domainTable }, { z }] = await Promise.all([\n import('@deepseek-ai/dsh-storage-domain'), import('zod'),\n ])\n // Strict, write-side semantics at the durable boundary: identifiers must be\n // non-blank, already trimmed and control-free, or the row is rejected —\n // a malformed stored route must never normalize into \"no default\".\n const identifier = z.string().min(1).max(250).refine(\n value => value === value.trim() && !/[\\x00-\\x1f\\x7f]/.test(value),\n 'model route identifiers must be non-blank, trimmed and control-free',\n )\n const model = z.union([\n z.object({\n provider: identifier,\n model: identifier,\n reasoningEffort: identifier.max(80).optional(),\n }).strict(),\n z.null(),\n ])\n return scope.storageDomain.open(defineDomain({\n name: DOMAIN_NAME, version: DOMAIN_VERSION,\n tables: {\n [TABLE]: domainTable(z.object({\n revision: z.number().int().nonnegative(),\n model,\n }).strict()),\n },\n }))\n}\n\n/** Marks an optimistic-lock conflict so the RPC envelope can carry 'conflict'. */\nfunction conflictError(message: string): Error & { conflict: true } {\n return Object.assign(new Error(message), { conflict: true as const })\n}\n\n/** RPC-visible error classification; storage failures stay sanitized. */\nfunction rpcFailure(error: unknown): RpcResult {\n if (error && typeof error === 'object' && 'conflict' in error) {\n return { ok: false, error: { code: 'auxiliary-model/conflict', message: error instanceof Error ? error.message : 'Revision conflict' } }\n }\n if (error instanceof Error && /Invalid model route|valid expected revision|Unknown auxiliary model setting/.test(error.message)) {\n return { ok: false, error: { code: 'auxiliary-model/rejected', message: error.message } }\n }\n return { ok: false, error: { code: 'auxiliary-model/store', message: 'Auxiliary model store request failed' } }\n}\n\n/**\n * Serialized optimistic-lock write; resolves after the durable put commits.\n * Revision verification happens inside the queue: two writers carrying the\n * same expectedRevision race for one slot and only the first commits.\n * Notification fires only after commit, so a failed observer can never turn\n * an already committed write into an apparent save failure.\n */\nfunction setSharedModel(state: SharedState, ctx: Context, input: unknown, expectedRevision: unknown): Promise<AuxiliaryModelDefaults> {\n if (!Number.isSafeInteger(expectedRevision)) return Promise.reject(conflictError('A valid expected revision is required; reload and retry'))\n const row = input && typeof input === 'object' && !Array.isArray(input) ? input as Record<string, unknown> : undefined\n const validField = (value: unknown): value is string =>\n typeof value === 'string' && value === value.trim() && !/[\\x00-\\x1f\\x7f]/.test(value)\n if (!row || ['provider', 'model', 'reasoningEffort'].some(key => row[key] !== undefined && !validField(row[key]))) {\n return Promise.reject(new Error('Invalid model route'))\n }\n const normalized = normalizeModelRoute(row)\n if ((Boolean(row.provider) || Boolean(row.model)) && !modelRouteOverride(normalized)) {\n return Promise.reject(new Error('Invalid model route'))\n }\n const commit = state.tail.then(async (): Promise<AuxiliaryModelDefaults> => {\n if (state.closed || !state.domain) throw new Error('Auxiliary model settings are unloading; retry in a moment')\n if (expectedRevision !== state.data.revision) throw conflictError('Auxiliary model settings changed; reload and retry')\n const next: AuxiliaryModelDefaults = { revision: state.data.revision + 1, model: modelRouteOverride(normalized) ?? null }\n await state.domain.table(TABLE).put(KEY, { revision: next.revision, model: next.model })\n state.data = next\n notifyModelSettingsChanged(ctx.root, AUXILIARY_MODEL_NS, next.revision)\n return next\n })\n // The tail itself never rejects: a failed commit must not poison later writes.\n state.tail = commit.then(() => {}, () => {})\n return commit\n}\n\nfunction initScope(state: SharedState, ctx: Context, scope: Scope): Promise<void> {\n // A dependency loss unloads this fiber (running its disposers) and a\n // remount re-runs the callback (bumping state.generation), so an init that\n // was still opening always detects its own supersession through these two\n // public signals. Service identity is intentionally NOT compared anywhere:\n // `ctx.<service>` reads hand out a fresh traceable proxy per access for\n // every tracker'd impl (all Service subclasses — storageDomain, webServer,\n // connection), so identity comparisons reported a fake dep swap after each\n // await and aborted every open with 'released during open'.\n const generation = ++state.generation\n let disposed = false\n // Registered synchronously while the callback runs; a throw means the\n // fiber is already inactive and this init must not open anything.\n scope.effect(() => () => { disposed = true })\n const stale = () => state.closed || disposed || state.generation !== generation\n const run = (async () => {\n // Reads must stay unavailable until this init completes.\n state.available = false\n const domain = await openSharedDomain(scope)\n if (stale()) { await domain.close(); throw recoverable(new Error('Auxiliary model store released during open')) }\n state.domain = domain\n // scope.effect throws on an inactive fiber (disposed mid-open): close the\n // domain directly so it is never leaked, then rethrow — a store that\n // cannot register its own cleanup must not publish data.\n try { scope.effect(() => () => domain.close()) } catch (error) { await domain.close(); throw error }\n // Strict schema: a malformed stored row fails the open path instead of\n // silently collapsing to \"no default\".\n const stored = domain.table(TABLE).get(KEY)\n if (stale()) { await domain.close(); throw recoverable(new Error('Auxiliary model store superseded during open')) }\n state.data = { revision: stored?.revision ?? 0, model: stored?.model ?? null }\n state.error = undefined\n state.available = true\n scope.effect(() => registerModelSettings(scope, {\n ns: AUXILIARY_MODEL_NS,\n title: { zh: '辅助模型', en: 'Auxiliary model' },\n read(signal) {\n signal.throwIfAborted()\n const { revision, model } = state.data\n return {\n revision,\n fields: [{\n path: ['model'],\n label: { zh: '全局辅助模型', en: 'Global auxiliary model' },\n current: model ?? undefined,\n allowFollow: true,\n followLabel: { zh: '当前会话模型', en: 'Current conversation model' },\n }],\n }\n },\n async write(path, route, expectedRevision, signal) {\n signal.throwIfAborted()\n if (path.length !== 1 || path[0] !== 'model') throw new Error('Unknown auxiliary model setting')\n return setSharedModel(state, ctx, route, expectedRevision)\n },\n }))\n scope.effect(() => registerHostRpc(scope, AUXILIARY_MODEL_CHANNEL, async (endpoint, payload, signal) => {\n signal.throwIfAborted()\n if (state.closed) return { ok: false, error: { code: 'auxiliary-model/unloading', message: 'Auxiliary model settings are unloading; retry in a moment' } } satisfies RpcResult\n if (!state.available) {\n return state.error\n ? { ok: false, error: { code: 'auxiliary-model/store', message: 'Auxiliary model store request failed' } } satisfies RpcResult\n : { ok: false, error: { code: 'auxiliary-model/unavailable', message: 'Auxiliary model settings are unavailable; retry in a moment' } } satisfies RpcResult\n }\n if (endpoint === 'defaults.get') {\n const { revision, model } = state.data\n return { ok: true, value: { revision, model } } satisfies RpcResult\n }\n if (endpoint === 'defaults.set') {\n try {\n const body = payload && typeof payload === 'object' && !Array.isArray(payload) ? payload as Record<string, unknown> : {}\n const value = await setSharedModel(state, ctx, body.model, body.expectedRevision)\n signal.throwIfAborted()\n return { ok: true, value } satisfies RpcResult\n } catch (error) {\n if (signal.aborted) throw error\n return rpcFailure(error)\n }\n }\n return { ok: false, error: { code: 'auxiliary-model/unknown-endpoint', message: `Unknown endpoint: ${endpoint}` } } satisfies RpcResult\n }, { isEndpoint: endpoint => /^[a-z.]+$/.test(endpoint) }))\n // The change stream lives and dies with this shared fiber.\n createModelSettingsChanges(scope as unknown as Context, AUXILIARY_MODEL_CHANGES_IDENTITY, AUXILIARY_MODEL_NS)\n // Disposers run LIFO on unload: registered last, this runs FIRST when a\n // dependency remount tears the scope down — reads go unavailable before\n // the domain closes, so no stale default ever leaks. Gated on generation\n // alone: the same generation's unload must clear state even when its dep\n // impl just changed; only a superseded scope's teardown stays out.\n scope.effect(() => () => { if (state.generation === generation) { state.available = false; state.domain = undefined } })\n })().catch(error => {\n // Tag the failure with its generation so ready.catch can distinguish a\n // superseded init's rejection from the live scope's.\n if (error && typeof error === 'object') (error as Record<string, unknown>).auxGeneration = generation\n // Only THIS generation's failure poisons the store: a superseded init's\n // rejection must not clear a newer scope's available state.\n if (state.generation === generation) {\n state.available = false\n state.error = error\n }\n throw error\n })\n // Retainers always await the CURRENT init: re-arm state.ready so nobody is\n // left waiting on a superseded generation's settled promise. Both promises\n // get a handled branch so a rejected init never surfaces as an unhandled\n // rejection while awaiters still see it.\n run.catch(() => {})\n const armed = run.then(() => {})\n armed.catch(() => {})\n state.ready = armed\n return run\n}\n\nfunction teardown(state: SharedState, ctx: Context): Promise<void> {\n if (!state.closing) {\n state.closed = true\n const root = ctx.root as unknown as RootLike\n state.closing = (async () => {\n // A still-opening init settles here so its domain/fiber are disposed.\n await state.scopeInit?.catch(() => {})\n await state.tail.catch(() => {})\n try { await state.fiber?.dispose() } catch (error) {\n // A failed dispose may leave the domain open; log loudly so the next\n // open's 'already open' error is attributable instead of mysterious.\n try { (ctx as unknown as { logger?: { warn(...args: unknown[]): void } }).logger?.warn('auxiliary-model: fiber dispose failed', error) }\n catch { /* no logger */ }\n }\n try {\n if (root.get(AUXILIARY_MODEL_SERVICE, false) === state) state.stopUnprovide?.()\n } catch { /* root already gone */ }\n state.stopUnprovide = undefined\n })()\n }\n return state.closing\n}\n\nfunction createSharedState(ctx: Context): SharedState {\n const root = ctx.root as unknown as RootLike\n const state: SharedState = {\n users: 0, closed: false, available: false, generation: 0, tail: Promise.resolve(),\n data: { revision: 0, model: null },\n snapshot() {\n // A persisted-open failure propagates: falling back to another model\n // after a storage error would silently switch what the user pays for.\n if (this.error) throw this.error\n // While the owner fiber re-initializes after a dependency remount, the\n // stored default is unreadable: reads fail instead of serving stale data.\n if (!this.available) throw new Error('Auxiliary model store is unavailable; retry in a moment')\n return this.data\n },\n ready: Promise.resolve(),\n teardown() { return teardown(this, ctx) },\n }\n // Strict requirement: every service must already be ACTIVE. Callers are\n // plugins declaring these in inject — Cordis only runs their apply once the\n // deps are active, so a missing or still-pending service is a hard error,\n // not something to wait on. Retry is the caller's Cordis lifecycle, not ours.\n const inactive = INJECT.filter(service => {\n try { return root.get(service, true) === undefined } catch { return true }\n })\n if (inactive.length) {\n throw new Error(`retainAuxiliaryModel requires active ${inactive.join(', ')}; declare them in inject`)\n }\n state.fiber = root.inject(INJECT, scope => { state.scopeInit = initScope(state, ctx, scope) })\n state.ready = Promise.resolve(state.fiber).then(() => {\n // The owner fiber ran to settle: its scope must have started init, and\n // that init must complete before the store reads as ready. A dep dropping\n // between the strict check and inject leaves the fiber PENDING; Cordis\n // re-runs it when the dep returns — never a silent half-initialized read.\n if (!state.scopeInit) throw recoverable(new Error('Auxiliary model owner fiber settled without initializing its scope'))\n return state.scopeInit\n })\n // A failed open must not leave a live-looking state behind: mark it\n // closed and tear it down so the next retain reinstalls. A rejection\n // tagged with a superseded generation describes a scope this state has\n // already moved past — it must not tear down a newer, live scope.\n state.ready.catch(error => {\n const tag = (error as { auxGeneration?: number }).auxGeneration\n if (tag !== undefined && tag !== state.generation) return\n state.error = state.error ?? error\n state.closed = true\n void state.teardown()\n })\n // Publish only after construction completes: another retainer can now\n // either reuse this state or watch its closed flag.\n state.stopUnprovide = root.provide(AUXILIARY_MODEL_SERVICE, state)\n return state\n}\n\nasync function obtainShared(ctx: Context): Promise<SharedState> {\n const root = ctx.root as unknown as RootLike\n for (;;) {\n const existing = root.get(AUXILIARY_MODEL_SERVICE, false) as SharedState | undefined\n if (existing) {\n if (!existing.closed) return existing\n // closing always settles; wait for it, then re-lookup.\n await existing.closing\n continue\n }\n return createSharedState(ctx)\n }\n}\n\n/**\n * Retain the shared auxiliary-model store for the calling plugin.\n *\n * Resolves once storage is open and the read/write surfaces are live, with a\n * release function; register it as `ctx.effect(() => release)` so the store\n * unloads with the plugin. The first participant opens the shared owner\n * fiber; `await release()` drains pending writes and fully tears the owner\n * down when the last participant leaves. Requires `storageDomain`,\n * `webServer` and `connection` to exist on the host.\n *\n * Concurrent retainers share one owner; a retain arriving during teardown\n * waits for the closing owner and then reinstalls — it never inherits a\n * half-torn-down state.\n */\nexport async function retainAuxiliaryModel(ctx: Context): Promise<() => Promise<void>> {\n for (;;) {\n const state = await obtainShared(ctx)\n // One await, one answer: a failed or superseded init rejects the retainer\n // once. The caller's plugin lifecycle (inject refresh) drives any retry —\n // no same-state spin here.\n await state.ready\n if (state.closed) continue\n state.users += 1\n let released = false\n return async () => {\n if (released) return\n released = true\n state.users -= 1\n if (state.users <= 0) await state.teardown()\n else await state.tail.catch(() => {})\n }\n }\n}\n\n/**\n * Re-exported here so consumers reading the shared default use the same\n * subpath as the store lifecycle: '@klarkxy/dsh-plugin-kit/auxiliary-model'.\n */\nexport { getAuxiliaryModel } from './contracts.ts'\n","/**\n * Auxiliary request-context packing for feature model calls.\n *\n * A feature may prepend stable material (session facts, its own durable\n * records) to the live request so provider-side caching reuses one prefix.\n * Three invariants keep this honest and testable:\n *\n * - Material is rebuilt by the caller from current facts on every call;\n * nothing here stores, accumulates or replays model outputs.\n * - Order is caller-owned: stable material first, live request last.\n * - A context that exceeds its byte budget fails loudly instead of\n * silently dropping evidence.\n *\n * Pure and browser-safe: no host imports.\n */\n\n/** Thrown when packed context exceeds the caller's byte budget. */\nexport class AuxiliaryContextTooLargeError extends Error {\n readonly bytes: number\n readonly maxBytes: number\n constructor(bytes: number, maxBytes: number) {\n super(`Auxiliary context is ${bytes} bytes, over the ${maxBytes}-byte budget.`)\n this.name = 'AuxiliaryContextTooLargeError'\n this.bytes = bytes\n this.maxBytes = maxBytes\n }\n}\n\nconst utf8 = new TextEncoder()\n\nfunction byteLength(text: string): number {\n return utf8.encode(text).byteLength\n}\n\nfunction normalizeSegments(context: string | readonly string[] | undefined): readonly string[] {\n if (context === undefined) return []\n const list: readonly string[] = typeof context === 'string' ? [context] : context\n return list.filter(segment => typeof segment === 'string' && segment.length > 0)\n}\n\n/**\n * Join stable material segments for one request. The packed text must fit\n * `maxBytes` or the call throws — the caller decides what to drop, so\n * evidence is never silently truncated. Empty input packs to ''.\n */\nexport function packAuxiliaryContext(segments: readonly string[], maxBytes: number): string {\n if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) throw new Error('Invalid auxiliary context budget')\n const text = normalizeSegments(segments).join('\\n')\n if (byteLength(text) > maxBytes) throw new AuxiliaryContextTooLargeError(byteLength(text), maxBytes)\n return text\n}\n\n/** Only word characters, dots, colons and dashes are kept inside the feature attribute. */\nfunction featureAttribute(feature: string): string {\n return feature.replaceAll(/[^\\w.:-]/g, '_')\n}\n\n/**\n * Assemble the single user message for an auxiliary model call: stable\n * material in one labelled block first, the live request last. With no\n * context the result is byte-identical to `text`, so callers without\n * material keep exactly the previous wire shape.\n */\nexport function buildAuxiliaryUserText(request: {\n feature?: string\n context?: string | readonly string[]\n text: string\n}): string {\n const context = normalizeSegments(request.context)\n if (!context.length) return request.text\n const attribute = request.feature ? ` feature=\"${featureAttribute(request.feature)}\"` : ''\n return `<auxiliary-context${attribute}>\\n${context.join('\\n')}\\n</auxiliary-context>\\n<request>\\n${request.text}\\n</request>`\n}\n","import {\n BlockAssembler, ReasoningEffortId, createUserMessage,\n type GenerateOptions, type LlmRuntime, type StreamChunk,\n} from '@deepseek-ai/dsh-llm'\nimport { getAuxiliaryModel, producerMessageSource, type ModelRoute } from './contracts.ts'\nimport { buildAuxiliaryUserText } from './auxiliary-context.ts'\n\n/** A feature's own saved model. Empty means the host default chat model. */\nexport interface FeatureModelRoute {\n readonly provider: string\n readonly model: string\n readonly reasoningEffort?: string\n}\n\nexport type LlmTextCaller = Pick<LlmRuntime, 'prepareCall' | 'resolveCallConfig'>\n\nexport interface LlmTextRequest {\n plugin: string\n /** Optional feature id, stamped on the context envelope for attribution. */\n feature?: string\n /**\n * Stable material rebuilt from current facts (session events, durable\n * records). Packed before the live text so provider-side caching reuses\n * the prefix; never model outputs or approval history. Strings or\n * pre-ordered segments.\n */\n context?: string | readonly string[]\n route: FeatureModelRoute\n system: string\n text: string\n maxTokens: number\n signal: AbortSignal\n /** The real session id for host attribution; never a feature-scoped alias. */\n sessionId?: string\n /** Auxiliary-call marker adapters may special-case (e.g. disable thinking for titles). */\n purpose?: GenerateOptions['purpose']\n /** Pure control selection using the exact model captured for this call. */\n configure?: Parameters<LlmRuntime['prepareCall']>[2]\n /** Rechecked before the call returns text. A false result discards the output. */\n isCurrent?: () => boolean\n}\n\nexport interface LlmTextResult {\n text: string\n provider: string\n model: string\n inputTokens?: number\n outputTokens?: number\n totalTokens?: number\n cacheReadTokens?: number\n cacheWriteTokens?: number\n reasoningTokens?: number\n}\n\ntype SessionModelsHost = {\n agents?: { get(sessionId: string): { session?: { requestHeader?: () => { config?: ModelRoute; adapterDefaults?: { reasoningEffort?: unknown } } | undefined } } | undefined }\n sessionProjections?: { stateOf(session: unknown, key: string): { pending?: ModelRoute | null } | undefined }\n agentDefaultModel?: { currentSelection(): ModelRoute | undefined }\n}\n\nfunction routeOf(value: { provider?: unknown; model?: unknown; reasoningEffort?: unknown } | undefined): FeatureModelRoute | undefined {\n if (typeof value?.provider !== 'string' || !value.provider.trim()) return undefined\n if (typeof value.model !== 'string' || !value.model.trim()) return undefined\n const effort = typeof value.reasoningEffort === 'string' ? value.reasoningEffort.trim() : ''\n return effort\n ? { provider: value.provider.trim(), model: value.model.trim(), reasoningEffort: effort }\n : { provider: value.provider.trim(), model: value.model.trim() }\n}\n\n/**\n * Plugin selection first; then the shared auxiliary default (when any\n * participant retains it); otherwise the live session model, then the host\n * default. Cordis callers must declare agents, sessionProjections and\n * agentDefaultModel in their inject list so the fallback reads use the\n * caller's live services.\n */\nexport function resolveFeatureModel(host: unknown, saved: FeatureModelRoute | undefined, sessionId?: string): FeatureModelRoute | undefined {\n const explicit = routeOf(saved)\n if (explicit) return explicit\n const auxiliary = getAuxiliaryModel(host)\n if (auxiliary) return auxiliary\n const face = host as SessionModelsHost | undefined\n if (sessionId && face?.agents && face.sessionProjections) {\n const session = face.agents.get(sessionId)?.session\n if (session) {\n try {\n const pending = face.sessionProjections.stateOf(session, 'modelSelection')?.pending\n const selected = routeOf(pending ?? undefined)\n if (selected) return selected\n } catch { /* fall through to the recorded route */ }\n const header = session.requestHeader?.()\n const recorded = header?.config\n if (recorded) {\n const selected = header?.adapterDefaults?.reasoningEffort === true\n ? { provider: recorded.provider, model: recorded.model }\n : recorded\n const route = routeOf(selected)\n if (route) return route\n }\n }\n }\n return routeOf(face?.agentDefaultModel?.currentSelection())\n}\n\nfunction joinText(assembler: BlockAssembler): string {\n return assembler.blocks()\n .filter((block): block is { type: 'text'; text: string } => block.type === 'text')\n .map(block => block.text)\n .join('')\n}\n\nasync function readStream(stream: AsyncIterable<StreamChunk>, signal: AbortSignal, live: () => boolean): Promise<BlockAssembler> {\n const assembler = new BlockAssembler()\n const iterator = stream[Symbol.asyncIterator]()\n try {\n while (live()) {\n if (signal.aborted) break\n const item = await iterator.next()\n if (item.done) break\n assembler.push(item.value)\n }\n } finally {\n // Settlement includes producer cleanup; never leave a detached return()\n // running after the caller has released its lifecycle ownership.\n await iterator.return?.()\n }\n return assembler\n}\n\n/** One native model call. No retry, timeout policy, or provider queue. */\nexport async function callLlmText(llm: LlmTextCaller, request: LlmTextRequest): Promise<LlmTextResult> {\n request.signal.throwIfAborted()\n const live = () => request.isCurrent?.() !== false && !request.signal.aborted\n if (!live()) throw Object.assign(new Error('调用已取消。'), { name: 'AbortError' })\n const effort = request.route.reasoningEffort?.trim()\n const prepared = await llm.prepareCall({\n provider: request.route.provider,\n model: request.route.model,\n ...(effort ? { reasoningEffort: ReasoningEffortId(effort) } : {}),\n maxTokens: request.maxTokens,\n }, request.signal, request.configure)\n if (!live()) throw Object.assign(new Error('调用已取消。'), { name: 'AbortError' })\n const options: GenerateOptions = {\n provider: prepared.config.provider,\n model: prepared.config.model,\n ...(prepared.config.reasoningEffort ? { reasoningEffort: prepared.config.reasoningEffort } : {}),\n ...(prepared.config.maxTokens !== undefined ? { maxTokens: Math.min(request.maxTokens, prepared.config.maxTokens) } : { maxTokens: request.maxTokens }),\n ...(prepared.config.temperature !== undefined ? { temperature: prepared.config.temperature } : {}),\n ...(prepared.config.stop ? { stop: [...prepared.config.stop] } : {}),\n system: request.system,\n messages: [createUserMessage({\n source: producerMessageSource(request.plugin),\n content: [{ type: 'text', text: buildAuxiliaryUserText(request) }],\n })],\n signal: request.signal,\n ...(request.purpose ? { purpose: request.purpose } : {}),\n ...(request.sessionId ? { sessionId: request.sessionId as GenerateOptions['sessionId'] } : {}),\n }\n const assembler = await readStream(prepared.stream(options), request.signal, live)\n if (request.signal.aborted || assembler.finish.kind === 'aborted') {\n throw Object.assign(new Error('调用已取消。'), { name: 'AbortError' })\n }\n if (!live()) throw Object.assign(new Error('调用已取消。'), { name: 'AbortError' })\n if (assembler.finish.kind === 'error') {\n const code = assembler.finish.failure.code\n throw Object.assign(new Error(assembler.finish.failure.message || '模型调用失败。'), { code })\n }\n if (assembler.blocks().some(block => block.type === 'tool-call') || assembler.finish.kind === 'tool-calls') {\n throw new Error('这次调用不使用工具。')\n }\n if (assembler.finish.kind !== 'stop') throw new Error('模型调用未完成。')\n // Every usable host usage field passes through; absent fields stay absent\n // (the caller's accounting must not see invented zeros).\n const usage = assembler.usage\n return {\n text: joinText(assembler),\n provider: prepared.config.provider,\n model: prepared.config.model,\n ...(usage ? {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n ...(usage.totalTokens !== undefined ? { totalTokens: usage.totalTokens } : {}),\n ...(usage.cacheReadTokens !== undefined ? { cacheReadTokens: usage.cacheReadTokens } : {}),\n ...(usage.cacheWriteTokens !== undefined ? { cacheWriteTokens: usage.cacheWriteTokens } : {}),\n ...(usage.reasoningTokens !== undefined ? { reasoningTokens: usage.reasoningTokens } : {}),\n } : {}),\n }\n}\n","import type { TitleMessage } from './contracts.ts'\n\nexport const FRAME_PREFIX =\n 'Choose the current task from these recent human messages, ordered oldest to newest:\\n'\n\nexport function frameMessages(messages: readonly TitleMessage[]): string {\n return `${FRAME_PREFIX}${JSON.stringify(messages)}`\n}\n\nexport function utf8Bytes(value: string): number {\n return Buffer.byteLength(value, 'utf8')\n}\n\nfunction middleSlice(codePoints: readonly string[], kept: number): string {\n if (kept >= codePoints.length) return codePoints.join('')\n if (kept <= 0) return ''\n if (kept === 1) return '…'\n\n const contentPoints = kept - 1\n const headCount = Math.ceil(contentPoints / 2)\n const tailCount = Math.floor(contentPoints / 2)\n return `${codePoints.slice(0, headCount).join('')}…${\n tailCount === 0 ? '' : codePoints.slice(-tailCount).join('')\n }`\n}\n\nexport function fitSingleMessage(message: TitleMessage, maxInputBytes: number): TitleMessage {\n const empty = { ...message, text: '' }\n if (utf8Bytes(frameMessages([empty])) > maxInputBytes) {\n throw new Error('dsh-current-title: maxInputBytes is too small for the input envelope')\n }\n if (utf8Bytes(frameMessages([message])) <= maxInputBytes) return message\n\n const points = Array.from(message.text)\n let low = 0\n let high = points.length\n let best = ''\n\n while (low <= high) {\n const kept = Math.floor((low + high) / 2)\n const text = middleSlice(points, kept)\n if (utf8Bytes(frameMessages([{ ...message, text }])) <= maxInputBytes) {\n best = text\n low = kept + 1\n } else {\n high = kept - 1\n }\n }\n\n return { ...message, text: best }\n}\n\nexport function selectRecentMessages(\n messages: readonly TitleMessage[],\n maxRecentMessages: number,\n maxInputBytes: number,\n): TitleMessage[] {\n if (messages.length === 0) return []\n\n const selected = messages.slice(-maxRecentMessages).map(message => ({ ...message }))\n while (selected.length > 1 && utf8Bytes(frameMessages(selected)) > maxInputBytes) {\n selected.shift()\n }\n\n if (utf8Bytes(frameMessages(selected)) > maxInputBytes) {\n selected[0] = fitSingleMessage(selected[0]!, maxInputBytes)\n }\n\n return selected\n}\n","export const TITLE_TYPE_KEYS = [\n 'feature',\n 'fix',\n 'optimize',\n 'refactor',\n 'test',\n 'docs',\n 'release',\n 'config',\n 'explore',\n 'discuss',\n] as const\n\nexport const TITLE_LOCALES = ['zh', 'en'] as const\nexport const TITLE_LOCALE_MODES = ['auto', ...TITLE_LOCALES] as const\n\nexport type TitleType = (typeof TITLE_TYPE_KEYS)[number]\nexport type TitleLocale = (typeof TITLE_LOCALES)[number]\nexport type TitleLocaleMode = (typeof TITLE_LOCALE_MODES)[number]\n\nconst TITLE_TYPE_LABELS: Record<TitleLocale, Record<TitleType, string>> = {\n zh: {\n feature: '功能',\n fix: '修复',\n optimize: '优化',\n refactor: '重构',\n test: '测试',\n docs: '文档',\n release: '发布',\n config: '配置',\n explore: '探索',\n discuss: '讨论',\n },\n en: {\n feature: 'Feature',\n fix: 'Fix',\n optimize: 'Optimize',\n refactor: 'Refactor',\n test: 'Test',\n docs: 'Docs',\n release: 'Release',\n config: 'Config',\n explore: 'Explore',\n discuss: 'Discussion',\n },\n}\n\nexport interface ParsedTitle {\n type: TitleType\n summary: string\n}\n\nconst OSC_SEQUENCE = /(?:\\u001B\\]|\\u009D)(?:(?!\\u0007|\\u001B\\\\)[\\s\\S])*(?:\\u0007|\\u001B\\\\|$)/gu\nconst CSI_SEQUENCE = /(?:\\u001B\\[|\\u009B)[0-?]*[ -/]*[@-~]/gu\nconst ESC_SEQUENCE = /\\u001B[@-_]/gu\nconst CONTROL_CHARACTER = /[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u009F]/gu\nconst DIRECTIONAL_CONTROL = /[\\u200B\\u200E\\u200F\\u202A-\\u202E\\u2060-\\u2064\\u2066-\\u206F\\uFEFF]/gu\n\nfunction cleanTitleText(input: string): string {\n return input\n .replace(OSC_SEQUENCE, '')\n .replace(CSI_SEQUENCE, '')\n .replace(ESC_SEQUENCE, '')\n .replace(CONTROL_CHARACTER, '')\n .replace(DIRECTIONAL_CONTROL, '')\n .replace(/\\s+/gu, ' ')\n .trim()\n}\n\nexport function truncateTitleUtf8(input: string, maxBytes: number): string {\n if (!Number.isInteger(maxBytes) || maxBytes <= 0) throw new Error('maxBytes must be a positive integer')\n if (Buffer.byteLength(input, 'utf8') <= maxBytes) return input\n let used = 0\n let output = ''\n for (const character of input) {\n const bytes = Buffer.byteLength(character, 'utf8')\n if (used + bytes > maxBytes) break\n output += character\n used += bytes\n }\n return output\n}\n\n/** Same sanitizing rules as DSH 0.1.7-rc.2 `normalizeSessionTitle`. */\nexport function normalizeSessionTitle(input: string, maxBytes: number): string {\n return truncateTitleUtf8(cleanTitleText(input), maxBytes).trimEnd()\n}\n\nfunction isTitleType(value: string): value is TitleType {\n return (TITLE_TYPE_KEYS as readonly string[]).includes(value)\n}\n\nexport function resolveTitleLocale(\n mode: TitleLocaleMode,\n messages: readonly string[],\n preference?: string,\n): TitleLocale {\n if (mode !== 'auto') return mode\n\n const preferred = preference?.trim().toLowerCase().split('-')[0]\n if (preferred === 'zh' || preferred === 'en') return preferred\n\n const text = messages.join('\\n')\n if (/[\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]/u.test(text)) return 'en'\n return /\\p{Script=Han}/u.test(text) ? 'zh' : 'en'\n}\n\nfunction removeTitleSyntax(value: string): string {\n return value.replace(/[|`*_~#\\[\\]\"“”]/gu, ' ')\n}\n\nfunction truncateSummary(value: string, targetWords: number, targetCjkCharacters: number): string {\n const containsCjk = /[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]/u.test(value)\n if (containsCjk) {\n return Array.from(value.replace(/\\s+/gu, '')).slice(0, targetCjkCharacters).join('')\n }\n return value.split(/\\s+/u).filter(Boolean).slice(0, targetWords).join(' ')\n}\n\nfunction unwrapModelText(raw: string): string {\n const trimmed = raw.trim()\n const fenced = /^```(?:json)?\\s*([\\s\\S]*?)\\s*```$/iu.exec(trimmed)\n return (fenced?.[1] ?? trimmed).trim()\n}\n\nfunction readJsonObject(raw: string): Record<string, unknown> | undefined {\n const text = unwrapModelText(raw)\n const start = text.indexOf('{')\n const end = text.lastIndexOf('}')\n if (start === -1 || end <= start) return undefined\n try {\n const value = JSON.parse(text.slice(start, end + 1))\n if (value && typeof value === 'object' && !Array.isArray(value)) return value as Record<string, unknown>\n } catch {\n return undefined\n }\n return undefined\n}\n\n/**\n * Accept the required JSON shape, including a code fence or a short preface.\n * Extra keys are ignored. A plain one-line title still becomes a title so a\n * chatty model does not leave the session on the built-in fallback.\n */\nexport function parseModelTitle(\n raw: string,\n targetWords: number,\n targetCjkCharacters: number,\n): ParsedTitle {\n const candidate = readJsonObject(raw)\n const typeValue = typeof candidate?.type === 'string' ? candidate.type.trim().toLowerCase() : ''\n const summaryValue = typeof candidate?.summary === 'string' ? candidate.summary : ''\n const type = isTitleType(typeValue) ? typeValue : 'discuss'\n const source = summaryValue || (candidate ? '' : unwrapModelText(raw).replace(/^[\"'`]+|[\"'`]+$/gu, ''))\n const normalized = normalizeSessionTitle(removeTitleSyntax(source), Number.MAX_SAFE_INTEGER)\n const summary = truncateSummary(normalized, targetWords, targetCjkCharacters)\n if (summary.length === 0) {\n throw new Error('dsh-current-title: title model returned an empty summary')\n }\n return { type, summary }\n}\n\nexport function localMonthDay(now: Date): string {\n const month = String(now.getMonth() + 1).padStart(2, '0')\n const day = String(now.getDate()).padStart(2, '0')\n return `${month}${day}`\n}\n\nexport function formatTitle(parsed: ParsedTitle, locale: TitleLocale, now = new Date()): string {\n return `${localMonthDay(now)} | ${TITLE_TYPE_LABELS[locale][parsed.type]} | ${parsed.summary}`\n}\n","import { normalizeSessionTitle } from './output.ts'\nimport type { TitleMessage } from './contracts.ts'\n\nexport interface SessionEventLike {\n readonly type: string\n readonly seq: number\n readonly time?: number\n readonly data?: {\n readonly source?: { readonly kind?: string; readonly plugin?: string; readonly provider?: string }\n readonly content?: ReadonlyArray<{ readonly type?: string; readonly text?: string }>\n readonly title?: string\n readonly messageSeqs?: readonly number[]\n }\n}\n\nexport interface SessionLike {\n readonly id: string\n readonly seq?: number\n snapshotEvents(): readonly SessionEventLike[]\n append?(type: string, data: unknown): unknown\n}\n\nfunction textFromContent(content: ReadonlyArray<{ readonly type?: string; readonly text?: string }> | undefined): string {\n if (!Array.isArray(content)) return ''\n return content\n .filter(block => block && block.type === 'text' && typeof block.text === 'string')\n .map(block => block.text as string)\n .join('\\n')\n}\n\n/** Eligible human prompts only. Plugin/tool/model user-role rows are excluded. */\nexport function collectHumanMessages(events: readonly SessionEventLike[], throughSeq?: number): TitleMessage[] {\n const messages: TitleMessage[] = []\n for (const event of events) {\n if (throughSeq !== undefined && event.seq > throughSeq) break\n if (event.type !== 'user/message') continue\n if (event.data?.source?.kind !== 'user') continue\n const text = textFromContent(event.data.content)\n if (normalizeSessionTitle(text, Number.MAX_SAFE_INTEGER).length === 0) continue\n messages.push({ seq: event.seq, text })\n }\n return messages\n}\n\nexport function sourceVersionOf(sessionId: string, messages: readonly TitleMessage[]): string {\n const last = messages.at(-1)\n return `${sessionId}:${last?.seq ?? -1}:${messages.length}`\n}\n","import { callLlmText, resolveFeatureModel, type LlmTextCaller } from '@klarkxy/dsh-plugin-kit'\nimport { buildAuxiliaryUserText } from '@klarkxy/dsh-plugin-kit/auxiliary-context'\nimport type { ModelRoute } from '@klarkxy/dsh-model-route'\nimport type { GenerateConfig, TitleMessage, TitleModelRoute } from './contracts.ts'\nimport { DEFAULT_TIMEOUT_MS, PLUGIN_NAME, TITLE_CALL_FEATURE } from './contracts.ts'\nimport { FRAME_PREFIX, frameMessages, selectRecentMessages, utf8Bytes } from './input.ts'\nimport { formatTitle, normalizeSessionTitle, parseModelTitle, resolveTitleLocale, type TitleLocaleMode } from './output.ts'\nimport { sourceVersionOf } from './messages.ts'\n\n/**\n * Fixed bytes the auxiliary-context envelope adds around the selected\n * messages, so maxInputBytes keeps bounding the wire text. The stable block\n * carries the framing rule and the request block the JSON message list —\n * selectRecentMessages measures that same pair through frameMessages, so\n * only the constant envelope overhead is new.\n */\nconst ENVELOPE_OVERHEAD_BYTES = utf8Bytes(\n buildAuxiliaryUserText({ feature: TITLE_CALL_FEATURE, context: FRAME_PREFIX, text: '[]' }),\n) - utf8Bytes(frameMessages([]))\n\nexport interface GeneratedTitle {\n readonly title: string\n readonly messageSeqs: readonly number[]\n readonly model?: { readonly provider: string; readonly model: string }\n readonly sourceVersion: string\n}\n\nexport function systemPrompt(config: GenerateConfig, customPrompt = ''): string {\n const instruction = customPrompt.trim()\n return [\n instruction || 'Name the current task in an AI coding-assistant session.',\n 'Prioritize the newest human messages. Older messages are context only and must not keep a completed task in the title.',\n 'Allowed type values: feature, fix, optimize, refactor, test, docs, release, config, explore, discuss.',\n 'Return exactly one JSON object: {\"type\":\"<type>\",\"summary\":\"<summary>\"}.',\n 'Return no Markdown, code fence, explanation, date, or extra key.',\n 'Keep the summary in the language of the recent messages.',\n `Aim for at most ${config.targetWords} non-CJK words or ${config.targetCjkCharacters} CJK characters.`,\n ].join('\\n')\n}\n\n/**\n * Saved override passed to resolveFeatureModel. Unlike modelRouteOverride,\n * this does not trim or re-apply the 250/80 caps: stored rows are already\n * normalized, and a whitespace-only id must stay a miss (not a trimmed hit)\n * so the host-default fallback is unchanged.\n */\nexport function titleModelRoute(route: TitleModelRoute | undefined): ModelRoute | undefined {\n if (!route?.provider || !route.model) return undefined\n return route.reasoningEffort\n ? { provider: route.provider, model: route.model, reasoningEffort: route.reasoningEffort }\n : { provider: route.provider, model: route.model }\n}\n\nexport async function generateCurrentTitle(options: {\n llm: LlmTextCaller\n host: unknown\n config: GenerateConfig\n sessionId: string\n messages: readonly TitleMessage[]\n prompt?: string\n model?: TitleModelRoute\n localePreference?: string\n localeMode?: TitleLocaleMode\n signal: AbortSignal\n isCurrent: () => boolean\n now?: Date\n}): Promise<GeneratedTitle> {\n options.signal.throwIfAborted()\n if (!options.isCurrent()) {\n throw Object.assign(new Error('dsh-current-title: generation is no longer current'), { code: 'superseded' })\n }\n const selected = selectRecentMessages(\n options.messages,\n options.config.maxRecentMessages,\n options.config.maxInputBytes - ENVELOPE_OVERHEAD_BYTES,\n )\n if (selected.length === 0) throw new Error('dsh-current-title: at least one source message is required')\n const route = resolveFeatureModel(options.host, titleModelRoute(options.model), options.sessionId)\n if (!route) throw new Error('dsh-current-title: 请在设置页选择模型,或设置默认辅助模型 / 宿主默认对话模型。')\n // Like the bundled title provider, select the first (least) advertised\n // effort inside prepareCall, before adapter defaults are materialized.\n const callRoute = { provider: route.provider, model: route.model }\n\n // The wire text carries the stable framing line inside the labelled\n // auxiliary-context block (fixed rules first) and the message list —\n // already ordered oldest to newest — inside the request block. Neither\n // side embeds a generated date.\n const framedInput = JSON.stringify(selected)\n const locale = resolveTitleLocale(\n options.localeMode ?? options.config.locale,\n selected.map(message => message.text),\n options.localePreference,\n )\n const sourceVersion = sourceVersionOf(options.sessionId, selected)\n const deadline = new AbortController()\n const timeoutMs = Number.isFinite(options.config.timeoutMs) && options.config.timeoutMs > 0\n ? options.config.timeoutMs : DEFAULT_TIMEOUT_MS\n const timer = setTimeout(() => deadline.abort(new DOMException('Title generation timed out.', 'TimeoutError')), timeoutMs)\n const signal = AbortSignal.any([options.signal, deadline.signal])\n let result\n try {\n result = await callLlmText(options.llm, {\n plugin: PLUGIN_NAME,\n route: callRoute,\n system: systemPrompt(options.config, options.prompt),\n feature: TITLE_CALL_FEATURE,\n context: FRAME_PREFIX,\n text: framedInput,\n maxTokens: options.config.maxOutputTokens,\n purpose: 'session-title',\n configure: (controls, model) => {\n const effort = model.reasoning?.efforts[0]?.id\n return { ...controls, ...(effort === undefined ? {} : { reasoningEffort: effort }) }\n },\n signal,\n sessionId: options.sessionId,\n isCurrent: options.isCurrent,\n })\n signal.throwIfAborted()\n } catch (error) {\n // The shared caller translates stream cancellation to AbortError. Retain\n // the originating deadline or lifecycle reason at this feature boundary.\n signal.throwIfAborted()\n throw error\n } finally {\n clearTimeout(timer)\n }\n options.signal.throwIfAborted()\n if (!options.isCurrent()) {\n throw Object.assign(new Error('dsh-current-title: generation is no longer current'), { code: 'superseded' })\n }\n const parsed = parseModelTitle(result.text, options.config.targetWords, options.config.targetCjkCharacters)\n const title = normalizeSessionTitle(formatTitle(parsed, locale, options.now ?? new Date()), options.config.maxTitleBytes)\n if (!title) throw new Error('dsh-current-title: title model returned an empty summary')\n return {\n title,\n messageSeqs: selected.map(message => message.seq),\n model: { provider: result.provider, model: result.model },\n sourceVersion,\n }\n}\n","export interface OwnershipClaim {\n readonly id: string\n readonly dispose: () => void | Promise<void>\n}\n\nexport interface TitleSlot {\n owner(): string | undefined\n occupy(id: string): Promise<() => void | Promise<void>>\n}\n\n/** Exclusive title-provider ownership. Enable claims the slot; disable releases only while this id still holds it. */\nexport async function claimTitleSlot(slot: TitleSlot, id: string): Promise<OwnershipClaim> {\n const dispose = await slot.occupy(id)\n return { id, dispose }\n}\n\nexport async function releaseTitleSlot(\n slot: TitleSlot,\n claim: OwnershipClaim | undefined,\n): Promise<'released' | 'left-other-owner' | 'idle'> {\n if (!claim) return 'idle'\n if (slot.owner() !== claim.id) return 'left-other-owner'\n await claim.dispose()\n if (slot.owner() && slot.owner() !== claim.id) return 'left-other-owner'\n return 'released'\n}\n\nexport function occupiedProviderId(error: unknown): string | undefined {\n const message = error instanceof Error ? error.message : String(error)\n return /session-title provider \"([^\"]+)\" is already registered/.exec(message)?.[1]\n}\n","import { PROVIDER_ID } from './contracts.ts'\nimport { occupiedProviderId, type TitleSlot } from './ownership.ts'\n\nexport interface SessionTitleProvider {\n readonly id: string\n readonly automatic: 'first-prompt' | 'all-prompts'\n generate(request: {\n session: { id: string; snapshotEvents(): readonly unknown[] }\n messages: ReadonlyArray<{ seq: number; text: string }>\n route?: { provider: string; model: string }\n signal: AbortSignal\n }): Promise<{ title: string; messageSeqs: readonly number[]; model?: { provider: string; model: string } }>\n}\n\nexport interface SessionTitleServiceLike {\n register(provider: SessionTitleProvider): () => void | Promise<void>\n get(session: unknown): { title: string; source?: { kind?: string; provider?: string }; eventSeq?: number; updatedAt?: number; messageSeqs?: readonly number[] } | undefined\n refresh(session: unknown, signal?: AbortSignal): Promise<unknown>\n}\n\nexport interface LoaderEntryOptions {\n id?: string\n name?: string\n disabled?: boolean | null\n config?: unknown\n inject?: unknown\n group?: boolean | null\n}\n\nexport interface LoaderEntry {\n id: string\n options?: LoaderEntryOptions\n}\n\nexport interface LoaderFace {\n entries(): Iterable<LoaderEntry>\n update(id: string, options: { disabled?: boolean | null }): Promise<unknown> | unknown\n}\n\nexport interface Displacement {\n readonly id: string\n readonly name: string\n readonly identity: string\n}\n\nfunction catalogLookupId(entryId: string): string {\n const colon = entryId.indexOf(':')\n return colon === -1 ? entryId : entryId.slice(colon + 1)\n}\n\nfunction entryName(entry: LoaderEntry): string {\n return String(entry.options?.name ?? '')\n}\n\nexport function entryDisabled(entry: LoaderEntry): boolean {\n return entry.options?.disabled === true\n}\n\nexport function displacementIdentity(entry: LoaderEntry): string {\n const options = entry.options ?? {}\n const { disabled: _disabled, ...rest } = options\n return JSON.stringify({ id: entry.id, name: entryName(entry), rest })\n}\n\nexport function captureDisplacement(entry: LoaderEntry): Displacement {\n return { id: entry.id, name: entryName(entry), identity: displacementIdentity(entry) }\n}\n\nexport function displacementUnchanged(snapshot: Displacement, entry: LoaderEntry): boolean {\n return entry.id === snapshot.id\n && entryName(entry) === snapshot.name\n && displacementIdentity(entry) === snapshot.identity\n}\n\nexport function findEntryById(loader: LoaderFace, id: string): LoaderEntry | undefined {\n for (const entry of loader.entries()) {\n if (entry.id === id) return entry\n }\n return undefined\n}\n\nexport function findLoaderEntry(loader: LoaderFace, providerId: string): LoaderEntry | undefined {\n for (const entry of loader.entries()) {\n const name = entryName(entry)\n const ids = [entry.id, entry.options?.id, name, catalogLookupId(entry.id)]\n if (ids.some(value => value === providerId)) return entry\n if (name.endsWith(`/${providerId}`) || name.endsWith(providerId)) return entry\n if (providerId === 'session-title-first-prompt-llm' && catalogLookupId(entry.id) === 'session-title-llm') return entry\n }\n return undefined\n}\n\nexport async function restoreOwnDisplacement(loader: LoaderFace | undefined, snapshot: Displacement | undefined): Promise<'restored' | 'skipped'> {\n if (!loader || !snapshot) return 'skipped'\n const current = findEntryById(loader, snapshot.id)\n if (!current || !entryDisabled(current) || !displacementUnchanged(snapshot, current)) return 'skipped'\n await loader.update(snapshot.id, { disabled: false })\n return 'restored'\n}\n\nexport function createNativeTitleSlot(options: {\n sessionTitle: SessionTitleServiceLike\n loader: LoaderFace\n /** Read at each occupy so a settings change can re-register with a new cadence. */\n automatic: () => SessionTitleProvider['automatic']\n generate: SessionTitleProvider['generate']\n}): TitleSlot & { displacement?: Displacement } {\n let owner: string | undefined\n const slot: TitleSlot & { displacement?: Displacement } = {\n owner: () => owner,\n async occupy(id: string) {\n const provider: SessionTitleProvider = {\n id: PROVIDER_ID,\n automatic: options.automatic(),\n generate: options.generate,\n }\n try {\n const dispose = options.sessionTitle.register(provider)\n owner = id\n return async () => {\n await dispose()\n if (owner === id) owner = undefined\n }\n } catch (error) {\n const occupied = occupiedProviderId(error)\n if (!occupied) throw error\n const entry = findLoaderEntry(options.loader, occupied)\n if (!entry || entryDisabled(entry)) throw error\n const snapshot = captureDisplacement(entry)\n await options.loader.update(entry.id, { disabled: true })\n const afterDisable = findEntryById(options.loader, entry.id)\n if (!afterDisable || !displacementUnchanged(snapshot, afterDisable)) throw error\n try {\n const dispose = options.sessionTitle.register(provider)\n slot.displacement = snapshot\n owner = id\n return async () => {\n await dispose()\n if (owner === id) owner = undefined\n }\n } catch (second) {\n if (findEntryById(options.loader, snapshot.id) && displacementUnchanged(snapshot, findEntryById(options.loader, snapshot.id)!)) {\n await options.loader.update(snapshot.id, { disabled: false })\n }\n throw second\n }\n }\n },\n }\n return slot\n}\n","import { defineDomain, domainTable } from '@deepseek-ai/dsh-storage-domain'\nimport { z } from 'zod'\nimport {\n SETTINGS_KEY, defaultModelRoute, isTitleLocaleMode, normalizeCadence, normalizeModelRoute, normalizePrompt,\n type TitleSettings,\n} from './contracts.ts'\n\nexport { SETTINGS_KEY }\n\nconst localeSchema = z.enum(['auto', 'zh', 'en'])\n\n/** Version 1 stored only the locale. Prompt and model are filled as defaults. */\nconst legacySettingsSchema = z.object({\n revision: z.number().int().nonnegative(),\n locale: localeSchema,\n}).strict()\n\nconst modelRouteSchema = z.object({\n provider: z.string(),\n model: z.string(),\n reasoningEffort: z.string().optional(),\n}).strict()\n\nexport const titleSettingsSchema = z.object({\n revision: z.number().int().nonnegative(),\n locale: localeSchema,\n prompt: z.string(),\n model: modelRouteSchema,\n /** Defaulted so rows stored before the cadence switch existed still parse. */\n cadence: z.enum(['all-prompts', 'first-prompt']).default('all-prompts'),\n}).strict()\n\nexport const titleDomain = defineDomain({\n name: 'dsh_editor_current_title',\n version: 2,\n tables: {\n settings: domainTable<string, TitleSettings>(titleSettingsSchema),\n },\n})\n\nexport function parseTitleSettings(value: unknown): TitleSettings | undefined {\n const current = titleSettingsSchema.safeParse(value)\n if (current.success) {\n return {\n revision: current.data.revision,\n locale: isTitleLocaleMode(current.data.locale) ? current.data.locale : 'auto',\n prompt: normalizePrompt(current.data.prompt),\n model: normalizeModelRoute(current.data.model),\n cadence: normalizeCadence(current.data.cadence),\n }\n }\n const legacy = legacySettingsSchema.safeParse(value)\n if (!legacy.success || !isTitleLocaleMode(legacy.data.locale)) return undefined\n return {\n revision: legacy.data.revision,\n locale: legacy.data.locale,\n prompt: '',\n model: defaultModelRoute(),\n cadence: 'all-prompts',\n }\n}\n\nexport function storedSettings(value: unknown, _fallbackLocale: TitleSettings['locale'] = 'auto'): TitleSettings {\n const parsed = parseTitleSettings(value)\n return {\n revision: parsed?.revision ?? 0,\n locale: 'auto',\n prompt: parsed?.prompt ?? '',\n model: parsed?.model ?? defaultModelRoute(),\n cadence: parsed?.cadence ?? 'all-prompts',\n }\n}\n\nexport function settingsPatch(current: TitleSettings, patch: {\n prompt?: unknown\n model?: unknown\n cadence?: unknown\n}): Pick<TitleSettings, 'prompt' | 'model' | 'cadence'> & { locale: 'auto' } {\n return {\n locale: 'auto',\n prompt: patch.prompt === undefined ? current.prompt : normalizePrompt(patch.prompt),\n model: patch.model === undefined ? current.model : normalizeModelRoute(patch.model),\n cadence: patch.cadence === undefined ? current.cadence : normalizeCadence(patch.cadence),\n }\n}\n","import type { RpcResult } from '@klarkxy/dsh-plugin-kit/contracts'\nimport { isSubagentSession } from '@klarkxy/dsh-plugin-kit/contracts'\nimport type { LlmTextCaller } from '@klarkxy/dsh-plugin-kit'\nimport type { GenerateConfig, TitleSettings, TitleSnapshot, TitleStatus, TitleSupport } from './contracts.ts'\nimport { PROVIDER_ID, defaultGenerateConfig } from './contracts.ts'\nimport { generateCurrentTitle } from './generate.ts'\nimport { collectHumanMessages, type SessionLike } from './messages.ts'\nimport {\n createNativeTitleSlot, restoreOwnDisplacement, type LoaderFace, type SessionTitleServiceLike,\n} from './native-slot.ts'\nimport { claimTitleSlot, releaseTitleSlot, type OwnershipClaim } from './ownership.ts'\nimport { settingsPatch, storedSettings } from './storage.ts'\nimport type { TitleLocaleMode } from './output.ts'\n\nexport interface TitleSettingsStore {\n load(): TitleSettings | undefined\n save(settings: TitleSettings): Promise<void>\n}\n\nexport interface CurrentTitleHost {\n get(name: string): unknown\n}\n\nexport class CurrentTitleService {\n private settings: TitleSettings\n private config: GenerateConfig\n private claim?: OwnershipClaim\n private nativeSlot?: ReturnType<typeof createNativeTitleSlot>\n private generation = 0\n private settingsPending: Promise<void> = Promise.resolve()\n private disposed = false\n private readonly inFlight = new Map<string, AbortController>()\n private readonly generations = new Set<Promise<unknown>>()\n readonly support: TitleSupport\n\n constructor(private readonly options: {\n plugin: string\n llm?: LlmTextCaller\n host?: unknown\n sessionTitle?: SessionTitleServiceLike\n loader?: LoaderFace\n sessions?: { get(id: string): SessionLike | undefined }\n store?: TitleSettingsStore\n localePreference?: () => string | undefined\n initialLocale?: TitleLocaleMode\n now?: () => Date\n onSettingsChanged?: (revision: number) => void\n }) {\n const stored = storedSettings(options.store?.load(), options.initialLocale ?? 'auto')\n this.settings = stored\n this.config = defaultGenerateConfig(this.settings.locale)\n this.support = { nativeOwner: null, weOwn: false }\n }\n\n async start(): Promise<void> {\n const { llm, sessionTitle, loader, sessions } = this.options\n if (!llm || !sessionTitle?.register || !sessions || !loader) {\n this.support.weOwn = false\n this.support.limitation = 'required host services are missing'\n return\n }\n this.nativeSlot = createNativeTitleSlot({\n sessionTitle,\n loader,\n automatic: () => this.settings.cadence,\n generate: request => this.nativeGenerate(request),\n })\n try {\n this.claim = await claimTitleSlot(this.nativeSlot, PROVIDER_ID)\n this.support.weOwn = true\n this.support.nativeOwner = PROVIDER_ID\n delete this.support.limitation\n } catch (error) {\n this.support.weOwn = false\n this.support.nativeOwner = this.nativeSlot.owner() ?? null\n this.support.limitation = error instanceof Error ? error.message : 'native title provider slot is occupied'\n }\n }\n\n async dispose(): Promise<void> {\n this.disposed = true\n this.generation += 1\n for (const controller of this.inFlight.values()) controller.abort(new Error('current-title disabled'))\n this.inFlight.clear()\n await Promise.allSettled([...this.generations])\n await this.settingsPending\n const snapshot = this.nativeSlot?.displacement\n const outcome = await releaseTitleSlot(this.nativeSlot ?? { owner: () => undefined, occupy: async () => () => {} }, this.claim)\n if (outcome === 'released') await restoreOwnDisplacement(this.options.loader, snapshot)\n this.claim = undefined\n this.support.weOwn = false\n this.support.nativeOwner = this.nativeSlot?.owner() ?? null\n if (outcome === 'left-other-owner') {\n this.support.limitation = 'another title provider owns the slot; previous owner was not restored'\n }\n }\n\n status(sessionId?: string): TitleStatus {\n const session = sessionId && this.options.sessions ? this.options.sessions.get(sessionId) : undefined\n const snapshot = session ? this.read(session) : undefined\n return {\n settings: { ...this.settings, model: { ...this.settings.model } },\n support: { ...this.support, nativeOwner: this.nativeSlot?.owner() ?? this.support.nativeOwner },\n ...(sessionId ? {\n session: {\n sessionId,\n title: snapshot?.title,\n sourceKind: snapshot?.source.kind,\n generating: this.inFlight.has(sessionId),\n pinned: snapshot?.source.kind === 'user',\n },\n } : {}),\n }\n }\n\n async updateSettings(patch: {\n prompt?: unknown\n model?: unknown\n cadence?: unknown\n expectedRevision: number\n }): Promise<TitleSettings> {\n patch = structuredClone(patch)\n const result = this.settingsPending.then(async () => {\n if (this.disposed) throw Object.assign(new Error('current-title disabled'), { code: 'unavailable' })\n if (this.settings.revision !== patch.expectedRevision) {\n throw Object.assign(new Error('current-title settings changed'), { code: 'revision' })\n }\n const previous = this.settings\n const next: TitleSettings = {\n revision: this.settings.revision + 1,\n ...settingsPatch(this.settings, patch),\n }\n if (this.options.store) await this.options.store.save(next)\n this.settings = next\n // Observer failures cannot roll back a committed settings write.\n try { this.options.onSettingsChanged?.(next.revision) } catch {}\n this.config = { ...this.config, locale: 'auto' }\n if (!this.disposed && next.cadence !== previous.cadence) await this.reclaimWithCadence()\n return {\n revision: next.revision,\n locale: next.locale,\n prompt: next.prompt,\n model: { ...next.model },\n cadence: next.cadence,\n }\n })\n this.settingsPending = result.then(() => {}, () => {})\n return result\n }\n\n /** Re-register the provider so a cadence change takes effect without a restart. */\n private async reclaimWithCadence(): Promise<void> {\n if (!this.claim || !this.nativeSlot) return\n const stale = this.claim\n this.claim = undefined\n await stale.dispose()\n try {\n this.claim = await claimTitleSlot(this.nativeSlot, PROVIDER_ID)\n this.support.weOwn = true\n this.support.nativeOwner = PROVIDER_ID\n delete this.support.limitation\n } catch (error) {\n this.support.weOwn = false\n this.support.nativeOwner = this.nativeSlot.owner() ?? null\n this.support.limitation = error instanceof Error ? error.message : 'native title provider slot is occupied'\n }\n }\n\n /** @deprecated Locale is always auto. Kept so older clients still save a revision. */\n async updateLocale(_locale: TitleLocaleMode, expectedRevision: number): Promise<TitleSettings> {\n return this.updateSettings({ expectedRevision })\n }\n\n async regenerate(sessionId: string, signal: AbortSignal): Promise<TitleSnapshot | undefined> {\n if (!this.support.weOwn) throw Object.assign(new Error('title provider is inactive'), { code: 'unavailable' })\n const session = this.options.sessions?.get(sessionId)\n if (!session) throw Object.assign(new Error('session not found'), { code: 'not-found' })\n await this.options.sessionTitle?.refresh(session, signal)\n return this.read(session)\n }\n\n read(session: SessionLike): TitleSnapshot | undefined {\n const snapshot = this.options.sessionTitle?.get(session)\n if (!snapshot?.title) return undefined\n const kind = snapshot.source?.kind\n return {\n title: snapshot.title,\n messageSeqs: snapshot.messageSeqs ? [...snapshot.messageSeqs] : [],\n source: {\n kind: kind === 'user' || kind === 'fallback' || kind === 'provider' ? kind : 'provider',\n ...(typeof snapshot.source?.provider === 'string' ? { provider: snapshot.source.provider } : {}),\n },\n eventSeq: Number(snapshot.eventSeq ?? 0),\n updatedAt: snapshot.updatedAt ?? 0,\n }\n }\n\n private nativeGenerate(request: Parameters<CurrentTitleService['runNativeGenerate']>[0]) {\n if (this.disposed) return Promise.reject(new Error('dsh-current-title: plugin disabled'))\n const pending = this.runNativeGenerate(request)\n this.generations.add(pending)\n void pending.then(() => this.generations.delete(pending), () => this.generations.delete(pending))\n return pending\n }\n\n private async runNativeGenerate(request: {\n session: { id: string; snapshotEvents(): readonly unknown[] }\n messages: ReadonlyArray<{ seq: number; text: string }>\n signal: AbortSignal\n }) {\n const llm = this.options.llm\n if (!llm) throw new Error('dsh-current-title: llm is not available')\n const generation = this.generation\n const controller = new AbortController()\n this.inFlight.get(request.session.id)?.abort(new Error('newer title generation superseded older work'))\n this.inFlight.set(request.session.id, controller)\n try {\n const combined = AbortSignal.any([request.signal, controller.signal])\n const session = this.options.sessions?.get(request.session.id)\n // The host writes a free deterministic fallback title before it consults a\n // provider, and this provider contract has no \"decline\" result. Declining is\n // therefore the only way to keep delegated child threads off the model: their\n // dispatch prompt arrives as the child's own user message, so `source.kind`\n // cannot exclude them. The host logs the rejection and keeps the fallback.\n if (isSubagentSession(session)) {\n throw Object.assign(new Error('dsh-current-title: delegated child thread keeps the host fallback title'), { code: 'subagent-session' })\n }\n const messages = collectHumanMessages(\n request.messages.map(message => ({\n type: 'user/message',\n seq: message.seq,\n data: { source: { kind: 'user' }, content: [{ type: 'text', text: message.text }] },\n })),\n )\n const generated = await generateCurrentTitle({\n llm,\n host: this.options.host ?? {},\n config: this.config,\n sessionId: request.session.id,\n messages: messages.length > 0 ? messages : [...request.messages],\n prompt: this.settings.prompt,\n model: this.settings.model,\n localePreference: this.options.localePreference?.(),\n signal: combined,\n isCurrent: () => this.generation === generation && this.support.weOwn\n && (!session || this.options.sessions?.get(request.session.id) === session),\n now: this.options.now?.(),\n })\n return { title: generated.title, messageSeqs: generated.messageSeqs, model: generated.model }\n } finally {\n if (this.inFlight.get(request.session.id) === controller) this.inFlight.delete(request.session.id)\n }\n }\n}\n\nexport function hostLocalePreference(host: CurrentTitleHost): string | undefined {\n try {\n const settings = host.get('settings') as { get?(namespace: string): unknown } | undefined\n const value = settings?.get?.('locale')\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return undefined\n const preference = (value as Record<string, unknown>).preference\n return typeof preference === 'string' ? preference : undefined\n } catch {\n return undefined\n }\n}\n\nexport async function handleRpc(service: CurrentTitleService, endpoint: string, payload: unknown, signal: AbortSignal): Promise<RpcResult> {\n signal.throwIfAborted()\n const body = payload && typeof payload === 'object' && !Array.isArray(payload) ? payload as Record<string, unknown> : {}\n if (endpoint === 'status') {\n return { ok: true, value: service.status(typeof body.sessionId === 'string' ? body.sessionId : undefined) }\n }\n if (endpoint === 'settings') {\n if (typeof body.expectedRevision !== 'number') {\n return { ok: false, error: { code: 'bad-request', message: '标题设置无效。' } }\n }\n try {\n return {\n ok: true,\n value: await service.updateSettings({\n ...(body.prompt !== undefined ? { prompt: body.prompt } : {}),\n ...(body.model !== undefined ? { model: body.model } : {}),\n ...(body.cadence !== undefined ? { cadence: body.cadence } : {}),\n expectedRevision: body.expectedRevision,\n }),\n }\n } catch (error) {\n const code = error instanceof Error && 'code' in error ? String((error as { code?: string }).code) : 'failed'\n if (code === 'revision') return { ok: false, error: { code, message: '设置已更新,请刷新后重试。' } }\n return { ok: false, error: { code: 'failed', message: '无法保存标题设置。' } }\n }\n }\n if (endpoint === 'regenerate') {\n if (typeof body.sessionId !== 'string' || !body.sessionId) {\n return { ok: false, error: { code: 'bad-request', message: '缺少会话。' } }\n }\n try {\n const snapshot = await service.regenerate(body.sessionId, signal)\n return { ok: true, value: snapshot ?? null }\n } catch (error) {\n const code = error instanceof Error && 'code' in error ? String((error as { code?: string }).code) : 'failed'\n if (code === 'not-found') return { ok: false, error: { code, message: '找不到该会话。' } }\n if (code === 'unavailable') return { ok: false, error: { code, message: '标题服务未就绪。' } }\n if (signal.aborted) return { ok: false, error: { code: 'cancelled', message: '已取消。' } }\n return { ok: false, error: { code: 'failed', message: '标题生成失败。' } }\n }\n }\n return { ok: false, error: { code: 'bad-request', message: '未知操作。' } }\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport type { LlmTextCaller } from '@klarkxy/dsh-plugin-kit'\nimport { retainAuxiliaryModel } from '@klarkxy/dsh-plugin-kit/auxiliary-model'\nimport { registerHostRpc, type HostRpcContext } from '@klarkxy/dsh-plugin-kit/host-rpc'\nimport { modelSettingsChangesIdentity } from '@klarkxy/dsh-plugin-kit/contracts'\nimport { createModelSettingsChanges } from '@klarkxy/dsh-plugin-kit/model-settings-changes'\nimport { registerModelSettings, notifyModelSettingsChanged, type ModelSettingsEvents } from '@klarkxy/dsh-plugin-kit/model-settings'\nimport { isTitleLocaleMode, PLUGIN_NAME, RPC_CHANNEL, SETTINGS_KEY, type TitleLocaleMode } from './contracts.ts'\nimport { CurrentTitleService, handleRpc, hostLocalePreference } from './service.ts'\nimport type { LoaderFace, SessionTitleServiceLike } from './native-slot.ts'\nimport type { SessionLike } from './messages.ts'\nimport { parseTitleSettings, titleDomain } from './storage.ts'\n\nexport const name = PLUGIN_NAME\nexport const inject = ['sessionTitle', 'llm', 'sessions', 'loader', 'storageDomain', 'connection', 'webServer', 'agents', 'sessionProjections', 'agentDefaultModel'] as const\nexport { CurrentTitleService }\nexport { selectRecentMessages, frameMessages } from './input.ts'\nexport { parseModelTitle, formatTitle, resolveTitleLocale } from './output.ts'\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context { currentTitle: CurrentTitleService }\n}\n\ntype DomainHandle = {\n table(name: 'settings'): {\n get(key: string): unknown\n put(key: string, value: unknown): Promise<void>\n }\n close(): Promise<void>\n}\n\ntype Host = Context & HostRpcContext & {\n sessionTitle: SessionTitleServiceLike\n llm: LlmTextCaller\n sessions: { get(id: string): SessionLike | undefined }\n loader: LoaderFace\n storageDomain: { open: (spec: typeof titleDomain) => Promise<DomainHandle> }\n}\n\nexport async function apply(ctx: Context, config: { locale?: TitleLocaleMode } = {}): Promise<void> {\n createModelSettingsChanges(ctx, modelSettingsChangesIdentity(PLUGIN_NAME), PLUGIN_NAME)\n // Keep the shared auxiliary default alive while this plugin is mounted: it\n // is the global default title generation follows when no title model is\n // set. A store that fails to open must fail this apply — silently falling\n // back to another tier would run generations on a model the user did not\n // choose.\n const release = await retainAuxiliaryModel(ctx)\n ctx.effect(() => release, 'current-title.auxiliary-model')\n const host = ctx as Host\n const domain = await host.storageDomain.open(titleDomain)\n const table = domain.table('settings')\n const locale = isTitleLocaleMode(config.locale) ? config.locale : 'auto'\n const service = new CurrentTitleService({\n plugin: PLUGIN_NAME,\n onSettingsChanged: revision => notifyModelSettingsChanged(ctx, PLUGIN_NAME, revision),\n llm: host.llm,\n host,\n sessionTitle: host.sessionTitle,\n loader: host.loader,\n sessions: host.sessions,\n store: {\n load: () => parseTitleSettings(table.get(SETTINGS_KEY)),\n save: settings => table.put(SETTINGS_KEY, settings),\n },\n initialLocale: locale,\n localePreference: () => hostLocalePreference(host),\n })\n await service.start()\n ctx.provide('currentTitle', service)\n ctx.effect(() => async () => { await service.dispose(); await domain.close() }, 'current-title.lifecycle')\n ctx.effect(() => registerHostRpc(host, RPC_CHANNEL, (endpoint, payload, signal) => handleRpc(service, endpoint, payload, signal)), 'current-title.rpc')\n ctx.effect(() => registerModelSettings(ctx as unknown as ModelSettingsEvents, {\n ns: PLUGIN_NAME, title: { zh: '自动标题', en: 'Auto Title' },\n read(signal) {\n signal.throwIfAborted()\n const settings = service.status().settings\n return { revision: settings.revision, fields: [{ path: ['model'], label: { zh: '标题模型', en: 'Title model' }, current: settings.model,\n followLabel: { zh: '默认辅助模型', en: 'Default auxiliary model' }, allowFollow: true }] }\n },\n async write(path, route, expectedRevision, signal) {\n if (path.length !== 1 || path[0] !== 'model') throw new Error('Unknown Current Title model setting')\n signal.throwIfAborted()\n return service.updateSettings({ model: route, expectedRevision })\n },\n }), 'current-title.model-settings')\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../dsh-plugin-kit/src/contracts.ts","../../dsh-plugin-kit/src/host-rpc.ts","../../dsh-plugin-kit/src/model-settings.ts","../../dsh-plugin-kit/src/model-settings-client.ts","../../dsh-plugin-kit/src/model-settings-changes.ts","../../dsh-plugin-kit/src/auxiliary-model.ts","../../dsh-plugin-kit/src/auxiliary-context.ts","../../dsh-plugin-kit/src/llm-call.ts","../src/input.ts","../src/output.ts","../src/messages.ts","../src/generate.ts","../src/ownership.ts","../src/native-slot.ts","../src/storage.ts","../src/service.ts","../src/index.ts"],"sourcesContent":["import type { ContextFormed } from '@deepseek-ai/dsh-llm'\nimport { modelRouteOverride, type ModelRoute } from '@klarkxy/dsh-model-route'\n\n/**\n * The canonical home is @klarkxy/dsh-model-route; re-exported here so existing\n * plugin-kit consumers keep compiling.\n */\nexport type { ModelRoute }\n\n/** Public, browser-safe contracts. Host implementations stay in their owning packages. */\nexport type ProducerSourceKind = `plugin:${string}`\nexport type ProducerMessageSource = { kind: ProducerSourceKind; plugin: string } & ContextFormed\n\n/**\n * V4 sessions persist the producing extension in `kind`; the retired generic\n * `plugin` wrapper is not admitted. Each feature plugin declares its own kind.\n */\ndeclare module '@deepseek-ai/dsh-llm' {\n interface MessageSourceMap {\n [kind: ProducerSourceKind]: ProducerMessageSource\n }\n}\n\nexport function producerMessageSource(plugin: string): ProducerMessageSource {\n return { kind: `plugin:${plugin}`, plugin }\n}\n\nexport type RpcResult<T = unknown> = { ok: true; value: T } | { ok: false; error: { code: string; message: string } }\nexport const CHAT_EVENTS_SLOT = 'dsh-editor.chat.events'\nexport interface EvidenceRef { sessionId: string; seq: number; kind: 'user' | 'tool' | 'turn' | 'manual'; excerpt?: string }\nexport interface TaskContract {\n id: string\n sessionId: string\n sourceVersion: string\n revision: number\n goal: string\n deliverables: string[]\n inScope: string[]\n outOfScope: string[]\n constraints: string[]\n acceptance: string[]\n assumptions: string[]\n questions: string[]\n evidence: EvidenceRef[]\n readiness: 'pending' | 'clear-request' | 'user-confirmed' | 'disclosed-assumptions' | 'cancelled' | 'stale'\n updatedAt: number\n}\nexport interface TaskCheckpoint {\n id: string\n sessionId: string\n sourceVersion: string\n contractVersion?: number\n fromSeq: number\n toSeq: number\n revision: number\n status: 'running' | 'completed' | 'failed' | 'cancelled'\n items: Array<{ label: string; state: 'pending' | 'verified' | 'failed'; evidence: EvidenceRef[] }>\n constraints: string[]\n nextAction: string\n createdAt: number\n}\nexport type KnowledgeScope = { kind: 'global' } | { kind: 'project'; projectId: string }\nexport type KnowledgeKind = 'preference' | 'project-fact' | 'decision' | 'vocabulary' | 'activity' | 'lesson'\n/** Descriptive context, never an executable instruction or authorization. */\nexport interface ContextKnowledge {\n subject: string\n domain: string\n key: string\n aliases: string[]\n observedAt: number\n /** The user's own time expression, not an inferred completion date. */\n eventTime?: string\n activityStatus?: 'planned' | 'in-progress' | 'blocked' | 'paused' | 'completed' | 'cancelled' | 'unknown'\n}\n/** A scoped method. Observations remain candidates until explicitly accepted. */\nexport interface ProcedureKnowledge {\n origin: 'instruction' | 'observation'\n goal: string\n when: string[]\n steps: string[]\n avoid: string[]\n verify: string[]\n}\nexport interface MemoryRecord {\n id: string\n revision: number\n scope: KnowledgeScope\n kind: KnowledgeKind\n status: 'candidate' | 'active' | 'rejected' | 'superseded' | 'revoked' | 'deleted'\n title: string\n content: string\n tags: string[]\n evidence: EvidenceRef[]\n exceptions: string[]\n source: 'user' | 'memory' | 'dream' | 'self-improvement'\n context?: ContextKnowledge\n procedure?: ProcedureKnowledge\n createdAt: number\n updatedAt: number\n expiresAt?: number\n supersedes?: string[]\n /** Exact record revisions behind a derived candidate; revalidated on adoption. */\n basis?: Array<{ id: string; revision: number }>\n}\nexport type NewMemoryRecord = Omit<MemoryRecord, 'id' | 'revision' | 'createdAt' | 'updatedAt'>\nexport interface MemoryQuery { scope: KnowledgeScope; query?: string; kinds?: KnowledgeKind[]; statuses?: MemoryRecord['status'][]; limit?: number }\nexport interface MemoryMutationOptions { signal?: AbortSignal; isCurrent?: () => boolean }\nexport interface MemoryService {\n list(query: MemoryQuery): Promise<MemoryRecord[]>\n create(record: NewMemoryRecord, options?: MemoryMutationOptions): Promise<MemoryRecord>\n update(id: string, patch: Partial<Pick<MemoryRecord, 'title' | 'content' | 'tags' | 'exceptions' | 'status' | 'expiresAt'>>, expectedRevision: number, options?: MemoryMutationOptions): Promise<MemoryRecord>\n /** Explicit user promotion, persisted atomically on the same record; preserves expiry and evidence. */\n promoteToGlobal(id: string, expectedRevision: number, options?: MemoryMutationOptions): Promise<MemoryRecord>\n remove(id: string, expectedRevision: number, options?: MemoryMutationOptions): Promise<void>\n recall(query: MemoryQuery): Promise<MemoryRecord[]>\n}\n\n/**\n * The session creation metadata the host snapshots when it creates a delegated child\n * thread. Mirrors `CreateAgentOptions.meta` in `@deepseek-ai/dsh-agent`; it is durable\n * session data, so it survives a restart and needs no ancestry walk.\n */\nexport interface SubagentSessionLike {\n readonly header?: {\n readonly parentSession?: unknown\n readonly origin?: unknown\n readonly delegationDepth?: unknown\n readonly isSeeded?: unknown\n readonly classification?: unknown\n }\n}\n\n/**\n * True when `session` is a delegated child thread rather than a human-driven top-level\n * conversation.\n *\n * A message's `source.kind === 'user'` cannot answer this: a lead agent's dispatch prompt\n * is delivered as the child's own user message, so delegated work is indistinguishable\n * from a person typing once you only look at the message. Plugins use this to keep\n * automatic writes and derived model calls on top-level sessions.\n */\nexport function isSubagentSession(session: unknown): boolean {\n const header = (session as SubagentSessionLike | null | undefined)?.header\n if (!header || typeof header !== 'object') return false\n if (header.origin === 'subagent' || Number(header.delegationDepth ?? 0) > 0) return true\n // Native human forks also persist parentSession for history lineage. A fork's\n // seeded header distinguishes it from legacy children whose parent is the\n // only marker. Native rc.2 forks omit depth; patched hosts may persist zero.\n // Explicit delegation and unknown metadata still keep the child guard.\n const humanFork = header.isSeeded === true\n && (header.delegationDepth === undefined || header.delegationDepth === 0)\n && header.origin === undefined\n && (header.classification === undefined || header.classification === 'ordinary' || header.classification === 'free')\n return Boolean(header.parentSession) && !humanFork\n}\n\n/** Project keys come only from the host-validated session directory, never client input. */\nexport function projectIdFromCwd(cwd: string | undefined): string | undefined {\n if (typeof cwd !== 'string') return undefined\n const normalized = cwd.trim().replaceAll('\\\\', '/')\n if (!normalized) return undefined\n return normalized === '/' || /^[A-Za-z]:\\/$/.test(normalized) ? normalized : normalized.replace(/\\/+$/, '')\n}\n\n/**\n * One settings owner's Remote stream. Typert accepts either case in an RPC\n * segment, so the Cordis service key and the wire namespace use the same\n * Pascal segment. The scope's first letter stays uppercase.\n */\nexport interface ModelSettingsChangesIdentity {\n readonly service: string\n readonly namespace: string\n}\n\n/** `@klarkxy/dsh-git-commit` becomes `KlarkxyDshGitCommitModelSettingsChanges`. */\nexport function modelSettingsChangesIdentity(packageName: string): ModelSettingsChangesIdentity {\n const scoped = /^@([^/]+)\\/(.+)$/.exec(packageName)\n const body = scoped ? `${scoped[1]}/${scoped[2]}` : packageName\n const parts = body.split(/[^A-Za-z0-9]+/).filter(Boolean)\n if (!parts.length) throw new Error('Model settings package name has no RPC segment')\n const segment = `${parts.map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('')}ModelSettingsChanges`\n if (!/^[A-Z][A-Za-z0-9]*$/.test(segment)) throw new Error(`Model settings sync name is not an RPC segment: ${segment}`)\n return { service: segment, namespace: segment }\n}\n\n/**\n * Repository extension: a native web provider announces that its local\n * availability changed. Kind is `search` or `fetch`; id is the provider id.\n * Listeners refresh management state and must not treat this as a network probe.\n */\nexport const WEB_PROVIDER_AVAILABILITY_EVENT = 'web/provider-availability-updated' as const\n\n/**\n * Optional display metadata a provider may attach when it registers directly\n * with `ctx.web`. Execution and credentials stay with the provider; this object\n * is display-only and must never carry secret values.\n */\nexport interface DshWebManagementDescriptor {\n readonly id: string\n readonly label: string\n readonly description: string\n readonly defaultBaseURL?: string\n readonly credentialRef?: string\n /** True when the key is shared with another surface. The page must not delete it. */\n readonly credentialShared?: boolean\n /** Optional notice naming the settings surface that owns a shared credential. */\n readonly credentialHint?: string\n readonly billing: 'request' | 'model-and-tools' | 'none' | 'unknown'\n /** Optional provider-supplied billing summary. */\n readonly pricing?: string\n /** Public HTTPS page explaining provider charges. */\n readonly pricingUrl?: string\n /** Public HTTPS page where the user can create an API key. */\n readonly signupUrl?: string\n /** Plugin that owns configuration. Native providers keep their settings there. */\n readonly configurationOwner?: string\n /** Explicit settings link supplied by the provider, never inferred from its id. */\n readonly configurationUrl?: string\n /** Fixed legacy route migrated by a bundle-owned adapter; not used by native plugins. */\n readonly legacyId?: string\n}\n\n/**\n * Host Creator agent-preset id (`agentPresets.composedPreset`).\n * Plugins that gate Creator-only tools or prompt sections compare against this.\n */\nexport const CREATOR_PRESET_ID = 'cordis'\n\n/**\n * Shared \"Session Management\" settings section id. The section is provided by\n * shared infrastructure (see `registerSessionSettingsItem` in `client-utils`),\n * not by any one business plugin: every participant registers only a row into\n * {@link SESSION_SETTINGS_ITEM_SLOT}, so any enabled subset yields the same page.\n */\nexport const SESSION_SETTINGS_SECTION_ID = 'session-manager'\n\n/**\n * Child list slot declared by the shared Session Management page. Neutral\n * naming on purpose: participants never import each other, they only\n * contribute `{id, order}` rows into this slot while the page is alive.\n */\nexport const SESSION_SETTINGS_ITEM_SLOT = 'dsh.session-settings.item'\n\n/**\n * Host-owned nav icon seat: a root-scoped list where each entry's `id` must\n * equal the `settings.section` id it decorates. Owner props are\n * `{size, active}`; icons stay `aria-hidden` so the section label remains the\n * accessible name. Contributors into a shared section may register the same\n * icon `id` with different priorities — the ledger keeps every entry while the\n * host renders one icon per section.\n */\nexport const SETTINGS_SECTION_ICON_SLOT = 'settings.section.icon'\n\n/* Shared auxiliary-model default. Feature plugins may store a global default\n * route that fills the tier between their own saved override and the live\n * session model. The durable state is a root-context singleton (like the\n * shared session-settings page): it exists while any participant retains it\n * and is never owned by a business plugin. See `auxiliary-model.ts`. */\n\n/** Root context service key holding the shared auxiliary-model state. */\nexport const AUXILIARY_MODEL_SERVICE = 'dshAuxiliaryModel'\n\n/** Authenticated host-RPC channel for get/set of the shared default. */\nexport const AUXILIARY_MODEL_CHANNEL = '/dsh-auxiliary-model'\n\n/** Model-settings namespace under which the shared default is published. */\nexport const AUXILIARY_MODEL_NS = '@klarkxy/dsh-plugin-kit/auxiliary-model'\n\n/**\n * Typert identity of the shared change stream. Mounted on the root context\n * with ownerNs filtering, so frames only carry {@link AUXILIARY_MODEL_NS}.\n */\nexport const AUXILIARY_MODEL_CHANGES_IDENTITY = modelSettingsChangesIdentity('@klarkxy/dsh-plugin-kit')\n\n/** The value the shared default persists: `model: null` means follow the live session/host model. */\nexport interface AuxiliaryModelDefaults {\n readonly revision: number\n readonly model: ModelRoute | null\n}\n\n/** Shape of the root singleton; produced and owned by `auxiliary-model.ts`. */\nexport interface AuxiliaryModelShared {\n readonly ready: Promise<void>\n snapshot(): AuxiliaryModelDefaults\n}\n\nfunction sharedAuxiliaryModel(host: unknown): AuxiliaryModelShared | undefined {\n const root = (host as { root?: unknown } | undefined)?.root as { get?(name: string, strict?: boolean): unknown } | undefined\n try {\n const shared = root?.get?.(AUXILIARY_MODEL_SERVICE, false) as AuxiliaryModelShared | undefined\n return shared && typeof shared.snapshot === 'function' ? shared : undefined\n } catch { return undefined }\n}\n\n/**\n * Synchronously read the shared auxiliary default; `undefined` only when no\n * participant retains the singleton or the default is legitimately unset.\n * An initialization or snapshot failure propagates: silently falling back to\n * a different model after a storage error would spend the wrong budget.\n */\nexport function getAuxiliaryModel(host: unknown): ModelRoute | undefined {\n const shared = sharedAuxiliaryModel(host)\n if (!shared) return undefined\n return modelRouteOverride(shared.snapshot().model ?? undefined)\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { RpcResult } from './contracts.ts'\n\nexport interface HostRpcContext {\n webServer: { register(route: { kind: 'prefix'; path: string; handler(req: IncomingMessage, res: ServerResponse): void | Promise<void> }): () => void }\n connection: { requestRejection?: (request: IncomingMessage) => number | undefined }\n}\n\ntype Rejection = { status: number; body?: string }\n\nexport interface HostRpcTransportOptions {\n maxBodyBytes?: number\n isEndpoint?: (endpoint: string) => boolean\n caseInsensitiveContentType?: boolean\n emptyBodyAsNull?: boolean\n beforeBody?: (request: IncomingMessage, endpoint: string) => Rejection | undefined\n errorBody?: (status: number, error?: unknown) => string | undefined\n}\n\nexport interface HostRpcOptions extends HostRpcTransportOptions {\n requirePayload?: boolean\n}\n\n/** The shared authenticated HTTP boundary. Each plugin still owns its RPC envelope semantics. */\nexport function registerHostRpcTransport(\n ctx: HostRpcContext,\n channel: string,\n dispatch: (endpoint: string, body: unknown, signal: AbortSignal, response: ServerResponse) => void | Promise<void>,\n options: HostRpcTransportOptions = {},\n): () => void {\n const bodyLimit = options.maxBodyBytes ?? 64 * 1024\n if (!Number.isSafeInteger(bodyLimit) || bodyLimit <= 0) throw new Error('Invalid RPC body limit')\n const isEndpoint = options.isEndpoint ?? ((endpoint: string) => /^[a-z.]+$/.test(endpoint))\n return ctx.webServer.register({ kind: 'prefix', path: channel, handler: async (req, res) => {\n const reject = (status: number, error?: unknown, override?: string) => {\n if (res.destroyed) return\n if (status === 413) res.writeHead(status, { connection: 'close' })\n else res.writeHead(status)\n res.end(override ?? options.errorBody?.(status, error) ?? (status === 500 ? 'rpc request failed' : ''))\n }\n try {\n // Host admission always runs before plugin-specific checks or body reads.\n if (typeof ctx.connection.requestRejection !== 'function') { reject(503); return }\n const rejection = ctx.connection.requestRejection(req)\n if (rejection !== undefined) { reject(rejection); return }\n const pathname = new URL(req.url ?? '/', 'http://dsh.internal').pathname\n const endpoint = pathname.startsWith(`${channel}/`) ? pathname.slice(channel.length + 1) : ''\n if (req.method !== 'POST' || !isEndpoint(endpoint)) { reject(404); return }\n const contentType = String(req.headers['content-type'] ?? '').split(';', 1)[0]?.trim()\n if ((options.caseInsensitiveContentType ? contentType.toLowerCase() : contentType) !== 'application/json') {\n reject(415); return\n }\n const guarded = options.beforeBody?.(req, endpoint)\n if (guarded) { reject(guarded.status, undefined, guarded.body); return }\n\n const controller = new AbortController()\n res.on('close', () => { if (!res.writableEnded) controller.abort() })\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of req) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n size += buffer.length\n if (size > bodyLimit) { reject(413); req.destroy(); return }\n chunks.push(buffer)\n }\n let body: unknown\n try { body = JSON.parse(Buffer.concat(chunks).toString('utf8') || (options.emptyBodyAsNull ? 'null' : '')) }\n catch { reject(400); return }\n await dispatch(endpoint, body, controller.signal, res)\n } catch (error) {\n reject(500, error)\n }\n } })\n}\n\n/** Write the native Connection response envelope after a plugin has handled a request. */\nexport function sendHostRpcResponse(response: ServerResponse, rpcId: string, result: unknown, noStore = true): void {\n if (response.destroyed) return\n response.writeHead(200, { 'content-type': 'application/json', ...(noStore ? { 'cache-control': 'no-store' } : {}) })\n response.end(JSON.stringify({ type: 'server-response', rpcId, result }))\n}\n\n/** Safe host RPC registration. Missing requestRejection fails closed. */\nexport function registerHostRpc<R extends RpcResult = RpcResult>(\n ctx: HostRpcContext,\n channel: string,\n call: (endpoint: string, payload: unknown, signal: AbortSignal) => Promise<R>,\n options: HostRpcOptions = {},\n): () => void {\n return registerHostRpcTransport(ctx, channel, async (endpoint, body, signal, res) => {\n if (!body || typeof body !== 'object' || Array.isArray(body)) { res.writeHead(400); res.end(); return }\n const request = body as Record<string, unknown>\n if (request.type !== 'client-request' || request.method !== endpoint || typeof request.rpcId !== 'string'\n || (options.requirePayload && !Object.hasOwn(request, 'payload'))) {\n res.writeHead(400); res.end(); return\n }\n const raw = await call(endpoint, request.payload, signal)\n const result = raw.ok ? raw : { ...raw, error: { details: {}, ...raw.error } }\n sendHostRpcResponse(res, request.rpcId, result)\n }, options)\n}\n","import type { ModelRoute } from '@klarkxy/dsh-model-route'\n\n/** Built-in display copy; plain strings preserve third-party and user-provided text. */\nexport type ModelSettingsText = string | { zh: string; en: string }\n\n/** Plugin-owned model settings, independent of native volatile Config forms. */\nexport interface ModelSettingsField {\n path: string[]\n label: ModelSettingsText\n description?: ModelSettingsText\n current?: ModelRoute\n editable?: false\n allowFollow?: boolean\n followLabel?: ModelSettingsText\n}\nexport interface ModelSettingsSnapshot {\n revision: number\n fields: ModelSettingsField[]\n /** A separate model domain, e.g. external Codex; never use the DSH catalog here. */\n catalog?: unknown\n catalogError?: ModelSettingsText\n}\nexport interface ModelSettingsProvider {\n ns: string\n title: ModelSettingsText\n instanceId?: string\n read(signal: AbortSignal): ModelSettingsSnapshot | Promise<ModelSettingsSnapshot>\n write(path: readonly string[], route: ModelRoute, expectedRevision: number, signal: AbortSignal): Promise<unknown>\n}\n\nexport const MODEL_SETTINGS_EVENT = 'model-settings/collect'\nexport const MODEL_SETTINGS_CHANGED_EVENT = 'model-settings/changed'\nexport interface ModelSettingsChange { ns: string; revision: number }\n\n/** Publish only after the owner's save commits. A failed observer must never\n * turn an already committed write into an apparent save failure. */\nexport function notifyModelSettingsChanged(ctx: {\n parallel(name: typeof MODEL_SETTINGS_CHANGED_EVENT, change: ModelSettingsChange): Promise<void>\n}, ns: string, revision: number): void {\n try {\n // Cordis emit returns void and cannot contain an async observer rejection.\n void ctx.parallel(MODEL_SETTINGS_CHANGED_EVENT, { ns, revision }).catch(() => {})\n } catch { /* The save has already committed. */ }\n}\ntype Collector = (provider: ModelSettingsProvider) => void\nexport interface ModelSettingsEvents {\n on(name: typeof MODEL_SETTINGS_EVENT, callback: (collect: Collector) => void): () => void\n}\nexport interface ModelSettingsDiscovery {\n parallel(name: typeof MODEL_SETTINGS_EVENT, collect: Collector): Promise<void>\n}\n\n/** Cordis disposes the listener with its fiber. In-flight references also fail closed. */\nexport function registerModelSettings(ctx: ModelSettingsEvents, provider: ModelSettingsProvider): () => void {\n let active = true\n const requireActive = (signal: AbortSignal) => {\n signal.throwIfAborted()\n if (!active) throw new Error('Model settings owner unloaded; refresh and retry')\n }\n const guarded: ModelSettingsProvider = {\n ns: provider.ns, title: provider.title, instanceId: globalThis.crypto.randomUUID(),\n async read(signal) {\n requireActive(signal)\n const value = await provider.read(signal)\n requireActive(signal)\n return value\n },\n async write(path, route, revision, signal) {\n requireActive(signal)\n return provider.write(path, route, revision, signal)\n },\n }\n const off = ctx.on(MODEL_SETTINGS_EVENT, collect => { if (active) collect(guarded) })\n // Call this disposer from ctx.effect as well: listener removal alone does not\n // revoke a reference captured just before the owning plugin was unloaded.\n return () => { active = false; off() }\n}\n\nexport async function collectModelSettings(ctx: ModelSettingsDiscovery): Promise<ModelSettingsProvider[]> {\n const providers: ModelSettingsProvider[] = []\n const duplicates: string[] = []\n await ctx.parallel(MODEL_SETTINGS_EVENT, provider => {\n if (!provider.ns || providers.some(item => item.ns === provider.ns)) { duplicates.push(provider.ns); return }\n providers.push(provider)\n })\n if (duplicates.length) throw new Error(`Duplicate model settings owner: ${duplicates.join(', ')}`)\n return providers.sort((a, b) => a.ns.localeCompare(b.ns))\n}\n","import type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport { modelSettingsChangesIdentity, type ModelSettingsChangesIdentity } from './contracts.ts'\n\nexport type ModelSettingsChangeFrame = { kind: 'ready' } | { kind: 'changed'; ns: string; revision: number }\n\n/** This stream carries invalidations only; ready is never a settings snapshot. */\nexport function parseModelSettingsChangeFrame(value: unknown): ModelSettingsChangeFrame {\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid model settings change frame')\n const frame = value as Record<string, unknown>\n if (frame.kind === 'ready' && Object.keys(frame).length === 1) return { kind: 'ready' }\n if (frame.kind === 'changed' && Object.keys(frame).length === 3 && typeof frame.ns === 'string' && frame.ns.length > 0\n && typeof frame.revision === 'number' && Number.isSafeInteger(frame.revision) && frame.revision >= 0) {\n return { kind: 'changed', ns: frame.ns, revision: frame.revision }\n }\n throw new Error('Invalid model settings change frame')\n}\n\n/** One owner's contribution. Each package mounts only its own endpoint. */\nexport function modelSettingsChangesRemote(packageName: string, identity: ModelSettingsChangesIdentity = modelSettingsChangesIdentity(packageName)): TypertRemoteContribution {\n return {\n package: packageName,\n descriptors: [{\n id: `${identity.namespace}/watch`,\n service: identity.service,\n namespace: identity.namespace,\n method: 'watch',\n mode: 'stream' as const,\n invocation: { kind: 'direct' as const },\n parameters: [],\n cancellation: { parameter: 'signal' as const },\n result: { mode: 'strict' as const, typeSymbol: 'ModelSettings.ChangeFrame', create: () => ({ parse: parseModelSettingsChangeFrame }) },\n }],\n }\n}\n\ninterface RemoteMountScope {\n remote: { $mount(contribution: TypertRemoteContribution): Promise<() => Promise<void>> }\n effect(callback: () => () => void | Promise<void>): unknown\n}\ninterface RemoteMountContext {\n inject(dependencies: string[], callback: (scope: unknown) => void): unknown\n}\n\n/** Mount from a synchronous apply. Disposal waits for an in-flight mount and\n * then withdraws it, so the contribution cannot outlive the plugin. */\nexport function mountModelSettingsChanges(ctx: RemoteMountContext, packageName: string): void {\n const contribution = modelSettingsChangesRemote(packageName)\n ctx.inject(['remote'], injected => {\n const scope = injected as RemoteMountScope\n const mounting = scope.remote.$mount(contribution)\n void mounting.catch(() => {})\n scope.effect(() => async () => {\n const unmount = await mounting.catch(() => undefined)\n await unmount?.()\n })\n })\n}\n\ninterface StreamItem {\n generation: number\n value: unknown\n signal: AbortSignal\n accept(): void\n}\ninterface ChangeStream extends AsyncIterable<StreamItem> { dispose(): Promise<void> }\ntype OpenChangeStream = (options: {\n name: string\n open(signal: AbortSignal): AsyncIterable<unknown>\n ended(accepted: boolean): Error\n}) => ChangeStream\nexport interface ModelSettingsSubscriberScope {\n remote: { $stream: OpenChangeStream } & Record<string, { watch?(signal: AbortSignal): AsyncIterable<unknown> } | OpenChangeStream | undefined>\n effect(callback: () => () => void | Promise<void>): unknown\n}\nexport interface ModelSettingsSubscriberContext {\n inject(dependencies: string[], callback: (scope: unknown) => void): unknown\n}\nexport interface ModelSettingsSubscriber {\n subscribe(onChange: () => void, onError?: (message: string) => void): () => void\n}\n\n/** Native RemoteStream owns carrier reconnects; no timers or browser transport.\n * A factory shares one logical stream while at least one subscriber remains. */\nexport function createModelSettingsSubscriber(\n ctx: ModelSettingsSubscriberContext,\n packageName: string,\n identity: ModelSettingsChangesIdentity = modelSettingsChangesIdentity(packageName),\n accept: (ns: string) => boolean = ns => ns === packageName,\n): ModelSettingsSubscriber {\n const endpoint = identity\n const listeners = new Set<{ change: () => void; error?: (message: string) => void }>()\n let injection: { dispose(): void | Promise<void> } | undefined\n let current: { stream: ChangeStream; active: boolean } | undefined\n let lifecycle = 0\n let failureMessage: string | undefined\n const report = (message: string) => {\n failureMessage = message\n for (const listener of [...listeners]) {\n try { listener.error?.(message) } catch { /* Isolate page callbacks. */ }\n }\n }\n const invalidate = () => {\n for (const listener of [...listeners]) {\n if (!listeners.has(listener)) continue\n try { listener.change() } catch (error) {\n try { listener.error?.(error instanceof Error ? error.message : String(error)) } catch { /* Isolate callbacks. */ }\n }\n }\n }\n const start = () => {\n const life = ++lifecycle\n injection = ctx.inject(['remote', `remote.${endpoint.namespace}`], injected => {\n if (life !== lifecycle || !listeners.size) return\n const scope = injected as ModelSettingsSubscriberScope\n const service = scope.remote[endpoint.namespace]\n if (!service || !('watch' in service) || !service.watch) { report('Model settings sync service unavailable'); return }\n const watch = service.watch\n const stream = scope.remote.$stream({\n name: 'Model settings sync',\n open: signal => watch(signal),\n ended: accepted => new Error(`Model settings sync stream ended ${accepted ? 'after' : 'before'} ready; refresh or reopen the page`),\n })\n const session = { stream, active: true }\n current = session\n scope.effect(() => () => {\n session.active = false\n if (current === session) {\n current = undefined\n if (life === lifecycle && listeners.size) report('Model settings sync service unavailable')\n }\n return stream.dispose()\n })\n void (async () => {\n let generation: number | undefined\n let ready = false\n try {\n for await (const item of stream) {\n if (!session.active || life !== lifecycle || !listeners.size) break\n if (item.signal.aborted) continue\n if (generation !== item.generation) { generation = item.generation; ready = false }\n const frame = parseModelSettingsChangeFrame(item.value)\n if (frame.kind === 'ready') {\n ready = true\n failureMessage = undefined\n // Accept the validated invalidation baseline, not fetched data.\n // Every current listener queues its own latest settings read.\n item.accept()\n invalidate()\n } else {\n if (!ready) throw new Error('Model settings sync change arrived before ready')\n if (accept(frame.ns)) invalidate()\n }\n }\n } catch (error) {\n if (session.active && life === lifecycle) report(error instanceof Error ? error.message : String(error))\n } finally {\n if (current === session) current = undefined\n session.active = false\n await stream.dispose().catch(() => {})\n }\n })()\n }) as { dispose(): void | Promise<void> }\n queueMicrotask(() => {\n if (life === lifecycle && listeners.size && !current) report('Model settings sync service unavailable')\n })\n }\n return Object.freeze({ subscribe(onChange: () => void, onError?: (message: string) => void) {\n const listener = { change: onChange, error: onError }\n listeners.add(listener)\n if (!injection) start()\n else if (failureMessage) queueMicrotask(() => {\n if (listeners.has(listener) && failureMessage) {\n try { listener.error?.(failureMessage) } catch { /* Isolate callbacks. */ }\n }\n })\n return () => {\n if (!listeners.delete(listener) || listeners.size) return\n lifecycle++\n if (current) { current.active = false; void current.stream.dispose().catch(() => {}) }\n current = undefined\n failureMessage = undefined\n const previous = injection\n injection = undefined\n try { void Promise.resolve(previous?.dispose()).catch(() => {}) } catch { /* Already unloaded. */ }\n }\n } })\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport { Remote, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'\nimport type { ModelSettingsChangesIdentity } from './contracts.ts'\nimport { MODEL_SETTINGS_CHANGED_EVENT, type ModelSettingsChange } from './model-settings.ts'\nimport { parseModelSettingsChangeFrame, type ModelSettingsChangeFrame } from './model-settings-client.ts'\n\ninterface ChangeEvents {\n on(name: typeof MODEL_SETTINGS_CHANGED_EVENT, callback: (change: ModelSettingsChange) => void): () => void\n on(name: 'settings/document-updated', callback: (ns: string, revision: number) => void): () => void\n}\n\n/** Attach first, then yield ready: commits during a consumer's baseline read\n * remain queued. Coalescing revisions never invents a settings snapshot.\n * `ownerNs` keeps one plugin's stream to its own settings; omit it to forward every namespace. */\nexport async function* watchModelSettingsChanges(events: ChangeEvents, signal: AbortSignal, ownerNs?: string): AsyncGenerator<ModelSettingsChangeFrame> {\n signal.throwIfAborted()\n const pending = new Map<string, ModelSettingsChangeFrame>()\n let full = false\n let wake: (() => void) | undefined\n const changed = (ns: string, revision: number) => {\n if (ownerNs !== undefined && ns !== ownerNs) return\n let frame: ModelSettingsChangeFrame\n try { frame = parseModelSettingsChangeFrame({ kind: 'changed', ns, revision }) } catch { return }\n if (!full) {\n if (!pending.has(ns) && pending.size >= 256) { pending.clear(); full = true }\n else pending.set(ns, frame)\n }\n wake?.()\n }\n const disposers: (() => void)[] = []\n const cleanup = () => {\n for (const off of disposers.splice(0).reverse()) off()\n pending.clear()\n }\n // Release listeners even if the consumer is paused at a yielded frame.\n const aborted = () => { cleanup(); wake?.() }\n signal.addEventListener('abort', aborted, { once: true })\n try {\n disposers.push(events.on(MODEL_SETTINGS_CHANGED_EVENT, ({ ns, revision }) => changed(ns, revision)))\n disposers.push(events.on('settings/document-updated', changed))\n signal.throwIfAborted()\n yield { kind: 'ready' }\n while (true) {\n signal.throwIfAborted()\n if (full) { full = false; yield { kind: 'ready' }; continue }\n if (pending.size) {\n const [ns, frame] = pending.entries().next().value!\n pending.delete(ns)\n yield frame\n continue\n }\n await new Promise<void>(resolve => {\n wake = resolve\n if (signal.aborted || full || pending.size) resolve()\n })\n wake = undefined\n }\n } finally {\n signal.removeEventListener('abort', aborted)\n cleanup()\n }\n}\n\n/** One owner's invalidation stream, registered on the calling plugin fiber.\n * Nothing here is stored in a module-level singleton. */\nexport class ModelSettingsChangesController extends TypertRemoteService {\n private readonly lifetime = new AbortController()\n private readonly ownerNs: string | undefined\n constructor(ctx: Context, identity: ModelSettingsChangesIdentity, ownerNs?: string) {\n super(ctx, identity.service, { namespace: identity.namespace })\n this.ownerNs = ownerNs\n ctx.effect(() => () => { this.lifetime.abort(new Error('Model settings sync owner unloaded')) })\n }\n\n @Remote({ mode: 'stream' })\n watch(signal: AbortSignal): AsyncIterable<ModelSettingsChangeFrame> {\n return watchModelSettingsChanges(this.ctx as unknown as ChangeEvents, AbortSignal.any([this.lifetime.signal, signal]), this.ownerNs)\n }\n}\n\n/** Register this owner's controller. `ownerNs` limits the stream to that settings namespace. */\nexport function createModelSettingsChanges(ctx: Context, identity: ModelSettingsChangesIdentity, ownerNs?: string): ModelSettingsChangesController {\n return new ModelSettingsChangesController(ctx, identity, ownerNs)\n}\n","/**\n * Shared auxiliary-model default: host-side lifecycle.\n *\n * The default model is repository-shared infrastructure, not one plugin's\n * business state. Its owner is a dedicated Cordis fiber started on the root\n * context by the first participant and disposed by the last release, so the\n * storage domain, the Typert change stream, the RPC channel and the\n * model-settings provider all live and die with the shared owner — never\n * with a business plugin's fiber. Every bundler's own copy of this module\n * rendezvous through `ctx.root`, so no participant depends on another being\n * enabled.\n *\n * Concurrency:\n * - Writes serialize on `state.tail`; the revision check and the bump both\n * happen inside the queued commit, so two callers carrying the same\n * expectedRevision cannot both succeed.\n * - `state.closing` is the single teardown promise: it settles init, drains\n * queued writes, disposes the owner fiber (route, stream, provider,\n * domain) and only then unprovides the state, so a re-entrant retain can\n * always await it and reinstall cleanly.\n * - Initialization and stored-row failures are sticky (`state.error`) and\n * rethrow from `snapshot()`: a storage error must never read as \"no\n * default\" and silently fall back to another model.\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { modelRouteOverride, normalizeModelRoute, type ModelRoute } from '@klarkxy/dsh-model-route'\nimport {\n AUXILIARY_MODEL_CHANNEL, AUXILIARY_MODEL_CHANGES_IDENTITY, AUXILIARY_MODEL_NS,\n AUXILIARY_MODEL_SERVICE, type AuxiliaryModelDefaults, type AuxiliaryModelShared, type RpcResult,\n} from './contracts.ts'\nimport { registerHostRpc, type HostRpcContext } from './host-rpc.ts'\nimport { createModelSettingsChanges } from './model-settings-changes.ts'\nimport { registerModelSettings, notifyModelSettingsChanged, type ModelSettingsEvents } from './model-settings.ts'\n\nconst DOMAIN_NAME = 'dsh_auxiliary'\nconst DOMAIN_VERSION = 1\nconst TABLE = 'settings'\nconst KEY = 'defaults'\nconst INJECT = ['storageDomain', 'webServer', 'connection'] as const\n\ninterface DomainHandle {\n table(name: string): {\n get(key: string): { revision: number; model: ModelRoute | null } | undefined\n put(key: string, value: unknown): Promise<void>\n }\n close(): Promise<void>\n}\n\ninterface Scope extends HostRpcContext, ModelSettingsEvents {\n storageDomain: { open(spec: unknown): Promise<DomainHandle> }\n effect(callback: () => (() => void) | Promise<(() => void) | void>): unknown\n}\n\ninterface RootLike {\n get(name: string, strict?: boolean): unknown\n provide(name: string, value: unknown): () => void\n inject(deps: readonly string[], callback: (scope: Scope) => void): { dispose(): Promise<void> } & PromiseLike<unknown>\n}\n\ninterface SharedState extends AuxiliaryModelShared {\n ready: Promise<void>\n users: number\n closed: boolean\n /** True only while the owner fiber's domain is open; snapshot() gates on it. */\n available: boolean\n /** Generation of the latest scope init; a stale run must not win. */\n generation: number\n /** Sticky init/storage failure; snapshot() rethrows it. */\n error?: unknown\n closing?: Promise<void>\n domain?: DomainHandle\n data: AuxiliaryModelDefaults\n tail: Promise<void>\n fiber?: { dispose(): Promise<void> }\n scopeInit?: Promise<void>\n stopUnprovide?: () => void\n teardown(): Promise<void>\n}\n\n/** Marker on the benign \"released while the domain was still opening\" error. */\nconst RECOVERABLE = Symbol.for('klarkxy.dsh.auxiliary-model.recoverable')\nfunction recoverable<T extends object>(error: T): T & { [RECOVERABLE]?: boolean } {\n (error as Record<symbol, unknown>)[RECOVERABLE] = true\n return error as T & { [RECOVERABLE]?: boolean }\n}\n\nasync function openSharedDomain(scope: Scope): Promise<DomainHandle> {\n const [{ defineDomain, domainTable }, { z }] = await Promise.all([\n import('@deepseek-ai/dsh-storage-domain'), import('zod'),\n ])\n // Strict, write-side semantics at the durable boundary: identifiers must be\n // non-blank, already trimmed and control-free, or the row is rejected —\n // a malformed stored route must never normalize into \"no default\".\n const identifier = z.string().min(1).max(250).refine(\n value => value === value.trim() && !/[\\x00-\\x1f\\x7f]/.test(value),\n 'model route identifiers must be non-blank, trimmed and control-free',\n )\n const model = z.union([\n z.object({\n provider: identifier,\n model: identifier,\n reasoningEffort: identifier.max(80).optional(),\n }).strict(),\n z.null(),\n ])\n return scope.storageDomain.open(defineDomain({\n name: DOMAIN_NAME, version: DOMAIN_VERSION,\n tables: {\n [TABLE]: domainTable(z.object({\n revision: z.number().int().nonnegative(),\n model,\n }).strict()),\n },\n }))\n}\n\n/** Marks an optimistic-lock conflict so the RPC envelope can carry 'conflict'. */\nfunction conflictError(message: string): Error & { conflict: true } {\n return Object.assign(new Error(message), { conflict: true as const })\n}\n\n/** RPC-visible error classification; storage failures stay sanitized. */\nfunction rpcFailure(error: unknown): RpcResult {\n if (error && typeof error === 'object' && 'conflict' in error) {\n return { ok: false, error: { code: 'auxiliary-model/conflict', message: error instanceof Error ? error.message : 'Revision conflict' } }\n }\n if (error instanceof Error && /Invalid model route|valid expected revision|Unknown auxiliary model setting/.test(error.message)) {\n return { ok: false, error: { code: 'auxiliary-model/rejected', message: error.message } }\n }\n return { ok: false, error: { code: 'auxiliary-model/store', message: 'Auxiliary model store request failed' } }\n}\n\n/**\n * Serialized optimistic-lock write; resolves after the durable put commits.\n * Revision verification happens inside the queue: two writers carrying the\n * same expectedRevision race for one slot and only the first commits.\n * Notification fires only after commit, so a failed observer can never turn\n * an already committed write into an apparent save failure.\n */\nfunction setSharedModel(state: SharedState, ctx: Context, input: unknown, expectedRevision: unknown): Promise<AuxiliaryModelDefaults> {\n if (!Number.isSafeInteger(expectedRevision)) return Promise.reject(conflictError('A valid expected revision is required; reload and retry'))\n const row = input && typeof input === 'object' && !Array.isArray(input) ? input as Record<string, unknown> : undefined\n const validField = (value: unknown): value is string =>\n typeof value === 'string' && value === value.trim() && !/[\\x00-\\x1f\\x7f]/.test(value)\n if (!row || ['provider', 'model', 'reasoningEffort'].some(key => row[key] !== undefined && !validField(row[key]))) {\n return Promise.reject(new Error('Invalid model route'))\n }\n const normalized = normalizeModelRoute(row)\n if ((Boolean(row.provider) || Boolean(row.model)) && !modelRouteOverride(normalized)) {\n return Promise.reject(new Error('Invalid model route'))\n }\n const commit = state.tail.then(async (): Promise<AuxiliaryModelDefaults> => {\n if (state.closed || !state.domain) throw new Error('Auxiliary model settings are unloading; retry in a moment')\n if (expectedRevision !== state.data.revision) throw conflictError('Auxiliary model settings changed; reload and retry')\n const next: AuxiliaryModelDefaults = { revision: state.data.revision + 1, model: modelRouteOverride(normalized) ?? null }\n await state.domain.table(TABLE).put(KEY, { revision: next.revision, model: next.model })\n state.data = next\n notifyModelSettingsChanged(ctx.root, AUXILIARY_MODEL_NS, next.revision)\n return next\n })\n // The tail itself never rejects: a failed commit must not poison later writes.\n state.tail = commit.then(() => {}, () => {})\n return commit\n}\n\nfunction initScope(state: SharedState, ctx: Context, scope: Scope): Promise<void> {\n // A dependency loss unloads this fiber (running its disposers) and a\n // remount re-runs the callback (bumping state.generation), so an init that\n // was still opening always detects its own supersession through these two\n // public signals. Service identity is intentionally NOT compared anywhere:\n // `ctx.<service>` reads hand out a fresh traceable proxy per access for\n // every tracker'd impl (all Service subclasses — storageDomain, webServer,\n // connection), so identity comparisons reported a fake dep swap after each\n // await and aborted every open with 'released during open'.\n const generation = ++state.generation\n let disposed = false\n // Registered synchronously while the callback runs; a throw means the\n // fiber is already inactive and this init must not open anything.\n scope.effect(() => () => { disposed = true })\n const stale = () => state.closed || disposed || state.generation !== generation\n const run = (async () => {\n // Reads must stay unavailable until this init completes.\n state.available = false\n const domain = await openSharedDomain(scope)\n if (stale()) { await domain.close(); throw recoverable(new Error('Auxiliary model store released during open')) }\n state.domain = domain\n // scope.effect throws on an inactive fiber (disposed mid-open): close the\n // domain directly so it is never leaked, then rethrow — a store that\n // cannot register its own cleanup must not publish data.\n try { scope.effect(() => () => domain.close()) } catch (error) { await domain.close(); throw error }\n // Strict schema: a malformed stored row fails the open path instead of\n // silently collapsing to \"no default\".\n const stored = domain.table(TABLE).get(KEY)\n if (stale()) { await domain.close(); throw recoverable(new Error('Auxiliary model store superseded during open')) }\n state.data = { revision: stored?.revision ?? 0, model: stored?.model ?? null }\n state.error = undefined\n state.available = true\n scope.effect(() => registerModelSettings(scope, {\n ns: AUXILIARY_MODEL_NS,\n title: { zh: '辅助模型', en: 'Auxiliary model' },\n read(signal) {\n signal.throwIfAborted()\n const { revision, model } = state.data\n return {\n revision,\n fields: [{\n path: ['model'],\n label: { zh: '全局辅助模型', en: 'Global auxiliary model' },\n current: model ?? undefined,\n allowFollow: true,\n followLabel: { zh: '当前会话模型', en: 'Current conversation model' },\n }],\n }\n },\n async write(path, route, expectedRevision, signal) {\n signal.throwIfAborted()\n if (path.length !== 1 || path[0] !== 'model') throw new Error('Unknown auxiliary model setting')\n return setSharedModel(state, ctx, route, expectedRevision)\n },\n }))\n scope.effect(() => registerHostRpc(scope, AUXILIARY_MODEL_CHANNEL, async (endpoint, payload, signal) => {\n signal.throwIfAborted()\n if (state.closed) return { ok: false, error: { code: 'auxiliary-model/unloading', message: 'Auxiliary model settings are unloading; retry in a moment' } } satisfies RpcResult\n if (!state.available) {\n return state.error\n ? { ok: false, error: { code: 'auxiliary-model/store', message: 'Auxiliary model store request failed' } } satisfies RpcResult\n : { ok: false, error: { code: 'auxiliary-model/unavailable', message: 'Auxiliary model settings are unavailable; retry in a moment' } } satisfies RpcResult\n }\n if (endpoint === 'defaults.get') {\n const { revision, model } = state.data\n return { ok: true, value: { revision, model } } satisfies RpcResult\n }\n if (endpoint === 'defaults.set') {\n try {\n const body = payload && typeof payload === 'object' && !Array.isArray(payload) ? payload as Record<string, unknown> : {}\n const value = await setSharedModel(state, ctx, body.model, body.expectedRevision)\n signal.throwIfAborted()\n return { ok: true, value } satisfies RpcResult\n } catch (error) {\n if (signal.aborted) throw error\n return rpcFailure(error)\n }\n }\n return { ok: false, error: { code: 'auxiliary-model/unknown-endpoint', message: `Unknown endpoint: ${endpoint}` } } satisfies RpcResult\n }, { isEndpoint: endpoint => /^[a-z.]+$/.test(endpoint) }))\n // The change stream lives and dies with this shared fiber.\n createModelSettingsChanges(scope as unknown as Context, AUXILIARY_MODEL_CHANGES_IDENTITY, AUXILIARY_MODEL_NS)\n // Disposers run LIFO on unload: registered last, this runs FIRST when a\n // dependency remount tears the scope down — reads go unavailable before\n // the domain closes, so no stale default ever leaks. Gated on generation\n // alone: the same generation's unload must clear state even when its dep\n // impl just changed; only a superseded scope's teardown stays out.\n scope.effect(() => () => { if (state.generation === generation) { state.available = false; state.domain = undefined } })\n })().catch(error => {\n // Tag the failure with its generation so ready.catch can distinguish a\n // superseded init's rejection from the live scope's.\n if (error && typeof error === 'object') (error as Record<string, unknown>).auxGeneration = generation\n // Only THIS generation's failure poisons the store: a superseded init's\n // rejection must not clear a newer scope's available state.\n if (state.generation === generation) {\n state.available = false\n state.error = error\n }\n throw error\n })\n // Retainers always await the CURRENT init: re-arm state.ready so nobody is\n // left waiting on a superseded generation's settled promise. Both promises\n // get a handled branch so a rejected init never surfaces as an unhandled\n // rejection while awaiters still see it.\n run.catch(() => {})\n const armed = run.then(() => {})\n armed.catch(() => {})\n state.ready = armed\n return run\n}\n\nfunction teardown(state: SharedState, ctx: Context): Promise<void> {\n if (!state.closing) {\n state.closed = true\n const root = ctx.root as unknown as RootLike\n state.closing = (async () => {\n // A still-opening init settles here so its domain/fiber are disposed.\n await state.scopeInit?.catch(() => {})\n await state.tail.catch(() => {})\n try { await state.fiber?.dispose() } catch (error) {\n // A failed dispose may leave the domain open; log loudly so the next\n // open's 'already open' error is attributable instead of mysterious.\n try { (ctx as unknown as { logger?: { warn(...args: unknown[]): void } }).logger?.warn('auxiliary-model: fiber dispose failed', error) }\n catch { /* no logger */ }\n }\n try {\n if (root.get(AUXILIARY_MODEL_SERVICE, false) === state) state.stopUnprovide?.()\n } catch { /* root already gone */ }\n state.stopUnprovide = undefined\n })()\n }\n return state.closing\n}\n\nfunction createSharedState(ctx: Context): SharedState {\n const root = ctx.root as unknown as RootLike\n const state: SharedState = {\n users: 0, closed: false, available: false, generation: 0, tail: Promise.resolve(),\n data: { revision: 0, model: null },\n snapshot() {\n // A persisted-open failure propagates: falling back to another model\n // after a storage error would silently switch what the user pays for.\n if (this.error) throw this.error\n // While the owner fiber re-initializes after a dependency remount, the\n // stored default is unreadable: reads fail instead of serving stale data.\n if (!this.available) throw new Error('Auxiliary model store is unavailable; retry in a moment')\n return this.data\n },\n ready: Promise.resolve(),\n teardown() { return teardown(this, ctx) },\n }\n // Strict requirement: every service must already be ACTIVE. Callers are\n // plugins declaring these in inject — Cordis only runs their apply once the\n // deps are active, so a missing or still-pending service is a hard error,\n // not something to wait on. Retry is the caller's Cordis lifecycle, not ours.\n const inactive = INJECT.filter(service => {\n try { return root.get(service, true) === undefined } catch { return true }\n })\n if (inactive.length) {\n throw new Error(`retainAuxiliaryModel requires active ${inactive.join(', ')}; declare them in inject`)\n }\n state.fiber = root.inject(INJECT, scope => { state.scopeInit = initScope(state, ctx, scope) })\n state.ready = Promise.resolve(state.fiber).then(() => {\n // The owner fiber ran to settle: its scope must have started init, and\n // that init must complete before the store reads as ready. A dep dropping\n // between the strict check and inject leaves the fiber PENDING; Cordis\n // re-runs it when the dep returns — never a silent half-initialized read.\n if (!state.scopeInit) throw recoverable(new Error('Auxiliary model owner fiber settled without initializing its scope'))\n return state.scopeInit\n })\n // A failed open must not leave a live-looking state behind: mark it\n // closed and tear it down so the next retain reinstalls. A rejection\n // tagged with a superseded generation describes a scope this state has\n // already moved past — it must not tear down a newer, live scope.\n state.ready.catch(error => {\n const tag = (error as { auxGeneration?: number }).auxGeneration\n if (tag !== undefined && tag !== state.generation) return\n state.error = state.error ?? error\n state.closed = true\n void state.teardown()\n })\n // Publish only after construction completes: another retainer can now\n // either reuse this state or watch its closed flag.\n state.stopUnprovide = root.provide(AUXILIARY_MODEL_SERVICE, state)\n return state\n}\n\nasync function obtainShared(ctx: Context): Promise<SharedState> {\n const root = ctx.root as unknown as RootLike\n for (;;) {\n const existing = root.get(AUXILIARY_MODEL_SERVICE, false) as SharedState | undefined\n if (existing) {\n if (!existing.closed) return existing\n // closing always settles; wait for it, then re-lookup.\n await existing.closing\n continue\n }\n return createSharedState(ctx)\n }\n}\n\n/**\n * Retain the shared auxiliary-model store for the calling plugin.\n *\n * Resolves once storage is open and the read/write surfaces are live, with a\n * release function; register it as `ctx.effect(() => release)` so the store\n * unloads with the plugin. The first participant opens the shared owner\n * fiber; `await release()` drains pending writes and fully tears the owner\n * down when the last participant leaves. Requires `storageDomain`,\n * `webServer` and `connection` to exist on the host.\n *\n * Concurrent retainers share one owner; a retain arriving during teardown\n * waits for the closing owner and then reinstalls — it never inherits a\n * half-torn-down state.\n */\nexport async function retainAuxiliaryModel(ctx: Context): Promise<() => Promise<void>> {\n for (;;) {\n const state = await obtainShared(ctx)\n // One await, one answer: a failed or superseded init rejects the retainer\n // once. The caller's plugin lifecycle (inject refresh) drives any retry —\n // no same-state spin here.\n await state.ready\n if (state.closed) continue\n state.users += 1\n let released = false\n return async () => {\n if (released) return\n released = true\n state.users -= 1\n if (state.users <= 0) await state.teardown()\n else await state.tail.catch(() => {})\n }\n }\n}\n\n/**\n * Re-exported here so consumers reading the shared default use the same\n * subpath as the store lifecycle: '@klarkxy/dsh-plugin-kit/auxiliary-model'.\n */\nexport { getAuxiliaryModel } from './contracts.ts'\n","/**\n * Auxiliary request-context packing for feature model calls.\n *\n * A feature may prepend stable material (session facts, its own durable\n * records) to the live request so provider-side caching reuses one prefix.\n * Three invariants keep this honest and testable:\n *\n * - Material is rebuilt by the caller from current facts on every call;\n * nothing here stores, accumulates or replays model outputs.\n * - Order is caller-owned: stable material first, live request last.\n * - A context that exceeds its byte budget fails loudly instead of\n * silently dropping evidence.\n *\n * Pure and browser-safe: no host imports.\n */\n\n/** Thrown when packed context exceeds the caller's byte budget. */\nexport class AuxiliaryContextTooLargeError extends Error {\n readonly bytes: number\n readonly maxBytes: number\n constructor(bytes: number, maxBytes: number) {\n super(`Auxiliary context is ${bytes} bytes, over the ${maxBytes}-byte budget.`)\n this.name = 'AuxiliaryContextTooLargeError'\n this.bytes = bytes\n this.maxBytes = maxBytes\n }\n}\n\nconst utf8 = new TextEncoder()\n\nfunction byteLength(text: string): number {\n return utf8.encode(text).byteLength\n}\n\nfunction normalizeSegments(context: string | readonly string[] | undefined): readonly string[] {\n if (context === undefined) return []\n const list: readonly string[] = typeof context === 'string' ? [context] : context\n return list.filter(segment => typeof segment === 'string' && segment.length > 0)\n}\n\n/**\n * Join stable material segments for one request. The packed text must fit\n * `maxBytes` or the call throws — the caller decides what to drop, so\n * evidence is never silently truncated. Empty input packs to ''.\n */\nexport function packAuxiliaryContext(segments: readonly string[], maxBytes: number): string {\n if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) throw new Error('Invalid auxiliary context budget')\n const text = normalizeSegments(segments).join('\\n')\n if (byteLength(text) > maxBytes) throw new AuxiliaryContextTooLargeError(byteLength(text), maxBytes)\n return text\n}\n\n/** Only word characters, dots, colons and dashes are kept inside the feature attribute. */\nfunction featureAttribute(feature: string): string {\n return feature.replaceAll(/[^\\w.:-]/g, '_')\n}\n\n/**\n * Assemble the single user message for an auxiliary model call: stable\n * material in one labelled block first, the live request last. With no\n * context the result is byte-identical to `text`, so callers without\n * material keep exactly the previous wire shape.\n */\nexport function buildAuxiliaryUserText(request: {\n feature?: string\n context?: string | readonly string[]\n text: string\n}): string {\n const context = normalizeSegments(request.context)\n if (!context.length) return request.text\n const attribute = request.feature ? ` feature=\"${featureAttribute(request.feature)}\"` : ''\n return `<auxiliary-context${attribute}>\\n${context.join('\\n')}\\n</auxiliary-context>\\n<request>\\n${request.text}\\n</request>`\n}\n","import {\n BlockAssembler, ReasoningEffortId, createUserMessage,\n type GenerateOptions, type LlmRuntime, type StreamChunk,\n} from '@deepseek-ai/dsh-llm'\nimport { getAuxiliaryModel, producerMessageSource, type ModelRoute } from './contracts.ts'\nimport { buildAuxiliaryUserText } from './auxiliary-context.ts'\n\n/** A feature's own saved model. Empty means the host default chat model. */\nexport interface FeatureModelRoute {\n readonly provider: string\n readonly model: string\n readonly reasoningEffort?: string\n}\n\nexport type LlmTextCaller = Pick<LlmRuntime, 'prepareCall' | 'resolveCallConfig'>\n\nexport interface LlmTextRequest {\n plugin: string\n /** Optional feature id, stamped on the context envelope for attribution. */\n feature?: string\n /**\n * Stable material rebuilt from current facts (session events, durable\n * records). Packed before the live text so provider-side caching reuses\n * the prefix; never model outputs or approval history. Strings or\n * pre-ordered segments.\n */\n context?: string | readonly string[]\n route: FeatureModelRoute\n system: string\n text: string\n /** Omit to use the selected model's normal output settings. */\n maxTokens?: number\n signal: AbortSignal\n /** The real session id for host attribution; never a feature-scoped alias. */\n sessionId?: string\n /** Auxiliary-call marker adapters may special-case (e.g. disable thinking for titles). */\n purpose?: GenerateOptions['purpose']\n /** Pure control selection using the exact model captured for this call. */\n configure?: Parameters<LlmRuntime['prepareCall']>[2]\n /** Rechecked before the call returns text. A false result discards the output. */\n isCurrent?: () => boolean\n}\n\nexport interface LlmTextResult {\n text: string\n provider: string\n model: string\n inputTokens?: number\n outputTokens?: number\n totalTokens?: number\n cacheReadTokens?: number\n cacheWriteTokens?: number\n reasoningTokens?: number\n}\n\ntype SessionModelsHost = {\n agents?: { get(sessionId: string): { session?: { requestHeader?: () => { config?: ModelRoute; adapterDefaults?: { reasoningEffort?: unknown } } | undefined } } | undefined }\n sessionProjections?: { stateOf(session: unknown, key: string): { pending?: ModelRoute | null } | undefined }\n agentDefaultModel?: { currentSelection(): ModelRoute | undefined }\n}\n\nfunction routeOf(value: { provider?: unknown; model?: unknown; reasoningEffort?: unknown } | undefined): FeatureModelRoute | undefined {\n if (typeof value?.provider !== 'string' || !value.provider.trim()) return undefined\n if (typeof value.model !== 'string' || !value.model.trim()) return undefined\n const effort = typeof value.reasoningEffort === 'string' ? value.reasoningEffort.trim() : ''\n return effort\n ? { provider: value.provider.trim(), model: value.model.trim(), reasoningEffort: effort }\n : { provider: value.provider.trim(), model: value.model.trim() }\n}\n\n/**\n * Plugin selection first; then the shared auxiliary default (when any\n * participant retains it); otherwise the live session model, then the host\n * default. Cordis callers must declare agents, sessionProjections and\n * agentDefaultModel in their inject list so the fallback reads use the\n * caller's live services.\n */\nexport function resolveFeatureModel(host: unknown, saved: FeatureModelRoute | undefined, sessionId?: string): FeatureModelRoute | undefined {\n const explicit = routeOf(saved)\n if (explicit) return explicit\n const auxiliary = getAuxiliaryModel(host)\n if (auxiliary) return auxiliary\n const face = host as SessionModelsHost | undefined\n if (sessionId && face?.agents && face.sessionProjections) {\n const session = face.agents.get(sessionId)?.session\n if (session) {\n try {\n const pending = face.sessionProjections.stateOf(session, 'modelSelection')?.pending\n const selected = routeOf(pending ?? undefined)\n if (selected) return selected\n } catch { /* fall through to the recorded route */ }\n const header = session.requestHeader?.()\n const recorded = header?.config\n if (recorded) {\n const selected = header?.adapterDefaults?.reasoningEffort === true\n ? { provider: recorded.provider, model: recorded.model }\n : recorded\n const route = routeOf(selected)\n if (route) return route\n }\n }\n }\n return routeOf(face?.agentDefaultModel?.currentSelection())\n}\n\nfunction joinText(assembler: BlockAssembler): string {\n return assembler.blocks()\n .filter((block): block is { type: 'text'; text: string } => block.type === 'text')\n .map(block => block.text)\n .join('')\n}\n\nasync function readStream(stream: AsyncIterable<StreamChunk>, signal: AbortSignal, live: () => boolean): Promise<BlockAssembler> {\n const assembler = new BlockAssembler()\n const iterator = stream[Symbol.asyncIterator]()\n try {\n while (live()) {\n if (signal.aborted) break\n const item = await iterator.next()\n if (item.done) break\n assembler.push(item.value)\n }\n } finally {\n // Settlement includes producer cleanup; never leave a detached return()\n // running after the caller has released its lifecycle ownership.\n await iterator.return?.()\n }\n return assembler\n}\n\n/** One native model call. No retry, timeout policy, or provider queue. */\nexport async function callLlmText(llm: LlmTextCaller, request: LlmTextRequest): Promise<LlmTextResult> {\n request.signal.throwIfAborted()\n const live = () => request.isCurrent?.() !== false && !request.signal.aborted\n if (!live()) throw Object.assign(new Error('调用已取消。'), { name: 'AbortError' })\n const effort = request.route.reasoningEffort?.trim()\n const prepared = await llm.prepareCall({\n provider: request.route.provider,\n model: request.route.model,\n ...(effort ? { reasoningEffort: ReasoningEffortId(effort) } : {}),\n ...(request.maxTokens !== undefined ? { maxTokens: request.maxTokens } : {}),\n }, request.signal, request.configure)\n if (!live()) throw Object.assign(new Error('调用已取消。'), { name: 'AbortError' })\n const maxTokens = request.maxTokens === undefined\n ? prepared.config.maxTokens\n : Math.min(request.maxTokens, prepared.config.maxTokens ?? request.maxTokens)\n const options: GenerateOptions = {\n provider: prepared.config.provider,\n model: prepared.config.model,\n ...(prepared.config.reasoningEffort ? { reasoningEffort: prepared.config.reasoningEffort } : {}),\n ...(maxTokens !== undefined ? { maxTokens } : {}),\n ...(prepared.config.temperature !== undefined ? { temperature: prepared.config.temperature } : {}),\n ...(prepared.config.stop ? { stop: [...prepared.config.stop] } : {}),\n system: request.system,\n messages: [createUserMessage({\n source: producerMessageSource(request.plugin),\n content: [{ type: 'text', text: buildAuxiliaryUserText(request) }],\n })],\n signal: request.signal,\n ...(request.purpose ? { purpose: request.purpose } : {}),\n ...(request.sessionId ? { sessionId: request.sessionId as GenerateOptions['sessionId'] } : {}),\n }\n const assembler = await readStream(prepared.stream(options), request.signal, live)\n if (request.signal.aborted || assembler.finish.kind === 'aborted') {\n throw Object.assign(new Error('调用已取消。'), { name: 'AbortError' })\n }\n if (!live()) throw Object.assign(new Error('调用已取消。'), { name: 'AbortError' })\n if (assembler.finish.kind === 'error') {\n const code = assembler.finish.failure.code\n throw Object.assign(new Error(assembler.finish.failure.message || '模型调用失败。'), { code })\n }\n if (assembler.blocks().some(block => block.type === 'tool-call') || assembler.finish.kind === 'tool-calls') {\n throw new Error('这次调用不使用工具。')\n }\n if (assembler.finish.kind !== 'stop') throw new Error('模型调用未完成。')\n // Every usable host usage field passes through; absent fields stay absent\n // (the caller's accounting must not see invented zeros).\n const usage = assembler.usage\n return {\n text: joinText(assembler),\n provider: prepared.config.provider,\n model: prepared.config.model,\n ...(usage ? {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n ...(usage.totalTokens !== undefined ? { totalTokens: usage.totalTokens } : {}),\n ...(usage.cacheReadTokens !== undefined ? { cacheReadTokens: usage.cacheReadTokens } : {}),\n ...(usage.cacheWriteTokens !== undefined ? { cacheWriteTokens: usage.cacheWriteTokens } : {}),\n ...(usage.reasoningTokens !== undefined ? { reasoningTokens: usage.reasoningTokens } : {}),\n } : {}),\n }\n}\n","import type { TitleMessage } from './contracts.ts'\n\nexport const FRAME_PREFIX =\n 'Choose the current task from these recent human messages, ordered oldest to newest:\\n'\n\nexport function frameMessages(messages: readonly TitleMessage[]): string {\n return `${FRAME_PREFIX}${JSON.stringify(messages)}`\n}\n\nexport function utf8Bytes(value: string): number {\n return Buffer.byteLength(value, 'utf8')\n}\n\nfunction middleSlice(codePoints: readonly string[], kept: number): string {\n if (kept >= codePoints.length) return codePoints.join('')\n if (kept <= 0) return ''\n if (kept === 1) return '…'\n\n const contentPoints = kept - 1\n const headCount = Math.ceil(contentPoints / 2)\n const tailCount = Math.floor(contentPoints / 2)\n return `${codePoints.slice(0, headCount).join('')}…${\n tailCount === 0 ? '' : codePoints.slice(-tailCount).join('')\n }`\n}\n\nexport function fitSingleMessage(message: TitleMessage, maxInputBytes: number): TitleMessage {\n const empty = { ...message, text: '' }\n if (utf8Bytes(frameMessages([empty])) > maxInputBytes) {\n throw new Error('dsh-current-title: maxInputBytes is too small for the input envelope')\n }\n if (utf8Bytes(frameMessages([message])) <= maxInputBytes) return message\n\n const points = Array.from(message.text)\n let low = 0\n let high = points.length\n let best = ''\n\n while (low <= high) {\n const kept = Math.floor((low + high) / 2)\n const text = middleSlice(points, kept)\n if (utf8Bytes(frameMessages([{ ...message, text }])) <= maxInputBytes) {\n best = text\n low = kept + 1\n } else {\n high = kept - 1\n }\n }\n\n return { ...message, text: best }\n}\n\nexport function selectRecentMessages(\n messages: readonly TitleMessage[],\n maxRecentMessages: number,\n maxInputBytes: number,\n): TitleMessage[] {\n if (messages.length === 0) return []\n\n const selected = messages.slice(-maxRecentMessages).map(message => ({ ...message }))\n while (selected.length > 1 && utf8Bytes(frameMessages(selected)) > maxInputBytes) {\n selected.shift()\n }\n\n if (utf8Bytes(frameMessages(selected)) > maxInputBytes) {\n selected[0] = fitSingleMessage(selected[0]!, maxInputBytes)\n }\n\n return selected\n}\n","export const TITLE_TYPE_KEYS = [\n 'feature',\n 'fix',\n 'optimize',\n 'refactor',\n 'test',\n 'docs',\n 'release',\n 'config',\n 'explore',\n 'discuss',\n] as const\n\nexport const TITLE_LOCALES = ['zh', 'en'] as const\nexport const TITLE_LOCALE_MODES = ['auto', ...TITLE_LOCALES] as const\n\nexport type TitleType = (typeof TITLE_TYPE_KEYS)[number]\nexport type TitleLocale = (typeof TITLE_LOCALES)[number]\nexport type TitleLocaleMode = (typeof TITLE_LOCALE_MODES)[number]\n\nconst TITLE_TYPE_LABELS: Record<TitleLocale, Record<TitleType, string>> = {\n zh: {\n feature: '功能',\n fix: '修复',\n optimize: '优化',\n refactor: '重构',\n test: '测试',\n docs: '文档',\n release: '发布',\n config: '配置',\n explore: '探索',\n discuss: '讨论',\n },\n en: {\n feature: 'Feature',\n fix: 'Fix',\n optimize: 'Optimize',\n refactor: 'Refactor',\n test: 'Test',\n docs: 'Docs',\n release: 'Release',\n config: 'Config',\n explore: 'Explore',\n discuss: 'Discussion',\n },\n}\n\nexport interface ParsedTitle {\n type: TitleType\n summary: string\n}\n\nconst OSC_SEQUENCE = /(?:\\u001B\\]|\\u009D)(?:(?!\\u0007|\\u001B\\\\)[\\s\\S])*(?:\\u0007|\\u001B\\\\|$)/gu\nconst CSI_SEQUENCE = /(?:\\u001B\\[|\\u009B)[0-?]*[ -/]*[@-~]/gu\nconst ESC_SEQUENCE = /\\u001B[@-_]/gu\nconst CONTROL_CHARACTER = /[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u009F]/gu\nconst DIRECTIONAL_CONTROL = /[\\u200B\\u200E\\u200F\\u202A-\\u202E\\u2060-\\u2064\\u2066-\\u206F\\uFEFF]/gu\n\nfunction cleanTitleText(input: string): string {\n return input\n .replace(OSC_SEQUENCE, '')\n .replace(CSI_SEQUENCE, '')\n .replace(ESC_SEQUENCE, '')\n .replace(CONTROL_CHARACTER, '')\n .replace(DIRECTIONAL_CONTROL, '')\n .replace(/\\s+/gu, ' ')\n .trim()\n}\n\nexport function truncateTitleUtf8(input: string, maxBytes: number): string {\n if (!Number.isInteger(maxBytes) || maxBytes <= 0) throw new Error('maxBytes must be a positive integer')\n if (Buffer.byteLength(input, 'utf8') <= maxBytes) return input\n let used = 0\n let output = ''\n for (const character of input) {\n const bytes = Buffer.byteLength(character, 'utf8')\n if (used + bytes > maxBytes) break\n output += character\n used += bytes\n }\n return output\n}\n\n/** Same sanitizing rules as DSH 0.1.7-rc.2 `normalizeSessionTitle`. */\nexport function normalizeSessionTitle(input: string, maxBytes: number): string {\n return truncateTitleUtf8(cleanTitleText(input), maxBytes).trimEnd()\n}\n\nfunction isTitleType(value: string): value is TitleType {\n return (TITLE_TYPE_KEYS as readonly string[]).includes(value)\n}\n\nexport function resolveTitleLocale(\n mode: TitleLocaleMode,\n messages: readonly string[],\n preference?: string,\n): TitleLocale {\n if (mode !== 'auto') return mode\n\n const preferred = preference?.trim().toLowerCase().split('-')[0]\n if (preferred === 'zh' || preferred === 'en') return preferred\n\n const text = messages.join('\\n')\n if (/[\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]/u.test(text)) return 'en'\n return /\\p{Script=Han}/u.test(text) ? 'zh' : 'en'\n}\n\nfunction removeTitleSyntax(value: string): string {\n return value.replace(/[|`*_~#\\[\\]\"“”]/gu, ' ')\n}\n\nfunction truncateSummary(value: string, targetWords: number, targetCjkCharacters: number): string {\n const containsCjk = /[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]/u.test(value)\n if (containsCjk) {\n return Array.from(value.replace(/\\s+/gu, '')).slice(0, targetCjkCharacters).join('')\n }\n return value.split(/\\s+/u).filter(Boolean).slice(0, targetWords).join(' ')\n}\n\nfunction unwrapModelText(raw: string): string {\n const trimmed = raw.trim()\n const fenced = /^```(?:json)?\\s*([\\s\\S]*?)\\s*```$/iu.exec(trimmed)\n return (fenced?.[1] ?? trimmed).trim()\n}\n\nfunction readJsonObject(raw: string): Record<string, unknown> | undefined {\n const text = unwrapModelText(raw)\n const start = text.indexOf('{')\n const end = text.lastIndexOf('}')\n if (start === -1 || end <= start) return undefined\n try {\n const value = JSON.parse(text.slice(start, end + 1))\n if (value && typeof value === 'object' && !Array.isArray(value)) return value as Record<string, unknown>\n } catch {\n return undefined\n }\n return undefined\n}\n\n/**\n * Accept the required JSON shape, including a code fence or a short preface.\n * Extra keys are ignored. A plain one-line title still becomes a title so a\n * chatty model does not leave the session on the built-in fallback.\n */\nexport function parseModelTitle(\n raw: string,\n targetWords: number,\n targetCjkCharacters: number,\n): ParsedTitle {\n const candidate = readJsonObject(raw)\n const typeValue = typeof candidate?.type === 'string' ? candidate.type.trim().toLowerCase() : ''\n const summaryValue = typeof candidate?.summary === 'string' ? candidate.summary : ''\n const type = isTitleType(typeValue) ? typeValue : 'discuss'\n const source = summaryValue || (candidate ? '' : unwrapModelText(raw).replace(/^[\"'`]+|[\"'`]+$/gu, ''))\n const normalized = normalizeSessionTitle(removeTitleSyntax(source), Number.MAX_SAFE_INTEGER)\n const summary = truncateSummary(normalized, targetWords, targetCjkCharacters)\n if (summary.length === 0) {\n throw new Error('dsh-current-title: title model returned an empty summary')\n }\n return { type, summary }\n}\n\nexport function localMonthDay(now: Date): string {\n const month = String(now.getMonth() + 1).padStart(2, '0')\n const day = String(now.getDate()).padStart(2, '0')\n return `${month}${day}`\n}\n\nexport function formatTitle(parsed: ParsedTitle, locale: TitleLocale, now = new Date()): string {\n return `${localMonthDay(now)} | ${TITLE_TYPE_LABELS[locale][parsed.type]} | ${parsed.summary}`\n}\n","import { normalizeSessionTitle } from './output.ts'\nimport type { TitleMessage } from './contracts.ts'\n\nexport interface SessionEventLike {\n readonly type: string\n readonly seq: number\n readonly time?: number\n readonly data?: {\n readonly source?: { readonly kind?: string; readonly plugin?: string; readonly provider?: string }\n readonly content?: ReadonlyArray<{ readonly type?: string; readonly text?: string }>\n readonly title?: string\n readonly messageSeqs?: readonly number[]\n }\n}\n\nexport interface SessionLike {\n readonly id: string\n readonly seq?: number\n snapshotEvents(): readonly SessionEventLike[]\n append?(type: string, data: unknown): unknown\n}\n\nfunction textFromContent(content: ReadonlyArray<{ readonly type?: string; readonly text?: string }> | undefined): string {\n if (!Array.isArray(content)) return ''\n return content\n .filter(block => block && block.type === 'text' && typeof block.text === 'string')\n .map(block => block.text as string)\n .join('\\n')\n}\n\n/** Eligible human prompts only. Plugin/tool/model user-role rows are excluded. */\nexport function collectHumanMessages(events: readonly SessionEventLike[], throughSeq?: number): TitleMessage[] {\n const messages: TitleMessage[] = []\n for (const event of events) {\n if (throughSeq !== undefined && event.seq > throughSeq) break\n if (event.type !== 'user/message') continue\n if (event.data?.source?.kind !== 'user') continue\n const text = textFromContent(event.data.content)\n if (normalizeSessionTitle(text, Number.MAX_SAFE_INTEGER).length === 0) continue\n messages.push({ seq: event.seq, text })\n }\n return messages\n}\n\nexport function sourceVersionOf(sessionId: string, messages: readonly TitleMessage[]): string {\n const last = messages.at(-1)\n return `${sessionId}:${last?.seq ?? -1}:${messages.length}`\n}\n","import { callLlmText, resolveFeatureModel, type LlmTextCaller } from '@klarkxy/dsh-plugin-kit'\nimport { buildAuxiliaryUserText } from '@klarkxy/dsh-plugin-kit/auxiliary-context'\nimport type { ModelRoute } from '@klarkxy/dsh-model-route'\nimport type { GenerateConfig, TitleMessage, TitleModelRoute } from './contracts.ts'\nimport { DEFAULT_TIMEOUT_MS, PLUGIN_NAME, TITLE_CALL_FEATURE } from './contracts.ts'\nimport { FRAME_PREFIX, frameMessages, selectRecentMessages, utf8Bytes } from './input.ts'\nimport { formatTitle, normalizeSessionTitle, parseModelTitle, resolveTitleLocale, type TitleLocaleMode } from './output.ts'\nimport { sourceVersionOf } from './messages.ts'\n\n// DSH 0.2.2 replaced free-form `purpose` strings with a declaration-merged map\n// (LlmRequestPurposeMap, empty by default). Declare the title purpose so the\n// typed call still forwards `purpose: 'session-title'` to the LLM runtime.\ndeclare module '@deepseek-ai/dsh-llm' {\n interface LlmRequestPurposeMap {\n 'session-title': true\n }\n}\n\n/**\n * Fixed bytes the auxiliary-context envelope adds around the selected\n * messages, so maxInputBytes keeps bounding the wire text. The stable block\n * carries the framing rule and the request block the JSON message list —\n * selectRecentMessages measures that same pair through frameMessages, so\n * only the constant envelope overhead is new.\n */\nconst ENVELOPE_OVERHEAD_BYTES = utf8Bytes(\n buildAuxiliaryUserText({ feature: TITLE_CALL_FEATURE, context: FRAME_PREFIX, text: '[]' }),\n) - utf8Bytes(frameMessages([]))\n\nexport interface GeneratedTitle {\n readonly title: string\n readonly messageSeqs: readonly number[]\n readonly model?: { readonly provider: string; readonly model: string }\n readonly sourceVersion: string\n}\n\nexport function systemPrompt(config: GenerateConfig, customPrompt = ''): string {\n const instruction = customPrompt.trim()\n return [\n instruction || 'Name the current task in an AI coding-assistant session.',\n 'Prioritize the newest human messages. Older messages are context only and must not keep a completed task in the title.',\n 'Allowed type values: feature, fix, optimize, refactor, test, docs, release, config, explore, discuss.',\n 'Return exactly one JSON object: {\"type\":\"<type>\",\"summary\":\"<summary>\"}.',\n 'Return no Markdown, code fence, explanation, date, or extra key.',\n 'Keep the summary in the language of the recent messages.',\n `Aim for at most ${config.targetWords} non-CJK words or ${config.targetCjkCharacters} CJK characters.`,\n ].join('\\n')\n}\n\n/**\n * Saved override passed to resolveFeatureModel. Unlike modelRouteOverride,\n * this does not trim or re-apply the 250/80 caps: stored rows are already\n * normalized, and a whitespace-only id must stay a miss (not a trimmed hit)\n * so the host-default fallback is unchanged.\n */\nexport function titleModelRoute(route: TitleModelRoute | undefined): ModelRoute | undefined {\n if (!route?.provider || !route.model) return undefined\n return route.reasoningEffort\n ? { provider: route.provider, model: route.model, reasoningEffort: route.reasoningEffort }\n : { provider: route.provider, model: route.model }\n}\n\nexport async function generateCurrentTitle(options: {\n llm: LlmTextCaller\n host: unknown\n config: GenerateConfig\n sessionId: string\n messages: readonly TitleMessage[]\n prompt?: string\n model?: TitleModelRoute\n localePreference?: string\n localeMode?: TitleLocaleMode\n signal: AbortSignal\n isCurrent: () => boolean\n now?: Date\n}): Promise<GeneratedTitle> {\n options.signal.throwIfAborted()\n if (!options.isCurrent()) {\n throw Object.assign(new Error('dsh-current-title: generation is no longer current'), { code: 'superseded' })\n }\n const selected = selectRecentMessages(\n options.messages,\n options.config.maxRecentMessages,\n options.config.maxInputBytes - ENVELOPE_OVERHEAD_BYTES,\n )\n if (selected.length === 0) throw new Error('dsh-current-title: at least one source message is required')\n const route = resolveFeatureModel(options.host, titleModelRoute(options.model), options.sessionId)\n if (!route) throw new Error('dsh-current-title: 请在设置页选择模型,或设置默认辅助模型 / 宿主默认对话模型。')\n // Like the bundled title provider, select the first (least) advertised\n // effort inside prepareCall, before adapter defaults are materialized.\n const callRoute = { provider: route.provider, model: route.model }\n\n // The wire text carries the stable framing line inside the labelled\n // auxiliary-context block (fixed rules first) and the message list —\n // already ordered oldest to newest — inside the request block. Neither\n // side embeds a generated date.\n const framedInput = JSON.stringify(selected)\n const locale = resolveTitleLocale(\n options.localeMode ?? options.config.locale,\n selected.map(message => message.text),\n options.localePreference,\n )\n const sourceVersion = sourceVersionOf(options.sessionId, selected)\n const deadline = new AbortController()\n const timeoutMs = Number.isFinite(options.config.timeoutMs) && options.config.timeoutMs > 0\n ? options.config.timeoutMs : DEFAULT_TIMEOUT_MS\n const timer = setTimeout(() => deadline.abort(new DOMException('Title generation timed out.', 'TimeoutError')), timeoutMs)\n const signal = AbortSignal.any([options.signal, deadline.signal])\n let result\n try {\n result = await callLlmText(options.llm, {\n plugin: PLUGIN_NAME,\n route: callRoute,\n system: systemPrompt(options.config, options.prompt),\n feature: TITLE_CALL_FEATURE,\n context: FRAME_PREFIX,\n text: framedInput,\n maxTokens: options.config.maxOutputTokens,\n purpose: 'session-title',\n configure: (controls, model) => {\n const effort = model.reasoning?.efforts[0]?.id\n return { ...controls, ...(effort === undefined ? {} : { reasoningEffort: effort }) }\n },\n signal,\n sessionId: options.sessionId,\n isCurrent: options.isCurrent,\n })\n signal.throwIfAborted()\n } catch (error) {\n // The shared caller translates stream cancellation to AbortError. Retain\n // the originating deadline or lifecycle reason at this feature boundary.\n signal.throwIfAborted()\n throw error\n } finally {\n clearTimeout(timer)\n }\n options.signal.throwIfAborted()\n if (!options.isCurrent()) {\n throw Object.assign(new Error('dsh-current-title: generation is no longer current'), { code: 'superseded' })\n }\n const parsed = parseModelTitle(result.text, options.config.targetWords, options.config.targetCjkCharacters)\n const title = normalizeSessionTitle(formatTitle(parsed, locale, options.now ?? new Date()), options.config.maxTitleBytes)\n if (!title) throw new Error('dsh-current-title: title model returned an empty summary')\n return {\n title,\n messageSeqs: selected.map(message => message.seq),\n model: { provider: result.provider, model: result.model },\n sourceVersion,\n }\n}\n","export interface OwnershipClaim {\n readonly id: string\n readonly dispose: () => void | Promise<void>\n}\n\nexport interface TitleSlot {\n owner(): string | undefined\n occupy(id: string): Promise<() => void | Promise<void>>\n}\n\n/** Exclusive title-provider ownership. Enable claims the slot; disable releases only while this id still holds it. */\nexport async function claimTitleSlot(slot: TitleSlot, id: string): Promise<OwnershipClaim> {\n const dispose = await slot.occupy(id)\n return { id, dispose }\n}\n\nexport async function releaseTitleSlot(\n slot: TitleSlot,\n claim: OwnershipClaim | undefined,\n): Promise<'released' | 'left-other-owner' | 'idle'> {\n if (!claim) return 'idle'\n if (slot.owner() !== claim.id) return 'left-other-owner'\n await claim.dispose()\n if (slot.owner() && slot.owner() !== claim.id) return 'left-other-owner'\n return 'released'\n}\n\nexport function occupiedProviderId(error: unknown): string | undefined {\n const message = error instanceof Error ? error.message : String(error)\n return /session-title provider \"([^\"]+)\" is already registered/.exec(message)?.[1]\n}\n","import { PROVIDER_ID } from './contracts.ts'\nimport { occupiedProviderId, type TitleSlot } from './ownership.ts'\n\nexport interface SessionTitleProvider {\n readonly id: string\n readonly automatic: 'first-prompt' | 'all-prompts'\n generate(request: {\n session: { id: string; snapshotEvents(): readonly unknown[] }\n messages: ReadonlyArray<{ seq: number; text: string }>\n route?: { provider: string; model: string }\n signal: AbortSignal\n }): Promise<{ title: string; messageSeqs: readonly number[]; model?: { provider: string; model: string } }>\n}\n\nexport interface SessionTitleServiceLike {\n register(provider: SessionTitleProvider): () => void | Promise<void>\n get(session: unknown): { title: string; source?: { kind?: string; provider?: string }; eventSeq?: number; updatedAt?: number; messageSeqs?: readonly number[] } | undefined\n refresh(session: unknown, signal?: AbortSignal): Promise<unknown>\n}\n\nexport interface LoaderEntryOptions {\n id?: string\n name?: string\n disabled?: boolean | null\n config?: unknown\n inject?: unknown\n group?: boolean | null\n}\n\nexport interface LoaderEntry {\n id: string\n options?: LoaderEntryOptions\n}\n\nexport interface LoaderFace {\n entries(): Iterable<LoaderEntry>\n update(id: string, options: { disabled?: boolean | null }): Promise<unknown> | unknown\n}\n\nexport interface Displacement {\n readonly id: string\n readonly name: string\n readonly identity: string\n}\n\nfunction catalogLookupId(entryId: string): string {\n const colon = entryId.indexOf(':')\n return colon === -1 ? entryId : entryId.slice(colon + 1)\n}\n\nfunction entryName(entry: LoaderEntry): string {\n return String(entry.options?.name ?? '')\n}\n\nexport function entryDisabled(entry: LoaderEntry): boolean {\n return entry.options?.disabled === true\n}\n\nexport function displacementIdentity(entry: LoaderEntry): string {\n const options = entry.options ?? {}\n const { disabled: _disabled, ...rest } = options\n return JSON.stringify({ id: entry.id, name: entryName(entry), rest })\n}\n\nexport function captureDisplacement(entry: LoaderEntry): Displacement {\n return { id: entry.id, name: entryName(entry), identity: displacementIdentity(entry) }\n}\n\nexport function displacementUnchanged(snapshot: Displacement, entry: LoaderEntry): boolean {\n return entry.id === snapshot.id\n && entryName(entry) === snapshot.name\n && displacementIdentity(entry) === snapshot.identity\n}\n\nexport function findEntryById(loader: LoaderFace, id: string): LoaderEntry | undefined {\n for (const entry of loader.entries()) {\n if (entry.id === id) return entry\n }\n return undefined\n}\n\nexport function findLoaderEntry(loader: LoaderFace, providerId: string): LoaderEntry | undefined {\n for (const entry of loader.entries()) {\n const name = entryName(entry)\n const ids = [entry.id, entry.options?.id, name, catalogLookupId(entry.id)]\n if (ids.some(value => value === providerId)) return entry\n if (name.endsWith(`/${providerId}`) || name.endsWith(providerId)) return entry\n if (providerId === 'session-title-first-prompt-llm' && catalogLookupId(entry.id) === 'session-title-llm') return entry\n }\n return undefined\n}\n\nexport async function restoreOwnDisplacement(loader: LoaderFace | undefined, snapshot: Displacement | undefined): Promise<'restored' | 'skipped'> {\n if (!loader || !snapshot) return 'skipped'\n const current = findEntryById(loader, snapshot.id)\n if (!current || !entryDisabled(current) || !displacementUnchanged(snapshot, current)) return 'skipped'\n await loader.update(snapshot.id, { disabled: false })\n return 'restored'\n}\n\nexport function createNativeTitleSlot(options: {\n sessionTitle: SessionTitleServiceLike\n loader: LoaderFace\n /** Read at each occupy so a settings change can re-register with a new cadence. */\n automatic: () => SessionTitleProvider['automatic']\n generate: SessionTitleProvider['generate']\n}): TitleSlot & { displacement?: Displacement } {\n let owner: string | undefined\n const slot: TitleSlot & { displacement?: Displacement } = {\n owner: () => owner,\n async occupy(id: string) {\n const provider: SessionTitleProvider = {\n id: PROVIDER_ID,\n automatic: options.automatic(),\n generate: options.generate,\n }\n try {\n const dispose = options.sessionTitle.register(provider)\n owner = id\n return async () => {\n await dispose()\n if (owner === id) owner = undefined\n }\n } catch (error) {\n const occupied = occupiedProviderId(error)\n if (!occupied) throw error\n const entry = findLoaderEntry(options.loader, occupied)\n if (!entry || entryDisabled(entry)) throw error\n const snapshot = captureDisplacement(entry)\n await options.loader.update(entry.id, { disabled: true })\n const afterDisable = findEntryById(options.loader, entry.id)\n if (!afterDisable || !displacementUnchanged(snapshot, afterDisable)) throw error\n try {\n const dispose = options.sessionTitle.register(provider)\n slot.displacement = snapshot\n owner = id\n return async () => {\n await dispose()\n if (owner === id) owner = undefined\n }\n } catch (second) {\n if (findEntryById(options.loader, snapshot.id) && displacementUnchanged(snapshot, findEntryById(options.loader, snapshot.id)!)) {\n await options.loader.update(snapshot.id, { disabled: false })\n }\n throw second\n }\n }\n },\n }\n return slot\n}\n","import { defineDomain, domainTable } from '@deepseek-ai/dsh-storage-domain'\nimport { z } from 'zod'\nimport {\n SETTINGS_KEY, defaultModelRoute, isTitleLocaleMode, normalizeCadence, normalizeModelRoute, normalizePrompt,\n type TitleSettings,\n} from './contracts.ts'\n\nexport { SETTINGS_KEY }\n\nconst localeSchema = z.enum(['auto', 'zh', 'en'])\n\n/** Version 1 stored only the locale. Prompt and model are filled as defaults. */\nconst legacySettingsSchema = z.object({\n revision: z.number().int().nonnegative(),\n locale: localeSchema,\n}).strict()\n\nconst modelRouteSchema = z.object({\n provider: z.string(),\n model: z.string(),\n reasoningEffort: z.string().optional(),\n}).strict()\n\nexport const titleSettingsSchema = z.object({\n revision: z.number().int().nonnegative(),\n locale: localeSchema,\n prompt: z.string(),\n model: modelRouteSchema,\n /** Defaulted so rows stored before the cadence switch existed still parse. */\n cadence: z.enum(['all-prompts', 'first-prompt']).default('all-prompts'),\n}).strict()\n\nexport const titleDomain = defineDomain({\n name: 'dsh_editor_current_title',\n version: 2,\n tables: {\n settings: domainTable<string, TitleSettings>(titleSettingsSchema),\n },\n})\n\nexport function parseTitleSettings(value: unknown): TitleSettings | undefined {\n const current = titleSettingsSchema.safeParse(value)\n if (current.success) {\n return {\n revision: current.data.revision,\n locale: isTitleLocaleMode(current.data.locale) ? current.data.locale : 'auto',\n prompt: normalizePrompt(current.data.prompt),\n model: normalizeModelRoute(current.data.model),\n cadence: normalizeCadence(current.data.cadence),\n }\n }\n const legacy = legacySettingsSchema.safeParse(value)\n if (!legacy.success || !isTitleLocaleMode(legacy.data.locale)) return undefined\n return {\n revision: legacy.data.revision,\n locale: legacy.data.locale,\n prompt: '',\n model: defaultModelRoute(),\n cadence: 'all-prompts',\n }\n}\n\nexport function storedSettings(value: unknown, _fallbackLocale: TitleSettings['locale'] = 'auto'): TitleSettings {\n const parsed = parseTitleSettings(value)\n return {\n revision: parsed?.revision ?? 0,\n locale: 'auto',\n prompt: parsed?.prompt ?? '',\n model: parsed?.model ?? defaultModelRoute(),\n cadence: parsed?.cadence ?? 'all-prompts',\n }\n}\n\nexport function settingsPatch(current: TitleSettings, patch: {\n prompt?: unknown\n model?: unknown\n cadence?: unknown\n}): Pick<TitleSettings, 'prompt' | 'model' | 'cadence'> & { locale: 'auto' } {\n return {\n locale: 'auto',\n prompt: patch.prompt === undefined ? current.prompt : normalizePrompt(patch.prompt),\n model: patch.model === undefined ? current.model : normalizeModelRoute(patch.model),\n cadence: patch.cadence === undefined ? current.cadence : normalizeCadence(patch.cadence),\n }\n}\n","import type { RpcResult } from '@klarkxy/dsh-plugin-kit/contracts'\nimport { isSubagentSession } from '@klarkxy/dsh-plugin-kit/contracts'\nimport type { LlmTextCaller } from '@klarkxy/dsh-plugin-kit'\nimport type { GenerateConfig, TitleSettings, TitleSnapshot, TitleStatus, TitleSupport } from './contracts.ts'\nimport { PROVIDER_ID, defaultGenerateConfig } from './contracts.ts'\nimport { generateCurrentTitle } from './generate.ts'\nimport { collectHumanMessages, type SessionLike } from './messages.ts'\nimport {\n createNativeTitleSlot, restoreOwnDisplacement, type LoaderFace, type SessionTitleServiceLike,\n} from './native-slot.ts'\nimport { claimTitleSlot, releaseTitleSlot, type OwnershipClaim } from './ownership.ts'\nimport { settingsPatch, storedSettings } from './storage.ts'\nimport type { TitleLocaleMode } from './output.ts'\n\nexport interface TitleSettingsStore {\n load(): TitleSettings | undefined\n save(settings: TitleSettings): Promise<void>\n}\n\nexport interface CurrentTitleHost {\n get(name: string): unknown\n}\n\nexport class CurrentTitleService {\n private settings: TitleSettings\n private config: GenerateConfig\n private claim?: OwnershipClaim\n private nativeSlot?: ReturnType<typeof createNativeTitleSlot>\n private generation = 0\n private settingsPending: Promise<void> = Promise.resolve()\n private disposed = false\n private readonly inFlight = new Map<string, AbortController>()\n private readonly generations = new Set<Promise<unknown>>()\n readonly support: TitleSupport\n\n constructor(private readonly options: {\n plugin: string\n llm?: LlmTextCaller\n host?: unknown\n sessionTitle?: SessionTitleServiceLike\n loader?: LoaderFace\n sessions?: { get(id: string): SessionLike | undefined }\n store?: TitleSettingsStore\n localePreference?: () => string | undefined\n initialLocale?: TitleLocaleMode\n now?: () => Date\n onSettingsChanged?: (revision: number) => void\n }) {\n const stored = storedSettings(options.store?.load(), options.initialLocale ?? 'auto')\n this.settings = stored\n this.config = defaultGenerateConfig(this.settings.locale)\n this.support = { nativeOwner: null, weOwn: false }\n }\n\n async start(): Promise<void> {\n const { llm, sessionTitle, loader, sessions } = this.options\n if (!llm || !sessionTitle?.register || !sessions || !loader) {\n this.support.weOwn = false\n this.support.limitation = 'required host services are missing'\n return\n }\n this.nativeSlot = createNativeTitleSlot({\n sessionTitle,\n loader,\n automatic: () => this.settings.cadence,\n generate: request => this.nativeGenerate(request),\n })\n try {\n this.claim = await claimTitleSlot(this.nativeSlot, PROVIDER_ID)\n this.support.weOwn = true\n this.support.nativeOwner = PROVIDER_ID\n delete this.support.limitation\n } catch (error) {\n this.support.weOwn = false\n this.support.nativeOwner = this.nativeSlot.owner() ?? null\n this.support.limitation = error instanceof Error ? error.message : 'native title provider slot is occupied'\n }\n }\n\n async dispose(): Promise<void> {\n this.disposed = true\n this.generation += 1\n for (const controller of this.inFlight.values()) controller.abort(new Error('current-title disabled'))\n this.inFlight.clear()\n await Promise.allSettled([...this.generations])\n await this.settingsPending\n const snapshot = this.nativeSlot?.displacement\n const outcome = await releaseTitleSlot(this.nativeSlot ?? { owner: () => undefined, occupy: async () => () => {} }, this.claim)\n if (outcome === 'released') await restoreOwnDisplacement(this.options.loader, snapshot)\n this.claim = undefined\n this.support.weOwn = false\n this.support.nativeOwner = this.nativeSlot?.owner() ?? null\n if (outcome === 'left-other-owner') {\n this.support.limitation = 'another title provider owns the slot; previous owner was not restored'\n }\n }\n\n status(sessionId?: string): TitleStatus {\n const session = sessionId && this.options.sessions ? this.options.sessions.get(sessionId) : undefined\n const snapshot = session ? this.read(session) : undefined\n return {\n settings: { ...this.settings, model: { ...this.settings.model } },\n support: { ...this.support, nativeOwner: this.nativeSlot?.owner() ?? this.support.nativeOwner },\n ...(sessionId ? {\n session: {\n sessionId,\n title: snapshot?.title,\n sourceKind: snapshot?.source.kind,\n generating: this.inFlight.has(sessionId),\n pinned: snapshot?.source.kind === 'user',\n },\n } : {}),\n }\n }\n\n async updateSettings(patch: {\n prompt?: unknown\n model?: unknown\n cadence?: unknown\n expectedRevision: number\n }): Promise<TitleSettings> {\n patch = structuredClone(patch)\n const result = this.settingsPending.then(async () => {\n if (this.disposed) throw Object.assign(new Error('current-title disabled'), { code: 'unavailable' })\n if (this.settings.revision !== patch.expectedRevision) {\n throw Object.assign(new Error('current-title settings changed'), { code: 'revision' })\n }\n const previous = this.settings\n const next: TitleSettings = {\n revision: this.settings.revision + 1,\n ...settingsPatch(this.settings, patch),\n }\n if (this.options.store) await this.options.store.save(next)\n this.settings = next\n // Observer failures cannot roll back a committed settings write.\n try { this.options.onSettingsChanged?.(next.revision) } catch {}\n this.config = { ...this.config, locale: 'auto' }\n if (!this.disposed && next.cadence !== previous.cadence) await this.reclaimWithCadence()\n return {\n revision: next.revision,\n locale: next.locale,\n prompt: next.prompt,\n model: { ...next.model },\n cadence: next.cadence,\n }\n })\n this.settingsPending = result.then(() => {}, () => {})\n return result\n }\n\n /** Re-register the provider so a cadence change takes effect without a restart. */\n private async reclaimWithCadence(): Promise<void> {\n if (!this.claim || !this.nativeSlot) return\n const stale = this.claim\n this.claim = undefined\n await stale.dispose()\n try {\n this.claim = await claimTitleSlot(this.nativeSlot, PROVIDER_ID)\n this.support.weOwn = true\n this.support.nativeOwner = PROVIDER_ID\n delete this.support.limitation\n } catch (error) {\n this.support.weOwn = false\n this.support.nativeOwner = this.nativeSlot.owner() ?? null\n this.support.limitation = error instanceof Error ? error.message : 'native title provider slot is occupied'\n }\n }\n\n /** @deprecated Locale is always auto. Kept so older clients still save a revision. */\n async updateLocale(_locale: TitleLocaleMode, expectedRevision: number): Promise<TitleSettings> {\n return this.updateSettings({ expectedRevision })\n }\n\n async regenerate(sessionId: string, signal: AbortSignal): Promise<TitleSnapshot | undefined> {\n if (!this.support.weOwn) throw Object.assign(new Error('title provider is inactive'), { code: 'unavailable' })\n const session = this.options.sessions?.get(sessionId)\n if (!session) throw Object.assign(new Error('session not found'), { code: 'not-found' })\n await this.options.sessionTitle?.refresh(session, signal)\n return this.read(session)\n }\n\n read(session: SessionLike): TitleSnapshot | undefined {\n const snapshot = this.options.sessionTitle?.get(session)\n if (!snapshot?.title) return undefined\n const kind = snapshot.source?.kind\n return {\n title: snapshot.title,\n messageSeqs: snapshot.messageSeqs ? [...snapshot.messageSeqs] : [],\n source: {\n kind: kind === 'user' || kind === 'fallback' || kind === 'provider' ? kind : 'provider',\n ...(typeof snapshot.source?.provider === 'string' ? { provider: snapshot.source.provider } : {}),\n },\n eventSeq: Number(snapshot.eventSeq ?? 0),\n updatedAt: snapshot.updatedAt ?? 0,\n }\n }\n\n private nativeGenerate(request: Parameters<CurrentTitleService['runNativeGenerate']>[0]) {\n if (this.disposed) return Promise.reject(new Error('dsh-current-title: plugin disabled'))\n const pending = this.runNativeGenerate(request)\n this.generations.add(pending)\n void pending.then(() => this.generations.delete(pending), () => this.generations.delete(pending))\n return pending\n }\n\n private async runNativeGenerate(request: {\n session: { id: string; snapshotEvents(): readonly unknown[] }\n messages: ReadonlyArray<{ seq: number; text: string }>\n signal: AbortSignal\n }) {\n const llm = this.options.llm\n if (!llm) throw new Error('dsh-current-title: llm is not available')\n const generation = this.generation\n const controller = new AbortController()\n this.inFlight.get(request.session.id)?.abort(new Error('newer title generation superseded older work'))\n this.inFlight.set(request.session.id, controller)\n try {\n const combined = AbortSignal.any([request.signal, controller.signal])\n const session = this.options.sessions?.get(request.session.id)\n // The host writes a free deterministic fallback title before it consults a\n // provider, and this provider contract has no \"decline\" result. Declining is\n // therefore the only way to keep delegated child threads off the model: their\n // dispatch prompt arrives as the child's own user message, so `source.kind`\n // cannot exclude them. The host logs the rejection and keeps the fallback.\n if (isSubagentSession(session)) {\n throw Object.assign(new Error('dsh-current-title: delegated child thread keeps the host fallback title'), { code: 'subagent-session' })\n }\n const messages = collectHumanMessages(\n request.messages.map(message => ({\n type: 'user/message',\n seq: message.seq,\n data: { source: { kind: 'user' }, content: [{ type: 'text', text: message.text }] },\n })),\n )\n const generated = await generateCurrentTitle({\n llm,\n host: this.options.host ?? {},\n config: this.config,\n sessionId: request.session.id,\n messages: messages.length > 0 ? messages : [...request.messages],\n prompt: this.settings.prompt,\n model: this.settings.model,\n localePreference: this.options.localePreference?.(),\n signal: combined,\n isCurrent: () => this.generation === generation && this.support.weOwn\n && (!session || this.options.sessions?.get(request.session.id) === session),\n now: this.options.now?.(),\n })\n return { title: generated.title, messageSeqs: generated.messageSeqs, model: generated.model }\n } finally {\n if (this.inFlight.get(request.session.id) === controller) this.inFlight.delete(request.session.id)\n }\n }\n}\n\nexport function hostLocalePreference(host: CurrentTitleHost): string | undefined {\n try {\n const settings = host.get('settings') as { get?(namespace: string): unknown } | undefined\n const value = settings?.get?.('locale')\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return undefined\n const preference = (value as Record<string, unknown>).preference\n return typeof preference === 'string' ? preference : undefined\n } catch {\n return undefined\n }\n}\n\nexport async function handleRpc(service: CurrentTitleService, endpoint: string, payload: unknown, signal: AbortSignal): Promise<RpcResult> {\n signal.throwIfAborted()\n const body = payload && typeof payload === 'object' && !Array.isArray(payload) ? payload as Record<string, unknown> : {}\n if (endpoint === 'status') {\n return { ok: true, value: service.status(typeof body.sessionId === 'string' ? body.sessionId : undefined) }\n }\n if (endpoint === 'settings') {\n if (typeof body.expectedRevision !== 'number') {\n return { ok: false, error: { code: 'bad-request', message: '标题设置无效。' } }\n }\n try {\n return {\n ok: true,\n value: await service.updateSettings({\n ...(body.prompt !== undefined ? { prompt: body.prompt } : {}),\n ...(body.model !== undefined ? { model: body.model } : {}),\n ...(body.cadence !== undefined ? { cadence: body.cadence } : {}),\n expectedRevision: body.expectedRevision,\n }),\n }\n } catch (error) {\n const code = error instanceof Error && 'code' in error ? String((error as { code?: string }).code) : 'failed'\n if (code === 'revision') return { ok: false, error: { code, message: '设置已更新,请刷新后重试。' } }\n return { ok: false, error: { code: 'failed', message: '无法保存标题设置。' } }\n }\n }\n if (endpoint === 'regenerate') {\n if (typeof body.sessionId !== 'string' || !body.sessionId) {\n return { ok: false, error: { code: 'bad-request', message: '缺少会话。' } }\n }\n try {\n const snapshot = await service.regenerate(body.sessionId, signal)\n return { ok: true, value: snapshot ?? null }\n } catch (error) {\n const code = error instanceof Error && 'code' in error ? String((error as { code?: string }).code) : 'failed'\n if (code === 'not-found') return { ok: false, error: { code, message: '找不到该会话。' } }\n if (code === 'unavailable') return { ok: false, error: { code, message: '标题服务未就绪。' } }\n if (signal.aborted) return { ok: false, error: { code: 'cancelled', message: '已取消。' } }\n return { ok: false, error: { code: 'failed', message: '标题生成失败。' } }\n }\n }\n return { ok: false, error: { code: 'bad-request', message: '未知操作。' } }\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport type { LlmTextCaller } from '@klarkxy/dsh-plugin-kit'\nimport { retainAuxiliaryModel } from '@klarkxy/dsh-plugin-kit/auxiliary-model'\nimport { registerHostRpc, type HostRpcContext } from '@klarkxy/dsh-plugin-kit/host-rpc'\nimport { modelSettingsChangesIdentity } from '@klarkxy/dsh-plugin-kit/contracts'\nimport { createModelSettingsChanges } from '@klarkxy/dsh-plugin-kit/model-settings-changes'\nimport { registerModelSettings, notifyModelSettingsChanged, type ModelSettingsEvents } from '@klarkxy/dsh-plugin-kit/model-settings'\nimport { isTitleLocaleMode, PLUGIN_NAME, RPC_CHANNEL, SETTINGS_KEY, type TitleLocaleMode } from './contracts.ts'\nimport { CurrentTitleService, handleRpc, hostLocalePreference } from './service.ts'\nimport type { LoaderFace, SessionTitleServiceLike } from './native-slot.ts'\nimport type { SessionLike } from './messages.ts'\nimport { parseTitleSettings, titleDomain } from './storage.ts'\n\nexport const name = PLUGIN_NAME\nexport const inject = ['sessionTitle', 'llm', 'sessions', 'loader', 'storageDomain', 'connection', 'webServer', 'agents', 'sessionProjections', 'agentDefaultModel'] as const\nexport { CurrentTitleService }\nexport { selectRecentMessages, frameMessages } from './input.ts'\nexport { parseModelTitle, formatTitle, resolveTitleLocale } from './output.ts'\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context { currentTitle: CurrentTitleService }\n}\n\ntype DomainHandle = {\n table(name: 'settings'): {\n get(key: string): unknown\n put(key: string, value: unknown): Promise<void>\n }\n close(): Promise<void>\n}\n\ntype Host = Context & HostRpcContext & {\n sessionTitle: SessionTitleServiceLike\n llm: LlmTextCaller\n sessions: { get(id: string): SessionLike | undefined }\n loader: LoaderFace\n storageDomain: { open: (spec: typeof titleDomain) => Promise<DomainHandle> }\n}\n\nexport async function apply(ctx: Context, config: { locale?: TitleLocaleMode } = {}): Promise<void> {\n createModelSettingsChanges(ctx, modelSettingsChangesIdentity(PLUGIN_NAME), PLUGIN_NAME)\n // Keep the shared auxiliary default alive while this plugin is mounted: it\n // is the global default title generation follows when no title model is\n // set. A store that fails to open must fail this apply — silently falling\n // back to another tier would run generations on a model the user did not\n // choose.\n const release = await retainAuxiliaryModel(ctx)\n ctx.effect(() => release, 'current-title.auxiliary-model')\n const host = ctx as Host\n const domain = await host.storageDomain.open(titleDomain)\n const table = domain.table('settings')\n const locale = isTitleLocaleMode(config.locale) ? config.locale : 'auto'\n const service = new CurrentTitleService({\n plugin: PLUGIN_NAME,\n onSettingsChanged: revision => notifyModelSettingsChanged(ctx, PLUGIN_NAME, revision),\n llm: host.llm,\n host,\n sessionTitle: host.sessionTitle,\n loader: host.loader,\n sessions: host.sessions,\n store: {\n load: () => parseTitleSettings(table.get(SETTINGS_KEY)),\n save: settings => table.put(SETTINGS_KEY, settings),\n },\n initialLocale: locale,\n localePreference: () => hostLocalePreference(host),\n })\n await service.start()\n ctx.provide('currentTitle', service)\n ctx.effect(() => async () => { await service.dispose(); await domain.close() }, 'current-title.lifecycle')\n ctx.effect(() => registerHostRpc(host, RPC_CHANNEL, (endpoint, payload, signal) => handleRpc(service, endpoint, payload, signal)), 'current-title.rpc')\n ctx.effect(() => registerModelSettings(ctx as unknown as ModelSettingsEvents, {\n ns: PLUGIN_NAME, title: { zh: '自动标题', en: 'Auto Title' },\n read(signal) {\n signal.throwIfAborted()\n const settings = service.status().settings\n return { revision: settings.revision, fields: [{ path: ['model'], label: { zh: '标题模型', en: 'Title model' }, current: settings.model,\n followLabel: { zh: '默认辅助模型', en: 'Default auxiliary model' }, allowFollow: true }] }\n },\n async write(path, route, expectedRevision, signal) {\n if (path.length !== 1 || path[0] !== 'model') throw new Error('Unknown Current Title model setting')\n signal.throwIfAborted()\n return service.updateSettings({ model: route, expectedRevision })\n },\n }), 'current-title.model-settings')\n}\n"],"mappings":";;;;;;AAuBA,SAAgB,sBAAsB,QAAuC;CAC3E,OAAO;EAAE,MAAM,UAAU;EAAU;CAAO;AAC5C;;;;;;;;;;AAoHA,SAAgB,kBAAkB,SAA2B;CAC3D,MAAM,SAAU,SAAoD;CACpE,IAAI,CAAC,UAAU,OAAO,WAAW,UAAU,OAAO;CAClD,IAAI,OAAO,WAAW,cAAc,OAAO,OAAO,mBAAmB,CAAC,IAAI,GAAG,OAAO;CAKpF,MAAM,YAAY,OAAO,aAAa,SAChC,OAAO,oBAAoB,KAAA,KAAa,OAAO,oBAAoB,MACpE,OAAO,WAAW,KAAA,MACjB,OAAO,mBAAmB,KAAA,KAAa,OAAO,mBAAmB,cAAc,OAAO,mBAAmB;CAC/G,OAAO,QAAQ,OAAO,aAAa,KAAK,CAAC;AAC3C;;AAqBA,SAAgB,6BAA6B,aAAmD;CAC9F,MAAM,SAAS,mBAAmB,KAAK,WAAW;CAElD,MAAM,SADO,SAAS,GAAG,OAAO,GAAG,GAAG,OAAO,OAAO,YAAA,CACjC,MAAM,eAAe,CAAC,CAAC,OAAO,OAAO;CACxD,IAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,gDAAgD;CACnF,MAAM,UAAU,GAAG,MAAM,KAAI,SAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE;CAC5F,IAAI,CAAC,sBAAsB,KAAK,OAAO,GAAG,MAAM,IAAI,MAAM,mDAAmD,SAAS;CACtH,OAAO;EAAE,SAAS;EAAS,WAAW;CAAQ;AAChD;;AA6EA,MAAa,0BAA0B;;AAGvC,MAAa,0BAA0B;;AAGvC,MAAa,qBAAqB;;;;;AAMlC,MAAa,mCAAmC,6BAA6B,yBAAyB;AActG,SAAS,qBAAqB,MAAiD;CAC7E,MAAM,OAAQ,MAAyC;CACvD,IAAI;EACF,MAAM,SAAS,MAAM,MAAM,yBAAyB,KAAK;EACzD,OAAO,UAAU,OAAO,OAAO,aAAa,aAAa,SAAS,KAAA;CACpE,QAAQ;EAAE;CAAiB;AAC7B;;;;;;;AAQA,SAAgB,kBAAkB,MAAuC;CACvE,MAAM,SAAS,qBAAqB,IAAI;CACxC,IAAI,CAAC,QAAQ,OAAO,KAAA;CACpB,OAAO,mBAAmB,OAAO,SAAS,CAAC,CAAC,SAAS,KAAA,CAAS;AAChE;;;;ACxRA,SAAgB,yBACd,KACA,SACA,UACA,UAAmC,CAAC,GACxB;CACZ,MAAM,YAAY,QAAQ,gBAAgB;CAC1C,IAAI,CAAC,OAAO,cAAc,SAAS,KAAK,aAAa,GAAG,MAAM,IAAI,MAAM,wBAAwB;CAChG,MAAM,aAAa,QAAQ,gBAAgB,aAAqB,YAAY,KAAK,QAAQ;CACzF,OAAO,IAAI,UAAU,SAAS;EAAE,MAAM;EAAU,MAAM;EAAS,SAAS,OAAO,KAAK,QAAQ;GAC1F,MAAM,UAAU,QAAgB,OAAiB,aAAsB;IACrE,IAAI,IAAI,WAAW;IACnB,IAAI,WAAW,KAAK,IAAI,UAAU,QAAQ,EAAE,YAAY,QAAQ,CAAC;SAC5D,IAAI,UAAU,MAAM;IACzB,IAAI,IAAI,YAAY,QAAQ,YAAY,QAAQ,KAAK,MAAM,WAAW,MAAM,uBAAuB,GAAG;GACxG;GACA,IAAI;IAEF,IAAI,OAAO,IAAI,WAAW,qBAAqB,YAAY;KAAE,OAAO,GAAG;KAAG;IAAO;IACjF,MAAM,YAAY,IAAI,WAAW,iBAAiB,GAAG;IACrD,IAAI,cAAc,KAAA,GAAW;KAAE,OAAO,SAAS;KAAG;IAAO;IACzD,MAAM,WAAW,IAAI,IAAI,IAAI,OAAO,KAAK,qBAAqB,CAAC,CAAC;IAChE,MAAM,WAAW,SAAS,WAAW,GAAG,QAAQ,EAAE,IAAI,SAAS,MAAM,QAAQ,SAAS,CAAC,IAAI;IAC3F,IAAI,IAAI,WAAW,UAAU,CAAC,WAAW,QAAQ,GAAG;KAAE,OAAO,GAAG;KAAG;IAAO;IAC1E,MAAM,cAAc,OAAO,IAAI,QAAQ,mBAAmB,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK;IACrF,KAAK,QAAQ,6BAA6B,YAAY,YAAY,IAAI,iBAAiB,oBAAoB;KACzG,OAAO,GAAG;KAAG;IACf;IACA,MAAM,UAAU,QAAQ,aAAa,KAAK,QAAQ;IAClD,IAAI,SAAS;KAAE,OAAO,QAAQ,QAAQ,KAAA,GAAW,QAAQ,IAAI;KAAG;IAAO;IAEvE,MAAM,aAAa,IAAI,gBAAgB;IACvC,IAAI,GAAG,eAAe;KAAE,IAAI,CAAC,IAAI,eAAe,WAAW,MAAM;IAAE,CAAC;IACpE,MAAM,SAAmB,CAAC;IAC1B,IAAI,OAAO;IACX,WAAW,MAAM,SAAS,KAAK;KAC7B,MAAM,SAAS,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK;KACjE,QAAQ,OAAO;KACf,IAAI,OAAO,WAAW;MAAE,OAAO,GAAG;MAAG,IAAI,QAAQ;MAAG;KAAO;KAC3D,OAAO,KAAK,MAAM;IACpB;IACA,IAAI;IACJ,IAAI;KAAE,OAAO,KAAK,MAAM,OAAO,OAAO,MAAM,CAAC,CAAC,SAAS,MAAM,MAAM,QAAQ,kBAAkB,SAAS,GAAG;IAAE,QACrG;KAAE,OAAO,GAAG;KAAG;IAAO;IAC5B,MAAM,SAAS,UAAU,MAAM,WAAW,QAAQ,GAAG;GACvD,SAAS,OAAO;IACd,OAAO,KAAK,KAAK;GACnB;EACF;CAAE,CAAC;AACL;;AAGA,SAAgB,oBAAoB,UAA0B,OAAe,QAAiB,UAAU,MAAY;CAClH,IAAI,SAAS,WAAW;CACxB,SAAS,UAAU,KAAK;EAAE,gBAAgB;EAAoB,GAAI,UAAU,EAAE,iBAAiB,WAAW,IAAI,CAAC;CAAG,CAAC;CACnH,SAAS,IAAI,KAAK,UAAU;EAAE,MAAM;EAAmB;EAAO;CAAO,CAAC,CAAC;AACzE;;AAGA,SAAgB,gBACd,KACA,SACA,MACA,UAA0B,CAAC,GACf;CACZ,OAAO,yBAAyB,KAAK,SAAS,OAAO,UAAU,MAAM,QAAQ,QAAQ;EACnF,IAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GAAG;GAAE,IAAI,UAAU,GAAG;GAAG,IAAI,IAAI;GAAG;EAAO;EACtG,MAAM,UAAU;EAChB,IAAI,QAAQ,SAAS,oBAAoB,QAAQ,WAAW,YAAY,OAAO,QAAQ,UAAU,YAC3F,QAAQ,kBAAkB,CAAC,OAAO,OAAO,SAAS,SAAS,GAAI;GACnE,IAAI,UAAU,GAAG;GAAG,IAAI,IAAI;GAAG;EACjC;EACA,MAAM,MAAM,MAAM,KAAK,UAAU,QAAQ,SAAS,MAAM;EACxD,MAAM,SAAS,IAAI,KAAK,MAAM;GAAE,GAAG;GAAK,OAAO;IAAE,SAAS,CAAC;IAAG,GAAG,IAAI;GAAM;EAAE;EAC7E,oBAAoB,KAAK,QAAQ,OAAO,MAAM;CAChD,GAAG,OAAO;AACZ;;;ACtEA,MAAa,uBAAuB;AACpC,MAAa,+BAA+B;;;AAK5C,SAAgB,2BAA2B,KAExC,IAAY,UAAwB;CACrC,IAAI;EAEF,IAAS,SAAS,8BAA8B;GAAE;GAAI;EAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;CAClF,QAAQ,CAAwC;AAClD;;AAUA,SAAgB,sBAAsB,KAA0B,UAA6C;CAC3G,IAAI,SAAS;CACb,MAAM,iBAAiB,WAAwB;EAC7C,OAAO,eAAe;EACtB,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,kDAAkD;CACjF;CACA,MAAM,UAAiC;EACrC,IAAI,SAAS;EAAI,OAAO,SAAS;EAAO,YAAY,WAAW,OAAO,WAAW;EACjF,MAAM,KAAK,QAAQ;GACjB,cAAc,MAAM;GACpB,MAAM,QAAQ,MAAM,SAAS,KAAK,MAAM;GACxC,cAAc,MAAM;GACpB,OAAO;EACT;EACA,MAAM,MAAM,MAAM,OAAO,UAAU,QAAQ;GACzC,cAAc,MAAM;GACpB,OAAO,SAAS,MAAM,MAAM,OAAO,UAAU,MAAM;EACrD;CACF;CACA,MAAM,MAAM,IAAI,GAAG,uBAAsB,YAAW;EAAE,IAAI,QAAQ,QAAQ,OAAO;CAAE,CAAC;CAGpF,aAAa;EAAE,SAAS;EAAO,IAAI;CAAE;AACvC;;;;ACtEA,SAAgB,8BAA8B,OAA0C;CACtF,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,MAAM,IAAI,MAAM,qCAAqC;CACtH,MAAM,QAAQ;CACd,IAAI,MAAM,SAAS,WAAW,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GAAG,OAAO,EAAE,MAAM,QAAQ;CACtF,IAAI,MAAM,SAAS,aAAa,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,KAAK,OAAO,MAAM,OAAO,YAAY,MAAM,GAAG,SAAS,KAChH,OAAO,MAAM,aAAa,YAAY,OAAO,cAAc,MAAM,QAAQ,KAAK,MAAM,YAAY,GACnG,OAAO;EAAE,MAAM;EAAW,IAAI,MAAM;EAAI,UAAU,MAAM;CAAS;CAEnE,MAAM,IAAI,MAAM,qCAAqC;AACvD;;;ACfA,IAAI,oBAAwD,SAAU,SAAS,cAAc,OAAO;CAChG,IAAI,WAAW,UAAU,SAAS;CAClC,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACrC,QAAQ,WAAW,aAAa,EAAE,CAAC,KAAK,SAAS,KAAK,IAAI,aAAa,EAAE,CAAC,KAAK,OAAO;CAE1F,OAAO,WAAW,QAAQ,KAAK;AACnC;AACA,IAAI,eAA8C,SAAU,MAAM,cAAc,YAAY,WAAW,cAAc,mBAAmB;CACpI,SAAS,OAAO,GAAG;EAAE,IAAI,MAAM,KAAK,KAAK,OAAO,MAAM,YAAY,MAAM,IAAI,UAAU,mBAAmB;EAAG,OAAO;CAAG;CACtH,IAAI,OAAO,UAAU,MAAM,MAAM,SAAS,WAAW,QAAQ,SAAS,WAAW,QAAQ;CACzF,IAAI,SAAS,CAAC,gBAAgB,OAAO,UAAU,YAAY,OAAO,KAAK,YAAY;CACnF,IAAI,aAAa,iBAAiB,SAAS,OAAO,yBAAyB,QAAQ,UAAU,IAAI,IAAI,CAAC;CACtG,IAAI,GAAG,OAAO;CACd,KAAK,IAAI,IAAI,WAAW,SAAS,GAAG,KAAK,GAAG,KAAK;EAC7C,IAAI,UAAU,CAAC;EACf,KAAK,IAAI,KAAK,WAAW,QAAQ,KAAK,MAAM,WAAW,CAAC,IAAI,UAAU;EACtE,KAAK,IAAI,KAAK,UAAU,QAAQ,QAAQ,OAAO,KAAK,UAAU,OAAO;EACrE,QAAQ,iBAAiB,SAAU,GAAG;GAAE,IAAI,MAAM,MAAM,IAAI,UAAU,wDAAwD;GAAG,kBAAkB,KAAK,OAAO,KAAK,IAAI,CAAC;EAAG;EAC5K,IAAI,UAAU,GAAG,WAAW,GAAA,CAAI,SAAS,aAAa;GAAE,KAAK,WAAW;GAAK,KAAK,WAAW;EAAI,IAAI,WAAW,MAAM,OAAO;EAC7H,IAAI,SAAS,YAAY;GACrB,IAAI,WAAW,KAAK,GAAG;GACvB,IAAI,WAAW,QAAQ,OAAO,WAAW,UAAU,MAAM,IAAI,UAAU,iBAAiB;GACxF,IAAI,IAAI,OAAO,OAAO,GAAG,GAAG,WAAW,MAAM;GAC7C,IAAI,IAAI,OAAO,OAAO,GAAG,GAAG,WAAW,MAAM;GAC7C,IAAI,IAAI,OAAO,OAAO,IAAI,GAAG,aAAa,QAAQ,CAAC;EACvD,OACK,IAAI,IAAI,OAAO,MAAM,GAAG;GACzB,IAAI,SAAS,SAAS,aAAa,QAAQ,CAAC;QACvC,WAAW,OAAO;EAC3B;CACJ;CACA,IAAI,QAAQ,OAAO,eAAe,QAAQ,UAAU,MAAM,UAAU;CACpE,OAAO;AACX;;;;AAOA,gBAAuB,0BAA0B,QAAQ,QAAQ,SAAS;CACtE,OAAO,eAAe;CACtB,MAAM,0BAAU,IAAI,IAAI;CACxB,IAAI,OAAO;CACX,IAAI;CACJ,MAAM,WAAW,IAAI,aAAa;EAC9B,IAAI,YAAY,KAAA,KAAa,OAAO,SAChC;EACJ,IAAI;EACJ,IAAI;GACA,QAAQ,8BAA8B;IAAE,MAAM;IAAW;IAAI;GAAS,CAAC;EAC3E,QACM;GACF;EACJ;EACA,IAAI,CAAC,MAAM;GACP,IAAI,CAAC,QAAQ,IAAI,EAAE,KAAK,QAAQ,QAAQ,KAAK;IACzC,QAAQ,MAAM;IACd,OAAO;GACX,OAEI,QAAQ,IAAI,IAAI,KAAK;EAC7B;EACA,OAAO;CACX;CACA,MAAM,YAAY,CAAC;CACnB,MAAM,gBAAgB;EAClB,KAAK,MAAM,OAAO,UAAU,OAAO,CAAC,CAAC,CAAC,QAAQ,GAC1C,IAAI;EACR,QAAQ,MAAM;CAClB;CAEA,MAAM,gBAAgB;EAAE,QAAQ;EAAG,OAAO;CAAG;CAC7C,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;CACxD,IAAI;EACA,UAAU,KAAK,OAAO,GAAG,+BAA+B,EAAE,IAAI,eAAe,QAAQ,IAAI,QAAQ,CAAC,CAAC;EACnG,UAAU,KAAK,OAAO,GAAG,6BAA6B,OAAO,CAAC;EAC9D,OAAO,eAAe;EACtB,MAAM,EAAE,MAAM,QAAQ;EACtB,OAAO,MAAM;GACT,OAAO,eAAe;GACtB,IAAI,MAAM;IACN,OAAO;IACP,MAAM,EAAE,MAAM,QAAQ;IACtB;GACJ;GACA,IAAI,QAAQ,MAAM;IACd,MAAM,CAAC,IAAI,SAAS,QAAQ,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC;IAC7C,QAAQ,OAAO,EAAE;IACjB,MAAM;IACN;GACJ;GACA,MAAM,IAAI,SAAQ,YAAW;IACzB,OAAO;IACP,IAAI,OAAO,WAAW,QAAQ,QAAQ,MAClC,QAAQ;GAChB,CAAC;GACD,OAAO,KAAA;EACX;CACJ,UACQ;EACJ,OAAO,oBAAoB,SAAS,OAAO;EAC3C,QAAQ;CACZ;AACJ;;;AAGA,IAAI,wCAAwC;CACxC,IAAI,cAAc;CAClB,IAAI,6BAA6B,CAAC;CAClC,IAAI;CACJ,OAAO,MAAM,uCAAuC,YAAY;EAC5D;GACI,MAAM,YAAY,OAAO,WAAW,cAAc,OAAO,WAAW,OAAO,OAAO,YAAY,OAAO,aAAa,IAAI,IAAI,KAAK;GAC/H,oBAAoB,CAAC,OAAO,EAAE,MAAM,SAAS,CAAC,CAAC;GAC/C,aAAa,MAAM,MAAM,mBAAmB;IAAE,MAAM;IAAU,MAAM;IAAS,QAAQ;IAAO,SAAS;IAAO,QAAQ;KAAE,MAAK,QAAO,WAAW;KAAK,MAAK,QAAO,IAAI;IAAM;IAAG,UAAU;GAAU,GAAG,MAAM,0BAA0B;GAClO,IAAI,WAAW,OAAO,eAAe,MAAM,OAAO,UAAU;IAAE,YAAY;IAAM,cAAc;IAAM,UAAU;IAAM,OAAO;GAAU,CAAC;EAC1I;EACA,YAAY,kBAAkB,MAAM,0BAA0B,GAAG,IAAI,gBAAgB;EACrF;EACA,YAAY,KAAK,UAAU,SAAS;GAChC,MAAM,KAAK,SAAS,SAAS,EAAE,WAAW,SAAS,UAAU,CAAC;GAC9D,KAAK,UAAU;GACf,IAAI,mBAAmB;IAAE,KAAK,SAAS,sBAAM,IAAI,MAAM,oCAAoC,CAAC;GAAG,CAAC;EACpG;EACA,MAAM,QAAQ;GACV,OAAO,0BAA0B,KAAK,KAAK,YAAY,IAAI,CAAC,KAAK,SAAS,QAAQ,MAAM,CAAC,GAAG,KAAK,OAAO;EAC5G;CACJ;AACJ,EAAA,CAAG;;AAGH,SAAgB,2BAA2B,KAAK,UAAU,SAAS;CAC/D,OAAO,IAAI,+BAA+B,KAAK,UAAU,OAAO;AACpE;;;ACpGA,MAAM,cAAc;AACpB,MAAM,iBAAiB;AACvB,MAAM,QAAQ;AACd,MAAM,MAAM;AACZ,MAAM,SAAS;CAAC;CAAiB;CAAa;AAAY;;AA0C1D,MAAM,cAAc,OAAO,IAAI,yCAAyC;AACxE,SAAS,YAA8B,OAA2C;CAChF,MAAmC,eAAe;CAClD,OAAO;AACT;AAEA,eAAe,iBAAiB,OAAqC;CACnE,MAAM,CAAC,EAAE,cAAc,eAAe,EAAE,OAAO,MAAM,QAAQ,IAAI,CAC/D,OAAO,oCAAoC,OAAO,MACpD,CAAC;CAID,MAAM,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,QAC5C,UAAS,UAAU,MAAM,KAAK,KAAK,CAAC,kBAAkB,KAAK,KAAK,GAChE,qEACF;CACA,MAAM,QAAQ,EAAE,MAAM,CACpB,EAAE,OAAO;EACP,UAAU;EACV,OAAO;EACP,iBAAiB,WAAW,IAAI,EAAE,CAAC,CAAC,SAAS;CAC/C,CAAC,CAAC,CAAC,OAAO,GACV,EAAE,KAAK,CACT,CAAC;CACD,OAAO,MAAM,cAAc,KAAK,aAAa;EAC3C,MAAM;EAAa,SAAS;EAC5B,QAAQ,GACL,QAAQ,YAAY,EAAE,OAAO;GAC5B,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY;GACvC;EACF,CAAC,CAAC,CAAC,OAAO,CAAC,EACb;CACF,CAAC,CAAC;AACJ;;AAGA,SAAS,cAAc,SAA6C;CAClE,OAAO,OAAO,OAAO,IAAI,MAAM,OAAO,GAAG,EAAE,UAAU,KAAc,CAAC;AACtE;;AAGA,SAAS,WAAW,OAA2B;CAC7C,IAAI,SAAS,OAAO,UAAU,YAAY,cAAc,OACtD,OAAO;EAAE,IAAI;EAAO,OAAO;GAAE,MAAM;GAA4B,SAAS,iBAAiB,QAAQ,MAAM,UAAU;EAAoB;CAAE;CAEzI,IAAI,iBAAiB,SAAS,8EAA8E,KAAK,MAAM,OAAO,GAC5H,OAAO;EAAE,IAAI;EAAO,OAAO;GAAE,MAAM;GAA4B,SAAS,MAAM;EAAQ;CAAE;CAE1F,OAAO;EAAE,IAAI;EAAO,OAAO;GAAE,MAAM;GAAyB,SAAS;EAAuC;CAAE;AAChH;;;;;;;;AASA,SAAS,eAAe,OAAoB,KAAc,OAAgB,kBAA4D;CACpI,IAAI,CAAC,OAAO,cAAc,gBAAgB,GAAG,OAAO,QAAQ,OAAO,cAAc,yDAAyD,CAAC;CAC3I,MAAM,MAAM,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAI,QAAmC,KAAA;CAC7G,MAAM,cAAc,UAClB,OAAO,UAAU,YAAY,UAAU,MAAM,KAAK,KAAK,CAAC,kBAAkB,KAAK,KAAK;CACtF,IAAI,CAAC,OAAO;EAAC;EAAY;EAAS;CAAiB,CAAC,CAAC,MAAK,QAAO,IAAI,SAAS,KAAA,KAAa,CAAC,WAAW,IAAI,IAAI,CAAC,GAC9G,OAAO,QAAQ,uBAAO,IAAI,MAAM,qBAAqB,CAAC;CAExD,MAAM,aAAa,oBAAoB,GAAG;CAC1C,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ,IAAI,KAAK,MAAM,CAAC,mBAAmB,UAAU,GACjF,OAAO,QAAQ,uBAAO,IAAI,MAAM,qBAAqB,CAAC;CAExD,MAAM,SAAS,MAAM,KAAK,KAAK,YAA6C;EAC1E,IAAI,MAAM,UAAU,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,2DAA2D;EAC9G,IAAI,qBAAqB,MAAM,KAAK,UAAU,MAAM,cAAc,oDAAoD;EACtH,MAAM,OAA+B;GAAE,UAAU,MAAM,KAAK,WAAW;GAAG,OAAO,mBAAmB,UAAU,KAAK;EAAK;EACxH,MAAM,MAAM,OAAO,MAAM,KAAK,CAAC,CAAC,IAAI,KAAK;GAAE,UAAU,KAAK;GAAU,OAAO,KAAK;EAAM,CAAC;EACvF,MAAM,OAAO;EACb,2BAA2B,IAAI,MAAM,oBAAoB,KAAK,QAAQ;EACtE,OAAO;CACT,CAAC;CAED,MAAM,OAAO,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC;CAC3C,OAAO;AACT;AAEA,SAAS,UAAU,OAAoB,KAAc,OAA6B;CAShF,MAAM,aAAa,EAAE,MAAM;CAC3B,IAAI,WAAW;CAGf,MAAM,mBAAmB;EAAE,WAAW;CAAK,CAAC;CAC5C,MAAM,cAAc,MAAM,UAAU,YAAY,MAAM,eAAe;CACrE,MAAM,OAAO,YAAY;EAEvB,MAAM,YAAY;EAClB,MAAM,SAAS,MAAM,iBAAiB,KAAK;EAC3C,IAAI,MAAM,GAAG;GAAE,MAAM,OAAO,MAAM;GAAG,MAAM,4BAAY,IAAI,MAAM,4CAA4C,CAAC;EAAE;EAChH,MAAM,SAAS;EAIf,IAAI;GAAE,MAAM,mBAAmB,OAAO,MAAM,CAAC;EAAE,SAAS,OAAO;GAAE,MAAM,OAAO,MAAM;GAAG,MAAM;EAAM;EAGnG,MAAM,SAAS,OAAO,MAAM,KAAK,CAAC,CAAC,IAAI,GAAG;EAC1C,IAAI,MAAM,GAAG;GAAE,MAAM,OAAO,MAAM;GAAG,MAAM,4BAAY,IAAI,MAAM,8CAA8C,CAAC;EAAE;EAClH,MAAM,OAAO;GAAE,UAAU,QAAQ,YAAY;GAAG,OAAO,QAAQ,SAAS;EAAK;EAC7E,MAAM,QAAQ,KAAA;EACd,MAAM,YAAY;EAClB,MAAM,aAAa,sBAAsB,OAAO;GAC9C,IAAI;GACJ,OAAO;IAAE,IAAI;IAAQ,IAAI;GAAkB;GAC3C,KAAK,QAAQ;IACX,OAAO,eAAe;IACtB,MAAM,EAAE,UAAU,UAAU,MAAM;IAClC,OAAO;KACL;KACA,QAAQ,CAAC;MACP,MAAM,CAAC,OAAO;MACd,OAAO;OAAE,IAAI;OAAU,IAAI;MAAyB;MACpD,SAAS,SAAS,KAAA;MAClB,aAAa;MACb,aAAa;OAAE,IAAI;OAAU,IAAI;MAA6B;KAChE,CAAC;IACH;GACF;GACA,MAAM,MAAM,MAAM,OAAO,kBAAkB,QAAQ;IACjD,OAAO,eAAe;IACtB,IAAI,KAAK,WAAW,KAAK,KAAK,OAAO,SAAS,MAAM,IAAI,MAAM,iCAAiC;IAC/F,OAAO,eAAe,OAAO,KAAK,OAAO,gBAAgB;GAC3D;EACF,CAAC,CAAC;EACF,MAAM,aAAa,gBAAgB,OAAO,yBAAyB,OAAO,UAAU,SAAS,WAAW;GACtG,OAAO,eAAe;GACtB,IAAI,MAAM,QAAQ,OAAO;IAAE,IAAI;IAAO,OAAO;KAAE,MAAM;KAA6B,SAAS;IAA4D;GAAE;GACzJ,IAAI,CAAC,MAAM,WACT,OAAO,MAAM,QACT;IAAE,IAAI;IAAO,OAAO;KAAE,MAAM;KAAyB,SAAS;IAAuC;GAAE,IACvG;IAAE,IAAI;IAAO,OAAO;KAAE,MAAM;KAA+B,SAAS;IAA8D;GAAE;GAE1I,IAAI,aAAa,gBAAgB;IAC/B,MAAM,EAAE,UAAU,UAAU,MAAM;IAClC,OAAO;KAAE,IAAI;KAAM,OAAO;MAAE;MAAU;KAAM;IAAE;GAChD;GACA,IAAI,aAAa,gBACf,IAAI;IACF,MAAM,OAAO,WAAW,OAAO,YAAY,YAAY,CAAC,MAAM,QAAQ,OAAO,IAAI,UAAqC,CAAC;IACvH,MAAM,QAAQ,MAAM,eAAe,OAAO,KAAK,KAAK,OAAO,KAAK,gBAAgB;IAChF,OAAO,eAAe;IACtB,OAAO;KAAE,IAAI;KAAM;IAAM;GAC3B,SAAS,OAAO;IACd,IAAI,OAAO,SAAS,MAAM;IAC1B,OAAO,WAAW,KAAK;GACzB;GAEF,OAAO;IAAE,IAAI;IAAO,OAAO;KAAE,MAAM;KAAoC,SAAS,qBAAqB;IAAW;GAAE;EACpH,GAAG,EAAE,aAAY,aAAY,YAAY,KAAK,QAAQ,EAAE,CAAC,CAAC;EAE1D,2BAA2B,OAA6B,kCAAkC,kBAAkB;EAM5G,MAAM,mBAAmB;GAAE,IAAI,MAAM,eAAe,YAAY;IAAE,MAAM,YAAY;IAAO,MAAM,SAAS,KAAA;GAAU;EAAE,CAAC;CACzH,EAAA,CAAG,CAAC,CAAC,OAAM,UAAS;EAGlB,IAAI,SAAS,OAAO,UAAU,UAAU,MAAmC,gBAAgB;EAG3F,IAAI,MAAM,eAAe,YAAY;GACnC,MAAM,YAAY;GAClB,MAAM,QAAQ;EAChB;EACA,MAAM;CACR,CAAC;CAKD,IAAI,YAAY,CAAC,CAAC;CAClB,MAAM,QAAQ,IAAI,WAAW,CAAC,CAAC;CAC/B,MAAM,YAAY,CAAC,CAAC;CACpB,MAAM,QAAQ;CACd,OAAO;AACT;AAEA,SAAS,SAAS,OAAoB,KAA6B;CACjE,IAAI,CAAC,MAAM,SAAS;EAClB,MAAM,SAAS;EACf,MAAM,OAAO,IAAI;EACjB,MAAM,WAAW,YAAY;GAE3B,MAAM,MAAM,WAAW,YAAY,CAAC,CAAC;GACrC,MAAM,MAAM,KAAK,YAAY,CAAC,CAAC;GAC/B,IAAI;IAAE,MAAM,MAAM,OAAO,QAAQ;GAAE,SAAS,OAAO;IAGjD,IAAI;KAAE,IAAoE,QAAQ,KAAK,yCAAyC,KAAK;IAAE,QACjI,CAAkB;GAC1B;GACA,IAAI;IACF,IAAI,KAAK,IAAA,qBAA6B,KAAK,MAAM,OAAO,MAAM,gBAAgB;GAChF,QAAQ,CAA0B;GAClC,MAAM,gBAAgB,KAAA;EACxB,EAAA,CAAG;CACL;CACA,OAAO,MAAM;AACf;AAEA,SAAS,kBAAkB,KAA2B;CACpD,MAAM,OAAO,IAAI;CACjB,MAAM,QAAqB;EACzB,OAAO;EAAG,QAAQ;EAAO,WAAW;EAAO,YAAY;EAAG,MAAM,QAAQ,QAAQ;EAChF,MAAM;GAAE,UAAU;GAAG,OAAO;EAAK;EACjC,WAAW;GAGT,IAAI,KAAK,OAAO,MAAM,KAAK;GAG3B,IAAI,CAAC,KAAK,WAAW,MAAM,IAAI,MAAM,yDAAyD;GAC9F,OAAO,KAAK;EACd;EACA,OAAO,QAAQ,QAAQ;EACvB,WAAW;GAAE,OAAO,SAAS,MAAM,GAAG;EAAE;CAC1C;CAKA,MAAM,WAAW,OAAO,QAAO,YAAW;EACxC,IAAI;GAAE,OAAO,KAAK,IAAI,SAAS,IAAI,MAAM,KAAA;EAAU,QAAQ;GAAE,OAAO;EAAK;CAC3E,CAAC;CACD,IAAI,SAAS,QACX,MAAM,IAAI,MAAM,wCAAwC,SAAS,KAAK,IAAI,EAAE,yBAAyB;CAEvG,MAAM,QAAQ,KAAK,OAAO,SAAQ,UAAS;EAAE,MAAM,YAAY,UAAU,OAAO,KAAK,KAAK;CAAE,CAAC;CAC7F,MAAM,QAAQ,QAAQ,QAAQ,MAAM,KAAK,CAAC,CAAC,WAAW;EAKpD,IAAI,CAAC,MAAM,WAAW,MAAM,4BAAY,IAAI,MAAM,oEAAoE,CAAC;EACvH,OAAO,MAAM;CACf,CAAC;CAKD,MAAM,MAAM,OAAM,UAAS;EACzB,MAAM,MAAO,MAAqC;EAClD,IAAI,QAAQ,KAAA,KAAa,QAAQ,MAAM,YAAY;EACnD,MAAM,QAAQ,MAAM,SAAS;EAC7B,MAAM,SAAS;EACf,MAAW,SAAS;CACtB,CAAC;CAGD,MAAM,gBAAgB,KAAK,QAAQ,yBAAyB,KAAK;CACjE,OAAO;AACT;AAEA,eAAe,aAAa,KAAoC;CAC9D,MAAM,OAAO,IAAI;CACjB,SAAS;EACP,MAAM,WAAW,KAAK,IAAI,yBAAyB,KAAK;EACxD,IAAI,UAAU;GACZ,IAAI,CAAC,SAAS,QAAQ,OAAO;GAE7B,MAAM,SAAS;GACf;EACF;EACA,OAAO,kBAAkB,GAAG;CAC9B;AACF;;;;;;;;;;;;;;;AAgBA,eAAsB,qBAAqB,KAA4C;CACrF,SAAS;EACP,MAAM,QAAQ,MAAM,aAAa,GAAG;EAIpC,MAAM,MAAM;EACZ,IAAI,MAAM,QAAQ;EAClB,MAAM,SAAS;EACf,IAAI,WAAW;EACf,OAAO,YAAY;GACjB,IAAI,UAAU;GACd,WAAW;GACX,MAAM,SAAS;GACf,IAAI,MAAM,SAAS,GAAG,MAAM,MAAM,SAAS;QACtC,MAAM,MAAM,KAAK,YAAY,CAAC,CAAC;EACtC;CACF;AACF;AClXa,IAAI,YAAY;AAM7B,SAAS,kBAAkB,SAAoE;CAC7F,IAAI,YAAY,KAAA,GAAW,OAAO,CAAC;CAEnC,QADgC,OAAO,YAAY,WAAW,CAAC,OAAO,IAAI,QAAA,CAC9D,QAAO,YAAW,OAAO,YAAY,YAAY,QAAQ,SAAS,CAAC;AACjF;;AAeA,SAAS,iBAAiB,SAAyB;CACjD,OAAO,QAAQ,WAAW,aAAa,GAAG;AAC5C;;;;;;;AAQA,SAAgB,uBAAuB,SAI5B;CACT,MAAM,UAAU,kBAAkB,QAAQ,OAAO;CACjD,IAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ;CAEpC,OAAO,qBADW,QAAQ,UAAU,aAAa,iBAAiB,QAAQ,OAAO,EAAE,KAAK,GAClD,KAAK,QAAQ,KAAK,IAAI,EAAE,qCAAqC,QAAQ,KAAK;AAClH;;;ACXA,SAAS,QAAQ,OAAsH;CACrI,IAAI,OAAO,OAAO,aAAa,YAAY,CAAC,MAAM,SAAS,KAAK,GAAG,OAAO,KAAA;CAC1E,IAAI,OAAO,MAAM,UAAU,YAAY,CAAC,MAAM,MAAM,KAAK,GAAG,OAAO,KAAA;CACnE,MAAM,SAAS,OAAO,MAAM,oBAAoB,WAAW,MAAM,gBAAgB,KAAK,IAAI;CAC1F,OAAO,SACH;EAAE,UAAU,MAAM,SAAS,KAAK;EAAG,OAAO,MAAM,MAAM,KAAK;EAAG,iBAAiB;CAAO,IACtF;EAAE,UAAU,MAAM,SAAS,KAAK;EAAG,OAAO,MAAM,MAAM,KAAK;CAAE;AACnE;;;;;;;;AASA,SAAgB,oBAAoB,MAAe,OAAsC,WAAmD;CAC1I,MAAM,WAAW,QAAQ,KAAK;CAC9B,IAAI,UAAU,OAAO;CACrB,MAAM,YAAY,kBAAkB,IAAI;CACxC,IAAI,WAAW,OAAO;CACtB,MAAM,OAAO;CACb,IAAI,aAAa,MAAM,UAAU,KAAK,oBAAoB;EACxD,MAAM,UAAU,KAAK,OAAO,IAAI,SAAS,CAAC,EAAE;EAC5C,IAAI,SAAS;GACX,IAAI;IACF,MAAM,UAAU,KAAK,mBAAmB,QAAQ,SAAS,gBAAgB,CAAC,EAAE;IAC5E,MAAM,WAAW,QAAQ,WAAW,KAAA,CAAS;IAC7C,IAAI,UAAU,OAAO;GACvB,QAAQ,CAA2C;GACnD,MAAM,SAAS,QAAQ,gBAAgB;GACvC,MAAM,WAAW,QAAQ;GACzB,IAAI,UAAU;IAIZ,MAAM,QAAQ,QAHG,QAAQ,iBAAiB,oBAAoB,OAC1D;KAAE,UAAU,SAAS;KAAU,OAAO,SAAS;IAAM,IACrD,QAC0B;IAC9B,IAAI,OAAO,OAAO;GACpB;EACF;CACF;CACA,OAAO,QAAQ,MAAM,mBAAmB,iBAAiB,CAAC;AAC5D;AAEA,SAAS,SAAS,WAAmC;CACnD,OAAO,UAAU,OAAO,CAAC,CACtB,QAAQ,UAAmD,MAAM,SAAS,MAAM,CAAC,CACjF,KAAI,UAAS,MAAM,IAAI,CAAC,CACxB,KAAK,EAAE;AACZ;AAEA,eAAe,WAAW,QAAoC,QAAqB,MAA8C;CAC/H,MAAM,YAAY,IAAI,eAAe;CACrC,MAAM,WAAW,OAAO,OAAO,cAAc,CAAC;CAC9C,IAAI;EACF,OAAO,KAAK,GAAG;GACb,IAAI,OAAO,SAAS;GACpB,MAAM,OAAO,MAAM,SAAS,KAAK;GACjC,IAAI,KAAK,MAAM;GACf,UAAU,KAAK,KAAK,KAAK;EAC3B;CACF,UAAU;EAGR,MAAM,SAAS,SAAS;CAC1B;CACA,OAAO;AACT;;AAGA,eAAsB,YAAY,KAAoB,SAAiD;CACrG,QAAQ,OAAO,eAAe;CAC9B,MAAM,aAAa,QAAQ,YAAY,MAAM,SAAS,CAAC,QAAQ,OAAO;CACtE,IAAI,CAAC,KAAK,GAAG,MAAM,OAAO,uBAAO,IAAI,MAAM,QAAQ,GAAG,EAAE,MAAM,aAAa,CAAC;CAC5E,MAAM,SAAS,QAAQ,MAAM,iBAAiB,KAAK;CACnD,MAAM,WAAW,MAAM,IAAI,YAAY;EACrC,UAAU,QAAQ,MAAM;EACxB,OAAO,QAAQ,MAAM;EACrB,GAAI,SAAS,EAAE,iBAAiB,kBAAkB,MAAM,EAAE,IAAI,CAAC;EAC/D,GAAI,QAAQ,cAAc,KAAA,IAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;CAC5E,GAAG,QAAQ,QAAQ,QAAQ,SAAS;CACpC,IAAI,CAAC,KAAK,GAAG,MAAM,OAAO,uBAAO,IAAI,MAAM,QAAQ,GAAG,EAAE,MAAM,aAAa,CAAC;CAC5E,MAAM,YAAY,QAAQ,cAAc,KAAA,IACpC,SAAS,OAAO,YAChB,KAAK,IAAI,QAAQ,WAAW,SAAS,OAAO,aAAa,QAAQ,SAAS;CAC9E,MAAM,UAA2B;EAC/B,UAAU,SAAS,OAAO;EAC1B,OAAO,SAAS,OAAO;EACvB,GAAI,SAAS,OAAO,kBAAkB,EAAE,iBAAiB,SAAS,OAAO,gBAAgB,IAAI,CAAC;EAC9F,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;EAC/C,GAAI,SAAS,OAAO,gBAAgB,KAAA,IAAY,EAAE,aAAa,SAAS,OAAO,YAAY,IAAI,CAAC;EAChG,GAAI,SAAS,OAAO,OAAO,EAAE,MAAM,CAAC,GAAG,SAAS,OAAO,IAAI,EAAE,IAAI,CAAC;EAClE,QAAQ,QAAQ;EAChB,UAAU,CAAC,kBAAkB;GAC3B,QAAQ,sBAAsB,QAAQ,MAAM;GAC5C,SAAS,CAAC;IAAE,MAAM;IAAQ,MAAM,uBAAuB,OAAO;GAAE,CAAC;EACnE,CAAC,CAAC;EACF,QAAQ,QAAQ;EAChB,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;EACtD,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAA0C,IAAI,CAAC;CAC9F;CACA,MAAM,YAAY,MAAM,WAAW,SAAS,OAAO,OAAO,GAAG,QAAQ,QAAQ,IAAI;CACjF,IAAI,QAAQ,OAAO,WAAW,UAAU,OAAO,SAAS,WACtD,MAAM,OAAO,uBAAO,IAAI,MAAM,QAAQ,GAAG,EAAE,MAAM,aAAa,CAAC;CAEjE,IAAI,CAAC,KAAK,GAAG,MAAM,OAAO,uBAAO,IAAI,MAAM,QAAQ,GAAG,EAAE,MAAM,aAAa,CAAC;CAC5E,IAAI,UAAU,OAAO,SAAS,SAAS;EACrC,MAAM,OAAO,UAAU,OAAO,QAAQ;EACtC,MAAM,OAAO,OAAO,IAAI,MAAM,UAAU,OAAO,QAAQ,WAAW,SAAS,GAAG,EAAE,KAAK,CAAC;CACxF;CACA,IAAI,UAAU,OAAO,CAAC,CAAC,MAAK,UAAS,MAAM,SAAS,WAAW,KAAK,UAAU,OAAO,SAAS,cAC5F,MAAM,IAAI,MAAM,YAAY;CAE9B,IAAI,UAAU,OAAO,SAAS,QAAQ,MAAM,IAAI,MAAM,UAAU;CAGhE,MAAM,QAAQ,UAAU;CACxB,OAAO;EACL,MAAM,SAAS,SAAS;EACxB,UAAU,SAAS,OAAO;EAC1B,OAAO,SAAS,OAAO;EACvB,GAAI,QAAQ;GACV,aAAa,MAAM;GACnB,cAAc,MAAM;GACpB,GAAI,MAAM,gBAAgB,KAAA,IAAY,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;GAC5E,GAAI,MAAM,oBAAoB,KAAA,IAAY,EAAE,iBAAiB,MAAM,gBAAgB,IAAI,CAAC;GACxF,GAAI,MAAM,qBAAqB,KAAA,IAAY,EAAE,kBAAkB,MAAM,iBAAiB,IAAI,CAAC;GAC3F,GAAI,MAAM,oBAAoB,KAAA,IAAY,EAAE,iBAAiB,MAAM,gBAAgB,IAAI,CAAC;EAC1F,IAAI,CAAC;CACP;AACF;;;AC7LA,MAAa,eACX;AAEF,SAAgB,cAAc,UAA2C;CACvE,OAAO,GAAG,eAAe,KAAK,UAAU,QAAQ;AAClD;AAEA,SAAgB,UAAU,OAAuB;CAC/C,OAAO,OAAO,WAAW,OAAO,MAAM;AACxC;AAEA,SAAS,YAAY,YAA+B,MAAsB;CACxE,IAAI,QAAQ,WAAW,QAAQ,OAAO,WAAW,KAAK,EAAE;CACxD,IAAI,QAAQ,GAAG,OAAO;CACtB,IAAI,SAAS,GAAG,OAAO;CAEvB,MAAM,gBAAgB,OAAO;CAC7B,MAAM,YAAY,KAAK,KAAK,gBAAgB,CAAC;CAC7C,MAAM,YAAY,KAAK,MAAM,gBAAgB,CAAC;CAC9C,OAAO,GAAG,WAAW,MAAM,GAAG,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,GAChD,cAAc,IAAI,KAAK,WAAW,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE;AAE/D;AAEA,SAAgB,iBAAiB,SAAuB,eAAqC;CAE3F,IAAI,UAAU,cAAc,CAAC;EADb,GAAG;EAAS,MAAM;CACD,CAAC,CAAC,CAAC,IAAI,eACtC,MAAM,IAAI,MAAM,sEAAsE;CAExF,IAAI,UAAU,cAAc,CAAC,OAAO,CAAC,CAAC,KAAK,eAAe,OAAO;CAEjE,MAAM,SAAS,MAAM,KAAK,QAAQ,IAAI;CACtC,IAAI,MAAM;CACV,IAAI,OAAO,OAAO;CAClB,IAAI,OAAO;CAEX,OAAO,OAAO,MAAM;EAClB,MAAM,OAAO,KAAK,OAAO,MAAM,QAAQ,CAAC;EACxC,MAAM,OAAO,YAAY,QAAQ,IAAI;EACrC,IAAI,UAAU,cAAc,CAAC;GAAE,GAAG;GAAS;EAAK,CAAC,CAAC,CAAC,KAAK,eAAe;GACrE,OAAO;GACP,MAAM,OAAO;EACf,OACE,OAAO,OAAO;CAElB;CAEA,OAAO;EAAE,GAAG;EAAS,MAAM;CAAK;AAClC;AAEA,SAAgB,qBACd,UACA,mBACA,eACgB;CAChB,IAAI,SAAS,WAAW,GAAG,OAAO,CAAC;CAEnC,MAAM,WAAW,SAAS,MAAM,CAAC,iBAAiB,CAAC,CAAC,KAAI,aAAY,EAAE,GAAG,QAAQ,EAAE;CACnF,OAAO,SAAS,SAAS,KAAK,UAAU,cAAc,QAAQ,CAAC,IAAI,eACjE,SAAS,MAAM;CAGjB,IAAI,UAAU,cAAc,QAAQ,CAAC,IAAI,eACvC,SAAS,KAAK,iBAAiB,SAAS,IAAK,aAAa;CAG5D,OAAO;AACT;;;ACrEA,MAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AASA,MAAM,oBAAoE;CACxE,IAAI;EACF,SAAS;EACT,KAAK;EACL,UAAU;EACV,UAAU;EACV,MAAM;EACN,MAAM;EACN,SAAS;EACT,QAAQ;EACR,SAAS;EACT,SAAS;CACX;CACA,IAAI;EACF,SAAS;EACT,KAAK;EACL,UAAU;EACV,UAAU;EACV,MAAM;EACN,MAAM;EACN,SAAS;EACT,QAAQ;EACR,SAAS;EACT,SAAS;CACX;AACF;AAOA,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB;AAE5B,SAAS,eAAe,OAAuB;CAC7C,OAAO,MACJ,QAAQ,cAAc,EAAE,CAAC,CACzB,QAAQ,cAAc,EAAE,CAAC,CACzB,QAAQ,cAAc,EAAE,CAAC,CACzB,QAAQ,mBAAmB,EAAE,CAAC,CAC9B,QAAQ,qBAAqB,EAAE,CAAC,CAChC,QAAQ,SAAS,GAAG,CAAC,CACrB,KAAK;AACV;AAEA,SAAgB,kBAAkB,OAAe,UAA0B;CACzE,IAAI,CAAC,OAAO,UAAU,QAAQ,KAAK,YAAY,GAAG,MAAM,IAAI,MAAM,qCAAqC;CACvG,IAAI,OAAO,WAAW,OAAO,MAAM,KAAK,UAAU,OAAO;CACzD,IAAI,OAAO;CACX,IAAI,SAAS;CACb,KAAK,MAAM,aAAa,OAAO;EAC7B,MAAM,QAAQ,OAAO,WAAW,WAAW,MAAM;EACjD,IAAI,OAAO,QAAQ,UAAU;EAC7B,UAAU;EACV,QAAQ;CACV;CACA,OAAO;AACT;;AAGA,SAAgB,sBAAsB,OAAe,UAA0B;CAC7E,OAAO,kBAAkB,eAAe,KAAK,GAAG,QAAQ,CAAC,CAAC,QAAQ;AACpE;AAEA,SAAS,YAAY,OAAmC;CACtD,OAAQ,gBAAsC,SAAS,KAAK;AAC9D;AAEA,SAAgB,mBACd,MACA,UACA,YACa;CACb,IAAI,SAAS,QAAQ,OAAO;CAE5B,MAAM,YAAY,YAAY,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;CAC9D,IAAI,cAAc,QAAQ,cAAc,MAAM,OAAO;CAErD,MAAM,OAAO,SAAS,KAAK,IAAI;CAC/B,IAAI,6DAA6D,KAAK,IAAI,GAAG,OAAO;CACpF,OAAO,kBAAkB,KAAK,IAAI,IAAI,OAAO;AAC/C;AAEA,SAAS,kBAAkB,OAAuB;CAChD,OAAO,MAAM,QAAQ,qBAAqB,GAAG;AAC/C;AAEA,SAAS,gBAAgB,OAAe,aAAqB,qBAAqC;CAEhG,IADoB,2EAA2E,KAAK,KACtF,GACZ,OAAO,MAAM,KAAK,MAAM,QAAQ,SAAS,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,mBAAmB,CAAC,CAAC,KAAK,EAAE;CAErF,OAAO,MAAM,MAAM,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC,KAAK,GAAG;AAC3E;AAEA,SAAS,gBAAgB,KAAqB;CAC5C,MAAM,UAAU,IAAI,KAAK;CAEzB,QADe,sCAAsC,KAAK,OAC7C,CAAC,GAAG,MAAM,QAAA,CAAS,KAAK;AACvC;AAEA,SAAS,eAAe,KAAkD;CACxE,MAAM,OAAO,gBAAgB,GAAG;CAChC,MAAM,QAAQ,KAAK,QAAQ,GAAG;CAC9B,MAAM,MAAM,KAAK,YAAY,GAAG;CAChC,IAAI,UAAU,MAAM,OAAO,OAAO,OAAO,KAAA;CACzC,IAAI;EACF,MAAM,QAAQ,KAAK,MAAM,KAAK,MAAM,OAAO,MAAM,CAAC,CAAC;EACnD,IAAI,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO;CAC1E,QAAQ;EACN;CACF;AAEF;;;;;;AAOA,SAAgB,gBACd,KACA,aACA,qBACa;CACb,MAAM,YAAY,eAAe,GAAG;CACpC,MAAM,YAAY,OAAO,WAAW,SAAS,WAAW,UAAU,KAAK,KAAK,CAAC,CAAC,YAAY,IAAI;CAC9F,MAAM,eAAe,OAAO,WAAW,YAAY,WAAW,UAAU,UAAU;CAClF,MAAM,OAAO,YAAY,SAAS,IAAI,YAAY;CAGlD,MAAM,UAAU,gBADG,sBAAsB,kBAD1B,iBAAiB,YAAY,KAAK,gBAAgB,GAAG,CAAC,CAAC,QAAQ,qBAAqB,EAAE,EACpC,GAAG,OAAO,gBAClC,GAAG,aAAa,mBAAmB;CAC5E,IAAI,QAAQ,WAAW,GACrB,MAAM,IAAI,MAAM,0DAA0D;CAE5E,OAAO;EAAE;EAAM;CAAQ;AACzB;AAEA,SAAgB,cAAc,KAAmB;CAG/C,OAAO,GAFO,OAAO,IAAI,SAAS,IAAI,CAAC,CAAC,CAAC,SAAS,GAAG,GAEvC,IADF,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAC,SAAS,GAAG,GAC1B;AACtB;AAEA,SAAgB,YAAY,QAAqB,QAAqB,sBAAM,IAAI,KAAK,GAAW;CAC9F,OAAO,GAAG,cAAc,GAAG,EAAE,KAAK,kBAAkB,OAAO,CAAC,OAAO,MAAM,KAAK,OAAO;AACvF;;;ACpJA,SAAS,gBAAgB,SAAgG;CACvH,IAAI,CAAC,MAAM,QAAQ,OAAO,GAAG,OAAO;CACpC,OAAO,QACJ,QAAO,UAAS,SAAS,MAAM,SAAS,UAAU,OAAO,MAAM,SAAS,QAAQ,CAAC,CACjF,KAAI,UAAS,MAAM,IAAc,CAAC,CAClC,KAAK,IAAI;AACd;;AAGA,SAAgB,qBAAqB,QAAqC,YAAqC;CAC7G,MAAM,WAA2B,CAAC;CAClC,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,eAAe,KAAA,KAAa,MAAM,MAAM,YAAY;EACxD,IAAI,MAAM,SAAS,gBAAgB;EACnC,IAAI,MAAM,MAAM,QAAQ,SAAS,QAAQ;EACzC,MAAM,OAAO,gBAAgB,MAAM,KAAK,OAAO;EAC/C,IAAI,sBAAsB,MAAM,OAAO,gBAAgB,CAAC,CAAC,WAAW,GAAG;EACvE,SAAS,KAAK;GAAE,KAAK,MAAM;GAAK;EAAK,CAAC;CACxC;CACA,OAAO;AACT;AAEA,SAAgB,gBAAgB,WAAmB,UAA2C;CAE5F,OAAO,GAAG,UAAU,GADP,SAAS,GAAG,EACC,CAAC,EAAE,OAAO,GAAG,GAAG,SAAS;AACrD;;;;;;;;;;ACtBA,MAAM,0BAA0B,UAC9B,uBAAuB;CAAE,SAAS;CAAoB,SAAS;CAAc,MAAM;AAAK,CAAC,CAC3F,IAAI,UAAU,cAAc,CAAC,CAAC,CAAC;AAS/B,SAAgB,aAAa,QAAwB,eAAe,IAAY;CAE9E,OAAO;EADa,aAAa,KAErB,KAAK;EACf;EACA;EACA;EACA;EACA;EACA,mBAAmB,OAAO,YAAY,oBAAoB,OAAO,oBAAoB;CACvF,CAAC,CAAC,KAAK,IAAI;AACb;;;;;;;AAQA,SAAgB,gBAAgB,OAA4D;CAC1F,IAAI,CAAC,OAAO,YAAY,CAAC,MAAM,OAAO,OAAO,KAAA;CAC7C,OAAO,MAAM,kBACT;EAAE,UAAU,MAAM;EAAU,OAAO,MAAM;EAAO,iBAAiB,MAAM;CAAgB,IACvF;EAAE,UAAU,MAAM;EAAU,OAAO,MAAM;CAAM;AACrD;AAEA,eAAsB,qBAAqB,SAaf;CAC1B,QAAQ,OAAO,eAAe;CAC9B,IAAI,CAAC,QAAQ,UAAU,GACrB,MAAM,OAAO,uBAAO,IAAI,MAAM,oDAAoD,GAAG,EAAE,MAAM,aAAa,CAAC;CAE7G,MAAM,WAAW,qBACf,QAAQ,UACR,QAAQ,OAAO,mBACf,QAAQ,OAAO,gBAAgB,uBACjC;CACA,IAAI,SAAS,WAAW,GAAG,MAAM,IAAI,MAAM,4DAA4D;CACvG,MAAM,QAAQ,oBAAoB,QAAQ,MAAM,gBAAgB,QAAQ,KAAK,GAAG,QAAQ,SAAS;CACjG,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,oDAAoD;CAGhF,MAAM,YAAY;EAAE,UAAU,MAAM;EAAU,OAAO,MAAM;CAAM;CAMjE,MAAM,cAAc,KAAK,UAAU,QAAQ;CAC3C,MAAM,SAAS,mBACb,QAAQ,cAAc,QAAQ,OAAO,QACrC,SAAS,KAAI,YAAW,QAAQ,IAAI,GACpC,QAAQ,gBACV;CACA,MAAM,gBAAgB,gBAAgB,QAAQ,WAAW,QAAQ;CACjE,MAAM,WAAW,IAAI,gBAAgB;CACrC,MAAM,YAAY,OAAO,SAAS,QAAQ,OAAO,SAAS,KAAK,QAAQ,OAAO,YAAY,IACtF,QAAQ,OAAO,YAAY;CAC/B,MAAM,QAAQ,iBAAiB,SAAS,MAAM,IAAI,aAAa,+BAA+B,cAAc,CAAC,GAAG,SAAS;CACzH,MAAM,SAAS,YAAY,IAAI,CAAC,QAAQ,QAAQ,SAAS,MAAM,CAAC;CAChE,IAAI;CACJ,IAAI;EACF,SAAS,MAAM,YAAY,QAAQ,KAAK;GACtC,QAAQ;GACR,OAAO;GACP,QAAQ,aAAa,QAAQ,QAAQ,QAAQ,MAAM;GACnD,SAAS;GACT,SAAS;GACT,MAAM;GACN,WAAW,QAAQ,OAAO;GAC1B,SAAS;GACT,YAAY,UAAU,UAAU;IAC9B,MAAM,SAAS,MAAM,WAAW,QAAQ,EAAE,EAAE;IAC5C,OAAO;KAAE,GAAG;KAAU,GAAI,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,OAAO;IAAG;GACrF;GACA;GACA,WAAW,QAAQ;GACnB,WAAW,QAAQ;EACrB,CAAC;EACD,OAAO,eAAe;CACxB,SAAS,OAAO;EAGd,OAAO,eAAe;EACtB,MAAM;CACR,UAAU;EACR,aAAa,KAAK;CACpB;CACA,QAAQ,OAAO,eAAe;CAC9B,IAAI,CAAC,QAAQ,UAAU,GACrB,MAAM,OAAO,uBAAO,IAAI,MAAM,oDAAoD,GAAG,EAAE,MAAM,aAAa,CAAC;CAG7G,MAAM,QAAQ,sBAAsB,YADrB,gBAAgB,OAAO,MAAM,QAAQ,OAAO,aAAa,QAAQ,OAAO,mBACvC,GAAQ,QAAQ,QAAQ,uBAAO,IAAI,KAAK,CAAC,GAAG,QAAQ,OAAO,aAAa;CACxH,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,0DAA0D;CACtF,OAAO;EACL;EACA,aAAa,SAAS,KAAI,YAAW,QAAQ,GAAG;EAChD,OAAO;GAAE,UAAU,OAAO;GAAU,OAAO,OAAO;EAAM;EACxD;CACF;AACF;;;;AC1IA,eAAsB,eAAe,MAAiB,IAAqC;CAEzF,OAAO;EAAE;EAAI,SAAA,MADS,KAAK,OAAO,EAAE;CACf;AACvB;AAEA,eAAsB,iBACpB,MACA,OACmD;CACnD,IAAI,CAAC,OAAO,OAAO;CACnB,IAAI,KAAK,MAAM,MAAM,MAAM,IAAI,OAAO;CACtC,MAAM,MAAM,QAAQ;CACpB,IAAI,KAAK,MAAM,KAAK,KAAK,MAAM,MAAM,MAAM,IAAI,OAAO;CACtD,OAAO;AACT;AAEA,SAAgB,mBAAmB,OAAoC;CACrE,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CACrE,OAAO,yDAAyD,KAAK,OAAO,CAAC,GAAG;AAClF;;;ACeA,SAAS,gBAAgB,SAAyB;CAChD,MAAM,QAAQ,QAAQ,QAAQ,GAAG;CACjC,OAAO,UAAU,KAAK,UAAU,QAAQ,MAAM,QAAQ,CAAC;AACzD;AAEA,SAAS,UAAU,OAA4B;CAC7C,OAAO,OAAO,MAAM,SAAS,QAAQ,EAAE;AACzC;AAEA,SAAgB,cAAc,OAA6B;CACzD,OAAO,MAAM,SAAS,aAAa;AACrC;AAEA,SAAgB,qBAAqB,OAA4B;CAE/D,MAAM,EAAE,UAAU,WAAW,GAAG,SADhB,MAAM,WAAW,CAAC;CAElC,OAAO,KAAK,UAAU;EAAE,IAAI,MAAM;EAAI,MAAM,UAAU,KAAK;EAAG;CAAK,CAAC;AACtE;AAEA,SAAgB,oBAAoB,OAAkC;CACpE,OAAO;EAAE,IAAI,MAAM;EAAI,MAAM,UAAU,KAAK;EAAG,UAAU,qBAAqB,KAAK;CAAE;AACvF;AAEA,SAAgB,sBAAsB,UAAwB,OAA6B;CACzF,OAAO,MAAM,OAAO,SAAS,MACxB,UAAU,KAAK,MAAM,SAAS,QAC9B,qBAAqB,KAAK,MAAM,SAAS;AAChD;AAEA,SAAgB,cAAc,QAAoB,IAAqC;CACrF,KAAK,MAAM,SAAS,OAAO,QAAQ,GACjC,IAAI,MAAM,OAAO,IAAI,OAAO;AAGhC;AAEA,SAAgB,gBAAgB,QAAoB,YAA6C;CAC/F,KAAK,MAAM,SAAS,OAAO,QAAQ,GAAG;EACpC,MAAM,OAAO,UAAU,KAAK;EAE5B,IAAI;GADS,MAAM;GAAI,MAAM,SAAS;GAAI;GAAM,gBAAgB,MAAM,EAAE;EAClE,CAAC,CAAC,MAAK,UAAS,UAAU,UAAU,GAAG,OAAO;EACpD,IAAI,KAAK,SAAS,IAAI,YAAY,KAAK,KAAK,SAAS,UAAU,GAAG,OAAO;EACzE,IAAI,eAAe,oCAAoC,gBAAgB,MAAM,EAAE,MAAM,qBAAqB,OAAO;CACnH;AAEF;AAEA,eAAsB,uBAAuB,QAAgC,UAAqE;CAChJ,IAAI,CAAC,UAAU,CAAC,UAAU,OAAO;CACjC,MAAM,UAAU,cAAc,QAAQ,SAAS,EAAE;CACjD,IAAI,CAAC,WAAW,CAAC,cAAc,OAAO,KAAK,CAAC,sBAAsB,UAAU,OAAO,GAAG,OAAO;CAC7F,MAAM,OAAO,OAAO,SAAS,IAAI,EAAE,UAAU,MAAM,CAAC;CACpD,OAAO;AACT;AAEA,SAAgB,sBAAsB,SAMU;CAC9C,IAAI;CACJ,MAAM,OAAoD;EACxD,aAAa;EACb,MAAM,OAAO,IAAY;GACvB,MAAM,WAAiC;IACrC,IAAI;IACJ,WAAW,QAAQ,UAAU;IAC7B,UAAU,QAAQ;GACpB;GACA,IAAI;IACF,MAAM,UAAU,QAAQ,aAAa,SAAS,QAAQ;IACtD,QAAQ;IACR,OAAO,YAAY;KACjB,MAAM,QAAQ;KACd,IAAI,UAAU,IAAI,QAAQ,KAAA;IAC5B;GACF,SAAS,OAAO;IACd,MAAM,WAAW,mBAAmB,KAAK;IACzC,IAAI,CAAC,UAAU,MAAM;IACrB,MAAM,QAAQ,gBAAgB,QAAQ,QAAQ,QAAQ;IACtD,IAAI,CAAC,SAAS,cAAc,KAAK,GAAG,MAAM;IAC1C,MAAM,WAAW,oBAAoB,KAAK;IAC1C,MAAM,QAAQ,OAAO,OAAO,MAAM,IAAI,EAAE,UAAU,KAAK,CAAC;IACxD,MAAM,eAAe,cAAc,QAAQ,QAAQ,MAAM,EAAE;IAC3D,IAAI,CAAC,gBAAgB,CAAC,sBAAsB,UAAU,YAAY,GAAG,MAAM;IAC3E,IAAI;KACF,MAAM,UAAU,QAAQ,aAAa,SAAS,QAAQ;KACtD,KAAK,eAAe;KACpB,QAAQ;KACR,OAAO,YAAY;MACjB,MAAM,QAAQ;MACd,IAAI,UAAU,IAAI,QAAQ,KAAA;KAC5B;IACF,SAAS,QAAQ;KACf,IAAI,cAAc,QAAQ,QAAQ,SAAS,EAAE,KAAK,sBAAsB,UAAU,cAAc,QAAQ,QAAQ,SAAS,EAAE,CAAE,GAC3H,MAAM,QAAQ,OAAO,OAAO,SAAS,IAAI,EAAE,UAAU,MAAM,CAAC;KAE9D,MAAM;IACR;GACF;EACF;CACF;CACA,OAAO;AACT;;;AC7IA,MAAM,eAAe,EAAE,KAAK;CAAC;CAAQ;CAAM;AAAI,CAAC;;AAGhD,MAAM,uBAAuB,EAAE,OAAO;CACpC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY;CACvC,QAAQ;AACV,CAAC,CAAC,CAAC,OAAO;AAEV,MAAM,mBAAmB,EAAE,OAAO;CAChC,UAAU,EAAE,OAAO;CACnB,OAAO,EAAE,OAAO;CAChB,iBAAiB,EAAE,OAAO,CAAC,CAAC,SAAS;AACvC,CAAC,CAAC,CAAC,OAAO;AAEV,MAAa,sBAAsB,EAAE,OAAO;CAC1C,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY;CACvC,QAAQ;CACR,QAAQ,EAAE,OAAO;CACjB,OAAO;;CAEP,SAAS,EAAE,KAAK,CAAC,eAAe,cAAc,CAAC,CAAC,CAAC,QAAQ,aAAa;AACxE,CAAC,CAAC,CAAC,OAAO;AAEV,MAAa,cAAc,aAAa;CACtC,MAAM;CACN,SAAS;CACT,QAAQ,EACN,UAAU,YAAmC,mBAAmB,EAClE;AACF,CAAC;AAED,SAAgB,mBAAmB,OAA2C;CAC5E,MAAM,UAAU,oBAAoB,UAAU,KAAK;CACnD,IAAI,QAAQ,SACV,OAAO;EACL,UAAU,QAAQ,KAAK;EACvB,QAAQ,kBAAkB,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,SAAS;EACvE,QAAQ,gBAAgB,QAAQ,KAAK,MAAM;EAC3C,OAAO,oBAAoB,QAAQ,KAAK,KAAK;EAC7C,SAAS,iBAAiB,QAAQ,KAAK,OAAO;CAChD;CAEF,MAAM,SAAS,qBAAqB,UAAU,KAAK;CACnD,IAAI,CAAC,OAAO,WAAW,CAAC,kBAAkB,OAAO,KAAK,MAAM,GAAG,OAAO,KAAA;CACtE,OAAO;EACL,UAAU,OAAO,KAAK;EACtB,QAAQ,OAAO,KAAK;EACpB,QAAQ;EACR,OAAO,kBAAkB;EACzB,SAAS;CACX;AACF;AAEA,SAAgB,eAAe,OAAgB,kBAA2C,QAAuB;CAC/G,MAAM,SAAS,mBAAmB,KAAK;CACvC,OAAO;EACL,UAAU,QAAQ,YAAY;EAC9B,QAAQ;EACR,QAAQ,QAAQ,UAAU;EAC1B,OAAO,QAAQ,SAAS,kBAAkB;EAC1C,SAAS,QAAQ,WAAW;CAC9B;AACF;AAEA,SAAgB,cAAc,SAAwB,OAIuB;CAC3E,OAAO;EACL,QAAQ;EACR,QAAQ,MAAM,WAAW,KAAA,IAAY,QAAQ,SAAS,gBAAgB,MAAM,MAAM;EAClF,OAAO,MAAM,UAAU,KAAA,IAAY,QAAQ,QAAQ,oBAAoB,MAAM,KAAK;EAClF,SAAS,MAAM,YAAY,KAAA,IAAY,QAAQ,UAAU,iBAAiB,MAAM,OAAO;CACzF;AACF;;;AC7DA,IAAa,sBAAb,MAAiC;CAYF;CAX7B;CACA;CACA;CACA;CACA,aAAqB;CACrB,kBAAyC,QAAQ,QAAQ;CACzD,WAAmB;CACnB,2BAA4B,IAAI,IAA6B;CAC7D,8BAA+B,IAAI,IAAsB;CACzD;CAEA,YAAY,SAYT;EAZ0B,KAAA,UAAA;EAa3B,MAAM,SAAS,eAAe,QAAQ,OAAO,KAAK,GAAG,QAAQ,iBAAiB,MAAM;EACpF,KAAK,WAAW;EAChB,KAAK,SAAS,sBAAsB,KAAK,SAAS,MAAM;EACxD,KAAK,UAAU;GAAE,aAAa;GAAM,OAAO;EAAM;CACnD;CAEA,MAAM,QAAuB;EAC3B,MAAM,EAAE,KAAK,cAAc,QAAQ,aAAa,KAAK;EACrD,IAAI,CAAC,OAAO,CAAC,cAAc,YAAY,CAAC,YAAY,CAAC,QAAQ;GAC3D,KAAK,QAAQ,QAAQ;GACrB,KAAK,QAAQ,aAAa;GAC1B;EACF;EACA,KAAK,aAAa,sBAAsB;GACtC;GACA;GACA,iBAAiB,KAAK,SAAS;GAC/B,WAAU,YAAW,KAAK,eAAe,OAAO;EAClD,CAAC;EACD,IAAI;GACF,KAAK,QAAQ,MAAM,eAAe,KAAK,YAAY,WAAW;GAC9D,KAAK,QAAQ,QAAQ;GACrB,KAAK,QAAQ,cAAc;GAC3B,OAAO,KAAK,QAAQ;EACtB,SAAS,OAAO;GACd,KAAK,QAAQ,QAAQ;GACrB,KAAK,QAAQ,cAAc,KAAK,WAAW,MAAM,KAAK;GACtD,KAAK,QAAQ,aAAa,iBAAiB,QAAQ,MAAM,UAAU;EACrE;CACF;CAEA,MAAM,UAAyB;EAC7B,KAAK,WAAW;EAChB,KAAK,cAAc;EACnB,KAAK,MAAM,cAAc,KAAK,SAAS,OAAO,GAAG,WAAW,sBAAM,IAAI,MAAM,wBAAwB,CAAC;EACrG,KAAK,SAAS,MAAM;EACpB,MAAM,QAAQ,WAAW,CAAC,GAAG,KAAK,WAAW,CAAC;EAC9C,MAAM,KAAK;EACX,MAAM,WAAW,KAAK,YAAY;EAClC,MAAM,UAAU,MAAM,iBAAiB,KAAK,cAAc;GAAE,aAAa,KAAA;GAAW,QAAQ,kBAAkB,CAAC;EAAE,GAAG,KAAK,KAAK;EAC9H,IAAI,YAAY,YAAY,MAAM,uBAAuB,KAAK,QAAQ,QAAQ,QAAQ;EACtF,KAAK,QAAQ,KAAA;EACb,KAAK,QAAQ,QAAQ;EACrB,KAAK,QAAQ,cAAc,KAAK,YAAY,MAAM,KAAK;EACvD,IAAI,YAAY,oBACd,KAAK,QAAQ,aAAa;CAE9B;CAEA,OAAO,WAAiC;EACtC,MAAM,UAAU,aAAa,KAAK,QAAQ,WAAW,KAAK,QAAQ,SAAS,IAAI,SAAS,IAAI,KAAA;EAC5F,MAAM,WAAW,UAAU,KAAK,KAAK,OAAO,IAAI,KAAA;EAChD,OAAO;GACL,UAAU;IAAE,GAAG,KAAK;IAAU,OAAO,EAAE,GAAG,KAAK,SAAS,MAAM;GAAE;GAChE,SAAS;IAAE,GAAG,KAAK;IAAS,aAAa,KAAK,YAAY,MAAM,KAAK,KAAK,QAAQ;GAAY;GAC9F,GAAI,YAAY,EACd,SAAS;IACP;IACA,OAAO,UAAU;IACjB,YAAY,UAAU,OAAO;IAC7B,YAAY,KAAK,SAAS,IAAI,SAAS;IACvC,QAAQ,UAAU,OAAO,SAAS;GACpC,EACF,IAAI,CAAC;EACP;CACF;CAEA,MAAM,eAAe,OAKM;EACzB,QAAQ,gBAAgB,KAAK;EAC7B,MAAM,SAAS,KAAK,gBAAgB,KAAK,YAAY;GACnD,IAAI,KAAK,UAAU,MAAM,OAAO,uBAAO,IAAI,MAAM,wBAAwB,GAAG,EAAE,MAAM,cAAc,CAAC;GACnG,IAAI,KAAK,SAAS,aAAa,MAAM,kBACnC,MAAM,OAAO,uBAAO,IAAI,MAAM,gCAAgC,GAAG,EAAE,MAAM,WAAW,CAAC;GAEvF,MAAM,WAAW,KAAK;GACtB,MAAM,OAAsB;IAC1B,UAAU,KAAK,SAAS,WAAW;IACnC,GAAG,cAAc,KAAK,UAAU,KAAK;GACvC;GACA,IAAI,KAAK,QAAQ,OAAO,MAAM,KAAK,QAAQ,MAAM,KAAK,IAAI;GAC1D,KAAK,WAAW;GAEhB,IAAI;IAAE,KAAK,QAAQ,oBAAoB,KAAK,QAAQ;GAAE,QAAQ,CAAC;GAC/D,KAAK,SAAS;IAAE,GAAG,KAAK;IAAQ,QAAQ;GAAO;GAC/C,IAAI,CAAC,KAAK,YAAY,KAAK,YAAY,SAAS,SAAS,MAAM,KAAK,mBAAmB;GACvF,OAAO;IACL,UAAU,KAAK;IACf,QAAQ,KAAK;IACb,QAAQ,KAAK;IACb,OAAO,EAAE,GAAG,KAAK,MAAM;IACvB,SAAS,KAAK;GAChB;EACF,CAAC;EACD,KAAK,kBAAkB,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC;EACrD,OAAO;CACT;;CAGA,MAAc,qBAAoC;EAChD,IAAI,CAAC,KAAK,SAAS,CAAC,KAAK,YAAY;EACrC,MAAM,QAAQ,KAAK;EACnB,KAAK,QAAQ,KAAA;EACb,MAAM,MAAM,QAAQ;EACpB,IAAI;GACF,KAAK,QAAQ,MAAM,eAAe,KAAK,YAAY,WAAW;GAC9D,KAAK,QAAQ,QAAQ;GACrB,KAAK,QAAQ,cAAc;GAC3B,OAAO,KAAK,QAAQ;EACtB,SAAS,OAAO;GACd,KAAK,QAAQ,QAAQ;GACrB,KAAK,QAAQ,cAAc,KAAK,WAAW,MAAM,KAAK;GACtD,KAAK,QAAQ,aAAa,iBAAiB,QAAQ,MAAM,UAAU;EACrE;CACF;;CAGA,MAAM,aAAa,SAA0B,kBAAkD;EAC7F,OAAO,KAAK,eAAe,EAAE,iBAAiB,CAAC;CACjD;CAEA,MAAM,WAAW,WAAmB,QAAyD;EAC3F,IAAI,CAAC,KAAK,QAAQ,OAAO,MAAM,OAAO,uBAAO,IAAI,MAAM,4BAA4B,GAAG,EAAE,MAAM,cAAc,CAAC;EAC7G,MAAM,UAAU,KAAK,QAAQ,UAAU,IAAI,SAAS;EACpD,IAAI,CAAC,SAAS,MAAM,OAAO,uBAAO,IAAI,MAAM,mBAAmB,GAAG,EAAE,MAAM,YAAY,CAAC;EACvF,MAAM,KAAK,QAAQ,cAAc,QAAQ,SAAS,MAAM;EACxD,OAAO,KAAK,KAAK,OAAO;CAC1B;CAEA,KAAK,SAAiD;EACpD,MAAM,WAAW,KAAK,QAAQ,cAAc,IAAI,OAAO;EACvD,IAAI,CAAC,UAAU,OAAO,OAAO,KAAA;EAC7B,MAAM,OAAO,SAAS,QAAQ;EAC9B,OAAO;GACL,OAAO,SAAS;GAChB,aAAa,SAAS,cAAc,CAAC,GAAG,SAAS,WAAW,IAAI,CAAC;GACjE,QAAQ;IACN,MAAM,SAAS,UAAU,SAAS,cAAc,SAAS,aAAa,OAAO;IAC7E,GAAI,OAAO,SAAS,QAAQ,aAAa,WAAW,EAAE,UAAU,SAAS,OAAO,SAAS,IAAI,CAAC;GAChG;GACA,UAAU,OAAO,SAAS,YAAY,CAAC;GACvC,WAAW,SAAS,aAAa;EACnC;CACF;CAEA,eAAuB,SAAkE;EACvF,IAAI,KAAK,UAAU,OAAO,QAAQ,uBAAO,IAAI,MAAM,oCAAoC,CAAC;EACxF,MAAM,UAAU,KAAK,kBAAkB,OAAO;EAC9C,KAAK,YAAY,IAAI,OAAO;EAC5B,QAAa,WAAW,KAAK,YAAY,OAAO,OAAO,SAAS,KAAK,YAAY,OAAO,OAAO,CAAC;EAChG,OAAO;CACT;CAEA,MAAc,kBAAkB,SAI7B;EACD,MAAM,MAAM,KAAK,QAAQ;EACzB,IAAI,CAAC,KAAK,MAAM,IAAI,MAAM,yCAAyC;EACnE,MAAM,aAAa,KAAK;EACxB,MAAM,aAAa,IAAI,gBAAgB;EACvC,KAAK,SAAS,IAAI,QAAQ,QAAQ,EAAE,CAAC,EAAE,sBAAM,IAAI,MAAM,8CAA8C,CAAC;EACtG,KAAK,SAAS,IAAI,QAAQ,QAAQ,IAAI,UAAU;EAChD,IAAI;GACF,MAAM,WAAW,YAAY,IAAI,CAAC,QAAQ,QAAQ,WAAW,MAAM,CAAC;GACpE,MAAM,UAAU,KAAK,QAAQ,UAAU,IAAI,QAAQ,QAAQ,EAAE;GAM7D,IAAI,kBAAkB,OAAO,GAC3B,MAAM,OAAO,uBAAO,IAAI,MAAM,yEAAyE,GAAG,EAAE,MAAM,mBAAmB,CAAC;GAExI,MAAM,WAAW,qBACf,QAAQ,SAAS,KAAI,aAAY;IAC/B,MAAM;IACN,KAAK,QAAQ;IACb,MAAM;KAAE,QAAQ,EAAE,MAAM,OAAO;KAAG,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,QAAQ;KAAK,CAAC;IAAE;GACpF,EAAE,CACJ;GACA,MAAM,YAAY,MAAM,qBAAqB;IAC3C;IACA,MAAM,KAAK,QAAQ,QAAQ,CAAC;IAC5B,QAAQ,KAAK;IACb,WAAW,QAAQ,QAAQ;IAC3B,UAAU,SAAS,SAAS,IAAI,WAAW,CAAC,GAAG,QAAQ,QAAQ;IAC/D,QAAQ,KAAK,SAAS;IACtB,OAAO,KAAK,SAAS;IACrB,kBAAkB,KAAK,QAAQ,mBAAmB;IAClD,QAAQ;IACR,iBAAiB,KAAK,eAAe,cAAc,KAAK,QAAQ,UAC1D,CAAC,WAAW,KAAK,QAAQ,UAAU,IAAI,QAAQ,QAAQ,EAAE,MAAM;IACrE,KAAK,KAAK,QAAQ,MAAM;GAC1B,CAAC;GACD,OAAO;IAAE,OAAO,UAAU;IAAO,aAAa,UAAU;IAAa,OAAO,UAAU;GAAM;EAC9F,UAAU;GACR,IAAI,KAAK,SAAS,IAAI,QAAQ,QAAQ,EAAE,MAAM,YAAY,KAAK,SAAS,OAAO,QAAQ,QAAQ,EAAE;EACnG;CACF;AACF;AAEA,SAAgB,qBAAqB,MAA4C;CAC/E,IAAI;EAEF,MAAM,QADW,KAAK,IAAI,UACL,CAAC,EAAE,MAAM,QAAQ;EACtC,IAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO,KAAA;EAChF,MAAM,aAAc,MAAkC;EACtD,OAAO,OAAO,eAAe,WAAW,aAAa,KAAA;CACvD,QAAQ;EACN;CACF;AACF;AAEA,eAAsB,UAAU,SAA8B,UAAkB,SAAkB,QAAyC;CACzI,OAAO,eAAe;CACtB,MAAM,OAAO,WAAW,OAAO,YAAY,YAAY,CAAC,MAAM,QAAQ,OAAO,IAAI,UAAqC,CAAC;CACvH,IAAI,aAAa,UACf,OAAO;EAAE,IAAI;EAAM,OAAO,QAAQ,OAAO,OAAO,KAAK,cAAc,WAAW,KAAK,YAAY,KAAA,CAAS;CAAE;CAE5G,IAAI,aAAa,YAAY;EAC3B,IAAI,OAAO,KAAK,qBAAqB,UACnC,OAAO;GAAE,IAAI;GAAO,OAAO;IAAE,MAAM;IAAe,SAAS;GAAU;EAAE;EAEzE,IAAI;GACF,OAAO;IACL,IAAI;IACJ,OAAO,MAAM,QAAQ,eAAe;KAClC,GAAI,KAAK,WAAW,KAAA,IAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;KAC3D,GAAI,KAAK,UAAU,KAAA,IAAY,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;KACxD,GAAI,KAAK,YAAY,KAAA,IAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;KAC9D,kBAAkB,KAAK;IACzB,CAAC;GACH;EACF,SAAS,OAAO;GACd,MAAM,OAAO,iBAAiB,SAAS,UAAU,QAAQ,OAAQ,MAA4B,IAAI,IAAI;GACrG,IAAI,SAAS,YAAY,OAAO;IAAE,IAAI;IAAO,OAAO;KAAE;KAAM,SAAS;IAAgB;GAAE;GACvF,OAAO;IAAE,IAAI;IAAO,OAAO;KAAE,MAAM;KAAU,SAAS;IAAY;GAAE;EACtE;CACF;CACA,IAAI,aAAa,cAAc;EAC7B,IAAI,OAAO,KAAK,cAAc,YAAY,CAAC,KAAK,WAC9C,OAAO;GAAE,IAAI;GAAO,OAAO;IAAE,MAAM;IAAe,SAAS;GAAQ;EAAE;EAEvE,IAAI;GAEF,OAAO;IAAE,IAAI;IAAM,OAAO,MADH,QAAQ,WAAW,KAAK,WAAW,MAAM,KAC1B;GAAK;EAC7C,SAAS,OAAO;GACd,MAAM,OAAO,iBAAiB,SAAS,UAAU,QAAQ,OAAQ,MAA4B,IAAI,IAAI;GACrG,IAAI,SAAS,aAAa,OAAO;IAAE,IAAI;IAAO,OAAO;KAAE;KAAM,SAAS;IAAU;GAAE;GAClF,IAAI,SAAS,eAAe,OAAO;IAAE,IAAI;IAAO,OAAO;KAAE;KAAM,SAAS;IAAW;GAAE;GACrF,IAAI,OAAO,SAAS,OAAO;IAAE,IAAI;IAAO,OAAO;KAAE,MAAM;KAAa,SAAS;IAAO;GAAE;GACtF,OAAO;IAAE,IAAI;IAAO,OAAO;KAAE,MAAM;KAAU,SAAS;IAAU;GAAE;EACpE;CACF;CACA,OAAO;EAAE,IAAI;EAAO,OAAO;GAAE,MAAM;GAAe,SAAS;EAAQ;CAAE;AACvE;;;ACxSA,MAAa,OAAO;AACpB,MAAa,SAAS;CAAC;CAAgB;CAAO;CAAY;CAAU;CAAiB;CAAc;CAAa;CAAU;CAAsB;AAAmB;AAyBnK,eAAsB,MAAM,KAAc,SAAuC,CAAC,GAAkB;CAClG,2BAA2B,KAAK,6BAA6B,WAAW,GAAG,WAAW;CAMtF,MAAM,UAAU,MAAM,qBAAqB,GAAG;CAC9C,IAAI,aAAa,SAAS,+BAA+B;CACzD,MAAM,OAAO;CACb,MAAM,SAAS,MAAM,KAAK,cAAc,KAAK,WAAW;CACxD,MAAM,QAAQ,OAAO,MAAM,UAAU;CACrC,MAAM,SAAS,kBAAkB,OAAO,MAAM,IAAI,OAAO,SAAS;CAClE,MAAM,UAAU,IAAI,oBAAoB;EACtC,QAAQ;EACR,oBAAmB,aAAY,2BAA2B,KAAK,aAAa,QAAQ;EACpF,KAAK,KAAK;EACV;EACA,cAAc,KAAK;EACnB,QAAQ,KAAK;EACb,UAAU,KAAK;EACf,OAAO;GACL,YAAY,mBAAmB,MAAM,IAAI,YAAY,CAAC;GACtD,OAAM,aAAY,MAAM,IAAI,cAAc,QAAQ;EACpD;EACA,eAAe;EACf,wBAAwB,qBAAqB,IAAI;CACnD,CAAC;CACD,MAAM,QAAQ,MAAM;CACpB,IAAI,QAAQ,gBAAgB,OAAO;CACnC,IAAI,aAAa,YAAY;EAAE,MAAM,QAAQ,QAAQ;EAAG,MAAM,OAAO,MAAM;CAAE,GAAG,yBAAyB;CACzG,IAAI,aAAa,gBAAgB,MAAM,cAAc,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU,SAAS,MAAM,CAAC,GAAG,mBAAmB;CACtJ,IAAI,aAAa,sBAAsB,KAAuC;EAC5E,IAAI;EAAa,OAAO;GAAE,IAAI;GAAQ,IAAI;EAAa;EACvD,KAAK,QAAQ;GACX,OAAO,eAAe;GACtB,MAAM,WAAW,QAAQ,OAAO,CAAC,CAAC;GAClC,OAAO;IAAE,UAAU,SAAS;IAAU,QAAQ,CAAC;KAAE,MAAM,CAAC,OAAO;KAAG,OAAO;MAAE,IAAI;MAAQ,IAAI;KAAc;KAAG,SAAS,SAAS;KAC5H,aAAa;MAAE,IAAI;MAAU,IAAI;KAA0B;KAAG,aAAa;IAAK,CAAC;GAAE;EACvF;EACA,MAAM,MAAM,MAAM,OAAO,kBAAkB,QAAQ;GACjD,IAAI,KAAK,WAAW,KAAK,KAAK,OAAO,SAAS,MAAM,IAAI,MAAM,qCAAqC;GACnG,OAAO,eAAe;GACtB,OAAO,QAAQ,eAAe;IAAE,OAAO;IAAO;GAAiB,CAAC;EAClE;CACF,CAAC,GAAG,8BAA8B;AACpC"}
|