threadwell 0.0.5 → 0.0.7
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/CHANGELOG.md +25 -0
- package/README.md +4 -8
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +5 -7
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +4 -2
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +5 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +7 -1
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +12 -4
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +2 -0
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +43 -4
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +4 -3
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +31 -8
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +4 -3
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +32 -8
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +1 -9
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +3 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +33 -20
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js +70 -0
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +61 -49
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/framed-message.d.ts +17 -0
- package/dist/modes/interactive/components/framed-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/framed-message.js +39 -0
- package/dist/modes/interactive/components/framed-message.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +0 -4
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +0 -20
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +4 -3
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +31 -9
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/split-info-card.d.ts.map +1 -1
- package/dist/modes/interactive/components/split-info-card.js +24 -17
- package/dist/modes/interactive/components/split-info-card.js.map +1 -1
- package/dist/modes/interactive/components/thinking-card.d.ts +6 -0
- package/dist/modes/interactive/components/thinking-card.d.ts.map +1 -0
- package/dist/modes/interactive/components/thinking-card.js +17 -0
- package/dist/modes/interactive/components/thinking-card.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +5 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +72 -2
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +16 -0
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +86 -73
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/visual-profile.d.ts +69 -0
- package/dist/modes/interactive/theme/visual-profile.d.ts.map +1 -0
- package/dist/modes/interactive/theme/visual-profile.js +131 -0
- package/dist/modes/interactive/theme/visual-profile.js.map +1 -0
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +1 -1
- package/dist/package-manager-cli.js.map +1 -1
- package/docs/docs.json +1 -5
- package/docs/extensions.md +7 -16
- package/docs/index.md +6 -5
- package/docs/packages.md +8 -30
- package/docs/quickstart.md +1 -1
- package/docs/sdk.md +2 -3
- package/docs/settings.md +24 -7
- package/docs/themes.md +5 -295
- package/docs/usage.md +14 -17
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, truncateToWidth, visibleWidth } from \"@threadwell/tui\";\nimport type { AgentSession } from \"../../../core/agent-session.js\";\nimport type { GitStatus, ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.js\";\nimport { DISTRO_IDENTITY } from \"../../../core/identity.js\";\nimport { theme } from \"../theme/theme.js\";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\n/**\n * Format token counts (similar to compact UI displays)\n */\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\nfunction getContextUsageColor(percent: number): (text: string) => string {\n\tif (percent > 90) return (text) => theme.fg(\"error\", text);\n\tif (percent > 70) return (text) => theme.fg(\"warning\", text);\n\treturn (text) => theme.fg(\"dim\", text);\n}\n\nfunction formatGitBadge(status: GitStatus | null): string | null {\n\tif (!status) return null;\n\n\tconst parts = [`git ${status.branch}`];\n\tif (status.conflicts > 0) {\n\t\tparts.push(theme.fg(\"error\", `conflicts ${status.conflicts}`));\n\t\treturn parts.join(\" \");\n\t}\n\tif (status.clean) {\n\t\tparts.push(theme.fg(\"accent\", \"clean\"));\n\t\treturn parts.join(\" \");\n\t}\n\n\tif (status.staged > 0) parts.push(theme.fg(\"accent\", `+${status.staged}`));\n\tif (status.unstaged > 0) parts.push(theme.fg(\"error\", `-${status.unstaged}`));\n\tif (status.untracked > 0) parts.push(theme.fg(\"warning\", `?${status.untracked}`));\n\tif (status.ahead > 0) parts.push(theme.fg(\"muted\", `↑${status.ahead}`));\n\tif (status.behind > 0) parts.push(theme.fg(\"muted\", `↓${status.behind}`));\n\treturn parts.join(\" \");\n}\n\nfunction renderContextBar(width: number, percent: number | null, autoCompactEnabled: boolean): string {\n\tif (width < 2) return truncateToWidth(\"██\", width, \"\");\n\n\tconst innerWidth = Math.max(0, width - 2);\n\tconst clampedPercent = percent === null ? 0 : Math.max(0, Math.min(100, percent));\n\tconst exactFilledWidth = (clampedPercent / 100) * innerWidth;\n\tconst filledWidth = Math.min(innerWidth, Math.floor(exactFilledWidth));\n\tconst partial = exactFilledWidth - filledWidth;\n\tconst partialChar = partial <= 0 ? \"\" : partial < 1 / 3 ? \"░\" : partial < 2 / 3 ? \"▒\" : \"▓\";\n\tconst fillColor = getContextUsageColor(clampedPercent);\n\tconst label = `${percent === null ? \"?\" : `${clampedPercent.toFixed(1)}%`} · Autocompact ${autoCompactEnabled ? \"On\" : \"Off\"}`;\n\tconst labelStart = Math.max(0, Math.floor((width - visibleWidth(label)) / 2));\n\tconst labelChars = [...label];\n\tlet labelIndex = 0;\n\tlet result = \"\";\n\n\tfor (let column = 0; column < width; column++) {\n\t\tconst labelEnd = labelStart + labelChars.length;\n\t\tif (column >= labelStart && column < labelEnd) {\n\t\t\tconst labelChar = labelChars[labelIndex++] ?? \"\";\n\t\t\tconst innerColumn = column - 1;\n\t\t\tconst isOverFill = column > 0 && column < width - 1 && innerColumn < exactFilledWidth;\n\t\t\tresult += isOverFill ? theme.inverse(fillColor(labelChar)) : theme.fg(\"dim\", labelChar);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (column === 0 || column === width - 1) {\n\t\t\tresult += theme.fg(\"dim\", \"█\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst innerColumn = column - 1;\n\t\tif (innerColumn < filledWidth) {\n\t\t\tresult += fillColor(\"█\");\n\t\t} else if (innerColumn === filledWidth && partialChar) {\n\t\t\tresult += fillColor(partialChar);\n\t\t} else {\n\t\t\tresult += \" \";\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\nexport class FooterComponent implements Component {\n\tprivate autoCompactEnabled = true;\n\n\tconstructor(\n\t\tprivate session: AgentSession,\n\t\tprivate footerData: ReadonlyFooterDataProvider,\n\t) {}\n\n\tsetSession(session: AgentSession): void {\n\t\tthis.session = session;\n\t}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * No-op: git branch caching now handled by provider.\n\t * Kept for compatibility with existing call sites in interactive-mode.\n\t */\n\tinvalidate(): void {\n\t\t// No-op: git branch is cached/invalidated by provider\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\n\t\t// Calculate cumulative usage from ALL session entries (not just post-compaction messages)\n\t\tlet totalInput = 0;\n\t\tlet totalOutput = 0;\n\t\tlet totalCacheRead = 0;\n\t\tlet totalCacheWrite = 0;\n\t\tlet totalCost = 0;\n\n\t\tfor (const entry of this.session.sessionManager.getEntries()) {\n\t\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\ttotalInput += entry.message.usage.input;\n\t\t\t\ttotalOutput += entry.message.usage.output;\n\t\t\t\ttotalCacheRead += entry.message.usage.cacheRead;\n\t\t\t\ttotalCacheWrite += entry.message.usage.cacheWrite;\n\t\t\t\ttotalCost += entry.message.usage.cost.total;\n\t\t\t}\n\t\t}\n\n\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\tconst contextUsage = this.session.getContextUsage();\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\n\t\t// Replace home directory with ~\n\t\tlet pwd = this.session.sessionManager.getCwd();\n\t\tconst home = process.env.HOME || process.env.USERPROFILE;\n\t\tif (home && pwd.startsWith(home)) {\n\t\t\tpwd = `~${pwd.slice(home.length)}`;\n\t\t}\n\n\t\t// Add session name if set\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\t\tif (sessionName) {\n\t\t\tpwd = `${pwd} • ${sessionName}`;\n\t\t}\n\n\t\t// Build stats line\n\t\tconst statsParts = [];\n\t\tif (totalInput) statsParts.push(`↑${formatTokens(totalInput)}`);\n\t\tif (totalOutput) statsParts.push(`↓${formatTokens(totalOutput)}`);\n\t\tif (totalCacheRead) statsParts.push(`R${formatTokens(totalCacheRead)}`);\n\t\tif (totalCacheWrite) statsParts.push(`W${formatTokens(totalCacheWrite)}`);\n\n\t\t// Show cost with \"(sub)\" indicator if using OAuth subscription\n\t\tconst usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;\n\t\tif (totalCost || usingSubscription) {\n\t\t\tconst costStr = `$${totalCost.toFixed(3)}${usingSubscription ? \" (sub)\" : \"\"}`;\n\t\t\tstatsParts.push(costStr);\n\t\t}\n\n\t\tconst continuityStatus = this.session.settingsManager.getContinuityEnabled()\n\t\t\t? \"continuity active\"\n\t\t\t: \"continuity off\";\n\t\tlet statsLeft = [theme.fg(\"accent\", DISTRO_IDENTITY.name), theme.fg(\"dim\", continuityStatus), ...statsParts].join(\n\t\t\t\" \",\n\t\t);\n\n\t\t// Add model name on the right side, plus thinking level if model supports it\n\t\tconst modelName = state.model?.id || \"no-model\";\n\n\t\tlet statsLeftWidth = visibleWidth(statsLeft);\n\n\t\t// If statsLeft is too wide, truncate it\n\t\tif (statsLeftWidth > width) {\n\t\t\tstatsLeft = truncateToWidth(statsLeft, width, \"...\");\n\t\t\tstatsLeftWidth = visibleWidth(statsLeft);\n\t\t}\n\n\t\t// Calculate available space for padding (minimum 2 spaces between stats and model)\n\t\tconst minPadding = 2;\n\n\t\t// Add thinking level indicator if model supports reasoning\n\t\tlet rightSideWithoutProvider = modelName;\n\t\tif (state.model?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\trightSideWithoutProvider =\n\t\t\t\tthinkingLevel === \"off\" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;\n\t\t}\n\n\t\t// Prepend the provider in parentheses if there are multiple providers and there's enough room\n\t\tlet rightSide = rightSideWithoutProvider;\n\t\tif (this.footerData.getAvailableProviderCount() > 1 && state.model) {\n\t\t\trightSide = `(${state.model!.provider}) ${rightSideWithoutProvider}`;\n\t\t\tif (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {\n\t\t\t\t// Too wide, fall back\n\t\t\t\trightSide = rightSideWithoutProvider;\n\t\t\t}\n\t\t}\n\n\t\tconst rightSideWidth = visibleWidth(rightSide);\n\t\tconst totalNeeded = statsLeftWidth + minPadding + rightSideWidth;\n\n\t\tlet statsLine: string;\n\t\tif (totalNeeded <= width) {\n\t\t\t// Both fit - add padding to right-align model\n\t\t\tconst padding = \" \".repeat(width - statsLeftWidth - rightSideWidth);\n\t\t\tstatsLine = statsLeft + padding + rightSide;\n\t\t} else {\n\t\t\t// Need to truncate right side\n\t\t\tconst availableForRight = width - statsLeftWidth - minPadding;\n\t\t\tif (availableForRight > 0) {\n\t\t\t\tconst truncatedRight = truncateToWidth(rightSide, availableForRight, \"\");\n\t\t\t\tconst truncatedRightWidth = visibleWidth(truncatedRight);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));\n\t\t\t\tstatsLine = statsLeft + padding + truncatedRight;\n\t\t\t} else {\n\t\t\t\t// Not enough space for right side at all\n\t\t\t\tstatsLine = statsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Apply dim to each part separately. statsLeft may contain color codes (for context %)\n\t\t// that end with a reset, which would clear an outer dim wrapper. So we dim the parts\n\t\t// before and after the colored section independently.\n\t\tconst dimStatsLeft = theme.fg(\"dim\", statsLeft);\n\t\tconst remainder = statsLine.slice(statsLeft.length); // padding + rightSide\n\t\tconst dimRemainder = theme.fg(\"dim\", remainder);\n\n\t\tconst gitBadge = formatGitBadge(this.footerData.getGitStatus());\n\t\tlet pwdLine: string;\n\t\tif (gitBadge) {\n\t\t\tconst left = theme.fg(\"dim\", pwd);\n\t\t\tconst leftWidth = visibleWidth(left);\n\t\t\tconst badgeWidth = visibleWidth(gitBadge);\n\t\t\tif (leftWidth + 2 + badgeWidth <= width) {\n\t\t\t\tpwdLine = left + \" \".repeat(width - leftWidth - badgeWidth) + gitBadge;\n\t\t\t} else {\n\t\t\t\tconst truncatedLeft = truncateToWidth(left, Math.max(0, width - badgeWidth - 2), theme.fg(\"dim\", \"...\"));\n\t\t\t\tpwdLine = `${truncatedLeft} ${gitBadge}`;\n\t\t\t}\n\t\t} else {\n\t\t\tpwdLine = truncateToWidth(theme.fg(\"dim\", pwd), width, theme.fg(\"dim\", \"...\"));\n\t\t}\n\t\tconst contextBarLine = renderContextBar(\n\t\t\twidth,\n\t\t\tcontextPercent === \"?\" ? null : contextPercentValue,\n\t\t\tthis.autoCompactEnabled,\n\t\t);\n\t\tconst lines = [pwdLine, dimStatsLeft + dimRemainder, contextBarLine];\n\n\t\t// Add extension statuses on a single line, sorted by key alphabetically\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tif (extensionStatuses.size > 0) {\n\t\t\tconst sortedStatuses = Array.from(extensionStatuses.entries())\n\t\t\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t\t\t.map(([, text]) => sanitizeStatusText(text));\n\t\t\tconst statusLine = sortedStatuses.join(\" \");\n\t\t\t// Truncate to terminal width with dim ellipsis for consistency with footer style\n\t\t\tlines.push(truncateToWidth(statusLine, width, theme.fg(\"dim\", \"...\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, truncateToWidth, visibleWidth } from \"@threadwell/tui\";\nimport type { AgentSession } from \"../../../core/agent-session.js\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.js\";\nimport { DISTRO_IDENTITY } from \"../../../core/identity.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { getVisualTokens } from \"../theme/visual-profile.js\";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\n/**\n * Format token counts (similar to compact UI displays)\n */\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\nfunction getContextUsageColor(percent: number): (text: string) => string {\n\tif (percent > 90) return (text) => theme.fg(\"error\", text);\n\tif (percent > 70) return (text) => theme.fg(\"warning\", text);\n\treturn (text) => theme.fg(\"dim\", text);\n}\n\nfunction renderContextBar(width: number, percent: number | null, autoCompactEnabled: boolean): string {\n\tif (width < 2) return truncateToWidth(\"██\", width, \"\");\n\n\tconst visual = getVisualTokens();\n\tconst clampedPercent = percent === null ? 0 : Math.max(0, Math.min(100, percent));\n\tconst fillColor = getContextUsageColor(clampedPercent);\n\tconst separator = visual.enhanced ? visual.glyphs.separator : \"·\";\n\tconst label = ` context ${percent === null ? \"?\" : `${clampedPercent.toFixed(1)}%`} ${separator} auto ${autoCompactEnabled ? \"on\" : \"off\"} `;\n\n\tif (visual.enhanced) {\n\t\tconst labelWidth = visibleWidth(label);\n\t\tif (width <= labelWidth) return truncateToWidth(theme.fg(\"muted\", label.trim()), width, \"\");\n\n\t\tconst lineWidth = width - labelWidth;\n\t\tconst activeWidth = Math.floor((lineWidth * clampedPercent) / 100);\n\t\tconst leftWidth = Math.floor(lineWidth / 2);\n\t\tconst rightWidth = lineWidth - leftWidth;\n\t\tconst activeLeftWidth = Math.min(leftWidth, activeWidth);\n\t\tconst activeRightWidth = Math.max(0, activeWidth - leftWidth);\n\t\tconst left = fillColor(\"━\".repeat(activeLeftWidth)) + theme.fg(\"dim\", \"─\".repeat(leftWidth - activeLeftWidth));\n\t\tconst right =\n\t\t\tfillColor(\"━\".repeat(Math.min(rightWidth, activeRightWidth))) +\n\t\t\ttheme.fg(\"dim\", \"─\".repeat(Math.max(0, rightWidth - activeRightWidth)));\n\t\treturn `${left}${theme.fg(\"muted\", label)}${right}`;\n\t}\n\n\tconst innerWidth = Math.max(0, width - 2);\n\tconst exactFilledWidth = (clampedPercent / 100) * innerWidth;\n\tconst filledWidth = Math.min(innerWidth, Math.floor(exactFilledWidth));\n\tconst partial = exactFilledWidth - filledWidth;\n\tconst partialChar = partial <= 0 ? \"\" : partial < 1 / 3 ? \"░\" : partial < 2 / 3 ? \"▒\" : \"▓\";\n\tconst labelStart = Math.max(0, Math.floor((width - visibleWidth(label)) / 2));\n\tconst labelChars = [...label];\n\tlet labelIndex = 0;\n\tlet result = \"\";\n\n\tfor (let column = 0; column < width; column++) {\n\t\tconst labelEnd = labelStart + labelChars.length;\n\t\tif (column >= labelStart && column < labelEnd) {\n\t\t\tconst labelChar = labelChars[labelIndex++] ?? \"\";\n\t\t\tconst innerColumn = column - 1;\n\t\t\tconst isOverFill = column > 0 && column < width - 1 && innerColumn < exactFilledWidth;\n\t\t\tresult += isOverFill ? theme.inverse(fillColor(labelChar)) : theme.fg(\"dim\", labelChar);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (column === 0 || column === width - 1) {\n\t\t\tresult += theme.fg(\"dim\", \"█\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst innerColumn = column - 1;\n\t\tif (innerColumn < filledWidth) {\n\t\t\tresult += fillColor(\"█\");\n\t\t} else if (innerColumn === filledWidth && partialChar) {\n\t\t\tresult += fillColor(partialChar);\n\t\t} else {\n\t\t\tresult += \" \";\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\nexport class FooterComponent implements Component {\n\tprivate autoCompactEnabled = true;\n\n\tconstructor(\n\t\tprivate session: AgentSession,\n\t\tprivate footerData: ReadonlyFooterDataProvider,\n\t) {}\n\n\tsetSession(session: AgentSession): void {\n\t\tthis.session = session;\n\t}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * No-op: git branch caching now handled by provider.\n\t * Kept for compatibility with existing call sites in interactive-mode.\n\t */\n\tinvalidate(): void {\n\t\t// No-op: git branch is cached/invalidated by provider\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\t\tconst visual = getVisualTokens();\n\t\tconst glyphs = visual.glyphs;\n\n\t\t// Calculate cumulative usage from ALL session entries (not just post-compaction messages)\n\t\tlet totalInput = 0;\n\t\tlet totalOutput = 0;\n\t\tlet totalCacheRead = 0;\n\t\tlet totalCacheWrite = 0;\n\t\tlet totalCost = 0;\n\n\t\tfor (const entry of this.session.sessionManager.getEntries()) {\n\t\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\ttotalInput += entry.message.usage.input;\n\t\t\t\ttotalOutput += entry.message.usage.output;\n\t\t\t\ttotalCacheRead += entry.message.usage.cacheRead;\n\t\t\t\ttotalCacheWrite += entry.message.usage.cacheWrite;\n\t\t\t\ttotalCost += entry.message.usage.cost.total;\n\t\t\t}\n\t\t}\n\n\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\tconst contextUsage = this.session.getContextUsage();\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\n\t\t// Replace home directory with ~\n\t\tlet pwd = this.session.sessionManager.getCwd();\n\t\tconst home = process.env.HOME || process.env.USERPROFILE;\n\t\tif (home && pwd.startsWith(home)) {\n\t\t\tpwd = `~${pwd.slice(home.length)}`;\n\t\t}\n\n\t\t// Add session name if set\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\t\tif (sessionName) {\n\t\t\tpwd = `${pwd} • ${sessionName}`;\n\t\t}\n\n\t\t// Build stats line\n\t\tconst statsParts = [];\n\t\tif (totalInput) statsParts.push(`↑${formatTokens(totalInput)}`);\n\t\tif (totalOutput) statsParts.push(`↓${formatTokens(totalOutput)}`);\n\t\tif (totalCacheRead) statsParts.push(`R${formatTokens(totalCacheRead)}`);\n\t\tif (totalCacheWrite) statsParts.push(`W${formatTokens(totalCacheWrite)}`);\n\n\t\t// Show cost with \"(sub)\" indicator if using OAuth subscription\n\t\tconst usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;\n\t\tif (totalCost || usingSubscription) {\n\t\t\tconst costStr = `$${totalCost.toFixed(3)}${usingSubscription ? \" (sub)\" : \"\"}`;\n\t\t\tstatsParts.push(costStr);\n\t\t}\n\n\t\tconst continuityEnabled = this.session.settingsManager.getContinuityEnabled();\n\t\tconst continuityStatus = continuityEnabled\n\t\t\t? visual.enhanced\n\t\t\t\t? `${glyphs.continuity} continuity active`\n\t\t\t\t: \"continuity active\"\n\t\t\t: \"continuity off\";\n\t\tconst memorySettings = this.session.settingsManager.getMemorySettings();\n\t\tconst memoryStatus = memorySettings.enabled\n\t\t\t? visual.enhanced\n\t\t\t\t? `${glyphs.memory} ${memorySettings.inject ? \"memory injecting\" : \"memory on\"}`\n\t\t\t\t: memorySettings.inject\n\t\t\t\t\t? \"memory injecting\"\n\t\t\t\t\t: \"memory on\"\n\t\t\t: undefined;\n\t\tconst statsSeparator = visual.enhanced ? theme.fg(\"muted\", ` ${glyphs.separator} `) : \" \";\n\t\tlet statsLeft = visual.enhanced\n\t\t\t? [\n\t\t\t\t\ttheme.fg(\"accent\", DISTRO_IDENTITY.name),\n\t\t\t\t\ttheme.fg(continuityEnabled ? \"accent\" : \"dim\", continuityStatus),\n\t\t\t\t\t...(memoryStatus ? [theme.fg(memorySettings.inject ? \"accent\" : \"muted\", memoryStatus)] : []),\n\t\t\t\t\t...statsParts.map((part) => theme.fg(\"dim\", part)),\n\t\t\t\t].join(statsSeparator)\n\t\t\t: [\n\t\t\t\t\ttheme.fg(\"accent\", DISTRO_IDENTITY.name),\n\t\t\t\t\ttheme.fg(\"dim\", continuityStatus),\n\t\t\t\t\t...(memoryStatus ? [theme.fg(\"dim\", memoryStatus)] : []),\n\t\t\t\t\t...statsParts,\n\t\t\t\t].join(\" \");\n\n\t\t// Add model name on the right side, plus thinking level if model supports it\n\t\tconst modelName = state.model?.id || \"no-model\";\n\n\t\tlet statsLeftWidth = visibleWidth(statsLeft);\n\n\t\t// If statsLeft is too wide, truncate it\n\t\tif (statsLeftWidth > width) {\n\t\t\tstatsLeft = truncateToWidth(statsLeft, width, \"...\");\n\t\t\tstatsLeftWidth = visibleWidth(statsLeft);\n\t\t}\n\n\t\t// Calculate available space for padding (minimum 2 spaces between stats and model)\n\t\tconst minPadding = 2;\n\n\t\t// Add thinking level indicator if model supports reasoning\n\t\tlet rightSideWithoutProvider = modelName;\n\t\tif (state.model?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\trightSideWithoutProvider =\n\t\t\t\tthinkingLevel === \"off\" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;\n\t\t}\n\t\tif (visual.enhanced) {\n\t\t\tconst thinkingLevel = state.model?.reasoning ? state.thinkingLevel || \"off\" : undefined;\n\t\t\trightSideWithoutProvider = [\n\t\t\t\t`${theme.fg(\"dim\", glyphs.model)} ${theme.fg(\"muted\", modelName)}`,\n\t\t\t\t...(thinkingLevel ? [theme.fg(thinkingLevel === \"off\" ? \"dim\" : \"accent\", thinkingLevel)] : []),\n\t\t\t].join(statsSeparator);\n\t\t}\n\n\t\t// Prepend the provider in parentheses if there are multiple providers and there's enough room\n\t\tlet rightSide = rightSideWithoutProvider;\n\t\tif (this.footerData.getAvailableProviderCount() > 1 && state.model) {\n\t\t\trightSide = `(${state.model!.provider}) ${rightSideWithoutProvider}`;\n\t\t\tif (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {\n\t\t\t\t// Too wide, fall back\n\t\t\t\trightSide = rightSideWithoutProvider;\n\t\t\t}\n\t\t}\n\n\t\tconst rightSideWidth = visibleWidth(rightSide);\n\t\tconst totalNeeded = statsLeftWidth + minPadding + rightSideWidth;\n\n\t\tlet statsLine: string;\n\t\tif (totalNeeded <= width) {\n\t\t\t// Both fit - add padding to right-align model\n\t\t\tconst padding = \" \".repeat(width - statsLeftWidth - rightSideWidth);\n\t\t\tstatsLine = statsLeft + padding + rightSide;\n\t\t} else {\n\t\t\t// Need to truncate right side\n\t\t\tconst availableForRight = width - statsLeftWidth - minPadding;\n\t\t\tif (availableForRight > 0) {\n\t\t\t\tconst truncatedRight = truncateToWidth(rightSide, availableForRight, \"\");\n\t\t\t\tconst truncatedRightWidth = visibleWidth(truncatedRight);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));\n\t\t\t\tstatsLine = statsLeft + padding + truncatedRight;\n\t\t\t} else {\n\t\t\t\t// Not enough space for right side at all\n\t\t\t\tstatsLine = statsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Apply dim to each part separately. statsLeft may contain color codes (for context %)\n\t\t// that end with a reset, which would clear an outer dim wrapper. So we dim the parts\n\t\t// before and after the colored section independently.\n\t\tconst dimStatsLeft = visual.enhanced ? statsLeft : theme.fg(\"dim\", statsLeft);\n\t\tconst remainder = statsLine.slice(statsLeft.length); // padding + rightSide\n\t\tconst dimRemainder = visual.enhanced ? remainder : theme.fg(\"dim\", remainder);\n\n\t\tconst folder = glyphs.folder;\n\t\tconst pwdLine = truncateToWidth(\n\t\t\t`${theme.fg(\"dim\", folder)} ${theme.fg(\"dim\", pwd)}`,\n\t\t\twidth,\n\t\t\ttheme.fg(\"dim\", \"...\"),\n\t\t);\n\t\tconst contextBarLine = renderContextBar(\n\t\t\twidth,\n\t\t\tcontextPercent === \"?\" ? null : contextPercentValue,\n\t\t\tthis.autoCompactEnabled,\n\t\t);\n\t\tconst lines = [pwdLine, dimStatsLeft + dimRemainder, contextBarLine];\n\n\t\t// Add extension statuses on a single line, sorted by key alphabetically\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tif (extensionStatuses.size > 0) {\n\t\t\tconst sortedStatuses = Array.from(extensionStatuses.entries())\n\t\t\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t\t\t.map(([, text]) => sanitizeStatusText(text));\n\t\t\tconst statusLine = sortedStatuses.join(\" \");\n\t\t\t// Truncate to terminal width with dim ellipsis for consistency with footer style\n\t\t\tlines.push(truncateToWidth(statusLine, width, theme.fg(\"dim\", \"...\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type Component, type MarkdownTheme } from "@threadwell/tui";
|
|
2
|
+
export interface FramedMessageOptions {
|
|
3
|
+
title: string;
|
|
4
|
+
text: string;
|
|
5
|
+
markdownTheme: MarkdownTheme;
|
|
6
|
+
borderColor: (text: string) => string;
|
|
7
|
+
titleColor?: (text: string) => string;
|
|
8
|
+
contentColor?: (text: string) => string;
|
|
9
|
+
titleAlign?: "left" | "right";
|
|
10
|
+
}
|
|
11
|
+
export declare class FramedMessage implements Component {
|
|
12
|
+
private options;
|
|
13
|
+
constructor(options: FramedMessageOptions);
|
|
14
|
+
invalidate(): void;
|
|
15
|
+
render(width: number): string[];
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=framed-message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framed-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/framed-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAY,KAAK,aAAa,EAAiC,MAAM,iBAAiB,CAAC;AAI9G,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC9B;AAED,qBAAa,aAAc,YAAW,SAAS;IAClC,OAAO,CAAC,OAAO;IAA3B,YAAoB,OAAO,EAAE,oBAAoB,EAAI;IAErD,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA6B9B;CACD","sourcesContent":["import { type Component, Markdown, type MarkdownTheme, truncateToWidth, visibleWidth } from \"@threadwell/tui\";\nimport { theme } from \"../theme/theme.js\";\nimport { getVisualTokens } from \"../theme/visual-profile.js\";\n\nexport interface FramedMessageOptions {\n\ttitle: string;\n\ttext: string;\n\tmarkdownTheme: MarkdownTheme;\n\tborderColor: (text: string) => string;\n\ttitleColor?: (text: string) => string;\n\tcontentColor?: (text: string) => string;\n\ttitleAlign?: \"left\" | \"right\";\n}\n\nexport class FramedMessage implements Component {\n\tconstructor(private options: FramedMessageOptions) {}\n\n\tinvalidate(): void {\n\t\t// Stateless wrapper. Markdown is recreated during render because width changes matter.\n\t}\n\n\trender(width: number): string[] {\n\t\tconst visual = getVisualTokens();\n\t\tconst border = visual.borders.rounded;\n\t\tconst innerWidth = Math.max(1, width - 2);\n\t\tconst contentWidth = Math.max(1, width - 4);\n\t\tconst title = this.options.titleColor?.(this.options.title) ?? this.options.title;\n\t\tconst titleGap = ` ${title} `;\n\t\tconst titleWidth = visibleWidth(titleGap);\n\t\tconst ruleWidth = Math.max(0, innerWidth - titleWidth);\n\t\tconst leftRuleWidth =\n\t\t\tthis.options.titleAlign === \"right\" ? Math.max(0, ruleWidth - 1) : Math.min(1, Math.floor(ruleWidth / 3));\n\t\tconst rightRuleWidth = Math.max(0, ruleWidth - leftRuleWidth);\n\t\tconst top =\n\t\t\tthis.options.borderColor(`${border.topLeft}${border.horizontal.repeat(leftRuleWidth)}`) +\n\t\t\t(titleWidth <= innerWidth ? titleGap : truncateToWidth(titleGap, innerWidth, \"\", false)) +\n\t\t\tthis.options.borderColor(`${border.horizontal.repeat(rightRuleWidth)}${border.topRight}`);\n\t\tconst markdown = new Markdown(this.options.text.trim(), 1, 0, this.options.markdownTheme, {\n\t\t\tcolor: this.options.contentColor ?? ((content: string) => theme.fg(\"text\", content)),\n\t\t});\n\t\tconst contentLines = markdown.render(contentWidth);\n\t\tconst body = contentLines.map((line) => {\n\t\t\tconst content = truncateToWidth(line, contentWidth, \"\", true);\n\t\t\tconst padding = \" \".repeat(Math.max(0, contentWidth - visibleWidth(content)));\n\t\t\treturn `${this.options.borderColor(border.vertical)} ${content}${padding} ${this.options.borderColor(border.vertical)}`;\n\t\t});\n\t\tconst bottom = this.options.borderColor(\n\t\t\t`${border.bottomLeft}${border.horizontal.repeat(innerWidth)}${border.bottomRight}`,\n\t\t);\n\t\treturn [top, ...body, bottom];\n\t}\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Markdown, truncateToWidth, visibleWidth } from "@threadwell/tui";
|
|
2
|
+
import { theme } from "../theme/theme.js";
|
|
3
|
+
import { getVisualTokens } from "../theme/visual-profile.js";
|
|
4
|
+
export class FramedMessage {
|
|
5
|
+
options;
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.options = options;
|
|
8
|
+
}
|
|
9
|
+
invalidate() {
|
|
10
|
+
// Stateless wrapper. Markdown is recreated during render because width changes matter.
|
|
11
|
+
}
|
|
12
|
+
render(width) {
|
|
13
|
+
const visual = getVisualTokens();
|
|
14
|
+
const border = visual.borders.rounded;
|
|
15
|
+
const innerWidth = Math.max(1, width - 2);
|
|
16
|
+
const contentWidth = Math.max(1, width - 4);
|
|
17
|
+
const title = this.options.titleColor?.(this.options.title) ?? this.options.title;
|
|
18
|
+
const titleGap = ` ${title} `;
|
|
19
|
+
const titleWidth = visibleWidth(titleGap);
|
|
20
|
+
const ruleWidth = Math.max(0, innerWidth - titleWidth);
|
|
21
|
+
const leftRuleWidth = this.options.titleAlign === "right" ? Math.max(0, ruleWidth - 1) : Math.min(1, Math.floor(ruleWidth / 3));
|
|
22
|
+
const rightRuleWidth = Math.max(0, ruleWidth - leftRuleWidth);
|
|
23
|
+
const top = this.options.borderColor(`${border.topLeft}${border.horizontal.repeat(leftRuleWidth)}`) +
|
|
24
|
+
(titleWidth <= innerWidth ? titleGap : truncateToWidth(titleGap, innerWidth, "", false)) +
|
|
25
|
+
this.options.borderColor(`${border.horizontal.repeat(rightRuleWidth)}${border.topRight}`);
|
|
26
|
+
const markdown = new Markdown(this.options.text.trim(), 1, 0, this.options.markdownTheme, {
|
|
27
|
+
color: this.options.contentColor ?? ((content) => theme.fg("text", content)),
|
|
28
|
+
});
|
|
29
|
+
const contentLines = markdown.render(contentWidth);
|
|
30
|
+
const body = contentLines.map((line) => {
|
|
31
|
+
const content = truncateToWidth(line, contentWidth, "", true);
|
|
32
|
+
const padding = " ".repeat(Math.max(0, contentWidth - visibleWidth(content)));
|
|
33
|
+
return `${this.options.borderColor(border.vertical)} ${content}${padding} ${this.options.borderColor(border.vertical)}`;
|
|
34
|
+
});
|
|
35
|
+
const bottom = this.options.borderColor(`${border.bottomLeft}${border.horizontal.repeat(innerWidth)}${border.bottomRight}`);
|
|
36
|
+
return [top, ...body, bottom];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=framed-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framed-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/framed-message.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, Markdown, type MarkdownTheme, truncateToWidth, visibleWidth } from \"@threadwell/tui\";\nimport { theme } from \"../theme/theme.js\";\nimport { getVisualTokens } from \"../theme/visual-profile.js\";\n\nexport interface FramedMessageOptions {\n\ttitle: string;\n\ttext: string;\n\tmarkdownTheme: MarkdownTheme;\n\tborderColor: (text: string) => string;\n\ttitleColor?: (text: string) => string;\n\tcontentColor?: (text: string) => string;\n\ttitleAlign?: \"left\" | \"right\";\n}\n\nexport class FramedMessage implements Component {\n\tconstructor(private options: FramedMessageOptions) {}\n\n\tinvalidate(): void {\n\t\t// Stateless wrapper. Markdown is recreated during render because width changes matter.\n\t}\n\n\trender(width: number): string[] {\n\t\tconst visual = getVisualTokens();\n\t\tconst border = visual.borders.rounded;\n\t\tconst innerWidth = Math.max(1, width - 2);\n\t\tconst contentWidth = Math.max(1, width - 4);\n\t\tconst title = this.options.titleColor?.(this.options.title) ?? this.options.title;\n\t\tconst titleGap = ` ${title} `;\n\t\tconst titleWidth = visibleWidth(titleGap);\n\t\tconst ruleWidth = Math.max(0, innerWidth - titleWidth);\n\t\tconst leftRuleWidth =\n\t\t\tthis.options.titleAlign === \"right\" ? Math.max(0, ruleWidth - 1) : Math.min(1, Math.floor(ruleWidth / 3));\n\t\tconst rightRuleWidth = Math.max(0, ruleWidth - leftRuleWidth);\n\t\tconst top =\n\t\t\tthis.options.borderColor(`${border.topLeft}${border.horizontal.repeat(leftRuleWidth)}`) +\n\t\t\t(titleWidth <= innerWidth ? titleGap : truncateToWidth(titleGap, innerWidth, \"\", false)) +\n\t\t\tthis.options.borderColor(`${border.horizontal.repeat(rightRuleWidth)}${border.topRight}`);\n\t\tconst markdown = new Markdown(this.options.text.trim(), 1, 0, this.options.markdownTheme, {\n\t\t\tcolor: this.options.contentColor ?? ((content: string) => theme.fg(\"text\", content)),\n\t\t});\n\t\tconst contentLines = markdown.render(contentWidth);\n\t\tconst body = contentLines.map((line) => {\n\t\t\tconst content = truncateToWidth(line, contentWidth, \"\", true);\n\t\t\tconst padding = \" \".repeat(Math.max(0, contentWidth - visibleWidth(content)));\n\t\t\treturn `${this.options.borderColor(border.vertical)} ${content}${padding} ${this.options.borderColor(border.vertical)}`;\n\t\t});\n\t\tconst bottom = this.options.borderColor(\n\t\t\t`${border.bottomLeft}${border.horizontal.repeat(innerWidth)}${border.bottomRight}`,\n\t\t);\n\t\treturn [top, ...body, bottom];\n\t}\n}\n"]}
|
|
@@ -15,8 +15,6 @@ export interface SettingsConfig {
|
|
|
15
15
|
transport: Transport;
|
|
16
16
|
thinkingLevel: ThinkingLevel;
|
|
17
17
|
availableThinkingLevels: ThinkingLevel[];
|
|
18
|
-
currentTheme: string;
|
|
19
|
-
availableThemes: string[];
|
|
20
18
|
hideThinkingBlock: boolean;
|
|
21
19
|
collapseChangelog: boolean;
|
|
22
20
|
enableInstallTelemetry: boolean;
|
|
@@ -44,8 +42,6 @@ export interface SettingsCallbacks {
|
|
|
44
42
|
onFollowUpModeChange: (mode: "all" | "one-at-a-time") => void;
|
|
45
43
|
onTransportChange: (transport: Transport) => void;
|
|
46
44
|
onThinkingLevelChange: (level: ThinkingLevel) => void;
|
|
47
|
-
onThemeChange: (theme: string) => void;
|
|
48
|
-
onThemePreview?: (theme: string) => void;
|
|
49
45
|
onHideThinkingBlockChange: (hidden: boolean) => void;
|
|
50
46
|
onCollapseChangelogChange: (collapsed: boolean) => void;
|
|
51
47
|
onEnableInstallTelemetryChange: (enabled: boolean) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/settings-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@threadwell/agent-core\";\nimport type { Transport } from \"@threadwell/ai\";\nimport {\n\tContainer,\n\tgetCapabilities,\n\ttype SelectItem,\n\tSelectList,\n\ttype SelectListLayoutOptions,\n\ttype SettingItem,\n\tSettingsList,\n\tSpacer,\n\tText,\n} from \"@threadwell/tui\";\nimport type { InterfaceSettings, MemorySettings, WarningSettings } from \"../../../core/settings-manager.js\";\nimport { getSelectListTheme, getSettingsListTheme, theme } from \"../theme/theme.js\";\nimport { DynamicBorder } from \"./dynamic-border.js\";\n\nconst SETTINGS_SUBMENU_SELECT_LIST_LAYOUT: SelectListLayoutOptions = {\n\tminPrimaryColumnWidth: 12,\n\tmaxPrimaryColumnWidth: 32,\n};\n\nconst THINKING_DESCRIPTIONS: Record<ThinkingLevel, string> = {\n\toff: \"No reasoning\",\n\tminimal: \"Very brief reasoning (~1k tokens)\",\n\tlow: \"Light reasoning (~2k tokens)\",\n\tmedium: \"Moderate reasoning (~8k tokens)\",\n\thigh: \"Deep reasoning (~16k tokens)\",\n\txhigh: \"Maximum reasoning (~32k tokens)\",\n};\n\nexport interface SettingsConfig {\n\tautoCompact: boolean;\n\tshowImages: boolean;\n\timageWidthCells: number;\n\tautoResizeImages: boolean;\n\tblockImages: boolean;\n\tskillsEnabled: boolean;\n\tenableSkillCommands: boolean;\n\tsteeringMode: \"all\" | \"one-at-a-time\";\n\tfollowUpMode: \"all\" | \"one-at-a-time\";\n\ttransport: Transport;\n\tthinkingLevel: ThinkingLevel;\n\tavailableThinkingLevels: ThinkingLevel[];\n\tcurrentTheme: string;\n\tavailableThemes: string[];\n\thideThinkingBlock: boolean;\n\tcollapseChangelog: boolean;\n\tenableInstallTelemetry: boolean;\n\tdoubleEscapeAction: \"fork\" | \"tree\" | \"none\";\n\ttreeFilterMode: \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\";\n\tshowHardwareCursor: boolean;\n\teditorPaddingX: number;\n\tautocompleteMaxVisible: number;\n\tquietStartup: boolean;\n\tclearOnShrink: boolean;\n\tshowTerminalProgress: boolean;\n\twarnings: WarningSettings;\n\tinterface: Required<InterfaceSettings>;\n\tmemory: Required<Pick<MemorySettings, \"enabled\" | \"inject\" | \"store\">>;\n}\n\nexport interface SettingsCallbacks {\n\tonAutoCompactChange: (enabled: boolean) => void;\n\tonShowImagesChange: (enabled: boolean) => void;\n\tonImageWidthCellsChange: (width: number) => void;\n\tonAutoResizeImagesChange: (enabled: boolean) => void;\n\tonBlockImagesChange: (blocked: boolean) => void;\n\tonSkillsEnabledChange: (enabled: boolean) => void;\n\tonEnableSkillCommandsChange: (enabled: boolean) => void;\n\tonSteeringModeChange: (mode: \"all\" | \"one-at-a-time\") => void;\n\tonFollowUpModeChange: (mode: \"all\" | \"one-at-a-time\") => void;\n\tonTransportChange: (transport: Transport) => void;\n\tonThinkingLevelChange: (level: ThinkingLevel) => void;\n\tonThemeChange: (theme: string) => void;\n\tonThemePreview?: (theme: string) => void;\n\tonHideThinkingBlockChange: (hidden: boolean) => void;\n\tonCollapseChangelogChange: (collapsed: boolean) => void;\n\tonEnableInstallTelemetryChange: (enabled: boolean) => void;\n\tonDoubleEscapeActionChange: (action: \"fork\" | \"tree\" | \"none\") => void;\n\tonTreeFilterModeChange: (mode: \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\") => void;\n\tonShowHardwareCursorChange: (enabled: boolean) => void;\n\tonEditorPaddingXChange: (padding: number) => void;\n\tonAutocompleteMaxVisibleChange: (maxVisible: number) => void;\n\tonQuietStartupChange: (enabled: boolean) => void;\n\tonClearOnShrinkChange: (enabled: boolean) => void;\n\tonShowTerminalProgressChange: (enabled: boolean) => void;\n\tonWarningsChange: (warnings: WarningSettings) => void;\n\tonInterfaceChange: (settings: InterfaceSettings) => void;\n\tonMemoryChange: (memory: MemorySettings) => void;\n\tonCancel: () => void;\n}\n\n/**\n * A submenu component for selecting from a list of options.\n */\nclass InterfaceSettingsSubmenu extends Container {\n\tprivate settingsList: SettingsList;\n\tprivate state: Required<InterfaceSettings>;\n\n\tconstructor(\n\t\tsettings: Required<InterfaceSettings>,\n\t\tonChange: (settings: InterfaceSettings) => void,\n\t\tonCancel: () => void,\n\t) {\n\t\tsuper();\n\n\t\tthis.state = { ...settings };\n\n\t\tconst items: SettingItem[] = [\n\t\t\t{\n\t\t\t\tid: \"show-startup-card\",\n\t\t\t\tlabel: \"Startup card\",\n\t\t\t\tdescription: \"Show the Threadwell split startup card\",\n\t\t\t\tcurrentValue: this.state.showStartupCard ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"show-update-notifications\",\n\t\t\t\tlabel: \"Update notifications\",\n\t\t\t\tdescription: \"Show version and package update boxes on startup\",\n\t\t\t\tcurrentValue: this.state.showUpdateNotifications ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"show-startup-context-files\",\n\t\t\t\tlabel: \"Startup context files\",\n\t\t\t\tdescription: \"Show loaded context files on startup\",\n\t\t\t\tcurrentValue: this.state.showStartupContextFiles ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"show-startup-prompts\",\n\t\t\t\tlabel: \"Startup prompts\",\n\t\t\t\tdescription: \"Show loaded prompt templates on startup\",\n\t\t\t\tcurrentValue: this.state.showStartupPrompts ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"show-startup-extensions\",\n\t\t\t\tlabel: \"Startup extensions\",\n\t\t\t\tdescription: \"Show loaded extensions on startup\",\n\t\t\t\tcurrentValue: this.state.showStartupExtensions ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t];\n\n\t\tthis.settingsList = new SettingsList(\n\t\t\titems,\n\t\t\tMath.min(items.length, 10),\n\t\t\tgetSettingsListTheme(),\n\t\t\t(id, newValue) => {\n\t\t\t\tswitch (id) {\n\t\t\t\t\tcase \"show-startup-card\":\n\t\t\t\t\t\tthis.state = { ...this.state, showStartupCard: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-update-notifications\":\n\t\t\t\t\t\tthis.state = { ...this.state, showUpdateNotifications: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-startup-context-files\":\n\t\t\t\t\t\tthis.state = { ...this.state, showStartupContextFiles: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-startup-prompts\":\n\t\t\t\t\t\tthis.state = { ...this.state, showStartupPrompts: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-startup-extensions\":\n\t\t\t\t\t\tthis.state = { ...this.state, showStartupExtensions: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tonCancel,\n\t\t);\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Text(theme.bold(\"Interface\"), 0, 0));\n\t\tthis.addChild(new Text(theme.fg(\"muted\", \" Visual startup and interface preferences\"), 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(this.settingsList);\n\t}\n\n\thandleInput(data: string): void {\n\t\tthis.settingsList.handleInput(data);\n\t}\n}\n\nclass WarningSettingsSubmenu extends Container {\n\tprivate settingsList: SettingsList;\n\tprivate state: WarningSettings;\n\n\tconstructor(warnings: WarningSettings, onChange: (warnings: WarningSettings) => void, onCancel: () => void) {\n\t\tsuper();\n\n\t\tthis.state = { ...warnings };\n\n\t\tconst items: SettingItem[] = [\n\t\t\t{\n\t\t\t\tid: \"anthropic-extra-usage\",\n\t\t\t\tlabel: \"Anthropic extra usage\",\n\t\t\t\tdescription: \"Warn when Anthropic subscription auth may use paid extra usage\",\n\t\t\t\tcurrentValue: (this.state.anthropicExtraUsage ?? true) ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t];\n\n\t\tthis.settingsList = new SettingsList(\n\t\t\titems,\n\t\t\tMath.min(items.length, 10),\n\t\t\tgetSettingsListTheme(),\n\t\t\t(id, newValue) => {\n\t\t\t\tswitch (id) {\n\t\t\t\t\tcase \"anthropic-extra-usage\":\n\t\t\t\t\t\tthis.state = { ...this.state, anthropicExtraUsage: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tonCancel,\n\t\t);\n\n\t\tthis.addChild(this.settingsList);\n\t}\n\n\thandleInput(data: string): void {\n\t\tthis.settingsList.handleInput(data);\n\t}\n}\n\nclass MemorySettingsSubmenu extends Container {\n\tprivate settingsList: SettingsList;\n\tprivate state: Required<Pick<MemorySettings, \"enabled\" | \"inject\" | \"store\">>;\n\n\tconstructor(\n\t\tmemory: Required<Pick<MemorySettings, \"enabled\" | \"inject\" | \"store\">>,\n\t\tonChange: (memory: MemorySettings) => void,\n\t\tonCancel: () => void,\n\t) {\n\t\tsuper();\n\t\tthis.state = { ...memory };\n\t\tconst items: SettingItem[] = [\n\t\t\t{\n\t\t\t\tid: \"memory-enabled\",\n\t\t\t\tlabel: \"Memory\",\n\t\t\t\tdescription: \"Capture local Threadwell memory events (restart required)\",\n\t\t\t\tcurrentValue: this.state.enabled ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"memory-inject\",\n\t\t\t\tlabel: \"Memory injection\",\n\t\t\t\tdescription: \"Inject bounded relevant memory before model calls (restart required)\",\n\t\t\t\tcurrentValue: this.state.inject ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"memory-store\",\n\t\t\t\tlabel: \"Memory store\",\n\t\t\t\tdescription: \"Local storage backend; sqlite is durable and project-local (restart required)\",\n\t\t\t\tcurrentValue: this.state.store,\n\t\t\t\tvalues: [\"sqlite\", \"memory\", \"noop\"],\n\t\t\t},\n\t\t];\n\n\t\tthis.settingsList = new SettingsList(\n\t\t\titems,\n\t\t\titems.length,\n\t\t\tgetSettingsListTheme(),\n\t\t\t(id, newValue) => {\n\t\t\t\tswitch (id) {\n\t\t\t\t\tcase \"memory-enabled\":\n\t\t\t\t\t\tthis.state = { ...this.state, enabled: newValue === \"true\" };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"memory-inject\":\n\t\t\t\t\t\tthis.state = { ...this.state, inject: newValue === \"true\" };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"memory-store\":\n\t\t\t\t\t\tthis.state = { ...this.state, store: newValue as \"sqlite\" | \"memory\" | \"noop\" };\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tonChange({ ...this.state });\n\t\t\t},\n\t\t\tonCancel,\n\t\t);\n\t\tthis.addChild(this.settingsList);\n\t}\n\n\thandleInput(data: string): void {\n\t\tthis.settingsList.handleInput(data);\n\t}\n}\n\nclass SelectSubmenu extends Container {\n\tprivate selectList: SelectList;\n\n\tconstructor(\n\t\ttitle: string,\n\t\tdescription: string,\n\t\toptions: SelectItem[],\n\t\tcurrentValue: string,\n\t\tonSelect: (value: string) => void,\n\t\tonCancel: () => void,\n\t\tonSelectionChange?: (value: string) => void,\n\t) {\n\t\tsuper();\n\n\t\t// Title\n\t\tthis.addChild(new Text(theme.bold(theme.fg(\"accent\", title)), 0, 0));\n\n\t\t// Description\n\t\tif (description) {\n\t\t\tthis.addChild(new Spacer(1));\n\t\t\tthis.addChild(new Text(theme.fg(\"muted\", description), 0, 0));\n\t\t}\n\n\t\t// Spacer\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Select list\n\t\tthis.selectList = new SelectList(\n\t\t\toptions,\n\t\t\tMath.min(options.length, 10),\n\t\t\tgetSelectListTheme(),\n\t\t\tSETTINGS_SUBMENU_SELECT_LIST_LAYOUT,\n\t\t);\n\n\t\t// Pre-select current value\n\t\tconst currentIndex = options.findIndex((o) => o.value === currentValue);\n\t\tif (currentIndex !== -1) {\n\t\t\tthis.selectList.setSelectedIndex(currentIndex);\n\t\t}\n\n\t\tthis.selectList.onSelect = (item) => {\n\t\t\tonSelect(item.value);\n\t\t};\n\n\t\tthis.selectList.onCancel = onCancel;\n\n\t\tif (onSelectionChange) {\n\t\t\tthis.selectList.onSelectionChange = (item) => {\n\t\t\t\tonSelectionChange(item.value);\n\t\t\t};\n\t\t}\n\n\t\tthis.addChild(this.selectList);\n\n\t\t// Hint\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.fg(\"dim\", \" Enter to select · Esc to go back\"), 0, 0));\n\t}\n\n\thandleInput(data: string): void {\n\t\tthis.selectList.handleInput(data);\n\t}\n}\n\n/**\n * Main settings selector component.\n */\nexport class SettingsSelectorComponent extends Container {\n\tprivate settingsList: SettingsList;\n\n\tconstructor(config: SettingsConfig, callbacks: SettingsCallbacks) {\n\t\tsuper();\n\n\t\tconst supportsImages = getCapabilities().images;\n\t\tlet currentWarnings = { ...config.warnings };\n\t\tlet currentInterface = { ...config.interface };\n\n\t\tconst items: SettingItem[] = [\n\t\t\t{\n\t\t\t\tid: \"interface\",\n\t\t\t\tlabel: \"Interface\",\n\t\t\t\tdescription: \"Visual startup and interface preferences\",\n\t\t\t\tcurrentValue: \"configure\",\n\t\t\t\tsubmenu: (_currentValue, done) =>\n\t\t\t\t\tnew InterfaceSettingsSubmenu(\n\t\t\t\t\t\tcurrentInterface,\n\t\t\t\t\t\t(settings) => {\n\t\t\t\t\t\t\tcurrentInterface = { ...currentInterface, ...settings };\n\t\t\t\t\t\t\tcallbacks.onInterfaceChange(settings);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => done(),\n\t\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"memory\",\n\t\t\t\tlabel: \"Threadwell memory\",\n\t\t\t\tdescription: \"Local SQLite memory capture and bounded injection (restart required)\",\n\t\t\t\tcurrentValue: config.memory.enabled ? \"enabled\" : \"disabled\",\n\t\t\t\tsubmenu: (_currentValue, done) =>\n\t\t\t\t\tnew MemorySettingsSubmenu(\n\t\t\t\t\t\tconfig.memory,\n\t\t\t\t\t\t(memory) => {\n\t\t\t\t\t\t\tcallbacks.onMemoryChange(memory);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => done(),\n\t\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"autocompact\",\n\t\t\t\tlabel: \"Auto-compact\",\n\t\t\t\tdescription: \"Automatically compact context when it gets too large\",\n\t\t\t\tcurrentValue: config.autoCompact ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"steering-mode\",\n\t\t\t\tlabel: \"Steering mode\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Enter while streaming queues steering messages. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.\",\n\t\t\t\tcurrentValue: config.steeringMode,\n\t\t\t\tvalues: [\"one-at-a-time\", \"all\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"follow-up-mode\",\n\t\t\t\tlabel: \"Follow-up mode\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Alt+Enter queues follow-up messages until agent stops. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.\",\n\t\t\t\tcurrentValue: config.followUpMode,\n\t\t\t\tvalues: [\"one-at-a-time\", \"all\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"transport\",\n\t\t\t\tlabel: \"Transport\",\n\t\t\t\tdescription: \"Preferred transport for providers that support multiple transports\",\n\t\t\t\tcurrentValue: config.transport,\n\t\t\t\tvalues: [\"sse\", \"websocket\", \"websocket-cached\", \"auto\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"hide-thinking\",\n\t\t\t\tlabel: \"Hide thinking\",\n\t\t\t\tdescription: \"Hide thinking blocks in assistant responses\",\n\t\t\t\tcurrentValue: config.hideThinkingBlock ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"collapse-changelog\",\n\t\t\t\tlabel: \"Collapse changelog\",\n\t\t\t\tdescription: \"Show condensed changelog after updates\",\n\t\t\t\tcurrentValue: config.collapseChangelog ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"quiet-startup\",\n\t\t\t\tlabel: \"Quiet startup\",\n\t\t\t\tdescription: \"Disable verbose printing at startup\",\n\t\t\t\tcurrentValue: config.quietStartup ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"install-telemetry\",\n\t\t\t\tlabel: \"Install telemetry\",\n\t\t\t\tdescription: \"Send an anonymous version/update ping after changelog-detected updates\",\n\t\t\t\tcurrentValue: config.enableInstallTelemetry ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"double-escape-action\",\n\t\t\t\tlabel: \"Double-escape action\",\n\t\t\t\tdescription: \"Action when pressing Escape twice with empty editor\",\n\t\t\t\tcurrentValue: config.doubleEscapeAction,\n\t\t\t\tvalues: [\"tree\", \"fork\", \"none\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"tree-filter-mode\",\n\t\t\t\tlabel: \"Tree filter mode\",\n\t\t\t\tdescription: \"Default filter when opening /tree\",\n\t\t\t\tcurrentValue: config.treeFilterMode,\n\t\t\t\tvalues: [\"default\", \"no-tools\", \"user-only\", \"labeled-only\", \"all\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"warnings\",\n\t\t\t\tlabel: \"Warnings\",\n\t\t\t\tdescription: \"Enable or disable individual warnings\",\n\t\t\t\tcurrentValue: \"configure\",\n\t\t\t\tsubmenu: (_currentValue, done) =>\n\t\t\t\t\tnew WarningSettingsSubmenu(\n\t\t\t\t\t\tcurrentWarnings,\n\t\t\t\t\t\t(warnings) => {\n\t\t\t\t\t\t\tcurrentWarnings = warnings;\n\t\t\t\t\t\t\tcallbacks.onWarningsChange(warnings);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => done(),\n\t\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"thinking\",\n\t\t\t\tlabel: \"Thinking level\",\n\t\t\t\tdescription: \"Reasoning depth for thinking-capable models\",\n\t\t\t\tcurrentValue: config.thinkingLevel,\n\t\t\t\tsubmenu: (currentValue, done) =>\n\t\t\t\t\tnew SelectSubmenu(\n\t\t\t\t\t\t\"Thinking Level\",\n\t\t\t\t\t\t\"Select reasoning depth for thinking-capable models\",\n\t\t\t\t\t\tconfig.availableThinkingLevels.map((level) => ({\n\t\t\t\t\t\t\tvalue: level,\n\t\t\t\t\t\t\tlabel: level,\n\t\t\t\t\t\t\tdescription: THINKING_DESCRIPTIONS[level],\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tcurrentValue,\n\t\t\t\t\t\t(value) => {\n\t\t\t\t\t\t\tcallbacks.onThinkingLevelChange(value as ThinkingLevel);\n\t\t\t\t\t\t\tdone(value);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => done(),\n\t\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"theme\",\n\t\t\t\tlabel: \"Theme\",\n\t\t\t\tdescription: \"Color theme for the interface\",\n\t\t\t\tcurrentValue: config.currentTheme,\n\t\t\t\tsubmenu: (currentValue, done) =>\n\t\t\t\t\tnew SelectSubmenu(\n\t\t\t\t\t\t\"Theme\",\n\t\t\t\t\t\t\"Select color theme\",\n\t\t\t\t\t\tconfig.availableThemes.map((t) => ({\n\t\t\t\t\t\t\tvalue: t,\n\t\t\t\t\t\t\tlabel: t,\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tcurrentValue,\n\t\t\t\t\t\t(value) => {\n\t\t\t\t\t\t\tcallbacks.onThemeChange(value);\n\t\t\t\t\t\t\tdone(value);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => {\n\t\t\t\t\t\t\t// Restore original theme on cancel\n\t\t\t\t\t\t\tcallbacks.onThemePreview?.(currentValue);\n\t\t\t\t\t\t\tdone();\n\t\t\t\t\t\t},\n\t\t\t\t\t\t(value) => {\n\t\t\t\t\t\t\t// Preview theme on selection change\n\t\t\t\t\t\t\tcallbacks.onThemePreview?.(value);\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t},\n\t\t];\n\n\t\t// Only show image toggle if terminal supports it\n\t\tif (supportsImages) {\n\t\t\t// Insert after autocompact\n\t\t\titems.splice(1, 0, {\n\t\t\t\tid: \"show-images\",\n\t\t\t\tlabel: \"Show images\",\n\t\t\t\tdescription: \"Render images inline in terminal\",\n\t\t\t\tcurrentValue: config.showImages ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t});\n\t\t\titems.splice(2, 0, {\n\t\t\t\tid: \"image-width-cells\",\n\t\t\t\tlabel: \"Image width\",\n\t\t\t\tdescription: \"Preferred inline image width in terminal cells\",\n\t\t\t\tcurrentValue: String(config.imageWidthCells),\n\t\t\t\tvalues: [\"60\", \"80\", \"120\"],\n\t\t\t});\n\t\t}\n\n\t\t// Image auto-resize toggle (always available, affects both attached and read images)\n\t\titems.splice(supportsImages ? 3 : 1, 0, {\n\t\t\tid: \"auto-resize-images\",\n\t\t\tlabel: \"Auto-resize images\",\n\t\t\tdescription: \"Resize large images to 2000x2000 max for better model compatibility\",\n\t\t\tcurrentValue: config.autoResizeImages ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Block images toggle (always available, insert after auto-resize-images)\n\t\tconst autoResizeIndex = items.findIndex((item) => item.id === \"auto-resize-images\");\n\t\titems.splice(autoResizeIndex + 1, 0, {\n\t\t\tid: \"block-images\",\n\t\t\tlabel: \"Block images\",\n\t\t\tdescription: \"Prevent images from being sent to LLM providers\",\n\t\t\tcurrentValue: config.blockImages ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Skills toggle (insert after block-images)\n\t\tconst blockImagesIndex = items.findIndex((item) => item.id === \"block-images\");\n\t\titems.splice(blockImagesIndex + 1, 0, {\n\t\t\tid: \"skills-enabled\",\n\t\t\tlabel: \"Skills\",\n\t\t\tdescription: \"Load and inject installed skills\",\n\t\t\tcurrentValue: config.skillsEnabled ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Skill commands toggle (insert after skills)\n\t\tconst skillsEnabledIndex = items.findIndex((item) => item.id === \"skills-enabled\");\n\t\titems.splice(skillsEnabledIndex + 1, 0, {\n\t\t\tid: \"skill-commands\",\n\t\t\tlabel: \"Skill commands\",\n\t\t\tdescription: \"Register loaded skills as /skill:name commands\",\n\t\t\tcurrentValue: config.enableSkillCommands ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Hardware cursor toggle (insert after skill-commands)\n\t\tconst skillCommandsIndex = items.findIndex((item) => item.id === \"skill-commands\");\n\t\titems.splice(skillCommandsIndex + 1, 0, {\n\t\t\tid: \"show-hardware-cursor\",\n\t\t\tlabel: \"Show hardware cursor\",\n\t\t\tdescription: \"Show the terminal cursor while still positioning it for IME support\",\n\t\t\tcurrentValue: config.showHardwareCursor ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Editor padding toggle (insert after show-hardware-cursor)\n\t\tconst hardwareCursorIndex = items.findIndex((item) => item.id === \"show-hardware-cursor\");\n\t\titems.splice(hardwareCursorIndex + 1, 0, {\n\t\t\tid: \"editor-padding\",\n\t\t\tlabel: \"Editor padding\",\n\t\t\tdescription: \"Horizontal padding for input editor (0-3)\",\n\t\t\tcurrentValue: String(config.editorPaddingX),\n\t\t\tvalues: [\"0\", \"1\", \"2\", \"3\"],\n\t\t});\n\n\t\t// Autocomplete max visible toggle (insert after editor-padding)\n\t\tconst editorPaddingIndex = items.findIndex((item) => item.id === \"editor-padding\");\n\t\titems.splice(editorPaddingIndex + 1, 0, {\n\t\t\tid: \"autocomplete-max-visible\",\n\t\t\tlabel: \"Autocomplete max items\",\n\t\t\tdescription: \"Max visible items in autocomplete dropdown (3-20)\",\n\t\t\tcurrentValue: String(config.autocompleteMaxVisible),\n\t\t\tvalues: [\"3\", \"5\", \"7\", \"10\", \"15\", \"20\"],\n\t\t});\n\n\t\t// Clear on shrink toggle (insert after autocomplete-max-visible)\n\t\tconst autocompleteIndex = items.findIndex((item) => item.id === \"autocomplete-max-visible\");\n\t\titems.splice(autocompleteIndex + 1, 0, {\n\t\t\tid: \"clear-on-shrink\",\n\t\t\tlabel: \"Clear on shrink\",\n\t\t\tdescription: \"Clear empty rows when content shrinks (may cause flicker)\",\n\t\t\tcurrentValue: config.clearOnShrink ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Terminal progress toggle (insert after clear-on-shrink)\n\t\tconst clearOnShrinkIndex = items.findIndex((item) => item.id === \"clear-on-shrink\");\n\t\titems.splice(clearOnShrinkIndex + 1, 0, {\n\t\t\tid: \"terminal-progress\",\n\t\t\tlabel: \"Terminal progress\",\n\t\t\tdescription: \"Show OSC 9;4 progress indicators in the terminal tab bar\",\n\t\t\tcurrentValue: config.showTerminalProgress ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Add borders\n\t\tthis.addChild(new DynamicBorder());\n\n\t\tthis.settingsList = new SettingsList(\n\t\t\titems,\n\t\t\t10,\n\t\t\tgetSettingsListTheme(),\n\t\t\t(id, newValue) => {\n\t\t\t\tswitch (id) {\n\t\t\t\t\tcase \"autocompact\":\n\t\t\t\t\t\tcallbacks.onAutoCompactChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-images\":\n\t\t\t\t\t\tcallbacks.onShowImagesChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"image-width-cells\":\n\t\t\t\t\t\tcallbacks.onImageWidthCellsChange(parseInt(newValue, 10));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"auto-resize-images\":\n\t\t\t\t\t\tcallbacks.onAutoResizeImagesChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"block-images\":\n\t\t\t\t\t\tcallbacks.onBlockImagesChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"skills-enabled\":\n\t\t\t\t\t\tcallbacks.onSkillsEnabledChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"skill-commands\":\n\t\t\t\t\t\tcallbacks.onEnableSkillCommandsChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"steering-mode\":\n\t\t\t\t\t\tcallbacks.onSteeringModeChange(newValue as \"all\" | \"one-at-a-time\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"follow-up-mode\":\n\t\t\t\t\t\tcallbacks.onFollowUpModeChange(newValue as \"all\" | \"one-at-a-time\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"transport\":\n\t\t\t\t\t\tcallbacks.onTransportChange(newValue as Transport);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"hide-thinking\":\n\t\t\t\t\t\tcallbacks.onHideThinkingBlockChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"collapse-changelog\":\n\t\t\t\t\t\tcallbacks.onCollapseChangelogChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"quiet-startup\":\n\t\t\t\t\t\tcallbacks.onQuietStartupChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"install-telemetry\":\n\t\t\t\t\t\tcallbacks.onEnableInstallTelemetryChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"double-escape-action\":\n\t\t\t\t\t\tcallbacks.onDoubleEscapeActionChange(newValue as \"fork\" | \"tree\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"tree-filter-mode\":\n\t\t\t\t\t\tcallbacks.onTreeFilterModeChange(\n\t\t\t\t\t\t\tnewValue as \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-hardware-cursor\":\n\t\t\t\t\t\tcallbacks.onShowHardwareCursorChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"editor-padding\":\n\t\t\t\t\t\tcallbacks.onEditorPaddingXChange(parseInt(newValue, 10));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"autocomplete-max-visible\":\n\t\t\t\t\t\tcallbacks.onAutocompleteMaxVisibleChange(parseInt(newValue, 10));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"clear-on-shrink\":\n\t\t\t\t\t\tcallbacks.onClearOnShrinkChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"terminal-progress\":\n\t\t\t\t\t\tcallbacks.onShowTerminalProgressChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tcallbacks.onCancel,\n\t\t\t{ enableSearch: true },\n\t\t);\n\n\t\tthis.addChild(this.settingsList);\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\tgetSettingsList(): SettingsList {\n\t\treturn this.settingsList;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"settings-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/settings-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@threadwell/agent-core\";\nimport type { Transport } from \"@threadwell/ai\";\nimport {\n\tContainer,\n\tgetCapabilities,\n\ttype SelectItem,\n\tSelectList,\n\ttype SelectListLayoutOptions,\n\ttype SettingItem,\n\tSettingsList,\n\tSpacer,\n\tText,\n} from \"@threadwell/tui\";\nimport type { InterfaceSettings, MemorySettings, WarningSettings } from \"../../../core/settings-manager.js\";\nimport { getSelectListTheme, getSettingsListTheme, theme } from \"../theme/theme.js\";\nimport { DynamicBorder } from \"./dynamic-border.js\";\n\nconst SETTINGS_SUBMENU_SELECT_LIST_LAYOUT: SelectListLayoutOptions = {\n\tminPrimaryColumnWidth: 12,\n\tmaxPrimaryColumnWidth: 32,\n};\n\nconst THINKING_DESCRIPTIONS: Record<ThinkingLevel, string> = {\n\toff: \"No reasoning\",\n\tminimal: \"Very brief reasoning (~1k tokens)\",\n\tlow: \"Light reasoning (~2k tokens)\",\n\tmedium: \"Moderate reasoning (~8k tokens)\",\n\thigh: \"Deep reasoning (~16k tokens)\",\n\txhigh: \"Maximum reasoning (~32k tokens)\",\n};\n\nexport interface SettingsConfig {\n\tautoCompact: boolean;\n\tshowImages: boolean;\n\timageWidthCells: number;\n\tautoResizeImages: boolean;\n\tblockImages: boolean;\n\tskillsEnabled: boolean;\n\tenableSkillCommands: boolean;\n\tsteeringMode: \"all\" | \"one-at-a-time\";\n\tfollowUpMode: \"all\" | \"one-at-a-time\";\n\ttransport: Transport;\n\tthinkingLevel: ThinkingLevel;\n\tavailableThinkingLevels: ThinkingLevel[];\n\thideThinkingBlock: boolean;\n\tcollapseChangelog: boolean;\n\tenableInstallTelemetry: boolean;\n\tdoubleEscapeAction: \"fork\" | \"tree\" | \"none\";\n\ttreeFilterMode: \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\";\n\tshowHardwareCursor: boolean;\n\teditorPaddingX: number;\n\tautocompleteMaxVisible: number;\n\tquietStartup: boolean;\n\tclearOnShrink: boolean;\n\tshowTerminalProgress: boolean;\n\twarnings: WarningSettings;\n\tinterface: Required<InterfaceSettings>;\n\tmemory: Required<Pick<MemorySettings, \"enabled\" | \"inject\" | \"store\">>;\n}\n\nexport interface SettingsCallbacks {\n\tonAutoCompactChange: (enabled: boolean) => void;\n\tonShowImagesChange: (enabled: boolean) => void;\n\tonImageWidthCellsChange: (width: number) => void;\n\tonAutoResizeImagesChange: (enabled: boolean) => void;\n\tonBlockImagesChange: (blocked: boolean) => void;\n\tonSkillsEnabledChange: (enabled: boolean) => void;\n\tonEnableSkillCommandsChange: (enabled: boolean) => void;\n\tonSteeringModeChange: (mode: \"all\" | \"one-at-a-time\") => void;\n\tonFollowUpModeChange: (mode: \"all\" | \"one-at-a-time\") => void;\n\tonTransportChange: (transport: Transport) => void;\n\tonThinkingLevelChange: (level: ThinkingLevel) => void;\n\tonHideThinkingBlockChange: (hidden: boolean) => void;\n\tonCollapseChangelogChange: (collapsed: boolean) => void;\n\tonEnableInstallTelemetryChange: (enabled: boolean) => void;\n\tonDoubleEscapeActionChange: (action: \"fork\" | \"tree\" | \"none\") => void;\n\tonTreeFilterModeChange: (mode: \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\") => void;\n\tonShowHardwareCursorChange: (enabled: boolean) => void;\n\tonEditorPaddingXChange: (padding: number) => void;\n\tonAutocompleteMaxVisibleChange: (maxVisible: number) => void;\n\tonQuietStartupChange: (enabled: boolean) => void;\n\tonClearOnShrinkChange: (enabled: boolean) => void;\n\tonShowTerminalProgressChange: (enabled: boolean) => void;\n\tonWarningsChange: (warnings: WarningSettings) => void;\n\tonInterfaceChange: (settings: InterfaceSettings) => void;\n\tonMemoryChange: (memory: MemorySettings) => void;\n\tonCancel: () => void;\n}\n\n/**\n * A submenu component for selecting from a list of options.\n */\nclass InterfaceSettingsSubmenu extends Container {\n\tprivate settingsList: SettingsList;\n\tprivate state: Required<InterfaceSettings>;\n\n\tconstructor(\n\t\tsettings: Required<InterfaceSettings>,\n\t\tonChange: (settings: InterfaceSettings) => void,\n\t\tonCancel: () => void,\n\t) {\n\t\tsuper();\n\n\t\tthis.state = { ...settings };\n\n\t\tconst items: SettingItem[] = [\n\t\t\t{\n\t\t\t\tid: \"show-startup-card\",\n\t\t\t\tlabel: \"Startup card\",\n\t\t\t\tdescription: \"Show the Threadwell split startup card\",\n\t\t\t\tcurrentValue: this.state.showStartupCard ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"show-update-notifications\",\n\t\t\t\tlabel: \"Update notifications\",\n\t\t\t\tdescription: \"Show version and package update boxes on startup\",\n\t\t\t\tcurrentValue: this.state.showUpdateNotifications ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"show-startup-context-files\",\n\t\t\t\tlabel: \"Startup context files\",\n\t\t\t\tdescription: \"Show loaded context files on startup\",\n\t\t\t\tcurrentValue: this.state.showStartupContextFiles ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"show-startup-prompts\",\n\t\t\t\tlabel: \"Startup prompts\",\n\t\t\t\tdescription: \"Show loaded prompt templates on startup\",\n\t\t\t\tcurrentValue: this.state.showStartupPrompts ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"show-startup-extensions\",\n\t\t\t\tlabel: \"Startup extensions\",\n\t\t\t\tdescription: \"Show loaded extensions on startup\",\n\t\t\t\tcurrentValue: this.state.showStartupExtensions ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t];\n\n\t\tthis.settingsList = new SettingsList(\n\t\t\titems,\n\t\t\tMath.min(items.length, 10),\n\t\t\tgetSettingsListTheme(),\n\t\t\t(id, newValue) => {\n\t\t\t\tswitch (id) {\n\t\t\t\t\tcase \"show-startup-card\":\n\t\t\t\t\t\tthis.state = { ...this.state, showStartupCard: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-update-notifications\":\n\t\t\t\t\t\tthis.state = { ...this.state, showUpdateNotifications: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-startup-context-files\":\n\t\t\t\t\t\tthis.state = { ...this.state, showStartupContextFiles: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-startup-prompts\":\n\t\t\t\t\t\tthis.state = { ...this.state, showStartupPrompts: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-startup-extensions\":\n\t\t\t\t\t\tthis.state = { ...this.state, showStartupExtensions: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tonCancel,\n\t\t);\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Text(theme.bold(\"Interface\"), 0, 0));\n\t\tthis.addChild(new Text(theme.fg(\"muted\", \" Visual startup and interface preferences\"), 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(this.settingsList);\n\t}\n\n\thandleInput(data: string): void {\n\t\tthis.settingsList.handleInput(data);\n\t}\n}\n\nclass WarningSettingsSubmenu extends Container {\n\tprivate settingsList: SettingsList;\n\tprivate state: WarningSettings;\n\n\tconstructor(warnings: WarningSettings, onChange: (warnings: WarningSettings) => void, onCancel: () => void) {\n\t\tsuper();\n\n\t\tthis.state = { ...warnings };\n\n\t\tconst items: SettingItem[] = [\n\t\t\t{\n\t\t\t\tid: \"anthropic-extra-usage\",\n\t\t\t\tlabel: \"Anthropic extra usage\",\n\t\t\t\tdescription: \"Warn when Anthropic subscription auth may use paid extra usage\",\n\t\t\t\tcurrentValue: (this.state.anthropicExtraUsage ?? true) ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t];\n\n\t\tthis.settingsList = new SettingsList(\n\t\t\titems,\n\t\t\tMath.min(items.length, 10),\n\t\t\tgetSettingsListTheme(),\n\t\t\t(id, newValue) => {\n\t\t\t\tswitch (id) {\n\t\t\t\t\tcase \"anthropic-extra-usage\":\n\t\t\t\t\t\tthis.state = { ...this.state, anthropicExtraUsage: newValue === \"true\" };\n\t\t\t\t\t\tonChange({ ...this.state });\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tonCancel,\n\t\t);\n\n\t\tthis.addChild(this.settingsList);\n\t}\n\n\thandleInput(data: string): void {\n\t\tthis.settingsList.handleInput(data);\n\t}\n}\n\nclass MemorySettingsSubmenu extends Container {\n\tprivate settingsList: SettingsList;\n\tprivate state: Required<Pick<MemorySettings, \"enabled\" | \"inject\" | \"store\">>;\n\n\tconstructor(\n\t\tmemory: Required<Pick<MemorySettings, \"enabled\" | \"inject\" | \"store\">>,\n\t\tonChange: (memory: MemorySettings) => void,\n\t\tonCancel: () => void,\n\t) {\n\t\tsuper();\n\t\tthis.state = { ...memory };\n\t\tconst items: SettingItem[] = [\n\t\t\t{\n\t\t\t\tid: \"memory-enabled\",\n\t\t\t\tlabel: \"Memory\",\n\t\t\t\tdescription: \"Capture local Threadwell memory events (restart required)\",\n\t\t\t\tcurrentValue: this.state.enabled ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"memory-inject\",\n\t\t\t\tlabel: \"Memory injection\",\n\t\t\t\tdescription: \"Inject bounded relevant memory before model calls (restart required)\",\n\t\t\t\tcurrentValue: this.state.inject ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"memory-store\",\n\t\t\t\tlabel: \"Memory store\",\n\t\t\t\tdescription: \"Local storage backend; sqlite is durable and project-local (restart required)\",\n\t\t\t\tcurrentValue: this.state.store,\n\t\t\t\tvalues: [\"sqlite\", \"memory\", \"noop\"],\n\t\t\t},\n\t\t];\n\n\t\tthis.settingsList = new SettingsList(\n\t\t\titems,\n\t\t\titems.length,\n\t\t\tgetSettingsListTheme(),\n\t\t\t(id, newValue) => {\n\t\t\t\tswitch (id) {\n\t\t\t\t\tcase \"memory-enabled\":\n\t\t\t\t\t\tthis.state = { ...this.state, enabled: newValue === \"true\" };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"memory-inject\":\n\t\t\t\t\t\tthis.state = { ...this.state, inject: newValue === \"true\" };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"memory-store\":\n\t\t\t\t\t\tthis.state = { ...this.state, store: newValue as \"sqlite\" | \"memory\" | \"noop\" };\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tonChange({ ...this.state });\n\t\t\t},\n\t\t\tonCancel,\n\t\t);\n\t\tthis.addChild(this.settingsList);\n\t}\n\n\thandleInput(data: string): void {\n\t\tthis.settingsList.handleInput(data);\n\t}\n}\n\nclass SelectSubmenu extends Container {\n\tprivate selectList: SelectList;\n\n\tconstructor(\n\t\ttitle: string,\n\t\tdescription: string,\n\t\toptions: SelectItem[],\n\t\tcurrentValue: string,\n\t\tonSelect: (value: string) => void,\n\t\tonCancel: () => void,\n\t\tonSelectionChange?: (value: string) => void,\n\t) {\n\t\tsuper();\n\n\t\t// Title\n\t\tthis.addChild(new Text(theme.bold(theme.fg(\"accent\", title)), 0, 0));\n\n\t\t// Description\n\t\tif (description) {\n\t\t\tthis.addChild(new Spacer(1));\n\t\t\tthis.addChild(new Text(theme.fg(\"muted\", description), 0, 0));\n\t\t}\n\n\t\t// Spacer\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Select list\n\t\tthis.selectList = new SelectList(\n\t\t\toptions,\n\t\t\tMath.min(options.length, 10),\n\t\t\tgetSelectListTheme(),\n\t\t\tSETTINGS_SUBMENU_SELECT_LIST_LAYOUT,\n\t\t);\n\n\t\t// Pre-select current value\n\t\tconst currentIndex = options.findIndex((o) => o.value === currentValue);\n\t\tif (currentIndex !== -1) {\n\t\t\tthis.selectList.setSelectedIndex(currentIndex);\n\t\t}\n\n\t\tthis.selectList.onSelect = (item) => {\n\t\t\tonSelect(item.value);\n\t\t};\n\n\t\tthis.selectList.onCancel = onCancel;\n\n\t\tif (onSelectionChange) {\n\t\t\tthis.selectList.onSelectionChange = (item) => {\n\t\t\t\tonSelectionChange(item.value);\n\t\t\t};\n\t\t}\n\n\t\tthis.addChild(this.selectList);\n\n\t\t// Hint\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.fg(\"dim\", \" Enter to select · Esc to go back\"), 0, 0));\n\t}\n\n\thandleInput(data: string): void {\n\t\tthis.selectList.handleInput(data);\n\t}\n}\n\n/**\n * Main settings selector component.\n */\nexport class SettingsSelectorComponent extends Container {\n\tprivate settingsList: SettingsList;\n\n\tconstructor(config: SettingsConfig, callbacks: SettingsCallbacks) {\n\t\tsuper();\n\n\t\tconst supportsImages = getCapabilities().images;\n\t\tlet currentWarnings = { ...config.warnings };\n\t\tlet currentInterface = { ...config.interface };\n\n\t\tconst items: SettingItem[] = [\n\t\t\t{\n\t\t\t\tid: \"interface\",\n\t\t\t\tlabel: \"Interface\",\n\t\t\t\tdescription: \"Visual startup and interface preferences\",\n\t\t\t\tcurrentValue: \"configure\",\n\t\t\t\tsubmenu: (_currentValue, done) =>\n\t\t\t\t\tnew InterfaceSettingsSubmenu(\n\t\t\t\t\t\tcurrentInterface,\n\t\t\t\t\t\t(settings) => {\n\t\t\t\t\t\t\tcurrentInterface = { ...currentInterface, ...settings };\n\t\t\t\t\t\t\tcallbacks.onInterfaceChange(settings);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => done(),\n\t\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"memory\",\n\t\t\t\tlabel: \"Threadwell memory\",\n\t\t\t\tdescription: \"Local SQLite memory capture and bounded injection (restart required)\",\n\t\t\t\tcurrentValue: config.memory.enabled ? \"enabled\" : \"disabled\",\n\t\t\t\tsubmenu: (_currentValue, done) =>\n\t\t\t\t\tnew MemorySettingsSubmenu(\n\t\t\t\t\t\tconfig.memory,\n\t\t\t\t\t\t(memory) => {\n\t\t\t\t\t\t\tcallbacks.onMemoryChange(memory);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => done(),\n\t\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"autocompact\",\n\t\t\t\tlabel: \"Auto-compact\",\n\t\t\t\tdescription: \"Automatically compact context when it gets too large\",\n\t\t\t\tcurrentValue: config.autoCompact ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"steering-mode\",\n\t\t\t\tlabel: \"Steering mode\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Enter while streaming queues steering messages. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.\",\n\t\t\t\tcurrentValue: config.steeringMode,\n\t\t\t\tvalues: [\"one-at-a-time\", \"all\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"follow-up-mode\",\n\t\t\t\tlabel: \"Follow-up mode\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Alt+Enter queues follow-up messages until agent stops. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.\",\n\t\t\t\tcurrentValue: config.followUpMode,\n\t\t\t\tvalues: [\"one-at-a-time\", \"all\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"transport\",\n\t\t\t\tlabel: \"Transport\",\n\t\t\t\tdescription: \"Preferred transport for providers that support multiple transports\",\n\t\t\t\tcurrentValue: config.transport,\n\t\t\t\tvalues: [\"sse\", \"websocket\", \"websocket-cached\", \"auto\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"hide-thinking\",\n\t\t\t\tlabel: \"Hide thinking\",\n\t\t\t\tdescription: \"Hide thinking blocks in assistant responses\",\n\t\t\t\tcurrentValue: config.hideThinkingBlock ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"collapse-changelog\",\n\t\t\t\tlabel: \"Collapse changelog\",\n\t\t\t\tdescription: \"Show condensed changelog after updates\",\n\t\t\t\tcurrentValue: config.collapseChangelog ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"quiet-startup\",\n\t\t\t\tlabel: \"Quiet startup\",\n\t\t\t\tdescription: \"Disable verbose printing at startup\",\n\t\t\t\tcurrentValue: config.quietStartup ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"install-telemetry\",\n\t\t\t\tlabel: \"Install telemetry\",\n\t\t\t\tdescription: \"Send an anonymous version/update ping after changelog-detected updates\",\n\t\t\t\tcurrentValue: config.enableInstallTelemetry ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"double-escape-action\",\n\t\t\t\tlabel: \"Double-escape action\",\n\t\t\t\tdescription: \"Action when pressing Escape twice with empty editor\",\n\t\t\t\tcurrentValue: config.doubleEscapeAction,\n\t\t\t\tvalues: [\"tree\", \"fork\", \"none\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"tree-filter-mode\",\n\t\t\t\tlabel: \"Tree filter mode\",\n\t\t\t\tdescription: \"Default filter when opening /tree\",\n\t\t\t\tcurrentValue: config.treeFilterMode,\n\t\t\t\tvalues: [\"default\", \"no-tools\", \"user-only\", \"labeled-only\", \"all\"],\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"warnings\",\n\t\t\t\tlabel: \"Warnings\",\n\t\t\t\tdescription: \"Enable or disable individual warnings\",\n\t\t\t\tcurrentValue: \"configure\",\n\t\t\t\tsubmenu: (_currentValue, done) =>\n\t\t\t\t\tnew WarningSettingsSubmenu(\n\t\t\t\t\t\tcurrentWarnings,\n\t\t\t\t\t\t(warnings) => {\n\t\t\t\t\t\t\tcurrentWarnings = warnings;\n\t\t\t\t\t\t\tcallbacks.onWarningsChange(warnings);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => done(),\n\t\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"thinking\",\n\t\t\t\tlabel: \"Thinking level\",\n\t\t\t\tdescription: \"Reasoning depth for thinking-capable models\",\n\t\t\t\tcurrentValue: config.thinkingLevel,\n\t\t\t\tsubmenu: (currentValue, done) =>\n\t\t\t\t\tnew SelectSubmenu(\n\t\t\t\t\t\t\"Thinking Level\",\n\t\t\t\t\t\t\"Select reasoning depth for thinking-capable models\",\n\t\t\t\t\t\tconfig.availableThinkingLevels.map((level) => ({\n\t\t\t\t\t\t\tvalue: level,\n\t\t\t\t\t\t\tlabel: level,\n\t\t\t\t\t\t\tdescription: THINKING_DESCRIPTIONS[level],\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tcurrentValue,\n\t\t\t\t\t\t(value) => {\n\t\t\t\t\t\t\tcallbacks.onThinkingLevelChange(value as ThinkingLevel);\n\t\t\t\t\t\t\tdone(value);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => done(),\n\t\t\t\t\t),\n\t\t\t},\n\t\t];\n\n\t\t// Only show image toggle if terminal supports it\n\t\tif (supportsImages) {\n\t\t\t// Insert after autocompact\n\t\t\titems.splice(1, 0, {\n\t\t\t\tid: \"show-images\",\n\t\t\t\tlabel: \"Show images\",\n\t\t\t\tdescription: \"Render images inline in terminal\",\n\t\t\t\tcurrentValue: config.showImages ? \"true\" : \"false\",\n\t\t\t\tvalues: [\"true\", \"false\"],\n\t\t\t});\n\t\t\titems.splice(2, 0, {\n\t\t\t\tid: \"image-width-cells\",\n\t\t\t\tlabel: \"Image width\",\n\t\t\t\tdescription: \"Preferred inline image width in terminal cells\",\n\t\t\t\tcurrentValue: String(config.imageWidthCells),\n\t\t\t\tvalues: [\"60\", \"80\", \"120\"],\n\t\t\t});\n\t\t}\n\n\t\t// Image auto-resize toggle (always available, affects both attached and read images)\n\t\titems.splice(supportsImages ? 3 : 1, 0, {\n\t\t\tid: \"auto-resize-images\",\n\t\t\tlabel: \"Auto-resize images\",\n\t\t\tdescription: \"Resize large images to 2000x2000 max for better model compatibility\",\n\t\t\tcurrentValue: config.autoResizeImages ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Block images toggle (always available, insert after auto-resize-images)\n\t\tconst autoResizeIndex = items.findIndex((item) => item.id === \"auto-resize-images\");\n\t\titems.splice(autoResizeIndex + 1, 0, {\n\t\t\tid: \"block-images\",\n\t\t\tlabel: \"Block images\",\n\t\t\tdescription: \"Prevent images from being sent to LLM providers\",\n\t\t\tcurrentValue: config.blockImages ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Skills toggle (insert after block-images)\n\t\tconst blockImagesIndex = items.findIndex((item) => item.id === \"block-images\");\n\t\titems.splice(blockImagesIndex + 1, 0, {\n\t\t\tid: \"skills-enabled\",\n\t\t\tlabel: \"Skills\",\n\t\t\tdescription: \"Load and inject installed skills\",\n\t\t\tcurrentValue: config.skillsEnabled ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Skill commands toggle (insert after skills)\n\t\tconst skillsEnabledIndex = items.findIndex((item) => item.id === \"skills-enabled\");\n\t\titems.splice(skillsEnabledIndex + 1, 0, {\n\t\t\tid: \"skill-commands\",\n\t\t\tlabel: \"Skill commands\",\n\t\t\tdescription: \"Register loaded skills as /skill:name commands\",\n\t\t\tcurrentValue: config.enableSkillCommands ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Hardware cursor toggle (insert after skill-commands)\n\t\tconst skillCommandsIndex = items.findIndex((item) => item.id === \"skill-commands\");\n\t\titems.splice(skillCommandsIndex + 1, 0, {\n\t\t\tid: \"show-hardware-cursor\",\n\t\t\tlabel: \"Show hardware cursor\",\n\t\t\tdescription: \"Show the terminal cursor while still positioning it for IME support\",\n\t\t\tcurrentValue: config.showHardwareCursor ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Editor padding toggle (insert after show-hardware-cursor)\n\t\tconst hardwareCursorIndex = items.findIndex((item) => item.id === \"show-hardware-cursor\");\n\t\titems.splice(hardwareCursorIndex + 1, 0, {\n\t\t\tid: \"editor-padding\",\n\t\t\tlabel: \"Editor padding\",\n\t\t\tdescription: \"Horizontal padding for input editor (0-3)\",\n\t\t\tcurrentValue: String(config.editorPaddingX),\n\t\t\tvalues: [\"0\", \"1\", \"2\", \"3\"],\n\t\t});\n\n\t\t// Autocomplete max visible toggle (insert after editor-padding)\n\t\tconst editorPaddingIndex = items.findIndex((item) => item.id === \"editor-padding\");\n\t\titems.splice(editorPaddingIndex + 1, 0, {\n\t\t\tid: \"autocomplete-max-visible\",\n\t\t\tlabel: \"Autocomplete max items\",\n\t\t\tdescription: \"Max visible items in autocomplete dropdown (3-20)\",\n\t\t\tcurrentValue: String(config.autocompleteMaxVisible),\n\t\t\tvalues: [\"3\", \"5\", \"7\", \"10\", \"15\", \"20\"],\n\t\t});\n\n\t\t// Clear on shrink toggle (insert after autocomplete-max-visible)\n\t\tconst autocompleteIndex = items.findIndex((item) => item.id === \"autocomplete-max-visible\");\n\t\titems.splice(autocompleteIndex + 1, 0, {\n\t\t\tid: \"clear-on-shrink\",\n\t\t\tlabel: \"Clear on shrink\",\n\t\t\tdescription: \"Clear empty rows when content shrinks (may cause flicker)\",\n\t\t\tcurrentValue: config.clearOnShrink ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Terminal progress toggle (insert after clear-on-shrink)\n\t\tconst clearOnShrinkIndex = items.findIndex((item) => item.id === \"clear-on-shrink\");\n\t\titems.splice(clearOnShrinkIndex + 1, 0, {\n\t\t\tid: \"terminal-progress\",\n\t\t\tlabel: \"Terminal progress\",\n\t\t\tdescription: \"Show OSC 9;4 progress indicators in the terminal tab bar\",\n\t\t\tcurrentValue: config.showTerminalProgress ? \"true\" : \"false\",\n\t\t\tvalues: [\"true\", \"false\"],\n\t\t});\n\n\t\t// Add borders\n\t\tthis.addChild(new DynamicBorder());\n\n\t\tthis.settingsList = new SettingsList(\n\t\t\titems,\n\t\t\t10,\n\t\t\tgetSettingsListTheme(),\n\t\t\t(id, newValue) => {\n\t\t\t\tswitch (id) {\n\t\t\t\t\tcase \"autocompact\":\n\t\t\t\t\t\tcallbacks.onAutoCompactChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-images\":\n\t\t\t\t\t\tcallbacks.onShowImagesChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"image-width-cells\":\n\t\t\t\t\t\tcallbacks.onImageWidthCellsChange(parseInt(newValue, 10));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"auto-resize-images\":\n\t\t\t\t\t\tcallbacks.onAutoResizeImagesChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"block-images\":\n\t\t\t\t\t\tcallbacks.onBlockImagesChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"skills-enabled\":\n\t\t\t\t\t\tcallbacks.onSkillsEnabledChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"skill-commands\":\n\t\t\t\t\t\tcallbacks.onEnableSkillCommandsChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"steering-mode\":\n\t\t\t\t\t\tcallbacks.onSteeringModeChange(newValue as \"all\" | \"one-at-a-time\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"follow-up-mode\":\n\t\t\t\t\t\tcallbacks.onFollowUpModeChange(newValue as \"all\" | \"one-at-a-time\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"transport\":\n\t\t\t\t\t\tcallbacks.onTransportChange(newValue as Transport);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"hide-thinking\":\n\t\t\t\t\t\tcallbacks.onHideThinkingBlockChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"collapse-changelog\":\n\t\t\t\t\t\tcallbacks.onCollapseChangelogChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"quiet-startup\":\n\t\t\t\t\t\tcallbacks.onQuietStartupChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"install-telemetry\":\n\t\t\t\t\t\tcallbacks.onEnableInstallTelemetryChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"double-escape-action\":\n\t\t\t\t\t\tcallbacks.onDoubleEscapeActionChange(newValue as \"fork\" | \"tree\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"tree-filter-mode\":\n\t\t\t\t\t\tcallbacks.onTreeFilterModeChange(\n\t\t\t\t\t\t\tnewValue as \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"show-hardware-cursor\":\n\t\t\t\t\t\tcallbacks.onShowHardwareCursorChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"editor-padding\":\n\t\t\t\t\t\tcallbacks.onEditorPaddingXChange(parseInt(newValue, 10));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"autocomplete-max-visible\":\n\t\t\t\t\t\tcallbacks.onAutocompleteMaxVisibleChange(parseInt(newValue, 10));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"clear-on-shrink\":\n\t\t\t\t\t\tcallbacks.onClearOnShrinkChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"terminal-progress\":\n\t\t\t\t\t\tcallbacks.onShowTerminalProgressChange(newValue === \"true\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tcallbacks.onCancel,\n\t\t\t{ enableSearch: true },\n\t\t);\n\n\t\tthis.addChild(this.settingsList);\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\tgetSettingsList(): SettingsList {\n\t\treturn this.settingsList;\n\t}\n}\n"]}
|
|
@@ -333,26 +333,6 @@ export class SettingsSelectorComponent extends Container {
|
|
|
333
333
|
done(value);
|
|
334
334
|
}, () => done()),
|
|
335
335
|
},
|
|
336
|
-
{
|
|
337
|
-
id: "theme",
|
|
338
|
-
label: "Theme",
|
|
339
|
-
description: "Color theme for the interface",
|
|
340
|
-
currentValue: config.currentTheme,
|
|
341
|
-
submenu: (currentValue, done) => new SelectSubmenu("Theme", "Select color theme", config.availableThemes.map((t) => ({
|
|
342
|
-
value: t,
|
|
343
|
-
label: t,
|
|
344
|
-
})), currentValue, (value) => {
|
|
345
|
-
callbacks.onThemeChange(value);
|
|
346
|
-
done(value);
|
|
347
|
-
}, () => {
|
|
348
|
-
// Restore original theme on cancel
|
|
349
|
-
callbacks.onThemePreview?.(currentValue);
|
|
350
|
-
done();
|
|
351
|
-
}, (value) => {
|
|
352
|
-
// Preview theme on selection change
|
|
353
|
-
callbacks.onThemePreview?.(value);
|
|
354
|
-
}),
|
|
355
|
-
},
|
|
356
336
|
];
|
|
357
337
|
// Only show image toggle if terminal supports it
|
|
358
338
|
if (supportsImages) {
|