@klarkxy/dsh-git-commit 0.1.3 → 0.1.5
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 +44 -16
- package/docs/README.zh-CN.md +28 -11
- package/lib/client.inner.cjs +923 -152
- package/lib/client.inner.cjs.map +1 -1
- package/lib/client.js +923 -152
- package/lib/contracts.d.ts +77 -2
- package/lib/contracts.js +38 -1
- package/lib/contracts.js.map +1 -1
- package/lib/index.d.ts +21 -7
- package/lib/index.js +139 -42
- package/lib/index.js.map +1 -1
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +20 -6
- package/lib/contracts2.d.ts +0 -54
package/lib/client.inner.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.inner.cjs","names":["useState","useRef","useAnchoredPosition","useCallback","Tooltip","createPortal"],"sources":["../src/contracts.ts","../src/client.tsx"],"sourcesContent":["/** Browser-safe contracts. Shared RPC/result types stay on @klarkxy/dsh-ai-services. */\nexport type { RpcResult } from '@klarkxy/dsh-ai-services/contracts'\n\nexport const PLUGIN_NAME = '@klarkxy/dsh-git-commit'\nexport const FEATURE_ID = 'git-commit'\nexport const PURPOSE_ID = 'git-commit.plan'\nexport const RPC_CHANNEL = '/dsh-git-commit'\nexport const GIT_COMMIT_CLIENT_SERVICE = 'dshGitCommitClient'\nexport const PROMPT_VERSION = 'git-commit.v1'\nexport const SCHEMA_VERSION = 'commit-plan-json.v1'\nexport const CONTRACT_VERSION = 1\n\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 2048\n/** Total character budget for the change manifest sent to the model. */\nexport const MAX_MANIFEST_CHARS = 48_000\n/** Per-file preview cap for untracked files. */\nexport const MAX_UNTRACKED_PREVIEW_CHARS = 2_000\n/** Recent commit subjects supplied as style reference. */\nexport const RECENT_LOG_COUNT = 10\n/** Hard cap for one generated commit message line. */\nexport const MAX_MESSAGE_CHARS = 120\n/** git subprocess timeout. */\nexport const GIT_TIMEOUT_MS = 30_000\n\nexport interface CommitModelInfo {\n readonly provider: string\n readonly model: string\n /** 'purpose' means the user configured an AI-services route; 'default' means the fallback default model. */\n readonly source: 'override' | 'purpose' | 'default'\n}\n\nexport interface GitCommitStatus {\n readonly available: boolean\n /** Machine-readable reason when unavailable: 'no-session' | 'no-cwd' | 'not-a-repo' | 'no-git'. */\n readonly reason?: string\n readonly detail?: string\n readonly root?: string\n readonly branch?: string\n readonly workspace: { readonly files: number }\n readonly model?: CommitModelInfo\n}\n\nexport interface CommitGroupResult {\n readonly hash: string\n readonly message: string\n readonly files: readonly string[]\n}\n\nexport interface CommitRunResult {\n readonly branch: string\n readonly commits: readonly CommitGroupResult[]\n /** True when the model plan was unavailable and a single fallback commit was used. */\n readonly fallback: boolean\n readonly model?: CommitModelInfo\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { Tooltip, useAnchoredPosition, useDismissOnOutsidePointer } from '@deepseek-ai/dsh-client-ui-primitives'\nimport {\n GIT_COMMIT_CLIENT_SERVICE, RPC_CHANNEL, type CommitRunResult, type GitCommitStatus, type RpcResult,\n} from './contracts.ts'\n\nexport const name = 'dsh-git-commit-client'\nexport const inject = ['slots', 'connection', 'locale'] as const\n\nconst NS = 'dsh-git-commit.action'\n\nconst zh = {\n action: '提交',\n title: '提交到 Git',\n commitAction: '分次提交全部工作区修改',\n files: '个文件',\n model: '模型',\n modelDefault: '默认模型',\n modelCustom: 'AI 服务配置',\n running: '正在整理修改并分次提交…',\n done: '已创建提交',\n fallback: '模型不可用,已合并为单个提交',\n noWorkspace: '工作区没有修改',\n unavailable: '不可用',\n reasonNoRepo: '当前目录不在 Git 仓库中',\n reasonNoGit: '未找到 git 命令',\n reasonNoCwd: '会话没有工作目录',\n reasonNoSession: '会话不在线',\n sessionRunning: '会话正在运行,提交已暂停',\n refresh: '刷新',\n failed: '操作失败',\n close: '关闭',\n}\n\nconst en: Record<keyof typeof zh, string> = {\n action: 'Commit',\n title: 'Commit to Git',\n commitAction: 'Commit all workspace changes',\n files: 'files',\n model: 'Model',\n modelDefault: 'default model',\n modelCustom: 'AI services route',\n running: 'Organizing changes into commits…',\n done: 'Commits created',\n fallback: 'Model unavailable; used a single commit',\n noWorkspace: 'No workspace changes',\n unavailable: 'Unavailable',\n reasonNoRepo: 'Current directory is not inside a Git repository',\n reasonNoGit: 'git executable not found',\n reasonNoCwd: 'Session has no working directory',\n reasonNoSession: 'Session is not live',\n sessionRunning: 'Session is running; commits paused',\n refresh: 'Refresh',\n failed: 'Operation failed',\n close: 'Close',\n}\n\ntype Key = keyof typeof zh\ntype Translate = (key: Key) => string\n\ninterface ConnectionLike {\n rpc: { call(channel: string, endpoint: string, payload: unknown): Promise<unknown> }\n}\n\ninterface SessionSnapshotLike {\n running?: boolean\n}\n\ninterface UseSessionLike {\n <T>(selector: (snapshot: SessionSnapshotLike) => T): T\n}\n\nexport interface GitCommitActionProps {\n sessionId: string\n useSession: UseSessionLike\n call: (endpoint: string, payload: unknown) => Promise<unknown>\n t: Translate\n}\n\nasync function rpc<T>(call: GitCommitActionProps['call'], endpoint: string, payload: unknown): Promise<T> {\n const result = await call(endpoint, payload) as RpcResult<T> | undefined\n if (!result || result.ok !== true) {\n throw new Error(result && 'error' in result ? result.error.message : 'request failed')\n }\n return result.value\n}\n\nfunction reasonText(t: Translate, status: GitCommitStatus): string {\n switch (status.reason) {\n case 'not-a-repo': return t('reasonNoRepo')\n case 'no-git': return t('reasonNoGit')\n case 'no-cwd': return t('reasonNoCwd')\n case 'no-session': return t('reasonNoSession')\n default: return t('unavailable')\n }\n}\n\nfunction GitBranchIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"4.5\" cy=\"3.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <circle cx=\"4.5\" cy=\"12.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <circle cx=\"11.5\" cy=\"6.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M4.5 5.1v5.8\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M11.5 8.1c0 2-1.6 2.9-3.4 3\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n </svg>\n )\n}\n\nexport function GitCommitAction({ sessionId, useSession, call, t }: GitCommitActionProps) {\n const [open, setOpen] = useState(false)\n const [status, setStatus] = useState<GitCommitStatus>()\n const [loading, setLoading] = useState(false)\n const [running, setRunning] = useState(false)\n const [result, setResult] = useState<CommitRunResult | null>(null)\n const [error, setError] = useState<string | null>(null)\n const rootRef = useRef<HTMLDivElement>(null)\n const triggerRef = useRef<HTMLButtonElement>(null)\n const panelRef = useRef<HTMLDivElement>(null)\n const generationRef = useRef(0)\n const position = useAnchoredPosition({ open, anchorRef: triggerRef, panelRef, gap: 5, margin: 16 })\n const sessionRunning = useSession(snapshot => snapshot.running === true)\n\n const changeOpen = useCallback((next: boolean) => {\n setOpen(next)\n if (next) {\n setResult(null)\n setError(null)\n }\n }, [])\n\n useDismissOnOutsidePointer(rootRef, open, changeOpen, panelRef)\n\n useEffect(() => {\n generationRef.current += 1\n setOpen(false)\n setStatus(undefined)\n setResult(null)\n setError(null)\n setRunning(false)\n }, [sessionId])\n\n const loadStatus = useCallback(async () => {\n const generation = generationRef.current\n setLoading(true)\n setError(null)\n try {\n const next = await rpc<GitCommitStatus>(call, 'status', { sessionId })\n if (generationRef.current !== generation) return\n setStatus(next)\n } catch (reason) {\n if (generationRef.current !== generation) return\n setStatus(undefined)\n setError(reason instanceof Error ? reason.message : String(reason))\n } finally {\n if (generationRef.current === generation) setLoading(false)\n }\n }, [call, sessionId])\n\n useEffect(() => {\n if (!open) return\n void loadStatus()\n }, [open, loadStatus])\n\n useEffect(() => {\n if (!open) return\n const dismiss = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return\n event.preventDefault()\n changeOpen(false)\n triggerRef.current?.focus()\n }\n document.addEventListener('keydown', dismiss)\n return () => document.removeEventListener('keydown', dismiss)\n }, [open, changeOpen])\n\n const runCommit = useCallback(async () => {\n const generation = generationRef.current\n setRunning(true)\n setResult(null)\n setError(null)\n try {\n const value = await rpc<CommitRunResult>(call, 'commit', { sessionId })\n if (generationRef.current !== generation) return\n setResult(value)\n const next = await rpc<GitCommitStatus>(call, 'status', { sessionId }).catch(() => undefined)\n if (generationRef.current !== generation) return\n if (next) setStatus(next)\n } catch (reason) {\n if (generationRef.current !== generation) return\n setError(reason instanceof Error ? reason.message : String(reason))\n } finally {\n if (generationRef.current === generation) setRunning(false)\n }\n }, [call, sessionId])\n\n const available = status?.available === true\n const workspaceCount = status?.workspace.files ?? 0\n const canCommit = available && !running && !sessionRunning && workspaceCount > 0\n const modelLabel = status?.model\n ? `${status.model.provider}/${status.model.model} · ${status.model.source === 'purpose' || status.model.source === 'override' ? t('modelCustom') : t('modelDefault')}`\n : undefined\n\n return (\n <div ref={rootRef} className=\"gcm-root\">\n <style>{css}</style>\n <Tooltip label={t('title')} side=\"bottom\" gap={4}>\n <button\n type=\"button\"\n ref={triggerRef}\n className=\"gcm-trigger\"\n aria-label={t('title')}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n onClick={() => changeOpen(!open)}\n >\n <GitBranchIcon />\n <span className=\"gcm-triggerLabel\">{t('action')}</span>\n </button>\n </Tooltip>\n {open && createPortal(\n <div\n ref={panelRef}\n className=\"gcm-panel\"\n style={position ?? { visibility: 'hidden', left: 0, top: 0 }}\n role=\"dialog\"\n tabIndex={-1}\n aria-label={t('title')}\n >\n <div className=\"gcm-body\">\n <div className=\"gcm-header\">\n <span className=\"gcm-title\">{t('title')}</span>\n {status?.branch ? <span className=\"gcm-branch\">{status.branch}</span> : null}\n <button type=\"button\" className=\"gcm-iconButton\" aria-label={t('refresh')}\n disabled={loading || running} onClick={() => void loadStatus()}>⟳</button>\n </div>\n {error !== null && <p className=\"gcm-error\" role=\"alert\">{error}</p>}\n {status && !available && <p className=\"gcm-notice\" role=\"status\">{reasonText(t, status)}</p>}\n {available && (\n <>\n {modelLabel ? <p className=\"gcm-meta\">{t('model')}: {modelLabel}</p> : null}\n <button type=\"button\" className=\"gcm-action gcm-primary\"\n disabled={!canCommit}\n onClick={() => void runCommit()}>\n {t('commitAction')}({workspaceCount} {t('files')})\n </button>\n {workspaceCount === 0 && <p className=\"gcm-notice\">{t('noWorkspace')}</p>}\n {sessionRunning && <p className=\"gcm-notice\">{t('sessionRunning')}</p>}\n </>\n )}\n {running && <p className=\"gcm-notice\" role=\"status\">{t('running')}</p>}\n {result && (\n <div className=\"gcm-result\">\n <p className=\"gcm-meta\">{t('done')} · {result.branch}</p>\n <ul className=\"gcm-commits\">\n {result.commits.map(commit => (\n <li key={commit.hash || commit.message}>\n <code>{commit.hash}</code> {commit.message}\n </li>\n ))}\n </ul>\n {result.fallback && <p className=\"gcm-notice\">{t('fallback')}</p>}\n </div>\n )}\n </div>\n </div>,\n document.body,\n )}\n </div>\n )\n}\n\nconst css = `\n.gcm-root{position:relative;display:inline-flex}\n.gcm-trigger{min-height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:none;border:0;border-radius:6px;align-items:center;gap:5px;padding:3px 7px;font-size:12px;display:inline-flex}\n.gcm-trigger:hover,.gcm-trigger:focus-visible{color:var(--dsw-alias-label-primary)}\n.gcm-triggerLabel{white-space:nowrap}\n.gcm-panel{--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);z-index:100;box-sizing:border-box;width:min(360px,100vw - 32px);max-height:min(560px,100vh - 32px);box-shadow:var(--dsw-elevation-prominent);border:0;border-radius:12px;display:flex;flex-direction:column;position:fixed;overflow:hidden;color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5;font-family:var(--default-font-family,system-ui,sans-serif)}\n.gcm-panel::before{content:\"\";z-index:-1;background:var(--dsw-specific-menu);backdrop-filter:var(--dsw-menu-backdrop-filter);border-radius:12px;position:absolute;inset:0}\n.gcm-body{display:grid;gap:8px;padding:12px 14px 14px;overflow-y:auto}\n.gcm-header{display:flex;align-items:center;gap:8px}\n.gcm-title{font-weight:600}\n.gcm-branch{color:var(--dsw-alias-label-caption);overflow-wrap:anywhere;font-size:12px}\n.gcm-iconButton{margin-left:auto;border:0;background:none;color:var(--dsw-alias-label-tertiary);cursor:pointer;font-size:14px;padding:2px 6px;border-radius:6px}\n.gcm-iconButton:hover:not(:disabled){color:var(--dsw-alias-label-primary)}\n.gcm-iconButton:disabled{opacity:.45;cursor:not-allowed}\n.gcm-action{--dsw-elevation-stroke-color:var(--dsw-alias-border-l2);display:block;width:100%;text-align:left;padding:7px 10px;border:0;box-shadow:var(--dsw-elevation-stroke);border-radius:8px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer}\n.gcm-action:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2)}\n.gcm-action:disabled{opacity:.45;cursor:not-allowed}\n.gcm-primary{--dsw-elevation-stroke-color:var(--dsw-alias-brand-primary)}\n.gcm-meta{margin:0;font-size:12px;color:var(--dsw-alias-label-caption);overflow-wrap:anywhere}\n.gcm-notice{margin:0;font-size:12px;color:var(--dsw-alias-label-secondary)}\n.gcm-error{margin:0;font-size:12px;color:var(--dsw-alias-state-error-primary)}\n.gcm-result{display:grid;gap:4px}\n.gcm-commits{margin:0;padding-left:18px;display:grid;gap:2px;font-size:12px;overflow-wrap:anywhere}\n.gcm-commits code{font-size:12px;background:var(--dsw-alias-bg-layer-2);padding:0 4px;border-radius:4px}\n`\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context { dshGitCommitClient: { active: boolean } }\n}\n\ntype Client = Context & {\n connection: ConnectionLike\n slots: {\n inject(key: string, callback: () => unknown): () => void\n register(spec: { name: string; id: string; order: number; locale: string; inject: () => unknown }, render: unknown): () => void\n }\n locale: { register(ns: string, locales: { zh: Record<string, string>; en: Record<string, string> }): () => void }\n}\n\nexport function apply(ctx: Context): void {\n const client = ctx as unknown as Client\n ctx.provide(GIT_COMMIT_CLIENT_SERVICE, { active: true })\n ctx.effect(() => client.locale.register(NS, { zh: { ...zh }, en: { ...en } }), 'git-commit.locale')\n ctx.effect(() => client.slots.inject('conversation.session.header.actions', () => client.slots.register(\n {\n name: 'conversation.session.header.actions',\n id: 'git-commit',\n order: 10,\n locale: NS,\n inject: () => ({\n call: (endpoint: string, payload: unknown) => client.connection.rpc.call(RPC_CHANNEL, endpoint, payload),\n }),\n },\n GitCommitAction,\n )), 'git-commit.slot')\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.inner.cjs","names":["useState","useRef","useAnchoredPosition","useCallback","Tooltip","Button","createPortal","IconRefreshOutlineRegular","Tag","useSyncExternalStore","Switch"],"sources":["../../dsh-plugin-kit/src/model-menu.ts","../../dsh-plugin-kit/lib/official-ui.js","../src/contracts.ts","../src/client.tsx"],"sourcesContent":["/**\n * Shared plugin-page model menu.\n *\n * A feature plugin's own settings row exposes a model select. An empty\n * selection means the host default chat model for that feature's own call.\n *\n * Browser-safe and React-optional: pure helpers live here so hosts and clients\n * share one catalog contract without bundling React into the host build.\n */\nimport { useEffect, useState } from 'react'\nimport type { ModelRoute } from './contracts.ts'\n\n/** One selectable model. `efforts` are the advertised reasoning efforts. */\nexport interface ModelMenuChoice {\n readonly provider: string\n readonly model: string\n readonly label: string\n readonly efforts: ReadonlyArray<{ id: string; name: string }>\n}\n\n/** The stored selection. Empty provider/model means \"follow the default\". */\nexport type ModelMenuRoute = ModelRoute\n\n/** The catalog face this helper needs; stays structural so hosts may add more. */\nexport interface ModelCatalogClient {\n readonly remote?: {\n readonly session?: { readonly modelCatalog?: () => Promise<unknown> }\n }\n}\n\nconst KEY_SEPARATOR = '\\u001f'\n\nexport function modelMenuChoiceKey(provider: string, model: string): string {\n return provider && model ? `${provider}${KEY_SEPARATOR}${model}` : ''\n}\n\nexport function parseModelMenuChoiceKey(value: string): { provider: string; model: string } | undefined {\n const index = value.indexOf(KEY_SEPARATOR)\n if (index <= 0) return undefined\n const provider = value.slice(0, index)\n const model = value.slice(index + KEY_SEPARATOR.length)\n if (!provider || !model) return undefined\n return { provider, model }\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined\n}\n\nfunction asText(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined\n}\n\nfunction parseEffort(value: unknown): { id: string; name: string } | undefined {\n const row = asRecord(value)\n const id = row ? asText(row.id) : undefined\n if (!id) return undefined\n return { id, name: row ? asText(row.name) ?? id : id }\n}\n\n/** Parse the host session catalog into flat choices, keeping a saved route selectable. */\nexport function parseModelMenuChoices(value: unknown, bound?: ModelMenuRoute): ModelMenuChoice[] {\n const envelope = asRecord(value)\n // Host remote calls resolve to a result envelope ({ ok, value }); older hosts\n // and unit tests hand over the bare catalog. Accept both.\n const root = (envelope && envelope.ok === true ? asRecord(envelope.value) : undefined) ?? envelope ?? {}\n const groups = Array.isArray(root.groups) ? root.groups : []\n const choices: ModelMenuChoice[] = []\n for (const group of groups) {\n const groupRow = asRecord(group)\n const provider = groupRow ? asText(groupRow.id) : undefined\n if (!provider || !groupRow || !Array.isArray(groupRow.models)) continue\n const providerName = asText(groupRow.name) ?? provider\n for (const entry of groupRow.models) {\n const modelRow = asRecord(entry)\n const model = modelRow ? asText(modelRow.id) : undefined\n if (!model || !modelRow) continue\n const name = asText(modelRow.name) ?? model\n const reasoning = asRecord(modelRow.reasoning)\n const efforts = reasoning && Array.isArray(reasoning.efforts)\n ? reasoning.efforts.flatMap(effort => { const parsed = parseEffort(effort); return parsed ? [parsed] : [] })\n : []\n choices.push({ provider, model, label: `${providerName} / ${name}`, efforts })\n }\n }\n if (bound?.provider && bound.model && !choices.some(item => item.provider === bound.provider && item.model === bound.model)) {\n choices.push({ provider: bound.provider, model: bound.model, label: `${bound.provider} / ${bound.model}`, efforts: [] })\n }\n return choices\n}\n\n/** An empty saved route means no explicit model. */\nexport function modelMenuOverride(route: ModelMenuRoute | undefined): ModelRoute | undefined {\n const provider = route?.provider?.trim()\n const model = route?.model?.trim()\n if (!provider || !model) return undefined\n const effort = route?.reasoningEffort?.trim()\n return effort ? { provider, model, reasoningEffort: effort } : { provider, model }\n}\n\nexport function normalizeModelMenuRoute(value: unknown): ModelMenuRoute {\n const row = asRecord(value)\n if (!row) return { provider: '', model: '' }\n const provider = asText(row.provider) ?? ''\n const model = asText(row.model) ?? ''\n const effort = asText(row.reasoningEffort)\n if (!provider || !model || provider.length > 250 || model.length > 250) return { provider: '', model: '' }\n return effort && effort.length <= 80 ? { provider, model, reasoningEffort: effort } : { provider, model }\n}\n\n/** Load the host catalog once per mount and republish whenever it answers. */\nexport function useModelMenuChoices(client: ModelCatalogClient, bound?: ModelMenuRoute): ModelMenuChoice[] {\n const [choices, setChoices] = useState<ModelMenuChoice[]>([])\n useEffect(() => {\n if (typeof document === 'undefined') return\n let live = true\n const load = () => {\n void client.remote?.session?.modelCatalog?.()\n ?.then(value => { if (live) setChoices(parseModelMenuChoices(value, bound)) })\n .catch(() => { if (live) setChoices([]) })\n }\n load()\n return () => { live = false }\n }, [client, bound?.provider, bound?.model])\n return choices\n}\n\n/** Reasoning-effort options for one choice; the saved value stays selectable. */\nexport function modelMenuEffortOptions(\n choice: ModelMenuChoice | undefined,\n current?: string,\n): Array<{ id: string; name: string }> {\n const listed = (choice?.efforts ?? []).map(item => ({ ...item }))\n if (current && !listed.some(item => item.id === current)) listed.push({ id: current, name: current })\n return listed\n}\n","//#region src/official-ui.ts\n/**\n* Shared contract that keeps every plugin's browser-side UI on the official\n* DeepSeek Harness Web design language.\n*\n* Two rules produce that language, and both are load-bearing here:\n*\n* 1. Colour, radius, elevation and focus come from the host theme's real\n* `--dsw-*` tokens, written under their own names. Plugins never invent a\n* token, never alias the official ones behind a private palette (a private\n* alias is just a second, diverging theme), and never carries a literal\n* fallback — the host publishes light and dark, and a literal would pin one\n* of them. The only non-colour custom properties used are the host's own\n* content-font axis and frame clearance.\n*\n* 2. Anything the host already ships is used, not reimplemented. Controls come\n* from `@deepseek-ai/dsh-client-ui-primitives` (`Button`, `Input`,\n* `Checkbox`, `Switch`, `Tag`, `Pill`, `SegmentedControl`, `Menu`, `Modal`,\n* `Tooltip`, `Toast`, `DisclosureRow`, `StateDot`, `PathLabel`, the settings\n* form suite). This module only styles what primitives do not cover: page\n* scaffolding, field layout, banners, empty states and scroll regions.\n*\n* The metrics below are transcribed from the primitives' own CSS modules so a\n* feature panel lines up pixel-for-pixel with a native one: the 14/22 body and\n* 13/20 compact type tiers, the 0.5px hairline scale, and the elevation family\n* that draws a surface's edge in its shadow (`border: 0`) instead of a border.\n*/\n/**\n* Every `--dsw-*` token this repo is allowed to reference, grouped by role.\n*\n* Plugins may only colour through this list. It is exported so the guard test\n* can fail a build when a stylesheet reaches for anything else — the failure\n* mode this prevents is silent: an unknown token resolves to nothing, so a\n* border disappears or a label inherits the wrong colour with no error anywhere.\n*/\nconst OFFICIAL_THEME_TOKENS = {\n\t/** Surfaces, from the page up to the topmost nested card. */\n\tsurface: [\n\t\t\"--dsw-alias-bg-base\",\n\t\t\"--dsw-alias-bg-layer-1\",\n\t\t\"--dsw-alias-bg-layer-2\",\n\t\t\"--dsw-alias-bg-layer-3\",\n\t\t\"--dsw-alias-bg-layer-4\",\n\t\t\"--dsw-alias-bg-module-platform\",\n\t\t\"--dsw-alias-bg-overlay\"\n\t],\n\t/** Hairlines. l1 is near-invisible on a menu surface, so menus use l2+. */\n\tborder: [\n\t\t\"--dsw-alias-border-l1\",\n\t\t\"--dsw-alias-border-l2\",\n\t\t\"--dsw-alias-border-l3\",\n\t\t\"--dsw-alias-border-l4\"\n\t],\n\t/** Text. `caption` is menu shortcut text, `dimmed` is placeholder text. */\n\tlabel: [\n\t\t\"--dsw-alias-label-primary\",\n\t\t\"--dsw-alias-label-secondary\",\n\t\t\"--dsw-alias-label-tertiary\",\n\t\t\"--dsw-alias-label-caption\",\n\t\t\"--dsw-alias-label-dimmed\",\n\t\t\"--dsw-alias-label-error\",\n\t\t\"--dsw-alias-label-primary-foreground\"\n\t],\n\t/** Interactive fills. The `-danger` hover belongs to destructive rows. */\n\tinteractive: [\n\t\t\"--dsw-alias-interactive-bg-hover\",\n\t\t\"--dsw-alias-interactive-bg-active\",\n\t\t\"--dsw-alias-interactive-bg-hover-danger\"\n\t],\n\t/** Accent and status. `business` is the focus ring's default colour. */\n\taccent: [\n\t\t\"--dsw-alias-brand-primary\",\n\t\t\"--dsw-alias-button-primary-fill\",\n\t\t\"--dsw-alias-button-primary-hover\",\n\t\t\"--dsw-alias-button-tool-bar-fill\",\n\t\t\"--dsw-alias-button-tool-bar-hover\",\n\t\t\"--dsw-alias-button-ghost-active-fill\",\n\t\t\"--dsw-alias-button-ghost-active-border\"\n\t],\n\tstate: [\n\t\t\"--dsw-alias-state-business-primary\",\n\t\t\"--dsw-alias-state-success-primary\",\n\t\t\"--dsw-alias-state-warn-primary\",\n\t\t\"--dsw-alias-state-error-primary\",\n\t\t\"--dsw-alias-state-idle-primary\"\n\t],\n\t/** Corner scale: sm 8, md 12, lg the large card, panel the modal. */\n\tradius: [\n\t\t\"--dsw-radius-sm\",\n\t\t\"--dsw-radius-md\",\n\t\t\"--dsw-radius-lg\",\n\t\t\"--dsw-radius-panel\"\n\t],\n\t/** An elevated surface draws its edge in the shadow, so it keeps border: 0. */\n\televation: [\n\t\t\"--dsw-elevation-soft\",\n\t\t\"--dsw-elevation-stroke\",\n\t\t\"--dsw-elevation-stroke-color\",\n\t\t\"--dsw-elevation-panel\",\n\t\t\"--dsw-elevation-prominent\"\n\t],\n\t/** Floats, masks and scrollbars. */\n\toverlay: [\n\t\t\"--dsw-menu-surface-fill\",\n\t\t\"--dsw-menu-backdrop-filter\",\n\t\t\"--dsw-mask-blur\",\n\t\t\"--dsw-alias-bg-mask-1\",\n\t\t\"--dsw-alias-menu-icon\",\n\t\t\"--dsw-alias-scrollbar-bg-l2\",\n\t\t\"--dsw-alias-scrollbar-hover-l2\",\n\t\t\"--dsw-shadow-lv3\"\n\t],\n\t/** Motion, focus and type axis, published by the host rather than by a component. */\n\tsystem: [\n\t\t\"--dsw-focus-ring-width\",\n\t\t\"--dsw-focus-ring-color\",\n\t\t\"--dsw-font-markdown-code-font-family\",\n\t\t\"--ds-transition-duration\",\n\t\t\"--ds-ease-in-out\",\n\t\t\"--ds-font-family-code\",\n\t\t\"--dsh-scrollbar-thumb\",\n\t\t\"--dsh-scrollbar-thumb-hover\",\n\t\t\"--dsh-content-font-size-secondary\",\n\t\t\"--dsh-content-font-delta\",\n\t\t\"--dsh-frame-top-clearance\"\n\t]\n};\n/** Every official token name, flat. Used by the token guard test. */\nconst OFFICIAL_THEME_TOKEN_NAMES = Object.values(OFFICIAL_THEME_TOKENS).flat();\n/**\n* The host's focus ring shorthand, verbatim. Writing this per control is how\n* rings drift apart; a stylesheet that draws its own focus style should use\n* {@link officialFocus} instead. The colour fallback is the host's own default.\n*/\nconst OFFICIAL_FOCUS_RING = \"var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary))\";\n/**\n* A complete `outline` declaration at the official geometry. `offset` defaults\n* to the 2px the native controls use; the host's inline field rules sit at 1px\n* and a segmented tab pulls the ring inside itself at -2px.\n*/\nfunction officialFocus(offset = \"2px\") {\n\treturn `outline: ${OFFICIAL_FOCUS_RING}; outline-offset: ${offset}`;\n}\n/**\n* An elevated surface. The host draws a raised surface's edge inside its\n* shadow rather than as a border, so a card sets `border: 0` and takes the edge\n* from the elevation — which is also why its border stays off the alias-border\n* set that a flat, non-elevated rule would use.\n*/\nfunction officialElevation(level) {\n\treturn `border: 0; box-shadow: var(--dsw-elevation-${level})`;\n}\n/**\n* An elevated surface whose edge should read as a specific hairline. Rebinding\n* the stroke colour is how a menu card picks l1 while a panel picks l3, without\n* the two growing apart by hand.\n*/\nfunction officialStrokedElevation(level, color) {\n\treturn `--dsw-elevation-stroke-color: ${color}; ${officialElevation(level)}`;\n}\n/**\n* The shared stylesheet for a plugin UI, scoped under that plugin's root class.\n*\n* Scoping is what keeps this safe to always-bundle into every client: the rules\n* can only match inside the plugin's own subtree, so two plugins can both mount\n* `dsh-ui-card` without either styling the other's markup.\n*\n* Each recipe matches the root element *and* its descendants, because the\n* commonest arrangement is one element that is both — a surface that carries\n* the root class and `dsh-ui-card`, or a portaled dialog that is the root and\n* the `dsh-ui-surface`. A descendant-only scope would silently leave those\n* unstyled, with no error anywhere.\n*\n* A caveat worth knowing: `Modal` and `Menu` portal to `document.body`, so their\n* content leaves the plugin's subtree entirely. A portaled surface therefore\n* needs its own root class on an element inside the portal.\n*\n* Only patterns that primitives do not provide live here. If a control appears\n* below that `Button`/`Input`/`Switch`/`Tag`/`Menu` already covers, that is a\n* bug in this file: use the primitive and delete the recipe.\n*/\nfunction officialUiCss(roots) {\n\tconst scope = (typeof roots === \"string\" ? [roots] : roots).map((root) => `.${root}`).join(\", \");\n\treturn `\n/* Official DSH Web UI contract. Generated by @klarkxy/dsh-plugin-kit/official-ui.\n * Do not hand-edit the copy inside a plugin: change this module so every plugin\n * moves together. Scope: ${scope} */\n/* The scope rule below stays open for the whole sheet: every rule after it\n * nests with the parent selector, so one stylesheet can cover several unrelated\n * roots without leaking into a neighbouring plugin. Its closing brace is last. */\n${scope} {\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 14px;\n line-height: 22px;\n min-width: 0;\n\n& *, & *::before, & *::after { box-sizing: border-box; }\n& h1, & h2, & h3, & h4, & p, & figure { margin: 0; }\n/* Keyboard focus only: pointer input keeps the native resting appearance. The\n * ring needs no radius of its own — the outline already follows the control's\n * own border-radius, and overriding it here would flatten every control. */\n& :focus-visible { ${officialFocus()}; }\n& [hidden] { display: none !important; }\n\n/* --- Type tiers. The same 14/22 and 13/20 steps the primitives use. --- */\n& .dsh-ui-title { font-size: 16px; line-height: 24px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-heading { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-compact { font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-meta { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); }\n& .dsh-ui-hint { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n& .dsh-ui-error { font-size: 12px; line-height: 18px; color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-warn { color: var(--dsw-alias-state-warn-primary); }\n& .dsh-ui-success { color: var(--dsw-alias-state-success-primary); }\n& .dsh-ui-muted { color: var(--dsw-alias-label-tertiary); }\n& .dsh-ui-truncate { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n& .dsh-ui-wrap { min-width: 0; overflow-wrap: anywhere; }\n\n/* --- Layout scaffolding. --- */\n& .dsh-ui-stack { display: flex; flex-direction: column; gap: 12px; }\n& .dsh-ui-stack-lg { display: flex; flex-direction: column; gap: 20px; }\n& .dsh-ui-row { display: flex; align-items: center; gap: 8px; min-width: 0; }\n& .dsh-ui-row-wrap { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }\n& .dsh-ui-spacer { flex: 1; min-width: 0; }\n/* A 0.5px l2 rule is the host's section divider; reserve the same rhythm. */\n& .dsh-ui-divider { height: 0.5px; background: var(--dsw-alias-border-l2); }\n& .dsh-ui-section { display: flex; flex-direction: column; gap: 12px; padding-top: 16px; border-top: 0.5px solid var(--dsw-alias-border-l2); }\n\n/* --- Card: a raised surface whose edge lives in the shadow. --- */\n& .dsh-ui-card {\n ${officialElevation(\"stroke\")}\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px;\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n min-width: 0;\n}\n& .dsh-ui-card--flat { border: 0.5px solid var(--dsw-alias-border-l3); box-shadow: none; }\n& .dsh-ui-card--nested { background: var(--dsw-alias-bg-layer-2); }\n& .dsh-ui-card--plain { background: none; }\n\n/* --- Field: label, control, help, error. The control itself is an\n * official primitive, so this only owns the vertical rhythm. --- */\n& .dsh-ui-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }\n& .dsh-ui-field + .dsh-ui-field { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }\n& .dsh-ui-label { display: flex; align-items: center; gap: 6px; font-size: 13px; line-height: 20px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }\n& .dsh-ui-help { font-size: 12px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }\n& .dsh-ui-help p { margin: 0; }\n& .dsh-ui-help p + p { margin-top: 8px; }\n& .dsh-ui-required { color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-control { width: 100%; min-width: 0; }\n/* An invalid control is marked on the control, not only in the message. */\n& .dsh-ui-control[aria-invalid='true'] { border-color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-readonly { display: flex; flex-direction: column; gap: 4px; min-width: 0; }\n& .dsh-ui-readonly > dt { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n& .dsh-ui-readonly > dd { margin: 0; font-size: 13px; line-height: 20px; overflow-wrap: anywhere; }\n\n/* --- Buttons row. A no-op container: it exists so actions line up on the\n * trailing edge the way every native panel does. --- */\n& .dsh-ui-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding-top: 4px; }\n& .dsh-ui-actions-end { justify-content: flex-end; }\n\n/* --- Banners. A banner is a left-rail notice, the shape used for warnings,\n * deprecations and blocking instructions. --- */\n& .dsh-ui-banner {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px 14px;\n border: 0.5px solid var(--dsw-alias-border-l3);\n border-left: 3px solid var(--dsw-alias-state-warn-primary);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-1);\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n}\n& .dsh-ui-banner-title { font-weight: 500; color: var(--dsw-alias-state-warn-primary); }\n& .dsh-ui-banner--info { border-left-color: var(--dsw-alias-state-business-primary); }\n& .dsh-ui-banner--danger { border-left-color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-banner--success { border-left-color: var(--dsw-alias-state-success-primary); }\n& .dsh-ui-banner p { margin: 0; }\n\n/* --- Inline notice: a transient confirmation with no chrome of its own. --- */\n& .dsh-ui-notice { display: flex; align-items: center; gap: 6px; font-size: 12px; line-height: 18px; color: var(--dsw-alias-state-success-primary); }\n& .dsh-ui-notice--error { color: var(--dsw-alias-state-error-primary); }\n\n/* --- Empty and loading states. Both sit in a dashed well so an empty panel\n * reads as \"nothing here yet\" rather than as a broken layout. --- */\n& .dsh-ui-empty {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n padding: 20px 16px;\n border: 0.5px dashed var(--dsw-alias-border-l3);\n border-radius: var(--dsw-radius-md);\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n}\n& .dsh-ui-loading { display: flex; align-items: center; gap: 8px; padding: 20px 0; font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-secondary); }\n\n/* --- Selectable list. A row is a button-sized target with a hover fill and\n * a selected fill; the name carries the weight, the description does not. --- */\n& .dsh-ui-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; min-width: 0; }\n& .dsh-ui-list-scroll { max-height: min(66vh, 760px); overflow-y: auto; overflow-x: hidden; }\n& .dsh-ui-list-row { border-radius: var(--dsw-radius-md); }\n& .dsh-ui-list-row:hover { background: var(--dsw-alias-interactive-bg-hover); }\n& .dsh-ui-list-row[aria-selected='true'], & .dsh-ui-list-row[data-selected] { background: var(--dsw-alias-interactive-bg-active); }\n& .dsh-ui-list-item {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n width: 100%;\n min-width: 0;\n padding: 10px 12px;\n border: 0;\n border-radius: var(--dsw-radius-md);\n background: none;\n font: inherit;\n color: inherit;\n text-align: start;\n cursor: pointer;\n}\n& .dsh-ui-list-item:disabled { cursor: default; }\n& .dsh-ui-list-item:disabled:hover { background: none; }\n& .dsh-ui-list-name { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); overflow-wrap: anywhere; }\n& .dsh-ui-list-desc { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n\n/* --- Code and structured output. Wraps rather than scrolls, because a\n * feature panel is read rather than scanned. --- */\n& .dsh-ui-code {\n padding: 10px 12px;\n border: 0.5px solid var(--dsw-alias-border-l3);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-1);\n font-family: var(--ds-font-family-code, ui-monospace, 'Cascadia Mono', Consolas, monospace);\n font-size: 12px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n overflow-wrap: anywhere;\n white-space: pre-wrap;\n}\n& .dsh-ui-scroll { max-height: 60vh; overflow: auto; overscroll-behavior: contain; }\n\n/* --- A toggle row: label on the left, switch on the trailing edge. This is\n * layout only; the switch itself is the official primitive. --- */\n& .dsh-ui-toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-width: 0; padding: 12px 0; }\n& .dsh-ui-toggle-row + .dsh-ui-toggle-row { border-top: 0.5px solid var(--dsw-alias-border-l2); }\n& .dsh-ui-toggle-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }\n& .dsh-ui-toggle-label { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n\n/* --- Floating surface: a panel anchored to a trigger. This is the material\n * a menu card is made of — the translucent fill plus its backdrop blur, with\n * the edge riding inside the prominent elevation. A plugin that hand-rolls this\n * is how tokens like --dsw-specific-menu get invented; use this instead. --- */\n& .dsh-ui-surface {\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);\n position: relative;\n display: flex;\n flex-direction: column;\n border: 0;\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-menu-surface-fill);\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n box-shadow: var(--dsw-elevation-prominent);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n line-height: 20px;\n min-width: 0;\n}\n& .dsh-ui-surface-body { display: flex; flex-direction: column; gap: 8px; padding: 12px 14px 14px; overflow-y: auto; }\n& .dsh-ui-surface-head { display: flex; align-items: center; gap: 8px; min-width: 0; }\n& .dsh-ui-surface-title { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n\n/* --- Native select. The primitives ship no select, so a plugin that offers a\n * closed list of choices keeps the platform control and matches the official\n * settings field geometry exactly (34px, 0.5px l4, radius-md, layer-3). A\n * SegmentedControl is the primitive to reach for when the choices are few\n * enough to show at once. --- */\n& .dsh-ui-select {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 34px;\n padding: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n& .dsh-ui-select:focus-visible { outline: none; border-color: var(--dsw-alias-state-business-primary); }\n& .dsh-ui-select:disabled { color: var(--dsw-alias-label-tertiary); cursor: default; }\n& .dsh-ui-select[aria-invalid='true'] { border-color: var(--dsw-alias-state-error-primary); }\n\n/* Long panels scroll inside themselves instead of growing the host page. */\n& .dsh-ui-panel { display: flex; flex-direction: column; gap: 16px; min-width: 0; }\n& .dsh-ui-panel-wide { max-width: 100%; }\n\n@media (prefers-reduced-motion: reduce) {\n & *, & *::before, & *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }\n}\n}\n`.replace(/^& (\\.dsh-ui-[a-z0-9-]+)(?![+>~])/gm, (_match, className) => `&${className}, & ${className}`);\n}\n//#endregion\nexport { OFFICIAL_FOCUS_RING, OFFICIAL_THEME_TOKENS, OFFICIAL_THEME_TOKEN_NAMES, officialElevation, officialFocus, officialStrokedElevation, officialUiCss };\n\n//# sourceMappingURL=official-ui.js.map","/** Browser-safe contracts. Shared RPC/result types stay on @klarkxy/dsh-plugin-kit. */\nexport type { RpcResult } from '@klarkxy/dsh-plugin-kit/contracts'\n\nexport const PLUGIN_NAME = '@klarkxy/dsh-git-commit'\nexport const FEATURE_ID = 'git-commit'\nexport const PURPOSE_ID = 'git-commit.plan'\nexport const RPC_CHANNEL = '/dsh-git-commit'\nexport const GIT_COMMIT_CLIENT_SERVICE = 'dshGitCommitClient'\nexport const PROMPT_VERSION = 'git-commit.v1'\nexport const SCHEMA_VERSION = 'commit-plan-json.v1'\nexport const CONTRACT_VERSION = 1\n\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 2048\n/** Total character budget for the change manifest sent to the model. */\nexport const MAX_MANIFEST_CHARS = 48_000\n/** Per-file preview cap for untracked files. */\nexport const MAX_UNTRACKED_PREVIEW_CHARS = 2_000\n/** Recent commit subjects supplied as style reference. */\nexport const RECENT_LOG_COUNT = 10\n/** Hard cap for one generated commit message line. */\nexport const MAX_MESSAGE_CHARS = 120\n/** git subprocess timeout. */\nexport const GIT_TIMEOUT_MS = 30_000\nexport const SETTINGS_KEY = 'current'\n\n/** Plugin-page model selection. Empty provider/model means \"follow the default\". */\nexport interface CommitModelRoute {\n readonly provider: string\n readonly model: string\n readonly reasoningEffort?: string\n}\n\nexport interface GitCommitSettings {\n readonly revision: number\n readonly model: CommitModelRoute\n /**\n * Opt-in single commit when the model produced no usable plan. Off by\n * default: an unplanned commit is one the user never reviewed, so a failed\n * or unusable model call rejects the run instead of writing to the index.\n */\n readonly allowFallback: boolean\n}\n\nexport const defaultModelRoute = (): CommitModelRoute => ({ provider: '', model: '' })\n\nexport const defaultSettings = (): GitCommitSettings => ({\n revision: 0, model: defaultModelRoute(), allowFallback: false,\n})\n\n/** Untrusted stored flags stay opt-in: anything but a literal true is false. */\nexport function normalizeFallback(value: unknown): boolean {\n return value === true\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined\n}\n\nfunction asText(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined\n}\n\n/** Untrusted stored routes collapse to the default so a bad row never breaks the run. */\nexport function normalizeModelRoute(value: unknown): CommitModelRoute {\n const row = asRecord(value)\n if (!row) return defaultModelRoute()\n const provider = asText(row.provider) ?? ''\n const model = asText(row.model) ?? ''\n const effort = asText(row.reasoningEffort)\n if (!provider || !model || provider.length > 250 || model.length > 250) return defaultModelRoute()\n return effort && effort.length <= 80 ? { provider, model, reasoningEffort: effort } : { provider, model }\n}\n\nexport interface CommitModelInfo {\n readonly provider: string\n readonly model: string\n /** 'page' is the plugin-page selection; 'default' is the host chat model. */\n readonly source: 'page' | 'default'\n}\n\nexport interface GitCommitStatus {\n readonly available: boolean\n /** Machine-readable reason when unavailable: 'no-session' | 'no-cwd' | 'not-a-repo' | 'no-git'. */\n readonly reason?: string\n readonly detail?: string\n readonly root?: string\n readonly branch?: string\n readonly workspace: { readonly files: number }\n readonly model?: CommitModelInfo\n}\n\nexport interface CommitGroupResult {\n readonly hash: string\n readonly message: string\n readonly files: readonly string[]\n}\n\nexport interface CommitRunResult {\n readonly branch: string\n readonly commits: readonly CommitGroupResult[]\n /** True when the model plan was unavailable and a single fallback commit was used. */\n readonly fallback: boolean\n readonly model?: CommitModelInfo\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport {\n modelMenuChoiceKey, modelMenuEffortOptions, parseModelMenuChoiceKey, parseModelMenuChoices,\n type ModelMenuChoice,\n} from '@klarkxy/dsh-plugin-kit/model-menu'\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n Button, IconRefreshOutlineRegular, Switch, Tag, Tooltip, useAnchoredPosition, useDismissOnOutsidePointer,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport { officialUiCss } from '@klarkxy/dsh-plugin-kit/official-ui'\nimport {\n GIT_COMMIT_CLIENT_SERVICE, PLUGIN_NAME, RPC_CHANNEL, type CommitModelRoute, type CommitRunResult,\n type GitCommitSettings, type GitCommitStatus, type RpcResult,\n} from './contracts.ts'\n\nexport const name = 'dsh-git-commit-client'\nexport const inject = ['slots', 'connection', 'remote', 'remote.session', 'locale'] as const\n\nconst NS = 'dsh-git-commit.action'\n\nconst zh = {\n action: '提交',\n title: '提交到 Git',\n commitAction: '分次提交全部工作区修改',\n files: '个文件',\n model: '模型',\n modelDefault: '默认模型',\n modelCustom: '插件设置',\n filesCount: '({n} 个文件)',\n confirmPrompt: '将把 {n} 个文件的全部修改分次提交到当前分支。',\n confirm: '确认提交',\n cancel: '取消',\n loading: '正在读取仓库状态…',\n running: '正在整理修改并分次提交…',\n done: '已创建提交',\n fallback: '模型不可用,已合并为单个提交',\n noWorkspace: '工作区没有修改',\n unavailable: '不可用',\n reasonNoRepo: '当前目录不在 Git 仓库中',\n reasonNoGit: '未找到 git 命令',\n reasonNoCwd: '会话没有工作目录',\n reasonNoSession: '会话不在线',\n sessionRunning: '会话正在运行,提交已暂停',\n refresh: '刷新',\n failed: '操作失败',\n planUnavailable: '模型没有给出可用的提交方案,已取消本次提交,工作区没有被改动。换一个模型重试,或在插件设置里开启兜底提交。',\n close: '关闭',\n}\n\nconst en: Record<keyof typeof zh, string> = {\n action: 'Commit',\n title: 'Commit to Git',\n commitAction: 'Commit all workspace changes',\n files: 'files',\n model: 'Model',\n modelDefault: 'default model',\n modelCustom: 'Plugin settings',\n filesCount: ' ({n} files)',\n confirmPrompt: 'All changes in {n} files will be committed to the current branch in one or more commits.',\n confirm: 'Commit now',\n cancel: 'Cancel',\n loading: 'Reading repository status…',\n running: 'Organizing changes into commits…',\n done: 'Commits created',\n fallback: 'Model unavailable; used a single commit',\n noWorkspace: 'No workspace changes',\n unavailable: 'Unavailable',\n reasonNoRepo: 'Current directory is not inside a Git repository',\n reasonNoGit: 'git executable not found',\n reasonNoCwd: 'Session has no working directory',\n reasonNoSession: 'Session is not live',\n sessionRunning: 'Session is running; commits paused',\n refresh: 'Refresh',\n failed: 'Operation failed',\n planUnavailable: 'The model returned no usable commit plan, so the run was cancelled and your workspace is untouched. Try another model, or turn on the fallback in plugin settings.',\n close: 'Close',\n}\n\ntype Key = keyof typeof zh\ntype Translate = (key: Key) => string\n\ninterface ConnectionLike {\n rpc: { call(channel: string, endpoint: string, payload: unknown): Promise<unknown> }\n}\n\ninterface SessionSnapshotLike {\n running?: boolean\n}\n\ninterface UseSessionLike {\n <T>(selector: (snapshot: SessionSnapshotLike) => T): T\n}\n\n/** A failed RPC keeps its code so the panel can explain a rejection in its own words. */\nclass RpcError extends Error {\n readonly code: string\n constructor(code: string, message: string) {\n super(message)\n this.name = 'RpcError'\n this.code = code\n }\n}\n\nexport interface GitCommitActionProps {\n sessionId: string\n useSession: UseSessionLike\n call: (endpoint: string, payload: unknown) => Promise<unknown>\n t: Translate\n}\n\nasync function rpc<T>(\n call: GitCommitActionProps['call'], endpoint: string, payload: unknown = {}, fallback = 'Operation failed',\n): Promise<T> {\n const result = await call(endpoint, payload) as RpcResult<T> | undefined\n if (!result || result.ok !== true) {\n const failed = result && 'error' in result ? result.error : undefined\n throw new RpcError(failed?.code ?? 'unknown', failed?.message ? failed.message : fallback)\n }\n return result.value\n}\n\nfunction reasonText(t: Translate, status: GitCommitStatus): string {\n switch (status.reason) {\n case 'not-a-repo': return t('reasonNoRepo')\n case 'no-git': return t('reasonNoGit')\n case 'no-cwd': return t('reasonNoCwd')\n case 'no-session': return t('reasonNoSession')\n default: return t('unavailable')\n }\n}\n\n/** A refusal the plugin can name gets its own sentence; the rest stay verbatim. */\nfunction errorText(t: Translate, error: { code: string; message: string }): string {\n return error.code === 'plan-unavailable' ? t('planUnavailable') : error.message\n}\n\nfunction panelError(reason: unknown): { code: string; message: string } {\n return reason instanceof RpcError\n ? { code: reason.code, message: reason.message }\n : { code: 'unknown', message: reason instanceof Error ? reason.message : String(reason) }\n}\n\nfunction GitBranchIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"4.5\" cy=\"3.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <circle cx=\"4.5\" cy=\"12.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <circle cx=\"11.5\" cy=\"6.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M4.5 5.1v5.8\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M11.5 8.1c0 2-1.6 2.9-3.4 3\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n </svg>\n )\n}\n\nexport function GitCommitAction({ sessionId, useSession, call, t }: GitCommitActionProps) {\n const [open, setOpen] = useState(false)\n const [status, setStatus] = useState<GitCommitStatus>()\n const [loading, setLoading] = useState(false)\n const [running, setRunning] = useState(false)\n const [result, setResult] = useState<CommitRunResult | null>(null)\n const [error, setError] = useState<{ code: string; message: string } | null>(null)\n const [confirming, setConfirming] = useState(false)\n const rootRef = useRef<HTMLDivElement>(null)\n const triggerRef = useRef<HTMLButtonElement>(null)\n const panelRef = useRef<HTMLDivElement>(null)\n const generationRef = useRef(0)\n const position = useAnchoredPosition({ open, anchorRef: triggerRef, panelRef, gap: 5, margin: 16 })\n const sessionRunning = useSession(snapshot => snapshot.running === true)\n\n const changeOpen = useCallback((next: boolean) => {\n setOpen(next)\n setConfirming(false)\n if (next) {\n setResult(null)\n setError(null)\n }\n }, [])\n\n // Move focus into the dialog once it is positioned, so keyboard users land inside it.\n const positioned = Boolean(position)\n useEffect(() => {\n if (open && positioned) panelRef.current?.focus()\n }, [open, positioned])\n\n useDismissOnOutsidePointer(rootRef, open, changeOpen, panelRef)\n\n useEffect(() => {\n generationRef.current += 1\n setOpen(false)\n setStatus(undefined)\n setResult(null)\n setError(null)\n setRunning(false)\n }, [sessionId])\n\n const loadStatus = useCallback(async () => {\n const generation = generationRef.current\n setLoading(true)\n setError(null)\n try {\n const next = await rpc<GitCommitStatus>(call, 'status', { sessionId }, t('failed'))\n if (generationRef.current !== generation) return\n setStatus(next)\n } catch (reason) {\n if (generationRef.current !== generation) return\n setStatus(undefined)\n setError(panelError(reason))\n } finally {\n if (generationRef.current === generation) setLoading(false)\n }\n }, [call, sessionId, t])\n\n useEffect(() => {\n if (!open) return\n void loadStatus()\n }, [open, loadStatus])\n\n useEffect(() => {\n if (!open) return\n const dismiss = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return\n event.preventDefault()\n changeOpen(false)\n triggerRef.current?.focus()\n }\n document.addEventListener('keydown', dismiss)\n return () => document.removeEventListener('keydown', dismiss)\n }, [open, changeOpen])\n\n const runCommit = useCallback(async () => {\n const generation = generationRef.current\n setConfirming(false)\n setRunning(true)\n setResult(null)\n setError(null)\n try {\n const value = await rpc<CommitRunResult>(call, 'commit', { sessionId }, t('failed'))\n if (generationRef.current !== generation) return\n setResult(value)\n const next = await rpc<GitCommitStatus>(call, 'status', { sessionId }).catch(() => undefined)\n if (generationRef.current !== generation) return\n if (next) setStatus(next)\n } catch (reason) {\n if (generationRef.current !== generation) return\n setError(panelError(reason))\n } finally {\n if (generationRef.current === generation) setRunning(false)\n }\n }, [call, sessionId, t])\n\n const available = status?.available === true\n const workspaceCount = status?.workspace.files ?? 0\n const canCommit = available && !running && !sessionRunning && workspaceCount > 0\n\n return (\n <div ref={rootRef} className=\"gcm-root\">\n <Tooltip label={t('title')} side=\"bottom\" gap={4}>\n <Button\n ref={triggerRef}\n variant=\"ghost\"\n size=\"sm\"\n icon={<GitBranchIcon />}\n aria-label={t('title')}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n onClick={() => changeOpen(!open)}\n >\n {t('action')}\n </Button>\n </Tooltip>\n {open && createPortal(\n <div\n ref={panelRef}\n className=\"gcm-root dsh-ui-surface gcm-panel\"\n style={position ?? { visibility: 'hidden', left: 0, top: 0 }}\n role=\"dialog\"\n tabIndex={-1}\n aria-label={t('title')}\n >\n <div className=\"dsh-ui-surface-body\">\n <div className=\"dsh-ui-surface-head\">\n <span className=\"dsh-ui-surface-title\">{t('title')}</span>\n {status?.branch ? <span className=\"dsh-ui-hint dsh-ui-truncate\">{status.branch}</span> : null}\n <span className=\"dsh-ui-spacer\" />\n <Tooltip label={t('refresh')} side=\"bottom\" gap={4}>\n <Button variant=\"ghost\" size=\"sm\" aria-label={t('refresh')} icon={<IconRefreshOutlineRegular size={14} />}\n disabled={loading || running} onClick={() => void loadStatus()} />\n </Tooltip>\n </div>\n {loading && !status && <p className=\"dsh-ui-hint\" role=\"status\">{t('loading')}</p>}\n {error !== null && <p className=\"dsh-ui-error\" role=\"alert\">{errorText(t, error)}</p>}\n {status && !available && <p className=\"dsh-ui-meta\" role=\"status\">{reasonText(t, status)}</p>}\n {available && (\n <>\n {status?.model ? (\n <p className=\"gcm-model\">\n <span className=\"dsh-ui-hint\">{t('model')}</span>\n <span className=\"dsh-ui-truncate\">{status.model.provider}/{status.model.model}</span>\n <Tag tone={status.model.source === 'page' ? 'info' : 'neutral'}>\n {status.model.source === 'page' ? t('modelCustom') : t('modelDefault')}\n </Tag>\n </p>\n ) : null}\n {confirming && canCommit ? (\n <div className=\"dsh-ui-stack\" role=\"group\" aria-label={t('commitAction')}>\n <p className=\"dsh-ui-hint dsh-ui-wrap\">{t('confirmPrompt').replace('{n}', String(workspaceCount))}</p>\n <div className=\"dsh-ui-actions\">\n <Button variant=\"ghost\" size=\"md\" onClick={() => setConfirming(false)}>{t('cancel')}</Button>\n <Button variant=\"primary\" size=\"md\" onClick={() => void runCommit()}>{t('confirm')}</Button>\n </div>\n </div>\n ) : (\n <Button variant=\"primary\" size=\"md\"\n disabled={!canCommit}\n onClick={() => setConfirming(true)}>\n {t('commitAction')}{t('filesCount').replace('{n}', String(workspaceCount))}\n </Button>\n )}\n {workspaceCount === 0 && <p className=\"dsh-ui-hint\">{t('noWorkspace')}</p>}\n {sessionRunning && <p className=\"dsh-ui-hint\">{t('sessionRunning')}</p>}\n </>\n )}\n {running && <p className=\"dsh-ui-hint\" role=\"status\">{t('running')}</p>}\n {result && (\n <div className=\"dsh-ui-stack\">\n <p className=\"dsh-ui-hint dsh-ui-wrap\">{t('done')} · {result.branch}</p>\n <ul className=\"gcm-commits\">\n {result.commits.map(commit => (\n <li key={commit.hash || commit.message}>\n <code>{commit.hash}</code> {commit.message}\n </li>\n ))}\n </ul>\n {result.fallback && <p className=\"dsh-ui-hint\">{t('fallback')}</p>}\n </div>\n )}\n </div>\n </div>,\n document.body,\n )}\n </div>\n )\n}\n\nexport const clientCss = `${officialUiCss('gcm-root')}\n/* Only the floating panel's geometry is this plugin's own: the material, the\n * rounded edge and the scrollbar tokens all come from the shared contract.\n *\n * The root class is spelled out because the panel is portaled and *is* the\n * root: the dsh-ui-surface recipe therefore reaches it as a compound\n * .gcm-root.dsh-ui-surface selector and declares position:relative at the\n * weight a bare .gcm-panel rule also carries. Left unqualified that recipe\n * wins, and the anchored left/top degrade into offsets from the panel's static\n * spot at the end of body — the popover then renders under the page instead\n * of at the trigger. Naming both classes puts this rule at the same weight,\n * later in the sheet, so it wins. */\n.gcm-root.gcm-panel { position: fixed; width: min(360px, calc(100vw - 32px)); max-height: min(560px, calc(100vh - 32px)); overflow: auto; }\n.gcm-model { display: flex; align-items: center; gap: 6px; min-width: 0; margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-primary); }\n.gcm-commits { margin: 0; padding-inline-start: 18px; display: grid; gap: 2px; font-size: 12px; line-height: 18px; overflow-wrap: anywhere; }\n.gcm-commits code { font-size: 12px; background: var(--dsw-alias-bg-layer-2); padding: 0 4px; border-radius: var(--dsw-radius-sm); }\n.gcm-settings { display: flex; flex-direction: column; gap: 12px; min-width: 0; }\n.gcm-settings-status { display: flex; flex-direction: column; gap: 4px; }\n`\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context { dshGitCommitClient: { active: boolean } }\n}\n\ntype Client = Context & {\n connection: ConnectionLike\n remote?: { session?: { modelCatalog?: () => Promise<unknown> } }\n slots: {\n inject(key: string, callback: () => unknown): () => void\n register(spec: { name: string; id: string; order: number; locale: string; inject: () => unknown } | { name: string; key: string }, render: unknown): () => void\n }\n locale: {\n register(ns: string, locales: { zh: Record<string, string>; en: Record<string, string> }): () => void\n getSnapshot?(): { active: string }\n subscribe?(listener: () => void): () => void\n }\n}\n\n/** Host UI language, following live switches; falls back to zh when the service lacks a snapshot. */\nfunction useHostLocale(client: Client): string {\n const subscribe = useCallback(\n (listener: () => void) => client.locale.subscribe?.(listener) ?? (() => {}),\n [client],\n )\n const snapshot = useCallback(() => client.locale.getSnapshot?.().active ?? 'zh', [client])\n return useSyncExternalStore(subscribe, snapshot, snapshot)\n}\n\nconst settingsZh = {\n pageTitle: 'Git 提交',\n model: '提交规划模型',\n modelDefault: '默认模型',\n modelEffort: '思考强度',\n modelHint: '留空则使用当前会话模型,再回落到宿主默认对话模型。',\n fallback: '模型不可用时仍然提交',\n fallbackHint: '默认关闭:模型规划失败会取消本次提交,工作区不变。开启后全部改动会合并成一个提交,由插件代写提交信息。',\n loading: '正在读取设置…',\n saved: '已保存。',\n stale: '设置已更新,请刷新后重试。',\n failed: '无法读取提交设置。',\n retry: '重试',\n}\n\nconst settingsEn: Record<keyof typeof settingsZh, string> = {\n pageTitle: 'Git Commit',\n model: 'Commit planning model',\n modelDefault: 'Default model',\n modelEffort: 'Reasoning effort',\n modelHint: 'Leave empty to use the current session model, then the host default chat model.',\n fallback: 'Commit even without a model plan',\n fallbackHint: 'Off by default: a failed plan cancels the run and leaves the workspace untouched. When on, every change lands in one commit with a plugin-written message.',\n loading: 'Loading settings…',\n saved: 'Saved.',\n stale: 'Settings changed; refresh and retry.',\n failed: 'Could not load commit settings.',\n retry: 'Retry',\n}\n\nfunction settingsCopy(locale: string): Record<keyof typeof settingsZh, string> {\n return String(locale).startsWith('zh') ? settingsZh : settingsEn\n}\n\n/** Plugin-page settings row: pick the model this plugin's planning call uses. */\nexport function GitCommitSettingsPanel(props: { client: Client; locale?: string }) {\n const hostLocale = useHostLocale(props.client)\n const text = settingsCopy(props.locale ?? hostLocale)\n const [settings, setSettings] = useState<GitCommitSettings | undefined>(undefined)\n const [choices, setChoices] = useState<ModelMenuChoice[]>([])\n const [error, setError] = useState('')\n const [note, setNote] = useState('')\n const [busy, setBusy] = useState(false)\n\n const call = useCallback(\n (endpoint: string, payload: unknown = {}) => props.client.connection.rpc.call(RPC_CHANNEL, endpoint, payload),\n [props.client],\n )\n\n // Settings load once per client; the catalog effect below is keyed on route\n // strings, so saving a new settings object never re-triggers either fetch.\n useEffect(() => {\n let live = true\n void rpc<GitCommitSettings>(call, 'settings', {}, text.failed).then(next => {\n if (live) { setSettings(next); setError('') }\n }).catch(() => { if (live) setError(text.failed) })\n return () => { live = false }\n }, [call, text.failed])\n\n const boundProvider = settings?.model.provider ?? ''\n const boundModel = settings?.model.model ?? ''\n useEffect(() => {\n let live = true\n const bound = boundProvider && boundModel ? { provider: boundProvider, model: boundModel } : undefined\n void props.client.remote?.session?.modelCatalog?.()\n ?.then(value => { if (live) setChoices(parseModelMenuChoices(value, bound)) })\n .catch(() => { if (live) setChoices([]) })\n return () => { live = false }\n }, [props.client, boundProvider, boundModel])\n\n // One patch shape for both rows: the service replaces the whole row, so an\n // update to the toggle must carry the model it is not changing.\n const save = useCallback((patch: { model?: CommitModelRoute; allowFallback?: boolean }) => {\n if (!settings) return\n setBusy(true); setNote(''); setError('')\n void rpc<GitCommitSettings>(call, 'settings.update', {\n settings: {\n model: patch.model ?? settings.model,\n allowFallback: patch.allowFallback ?? settings.allowFallback,\n },\n expectedRevision: settings.revision,\n }, text.stale).then(next => {\n setSettings(next); setNote(text.saved); setBusy(false)\n }).catch(() => {\n setError(text.stale); setBusy(false)\n })\n }, [call, settings, text.saved, text.stale])\n\n if (!settings) {\n return (\n <section className=\"gcm-root gcm-settings\">\n {error\n ? <p role=\"alert\" className=\"dsh-ui-error\">{error}</p>\n : <p role=\"status\" className=\"dsh-ui-hint\">{text.loading}</p>}\n </section>\n )\n }\n\n const current = settings.model\n const selected = choices.find(item => item.provider === current.provider && item.model === current.model)\n const efforts = modelMenuEffortOptions(selected, current.reasoningEffort)\n\n return (\n <section className=\"gcm-root gcm-settings\" data-testid=\"git-commit-settings\">\n <div className=\"gcm-settings-status\">\n {error && <p role=\"alert\" className=\"dsh-ui-error\">{error}</p>}\n {note && <p role=\"status\" className=\"dsh-ui-notice\">{note}</p>}\n </div>\n <label className=\"dsh-ui-field\">\n <span className=\"dsh-ui-label\">{text.model}</span>\n <select\n className=\"dsh-ui-select\"\n value={modelMenuChoiceKey(current.provider, current.model)}\n disabled={busy}\n onChange={event => {\n const key = event.target.value\n if (!key) { save({ model: { provider: '', model: '' } }); return }\n const parsed = parseModelMenuChoiceKey(key)\n if (parsed) save({ model: parsed })\n }}\n >\n <option value=\"\">{text.modelDefault}</option>\n {choices.map(choice => (\n <option key={modelMenuChoiceKey(choice.provider, choice.model)} value={modelMenuChoiceKey(choice.provider, choice.model)}>\n {choice.label}\n </option>\n ))}\n </select>\n </label>\n {selected && efforts.length > 0 && (\n <label className=\"dsh-ui-field\">\n <span className=\"dsh-ui-label\">{text.modelEffort}</span>\n <select\n className=\"dsh-ui-select\"\n value={current.reasoningEffort ?? ''}\n disabled={busy}\n onChange={event => save({ model: { ...current, reasoningEffort: event.target.value || undefined } })}\n >\n <option value=\"\">{text.modelDefault}</option>\n {efforts.map(effort => <option key={effort.id} value={effort.id}>{effort.name}</option>)}\n </select>\n </label>\n )}\n <p className=\"dsh-ui-meta\">{text.modelHint}</p>\n <article className=\"gcm-root dsh-ui-card\">\n <header className=\"dsh-ui-toggle-row\">\n <div className=\"dsh-ui-toggle-text\">\n <h3 className=\"dsh-ui-toggle-label\">{text.fallback}</h3>\n <p className=\"dsh-ui-hint\">{text.fallbackHint}</p>\n </div>\n <Switch\n checked={settings.allowFallback}\n label={text.fallback}\n disabled={busy}\n onChange={next => save({ allowFallback: next })}\n />\n </header>\n </article>\n </section>\n )\n}\n\nexport function apply(ctx: Context): void {\n const client = ctx as unknown as Client\n ctx.provide(GIT_COMMIT_CLIENT_SERVICE, { active: true })\n ctx.effect(() => client.locale.register(NS, { zh: { ...zh }, en: { ...en } }), 'git-commit.locale')\n // One stylesheet for both the header popover and the plugin-page settings,\n // so the settings page is styled even when no session header is mounted.\n ctx.effect(() => {\n if (typeof document === 'undefined') return () => {}\n const style = document.createElement('style')\n style.setAttribute('data-plugin', name)\n style.textContent = clientCss\n document.head.appendChild(style)\n return () => style.remove()\n }, 'git-commit.styles')\n ctx.effect(() => client.slots.inject('plugins.bundle.config', () => client.slots.register(\n { name: 'plugins.bundle.config', key: PLUGIN_NAME },\n () => <GitCommitSettingsPanel client={client} />,\n )), 'git-commit.settings')\n ctx.effect(() => client.slots.inject('conversation.session.header.actions', () => client.slots.register(\n {\n name: 'conversation.session.header.actions',\n id: 'git-commit',\n order: 10,\n locale: NS,\n inject: () => ({\n call: (endpoint: string, payload: unknown) => client.connection.rpc.call(RPC_CHANNEL, endpoint, payload),\n }),\n },\n GitCommitAction,\n )), 'git-commit.slot')\n}\n"],"mappings":"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"}
|