@klarkxy/dsh-self-improvement 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.inner.cjs","names":["useSyncExternalStore","useCallback","useRef","captured","useState","useRef","useId"],"sources":["../../dsh-ai-services/src/client-utils.ts","../src/contracts.ts","../src/rpc-result.ts","../src/skills.ts","../src/review-lifetime.ts","../src/client.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\n\nexport interface NativeSurfaceClient {\n sessions: {\n binding?(sessionId: string): { eventSource: { subscribe(listener: () => void): () => void } } | undefined\n }\n uiWorkspace: { current?: { getSnapshot(): { sessionId: string } | undefined; subscribe(listener: () => void): () => void } }\n uiSession: { adapter: { current: { getSnapshot(): { key?: string }; subscribe(listener: () => void): () => void } } }\n locale: { getSnapshot(): { active: string }; subscribe(listener: () => void): () => void }\n connection?: { generation?: { subscribe(listener: () => void): () => void } }\n}\n\n/** The Editor retains its manuscript session separately; native DSH exposes the main-view binding. */\nexport function selectedSessionId(client: Pick<NativeSurfaceClient, 'uiWorkspace' | 'uiSession'>): string {\n return client.uiWorkspace.current\n ? client.uiWorkspace.current.getSnapshot()?.sessionId ?? ''\n : client.uiSession.adapter.current.getSnapshot().key ?? ''\n}\n\n/** Owner props win; native settings only supplies close, so resolve its selected session. */\nexport function useNativeSeat(client: NativeSurfaceClient, props: unknown) {\n const current = useSyncExternalStore(\n useCallback((fn: () => void) => (client.uiWorkspace.current ?? client.uiSession.adapter.current).subscribe(fn), [client]),\n useCallback(() => selectedSessionId(client), [client]),\n () => '',\n )\n const language = useSyncExternalStore(\n useCallback((fn: () => void) => client.locale.subscribe(fn), [client]),\n useCallback(() => client.locale.getSnapshot().active, [client]),\n () => 'en',\n )\n const row = props && typeof props === 'object' ? props as Record<string, unknown> : {}\n const owner = row.owner && typeof row.owner === 'object' ? row.owner as Record<string, unknown> : {}\n const sessionId = typeof row.sessionId === 'string' ? row.sessionId\n : typeof owner.sessionId === 'string' ? owner.sessionId : current\n const requestedLocale = row.locale ?? owner.locale ?? language\n return { sessionId, locale: (String(requestedLocale).startsWith('zh') ? 'zh' : 'en') as 'zh' | 'en',\n hidden: row.hidden === true || owner.hidden === true }\n}\n\n/** Refresh on native log boundaries/reconnect/focus. Read-only settling is bounded to an observed job. */\nexport function useFeatureRefresh(\n client: NativeSurfaceClient, sessionId: string, refresh: () => void,\n working = false, enabled = true,\n): void {\n const refreshRef = useRef(refresh)\n refreshRef.current = refresh\n useEffect(() => {\n if (!enabled) return\n let timer: ReturnType<typeof setTimeout> | undefined\n const queue = () => {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return\n clearTimeout(timer)\n timer = setTimeout(() => refreshRef.current(), 150)\n }\n const source = sessionId ? client.sessions.binding?.(sessionId)?.eventSource : undefined\n const stopEvents = source?.subscribe(queue)\n const stopConnection = client.connection?.generation?.subscribe(queue)\n const visibility = () => { if (document.visibilityState === 'visible') queue() }\n window.addEventListener('focus', queue)\n document.addEventListener('visibilitychange', visibility)\n // Details are collapsed by default; opening an existing panel must get current state.\n document.addEventListener('toggle', queue, true)\n return () => {\n clearTimeout(timer)\n stopEvents?.(); stopConnection?.()\n window.removeEventListener('focus', queue)\n document.removeEventListener('visibilitychange', visibility)\n document.removeEventListener('toggle', queue, true)\n }\n }, [client, sessionId, enabled])\n useEffect(() => {\n if (!enabled || !working) return\n let delay = 250\n const until = Date.now() + 300_000\n let timer: ReturnType<typeof setTimeout>\n const tick = () => {\n if (Date.now() >= until) return\n if (document.visibilityState !== 'hidden') refreshRef.current()\n delay = Math.min(delay * 2, 2000)\n timer = setTimeout(tick, delay)\n }\n timer = setTimeout(tick, delay)\n return () => clearTimeout(timer)\n }, [client, sessionId, working, enabled])\n}\n","/** Own records plus reexported frozen AI/Memory interfaces. */\nimport {\n CHAT_EVENTS_SLOT as FROZEN_CHAT_EVENTS_SLOT,\n projectIdFromCwd as sharedProjectIdFromCwd,\n} from '@klarkxy/dsh-ai-services/contracts'\nimport type {\n AiFeatureScope,\n AiServices,\n AuxiliaryRequest,\n AuxiliaryResult,\n EvidenceRef,\n KnowledgeKind,\n KnowledgeScope,\n MemoryMutationOptions,\n MemoryQuery,\n MemoryRecord,\n MemoryService,\n NewMemoryRecord,\n PurposeSpec,\n ProducerMessageSource,\n RpcResult,\n UsageReceipt,\n} from '@klarkxy/dsh-ai-services/contracts'\n\nexport type {\n AiFeatureScope,\n AiServices,\n AuxiliaryRequest,\n AuxiliaryResult,\n EvidenceRef,\n KnowledgeKind,\n KnowledgeScope,\n MemoryMutationOptions,\n MemoryQuery,\n MemoryRecord,\n MemoryService,\n NewMemoryRecord,\n PurposeSpec,\n ProducerMessageSource,\n RpcResult,\n UsageReceipt,\n}\n\nexport const CHAT_EVENTS_SLOT = FROZEN_CHAT_EVENTS_SLOT\nexport const projectIdFromCwd = sharedProjectIdFromCwd\nexport const SELF_IMPROVEMENT_RPC_CHANNEL = '/dsh-self-improvement'\nexport const SELF_IMPROVEMENT_PLUGIN = '@klarkxy/dsh-self-improvement'\nexport const SELF_IMPROVEMENT_SOURCE_KIND = 'plugin:@klarkxy/dsh-self-improvement' as const\n/** Production activate identity. Core owns the scoped pluginName regex. */\nexport const SELF_IMPROVEMENT_ACTIVATE_ID = SELF_IMPROVEMENT_PLUGIN\nexport const EXTRACT_PURPOSE = 'self-improvement.extract'\nexport const LESSON_INJECTION_SECTION = 'dsh-self-improvement:lessons'\nexport const LESSON_SCHEMA_TAG = 'lesson-schema:1'\nexport const LESSON_SCHEMA_VERSION = 1\nexport const MAX_INJECTED_LESSONS = 5\nexport const MAX_INJECTION_TOKENS = 800\nexport const MAX_PROJECT_ID_CHARS = 32_768\nexport const MAX_RECALL_QUERY_CHARS = 200\n\nexport type SkillStatus = 'preview' | 'accepted' | 'rejected' | 'revoked'\nexport type SkillExportState = 'none' | 'recorded' | 'revoked'\nexport interface SkillAuditEntry { at: number; action: string; detail?: string }\nexport interface SkillSourceRef {\n id: string\n revision: number\n status: MemoryRecord['status']\n scope: KnowledgeScope\n expiresAt?: number\n}\nexport interface SkillRecord {\n id: string\n revision: number\n status: SkillStatus\n lessonIds: string[]\n sources: SkillSourceRef[]\n title: string\n markdown: string\n createdAt: number\n updatedAt: number\n exportState: SkillExportState\n exportedAt?: number\n exportRevokedAt?: number\n exportFilename?: string\n audit: SkillAuditEntry[]\n}\nexport interface SessionWatermark {\n sessionId: string\n seq: number\n projectId?: string\n updatedAt: number\n}\n\nexport type LessonTriggerKind = 'human-correction' | 'verified-tool-fix' | 'manual'\nexport interface LessonTrigger {\n kind: LessonTriggerKind\n evidence: EvidenceRef[]\n titleHint: string\n contentHint: string\n toolName?: string\n}\n\nexport interface LessonInjectPayload {\n source: ProducerMessageSource & {\n kind: typeof SELF_IMPROVEMENT_SOURCE_KIND\n plugin: typeof SELF_IMPROVEMENT_PLUGIN\n form: 'snapshot'\n sections: Array<{ name: string; text: string }>\n }\n content: Array<{ type: 'text'; text: string }>\n}\n\nexport interface PreStepEnter { kind: 'enter'; messages: unknown[]; startsRequestSeries?: true }\nexport type PreStepDecision = { kind: 'reject' } | PreStepEnter\n\nexport interface ReviewSnapshot {\n memoryAvailable: boolean\n memoryMessage?: string\n projectId?: string\n generation: number\n storageFailed: boolean\n lessons: MemoryRecord[]\n skills: SkillRecord[]\n /** True while an extract for this session (or any session, if none requested) is queued or in flight. */\n extracting?: boolean\n}\n\nexport function evidenceWatermark(refs: readonly EvidenceRef[]): string {\n return [...refs].map(ref => `${ref.sessionId}:${ref.seq}:${ref.kind}`).sort().join('|')\n}\n\nexport function sessionCwd(session: unknown): string | undefined {\n if (!session || typeof session !== 'object') return undefined\n const row = session as { meta?: { cwd?: unknown }; header?: { cwd?: unknown } }\n const cwd = row.meta?.cwd ?? row.header?.cwd\n return typeof cwd === 'string' ? cwd : undefined\n}\n\nexport function fail(code: string, message: string): RpcResult<never> {\n return { ok: false, error: { code, message } }\n}\n\nexport const MEMORY_UNAVAILABLE_MESSAGE = '记忆服务不可用。请先单独启用「记忆」插件;启用自我改进不会自动打开记忆。'\nexport const MEMORY_UNAVAILABLE_MESSAGE_EN = 'Memory is unavailable. Enable the Memory plugin separately; turning on self-improvement does not enable Memory.'\n","import type { RpcResult } from './contracts.ts'\n\nexport function unwrap<T>(result: RpcResult<T>): T {\n if (!result.ok) throw new Error(result.error.message)\n return result.value\n}\n","import { SELF_IMPROVEMENT_PLUGIN, type MemoryRecord, type SkillRecord, type SkillSourceRef } from './contracts.ts'\nimport { isExpired, lessonScopeLabel } from './recall.ts'\n\nfunction yamlScalar(value: string | number | boolean): string {\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n return JSON.stringify(value)\n}\n\nexport function skillDownloadName(id: string, title: string): string {\n const slug = title.replace(/[^\\p{L}\\p{N}]+/gu, '-').replace(/^-+|-+$/g, '').slice(0, 40) || 'skill'\n const safe = id.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 12) || 'id'\n return `self-improvement-${slug}-${safe}.md`\n}\n\nexport function skillNameFromTitle(title: string): string {\n return title.replace(/[^\\p{L}\\p{N}]+/gu, '-').replace(/^-+|-+$/g, '').slice(0, 64).toLowerCase() || 'self-improvement-lesson'\n}\n\nexport function skillDescriptionFromLessons(lessons: readonly MemoryRecord[]): string {\n const first = lessons[0]\n const line = (first ? `${first.title}: ${first.content}` : 'Accepted self-improvement lessons.')\n .replace(/[\\r\\n]+/g, ' ')\n .trim()\n return line.slice(0, 200) || 'Accepted self-improvement lessons.'\n}\n\nexport function skillSourcesFromLessons(lessons: readonly MemoryRecord[]): SkillSourceRef[] {\n return lessons.map(lesson => ({\n id: lesson.id,\n revision: lesson.revision,\n status: lesson.status,\n scope: lesson.scope,\n expiresAt: lesson.expiresAt,\n }))\n}\n\nexport function sourcesMatchLive(\n sources: readonly SkillSourceRef[],\n lessons: readonly MemoryRecord[],\n now: number,\n): boolean {\n if (sources.length === 0) return false\n const byId = new Map(lessons.map(lesson => [lesson.id, lesson]))\n for (const source of sources) {\n const live = byId.get(source.id)\n if (!live || live.kind !== 'lesson') return false\n if (live.revision !== source.revision) return false\n if (live.status !== 'active' || source.status !== 'active') return false\n if (isExpired(live, now)) return false\n if (live.scope.kind !== source.scope.kind) return false\n if (live.scope.kind === 'project' && source.scope.kind === 'project' && live.scope.projectId !== source.scope.projectId) {\n return false\n }\n }\n return true\n}\n\nfunction provenanceYaml(lessons: readonly MemoryRecord[]): string[] {\n const lines: string[] = ['provenance:']\n for (const lesson of lessons) {\n lines.push(` - lessonId: ${yamlScalar(lesson.id)}`)\n lines.push(` revision: ${lesson.revision}`)\n lines.push(` scope: ${yamlScalar(lessonScopeLabel(lesson))}`)\n lines.push(` status: ${yamlScalar(lesson.status)}`)\n lines.push(' evidence:')\n if (lesson.evidence.length === 0) {\n lines.push(' []')\n continue\n }\n for (const ref of lesson.evidence) {\n lines.push(` - sessionId: ${yamlScalar(ref.sessionId)}`)\n lines.push(` seq: ${ref.seq}`)\n lines.push(` kind: ${yamlScalar(ref.kind)}`)\n }\n }\n return lines\n}\n\nexport function renderSkillMarkdown(lessons: readonly MemoryRecord[], generatedAt: number): string {\n const title = skillTitleFromLessons(lessons)\n const scopes = [...new Set(lessons.map(lessonScopeLabel))]\n const lines = [\n '---',\n `name: ${yamlScalar(skillNameFromTitle(title))}`,\n `description: ${yamlScalar(skillDescriptionFromLessons(lessons))}`,\n 'source: self-improvement',\n `plugin: ${yamlScalar(SELF_IMPROVEMENT_PLUGIN)}`,\n `generatedAt: ${generatedAt}`,\n ...provenanceYaml(lessons),\n '---',\n '',\n `# ${title.replace(/[\\r\\n]+/g, ' ')}`,\n '',\n '## Instructions',\n '',\n 'Follow these accepted lessons for the scoped work below. They are a reusable skill proposal. They are not a user request and do not authorize edits to AGENTS.md, scripts, or plugins.',\n '',\n `Scope: ${scopes.join(', ') || 'unspecified'}.`,\n '',\n ]\n for (const lesson of lessons) {\n lines.push(`### ${lesson.title.replace(/[\\r\\n]+/g, ' ')}`)\n lines.push('')\n lines.push(lesson.content.replace(/\\r\\n/g, '\\n').trim())\n lines.push('')\n if (lesson.exceptions.length) {\n lines.push('Exceptions for this lesson:')\n for (const item of lesson.exceptions) lines.push(`- ${item.replace(/[\\r\\n]+/g, ' ')}`)\n lines.push('')\n }\n }\n lines.push('Downloading this Markdown is a local save of the proposal. It does not install the skill.')\n lines.push('')\n return lines.join('\\n')\n}\n\nexport function skillTitleFromLessons(lessons: readonly MemoryRecord[]): string {\n if (lessons.length === 1) return lessons[0]!.title.slice(0, 160)\n return `技能草稿(${lessons.length} 条教训)`\n}\n\nexport interface SkillFrontmatter {\n name: string\n description: string\n source: string\n plugin: string\n generatedAt: number\n provenance: Array<{\n lessonId: string\n revision: number\n scope: string\n status: string\n evidence: Array<{ sessionId: string; seq: number; kind: string }>\n }>\n}\n\nfunction parseYamlValue(raw: string): string | number | boolean {\n const trimmed = raw.trim()\n if (trimmed === '[]') return trimmed\n if (trimmed === 'true' || trimmed === 'false') return trimmed === 'true'\n if (/^-?\\d+(?:\\.\\d+)?$/.test(trimmed)) return Number(trimmed)\n if (trimmed.startsWith('\"')) {\n try { return JSON.parse(trimmed) as string } catch { return trimmed.slice(1, -1) }\n }\n return trimmed\n}\n\n/** Parses the YAML subset this package emits (quoted scalars, nested provenance lists). */\nexport function parseSkillFrontmatter(markdown: string): SkillFrontmatter {\n const match = markdown.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n/)\n if (!match) throw new Error('missing YAML frontmatter')\n const body = match[1]!\n const seen = new Set<string>()\n let name = ''\n let description = ''\n let source = ''\n let plugin = ''\n let generatedAt = 0\n const provenance: SkillFrontmatter['provenance'] = []\n let current: SkillFrontmatter['provenance'][number] | undefined\n let evidence: { sessionId: string; seq: number; kind: string } | undefined\n for (const rawLine of body.split(/\\r?\\n/)) {\n if (!rawLine.trim() || rawLine.trim() === '[]') {\n if (rawLine.trim() === '[]' && current && current.evidence.length === 0) continue\n continue\n }\n const keyMatch = rawLine.match(/^([A-Za-z][A-Za-z0-9]*)\\s*:\\s*(.*)$/)\n if (keyMatch && !rawLine.startsWith(' ')) {\n const key = keyMatch[1]!\n if (seen.has(key) && key !== 'provenance') throw new Error(`duplicate YAML key ${key}`)\n seen.add(key)\n const value = parseYamlValue(keyMatch[2] ?? '')\n if (key === 'name') name = String(value)\n else if (key === 'description') description = String(value)\n else if (key === 'source') source = String(value)\n else if (key === 'plugin') plugin = String(value)\n else if (key === 'generatedAt') generatedAt = Number(value)\n continue\n }\n const item = rawLine.match(/^\\s{2}-\\s+lessonId:\\s*(.*)$/)\n if (item) {\n current = { lessonId: String(parseYamlValue(item[1] ?? '')), revision: 0, scope: '', status: '', evidence: [] }\n provenance.push(current)\n evidence = undefined\n continue\n }\n if (!current) continue\n const field = rawLine.match(/^\\s{4}(revision|scope|status|evidence)\\s*:\\s*(.*)$/)\n if (field) {\n const key = field[1]!\n if (key === 'revision') current.revision = Number(parseYamlValue(field[2] ?? ''))\n else if (key === 'scope') current.scope = String(parseYamlValue(field[2] ?? ''))\n else if (key === 'status') current.status = String(parseYamlValue(field[2] ?? ''))\n continue\n }\n const evidenceItem = rawLine.match(/^\\s{6}-\\s+sessionId:\\s*(.*)$/)\n if (evidenceItem) {\n evidence = { sessionId: String(parseYamlValue(evidenceItem[1] ?? '')), seq: 0, kind: '' }\n current.evidence.push(evidence)\n continue\n }\n const evidenceField = rawLine.match(/^\\s{8}(seq|kind)\\s*:\\s*(.*)$/)\n if (evidenceField && evidence) {\n if (evidenceField[1] === 'seq') evidence.seq = Number(parseYamlValue(evidenceField[2] ?? ''))\n else evidence.kind = String(parseYamlValue(evidenceField[2] ?? ''))\n }\n }\n if (!name || !description) throw new Error('skill frontmatter needs name and description')\n return { name, description, source, plugin, generatedAt, provenance }\n}\n\nexport function downloadMarkdown(\n filename: string,\n markdown: string,\n doc: Pick<Document, 'createElement' | 'body'> | undefined = typeof document === 'undefined' ? undefined : document,\n): boolean {\n if (!doc) return false\n const blob = new Blob([markdown], { type: 'text/markdown;charset=utf-8' })\n const url = URL.createObjectURL(blob)\n const anchor = doc.createElement('a')\n anchor.href = url\n anchor.setAttribute('download', filename)\n anchor.rel = 'noopener'\n doc.body.appendChild(anchor)\n anchor.click()\n anchor.remove()\n URL.revokeObjectURL(url)\n return true\n}\n\nexport function exportRevocationCopy(locale: 'zh' | 'en'): string {\n return locale === 'en'\n ? 'Export record revoked. Already downloaded files are not recalled.'\n : '已撤回导出记录。不会收回或删除已下载的文件。'\n}\n\nexport function skillExportStateLabel(record: Pick<SkillRecord, 'exportState'>, locale: 'zh' | 'en'): string {\n if (record.exportState === 'recorded') return locale === 'en' ? 'Download recorded' : '已记录下载'\n if (record.exportState === 'revoked') return locale === 'en' ? 'Download record revoked' : '已撤回下载记录'\n return locale === 'en' ? 'Not downloaded' : '未下载'\n}\n","import type { ReviewSnapshot, RpcResult, SkillRecord } from './contracts.ts'\nimport { unwrap } from './rpc-result.ts'\nimport { downloadMarkdown } from './skills.ts'\n\nexport type ReviewGenerationGate = {\n current: () => number\n next: () => number\n isCurrent: (token: number) => boolean\n}\n\nexport function createReviewGeneration(start = 0): ReviewGenerationGate {\n let current = start\n return {\n current: () => current,\n next: () => {\n current += 1\n return current\n },\n isCurrent: token => token === current,\n }\n}\n\nexport function reviewRequestStillCurrent(input: {\n token: number\n gate: Pick<ReviewGenerationGate, 'isCurrent'>\n signal: AbortSignal\n sessionId: string\n viewSessionId: string\n}): boolean {\n return input.gate.isCurrent(input.token)\n && !input.signal.aborted\n && input.sessionId === input.viewSessionId\n}\n\nexport type ReviewRequest = {\n sessionId: string\n token: number\n signal: AbortSignal\n controller: AbortController\n}\n\n/** Capture session, generation token, and abort lifetime before the first await. */\nexport function beginReviewRequest(\n gate: ReviewGenerationGate,\n sessionId: string,\n previous?: AbortController | null,\n): ReviewRequest {\n previous?.abort()\n const controller = new AbortController()\n const captured = sessionId\n const token = gate.next()\n return { sessionId: captured, token, signal: controller.signal, controller }\n}\n\nexport function disposeReviewRequest(gate: ReviewGenerationGate, controller: AbortController): void {\n controller.abort()\n gate.next()\n}\n\nexport type ReviewRpc = (endpoint: string, payload: unknown, signal?: AbortSignal) => Promise<unknown>\n\nexport function shouldSkipReviewRefresh(input: { busy: boolean; editing?: boolean }): boolean {\n return input.busy || input.editing === true\n}\n\nexport async function loadReviewSnapshot(input: {\n rpc: ReviewRpc\n sessionId: string\n token: number\n gate: Pick<ReviewGenerationGate, 'isCurrent'>\n signal: AbortSignal\n viewSessionId: () => string\n}): Promise<ReviewSnapshot | undefined> {\n const captured = input.sessionId\n const raw = await input.rpc('status', { sessionId: captured }, input.signal)\n if (!reviewRequestStillCurrent({\n token: input.token, gate: input.gate, signal: input.signal, sessionId: captured, viewSessionId: input.viewSessionId(),\n })) return undefined\n return unwrap(raw as RpcResult<ReviewSnapshot>)\n}\n\n/** Read-only status peek; uses an independent signal so it cannot abort an in-flight write. */\nexport async function peekReviewSnapshot(input: {\n rpc: ReviewRpc\n sessionId: string\n token: number\n gate: Pick<ReviewGenerationGate, 'isCurrent'>\n viewSessionId: () => string\n busy: () => boolean\n editing?: () => boolean\n}): Promise<ReviewSnapshot | undefined> {\n if (shouldSkipReviewRefresh({ busy: input.busy(), editing: input.editing?.() === true })) return undefined\n const token = input.token\n if (!input.gate.isCurrent(token) || token === 0) return undefined\n const next = await loadReviewSnapshot({\n rpc: input.rpc,\n sessionId: input.sessionId,\n token,\n gate: input.gate,\n signal: new AbortController().signal,\n viewSessionId: input.viewSessionId,\n })\n if (!next) return undefined\n if (shouldSkipReviewRefresh({ busy: input.busy(), editing: input.editing?.() === true })) return undefined\n return next\n}\n\nexport async function exportSkillIfCurrent(input: {\n rpc: ReviewRpc\n sessionId: string\n token: number\n gate: Pick<ReviewGenerationGate, 'isCurrent'>\n signal: AbortSignal\n viewSessionId: () => string\n record: Pick<SkillRecord, 'id' | 'revision'>\n download?: typeof downloadMarkdown\n}): Promise<'recorded' | 'stale'> {\n const captured = input.sessionId\n const still = () => reviewRequestStillCurrent({\n token: input.token, gate: input.gate, signal: input.signal, sessionId: captured, viewSessionId: input.viewSessionId(),\n })\n const prepared = unwrap(await input.rpc('skill.export', {\n id: input.record.id, expectedRevision: input.record.revision, sessionId: captured,\n }, input.signal) as RpcResult<{ filename: string; markdown: string; skill: SkillRecord }>)\n if (!still()) return 'stale'\n const download = input.download ?? downloadMarkdown\n const started = download(prepared.filename, prepared.markdown)\n if (!still()) return 'stale'\n if (!started) throw new Error('未能开始下载。')\n unwrap(await input.rpc('skill.exported', {\n id: prepared.skill.id, expectedRevision: prepared.skill.revision, filename: prepared.filename, sessionId: captured,\n }, input.signal) as RpcResult<SkillRecord>)\n if (!still()) return 'stale'\n return 'recorded'\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport { useFeatureRefresh, useNativeSeat, type NativeSurfaceClient } from '@klarkxy/dsh-ai-services/client-utils'\nimport { useEffect, useId, useRef, useState } from 'react'\nimport {\n MEMORY_UNAVAILABLE_MESSAGE, MEMORY_UNAVAILABLE_MESSAGE_EN,\n SELF_IMPROVEMENT_RPC_CHANNEL, type MemoryRecord, type ReviewSnapshot, type RpcResult, type SkillRecord,\n} from './contracts.ts'\nimport {\n beginReviewRequest, createReviewGeneration, disposeReviewRequest, exportSkillIfCurrent,\n loadReviewSnapshot, peekReviewSnapshot, reviewRequestStillCurrent,\n} from './review-lifetime.ts'\nimport { unwrap } from './rpc-result.ts'\nimport { exportRevocationCopy, skillExportStateLabel } from './skills.ts'\n\nexport const name = 'dsh-self-improvement-client'\nexport const inject = ['slots', 'connection', 'sessions', 'locale', 'uiWorkspace', 'uiSession'] as const\nexport { unwrap }\nexport {\n beginReviewRequest, createReviewGeneration, disposeReviewRequest, exportSkillIfCurrent,\n loadReviewSnapshot, peekReviewSnapshot, reviewRequestStillCurrent, shouldSkipReviewRefresh,\n} from './review-lifetime.ts'\n\ntype Client = NativeSurfaceClient & {\n connection: {\n rpc: { call(channel: string, endpoint: string, payload: unknown, signal?: AbortSignal): Promise<unknown> }\n generation?: { subscribe(listener: () => void): () => void }\n }\n slots: {\n inject(key: string, callback: () => unknown): () => void\n register(spec: { name: string; id: string; label: string; order: number }, render: unknown): () => void\n }\n}\n\nexport type SeatProps = { sessionId: string; locale: 'zh' | 'en'; hidden: boolean }\n\nexport function parseSeatProps(props: unknown): SeatProps {\n const row = props && typeof props === 'object' ? props as Record<string, unknown> : {}\n const nested = row.owner && typeof row.owner === 'object' ? row.owner as Record<string, unknown> : undefined\n const sessionId = typeof row.sessionId === 'string' && row.sessionId\n ? row.sessionId\n : typeof nested?.sessionId === 'string' ? nested.sessionId : ''\n const locale = row.locale === 'en' || nested?.locale === 'en' ? 'en' : 'zh'\n const hidden = row.hidden === true || nested?.hidden === true\n return { sessionId, locale, hidden }\n}\n\nexport function memoryUnavailableCopy(locale: 'zh' | 'en'): string {\n return locale === 'en' ? MEMORY_UNAVAILABLE_MESSAGE_EN : MEMORY_UNAVAILABLE_MESSAGE\n}\n\nfunction statusLabel(status: MemoryRecord['status'], locale: 'zh' | 'en'): string {\n const zh = { candidate: '候选', active: '已生效', rejected: '已拒绝', superseded: '已替代', revoked: '已撤回', deleted: '已删除' }\n const en = { candidate: 'Candidate', active: 'Active', rejected: 'Rejected', superseded: 'Superseded', revoked: 'Revoked', deleted: 'Deleted' }\n return (locale === 'en' ? en : zh)[status]\n}\n\nconst emptySnapshot = (): ReviewSnapshot => ({\n memoryAvailable: false, memoryMessage: MEMORY_UNAVAILABLE_MESSAGE,\n generation: 0, storageFailed: false, lessons: [], skills: [],\n})\n\nfunction LessonEvidence({ record, locale }: { record: MemoryRecord; locale: 'zh' | 'en' }) {\n return record.evidence.length === 0\n ? <p className=\"si-meta\">{locale === 'en' ? 'No evidence refs.' : '没有依据引用。'}</p>\n : <ul className=\"si-evidence\">\n {record.evidence.map(ref => (\n <li key={`${ref.sessionId}:${ref.seq}:${ref.kind}`}>\n {ref.kind} · {ref.sessionId}#{ref.seq}{ref.excerpt ? ` — ${ref.excerpt}` : ''}\n </li>\n ))}\n </ul>\n}\n\nfunction ConfirmButton(props: { label: string; confirmLabel: string; disabled?: boolean; onConfirm(): void }) {\n const [armed, setArmed] = useState(false)\n const timer = useRef<ReturnType<typeof setTimeout>>(undefined)\n useEffect(() => () => clearTimeout(timer.current), [])\n function disarm() {\n clearTimeout(timer.current)\n setArmed(false)\n }\n return <button type=\"button\" className=\"si-danger\" disabled={props.disabled}\n onClick={() => {\n if (!armed) {\n setArmed(true)\n timer.current = setTimeout(() => setArmed(false), 3000)\n return\n }\n disarm()\n props.onConfirm()\n }}\n onBlur={disarm}>{armed ? props.confirmLabel : props.label}</button>\n}\n\nfunction LessonList(props: {\n lessons: MemoryRecord[]\n locale: 'zh' | 'en'\n busy: boolean\n projectId?: string\n onPromote(record: MemoryRecord): void\n onReject(record: MemoryRecord): void\n onRevoke(record: MemoryRecord): void\n}) {\n const { lessons, locale, busy, projectId, onPromote, onReject, onRevoke } = props\n if (lessons.length === 0) {\n return <p className=\"si-empty\">{locale === 'en' ? 'No lessons yet.' : '还没有教训。'}</p>\n }\n return <ol className=\"si-list\">\n {lessons.map(record => {\n const candidate = record.status === 'candidate'\n const active = record.status === 'active'\n const foreignProject = record.scope.kind === 'project' && Boolean(projectId) && record.scope.projectId !== projectId\n const scope = record.scope.kind === 'global' ? (locale === 'en' ? 'global' : '全局') : record.scope.projectId\n return <li key={record.id} className=\"si-card\" data-status={record.status}>\n <header>\n <h3>{record.title}</h3>\n <span className=\"si-meta\">{statusLabel(record.status, locale)} · {scope}</span>\n </header>\n <p>{record.content}</p>\n <LessonEvidence record={record} locale={locale} />\n <div className=\"si-actions\">\n {active && record.scope.kind === 'project' && !foreignProject ? <button type=\"button\" disabled={busy} onClick={() => onPromote(record)}>\n {locale === 'en' ? 'Promote to global' : '提升为全局'}\n </button> : null}\n {candidate ? <ConfirmButton disabled={busy}\n label={locale === 'en' ? 'Reject' : '拒绝'}\n confirmLabel={locale === 'en' ? 'Confirm reject?' : '确认拒绝?'}\n onConfirm={() => onReject(record)} /> : null}\n {active ? <ConfirmButton disabled={busy}\n label={locale === 'en' ? 'Revoke' : '撤回'}\n confirmLabel={locale === 'en' ? 'Confirm revoke?' : '确认撤回?'}\n onConfirm={() => onRevoke(record)} /> : null}\n {foreignProject\n ? <p className=\"si-meta\">{locale === 'en' ? 'Other project — promotion is blocked here.' : '其他项目的教训,此处不能提升。'}</p>\n : null}\n </div>\n </li>\n })}\n </ol>\n}\n\nfunction SkillList(props: {\n skills: SkillRecord[]\n locale: 'zh' | 'en'\n busy: boolean\n onAccept(record: SkillRecord): void\n onReject(record: SkillRecord): void\n onRevoke(record: SkillRecord): void\n onExport(record: SkillRecord): void\n onUnexport(record: SkillRecord): void\n}) {\n const { skills, locale, busy } = props\n if (skills.length === 0) {\n return <p className=\"si-empty\">{locale === 'en' ? 'No skill drafts.' : '没有技能草稿。'}</p>\n }\n return <ol className=\"si-list\">\n {skills.map(record => (\n <li key={record.id} className=\"si-card\" data-skill-status={record.status} data-export={record.exportState}>\n <header>\n <h3>{record.title}</h3>\n <span className=\"si-meta\">{record.status} · {skillExportStateLabel(record, locale)}</span>\n </header>\n <pre className=\"si-preview\">{record.markdown}</pre>\n <div className=\"si-actions\">\n {record.status === 'preview' ? <button type=\"button\" disabled={busy} onClick={() => props.onAccept(record)}>\n {locale === 'en' ? 'Accept draft' : '接受草稿'}\n </button> : null}\n {record.status === 'preview' ? <button type=\"button\" disabled={busy} onClick={() => props.onReject(record)}>\n {locale === 'en' ? 'Reject draft' : '拒绝草稿'}\n </button> : null}\n {record.status === 'accepted' || record.status === 'preview' ? <button type=\"button\" disabled={busy} onClick={() => props.onExport(record)}>\n {locale === 'en' ? 'Download Markdown' : '下载 Markdown'}\n </button> : null}\n {record.exportState === 'recorded' ? <ConfirmButton disabled={busy}\n label={locale === 'en' ? 'Revoke export record' : '撤回导出记录'}\n confirmLabel={locale === 'en' ? 'Confirm revoke export record?' : '确认撤回导出记录?'}\n onConfirm={() => props.onUnexport(record)} /> : null}\n {record.status === 'accepted' ? <ConfirmButton disabled={busy}\n label={locale === 'en' ? 'Revoke skill' : '撤回技能'}\n confirmLabel={locale === 'en' ? 'Confirm revoke skill?' : '确认撤回技能?'}\n onConfirm={() => props.onRevoke(record)} /> : null}\n </div>\n </li>\n ))}\n </ol>\n}\n\nexport function ReviewPanel({ client, sessionId, locale }: {\n client: Client\n sessionId: string\n locale: 'zh' | 'en'\n}) {\n const tabsId = useId()\n const gate = useRef(createReviewGeneration())\n const sessionRef = useRef(sessionId)\n const workRef = useRef<AbortController | null>(null)\n sessionRef.current = sessionId\n const [tab, setTab] = useState<'lessons' | 'skills'>('lessons')\n const [snapshot, setSnapshot] = useState<ReviewSnapshot>()\n const [busy, setBusy] = useState(false)\n const [note, setNote] = useState('')\n const [error, setError] = useState('')\n const [selected, setSelected] = useState<string[]>([])\n const busyRef = useRef(false)\n busyRef.current = busy\n\n function rpc(endpoint: string, payload: unknown, signal?: AbortSignal): Promise<unknown> {\n return client.connection.rpc.call(SELF_IMPROVEMENT_RPC_CHANNEL, endpoint, payload, signal)\n }\n async function call<T>(endpoint: string, payload: unknown = {}): Promise<T> {\n return unwrap(await rpc(endpoint, payload) as RpcResult<T>)\n }\n\n useEffect(() => {\n const request = beginReviewRequest(gate.current, sessionId, workRef.current)\n workRef.current = request.controller\n setError('')\n setNote('')\n void loadReviewSnapshot({\n rpc,\n sessionId: request.sessionId,\n token: request.token,\n gate: gate.current,\n signal: request.signal,\n viewSessionId: () => sessionRef.current,\n }).then(next => {\n if (next === undefined) return\n setSnapshot(next)\n }).catch(cause => {\n if (!reviewRequestStillCurrent({\n token: request.token,\n gate: gate.current,\n signal: request.signal,\n sessionId: request.sessionId,\n viewSessionId: sessionRef.current,\n })) return\n setError(cause instanceof Error ? cause.message : (locale === 'en' ? 'Unable to read self-improvement state.' : '无法读取自我改进状态。'))\n })\n return () => disposeReviewRequest(gate.current, workRef.current ?? request.controller)\n }, [client, sessionId, locale])\n\n useFeatureRefresh(client, sessionId, () => {\n void peekReviewSnapshot({\n rpc, sessionId: sessionRef.current, token: gate.current.current(), gate: gate.current,\n viewSessionId: () => sessionRef.current, busy: () => busyRef.current, editing: () => false,\n }).then(next => { if (next) setSnapshot(next) }).catch(() => {})\n }, snapshot?.extracting === true, true)\n\n async function action(run: (ctx: { sessionId: string; token: number; signal: AbortSignal }) => Promise<void>) {\n const request = beginReviewRequest(gate.current, sessionId, workRef.current)\n workRef.current = request.controller\n setBusy(true); setNote(''); setError('')\n const still = () => reviewRequestStillCurrent({\n token: request.token,\n gate: gate.current,\n signal: request.signal,\n sessionId: request.sessionId,\n viewSessionId: sessionRef.current,\n })\n try {\n await run({ sessionId: request.sessionId, token: request.token, signal: request.signal })\n } catch (cause) {\n if (!still()) return\n setError(cause instanceof Error ? cause.message : (locale === 'en' ? 'Action failed.' : '操作失败。'))\n const next = await loadReviewSnapshot({\n rpc,\n sessionId: request.sessionId,\n token: request.token,\n gate: gate.current,\n signal: request.signal,\n viewSessionId: () => sessionRef.current,\n }).catch(() => undefined)\n if (next) setSnapshot(next)\n } finally {\n if (still()) setBusy(false)\n }\n }\n\n const data = snapshot ?? emptySnapshot()\n const visibleLessons = data.lessons\n\n const body = <>\n {error ? <p role=\"alert\" className=\"si-error\">{error}</p> : null}\n {note ? <p role=\"status\">{note}</p> : null}\n {data.storageFailed ? <p role=\"alert\">{locale === 'en' ? 'Save failed; previous state was kept.' : '保存失败,已保留上一次成功的状态。'}</p> : null}\n {data.memoryAvailable ? null : <p role=\"alert\" className=\"si-error\">{memoryUnavailableCopy(locale)}</p>}\n <div className=\"si-tabs\" role=\"tablist\" aria-label={locale === 'en' ? 'Self-improvement' : '自我改进'} onKeyDown={event => {\n if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return\n const buttons = [...event.currentTarget.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]')]\n const index = buttons.indexOf(event.target as HTMLButtonElement)\n if (index < 0) return\n event.preventDefault()\n const next = event.key === 'Home' ? 0 : event.key === 'End' ? buttons.length - 1\n : (index + (event.key === 'ArrowRight' ? 1 : -1) + buttons.length) % buttons.length\n buttons[next]?.focus()\n buttons[next]?.click()\n }}>\n {([['lessons', locale === 'en' ? 'Lessons' : '教训'], ['skills', locale === 'en' ? 'Skills' : '技能草稿']] as const).map(([key, label]) => (\n <button key={key} type=\"button\" role=\"tab\" id={`${tabsId}-${key}-tab`}\n aria-controls={`${tabsId}-${key}-panel`} aria-selected={tab === key}\n tabIndex={tab === key ? 0 : -1} onClick={() => setTab(key)}>{label}</button>\n ))}\n </div>\n <div role=\"tabpanel\" id={`${tabsId}-lessons-panel`}\n aria-labelledby={`${tabsId}-lessons-tab`} hidden={tab !== 'lessons'} tabIndex={0}>\n <p className=\"si-meta\">{locale === 'en'\n ? 'Extracted lessons take effect automatically and join prompts; revoke any time to retire one.'\n : '摘录的教训自动生效并进入提示,可随时撤回。'}</p>\n {sessionId ? <button type=\"button\" disabled={busy || !data.memoryAvailable} onClick={() => void action(async ctx => {\n if (!reviewRequestStillCurrent({\n token: ctx.token, gate: gate.current, signal: ctx.signal, sessionId: ctx.sessionId, viewSessionId: sessionRef.current,\n })) return\n await call('extract', { sessionId: ctx.sessionId })\n const next = await loadReviewSnapshot({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal, viewSessionId: () => sessionRef.current,\n })\n if (!next) return\n setSnapshot(next)\n setNote(locale === 'en' ? 'Extracted from this session when evidence was sufficient.' : '已按明确依据尝试摘录。')\n })}>{locale === 'en' ? 'Extract from this session' : '从本会话摘录'}</button> : null}\n <LessonList\n lessons={visibleLessons}\n locale={locale}\n busy={busy || !data.memoryAvailable}\n projectId={data.projectId}\n onPromote={record => void action(async ctx => {\n await call('accept', { id: record.id, expectedRevision: record.revision, scope: 'global', sessionId: ctx.sessionId })\n const next = await loadReviewSnapshot({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal, viewSessionId: () => sessionRef.current,\n })\n if (next) setSnapshot(next)\n })}\n onReject={record => void action(async ctx => {\n await call('reject', { id: record.id, expectedRevision: record.revision, sessionId: ctx.sessionId })\n const next = await loadReviewSnapshot({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal, viewSessionId: () => sessionRef.current,\n })\n if (next) setSnapshot(next)\n })}\n onRevoke={record => void action(async ctx => {\n await call('revoke', { id: record.id, expectedRevision: record.revision, sessionId: ctx.sessionId })\n const next = await loadReviewSnapshot({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal, viewSessionId: () => sessionRef.current,\n })\n if (next) setSnapshot(next)\n })}\n />\n </div>\n <div role=\"tabpanel\" id={`${tabsId}-skills-panel`} aria-labelledby={`${tabsId}-skills-tab`} hidden={tab !== 'skills'} tabIndex={0}>\n {skillManagement()}\n </div>\n </>\n\n function skillManagement() {\n return <>\n <fieldset className=\"si-select\" disabled={busy || !data.memoryAvailable}>\n <legend>{locale === 'en' ? 'Active lessons for a skill draft' : '从已生效的教训生成草稿'}</legend>\n {data.lessons.filter(record => record.status === 'active').map(record => (\n <label key={record.id}>\n <input type=\"checkbox\" checked={selected.includes(record.id)}\n onChange={event => setSelected(current => event.target.checked ? [...current, record.id] : current.filter(id => id !== record.id))} />\n {record.title}\n </label>\n ))}\n {data.lessons.some(record => record.status === 'active') ? null\n : <p className=\"si-meta\">{locale === 'en' ? 'No active lessons yet.' : '还没有已生效的教训。'}</p>}\n </fieldset>\n <button type=\"button\" disabled={busy || selected.length === 0 || !data.memoryAvailable} onClick={() => void action(async ctx => {\n await call('skill.preview', { lessonIds: selected, sessionId: ctx.sessionId })\n const next = await loadReviewSnapshot({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal, viewSessionId: () => sessionRef.current,\n })\n if (!next) return\n setSnapshot(next)\n setTab('skills')\n })}>{locale === 'en' ? 'Preview skill Markdown' : '预览技能 Markdown'}</button>\n <SkillList\n skills={data.skills}\n locale={locale}\n busy={busy}\n onAccept={record => void action(async ctx => {\n await call('skill.accept', { id: record.id, expectedRevision: record.revision, sessionId: ctx.sessionId })\n const next = await loadReviewSnapshot({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal, viewSessionId: () => sessionRef.current,\n })\n if (next) setSnapshot(next)\n })}\n onReject={record => void action(async ctx => {\n await call('skill.reject', { id: record.id, expectedRevision: record.revision, sessionId: ctx.sessionId })\n const next = await loadReviewSnapshot({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal, viewSessionId: () => sessionRef.current,\n })\n if (next) setSnapshot(next)\n })}\n onRevoke={record => void action(async ctx => {\n await call('skill.revoke', { id: record.id, expectedRevision: record.revision, sessionId: ctx.sessionId })\n const next = await loadReviewSnapshot({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal, viewSessionId: () => sessionRef.current,\n })\n if (next) setSnapshot(next)\n })}\n onExport={record => void action(async ctx => {\n const result = await exportSkillIfCurrent({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal,\n viewSessionId: () => sessionRef.current, record,\n })\n if (result !== 'recorded') return\n const next = await loadReviewSnapshot({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal, viewSessionId: () => sessionRef.current,\n })\n if (!next) return\n setSnapshot(next)\n setNote(locale === 'en' ? 'Browser download started. Destination is chosen in the save dialog.' : '已开始浏览器下载,保存位置由系统对话框决定。')\n })}\n onUnexport={record => void action(async ctx => {\n await call('skill.unexport', { id: record.id, expectedRevision: record.revision, sessionId: ctx.sessionId })\n const next = await loadReviewSnapshot({\n rpc, sessionId: ctx.sessionId, token: ctx.token, gate: gate.current, signal: ctx.signal, viewSessionId: () => sessionRef.current,\n })\n if (!next) return\n setSnapshot(next)\n setNote(exportRevocationCopy(locale))\n })}\n />\n </>\n }\n\n return <section className=\"si-settings\" data-testid=\"self-improvement-settings\" data-session={sessionId || undefined}>\n {sessionId ? null : <p className=\"si-meta\">{locale === 'en'\n ? 'Select a session to view lessons for the current project.'\n : '选择一个会话后可查看当前项目的教训。'}</p>}\n {body}\n </section>\n}\n\nconst styles = `\n.si-settings{max-width:760px;color:inherit;font:400 var(--font-size-2,14px)/1.5 var(--default-font-family,system-ui,sans-serif)}\n.si-settings{display:grid;gap:16px}\n.si-settings p{margin:0;line-height:1.5}\n.si-meta,.si-empty{font-size:var(--font-size-1,13px);color:var(--gray-11,inherit)}\n.si-error{color:var(--red-11,#b42318)}\n.si-card{display:grid;gap:8px;padding:12px 14px;border:1px solid var(--gray-6,color-mix(in srgb,currentColor 15%,transparent));border-radius:12px}\n.si-card h3{margin:0;font-size:var(--font-size-3,16px);font-weight:600}\n.si-list{margin:0;padding:0;list-style:none}\n.si-evidence{margin:0;padding-left:1.2em;font-size:var(--font-size-1,13px)}\n.si-actions{display:flex;flex-wrap:wrap;gap:8px}\n.si-settings button:not([role=\"tab\"]){min-height:34px;padding:6px 12px;border:1px solid color-mix(in srgb,currentColor 25%,transparent);border-radius:8px;background:transparent;color:inherit;cursor:pointer;font:inherit;justify-self:start;transition:background-color 150ms ease,color 150ms ease,border-color 150ms ease,box-shadow 150ms ease,transform 150ms ease}\n.si-settings button:not([role=\"tab\"]):hover:not(:disabled){background:var(--gray-3,color-mix(in srgb,currentColor 6%,transparent));border-color:color-mix(in srgb,currentColor 35%,transparent)}\n.si-settings button:not([role=\"tab\"]):active:not(:disabled){transform:scale(.97)}\n.si-danger:hover:not(:disabled){border-color:var(--red-11,#b42318);color:var(--red-11,#b42318);background:color-mix(in srgb,var(--red-11,#b42318) 8%,transparent)}\n.si-settings button:disabled{opacity:.45;cursor:not-allowed}\n.si-tabs{display:flex;gap:20px;border-bottom:1px solid var(--gray-6,color-mix(in srgb,currentColor 15%,transparent))}\n.si-tabs button[role=\"tab\"]{padding:8px 0;border:0;border-bottom:2px solid transparent;border-radius:0;background:transparent;color:var(--gray-11,inherit);cursor:pointer;font:inherit;transition:color 150ms ease,border-color 150ms ease}\n.si-tabs button[role=\"tab\"]:hover{color:inherit}\n.si-tabs button[aria-selected=\"true\"]{border-bottom-color:var(--accent-9,#3b82f6);color:var(--accent-11,inherit);font-weight:600}\n.si-settings [role=\"tabpanel\"]{border-radius:12px}\n.si-settings :focus-visible{outline:2px solid var(--accent-9,currentColor);outline-offset:3px}\n.si-preview{margin:0;padding:8px 10px;border-radius:8px;background:var(--gray-2,color-mix(in srgb,currentColor 4%,transparent));white-space:pre-wrap;overflow:auto;max-height:240px;font:400 var(--font-size-1,13px)/1.45 var(--code-font-family,ui-monospace,monospace)}\n.si-select{margin:0;border:1px solid var(--gray-6,color-mix(in srgb,currentColor 15%,transparent));border-radius:10px;padding:8px 12px;display:grid;gap:6px}\n.si-select label{display:flex;gap:8px;align-items:flex-start}\n@media(prefers-reduced-motion:reduce){.si-settings button{transition:none}}\n`\n\nexport function reviewPanelKey(sessionId: string, locale: 'zh' | 'en'): string {\n return `${sessionId}:${locale}`\n}\n\nexport function SelfImprovementSettings({ client, props }: { client: Client; props: unknown }) {\n const seat = useNativeSeat(client, props)\n return <ReviewPanel key={reviewPanelKey(seat.sessionId, seat.locale)} client={client} sessionId={seat.sessionId} locale={seat.locale} />\n}\n\nexport function apply(ctx: Context): void {\n const client = ctx as unknown as Client\n ctx.effect(() => {\n if (typeof document === 'undefined') return () => {}\n const style = document.createElement('style')\n style.setAttribute('data-plugin', '@klarkxy/dsh-self-improvement')\n style.textContent = styles\n document.head.appendChild(style)\n return () => style.remove()\n }, 'self-improvement.styles')\n ctx.effect(() => client.slots.inject('settings.section', () => client.slots.register({\n name: 'settings.section', id: 'self-improvement', order: 85, label: '自我改进',\n }, (props: unknown) => <SelfImprovementSettings client={client} props={props} />)), 'self-improvement.settings')\n}\n"],"mappings":"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"}