@norman-else/dsh-claude 0.1.43 → 0.1.45
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/INSTALL.md +55 -55
- package/LICENSE +21 -21
- package/README.md +200 -200
- package/cordis.patch.yml +12 -12
- package/legacy-preset/agent.cordis.yml +11 -11
- package/legacy-preset/preset.yml +4 -4
- package/lib/bin.mjs +1 -1
- package/lib/bin.mjs.map +1 -1
- package/lib/client.js +4 -4
- package/lib/client.js.map +1 -1
- package/lib/events-oovRTmX7.mjs.map +1 -1
- package/lib/index.mjs +255 -32
- package/lib/index.mjs.map +1 -1
- package/lib/presenters-BVWj7u0a.mjs.map +1 -1
- package/lib/{preset-installer-JUktnfwS.mjs → preset-installer-CuosP3sA.mjs} +2 -2
- package/lib/preset-installer-CuosP3sA.mjs.map +1 -0
- package/lib/preset-route.mjs.map +1 -1
- package/package.json +197 -195
- package/preset/claude/agent.cordis.yml +11 -11
- package/preset/claude/preset.yml +4 -4
- package/lib/preset-installer-JUktnfwS.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events-oovRTmX7.mjs","names":[],"sources":["../src/constants.ts","../src/events.ts"],"sourcesContent":["export const CLAUDE_CODE_PROVIDER = 'claude'\nexport const CLAUDE_CODE_PRESET_ID = 'claude'\nexport const CLAUDE_CODE_PROVIDER_IDS = [CLAUDE_CODE_PROVIDER] as const\nexport const CLAUDE_SESSION_BOUND_EVENT = 'claude-code/session-bound'\nexport const CLAUDE_ACTIVITY_EVENT = 'claude-code/activity'\nexport const CLAUDE_CONTEXT_USAGE_EVENT = 'claude-code/context-usage'\nexport const CLAUDE_TASKS_EVENT = 'claude-code/tasks'\n/** Claude's subagent dispatch tools; rendered as plugin-owned group cards\n * gathering subagent activity instead of native tool cards. */\nexport const TASK_TOOL_NAMES: ReadonlySet<string> = new Set(['Task', 'Agent'])\nexport const SDK_VERSION = '0.3.247'\nexport const CLAUDE_DOCTOR_PATH = '/plugins/dsh-claude/doctor'\nexport const CLAUDE_CLIENT_DIAGNOSTICS_PATH = '/plugins/dsh-claude/client-diagnostics'\nexport const CLAUDE_UPDATE_CHECK_PATH = '/plugins/dsh-claude/update/check'\nexport const CLAUDE_USAGE_PATH = '/plugins/dsh-claude/usage'\nexport const CLAUDE_UPDATE_PATH = '/plugins/dsh-claude/update'\nexport const CLAUDE_PROJECTION_PATH = '/plugins/dsh-claude/projection'\nexport const CLAUDE_GLOBAL_SETTINGS_PATH = '/plugins/dsh-claude/settings/global'\nexport const CLAUDE_REPOSITORY_SETUP_PATH = '/plugins/dsh-claude/repository/setup'\nexport const CLAUDE_REPOSITORY_ACTION_PATH = '/plugins/dsh-claude/repository/action'\nexport const CLAUDE_REVIEW_COMMENT_PATH = '/plugins/dsh-claude/review-comments'\nexport const CLAUDE_REPOSITORY_FEEDBACK_PATH = '/plugins/dsh-claude/repository/feedback'\nexport const CLAUDE_REPOSITORY_STATUS_PATH = '/plugins/dsh-claude/repository/status'\nexport const CLAUDE_REPOSITORY_FILE_PATH = '/plugins/dsh-claude/repository/file'\nexport const CLAUDE_JIRA_PATH = '/plugins/dsh-claude/jira'\nexport const CLAUDE_ASK_PATH = '/plugins/dsh-claude/ask'\nexport const CLAUDE_EDITOR_OPEN_PATH = '/plugins/dsh-claude/editor/open'\nexport const CLAUDE_REWIND_PATH = '/plugins/dsh-claude/rewind'\nexport const CLAUDE_PLAN_FEEDBACK_PATH = '/plugins/dsh-claude/plan/feedback'\nexport const CLAUDE_PROMPTS_PATH = '/plugins/dsh-claude/prompts'\nexport const CLAUDE_PROMPT_NAME_PATH = '/plugins/dsh-claude/prompts/name'\nexport const CLAUDE_PROMPT_REFINE_PATH = '/plugins/dsh-claude/prompts/refine'\n\n/** Which renderer draws Claude's visible output.\n *\n * 'plugin' keeps the sidecar-backed transcript this package owns (interleaved\n * prose, grouped tool cards, activity rows). 'native' hands the same turn to\n * DSH's own conversation renderer: prose streams as ordinary assistant text\n * blocks, thinking as reasoning blocks, and root Claude tools are mirrored\n * into the durable `tool/call`/`tool/result` channel so the Host's tool\n * presentation pipeline draws them exactly like DSH-executed calls. */\nexport type ClaudeRenderMode = 'plugin' | 'native'\nexport const CLAUDE_RENDER_MODES = ['plugin', 'native'] as const\nexport const DEFAULT_CLAUDE_RENDER_MODE: ClaudeRenderMode = 'plugin'\n\nexport function isClaudeRenderMode(value: unknown): value is ClaudeRenderMode {\n return value === 'plugin' || value === 'native'\n}\n\n/** How this package paints the PROSE of a Claude answer.\n *\n * 'plain' is Claude's own presentation: body text in the Host's text colour,\n * colour reserved for code. 'enhanced' gives headings, emphasis, list markers,\n * quotes and links their own hues and darkens the code surface — the way a\n * Markdown-highlighting editor shows a document rather than the way Claude\n * desktop shows an answer. It is opt-in because it deliberately breaks the\n * parity the rest of `markdown-theme.ts` exists to hold.\n *\n * Only meaningful under {@link ClaudeRenderMode} 'plugin': the stylesheet is\n * scoped to markup this package renders, and 'native' turns are drawn by the\n * Host, where it has no reach. */\nexport type ClaudeProseMode = 'plain' | 'enhanced'\nexport const CLAUDE_PROSE_MODES = ['plain', 'enhanced'] as const\nexport const DEFAULT_CLAUDE_PROSE_MODE: ClaudeProseMode = 'plain'\n\nexport function isClaudeProseMode(value: unknown): value is ClaudeProseMode {\n return value === 'plain' || value === 'enhanced'\n}\n\n/** Whether a session that needs the user raises a desktop notification while\n * the user is looking at another session. Client-side presentation, like\n * {@link ClaudeProseMode}: nothing on the server reads it back. */\nexport type ClaudeAlertMode = 'off' | 'on'\nexport const CLAUDE_ALERT_MODES = ['off', 'on'] as const\nexport const DEFAULT_CLAUDE_ALERT_MODE: ClaudeAlertMode = 'on'\n\nexport function isClaudeAlertMode(value: unknown): value is ClaudeAlertMode {\n return value === 'off' || value === 'on'\n}\n","import type { SessionEvent } from '@deepseek-ai/dsh-session'\nimport {\n CLAUDE_ACTIVITY_EVENT,\n CLAUDE_CONTEXT_USAGE_EVENT,\n CLAUDE_SESSION_BOUND_EVENT,\n CLAUDE_TASKS_EVENT,\n isClaudeRenderMode,\n type ClaudeRenderMode,\n} from './constants.ts'\n\nexport type ClaudeActivityKind =\n | 'text'\n | 'status'\n /** Context compaction boundary; the transcript draws it as a divider. */\n | 'compaction'\n | 'thinking'\n | 'tool-call'\n | 'tool-result'\n | 'permission'\n | 'question'\n | 'subagent'\n | 'usage'\n | 'warning'\n | 'error'\n\nexport type ClaudeActivityPhase =\n | 'started'\n | 'updated'\n | 'completed'\n | 'denied'\n | 'failed'\n\nexport interface ClaudeUsage {\n inputTokens?: number\n outputTokens?: number\n cacheReadTokens?: number\n cacheCreationTokens?: number\n cumulativeCostUsd?: number\n /** Wall time from the turn being admitted to it settling. Measured here\n * rather than derived on the client: activities carry no timestamps. */\n durationMs?: number\n /** Wall time to the first visible token of the turn. */\n ttftMs?: number\n}\n\nexport interface ClaudeSessionBoundEvent {\n claudeSessionId: string\n cliVersion?: string\n sdkVersion: string\n cwd: string\n}\n\nexport interface ClaudeActivityEvent {\n turn: number\n step: number\n ordinal: number\n kind: ClaudeActivityKind\n phase?: ClaudeActivityPhase\n /** Claude task-board identity for lifecycle activity; never a transcript path. */\n taskId?: string\n toolUseId?: string\n /** Enclosing Claude tool call for subagent-nested activity. */\n parentToolUseId?: string\n toolName?: string\n title?: string\n summary?: string\n detail?: string\n /** Redacted visible Claude prose used by the plugin-owned interleaved transcript. */\n text?: string\n isError?: boolean\n usage?: ClaudeUsage\n /** Which renderer this record was produced for. Stamped only when the Host\n * drew the step natively, so a record written before the setting existed —\n * and every record written under the plugin renderer — reads as 'plugin'.\n * It travels with the data so a step always renders the way it was\n * recorded, whatever the setting says now. */\n renderer?: ClaudeRenderMode\n}\n\nexport interface ClaudeContextUsageCategory {\n name: string\n tokens: number\n color: string\n isDeferred?: boolean\n}\n\nexport interface ClaudeContextUsageEvent {\n model: string\n totalTokens: number\n maxTokens: number\n percentage: number\n categories: readonly ClaudeContextUsageCategory[]\n}\n\nexport interface ClaudeContextUsageInput {\n model: unknown\n totalTokens: unknown\n maxTokens: unknown\n percentage: unknown\n categories: readonly {\n name?: unknown\n tokens?: unknown\n color?: unknown\n isDeferred?: unknown\n }[]\n}\n\ndeclare module '@deepseek-ai/dsh-session/types' {\n interface SessionEventMap {\n 'claude-code/session-bound': ClaudeSessionBoundEvent\n 'claude-code/activity': ClaudeActivityEvent\n 'claude-code/context-usage': ClaudeContextUsageEvent\n 'claude-code/tasks': ClaudeTasksEvent\n }\n}\n\nconst SECRET_KEY = /(?:^|[_-])(password|passwd|secret|token|api[_-]?key|authorization|credential|private[_-]?key|session[_-]?key|env|environ|environment)(?:$|[_-])/i\nconst MAX_SUMMARY_CHARS = 1_000\nconst MAX_DETAIL_CHARS = 4_000\nconst MAX_TRANSCRIPT_TEXT_CHARS = 64_000\nconst MAX_DEPTH = 6\nconst MAX_ARRAY_ITEMS = 40\nconst MAX_OBJECT_KEYS = 60\nconst REDACTED = '[REDACTED]'\nconst TRUNCATED = '…[truncated]'\nconst SECRET_ASSIGNMENT = /((?:password|passwd|secret|token|api[_-]?key|authorization|credential|private[_-]?key|session[_-]?key)\\s*(?:=|:)\\s*)(?:\"[^\"]*\"|'[^']*'|[^\\s,;&]+)/giu\nconst BEARER_TOKEN = /(\\bbearer\\s+)[A-Za-z0-9._~+/=-]+/giu\nconst PREFIXED_TOKEN = /\\b(?:sk-(?:ant-|proj-)?|xox[baprs]-|ghp_|github_pat_)[A-Za-z0-9_-]{8,}/giu\nconst JWT_TOKEN = /\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\b/gu\nconst URL_USERINFO = /([a-z][a-z0-9+.-]*:\\/\\/[^:\\s/@]+:)[^@\\s/]+@/giu\nconst URL_SECRET_PARAM = /([?&](?:password|secret|token|api[_-]?key|access[_-]?token|refresh[_-]?token)=)[^&#\\s]+/giu\n\nexport function boundText(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value\n return `${value.slice(0, Math.max(0, maxChars - TRUNCATED.length))}${TRUNCATED}`\n}\n\nexport function redactText(value: string, maxChars = MAX_DETAIL_CHARS): string {\n return boundText(\n value\n .replace(JWT_TOKEN, REDACTED)\n .replace(PREFIXED_TOKEN, REDACTED)\n .replace(BEARER_TOKEN, `$1${REDACTED}`)\n .replace(URL_USERINFO, `$1${REDACTED}@`)\n .replace(URL_SECRET_PARAM, `$1${REDACTED}`)\n .replace(SECRET_ASSIGNMENT, `$1${REDACTED}`),\n maxChars,\n )\n}\n\nexport function redactValue(value: unknown, depth = 0, seen = new WeakSet<object>()): unknown {\n if (depth > MAX_DEPTH) return '[max-depth]'\n if (value === null || typeof value === 'boolean' || typeof value === 'number') return value\n if (typeof value === 'string') return redactText(value)\n if (typeof value === 'bigint') return value.toString()\n if (typeof value === 'undefined') return null\n if (typeof value === 'function' || typeof value === 'symbol') return `[${typeof value}]`\n if (value instanceof Error) {\n return { name: value.name, message: redactText(value.message, MAX_SUMMARY_CHARS) }\n }\n if (typeof value !== 'object') return String(value)\n if (seen.has(value)) return '[circular]'\n seen.add(value)\n try {\n if (Array.isArray(value)) {\n const items = value.slice(0, MAX_ARRAY_ITEMS).map(item => redactValue(item, depth + 1, seen))\n if (value.length > MAX_ARRAY_ITEMS) items.push(`[${value.length - MAX_ARRAY_ITEMS} more items]`)\n return items\n }\n const result: Record<string, unknown> = {}\n const entries = Object.entries(value as Record<string, unknown>)\n for (const [key, item] of entries.slice(0, MAX_OBJECT_KEYS)) {\n result[key] = SECRET_KEY.test(key) ? REDACTED : redactValue(item, depth + 1, seen)\n }\n if (entries.length > MAX_OBJECT_KEYS) result.__truncatedKeys = entries.length - MAX_OBJECT_KEYS\n return result\n } finally {\n seen.delete(value)\n }\n}\n\nexport function safeDetail(value: unknown): string | undefined {\n if (value === undefined) return undefined\n const redacted = redactValue(value)\n const text = typeof redacted === 'string' ? redacted : JSON.stringify(redacted)\n return boundText(text, MAX_DETAIL_CHARS)\n}\n\nexport function normalizeActivity(\n activity: Omit<ClaudeActivityEvent, 'summary' | 'detail'> & {\n summary?: unknown\n detail?: unknown\n },\n): ClaudeActivityEvent {\n const normalized: ClaudeActivityEvent = {\n turn: activity.turn,\n step: activity.step,\n ordinal: activity.ordinal,\n kind: activity.kind,\n }\n if (activity.phase !== undefined) normalized.phase = activity.phase\n if (activity.taskId !== undefined) normalized.taskId = redactText(activity.taskId, 128)\n if (activity.toolUseId !== undefined) normalized.toolUseId = redactText(activity.toolUseId, 256)\n if (activity.parentToolUseId !== undefined) normalized.parentToolUseId = redactText(activity.parentToolUseId, 256)\n if (activity.toolName !== undefined) normalized.toolName = redactText(activity.toolName, 256)\n if (activity.title !== undefined) normalized.title = redactText(activity.title, MAX_SUMMARY_CHARS)\n if (activity.summary !== undefined) {\n normalized.summary = redactText(\n typeof activity.summary === 'string' ? activity.summary : safeDetail(activity.summary) ?? '',\n MAX_SUMMARY_CHARS,\n )\n }\n const detail = safeDetail(activity.detail)\n if (detail !== undefined) normalized.detail = detail\n if (activity.text !== undefined) normalized.text = redactText(activity.text, MAX_TRANSCRIPT_TEXT_CHARS)\n if (activity.isError !== undefined) normalized.isError = activity.isError\n if (activity.usage !== undefined) normalized.usage = { ...activity.usage }\n if (isClaudeRenderMode(activity.renderer)) normalized.renderer = activity.renderer\n return normalized\n}\n\nconst MAX_CONTEXT_CATEGORIES = 24\nconst FALLBACK_CONTEXT_COLOR = '#8b95a5'\nconst SAFE_CONTEXT_COLOR = /^#[0-9a-f]{3,8}$/iu\n\nfunction nonNegativeInteger(value: unknown): number {\n return typeof value === 'number' && Number.isFinite(value)\n ? Math.max(0, Math.floor(value))\n : 0\n}\n\nexport function normalizeContextUsage(input: ClaudeContextUsageInput): ClaudeContextUsageEvent {\n return {\n model: redactText(typeof input.model === 'string' ? input.model : 'unknown', 128),\n totalTokens: nonNegativeInteger(input.totalTokens),\n maxTokens: nonNegativeInteger(input.maxTokens),\n percentage: Math.min(100, nonNegativeInteger(input.percentage)),\n categories: input.categories.slice(0, MAX_CONTEXT_CATEGORIES).map(category => ({\n name: redactText(typeof category.name === 'string' ? category.name : 'Unknown', 128),\n tokens: nonNegativeInteger(category.tokens),\n color: typeof category.color === 'string' && SAFE_CONTEXT_COLOR.test(category.color)\n ? category.color\n : FALLBACK_CONTEXT_COLOR,\n ...(category.isDeferred === true ? { isDeferred: true } : {}),\n })),\n }\n}\n\nexport function latestClaudeContextUsage(\n events: readonly SessionEvent[],\n): ClaudeContextUsageEvent | undefined {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index]\n if (event?.type === CLAUDE_CONTEXT_USAGE_EVENT) return event.data as ClaudeContextUsageEvent\n }\n return undefined\n}\n\nexport type ClaudeTaskStatus = 'running' | 'completed' | 'failed' | 'stopped' | 'killed'\n\nexport interface ClaudeTaskUsage {\n totalTokens?: number\n toolUses?: number\n durationMs?: number\n}\n\nexport interface ClaudeTaskInfo {\n taskId: string\n description: string\n status: ClaudeTaskStatus\n /** DSH turn during which this task was first observed, when known. */\n originTurn?: number\n subagentType?: string\n taskType?: string\n lastToolName?: string\n summary?: string\n usage?: ClaudeTaskUsage\n /** True while the task runs detached (background command/subagent). */\n backgrounded?: boolean\n}\n\n/** Level snapshot of one session's Claude task board, REPLACE semantics. */\nexport interface ClaudeTasksEvent {\n tasks: readonly ClaudeTaskInfo[]\n}\n\nconst MAX_TASKS_PER_SNAPSHOT = 50\nconst MAX_TASK_TEXT_CHARS = 300\n\nconst TASK_STATUSES: ReadonlySet<string> = new Set(['running', 'completed', 'failed', 'stopped', 'killed'])\n\nfunction normalizeTaskUsage(input: ClaudeTaskUsage | undefined): ClaudeTaskUsage | undefined {\n if (input === undefined) return undefined\n const usage: ClaudeTaskUsage = {}\n if (input.totalTokens !== undefined) usage.totalTokens = nonNegativeInteger(input.totalTokens)\n if (input.toolUses !== undefined) usage.toolUses = nonNegativeInteger(input.toolUses)\n if (input.durationMs !== undefined) usage.durationMs = nonNegativeInteger(input.durationMs)\n return Object.keys(usage).length === 0 ? undefined : usage\n}\n\nexport function normalizeTasksEvent(tasks: readonly ClaudeTaskInfo[]): ClaudeTasksEvent {\n return {\n tasks: tasks.slice(0, MAX_TASKS_PER_SNAPSHOT).map(task => {\n const usage = normalizeTaskUsage(task.usage)\n return {\n taskId: redactText(String(task.taskId), 128),\n description: redactText(String(task.description), MAX_TASK_TEXT_CHARS),\n status: TASK_STATUSES.has(task.status) ? task.status : 'running',\n ...(task.originTurn === undefined ? {} : { originTurn: nonNegativeInteger(task.originTurn) }),\n ...(task.subagentType === undefined ? {} : { subagentType: redactText(task.subagentType, 64) }),\n ...(task.taskType === undefined ? {} : { taskType: redactText(task.taskType, 64) }),\n ...(task.lastToolName === undefined ? {} : { lastToolName: redactText(task.lastToolName, 64) }),\n ...(task.summary === undefined ? {} : { summary: redactText(task.summary, MAX_TASK_TEXT_CHARS) }),\n ...(usage === undefined ? {} : { usage }),\n ...(task.backgrounded === true ? { backgrounded: true } : {}),\n }\n }),\n }\n}\n\nexport function latestClaudeTasks(\n events: readonly SessionEvent[],\n): ClaudeTasksEvent | undefined {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index]\n if (event?.type === CLAUDE_TASKS_EVENT) return event.data as ClaudeTasksEvent\n }\n return undefined\n}\n\nexport type ClaudeActivityInput = Omit<\n ClaudeActivityEvent,\n 'turn' | 'step' | 'ordinal' | 'summary' | 'detail'\n> & {\n summary?: unknown\n detail?: unknown\n}\n\nexport interface ClaudeActivityCursor {\n turn: number\n step: number\n nextOrdinal: number\n}\n\n/** Derive the current DSH turn/step; activity ordinals are completed from the sidecar. */\nexport function currentClaudeActivityCursor(events: readonly SessionEvent[]): ClaudeActivityCursor {\n let turn = 0\n let step = 0\n for (const event of events) {\n if (event.type !== 'step/start') continue\n const data = event.data as { turn: number; step: number }\n turn = data.turn\n step = data.step\n }\n if (turn < 1 || step < 1) {\n throw new Error('dsh-claude: Claude activity requires an open DSH step')\n }\n return { turn, step, nextOrdinal: 0 }\n}\n\nexport function latestClaudeSessionBinding(\n events: readonly SessionEvent[],\n): ClaudeSessionBoundEvent | undefined {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index]\n if (event?.type === CLAUDE_SESSION_BOUND_EVENT) {\n return event.data as ClaudeSessionBoundEvent\n }\n }\n return undefined\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"events-oovRTmX7.mjs","names":[],"sources":["../src/constants.ts","../src/events.ts"],"sourcesContent":["export const CLAUDE_CODE_PROVIDER = 'claude'\r\nexport const CLAUDE_CODE_PRESET_ID = 'claude'\r\nexport const CLAUDE_CODE_PROVIDER_IDS = [CLAUDE_CODE_PROVIDER] as const\r\nexport const CLAUDE_SESSION_BOUND_EVENT = 'claude-code/session-bound'\r\nexport const CLAUDE_ACTIVITY_EVENT = 'claude-code/activity'\r\nexport const CLAUDE_CONTEXT_USAGE_EVENT = 'claude-code/context-usage'\r\nexport const CLAUDE_TASKS_EVENT = 'claude-code/tasks'\r\n/** Claude's subagent dispatch tools; rendered as plugin-owned group cards\r\n * gathering subagent activity instead of native tool cards. */\r\nexport const TASK_TOOL_NAMES: ReadonlySet<string> = new Set(['Task', 'Agent'])\r\nexport const SDK_VERSION = '0.3.247'\r\nexport const CLAUDE_DOCTOR_PATH = '/plugins/dsh-claude/doctor'\r\nexport const CLAUDE_CLIENT_DIAGNOSTICS_PATH = '/plugins/dsh-claude/client-diagnostics'\r\nexport const CLAUDE_UPDATE_CHECK_PATH = '/plugins/dsh-claude/update/check'\r\nexport const CLAUDE_USAGE_PATH = '/plugins/dsh-claude/usage'\r\nexport const CLAUDE_UPDATE_PATH = '/plugins/dsh-claude/update'\r\nexport const CLAUDE_PROJECTION_PATH = '/plugins/dsh-claude/projection'\r\nexport const CLAUDE_GLOBAL_SETTINGS_PATH = '/plugins/dsh-claude/settings/global'\r\nexport const CLAUDE_REPOSITORY_SETUP_PATH = '/plugins/dsh-claude/repository/setup'\r\nexport const CLAUDE_REPOSITORY_ACTION_PATH = '/plugins/dsh-claude/repository/action'\r\nexport const CLAUDE_REVIEW_COMMENT_PATH = '/plugins/dsh-claude/review-comments'\r\nexport const CLAUDE_REPOSITORY_FEEDBACK_PATH = '/plugins/dsh-claude/repository/feedback'\r\nexport const CLAUDE_REPOSITORY_STATUS_PATH = '/plugins/dsh-claude/repository/status'\r\nexport const CLAUDE_REPOSITORY_FILE_PATH = '/plugins/dsh-claude/repository/file'\r\nexport const CLAUDE_JIRA_PATH = '/plugins/dsh-claude/jira'\r\nexport const CLAUDE_ASK_PATH = '/plugins/dsh-claude/ask'\r\nexport const CLAUDE_EDITOR_OPEN_PATH = '/plugins/dsh-claude/editor/open'\r\nexport const CLAUDE_REWIND_PATH = '/plugins/dsh-claude/rewind'\r\nexport const CLAUDE_PLAN_FEEDBACK_PATH = '/plugins/dsh-claude/plan/feedback'\r\nexport const CLAUDE_PROMPTS_PATH = '/plugins/dsh-claude/prompts'\r\nexport const CLAUDE_PROMPT_NAME_PATH = '/plugins/dsh-claude/prompts/name'\r\nexport const CLAUDE_PROMPT_REFINE_PATH = '/plugins/dsh-claude/prompts/refine'\r\n\r\n/** Which renderer draws Claude's visible output.\r\n *\r\n * 'plugin' keeps the sidecar-backed transcript this package owns (interleaved\r\n * prose, grouped tool cards, activity rows). 'native' hands the same turn to\r\n * DSH's own conversation renderer: prose streams as ordinary assistant text\r\n * blocks, thinking as reasoning blocks, and root Claude tools are mirrored\r\n * into the durable `tool/call`/`tool/result` channel so the Host's tool\r\n * presentation pipeline draws them exactly like DSH-executed calls. */\r\nexport type ClaudeRenderMode = 'plugin' | 'native'\r\nexport const CLAUDE_RENDER_MODES = ['plugin', 'native'] as const\r\nexport const DEFAULT_CLAUDE_RENDER_MODE: ClaudeRenderMode = 'plugin'\r\n\r\nexport function isClaudeRenderMode(value: unknown): value is ClaudeRenderMode {\r\n return value === 'plugin' || value === 'native'\r\n}\r\n\r\n/** How this package paints the PROSE of a Claude answer.\r\n *\r\n * 'plain' is Claude's own presentation: body text in the Host's text colour,\r\n * colour reserved for code. 'enhanced' gives headings, emphasis, list markers,\r\n * quotes and links their own hues and darkens the code surface — the way a\r\n * Markdown-highlighting editor shows a document rather than the way Claude\r\n * desktop shows an answer. It is opt-in because it deliberately breaks the\r\n * parity the rest of `markdown-theme.ts` exists to hold.\r\n *\r\n * Only meaningful under {@link ClaudeRenderMode} 'plugin': the stylesheet is\r\n * scoped to markup this package renders, and 'native' turns are drawn by the\r\n * Host, where it has no reach. */\r\nexport type ClaudeProseMode = 'plain' | 'enhanced'\r\nexport const CLAUDE_PROSE_MODES = ['plain', 'enhanced'] as const\r\nexport const DEFAULT_CLAUDE_PROSE_MODE: ClaudeProseMode = 'plain'\r\n\r\nexport function isClaudeProseMode(value: unknown): value is ClaudeProseMode {\r\n return value === 'plain' || value === 'enhanced'\r\n}\r\n\r\n/** Whether a session that needs the user raises a desktop notification while\r\n * the user is looking at another session. Client-side presentation, like\r\n * {@link ClaudeProseMode}: nothing on the server reads it back. */\r\nexport type ClaudeAlertMode = 'off' | 'on'\r\nexport const CLAUDE_ALERT_MODES = ['off', 'on'] as const\r\nexport const DEFAULT_CLAUDE_ALERT_MODE: ClaudeAlertMode = 'on'\r\n\r\nexport function isClaudeAlertMode(value: unknown): value is ClaudeAlertMode {\r\n return value === 'off' || value === 'on'\r\n}\r\n","import type { SessionEvent } from '@deepseek-ai/dsh-session'\nimport {\n CLAUDE_ACTIVITY_EVENT,\n CLAUDE_CONTEXT_USAGE_EVENT,\n CLAUDE_SESSION_BOUND_EVENT,\n CLAUDE_TASKS_EVENT,\n isClaudeRenderMode,\n type ClaudeRenderMode,\n} from './constants.ts'\n\nexport type ClaudeActivityKind =\n | 'text'\n | 'status'\n /** Context compaction boundary; the transcript draws it as a divider. */\n | 'compaction'\n | 'thinking'\n | 'tool-call'\n | 'tool-result'\n | 'permission'\n | 'question'\n | 'subagent'\n | 'usage'\n | 'warning'\n | 'error'\n\nexport type ClaudeActivityPhase =\n | 'started'\n | 'updated'\n | 'completed'\n | 'denied'\n | 'failed'\n\nexport interface ClaudeUsage {\n inputTokens?: number\n outputTokens?: number\n cacheReadTokens?: number\n cacheCreationTokens?: number\n cumulativeCostUsd?: number\n /** Wall time from the turn being admitted to it settling. Measured here\n * rather than derived on the client: activities carry no timestamps. */\n durationMs?: number\n /** Wall time to the first visible token of the turn. */\n ttftMs?: number\n}\n\nexport interface ClaudeSessionBoundEvent {\n claudeSessionId: string\n cliVersion?: string\n sdkVersion: string\n cwd: string\n}\n\nexport interface ClaudeActivityEvent {\n turn: number\n step: number\n ordinal: number\n kind: ClaudeActivityKind\n phase?: ClaudeActivityPhase\n /** Claude task-board identity for lifecycle activity; never a transcript path. */\n taskId?: string\n toolUseId?: string\n /** Enclosing Claude tool call for subagent-nested activity. */\n parentToolUseId?: string\n toolName?: string\n title?: string\n summary?: string\n detail?: string\n /** Redacted visible Claude prose used by the plugin-owned interleaved transcript. */\n text?: string\n isError?: boolean\n usage?: ClaudeUsage\n /** Which renderer this record was produced for. Stamped only when the Host\n * drew the step natively, so a record written before the setting existed —\n * and every record written under the plugin renderer — reads as 'plugin'.\n * It travels with the data so a step always renders the way it was\n * recorded, whatever the setting says now. */\n renderer?: ClaudeRenderMode\n}\n\nexport interface ClaudeContextUsageCategory {\n name: string\n tokens: number\n color: string\n isDeferred?: boolean\n}\n\nexport interface ClaudeContextUsageEvent {\n model: string\n totalTokens: number\n maxTokens: number\n percentage: number\n categories: readonly ClaudeContextUsageCategory[]\n}\n\nexport interface ClaudeContextUsageInput {\n model: unknown\n totalTokens: unknown\n maxTokens: unknown\n percentage: unknown\n categories: readonly {\n name?: unknown\n tokens?: unknown\n color?: unknown\n isDeferred?: unknown\n }[]\n}\n\ndeclare module '@deepseek-ai/dsh-session/types' {\n interface SessionEventMap {\n 'claude-code/session-bound': ClaudeSessionBoundEvent\n 'claude-code/activity': ClaudeActivityEvent\n 'claude-code/context-usage': ClaudeContextUsageEvent\n 'claude-code/tasks': ClaudeTasksEvent\n }\n}\n\nconst SECRET_KEY = /(?:^|[_-])(password|passwd|secret|token|api[_-]?key|authorization|credential|private[_-]?key|session[_-]?key|env|environ|environment)(?:$|[_-])/i\nconst MAX_SUMMARY_CHARS = 1_000\nconst MAX_DETAIL_CHARS = 4_000\nconst MAX_TRANSCRIPT_TEXT_CHARS = 64_000\nconst MAX_DEPTH = 6\nconst MAX_ARRAY_ITEMS = 40\nconst MAX_OBJECT_KEYS = 60\nconst REDACTED = '[REDACTED]'\nconst TRUNCATED = '…[truncated]'\nconst SECRET_ASSIGNMENT = /((?:password|passwd|secret|token|api[_-]?key|authorization|credential|private[_-]?key|session[_-]?key)\\s*(?:=|:)\\s*)(?:\"[^\"]*\"|'[^']*'|[^\\s,;&]+)/giu\nconst BEARER_TOKEN = /(\\bbearer\\s+)[A-Za-z0-9._~+/=-]+/giu\nconst PREFIXED_TOKEN = /\\b(?:sk-(?:ant-|proj-)?|xox[baprs]-|ghp_|github_pat_)[A-Za-z0-9_-]{8,}/giu\nconst JWT_TOKEN = /\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\b/gu\nconst URL_USERINFO = /([a-z][a-z0-9+.-]*:\\/\\/[^:\\s/@]+:)[^@\\s/]+@/giu\nconst URL_SECRET_PARAM = /([?&](?:password|secret|token|api[_-]?key|access[_-]?token|refresh[_-]?token)=)[^&#\\s]+/giu\n\nexport function boundText(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value\n return `${value.slice(0, Math.max(0, maxChars - TRUNCATED.length))}${TRUNCATED}`\n}\n\nexport function redactText(value: string, maxChars = MAX_DETAIL_CHARS): string {\n return boundText(\n value\n .replace(JWT_TOKEN, REDACTED)\n .replace(PREFIXED_TOKEN, REDACTED)\n .replace(BEARER_TOKEN, `$1${REDACTED}`)\n .replace(URL_USERINFO, `$1${REDACTED}@`)\n .replace(URL_SECRET_PARAM, `$1${REDACTED}`)\n .replace(SECRET_ASSIGNMENT, `$1${REDACTED}`),\n maxChars,\n )\n}\n\nexport function redactValue(value: unknown, depth = 0, seen = new WeakSet<object>()): unknown {\n if (depth > MAX_DEPTH) return '[max-depth]'\n if (value === null || typeof value === 'boolean' || typeof value === 'number') return value\n if (typeof value === 'string') return redactText(value)\n if (typeof value === 'bigint') return value.toString()\n if (typeof value === 'undefined') return null\n if (typeof value === 'function' || typeof value === 'symbol') return `[${typeof value}]`\n if (value instanceof Error) {\n return { name: value.name, message: redactText(value.message, MAX_SUMMARY_CHARS) }\n }\n if (typeof value !== 'object') return String(value)\n if (seen.has(value)) return '[circular]'\n seen.add(value)\n try {\n if (Array.isArray(value)) {\n const items = value.slice(0, MAX_ARRAY_ITEMS).map(item => redactValue(item, depth + 1, seen))\n if (value.length > MAX_ARRAY_ITEMS) items.push(`[${value.length - MAX_ARRAY_ITEMS} more items]`)\n return items\n }\n const result: Record<string, unknown> = {}\n const entries = Object.entries(value as Record<string, unknown>)\n for (const [key, item] of entries.slice(0, MAX_OBJECT_KEYS)) {\n result[key] = SECRET_KEY.test(key) ? REDACTED : redactValue(item, depth + 1, seen)\n }\n if (entries.length > MAX_OBJECT_KEYS) result.__truncatedKeys = entries.length - MAX_OBJECT_KEYS\n return result\n } finally {\n seen.delete(value)\n }\n}\n\nexport function safeDetail(value: unknown): string | undefined {\n if (value === undefined) return undefined\n const redacted = redactValue(value)\n const text = typeof redacted === 'string' ? redacted : JSON.stringify(redacted)\n return boundText(text, MAX_DETAIL_CHARS)\n}\n\nexport function normalizeActivity(\n activity: Omit<ClaudeActivityEvent, 'summary' | 'detail'> & {\n summary?: unknown\n detail?: unknown\n },\n): ClaudeActivityEvent {\n const normalized: ClaudeActivityEvent = {\n turn: activity.turn,\n step: activity.step,\n ordinal: activity.ordinal,\n kind: activity.kind,\n }\n if (activity.phase !== undefined) normalized.phase = activity.phase\n if (activity.taskId !== undefined) normalized.taskId = redactText(activity.taskId, 128)\n if (activity.toolUseId !== undefined) normalized.toolUseId = redactText(activity.toolUseId, 256)\n if (activity.parentToolUseId !== undefined) normalized.parentToolUseId = redactText(activity.parentToolUseId, 256)\n if (activity.toolName !== undefined) normalized.toolName = redactText(activity.toolName, 256)\n if (activity.title !== undefined) normalized.title = redactText(activity.title, MAX_SUMMARY_CHARS)\n if (activity.summary !== undefined) {\n normalized.summary = redactText(\n typeof activity.summary === 'string' ? activity.summary : safeDetail(activity.summary) ?? '',\n MAX_SUMMARY_CHARS,\n )\n }\n const detail = safeDetail(activity.detail)\n if (detail !== undefined) normalized.detail = detail\n if (activity.text !== undefined) normalized.text = redactText(activity.text, MAX_TRANSCRIPT_TEXT_CHARS)\n if (activity.isError !== undefined) normalized.isError = activity.isError\n if (activity.usage !== undefined) normalized.usage = { ...activity.usage }\n if (isClaudeRenderMode(activity.renderer)) normalized.renderer = activity.renderer\n return normalized\n}\n\nconst MAX_CONTEXT_CATEGORIES = 24\nconst FALLBACK_CONTEXT_COLOR = '#8b95a5'\nconst SAFE_CONTEXT_COLOR = /^#[0-9a-f]{3,8}$/iu\n\nfunction nonNegativeInteger(value: unknown): number {\n return typeof value === 'number' && Number.isFinite(value)\n ? Math.max(0, Math.floor(value))\n : 0\n}\n\nexport function normalizeContextUsage(input: ClaudeContextUsageInput): ClaudeContextUsageEvent {\n return {\n model: redactText(typeof input.model === 'string' ? input.model : 'unknown', 128),\n totalTokens: nonNegativeInteger(input.totalTokens),\n maxTokens: nonNegativeInteger(input.maxTokens),\n percentage: Math.min(100, nonNegativeInteger(input.percentage)),\n categories: input.categories.slice(0, MAX_CONTEXT_CATEGORIES).map(category => ({\n name: redactText(typeof category.name === 'string' ? category.name : 'Unknown', 128),\n tokens: nonNegativeInteger(category.tokens),\n color: typeof category.color === 'string' && SAFE_CONTEXT_COLOR.test(category.color)\n ? category.color\n : FALLBACK_CONTEXT_COLOR,\n ...(category.isDeferred === true ? { isDeferred: true } : {}),\n })),\n }\n}\n\nexport function latestClaudeContextUsage(\n events: readonly SessionEvent[],\n): ClaudeContextUsageEvent | undefined {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index]\n if (event?.type === CLAUDE_CONTEXT_USAGE_EVENT) return event.data as ClaudeContextUsageEvent\n }\n return undefined\n}\n\nexport type ClaudeTaskStatus = 'running' | 'completed' | 'failed' | 'stopped' | 'killed'\n\nexport interface ClaudeTaskUsage {\n totalTokens?: number\n toolUses?: number\n durationMs?: number\n}\n\nexport interface ClaudeTaskInfo {\n taskId: string\n description: string\n status: ClaudeTaskStatus\n /** DSH turn during which this task was first observed, when known. */\n originTurn?: number\n subagentType?: string\n taskType?: string\n lastToolName?: string\n summary?: string\n usage?: ClaudeTaskUsage\n /** True while the task runs detached (background command/subagent). */\n backgrounded?: boolean\n}\n\n/** Level snapshot of one session's Claude task board, REPLACE semantics. */\nexport interface ClaudeTasksEvent {\n tasks: readonly ClaudeTaskInfo[]\n}\n\nconst MAX_TASKS_PER_SNAPSHOT = 50\nconst MAX_TASK_TEXT_CHARS = 300\n\nconst TASK_STATUSES: ReadonlySet<string> = new Set(['running', 'completed', 'failed', 'stopped', 'killed'])\n\nfunction normalizeTaskUsage(input: ClaudeTaskUsage | undefined): ClaudeTaskUsage | undefined {\n if (input === undefined) return undefined\n const usage: ClaudeTaskUsage = {}\n if (input.totalTokens !== undefined) usage.totalTokens = nonNegativeInteger(input.totalTokens)\n if (input.toolUses !== undefined) usage.toolUses = nonNegativeInteger(input.toolUses)\n if (input.durationMs !== undefined) usage.durationMs = nonNegativeInteger(input.durationMs)\n return Object.keys(usage).length === 0 ? undefined : usage\n}\n\nexport function normalizeTasksEvent(tasks: readonly ClaudeTaskInfo[]): ClaudeTasksEvent {\n return {\n tasks: tasks.slice(0, MAX_TASKS_PER_SNAPSHOT).map(task => {\n const usage = normalizeTaskUsage(task.usage)\n return {\n taskId: redactText(String(task.taskId), 128),\n description: redactText(String(task.description), MAX_TASK_TEXT_CHARS),\n status: TASK_STATUSES.has(task.status) ? task.status : 'running',\n ...(task.originTurn === undefined ? {} : { originTurn: nonNegativeInteger(task.originTurn) }),\n ...(task.subagentType === undefined ? {} : { subagentType: redactText(task.subagentType, 64) }),\n ...(task.taskType === undefined ? {} : { taskType: redactText(task.taskType, 64) }),\n ...(task.lastToolName === undefined ? {} : { lastToolName: redactText(task.lastToolName, 64) }),\n ...(task.summary === undefined ? {} : { summary: redactText(task.summary, MAX_TASK_TEXT_CHARS) }),\n ...(usage === undefined ? {} : { usage }),\n ...(task.backgrounded === true ? { backgrounded: true } : {}),\n }\n }),\n }\n}\n\nexport function latestClaudeTasks(\n events: readonly SessionEvent[],\n): ClaudeTasksEvent | undefined {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index]\n if (event?.type === CLAUDE_TASKS_EVENT) return event.data as ClaudeTasksEvent\n }\n return undefined\n}\n\nexport type ClaudeActivityInput = Omit<\n ClaudeActivityEvent,\n 'turn' | 'step' | 'ordinal' | 'summary' | 'detail'\n> & {\n summary?: unknown\n detail?: unknown\n}\n\nexport interface ClaudeActivityCursor {\n turn: number\n step: number\n nextOrdinal: number\n}\n\n/** Derive the current DSH turn/step; activity ordinals are completed from the sidecar. */\nexport function currentClaudeActivityCursor(events: readonly SessionEvent[]): ClaudeActivityCursor {\n let turn = 0\n let step = 0\n for (const event of events) {\n if (event.type !== 'step/start') continue\n const data = event.data as { turn: number; step: number }\n turn = data.turn\n step = data.step\n }\n if (turn < 1 || step < 1) {\n throw new Error('dsh-claude: Claude activity requires an open DSH step')\n }\n return { turn, step, nextOrdinal: 0 }\n}\n\nexport function latestClaudeSessionBinding(\n events: readonly SessionEvent[],\n): ClaudeSessionBoundEvent | undefined {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index]\n if (event?.type === CLAUDE_SESSION_BOUND_EVENT) {\n return event.data as ClaudeSessionBoundEvent\n }\n }\n return undefined\n}\n"],"mappings":"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"}
|
package/lib/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as CLAUDE_REPOSITORY_FEEDBACK_PATH, B as DEFAULT_CLAUDE_RENDER_MODE, C as CLAUDE_PROJECTION_PATH, D as CLAUDE_PROSE_MODES, E as CLAUDE_PROMPT_REFINE_PATH, F as CLAUDE_REWIND_PATH, G as isClaudeRenderMode, H as TASK_TOOL_NAMES, I as CLAUDE_UPDATE_CHECK_PATH, L as CLAUDE_UPDATE_PATH, M as CLAUDE_REPOSITORY_SETUP_PATH, N as CLAUDE_REPOSITORY_STATUS_PATH, O as CLAUDE_RENDER_MODES, P as CLAUDE_REVIEW_COMMENT_PATH, R as CLAUDE_USAGE_PATH, S as CLAUDE_PLAN_FEEDBACK_PATH, T as CLAUDE_PROMPT_NAME_PATH, U as isClaudeAlertMode, W as isClaudeProseMode, _ as CLAUDE_CODE_PROVIDER_IDS, a as latestClaudeTasks, b as CLAUDE_GLOBAL_SETTINGS_PATH, c as normalizeTasksEvent, d as CLAUDE_ACTIVITY_EVENT, f as CLAUDE_ALERT_MODES, g as CLAUDE_CODE_PROVIDER, h as CLAUDE_CODE_PRESET_ID, i as latestClaudeSessionBinding, j as CLAUDE_REPOSITORY_FILE_PATH, k as CLAUDE_REPOSITORY_ACTION_PATH, l as redactText, m as CLAUDE_CLIENT_DIAGNOSTICS_PATH, n as currentClaudeActivityCursor, o as normalizeActivity, p as CLAUDE_ASK_PATH, r as latestClaudeContextUsage, s as normalizeContextUsage, t as boundText, u as safeDetail, v as CLAUDE_DOCTOR_PATH, w as CLAUDE_PROMPTS_PATH, x as CLAUDE_JIRA_PATH, y as CLAUDE_EDITOR_OPEN_PATH, z as DEFAULT_CLAUDE_PROSE_MODE } from "./events-oovRTmX7.mjs";
|
|
2
2
|
import { a as projectClaudeCommands, i as CLAUDE_COMMANDS_SERVICE, r as dynamicPresenterDefinition, t as CLAUDE_PRESENTER_NAMES } from "./presenters-BVWj7u0a.mjs";
|
|
3
|
-
import { a as resolveClaudeExecutable, n as ensureManagedPreset, o as runClaudeDoctor, t as ManagedPresetConflictError } from "./preset-installer-
|
|
3
|
+
import { a as resolveClaudeExecutable, n as ensureManagedPreset, o as runClaudeDoctor, t as ManagedPresetConflictError } from "./preset-installer-CuosP3sA.mjs";
|
|
4
4
|
import z from "@deepseek-ai/schemastery";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
6
|
import { chmod, mkdir, opendir, readFile, readdir, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
@@ -846,7 +846,7 @@ function createPermissionBridge(approval, activeContext, userQuestion, planFeedb
|
|
|
846
846
|
...plan === void 0 ? {} : { text: plan }
|
|
847
847
|
});
|
|
848
848
|
const userDecides = plan !== void 0;
|
|
849
|
-
silenced = userDecides && approvalPolicyOf(session.
|
|
849
|
+
silenced = userDecides && approvalPolicyOf(session.snapshotEvents()) === SILENT_POLICY;
|
|
850
850
|
if (silenced) session.append("approval/policy", { policy: ASKING_POLICY });
|
|
851
851
|
const alreadyFullAccess = !userDecides && await active.hasFullAccess?.() === true;
|
|
852
852
|
const revision = new AbortController();
|
|
@@ -1408,56 +1408,108 @@ function normalizeSdkMessage(message) {
|
|
|
1408
1408
|
}
|
|
1409
1409
|
//#endregion
|
|
1410
1410
|
//#region src/model-catalog.ts
|
|
1411
|
-
/**
|
|
1412
|
-
*
|
|
1413
|
-
*
|
|
1414
|
-
*
|
|
1415
|
-
*
|
|
1416
|
-
*
|
|
1411
|
+
/** The Claude Code model lineup, read from the running CLI instead of pinned
|
|
1412
|
+
* here.
|
|
1413
|
+
*
|
|
1414
|
+
* Anthropic ships models between releases of this plugin -- Fable arrived in a
|
|
1415
|
+
* CLI update, not in one of ours -- so a table maintained here is stale the day
|
|
1416
|
+
* it is written, and a model the user can already pick in `/model` is missing
|
|
1417
|
+
* from the DSH selector until someone edits an array. The CLI answers the same
|
|
1418
|
+
* question itself: every session's initialize response carries the lineup it
|
|
1419
|
+
* would show in `/model`, already narrowed to the logged-in account's plan and
|
|
1420
|
+
* to any `availableModels` restriction the settings cascade imposes.
|
|
1421
|
+
*
|
|
1422
|
+
* What DSH persists on a session, though, must NOT be a CLI model id. DSH
|
|
1423
|
+
* stores the selector row's id verbatim and matches it back by string
|
|
1424
|
+
* equality, so a concrete id (`claude-fable-5-1[1m]`) turns into a dangling
|
|
1425
|
+
* reference the moment Anthropic bumps the version -- the session keeps
|
|
1426
|
+
* pointing at a row nothing advertises any more, and the composer falls back
|
|
1427
|
+
* to printing the raw id. The selector therefore advertises an alias this
|
|
1428
|
+
* plugin owns (`fable[1m]`), derived from the row rather than tabulated, and
|
|
1429
|
+
* the CLI id it stands for is kept beside it and used only at dispatch.
|
|
1430
|
+
*/
|
|
1431
|
+
/** A 1M-context route spells it in the id (`opus[1m]`, `claude-fable-5-1[1m]`). */
|
|
1432
|
+
const WIDE_ROUTE = /\[1m\]$/u;
|
|
1433
|
+
/** What the selector shows before the lineup is known -- the probe below failed
|
|
1434
|
+
* or has not answered yet. `default` is the only id that is valid on every
|
|
1435
|
+
* release and plan; the rest are the stable `/model` spellings Claude Code has
|
|
1436
|
+
* kept across releases, and every one of them is a spelling the CLI accepts,
|
|
1437
|
+
* so a session that persists one still dispatches. */
|
|
1417
1438
|
const SEED = [
|
|
1418
1439
|
{
|
|
1419
1440
|
id: "default",
|
|
1441
|
+
value: "default",
|
|
1420
1442
|
name: "Default (recommended)",
|
|
1421
1443
|
description: ""
|
|
1422
1444
|
},
|
|
1423
1445
|
{
|
|
1424
1446
|
id: "opus[1m]",
|
|
1447
|
+
value: "opus[1m]",
|
|
1425
1448
|
name: "Opus (1M context)",
|
|
1426
1449
|
description: "",
|
|
1427
1450
|
contextWindow: 1e6
|
|
1428
1451
|
},
|
|
1429
1452
|
{
|
|
1430
1453
|
id: "fable",
|
|
1454
|
+
value: "fable",
|
|
1431
1455
|
name: "Fable",
|
|
1432
1456
|
description: ""
|
|
1433
1457
|
},
|
|
1434
1458
|
{
|
|
1435
1459
|
id: "sonnet",
|
|
1460
|
+
value: "sonnet",
|
|
1436
1461
|
name: "Sonnet",
|
|
1437
1462
|
description: ""
|
|
1438
1463
|
},
|
|
1439
1464
|
{
|
|
1440
1465
|
id: "haiku",
|
|
1466
|
+
value: "haiku",
|
|
1441
1467
|
name: "Haiku",
|
|
1442
1468
|
description: ""
|
|
1443
1469
|
}
|
|
1444
1470
|
];
|
|
1445
|
-
/** A 1M-context route spells it in the id
|
|
1446
|
-
*
|
|
1447
|
-
*
|
|
1471
|
+
/** A 1M-context route spells it in the id, so this needs no capacity table
|
|
1472
|
+
* either. It is only a floor: the supervisor overrides it with the window the
|
|
1473
|
+
* CLI reports once a turn has run. */
|
|
1448
1474
|
function declaredContextWindow(row) {
|
|
1449
|
-
return
|
|
1475
|
+
return WIDE_ROUTE.test(row.resolvedModel ?? row.value) ? 1e6 : void 0;
|
|
1476
|
+
}
|
|
1477
|
+
/**
|
|
1478
|
+
* The selector id for one CLI row: the model's family, plus the `[1m]` marker
|
|
1479
|
+
* when the route carries one.
|
|
1480
|
+
*
|
|
1481
|
+
* Derived, never tabulated -- a family this plugin has never heard of gets its
|
|
1482
|
+
* id the same way, so a model Anthropic ships tomorrow lands in the selector
|
|
1483
|
+
* without an edit here, and a version bump (`claude-fable-5-1` ->
|
|
1484
|
+
* `claude-fable-5-2`) leaves an already-persisted selection pointing at the
|
|
1485
|
+
* same row. The family is the first non-numeric segment, which covers both
|
|
1486
|
+
* spellings Anthropic has used (`claude-fable-5-1`, `claude-3-5-sonnet-…`).
|
|
1487
|
+
*
|
|
1488
|
+
* Read off `value` alone, never the id it resolves to: `default` names a route
|
|
1489
|
+
* whose resolution moves with the account and the release, so folding the
|
|
1490
|
+
* resolved `[1m]` in would flip an already-persisted `default` to `default[1m]`
|
|
1491
|
+
* the day Anthropic repoints it.
|
|
1492
|
+
* @param value - the CLI's own id for the row.
|
|
1493
|
+
* @returns the alias to advertise.
|
|
1494
|
+
*/
|
|
1495
|
+
function claudeModelAlias(value) {
|
|
1496
|
+
const wide = WIDE_ROUTE.test(value);
|
|
1497
|
+
const bare = value.replace(WIDE_ROUTE, "").replace(/^claude-/u, "");
|
|
1498
|
+
const family = bare.split("-").find((segment) => !/^\d+$/u.test(segment)) ?? bare;
|
|
1499
|
+
return wide ? `${family}[1m]` : family;
|
|
1450
1500
|
}
|
|
1451
|
-
function projectModel(row) {
|
|
1501
|
+
function projectModel(row, id) {
|
|
1452
1502
|
const contextWindow = declaredContextWindow(row);
|
|
1453
1503
|
return {
|
|
1454
|
-
id
|
|
1504
|
+
id,
|
|
1505
|
+
value: row.value,
|
|
1455
1506
|
name: row.displayName,
|
|
1456
1507
|
description: row.description,
|
|
1457
1508
|
...contextWindow === void 0 ? {} : { contextWindow }
|
|
1458
1509
|
};
|
|
1459
1510
|
}
|
|
1460
1511
|
let latest$1;
|
|
1512
|
+
let inflight;
|
|
1461
1513
|
/**
|
|
1462
1514
|
* Learn the lineup from one session's initialize response.
|
|
1463
1515
|
* @param models - the CLI's own `/model` rows; an empty list is ignored so a
|
|
@@ -1465,20 +1517,96 @@ let latest$1;
|
|
|
1465
1517
|
*/
|
|
1466
1518
|
function recordClaudeModels(models) {
|
|
1467
1519
|
if (models.length === 0) return;
|
|
1468
|
-
|
|
1520
|
+
const taken = /* @__PURE__ */ new Set();
|
|
1521
|
+
latest$1 = models.map((row) => {
|
|
1522
|
+
const alias = claudeModelAlias(row.value);
|
|
1523
|
+
const id = taken.has(alias) ? row.value : alias;
|
|
1524
|
+
taken.add(id);
|
|
1525
|
+
return projectModel(row, id);
|
|
1526
|
+
});
|
|
1469
1527
|
}
|
|
1470
1528
|
/** The lineup to advertise: whatever the CLI last reported, else the seed. */
|
|
1471
1529
|
function latestClaudeModels() {
|
|
1472
1530
|
return latest$1 ?? SEED;
|
|
1473
1531
|
}
|
|
1532
|
+
/** A throwaway probe should not outlive a wedged CLI. */
|
|
1533
|
+
const CLAUDE_MODEL_PROBE_TIMEOUT_MS = 2e4;
|
|
1534
|
+
/**
|
|
1535
|
+
* Read the lineup from a throwaway CLI process.
|
|
1536
|
+
*
|
|
1537
|
+
* Waiting for a session to start is too late: DSH loads the model catalog once
|
|
1538
|
+
* per Host generation, at connect, and does not reload it when this plugin
|
|
1539
|
+
* later learns the real lineup. A selector left on the seed until then hands
|
|
1540
|
+
* out seed ids, which is exactly how a session ends up persisting an id the
|
|
1541
|
+
* next launch cannot resolve. This query carries no tools, no permission
|
|
1542
|
+
* bridge and no session binding: it starts, reports what `/model` would show,
|
|
1543
|
+
* and is killed -- no prompt is ever sent, so it costs no tokens.
|
|
1544
|
+
* @param executablePath - the resolved CLI, or '' to let the SDK find it.
|
|
1545
|
+
* @param factory - test seam for the SDK query.
|
|
1546
|
+
* @returns the CLI's own `/model` rows.
|
|
1547
|
+
*/
|
|
1548
|
+
async function probeClaudeModels(executablePath, factory = query) {
|
|
1549
|
+
const lifetime = new AbortController();
|
|
1550
|
+
const timer = setTimeout(() => lifetime.abort(), CLAUDE_MODEL_PROBE_TIMEOUT_MS);
|
|
1551
|
+
timer.unref?.();
|
|
1552
|
+
const query$2 = factory({
|
|
1553
|
+
prompt: (async function* () {
|
|
1554
|
+
await new Promise(() => {});
|
|
1555
|
+
})(),
|
|
1556
|
+
options: {
|
|
1557
|
+
cwd: process.cwd(),
|
|
1558
|
+
abortController: lifetime,
|
|
1559
|
+
...executablePath.length === 0 ? {} : { pathToClaudeCodeExecutable: executablePath }
|
|
1560
|
+
}
|
|
1561
|
+
});
|
|
1562
|
+
try {
|
|
1563
|
+
(async () => {
|
|
1564
|
+
for await (const _ of query$2);
|
|
1565
|
+
})().catch(() => void 0);
|
|
1566
|
+
return (await Promise.race([query$2.initializationResult(), new Promise((_resolve, reject) => {
|
|
1567
|
+
setTimeout(() => reject(/* @__PURE__ */ new Error("dsh-claude: the model lineup probe did not answer in time")), CLAUDE_MODEL_PROBE_TIMEOUT_MS).unref?.();
|
|
1568
|
+
})])).models;
|
|
1569
|
+
} finally {
|
|
1570
|
+
clearTimeout(timer);
|
|
1571
|
+
lifetime.abort();
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
/**
|
|
1575
|
+
* The lineup, learning it from the CLI the first time DSH asks for the catalog.
|
|
1576
|
+
* @param probe - reads the CLI's rows; a failure leaves the seed in place and
|
|
1577
|
+
* is retried on the next catalog load.
|
|
1578
|
+
* @returns the rows to advertise, never rejecting.
|
|
1579
|
+
*/
|
|
1580
|
+
function ensureClaudeModels(probe) {
|
|
1581
|
+
if (latest$1 !== void 0) return Promise.resolve(latest$1);
|
|
1582
|
+
inflight ??= probe().then((models) => {
|
|
1583
|
+
recordClaudeModels(models);
|
|
1584
|
+
}).catch(() => void 0).then(() => {
|
|
1585
|
+
inflight = void 0;
|
|
1586
|
+
return latestClaudeModels();
|
|
1587
|
+
});
|
|
1588
|
+
return inflight;
|
|
1589
|
+
}
|
|
1474
1590
|
/**
|
|
1475
1591
|
* Look one id up in the current lineup.
|
|
1476
|
-
* @param id - the id DSH persisted on the session, which may
|
|
1592
|
+
* @param id - the id DSH persisted on the session, which may be an alias, a
|
|
1593
|
+
* concrete CLI id persisted before this plugin aliased anything, or a row the
|
|
1477
1594
|
* running CLI no longer lists.
|
|
1478
1595
|
* @returns the row, or undefined when the lineup does not cover the id.
|
|
1479
1596
|
*/
|
|
1480
1597
|
function claudeModelRow(id) {
|
|
1481
|
-
|
|
1598
|
+
const rows = latestClaudeModels();
|
|
1599
|
+
return rows.find((row) => row.id === id) ?? rows.find((row) => row.value === id) ?? rows.find((row) => row.id === claudeModelAlias(id));
|
|
1600
|
+
}
|
|
1601
|
+
/**
|
|
1602
|
+
* The spelling to hand the CLI for one selector id.
|
|
1603
|
+
* @param id - the id DSH persisted on the session.
|
|
1604
|
+
* @returns the CLI's own id, or the selector id itself when the lineup does not
|
|
1605
|
+
* cover it -- the seed vocabulary is made of spellings the CLI accepts, and a
|
|
1606
|
+
* session persisted before this plugin aliased anything already holds one.
|
|
1607
|
+
*/
|
|
1608
|
+
function claudeModelValue(id) {
|
|
1609
|
+
return claudeModelRow(id)?.value ?? id;
|
|
1482
1610
|
}
|
|
1483
1611
|
//#endregion
|
|
1484
1612
|
//#region src/plan-usage.ts
|
|
@@ -1687,6 +1815,10 @@ const MAX_OUTPUT_BYTES$5 = 65536;
|
|
|
1687
1815
|
* status probes' five seconds, and this sits in front of every turn. */
|
|
1688
1816
|
const GIT_TIMEOUT_MS$4 = 3e4;
|
|
1689
1817
|
const OBJECT_NAME = /^[0-9a-f]{40}$|^[0-9a-f]{64}$/u;
|
|
1818
|
+
/** A snapshot holds the bytes on disk, not git's line-ending translation of
|
|
1819
|
+
* them. Under `core.autocrlf=true` a plain `add` would store LF and the
|
|
1820
|
+
* restore would write CRLF, so a rewind on Windows would flip every LF file. */
|
|
1821
|
+
const GIT_OPTIONS = ["-c", "core.autocrlf=false"];
|
|
1690
1822
|
async function collect$4(handle) {
|
|
1691
1823
|
return {
|
|
1692
1824
|
exitCode: (await handle.done).exitCode,
|
|
@@ -1695,7 +1827,11 @@ async function collect$4(handle) {
|
|
|
1695
1827
|
}
|
|
1696
1828
|
async function run$1(runtime, git, args, cwd, env = {}) {
|
|
1697
1829
|
return collect$4(runtime.spawn({
|
|
1698
|
-
argv: [
|
|
1830
|
+
argv: [
|
|
1831
|
+
git,
|
|
1832
|
+
...GIT_OPTIONS,
|
|
1833
|
+
...args
|
|
1834
|
+
],
|
|
1699
1835
|
cwd,
|
|
1700
1836
|
stdio: {
|
|
1701
1837
|
stdin: "ignore",
|
|
@@ -2155,7 +2291,7 @@ var ClaudeSupervisor = class {
|
|
|
2155
2291
|
} else await this.#syncPermissionMode(entry);
|
|
2156
2292
|
await throwIfUnavailable();
|
|
2157
2293
|
const promptUuid = randomUUID();
|
|
2158
|
-
const cursor = currentClaudeActivityCursor(request.agent.session.
|
|
2294
|
+
const cursor = currentClaudeActivityCursor(request.agent.session.snapshotEvents());
|
|
2159
2295
|
const projection = await this.#sidecar.read(sessionId);
|
|
2160
2296
|
await throwIfUnavailable();
|
|
2161
2297
|
cursor.nextOrdinal = projection.activities.reduce((next, activity) => activity.turn === cursor.turn && activity.step === cursor.step ? Math.max(next, activity.ordinal + 1) : next, 0);
|
|
@@ -2308,7 +2444,7 @@ var ClaudeSupervisor = class {
|
|
|
2308
2444
|
}
|
|
2309
2445
|
}
|
|
2310
2446
|
async #syncPermissionMode(entry) {
|
|
2311
|
-
const mode = claudePermissionMode(entry.ownerAgent.session.
|
|
2447
|
+
const mode = claudePermissionMode(entry.ownerAgent.session.snapshotEvents());
|
|
2312
2448
|
if (mode === entry.permissionMode) return;
|
|
2313
2449
|
await this.#control(entry, entry.query.setPermissionMode(mode), "Claude Code permission mode switch");
|
|
2314
2450
|
entry.permissionMode = mode;
|
|
@@ -2402,13 +2538,13 @@ var ClaudeSupervisor = class {
|
|
|
2402
2538
|
const cwd = agent.session.header.cwd ?? process.cwd();
|
|
2403
2539
|
const input = new AsyncQueue();
|
|
2404
2540
|
const lifetime = new AbortController();
|
|
2405
|
-
const projection = await this.#sidecar.importLegacy(sessionId, agent.session.
|
|
2541
|
+
const projection = await this.#sidecar.importLegacy(sessionId, agent.session.snapshotEvents());
|
|
2406
2542
|
if (signalAborted(signal) || signalAborted(cancellationSignal)) throw abortFailure();
|
|
2407
2543
|
const binding = projection.binding;
|
|
2408
2544
|
const pendingRewind = projection.rewind?.pending;
|
|
2409
2545
|
const forkAt = pendingRewind !== void 0 && "resumeAt" in pendingRewind ? pendingRewind.resumeAt : void 0;
|
|
2410
2546
|
const startFresh = pendingRewind !== void 0 && "fresh" in pendingRewind;
|
|
2411
|
-
const permissionMode = claudePermissionMode(agent.session.
|
|
2547
|
+
const permissionMode = claudePermissionMode(agent.session.snapshotEvents());
|
|
2412
2548
|
const entry = {
|
|
2413
2549
|
sessionId,
|
|
2414
2550
|
ownerAgent: agent,
|
|
@@ -2478,7 +2614,7 @@ var ClaudeSupervisor = class {
|
|
|
2478
2614
|
resume: binding.claudeSessionId,
|
|
2479
2615
|
...forkAt === void 0 ? {} : { resumeSessionAt: forkAt }
|
|
2480
2616
|
},
|
|
2481
|
-
model,
|
|
2617
|
+
model: claudeModelValue(model),
|
|
2482
2618
|
...thinkingMode === void 0 ? {} : thinkingMode === "off" ? { thinking: { type: "disabled" } } : thinkingMode === "ultracode" ? { settings: { ultracode: true } } : { effort: thinkingMode }
|
|
2483
2619
|
};
|
|
2484
2620
|
entry.query = this.#queryFactory({
|
|
@@ -3527,7 +3663,10 @@ var ClaudeCodeAdapter = class extends LlmAdapter {
|
|
|
3527
3663
|
* Settings dialog, and the read is dwarfed by the process the turn spawns. */
|
|
3528
3664
|
#renderMode;
|
|
3529
3665
|
#summarizeTitle;
|
|
3530
|
-
|
|
3666
|
+
/** Reads the CLI's own `/model` rows, so the selector never has to advertise
|
|
3667
|
+
* the seed vocabulary once the CLI can answer for itself. */
|
|
3668
|
+
#probeModels;
|
|
3669
|
+
constructor(supervisor, agents, attachments, presetIdFor, drainReviewComments = () => [], renderMode = async () => DEFAULT_CLAUDE_RENDER_MODE, summarizeTitle = (request) => summarizeSessionTitle("", request), probeModels = async () => []) {
|
|
3531
3670
|
super();
|
|
3532
3671
|
this.#supervisor = supervisor;
|
|
3533
3672
|
this.#agents = agents;
|
|
@@ -3536,6 +3675,7 @@ var ClaudeCodeAdapter = class extends LlmAdapter {
|
|
|
3536
3675
|
this.#drainReviewComments = drainReviewComments;
|
|
3537
3676
|
this.#renderMode = renderMode;
|
|
3538
3677
|
this.#summarizeTitle = summarizeTitle;
|
|
3678
|
+
this.#probeModels = probeModels;
|
|
3539
3679
|
}
|
|
3540
3680
|
providerInfo(provider) {
|
|
3541
3681
|
return {
|
|
@@ -3547,7 +3687,7 @@ var ClaudeCodeAdapter = class extends LlmAdapter {
|
|
|
3547
3687
|
return NO_RETRY_POLICY;
|
|
3548
3688
|
}
|
|
3549
3689
|
async listModels(provider) {
|
|
3550
|
-
return
|
|
3690
|
+
return (await ensureClaudeModels(this.#probeModels)).map((model) => ({
|
|
3551
3691
|
provider,
|
|
3552
3692
|
id: model.id,
|
|
3553
3693
|
name: model.name,
|
|
@@ -3748,8 +3888,8 @@ var ClaudeCodeAdapter = class extends LlmAdapter {
|
|
|
3748
3888
|
if (!completed) throw new Error("dsh-claude: Claude turn stream ended without a result");
|
|
3749
3889
|
}
|
|
3750
3890
|
};
|
|
3751
|
-
function createClaudeCodeAdapter(supervisor, agents, attachments, presetIdFor, drainReviewComments = () => [], renderMode = async () => DEFAULT_CLAUDE_RENDER_MODE, summarizeTitle = (request) => summarizeSessionTitle("", request)) {
|
|
3752
|
-
return new ClaudeCodeAdapter(supervisor, agents, attachments, presetIdFor, drainReviewComments, renderMode, summarizeTitle);
|
|
3891
|
+
function createClaudeCodeAdapter(supervisor, agents, attachments, presetIdFor, drainReviewComments = () => [], renderMode = async () => DEFAULT_CLAUDE_RENDER_MODE, summarizeTitle = (request) => summarizeSessionTitle("", request), probeModels = async () => []) {
|
|
3892
|
+
return new ClaudeCodeAdapter(supervisor, agents, attachments, presetIdFor, drainReviewComments, renderMode, summarizeTitle, probeModels);
|
|
3753
3893
|
}
|
|
3754
3894
|
//#endregion
|
|
3755
3895
|
//#region src/plugin-budget.ts
|
|
@@ -4314,6 +4454,82 @@ function registerClaudeProjectionRoute(ctx, sidecar, ownsSession, commandsForSes
|
|
|
4314
4454
|
});
|
|
4315
4455
|
}
|
|
4316
4456
|
//#endregion
|
|
4457
|
+
//#region src/diff-funcname.ts
|
|
4458
|
+
/** Extensions mapped onto a funcname driver, so `@@` hunk headers name the
|
|
4459
|
+
* method a change sits in. Without one git falls back to "the last line that
|
|
4460
|
+
* starts in column 0", which in Java or Kotlin is always the class. */
|
|
4461
|
+
const DIFF_ATTRIBUTES = [
|
|
4462
|
+
"*.java diff=java",
|
|
4463
|
+
"*.kt diff=kotlin",
|
|
4464
|
+
"*.kts diff=kotlin",
|
|
4465
|
+
"*.py diff=python",
|
|
4466
|
+
"*.pyi diff=python",
|
|
4467
|
+
"*.js diff=dshweb",
|
|
4468
|
+
"*.jsx diff=dshweb",
|
|
4469
|
+
"*.mjs diff=dshweb",
|
|
4470
|
+
"*.cjs diff=dshweb",
|
|
4471
|
+
"*.ts diff=dshweb",
|
|
4472
|
+
"*.tsx diff=dshweb",
|
|
4473
|
+
"*.mts diff=dshweb",
|
|
4474
|
+
"*.cts diff=dshweb",
|
|
4475
|
+
"*.vue diff=dshweb",
|
|
4476
|
+
"*.svelte diff=dshweb",
|
|
4477
|
+
"*.css diff=css",
|
|
4478
|
+
"*.scss diff=css",
|
|
4479
|
+
"*.less diff=css",
|
|
4480
|
+
""
|
|
4481
|
+
].join("\n");
|
|
4482
|
+
/** git ships no JavaScript driver, so this is the one pattern we write ourselves.
|
|
4483
|
+
*
|
|
4484
|
+
* POSIX extended regexes, one per line, matched top-down: a leading `!` marks a
|
|
4485
|
+
* line that can never be a header, and the reported text is capture group 1 --
|
|
4486
|
+
* hence the outer parentheses around everything worth showing.
|
|
4487
|
+
*
|
|
4488
|
+
* Line 2 keeps git's own fallback (anything unindented), because a driver
|
|
4489
|
+
* replaces that fallback rather than extending it, and most of a frontend file's
|
|
4490
|
+
* declarations already live in column 0. Lines 3 and 4 add what the fallback
|
|
4491
|
+
* cannot see: nested declarations, and indented class or object methods.
|
|
4492
|
+
*
|
|
4493
|
+
* ponytail: a method line must end in `{`. Allowing `)` too would pick up every
|
|
4494
|
+
* bare `foo(bar)` statement, which reads as a header and hides the real one.
|
|
4495
|
+
*/
|
|
4496
|
+
const DSHWEB_FUNCNAME = [
|
|
4497
|
+
"!^[ ]*(if|else|for|while|do|switch|case|catch|try|finally|return|await|new|throw|typeof)[^A-Za-z0-9_$]",
|
|
4498
|
+
"^([A-Za-z_$].*)$",
|
|
4499
|
+
"^[ ]*((export[ ]+)?(default[ ]+)?(declare[ ]+)?(abstract[ ]+)?(async[ ]+)?(function|class|interface|enum|namespace|module)[ ].*)$",
|
|
4500
|
+
"^[ ]*(((public|private|protected|static|readonly|abstract|async|get|set)[ ]+)*[A-Za-z_$#][A-Za-z0-9_$]*[ ]*[:=]?[ ]*(async[ ]+)?[(<][^;]*\\{)[ ]*$"
|
|
4501
|
+
].join("\n");
|
|
4502
|
+
let attributesFile;
|
|
4503
|
+
async function writeAttributes() {
|
|
4504
|
+
const path = dshHomePath("plugins", "dsh-claude", "diff-attributes");
|
|
4505
|
+
try {
|
|
4506
|
+
await mkdir(dirname(path), { recursive: true });
|
|
4507
|
+
await writeFile(path, DIFF_ATTRIBUTES, "utf8");
|
|
4508
|
+
return path;
|
|
4509
|
+
} catch {
|
|
4510
|
+
return;
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4513
|
+
/** `-c` overrides to place in front of a `git diff`, teaching it which funcname
|
|
4514
|
+
* driver each extension uses.
|
|
4515
|
+
*
|
|
4516
|
+
* `core.attributesFile` is the lowest-precedence attribute source, so a
|
|
4517
|
+
* repository that already declares its own `.gitattributes` still wins. Better
|
|
4518
|
+
* hunk headers are cosmetic: a failed write drops the overrides and the diff
|
|
4519
|
+
* runs exactly as before.
|
|
4520
|
+
*/
|
|
4521
|
+
async function diffFuncnameArgs() {
|
|
4522
|
+
attributesFile ??= writeAttributes();
|
|
4523
|
+
const path = await attributesFile;
|
|
4524
|
+
if (path === void 0) return [];
|
|
4525
|
+
return [
|
|
4526
|
+
"-c",
|
|
4527
|
+
`core.attributesFile=${path}`,
|
|
4528
|
+
"-c",
|
|
4529
|
+
`diff.dshweb.xfuncname=${DSHWEB_FUNCNAME}`
|
|
4530
|
+
];
|
|
4531
|
+
}
|
|
4532
|
+
//#endregion
|
|
4317
4533
|
//#region src/repository-status.ts
|
|
4318
4534
|
const MAX_OUTPUT_BYTES$4 = 65536;
|
|
4319
4535
|
const MAX_DIFF_BYTES = 262144;
|
|
@@ -4707,6 +4923,7 @@ var RepositoryStatusService = class {
|
|
|
4707
4923
|
if (numstat.exitCode !== 0 || numstat.lossy) return void 0;
|
|
4708
4924
|
const summary = parseDiffNumstat(numstat.stdout);
|
|
4709
4925
|
const patch = await run(this.#runtime, git, [
|
|
4926
|
+
...await diffFuncnameArgs(),
|
|
4710
4927
|
"diff",
|
|
4711
4928
|
"--no-ext-diff",
|
|
4712
4929
|
"--no-color",
|
|
@@ -5851,6 +6068,7 @@ var RepositoryActionService = class {
|
|
|
5851
6068
|
"--path-format=absolute",
|
|
5852
6069
|
"--show-toplevel"
|
|
5853
6070
|
], cwd, GIT_TIMEOUT_MS$1, "not-repository", "The session directory is not a Git repository.")).stdout.trim();
|
|
6071
|
+
const funcname = await diffFuncnameArgs();
|
|
5854
6072
|
const [branchResult, headResult, statusResult, stagedPatch, unstagedPatch] = await Promise.all([
|
|
5855
6073
|
this.#run(git, [
|
|
5856
6074
|
"symbolic-ref",
|
|
@@ -5866,6 +6084,7 @@ var RepositoryActionService = class {
|
|
|
5866
6084
|
"--untracked-files=all"
|
|
5867
6085
|
], root, GIT_TIMEOUT_MS$1),
|
|
5868
6086
|
this.#run(git, [
|
|
6087
|
+
...funcname,
|
|
5869
6088
|
"diff",
|
|
5870
6089
|
"--cached",
|
|
5871
6090
|
"--no-ext-diff",
|
|
@@ -5876,6 +6095,7 @@ var RepositoryActionService = class {
|
|
|
5876
6095
|
":(exclude)**/WARP.md"
|
|
5877
6096
|
], root, GIT_TIMEOUT_MS$1, MAX_OUTPUT_BYTES$2),
|
|
5878
6097
|
this.#run(git, [
|
|
6098
|
+
...funcname,
|
|
5879
6099
|
"diff",
|
|
5880
6100
|
"--no-ext-diff",
|
|
5881
6101
|
"--no-color",
|
|
@@ -6468,10 +6688,13 @@ const PROMPT_NAME = /^[\p{L}\p{N}][\p{L}\p{M}\p{N} ._()\[\]-]{0,127}$/u;
|
|
|
6468
6688
|
function claudePromptsDir() {
|
|
6469
6689
|
return join(homedir(), ".claude", "prompts");
|
|
6470
6690
|
}
|
|
6471
|
-
/** `~/.claude/prompts/x.md` rather than the absolute path it expands to.
|
|
6691
|
+
/** `~/.claude/prompts/x.md` rather than the absolute path it expands to.
|
|
6692
|
+
* Windows joins with backslashes; the display form is the same on every OS. */
|
|
6472
6693
|
function displayPath(file) {
|
|
6473
6694
|
const home = homedir();
|
|
6474
|
-
|
|
6695
|
+
const separator = file.charAt(home.length);
|
|
6696
|
+
if (!file.startsWith(home) || separator !== "/" && separator !== "\\") return file;
|
|
6697
|
+
return `~${file.slice(home.length).replaceAll("\\", "/")}`;
|
|
6475
6698
|
}
|
|
6476
6699
|
/** The menu's second row: the first non-empty line, collapsed and bounded. */
|
|
6477
6700
|
function summarize(body) {
|
|
@@ -9232,7 +9455,7 @@ async function apply(ctx, config) {
|
|
|
9232
9455
|
let resolutionError;
|
|
9233
9456
|
try {
|
|
9234
9457
|
supervisorConfig.executablePath = (await resolveClaudeExecutable(ctx.subprocess, config.executablePath === void 0 || config.executablePath.length === 0 ? void 0 : config.executablePath)).path;
|
|
9235
|
-
ctx.llm.registerAdapter([...CLAUDE_CODE_PROVIDER_IDS], createClaudeCodeAdapter(supervisor, ctx.agents, ctx.attachments, (agent) => ctx.agentPresets.composedPreset(agent.ctx), (sessionId) => reviewComments.drain(sessionId), () => readRenderMode(), (request) => summarizeSessionTitle(supervisorConfig.executablePath, request)));
|
|
9458
|
+
ctx.llm.registerAdapter([...CLAUDE_CODE_PROVIDER_IDS], createClaudeCodeAdapter(supervisor, ctx.agents, ctx.attachments, (agent) => ctx.agentPresets.composedPreset(agent.ctx), (sessionId) => reviewComments.drain(sessionId), () => readRenderMode(), (request) => summarizeSessionTitle(supervisorConfig.executablePath, request), () => probeClaudeModels(supervisorConfig.executablePath)));
|
|
9236
9459
|
ctx.effect(() => {
|
|
9237
9460
|
const mounted = /* @__PURE__ */ new Map();
|
|
9238
9461
|
const pending = /* @__PURE__ */ new Set();
|
|
@@ -9361,7 +9584,7 @@ async function apply(ctx, config) {
|
|
|
9361
9584
|
registerAskRoute(webCtx, new AskService(webCtx.subprocess, supervisorConfig.executablePath), cwdForClaudeSession, (sessionId) => {
|
|
9362
9585
|
const snapshot = supervisor.snapshots().find((item) => item.sessionId === sessionId);
|
|
9363
9586
|
return snapshot === void 0 ? void 0 : {
|
|
9364
|
-
model: snapshot.model,
|
|
9587
|
+
model: claudeModelValue(snapshot.model),
|
|
9365
9588
|
...snapshot.thinkingMode === void 0 ? {} : { thinkingMode: snapshot.thinkingMode }
|
|
9366
9589
|
};
|
|
9367
9590
|
});
|
|
@@ -9374,7 +9597,7 @@ async function apply(ctx, config) {
|
|
|
9374
9597
|
registerClaudeRewindRoute(webCtx, sidecar, {
|
|
9375
9598
|
eventsFor: (sessionId) => {
|
|
9376
9599
|
const agent = webCtx.agents.get(sessionId);
|
|
9377
|
-
return agent === void 0 || webCtx.agentPresets.composedPreset(agent.ctx) !== "claude" ? void 0 : agent.session.
|
|
9600
|
+
return agent === void 0 || webCtx.agentPresets.composedPreset(agent.ctx) !== "claude" ? void 0 : agent.session.snapshotEvents();
|
|
9378
9601
|
},
|
|
9379
9602
|
busy: (sessionId) => supervisor.snapshots().some((item) => item.sessionId === sessionId && (item.state === "running" || item.state === "interrupting")),
|
|
9380
9603
|
reset: (sessionId) => supervisor.disposeSession(sessionId),
|