@xopcai/xopc 0.0.27 → 0.0.29
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/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/adapters/onboard-cli.d.ts +7 -0
- package/dist/extensions/weixin/src/adapters/onboard-cli.js +61 -0
- package/dist/extensions/weixin/src/adapters/onboard-cli.js.map +1 -0
- package/dist/extensions/weixin/src/cli/qr-login.d.ts +5 -0
- package/dist/extensions/weixin/src/cli/qr-login.js +1 -1
- package/dist/extensions/weixin/src/cli/qr-login.js.map +1 -1
- package/dist/extensions/weixin/src/index.js +1 -1
- package/dist/extensions/weixin/src/plugin.d.ts +1 -0
- package/dist/extensions/weixin/src/plugin.js +2 -0
- package/dist/extensions/weixin/src/plugin.js.map +1 -1
- package/dist/gateway/static/root/assets/agents-CkgFSiCY.js +216 -0
- package/dist/gateway/static/root/assets/agents-CkgFSiCY.js.map +1 -0
- package/dist/gateway/static/root/assets/{apps-page-CBBh_Ww8.js → apps-page-Bmq19MS-.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-CBBh_Ww8.js.map → apps-page-Bmq19MS-.js.map} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-CE7jrdkO.js +9 -0
- package/dist/gateway/static/root/assets/channels-settings-CE7jrdkO.js.map +1 -0
- package/dist/gateway/static/root/assets/cron-page-BpPPcykJ.js +2 -0
- package/dist/gateway/static/root/assets/cron-page-BpPPcykJ.js.map +1 -0
- package/dist/gateway/static/root/assets/{cron-utils-08gdQfl9.js → cron-utils-N1PqD2DB.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-utils-08gdQfl9.js.map → cron-utils-N1PqD2DB.js.map} +1 -1
- package/dist/gateway/static/root/assets/{dist-C1MrygQH.js → dist--p2HQ2QF.js} +2 -2
- package/dist/gateway/static/root/assets/{dist-C1MrygQH.js.map → dist--p2HQ2QF.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DN3HKUGS.js → extension-debug-page-DwHCB_6T.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-DN3HKUGS.js.map → extension-debug-page-DwHCB_6T.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CoFDHZtZ.js → extension-page-BsYwQIex.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-CoFDHZtZ.js.map → extension-page-BsYwQIex.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BcPCu_Go.js → extension-settings-page-nsisEgjB.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-BcPCu_Go.js.map → extension-settings-page-nsisEgjB.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-CR8zUHGR.js +4734 -0
- package/dist/gateway/static/root/assets/{index-PfkB8N37.js.map → index-CR8zUHGR.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-Dnfha4O2.css +1 -0
- package/dist/gateway/static/root/assets/logs-page-CQwdV_Xw.js +2 -0
- package/dist/gateway/static/root/assets/logs-page-CQwdV_Xw.js.map +1 -0
- package/dist/gateway/static/root/assets/sessions-page-Be5kIGl_.js +2 -0
- package/dist/gateway/static/root/assets/sessions-page-Be5kIGl_.js.map +1 -0
- package/dist/gateway/static/root/assets/settings-page-PodSlNwr.js +2 -0
- package/dist/gateway/static/root/assets/settings-page-PodSlNwr.js.map +1 -0
- package/dist/gateway/static/root/assets/skills-page-Clg8deH0.js +3 -0
- package/dist/gateway/static/root/assets/{skills-page-BmBDCEbY.js.map → skills-page-Clg8deH0.js.map} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/src/agent/lifecycle/hook-handler.d.ts +2 -0
- package/dist/src/agent/lifecycle/hook-handler.js +24 -0
- package/dist/src/agent/lifecycle/hook-handler.js.map +1 -1
- package/dist/src/agent/messaging/command-handler.js +10 -2
- package/dist/src/agent/messaging/command-handler.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.js +77 -20
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.d.ts +15 -0
- package/dist/src/agent/service.js +21 -1
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/channels/weixin/index.js +1 -1
- package/dist/src/cli/agent-chat-log-level-preset.d.ts +8 -0
- package/dist/src/cli/agent-chat-log-level-preset.js +25 -0
- package/dist/src/cli/agent-chat-log-level-preset.js.map +1 -0
- package/dist/src/cli/commands/agent/interactive.js +4 -2
- package/dist/src/cli/commands/agent/interactive.js.map +1 -1
- package/dist/src/cli/commands/agent/stream-renderer.d.ts +14 -0
- package/dist/src/cli/commands/agent/stream-renderer.js +99 -0
- package/dist/src/cli/commands/agent/stream-renderer.js.map +1 -0
- package/dist/src/cli/commands/agent.js +2 -2
- package/dist/src/cli/commands/agent.js.map +1 -1
- package/dist/src/cli/commands/onboard.js +77 -93
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/tui.d.ts +1 -0
- package/dist/src/cli/commands/tui.js +40 -0
- package/dist/src/cli/commands/tui.js.map +1 -0
- package/dist/src/cli/index.d.ts +2 -0
- package/dist/src/cli/index.js +7 -3
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/config/schema.d.ts +6 -0
- package/dist/src/config/schema.js +11 -3
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/extensions/hooks.js +5 -1
- package/dist/src/extensions/hooks.js.map +1 -1
- package/dist/src/extensions/loader.d.ts +1 -0
- package/dist/src/extensions/loader.js +3 -1
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/sdk/index.d.ts +1 -1
- package/dist/src/extensions/sdk/index.js.map +1 -1
- package/dist/src/extensions/types/core.d.ts +8 -0
- package/dist/src/extensions/types/hooks.d.ts +16 -1
- package/dist/src/extensions/types/hooks.js +1 -0
- package/dist/src/extensions/types/hooks.js.map +1 -1
- package/dist/src/gateway/agents-admin.d.ts +19 -1
- package/dist/src/gateway/agents-admin.js +164 -3
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/auth.d.ts +17 -3
- package/dist/src/gateway/auth.js +35 -16
- package/dist/src/gateway/auth.js.map +1 -1
- package/dist/src/gateway/hono/app.js +31 -1
- package/dist/src/gateway/hono/app.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -1
- package/dist/src/gateway/hono/middleware/auth.js +4 -3
- package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
- package/dist/src/gateway/hono/middleware/scopes.d.ts +15 -0
- package/dist/src/gateway/hono/middleware/scopes.js +41 -0
- package/dist/src/gateway/hono/middleware/scopes.js.map +1 -0
- package/dist/src/gateway/hono/routes/agents.js +59 -5
- package/dist/src/gateway/hono/routes/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/config.js +2 -2
- package/dist/src/gateway/hono/routes/config.js.map +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +1 -0
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +17 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/security/audit.d.ts +18 -0
- package/dist/src/gateway/security/audit.js +68 -0
- package/dist/src/gateway/security/audit.js.map +1 -0
- package/dist/src/gateway/security/csp.d.ts +19 -0
- package/dist/src/gateway/security/csp.js +52 -0
- package/dist/src/gateway/security/csp.js.map +1 -0
- package/dist/src/gateway/security/dangerous-tools.d.ts +20 -0
- package/dist/src/gateway/security/dangerous-tools.js +46 -0
- package/dist/src/gateway/security/dangerous-tools.js.map +1 -0
- package/dist/src/gateway/security/flood-guard.d.ts +28 -0
- package/dist/src/gateway/security/flood-guard.js +42 -0
- package/dist/src/gateway/security/flood-guard.js.map +1 -0
- package/dist/src/gateway/security/index.d.ts +9 -0
- package/dist/src/gateway/security/index.js +10 -0
- package/dist/src/gateway/security/known-weak-secrets.d.ts +10 -0
- package/dist/src/gateway/security/known-weak-secrets.js +36 -0
- package/dist/src/gateway/security/known-weak-secrets.js.map +1 -0
- package/dist/src/gateway/security/operator-scopes.d.ts +37 -0
- package/dist/src/gateway/security/operator-scopes.js +137 -0
- package/dist/src/gateway/security/operator-scopes.js.map +1 -0
- package/dist/src/gateway/security/origin-check.d.ts +21 -0
- package/dist/src/gateway/security/origin-check.js +56 -0
- package/dist/src/gateway/security/origin-check.js.map +1 -0
- package/dist/src/gateway/security/preauth-connection-budget.d.ts +17 -0
- package/dist/src/gateway/security/preauth-connection-budget.js +49 -0
- package/dist/src/gateway/security/preauth-connection-budget.js.map +1 -0
- package/dist/src/gateway/security/secret-equal.d.ts +8 -0
- package/dist/src/gateway/security/secret-equal.js +30 -0
- package/dist/src/gateway/security/secret-equal.js.map +1 -0
- package/dist/src/gateway/service.d.ts +3 -1
- package/dist/src/gateway/service.js +40 -4
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/session/client-history.d.ts +21 -0
- package/dist/src/session/client-history.js +89 -0
- package/dist/src/session/client-history.js.map +1 -0
- package/dist/src/session/index.d.ts +1 -0
- package/dist/src/session/index.js +2 -1
- package/dist/src/session/manager.d.ts +2 -0
- package/dist/src/session/manager.js +5 -0
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/thinking-resolve.js +1 -1
- package/dist/src/session/thinking-resolve.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +42 -0
- package/dist/src/tui/backends/embedded-backend.js +173 -0
- package/dist/src/tui/backends/embedded-backend.js.map +1 -0
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +53 -0
- package/dist/src/tui/backends/gateway-sse-backend.js +256 -0
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -0
- package/dist/src/tui/chat-history.d.ts +4 -0
- package/dist/src/tui/chat-history.js +29 -0
- package/dist/src/tui/chat-history.js.map +1 -0
- package/dist/src/tui/components/assistant-message.d.ts +6 -0
- package/dist/src/tui/components/assistant-message.js +19 -0
- package/dist/src/tui/components/assistant-message.js.map +1 -0
- package/dist/src/tui/components/chat-log.d.ts +21 -0
- package/dist/src/tui/components/chat-log.js +113 -0
- package/dist/src/tui/components/chat-log.js.map +1 -0
- package/dist/src/tui/components/custom-editor.d.ts +14 -0
- package/dist/src/tui/components/custom-editor.js +50 -0
- package/dist/src/tui/components/custom-editor.js.map +1 -0
- package/dist/src/tui/components/fuzzy-filter.d.ts +17 -0
- package/dist/src/tui/components/fuzzy-filter.js +85 -0
- package/dist/src/tui/components/fuzzy-filter.js.map +1 -0
- package/dist/src/tui/components/searchable-select-list.d.ts +39 -0
- package/dist/src/tui/components/searchable-select-list.js +257 -0
- package/dist/src/tui/components/searchable-select-list.js.map +1 -0
- package/dist/src/tui/components/tool-execution.d.ts +16 -0
- package/dist/src/tui/components/tool-execution.js +76 -0
- package/dist/src/tui/components/tool-execution.js.map +1 -0
- package/dist/src/tui/components/user-message.d.ts +6 -0
- package/dist/src/tui/components/user-message.js +22 -0
- package/dist/src/tui/components/user-message.js.map +1 -0
- package/dist/src/tui/sse-consumer.d.ts +15 -0
- package/dist/src/tui/sse-consumer.js +75 -0
- package/dist/src/tui/sse-consumer.js.map +1 -0
- package/dist/src/tui/stream-assembler.d.ts +22 -0
- package/dist/src/tui/stream-assembler.js +63 -0
- package/dist/src/tui/stream-assembler.js.map +1 -0
- package/dist/src/tui/theme.d.ts +73 -0
- package/dist/src/tui/theme.js +157 -0
- package/dist/src/tui/theme.js.map +1 -0
- package/dist/src/tui/tui-agent-events.d.ts +7 -0
- package/dist/src/tui/tui-agent-events.js +103 -0
- package/dist/src/tui/tui-agent-events.js.map +1 -0
- package/dist/src/tui/tui-backend.d.ts +80 -0
- package/dist/src/tui/tui-backend.js +1 -0
- package/dist/src/tui/tui-commands.d.ts +23 -0
- package/dist/src/tui/tui-commands.js +165 -0
- package/dist/src/tui/tui-commands.js.map +1 -0
- package/dist/src/tui/tui-lifecycle.d.ts +26 -0
- package/dist/src/tui/tui-lifecycle.js +57 -0
- package/dist/src/tui/tui-lifecycle.js.map +1 -0
- package/dist/src/tui/tui-local-shell.d.ts +28 -0
- package/dist/src/tui/tui-local-shell.js +147 -0
- package/dist/src/tui/tui-local-shell.js.map +1 -0
- package/dist/src/tui/tui-overlays.d.ts +8 -0
- package/dist/src/tui/tui-overlays.js +22 -0
- package/dist/src/tui/tui-overlays.js.map +1 -0
- package/dist/src/tui/tui-picker-overlay.d.ts +26 -0
- package/dist/src/tui/tui-picker-overlay.js +69 -0
- package/dist/src/tui/tui-picker-overlay.js.map +1 -0
- package/dist/src/tui/tui-stdio-filter.d.ts +17 -0
- package/dist/src/tui/tui-stdio-filter.js +96 -0
- package/dist/src/tui/tui-stdio-filter.js.map +1 -0
- package/dist/src/tui/tui-submit.d.ts +25 -0
- package/dist/src/tui/tui-submit.js +102 -0
- package/dist/src/tui/tui-submit.js.map +1 -0
- package/dist/src/tui/tui-suspend.d.ts +10 -0
- package/dist/src/tui/tui-suspend.js +18 -0
- package/dist/src/tui/tui-suspend.js.map +1 -0
- package/dist/src/tui/tui-types.d.ts +86 -0
- package/dist/src/tui/tui-types.js +21 -0
- package/dist/src/tui/tui-types.js.map +1 -0
- package/dist/src/tui/tui.d.ts +5 -0
- package/dist/src/tui/tui.js +389 -0
- package/dist/src/tui/tui.js.map +1 -0
- package/package.json +5 -3
- package/dist/gateway/static/root/assets/agents-w8_jzuiX.js +0 -216
- package/dist/gateway/static/root/assets/agents-w8_jzuiX.js.map +0 -1
- package/dist/gateway/static/root/assets/channels-settings-DUKRPC7C.js +0 -9
- package/dist/gateway/static/root/assets/channels-settings-DUKRPC7C.js.map +0 -1
- package/dist/gateway/static/root/assets/cron-page-S18t1yG-.js +0 -2
- package/dist/gateway/static/root/assets/cron-page-S18t1yG-.js.map +0 -1
- package/dist/gateway/static/root/assets/index-OT4cGzon.css +0 -1
- package/dist/gateway/static/root/assets/index-PfkB8N37.js +0 -4734
- package/dist/gateway/static/root/assets/logs-page-DoWe1GWy.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-DoWe1GWy.js.map +0 -1
- package/dist/gateway/static/root/assets/sessions-page-2uOYwEwd.js +0 -2
- package/dist/gateway/static/root/assets/sessions-page-2uOYwEwd.js.map +0 -1
- package/dist/gateway/static/root/assets/settings-page-fQWswCuq.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-fQWswCuq.js.map +0 -1
- package/dist/gateway/static/root/assets/skills-page-BmBDCEbY.js +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchable-select-list.js","names":[],"sources":["../../../../src/tui/components/searchable-select-list.ts"],"sourcesContent":["import {\n Input,\n isKeyRelease,\n matchesKey,\n type Component,\n type SelectItem,\n type SelectListTheme,\n truncateToWidth,\n visibleWidth,\n} from '@mariozechner/pi-tui';\n\nimport {\n findWordBoundaryIndex,\n fuzzyFilterLower,\n normalizeLowercaseStringOrEmpty,\n} from './fuzzy-filter.js';\n\nconst ANSI_ESCAPE = String.fromCharCode(27);\nconst ANSI_SGR_REGEX = new RegExp(`${ANSI_ESCAPE}\\\\[[0-9;]*m`, 'g');\n\nexport interface SearchableSelectListTheme extends SelectListTheme {\n searchPrompt: (text: string) => string;\n searchInput: (text: string) => string;\n matchHighlight: (text: string) => string;\n}\n\nfunction stripAnsi(raw: string): string {\n return raw.replace(/\\x1b\\[[0-9;]*m/g, '');\n}\n\nexport class SearchableSelectList implements Component {\n private items: SelectItem[];\n private filteredItems: SelectItem[];\n private selectedIndex = 0;\n private maxVisible: number;\n private theme: SearchableSelectListTheme;\n private searchInput: Input;\n private regexCache = new Map<string, RegExp>();\n\n onSelect?: (item: SelectItem) => void;\n onCancel?: () => void;\n onSelectionChange?: (item: SelectItem) => void;\n\n private static readonly DESCRIPTION_LAYOUT_MIN_WIDTH = 40;\n private static readonly DESCRIPTION_MIN_WIDTH = 12;\n private static readonly DESCRIPTION_SPACING_WIDTH = 2;\n private static readonly RIGHT_MARGIN_WIDTH = 2;\n\n constructor(items: SelectItem[], maxVisible: number, theme: SearchableSelectListTheme) {\n this.items = items;\n this.filteredItems = items;\n this.maxVisible = maxVisible;\n this.theme = theme;\n this.searchInput = new Input();\n }\n\n private getCachedRegex(pattern: string): RegExp {\n let regex = this.regexCache.get(pattern);\n if (!regex) {\n regex = new RegExp(this.escapeRegex(pattern), 'gi');\n this.regexCache.set(pattern, regex);\n }\n return regex;\n }\n\n private updateFilter() {\n const query = this.searchInput.getValue().trim();\n\n if (!query) {\n this.filteredItems = this.items;\n } else {\n this.filteredItems = this.smartFilter(query);\n }\n\n this.selectedIndex = 0;\n this.notifySelectionChange();\n }\n\n private smartFilter(query: string): SelectItem[] {\n const q = normalizeLowercaseStringOrEmpty(query);\n type ScoredItem = { item: SelectItem; tier: number; score: number };\n type FuzzyCandidate = { item: SelectItem; searchTextLower: string };\n const scoredItems: ScoredItem[] = [];\n const fuzzyCandidates: FuzzyCandidate[] = [];\n\n for (const item of this.items) {\n const rawLabel = this.getItemLabel(item);\n const rawDesc = item.description ?? '';\n const label = normalizeLowercaseStringOrEmpty(stripAnsi(rawLabel));\n const desc = normalizeLowercaseStringOrEmpty(stripAnsi(rawDesc));\n\n const labelIndex = label.indexOf(q);\n if (labelIndex !== -1) {\n scoredItems.push({ item, tier: 0, score: labelIndex });\n continue;\n }\n const wordBoundaryIndex = findWordBoundaryIndex(label, q);\n if (wordBoundaryIndex !== null) {\n scoredItems.push({ item, tier: 1, score: wordBoundaryIndex });\n continue;\n }\n const descIndex = desc.indexOf(q);\n if (descIndex !== -1) {\n scoredItems.push({ item, tier: 2, score: descIndex });\n continue;\n }\n const searchText = (item as { searchText?: string }).searchText ?? '';\n fuzzyCandidates.push({\n item,\n searchTextLower: normalizeLowercaseStringOrEmpty(\n [rawLabel, rawDesc, searchText]\n .map((value) => stripAnsi(value))\n .filter(Boolean)\n .join(' '),\n ),\n });\n }\n\n scoredItems.sort(this.compareByScore);\n const fuzzyMatches = fuzzyFilterLower(fuzzyCandidates, q);\n return [...scoredItems.map((s) => s.item), ...fuzzyMatches.map((entry) => entry.item)];\n }\n\n private escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n\n private compareByScore = (\n a: { item: SelectItem; tier: number; score: number },\n b: { item: SelectItem; tier: number; score: number },\n ) => {\n if (a.tier !== b.tier) {\n return a.tier - b.tier;\n }\n if (a.score !== b.score) {\n return a.score - b.score;\n }\n return this.getItemLabel(a.item).localeCompare(this.getItemLabel(b.item));\n };\n\n private getItemLabel(item: SelectItem): string {\n return item.label || item.value;\n }\n\n private splitAnsiParts(text: string): Array<{ text: string; isAnsi: boolean }> {\n const parts: Array<{ text: string; isAnsi: boolean }> = [];\n ANSI_SGR_REGEX.lastIndex = 0;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = ANSI_SGR_REGEX.exec(text)) !== null) {\n if (match.index > lastIndex) {\n parts.push({ text: text.slice(lastIndex, match.index), isAnsi: false });\n }\n parts.push({ text: match[0], isAnsi: true });\n lastIndex = match.index + match[0].length;\n }\n if (lastIndex < text.length) {\n parts.push({ text: text.slice(lastIndex), isAnsi: false });\n }\n return parts;\n }\n\n private highlightMatch(text: string, query: string): string {\n const tokens = query\n .trim()\n .split(/\\s+/)\n .map((token) => normalizeLowercaseStringOrEmpty(token))\n .filter((token) => token.length > 0);\n if (tokens.length === 0) {\n return text;\n }\n\n const uniqueTokens = Array.from(new Set(tokens)).toSorted((a, b) => b.length - a.length);\n let parts = this.splitAnsiParts(text);\n for (const token of uniqueTokens) {\n const regex = this.getCachedRegex(token);\n const nextParts: Array<{ text: string; isAnsi: boolean }> = [];\n for (const part of parts) {\n if (part.isAnsi) {\n nextParts.push(part);\n continue;\n }\n regex.lastIndex = 0;\n const replaced = part.text.replace(regex, (match) => this.theme.matchHighlight(match));\n if (replaced === part.text) {\n nextParts.push(part);\n continue;\n }\n nextParts.push(...this.splitAnsiParts(replaced));\n }\n parts = nextParts;\n }\n return parts.map((part) => part.text).join('');\n }\n\n setSelectedIndex(index: number) {\n this.selectedIndex = Math.max(0, Math.min(index, this.filteredItems.length - 1));\n }\n\n invalidate() {\n this.searchInput.invalidate();\n }\n\n render(width: number): string[] {\n const lines: string[] = [];\n\n const promptText = 'search: ';\n const prompt = this.theme.searchPrompt(promptText);\n const inputWidth = Math.max(1, width - visibleWidth(prompt));\n const inputLines = this.searchInput.render(inputWidth);\n const inputText = inputLines[0] ?? '';\n lines.push(`${prompt}${this.theme.searchInput(inputText)}`);\n lines.push('');\n\n const query = this.searchInput.getValue().trim();\n\n if (this.filteredItems.length === 0) {\n lines.push(this.theme.noMatch(' No matches'));\n return lines;\n }\n\n const startIndex = Math.max(\n 0,\n Math.min(\n this.selectedIndex - Math.floor(this.maxVisible / 2),\n this.filteredItems.length - this.maxVisible,\n ),\n );\n const endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);\n\n for (let i = startIndex; i < endIndex; i++) {\n const item = this.filteredItems[i];\n if (!item) {\n continue;\n }\n const isSelected = i === this.selectedIndex;\n lines.push(this.renderItemLine(item, isSelected, width, query));\n }\n\n if (this.filteredItems.length > this.maxVisible) {\n const scrollInfo = `${this.selectedIndex + 1}/${this.filteredItems.length}`;\n lines.push(this.theme.scrollInfo(` ${scrollInfo}`));\n }\n\n return lines;\n }\n\n private renderItemLine(\n item: SelectItem,\n isSelected: boolean,\n width: number,\n query: string,\n ): string {\n const prefix = isSelected ? '→ ' : ' ';\n const prefixWidth = prefix.length;\n const displayValue = this.getItemLabel(item);\n\n const description = item.description;\n if (description) {\n const descriptionLayout = this.getDescriptionLayout(width, prefixWidth);\n if (descriptionLayout) {\n const truncatedValue = truncateToWidth(displayValue, descriptionLayout.maxValueWidth, '');\n const valueText = this.highlightMatch(truncatedValue, query);\n\n const usedByValue = visibleWidth(valueText);\n const remainingWidth = descriptionLayout.availableWidth - usedByValue;\n const descriptionWidth = remainingWidth - descriptionLayout.spacingWidth;\n\n if (descriptionWidth >= SearchableSelectList.DESCRIPTION_MIN_WIDTH) {\n const spacing = ' '.repeat(descriptionLayout.spacingWidth);\n const truncatedDesc = truncateToWidth(description, descriptionWidth, '');\n const highlightedDesc = this.highlightMatch(truncatedDesc, query);\n const descText = isSelected ? highlightedDesc : this.theme.description(highlightedDesc);\n const line = `${prefix}${valueText}${spacing}${descText}`;\n return isSelected ? this.theme.selectedText(line) : line;\n }\n }\n }\n\n const maxWidth = width - prefixWidth - 2;\n const truncatedValue = truncateToWidth(displayValue, maxWidth, '');\n const valueText = this.highlightMatch(truncatedValue, query);\n const line = `${prefix}${valueText}`;\n return isSelected ? this.theme.selectedText(line) : line;\n }\n\n private getDescriptionLayout(\n width: number,\n prefixWidth: number,\n ): { availableWidth: number; maxValueWidth: number; spacingWidth: number } | null {\n if (width <= SearchableSelectList.DESCRIPTION_LAYOUT_MIN_WIDTH) {\n return null;\n }\n\n const availableWidth = Math.max(\n 1,\n width - prefixWidth - SearchableSelectList.RIGHT_MARGIN_WIDTH,\n );\n const maxValueWidth =\n availableWidth -\n SearchableSelectList.DESCRIPTION_MIN_WIDTH -\n SearchableSelectList.DESCRIPTION_SPACING_WIDTH;\n\n if (maxValueWidth < 1) {\n return null;\n }\n\n return {\n availableWidth,\n maxValueWidth,\n spacingWidth: SearchableSelectList.DESCRIPTION_SPACING_WIDTH,\n };\n }\n\n handleInput(keyData: string): void {\n if (isKeyRelease(keyData)) {\n return;\n }\n\n if (matchesKey(keyData, 'up') || matchesKey(keyData, 'ctrl+p')) {\n this.selectedIndex = Math.max(0, this.selectedIndex - 1);\n this.notifySelectionChange();\n return;\n }\n\n if (matchesKey(keyData, 'down') || matchesKey(keyData, 'ctrl+n')) {\n this.selectedIndex = Math.min(this.filteredItems.length - 1, this.selectedIndex + 1);\n this.notifySelectionChange();\n return;\n }\n\n if (matchesKey(keyData, 'enter')) {\n const item = this.filteredItems[this.selectedIndex];\n if (item && this.onSelect) {\n this.onSelect(item);\n }\n return;\n }\n\n if (matchesKey(keyData, 'escape') || keyData === '\\u0003') {\n if (this.onCancel) {\n this.onCancel();\n }\n return;\n }\n\n const prevValue = this.searchInput.getValue();\n this.searchInput.handleInput(keyData);\n const newValue = this.searchInput.getValue();\n\n if (prevValue !== newValue) {\n this.updateFilter();\n }\n }\n\n private notifySelectionChange() {\n const item = this.filteredItems[this.selectedIndex];\n if (item && this.onSelectionChange) {\n this.onSelectionChange(item);\n }\n }\n\n getSelectedItem(): SelectItem | null {\n return this.filteredItems[this.selectedIndex] ?? null;\n }\n}\n"],"mappings":";;;AAkBA,MAAM,iBAAiB,IAAI,OAAO,GADd,OAAO,aAAa,GACQ,CAAC,cAAc,IAAI;AAQnE,SAAS,UAAU,KAAqB;AACtC,QAAO,IAAI,QAAQ,mBAAmB,GAAG;;AAG3C,IAAa,uBAAb,MAAa,qBAA0C;CACrD;CACA;CACA,gBAAwB;CACxB;CACA;CACA;CACA,6BAAqB,IAAI,KAAqB;CAE9C;CACA;CACA;CAEA,OAAwB,+BAA+B;CACvD,OAAwB,wBAAwB;CAChD,OAAwB,4BAA4B;CACpD,OAAwB,qBAAqB;CAE7C,YAAY,OAAqB,YAAoB,OAAkC;AACrF,OAAK,QAAQ;AACb,OAAK,gBAAgB;AACrB,OAAK,aAAa;AAClB,OAAK,QAAQ;AACb,OAAK,cAAc,IAAI,OAAO;;CAGhC,eAAuB,SAAyB;EAC9C,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ;AACxC,MAAI,CAAC,OAAO;AACV,WAAQ,IAAI,OAAO,KAAK,YAAY,QAAQ,EAAE,KAAK;AACnD,QAAK,WAAW,IAAI,SAAS,MAAM;;AAErC,SAAO;;CAGT,eAAuB;EACrB,MAAM,QAAQ,KAAK,YAAY,UAAU,CAAC,MAAM;AAEhD,MAAI,CAAC,MACH,MAAK,gBAAgB,KAAK;MAE1B,MAAK,gBAAgB,KAAK,YAAY,MAAM;AAG9C,OAAK,gBAAgB;AACrB,OAAK,uBAAuB;;CAG9B,YAAoB,OAA6B;EAC/C,MAAM,IAAI,gCAAgC,MAAM;EAGhD,MAAM,cAA4B,EAAE;EACpC,MAAM,kBAAoC,EAAE;AAE5C,OAAK,MAAM,QAAQ,KAAK,OAAO;GAC7B,MAAM,WAAW,KAAK,aAAa,KAAK;GACxC,MAAM,UAAU,KAAK,eAAe;GACpC,MAAM,QAAQ,gCAAgC,UAAU,SAAS,CAAC;GAClE,MAAM,OAAO,gCAAgC,UAAU,QAAQ,CAAC;GAEhE,MAAM,aAAa,MAAM,QAAQ,EAAE;AACnC,OAAI,eAAe,IAAI;AACrB,gBAAY,KAAK;KAAE;KAAM,MAAM;KAAG,OAAO;KAAY,CAAC;AACtD;;GAEF,MAAM,oBAAoB,sBAAsB,OAAO,EAAE;AACzD,OAAI,sBAAsB,MAAM;AAC9B,gBAAY,KAAK;KAAE;KAAM,MAAM;KAAG,OAAO;KAAmB,CAAC;AAC7D;;GAEF,MAAM,YAAY,KAAK,QAAQ,EAAE;AACjC,OAAI,cAAc,IAAI;AACpB,gBAAY,KAAK;KAAE;KAAM,MAAM;KAAG,OAAO;KAAW,CAAC;AACrD;;GAEF,MAAM,aAAc,KAAiC,cAAc;AACnE,mBAAgB,KAAK;IACnB;IACA,iBAAiB,gCACf;KAAC;KAAU;KAAS;KAAW,CAC5B,KAAK,UAAU,UAAU,MAAM,CAAC,CAChC,OAAO,QAAQ,CACf,KAAK,IAAI,CACb;IACF,CAAC;;AAGJ,cAAY,KAAK,KAAK,eAAe;EACrC,MAAM,eAAe,iBAAiB,iBAAiB,EAAE;AACzD,SAAO,CAAC,GAAG,YAAY,KAAK,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,KAAK,UAAU,MAAM,KAAK,CAAC;;CAGxF,YAAoB,KAAqB;AACvC,SAAO,IAAI,QAAQ,uBAAuB,OAAO;;CAGnD,kBACE,GACA,MACG;AACH,MAAI,EAAE,SAAS,EAAE,KACf,QAAO,EAAE,OAAO,EAAE;AAEpB,MAAI,EAAE,UAAU,EAAE,MAChB,QAAO,EAAE,QAAQ,EAAE;AAErB,SAAO,KAAK,aAAa,EAAE,KAAK,CAAC,cAAc,KAAK,aAAa,EAAE,KAAK,CAAC;;CAG3E,aAAqB,MAA0B;AAC7C,SAAO,KAAK,SAAS,KAAK;;CAG5B,eAAuB,MAAwD;EAC7E,MAAM,QAAkD,EAAE;AAC1D,iBAAe,YAAY;EAC3B,IAAI,YAAY;EAChB,IAAI;AAEJ,UAAQ,QAAQ,eAAe,KAAK,KAAK,MAAM,MAAM;AACnD,OAAI,MAAM,QAAQ,UAChB,OAAM,KAAK;IAAE,MAAM,KAAK,MAAM,WAAW,MAAM,MAAM;IAAE,QAAQ;IAAO,CAAC;AAEzE,SAAM,KAAK;IAAE,MAAM,MAAM;IAAI,QAAQ;IAAM,CAAC;AAC5C,eAAY,MAAM,QAAQ,MAAM,GAAG;;AAErC,MAAI,YAAY,KAAK,OACnB,OAAM,KAAK;GAAE,MAAM,KAAK,MAAM,UAAU;GAAE,QAAQ;GAAO,CAAC;AAE5D,SAAO;;CAGT,eAAuB,MAAc,OAAuB;EAC1D,MAAM,SAAS,MACZ,MAAM,CACN,MAAM,MAAM,CACZ,KAAK,UAAU,gCAAgC,MAAM,CAAC,CACtD,QAAQ,UAAU,MAAM,SAAS,EAAE;AACtC,MAAI,OAAO,WAAW,EACpB,QAAO;EAGT,MAAM,eAAe,MAAM,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,UAAU,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO;EACxF,IAAI,QAAQ,KAAK,eAAe,KAAK;AACrC,OAAK,MAAM,SAAS,cAAc;GAChC,MAAM,QAAQ,KAAK,eAAe,MAAM;GACxC,MAAM,YAAsD,EAAE;AAC9D,QAAK,MAAM,QAAQ,OAAO;AACxB,QAAI,KAAK,QAAQ;AACf,eAAU,KAAK,KAAK;AACpB;;AAEF,UAAM,YAAY;IAClB,MAAM,WAAW,KAAK,KAAK,QAAQ,QAAQ,UAAU,KAAK,MAAM,eAAe,MAAM,CAAC;AACtF,QAAI,aAAa,KAAK,MAAM;AAC1B,eAAU,KAAK,KAAK;AACpB;;AAEF,cAAU,KAAK,GAAG,KAAK,eAAe,SAAS,CAAC;;AAElD,WAAQ;;AAEV,SAAO,MAAM,KAAK,SAAS,KAAK,KAAK,CAAC,KAAK,GAAG;;CAGhD,iBAAiB,OAAe;AAC9B,OAAK,gBAAgB,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,KAAK,cAAc,SAAS,EAAE,CAAC;;CAGlF,aAAa;AACX,OAAK,YAAY,YAAY;;CAG/B,OAAO,OAAyB;EAC9B,MAAM,QAAkB,EAAE;EAG1B,MAAM,SAAS,KAAK,MAAM,aAAa,WAAW;EAClD,MAAM,aAAa,KAAK,IAAI,GAAG,QAAQ,aAAa,OAAO,CAAC;EAE5D,MAAM,YADa,KAAK,YAAY,OAAO,WACf,CAAC,MAAM;AACnC,QAAM,KAAK,GAAG,SAAS,KAAK,MAAM,YAAY,UAAU,GAAG;AAC3D,QAAM,KAAK,GAAG;EAEd,MAAM,QAAQ,KAAK,YAAY,UAAU,CAAC,MAAM;AAEhD,MAAI,KAAK,cAAc,WAAW,GAAG;AACnC,SAAM,KAAK,KAAK,MAAM,QAAQ,eAAe,CAAC;AAC9C,UAAO;;EAGT,MAAM,aAAa,KAAK,IACtB,GACA,KAAK,IACH,KAAK,gBAAgB,KAAK,MAAM,KAAK,aAAa,EAAE,EACpD,KAAK,cAAc,SAAS,KAAK,WAClC,CACF;EACD,MAAM,WAAW,KAAK,IAAI,aAAa,KAAK,YAAY,KAAK,cAAc,OAAO;AAElF,OAAK,IAAI,IAAI,YAAY,IAAI,UAAU,KAAK;GAC1C,MAAM,OAAO,KAAK,cAAc;AAChC,OAAI,CAAC,KACH;GAEF,MAAM,aAAa,MAAM,KAAK;AAC9B,SAAM,KAAK,KAAK,eAAe,MAAM,YAAY,OAAO,MAAM,CAAC;;AAGjE,MAAI,KAAK,cAAc,SAAS,KAAK,YAAY;GAC/C,MAAM,aAAa,GAAG,KAAK,gBAAgB,EAAE,GAAG,KAAK,cAAc;AACnE,SAAM,KAAK,KAAK,MAAM,WAAW,KAAK,aAAa,CAAC;;AAGtD,SAAO;;CAGT,eACE,MACA,YACA,OACA,OACQ;EACR,MAAM,SAAS,aAAa,OAAO;EACnC,MAAM,cAAc,OAAO;EAC3B,MAAM,eAAe,KAAK,aAAa,KAAK;EAE5C,MAAM,cAAc,KAAK;AACzB,MAAI,aAAa;GACf,MAAM,oBAAoB,KAAK,qBAAqB,OAAO,YAAY;AACvE,OAAI,mBAAmB;IACrB,MAAM,iBAAiB,gBAAgB,cAAc,kBAAkB,eAAe,GAAG;IACzF,MAAM,YAAY,KAAK,eAAe,gBAAgB,MAAM;IAE5D,MAAM,cAAc,aAAa,UAAU;IAE3C,MAAM,mBADiB,kBAAkB,iBAAiB,cAChB,kBAAkB;AAE5D,QAAI,oBAAoB,qBAAqB,uBAAuB;KAClE,MAAM,UAAU,IAAI,OAAO,kBAAkB,aAAa;KAC1D,MAAM,gBAAgB,gBAAgB,aAAa,kBAAkB,GAAG;KACxE,MAAM,kBAAkB,KAAK,eAAe,eAAe,MAAM;KAEjE,MAAM,OAAO,GAAG,SAAS,YAAY,UADpB,aAAa,kBAAkB,KAAK,MAAM,YAAY,gBAAgB;AAEvF,YAAO,aAAa,KAAK,MAAM,aAAa,KAAK,GAAG;;;;EAM1D,MAAM,iBAAiB,gBAAgB,cADtB,QAAQ,cAAc,GACwB,GAAG;EAElE,MAAM,OAAO,GAAG,SADE,KAAK,eAAe,gBAAgB,MACpB;AAClC,SAAO,aAAa,KAAK,MAAM,aAAa,KAAK,GAAG;;CAGtD,qBACE,OACA,aACgF;AAChF,MAAI,SAAS,qBAAqB,6BAChC,QAAO;EAGT,MAAM,iBAAiB,KAAK,IAC1B,GACA,QAAQ,cAAc,qBAAqB,mBAC5C;EACD,MAAM,gBACJ,iBACA,qBAAqB,wBACrB,qBAAqB;AAEvB,MAAI,gBAAgB,EAClB,QAAO;AAGT,SAAO;GACL;GACA;GACA,cAAc,qBAAqB;GACpC;;CAGH,YAAY,SAAuB;AACjC,MAAI,aAAa,QAAQ,CACvB;AAGF,MAAI,WAAW,SAAS,KAAK,IAAI,WAAW,SAAS,SAAS,EAAE;AAC9D,QAAK,gBAAgB,KAAK,IAAI,GAAG,KAAK,gBAAgB,EAAE;AACxD,QAAK,uBAAuB;AAC5B;;AAGF,MAAI,WAAW,SAAS,OAAO,IAAI,WAAW,SAAS,SAAS,EAAE;AAChE,QAAK,gBAAgB,KAAK,IAAI,KAAK,cAAc,SAAS,GAAG,KAAK,gBAAgB,EAAE;AACpF,QAAK,uBAAuB;AAC5B;;AAGF,MAAI,WAAW,SAAS,QAAQ,EAAE;GAChC,MAAM,OAAO,KAAK,cAAc,KAAK;AACrC,OAAI,QAAQ,KAAK,SACf,MAAK,SAAS,KAAK;AAErB;;AAGF,MAAI,WAAW,SAAS,SAAS,IAAI,YAAY,KAAU;AACzD,OAAI,KAAK,SACP,MAAK,UAAU;AAEjB;;EAGF,MAAM,YAAY,KAAK,YAAY,UAAU;AAC7C,OAAK,YAAY,YAAY,QAAQ;AAGrC,MAAI,cAFa,KAAK,YAAY,UAER,CACxB,MAAK,cAAc;;CAIvB,wBAAgC;EAC9B,MAAM,OAAO,KAAK,cAAc,KAAK;AACrC,MAAI,QAAQ,KAAK,kBACf,MAAK,kBAAkB,KAAK;;CAIhC,kBAAqC;AACnC,SAAO,KAAK,cAAc,KAAK,kBAAkB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Container } from '@mariozechner/pi-tui';
|
|
2
|
+
export declare class ToolExecutionComponent extends Container {
|
|
3
|
+
private contentText;
|
|
4
|
+
private toolName;
|
|
5
|
+
private args;
|
|
6
|
+
private resultText;
|
|
7
|
+
private expanded;
|
|
8
|
+
private isError;
|
|
9
|
+
private isPartial;
|
|
10
|
+
constructor(toolName: string, args: unknown);
|
|
11
|
+
setArgs(args: unknown): void;
|
|
12
|
+
setExpanded(expanded: boolean): void;
|
|
13
|
+
setResult(result: string, isError: boolean): void;
|
|
14
|
+
private refresh;
|
|
15
|
+
private formatToolExecution;
|
|
16
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { theme } from "../theme.js";
|
|
2
|
+
import { Container, Spacer, Text } from "@mariozechner/pi-tui";
|
|
3
|
+
//#region src/tui/components/tool-execution.ts
|
|
4
|
+
const MAX_ARG_VALUE_LENGTH = 120;
|
|
5
|
+
function sanitize(text) {
|
|
6
|
+
return text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "");
|
|
7
|
+
}
|
|
8
|
+
function formatArgsSummary(args) {
|
|
9
|
+
if (!args || typeof args !== "object") return "";
|
|
10
|
+
const entries = Object.entries(args);
|
|
11
|
+
if (entries.length === 0) return "";
|
|
12
|
+
return entries.map(([key, value]) => {
|
|
13
|
+
const stringValue = typeof value === "string" ? value : JSON.stringify(value);
|
|
14
|
+
return `${key}=${stringValue.length > MAX_ARG_VALUE_LENGTH ? `${stringValue.slice(0, MAX_ARG_VALUE_LENGTH - 3)}...` : stringValue}`;
|
|
15
|
+
}).join(", ");
|
|
16
|
+
}
|
|
17
|
+
var ToolExecutionComponent = class extends Container {
|
|
18
|
+
contentText;
|
|
19
|
+
toolName;
|
|
20
|
+
args;
|
|
21
|
+
resultText = "";
|
|
22
|
+
expanded = false;
|
|
23
|
+
isError = false;
|
|
24
|
+
isPartial = true;
|
|
25
|
+
constructor(toolName, args) {
|
|
26
|
+
super();
|
|
27
|
+
this.toolName = toolName;
|
|
28
|
+
this.args = args;
|
|
29
|
+
this.addChild(new Spacer(1));
|
|
30
|
+
const bgFn = (text) => theme.toolPendingBg(text);
|
|
31
|
+
this.contentText = new Text("", 1, 1, bgFn);
|
|
32
|
+
this.addChild(this.contentText);
|
|
33
|
+
this.refresh();
|
|
34
|
+
}
|
|
35
|
+
setArgs(args) {
|
|
36
|
+
this.args = args;
|
|
37
|
+
this.refresh();
|
|
38
|
+
}
|
|
39
|
+
setExpanded(expanded) {
|
|
40
|
+
this.expanded = expanded;
|
|
41
|
+
this.refresh();
|
|
42
|
+
}
|
|
43
|
+
setResult(result, isError) {
|
|
44
|
+
this.resultText = sanitize(result);
|
|
45
|
+
this.isError = isError;
|
|
46
|
+
this.isPartial = false;
|
|
47
|
+
this.refresh();
|
|
48
|
+
}
|
|
49
|
+
refresh() {
|
|
50
|
+
const bgFn = this.isPartial ? (text) => theme.toolPendingBg(text) : this.isError ? (text) => theme.toolErrorBg(text) : (text) => theme.toolSuccessBg(text);
|
|
51
|
+
this.contentText.setCustomBgFn(bgFn);
|
|
52
|
+
this.contentText.setText(this.formatToolExecution());
|
|
53
|
+
}
|
|
54
|
+
formatToolExecution() {
|
|
55
|
+
const argsStr = formatArgsSummary(this.args);
|
|
56
|
+
const titleParts = [theme.toolTitle(theme.bold(this.toolName))];
|
|
57
|
+
if (argsStr) titleParts.push(theme.dim(`(${argsStr})`));
|
|
58
|
+
let text = titleParts.join(" ");
|
|
59
|
+
const output = this.resultText;
|
|
60
|
+
if (output) if (this.expanded) text += `\n${theme.toolOutput(output)}`;
|
|
61
|
+
else {
|
|
62
|
+
const oneLine = output.replace(/\n/g, " ").replace(/\s+/g, " ").trim();
|
|
63
|
+
const lineCount = output.split("\n").length;
|
|
64
|
+
const maxPreviewLength = 200;
|
|
65
|
+
const preview = oneLine.length > maxPreviewLength ? `${oneLine.slice(0, maxPreviewLength)}…` : oneLine;
|
|
66
|
+
const suffix = lineCount > 1 ? theme.dim(` (${lineCount} lines)`) : "";
|
|
67
|
+
text += `\n${theme.toolOutput(preview)}${suffix}`;
|
|
68
|
+
}
|
|
69
|
+
else if (this.isPartial) text += `\n${theme.dim("…")}`;
|
|
70
|
+
return text;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
export { ToolExecutionComponent };
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=tool-execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-execution.js","names":[],"sources":["../../../../src/tui/components/tool-execution.ts"],"sourcesContent":["import { Container, Spacer, Text } from '@mariozechner/pi-tui';\n\nimport { theme } from '../theme.js';\n\nconst MAX_ARG_VALUE_LENGTH = 120;\n\nfunction sanitize(text: string): string {\n return text.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, '');\n}\n\nfunction formatArgsSummary(args: unknown): string {\n if (!args || typeof args !== 'object') return '';\n const entries = Object.entries(args as Record<string, unknown>);\n if (entries.length === 0) return '';\n return entries\n .map(([key, value]) => {\n const stringValue = typeof value === 'string' ? value : JSON.stringify(value);\n const truncated =\n stringValue.length > MAX_ARG_VALUE_LENGTH\n ? `${stringValue.slice(0, MAX_ARG_VALUE_LENGTH - 3)}...`\n : stringValue;\n return `${key}=${truncated}`;\n })\n .join(', ');\n}\n\nexport class ToolExecutionComponent extends Container {\n private contentText: Text;\n private toolName: string;\n private args: unknown;\n private resultText = '';\n private expanded = false;\n private isError = false;\n private isPartial = true;\n\n constructor(toolName: string, args: unknown) {\n super();\n this.toolName = toolName;\n this.args = args;\n\n this.addChild(new Spacer(1));\n\n const bgFn = (text: string) => theme.toolPendingBg(text);\n this.contentText = new Text('', 1, 1, bgFn);\n this.addChild(this.contentText);\n\n this.refresh();\n }\n\n setArgs(args: unknown): void {\n this.args = args;\n this.refresh();\n }\n\n setExpanded(expanded: boolean): void {\n this.expanded = expanded;\n this.refresh();\n }\n\n setResult(result: string, isError: boolean): void {\n this.resultText = sanitize(result);\n this.isError = isError;\n this.isPartial = false;\n this.refresh();\n }\n\n private refresh(): void {\n const bgFn = this.isPartial\n ? (text: string) => theme.toolPendingBg(text)\n : this.isError\n ? (text: string) => theme.toolErrorBg(text)\n : (text: string) => theme.toolSuccessBg(text);\n this.contentText.setCustomBgFn(bgFn);\n this.contentText.setText(this.formatToolExecution());\n }\n\n private formatToolExecution(): string {\n // Title line: 🔧 tool_name (args_summary)\n const argsStr = formatArgsSummary(this.args);\n const titleParts = [theme.toolTitle(theme.bold(this.toolName))];\n if (argsStr) {\n titleParts.push(theme.dim(`(${argsStr})`));\n }\n let text = titleParts.join(' ');\n\n // Output / result — collapsed: single-line summary; expanded: full output\n const output = this.resultText;\n if (output) {\n if (this.expanded) {\n text += `\\n${theme.toolOutput(output)}`;\n } else {\n // Compact single-line preview: flatten to one line and truncate\n const oneLine = output.replace(/\\n/g, ' ').replace(/\\s+/g, ' ').trim();\n const lineCount = output.split('\\n').length;\n const maxPreviewLength = 200;\n const preview = oneLine.length > maxPreviewLength\n ? `${oneLine.slice(0, maxPreviewLength)}…`\n : oneLine;\n const suffix = lineCount > 1 ? theme.dim(` (${lineCount} lines)`) : '';\n text += `\\n${theme.toolOutput(preview)}${suffix}`;\n }\n } else if (this.isPartial) {\n text += `\\n${theme.dim('…')}`;\n }\n\n return text;\n }\n}\n"],"mappings":";;;AAIA,MAAM,uBAAuB;AAE7B,SAAS,SAAS,MAAsB;AACtC,QAAO,KAAK,QAAQ,iCAAiC,GAAG;;AAG1D,SAAS,kBAAkB,MAAuB;AAChD,KAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;CAC9C,MAAM,UAAU,OAAO,QAAQ,KAAgC;AAC/D,KAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QAAO,QACJ,KAAK,CAAC,KAAK,WAAW;EACrB,MAAM,cAAc,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,MAAM;AAK7E,SAAO,GAAG,IAAI,GAHZ,YAAY,SAAS,uBACjB,GAAG,YAAY,MAAM,GAAG,uBAAuB,EAAE,CAAC,OAClD;GAEN,CACD,KAAK,KAAK;;AAGf,IAAa,yBAAb,cAA4C,UAAU;CACpD;CACA;CACA;CACA,aAAqB;CACrB,WAAmB;CACnB,UAAkB;CAClB,YAAoB;CAEpB,YAAY,UAAkB,MAAe;AAC3C,SAAO;AACP,OAAK,WAAW;AAChB,OAAK,OAAO;AAEZ,OAAK,SAAS,IAAI,OAAO,EAAE,CAAC;EAE5B,MAAM,QAAQ,SAAiB,MAAM,cAAc,KAAK;AACxD,OAAK,cAAc,IAAI,KAAK,IAAI,GAAG,GAAG,KAAK;AAC3C,OAAK,SAAS,KAAK,YAAY;AAE/B,OAAK,SAAS;;CAGhB,QAAQ,MAAqB;AAC3B,OAAK,OAAO;AACZ,OAAK,SAAS;;CAGhB,YAAY,UAAyB;AACnC,OAAK,WAAW;AAChB,OAAK,SAAS;;CAGhB,UAAU,QAAgB,SAAwB;AAChD,OAAK,aAAa,SAAS,OAAO;AAClC,OAAK,UAAU;AACf,OAAK,YAAY;AACjB,OAAK,SAAS;;CAGhB,UAAwB;EACtB,MAAM,OAAO,KAAK,aACb,SAAiB,MAAM,cAAc,KAAK,GAC3C,KAAK,WACF,SAAiB,MAAM,YAAY,KAAK,IACxC,SAAiB,MAAM,cAAc,KAAK;AACjD,OAAK,YAAY,cAAc,KAAK;AACpC,OAAK,YAAY,QAAQ,KAAK,qBAAqB,CAAC;;CAGtD,sBAAsC;EAEpC,MAAM,UAAU,kBAAkB,KAAK,KAAK;EAC5C,MAAM,aAAa,CAAC,MAAM,UAAU,MAAM,KAAK,KAAK,SAAS,CAAC,CAAC;AAC/D,MAAI,QACF,YAAW,KAAK,MAAM,IAAI,IAAI,QAAQ,GAAG,CAAC;EAE5C,IAAI,OAAO,WAAW,KAAK,IAAI;EAG/B,MAAM,SAAS,KAAK;AACpB,MAAI,OACF,KAAI,KAAK,SACP,SAAQ,KAAK,MAAM,WAAW,OAAO;OAChC;GAEL,MAAM,UAAU,OAAO,QAAQ,OAAO,IAAI,CAAC,QAAQ,QAAQ,IAAI,CAAC,MAAM;GACtE,MAAM,YAAY,OAAO,MAAM,KAAK,CAAC;GACrC,MAAM,mBAAmB;GACzB,MAAM,UAAU,QAAQ,SAAS,mBAC7B,GAAG,QAAQ,MAAM,GAAG,iBAAiB,CAAC,KACtC;GACJ,MAAM,SAAS,YAAY,IAAI,MAAM,IAAI,KAAK,UAAU,SAAS,GAAG;AACpE,WAAQ,KAAK,MAAM,WAAW,QAAQ,GAAG;;WAElC,KAAK,UACd,SAAQ,KAAK,MAAM,IAAI,IAAI;AAG7B,SAAO"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { markdownTheme, theme } from "../theme.js";
|
|
2
|
+
import { Container, Markdown, Spacer } from "@mariozechner/pi-tui";
|
|
3
|
+
//#region src/tui/components/user-message.ts
|
|
4
|
+
var UserMessageComponent = class extends Container {
|
|
5
|
+
body;
|
|
6
|
+
constructor(text) {
|
|
7
|
+
super();
|
|
8
|
+
this.body = new Markdown(text, 1, 0, markdownTheme, {
|
|
9
|
+
bgColor: (line) => theme.userBg(line),
|
|
10
|
+
color: (line) => theme.userText(line)
|
|
11
|
+
});
|
|
12
|
+
this.addChild(new Spacer(1));
|
|
13
|
+
this.addChild(this.body);
|
|
14
|
+
}
|
|
15
|
+
setText(text) {
|
|
16
|
+
this.body.setText(text);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { UserMessageComponent };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=user-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-message.js","names":[],"sources":["../../../../src/tui/components/user-message.ts"],"sourcesContent":["import { Container, Markdown, Spacer } from '@mariozechner/pi-tui';\n\nimport { markdownTheme, theme } from '../theme.js';\n\nexport class UserMessageComponent extends Container {\n private body: Markdown;\n\n constructor(text: string) {\n super();\n this.body = new Markdown(text, 1, 0, markdownTheme, {\n bgColor: (line) => theme.userBg(line),\n color: (line) => theme.userText(line),\n });\n this.addChild(new Spacer(1));\n this.addChild(this.body);\n }\n\n setText(text: string): void {\n this.body.setText(text);\n }\n}\n"],"mappings":";;;AAIA,IAAa,uBAAb,cAA0C,UAAU;CAClD;CAEA,YAAY,MAAc;AACxB,SAAO;AACP,OAAK,OAAO,IAAI,SAAS,MAAM,GAAG,GAAG,eAAe;GAClD,UAAU,SAAS,MAAM,OAAO,KAAK;GACrC,QAAQ,SAAS,MAAM,SAAS,KAAK;GACtC,CAAC;AACF,OAAK,SAAS,IAAI,OAAO,EAAE,CAAC;AAC5B,OAAK,SAAS,KAAK,KAAK;;CAG1B,QAAQ,MAAoB;AAC1B,OAAK,KAAK,QAAQ,KAAK"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ParsedSSEEvent } from './tui-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Consume an SSE stream from a `ReadableStream<Uint8Array>` (Node.js 22+ fetch body).
|
|
4
|
+
*
|
|
5
|
+
* Parses the standard SSE wire format:
|
|
6
|
+
* event: <name>\n
|
|
7
|
+
* data: <json>\n
|
|
8
|
+
* id: <id>\n
|
|
9
|
+
* \n
|
|
10
|
+
*
|
|
11
|
+
* Calls `onEvent` for each complete event block.
|
|
12
|
+
*/
|
|
13
|
+
export declare function consumeSSEStream(body: ReadableStream<Uint8Array>, onEvent: (event: ParsedSSEEvent) => void, signal?: AbortSignal): Promise<void>;
|
|
14
|
+
/** Parse SSE data field as JSON, returning null on failure. */
|
|
15
|
+
export declare function parseSSEData<T = unknown>(data: string): T | null;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//#region src/tui/sse-consumer.ts
|
|
2
|
+
/**
|
|
3
|
+
* Consume an SSE stream from a `ReadableStream<Uint8Array>` (Node.js 22+ fetch body).
|
|
4
|
+
*
|
|
5
|
+
* Parses the standard SSE wire format:
|
|
6
|
+
* event: <name>\n
|
|
7
|
+
* data: <json>\n
|
|
8
|
+
* id: <id>\n
|
|
9
|
+
* \n
|
|
10
|
+
*
|
|
11
|
+
* Calls `onEvent` for each complete event block.
|
|
12
|
+
*/
|
|
13
|
+
async function consumeSSEStream(body, onEvent, signal) {
|
|
14
|
+
const reader = body.getReader();
|
|
15
|
+
const decoder = new TextDecoder();
|
|
16
|
+
let buffer = "";
|
|
17
|
+
let currentEvent = "";
|
|
18
|
+
let currentData = "";
|
|
19
|
+
let currentId = "";
|
|
20
|
+
try {
|
|
21
|
+
while (true) {
|
|
22
|
+
if (signal?.aborted) break;
|
|
23
|
+
const { done, value } = await reader.read();
|
|
24
|
+
if (done) break;
|
|
25
|
+
buffer += decoder.decode(value, { stream: true });
|
|
26
|
+
const lines = buffer.split("\n");
|
|
27
|
+
buffer = lines.pop() ?? "";
|
|
28
|
+
for (const line of lines) {
|
|
29
|
+
if (line === "") {
|
|
30
|
+
if (currentData) onEvent({
|
|
31
|
+
event: currentEvent || "message",
|
|
32
|
+
data: currentData,
|
|
33
|
+
id: currentId || void 0
|
|
34
|
+
});
|
|
35
|
+
currentEvent = "";
|
|
36
|
+
currentData = "";
|
|
37
|
+
currentId = "";
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (line.startsWith(":")) continue;
|
|
41
|
+
const colonIndex = line.indexOf(":");
|
|
42
|
+
if (colonIndex === -1) continue;
|
|
43
|
+
const field = line.slice(0, colonIndex);
|
|
44
|
+
const valueStart = line[colonIndex + 1] === " " ? colonIndex + 2 : colonIndex + 1;
|
|
45
|
+
const fieldValue = line.slice(valueStart);
|
|
46
|
+
switch (field) {
|
|
47
|
+
case "event":
|
|
48
|
+
currentEvent = fieldValue;
|
|
49
|
+
break;
|
|
50
|
+
case "data":
|
|
51
|
+
currentData = currentData ? `${currentData}\n${fieldValue}` : fieldValue;
|
|
52
|
+
break;
|
|
53
|
+
case "id":
|
|
54
|
+
currentId = fieldValue;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
} finally {
|
|
60
|
+
buffer += decoder.decode();
|
|
61
|
+
reader.releaseLock();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** Parse SSE data field as JSON, returning null on failure. */
|
|
65
|
+
function parseSSEData(data) {
|
|
66
|
+
try {
|
|
67
|
+
return JSON.parse(data);
|
|
68
|
+
} catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { consumeSSEStream, parseSSEData };
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=sse-consumer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-consumer.js","names":[],"sources":["../../../src/tui/sse-consumer.ts"],"sourcesContent":["import type { ParsedSSEEvent } from './tui-types.js';\n\n/**\n * Consume an SSE stream from a `ReadableStream<Uint8Array>` (Node.js 22+ fetch body).\n *\n * Parses the standard SSE wire format:\n * event: <name>\\n\n * data: <json>\\n\n * id: <id>\\n\n * \\n\n *\n * Calls `onEvent` for each complete event block.\n */\nexport async function consumeSSEStream(\n body: ReadableStream<Uint8Array>,\n onEvent: (event: ParsedSSEEvent) => void,\n signal?: AbortSignal,\n): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let currentEvent = '';\n let currentData = '';\n let currentId = '';\n\n try {\n while (true) {\n if (signal?.aborted) break;\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n // Keep the last (possibly incomplete) line in the buffer\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line === '') {\n // Empty line = end of event block\n if (currentData) {\n onEvent({\n event: currentEvent || 'message',\n data: currentData,\n id: currentId || undefined,\n });\n }\n currentEvent = '';\n currentData = '';\n currentId = '';\n continue;\n }\n\n if (line.startsWith(':')) {\n // Comment line, skip\n continue;\n }\n\n const colonIndex = line.indexOf(':');\n if (colonIndex === -1) continue;\n\n const field = line.slice(0, colonIndex);\n // SSE spec: if there's a space after the colon, skip it\n const valueStart = line[colonIndex + 1] === ' ' ? colonIndex + 2 : colonIndex + 1;\n const fieldValue = line.slice(valueStart);\n\n switch (field) {\n case 'event':\n currentEvent = fieldValue;\n break;\n case 'data':\n currentData = currentData ? `${currentData}\\n${fieldValue}` : fieldValue;\n break;\n case 'id':\n currentId = fieldValue;\n break;\n }\n }\n }\n } finally {\n buffer += decoder.decode();\n reader.releaseLock();\n }\n}\n\n/** Parse SSE data field as JSON, returning null on failure. */\nexport function parseSSEData<T = unknown>(data: string): T | null {\n try {\n return JSON.parse(data) as T;\n } catch {\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;AAaA,eAAsB,iBACpB,MACA,SACA,QACe;CACf,MAAM,SAAS,KAAK,WAAW;CAC/B,MAAM,UAAU,IAAI,aAAa;CACjC,IAAI,SAAS;CACb,IAAI,eAAe;CACnB,IAAI,cAAc;CAClB,IAAI,YAAY;AAEhB,KAAI;AACF,SAAO,MAAM;AACX,OAAI,QAAQ,QAAS;GACrB,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,OAAI,KAAM;AAEV,aAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,MAAM,CAAC;GACjD,MAAM,QAAQ,OAAO,MAAM,KAAK;AAEhC,YAAS,MAAM,KAAK,IAAI;AAExB,QAAK,MAAM,QAAQ,OAAO;AACxB,QAAI,SAAS,IAAI;AAEf,SAAI,YACF,SAAQ;MACN,OAAO,gBAAgB;MACvB,MAAM;MACN,IAAI,aAAa,KAAA;MAClB,CAAC;AAEJ,oBAAe;AACf,mBAAc;AACd,iBAAY;AACZ;;AAGF,QAAI,KAAK,WAAW,IAAI,CAEtB;IAGF,MAAM,aAAa,KAAK,QAAQ,IAAI;AACpC,QAAI,eAAe,GAAI;IAEvB,MAAM,QAAQ,KAAK,MAAM,GAAG,WAAW;IAEvC,MAAM,aAAa,KAAK,aAAa,OAAO,MAAM,aAAa,IAAI,aAAa;IAChF,MAAM,aAAa,KAAK,MAAM,WAAW;AAEzC,YAAQ,OAAR;KACE,KAAK;AACH,qBAAe;AACf;KACF,KAAK;AACH,oBAAc,cAAc,GAAG,YAAY,IAAI,eAAe;AAC9D;KACF,KAAK;AACH,kBAAY;AACZ;;;;WAIA;AACR,YAAU,QAAQ,QAAQ;AAC1B,SAAO,aAAa;;;;AAKxB,SAAgB,aAA0B,MAAwB;AAChE,KAAI;AACF,SAAO,KAAK,MAAM,KAAK;SACjB;AACN,SAAO"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assembles incremental LLM streaming deltas into displayable text.
|
|
3
|
+
*
|
|
4
|
+
* Tracks per-run thinking + content text, composes them for display,
|
|
5
|
+
* and handles finalization.
|
|
6
|
+
*/
|
|
7
|
+
export declare class StreamAssembler {
|
|
8
|
+
private runs;
|
|
9
|
+
private getOrCreate;
|
|
10
|
+
/** Append a content token delta. Returns updated display text, or null if unchanged. */
|
|
11
|
+
ingestToken(runId: string, delta: string, showThinking: boolean): string | null;
|
|
12
|
+
/** Update thinking content. Returns updated display text, or null if unchanged. */
|
|
13
|
+
ingestThinking(runId: string, content: string, isDelta: boolean, showThinking: boolean): string | null;
|
|
14
|
+
/** Finalize a run and return the final display text. */
|
|
15
|
+
finalize(runId: string, showThinking: boolean): string;
|
|
16
|
+
/** Get current display text for a run. */
|
|
17
|
+
getDisplayText(runId: string): string;
|
|
18
|
+
/** Drop a run without finalizing. */
|
|
19
|
+
drop(runId: string): void;
|
|
20
|
+
/** Clear all run state. */
|
|
21
|
+
clear(): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//#region src/tui/stream-assembler.ts
|
|
2
|
+
function composeDisplay(thinking, content, showThinking) {
|
|
3
|
+
if (!showThinking || !thinking) return content;
|
|
4
|
+
const thinkingBlock = `<thinking>\n${thinking}\n</thinking>\n\n`;
|
|
5
|
+
return content ? `${thinkingBlock}${content}` : thinkingBlock;
|
|
6
|
+
}
|
|
7
|
+
var StreamAssembler = class {
|
|
8
|
+
runs = /* @__PURE__ */ new Map();
|
|
9
|
+
getOrCreate(runId) {
|
|
10
|
+
let state = this.runs.get(runId);
|
|
11
|
+
if (!state) {
|
|
12
|
+
state = {
|
|
13
|
+
thinkingText: "",
|
|
14
|
+
contentText: "",
|
|
15
|
+
displayText: ""
|
|
16
|
+
};
|
|
17
|
+
this.runs.set(runId, state);
|
|
18
|
+
}
|
|
19
|
+
return state;
|
|
20
|
+
}
|
|
21
|
+
/** Append a content token delta. Returns updated display text, or null if unchanged. */
|
|
22
|
+
ingestToken(runId, delta, showThinking) {
|
|
23
|
+
const state = this.getOrCreate(runId);
|
|
24
|
+
state.contentText += delta;
|
|
25
|
+
const next = composeDisplay(state.thinkingText, state.contentText, showThinking);
|
|
26
|
+
if (next === state.displayText) return null;
|
|
27
|
+
state.displayText = next;
|
|
28
|
+
return next;
|
|
29
|
+
}
|
|
30
|
+
/** Update thinking content. Returns updated display text, or null if unchanged. */
|
|
31
|
+
ingestThinking(runId, content, isDelta, showThinking) {
|
|
32
|
+
const state = this.getOrCreate(runId);
|
|
33
|
+
state.thinkingText = isDelta ? state.thinkingText + content : content;
|
|
34
|
+
const next = composeDisplay(state.thinkingText, state.contentText, showThinking);
|
|
35
|
+
if (next === state.displayText) return null;
|
|
36
|
+
state.displayText = next;
|
|
37
|
+
return next;
|
|
38
|
+
}
|
|
39
|
+
/** Finalize a run and return the final display text. */
|
|
40
|
+
finalize(runId, showThinking) {
|
|
41
|
+
const state = this.runs.get(runId);
|
|
42
|
+
if (!state) return "";
|
|
43
|
+
const final = composeDisplay(state.thinkingText, state.contentText, showThinking);
|
|
44
|
+
this.runs.delete(runId);
|
|
45
|
+
return final;
|
|
46
|
+
}
|
|
47
|
+
/** Get current display text for a run. */
|
|
48
|
+
getDisplayText(runId) {
|
|
49
|
+
return this.runs.get(runId)?.displayText ?? "";
|
|
50
|
+
}
|
|
51
|
+
/** Drop a run without finalizing. */
|
|
52
|
+
drop(runId) {
|
|
53
|
+
this.runs.delete(runId);
|
|
54
|
+
}
|
|
55
|
+
/** Clear all run state. */
|
|
56
|
+
clear() {
|
|
57
|
+
this.runs.clear();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
//#endregion
|
|
61
|
+
export { StreamAssembler };
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=stream-assembler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-assembler.js","names":[],"sources":["../../../src/tui/stream-assembler.ts"],"sourcesContent":["/**\n * Assembles incremental LLM streaming deltas into displayable text.\n *\n * Tracks per-run thinking + content text, composes them for display,\n * and handles finalization.\n */\n\ninterface RunStreamState {\n thinkingText: string;\n contentText: string;\n displayText: string;\n}\n\nfunction composeDisplay(thinking: string, content: string, showThinking: boolean): string {\n if (!showThinking || !thinking) return content;\n const thinkingBlock = `<thinking>\\n${thinking}\\n</thinking>\\n\\n`;\n return content ? `${thinkingBlock}${content}` : thinkingBlock;\n}\n\nexport class StreamAssembler {\n private runs = new Map<string, RunStreamState>();\n\n private getOrCreate(runId: string): RunStreamState {\n let state = this.runs.get(runId);\n if (!state) {\n state = { thinkingText: '', contentText: '', displayText: '' };\n this.runs.set(runId, state);\n }\n return state;\n }\n\n /** Append a content token delta. Returns updated display text, or null if unchanged. */\n ingestToken(runId: string, delta: string, showThinking: boolean): string | null {\n const state = this.getOrCreate(runId);\n state.contentText += delta;\n const next = composeDisplay(state.thinkingText, state.contentText, showThinking);\n if (next === state.displayText) return null;\n state.displayText = next;\n return next;\n }\n\n /** Update thinking content. Returns updated display text, or null if unchanged. */\n ingestThinking(\n runId: string,\n content: string,\n isDelta: boolean,\n showThinking: boolean,\n ): string | null {\n const state = this.getOrCreate(runId);\n state.thinkingText = isDelta ? state.thinkingText + content : content;\n const next = composeDisplay(state.thinkingText, state.contentText, showThinking);\n if (next === state.displayText) return null;\n state.displayText = next;\n return next;\n }\n\n /** Finalize a run and return the final display text. */\n finalize(runId: string, showThinking: boolean): string {\n const state = this.runs.get(runId);\n if (!state) return '';\n const final = composeDisplay(state.thinkingText, state.contentText, showThinking);\n this.runs.delete(runId);\n return final;\n }\n\n /** Get current display text for a run. */\n getDisplayText(runId: string): string {\n return this.runs.get(runId)?.displayText ?? '';\n }\n\n /** Drop a run without finalizing. */\n drop(runId: string): void {\n this.runs.delete(runId);\n }\n\n /** Clear all run state. */\n clear(): void {\n this.runs.clear();\n }\n}\n"],"mappings":";AAaA,SAAS,eAAe,UAAkB,SAAiB,cAA+B;AACxF,KAAI,CAAC,gBAAgB,CAAC,SAAU,QAAO;CACvC,MAAM,gBAAgB,eAAe,SAAS;AAC9C,QAAO,UAAU,GAAG,gBAAgB,YAAY;;AAGlD,IAAa,kBAAb,MAA6B;CAC3B,uBAAe,IAAI,KAA6B;CAEhD,YAAoB,OAA+B;EACjD,IAAI,QAAQ,KAAK,KAAK,IAAI,MAAM;AAChC,MAAI,CAAC,OAAO;AACV,WAAQ;IAAE,cAAc;IAAI,aAAa;IAAI,aAAa;IAAI;AAC9D,QAAK,KAAK,IAAI,OAAO,MAAM;;AAE7B,SAAO;;;CAIT,YAAY,OAAe,OAAe,cAAsC;EAC9E,MAAM,QAAQ,KAAK,YAAY,MAAM;AACrC,QAAM,eAAe;EACrB,MAAM,OAAO,eAAe,MAAM,cAAc,MAAM,aAAa,aAAa;AAChF,MAAI,SAAS,MAAM,YAAa,QAAO;AACvC,QAAM,cAAc;AACpB,SAAO;;;CAIT,eACE,OACA,SACA,SACA,cACe;EACf,MAAM,QAAQ,KAAK,YAAY,MAAM;AACrC,QAAM,eAAe,UAAU,MAAM,eAAe,UAAU;EAC9D,MAAM,OAAO,eAAe,MAAM,cAAc,MAAM,aAAa,aAAa;AAChF,MAAI,SAAS,MAAM,YAAa,QAAO;AACvC,QAAM,cAAc;AACpB,SAAO;;;CAIT,SAAS,OAAe,cAA+B;EACrD,MAAM,QAAQ,KAAK,KAAK,IAAI,MAAM;AAClC,MAAI,CAAC,MAAO,QAAO;EACnB,MAAM,QAAQ,eAAe,MAAM,cAAc,MAAM,aAAa,aAAa;AACjF,OAAK,KAAK,OAAO,MAAM;AACvB,SAAO;;;CAIT,eAAe,OAAuB;AACpC,SAAO,KAAK,KAAK,IAAI,MAAM,EAAE,eAAe;;;CAI9C,KAAK,OAAqB;AACxB,OAAK,KAAK,OAAO,MAAM;;;CAIzB,QAAc;AACZ,OAAK,KAAK,OAAO"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { EditorTheme, MarkdownTheme, SelectListTheme } from '@mariozechner/pi-tui';
|
|
2
|
+
import type { SearchableSelectListTheme } from './components/searchable-select-list.js';
|
|
3
|
+
export declare const lightMode: boolean;
|
|
4
|
+
export declare const palette: {
|
|
5
|
+
readonly text: "#f5f5f7";
|
|
6
|
+
readonly dim: "#a1a1a6";
|
|
7
|
+
readonly accent: "#3b82f6";
|
|
8
|
+
readonly accentSoft: "#60a5fa";
|
|
9
|
+
readonly border: "#48484a";
|
|
10
|
+
readonly userBg: "#3a3a3c";
|
|
11
|
+
readonly userText: "#f5f5f7";
|
|
12
|
+
readonly systemText: "#8e8e93";
|
|
13
|
+
readonly toolPendingBg: "#2c2c2e";
|
|
14
|
+
readonly toolSuccessBg: "#1e2a22";
|
|
15
|
+
readonly toolErrorBg: "#2a2222";
|
|
16
|
+
readonly toolTitle: "#3b82f6";
|
|
17
|
+
readonly toolOutput: "#d1d1d6";
|
|
18
|
+
readonly quote: "#60a5fa";
|
|
19
|
+
readonly quoteBorder: "#48484a";
|
|
20
|
+
readonly code: "#d1d1d6";
|
|
21
|
+
readonly codeBlock: "#1c1c1e";
|
|
22
|
+
readonly codeBorder: "#48484a";
|
|
23
|
+
readonly link: "#60a5fa";
|
|
24
|
+
readonly error: "#f87171";
|
|
25
|
+
readonly success: "#34d399";
|
|
26
|
+
} | {
|
|
27
|
+
readonly text: "#1d1d1f";
|
|
28
|
+
readonly dim: "#6e6e73";
|
|
29
|
+
readonly accent: "#2563eb";
|
|
30
|
+
readonly accentSoft: "#3b82f6";
|
|
31
|
+
readonly border: "#d2d2d7";
|
|
32
|
+
readonly userBg: "#ffffff";
|
|
33
|
+
readonly userText: "#1d1d1f";
|
|
34
|
+
readonly systemText: "#86868b";
|
|
35
|
+
readonly toolPendingBg: "#f0f5ff";
|
|
36
|
+
readonly toolSuccessBg: "#ecfdf5";
|
|
37
|
+
readonly toolErrorBg: "#fef2f2";
|
|
38
|
+
readonly toolTitle: "#2563eb";
|
|
39
|
+
readonly toolOutput: "#6e6e73";
|
|
40
|
+
readonly quote: "#2563eb";
|
|
41
|
+
readonly quoteBorder: "#d2d2d7";
|
|
42
|
+
readonly code: "#92400e";
|
|
43
|
+
readonly codeBlock: "#ffffff";
|
|
44
|
+
readonly codeBorder: "#d2d2d7";
|
|
45
|
+
readonly link: "#2563eb";
|
|
46
|
+
readonly error: "#dc2626";
|
|
47
|
+
readonly success: "#059669";
|
|
48
|
+
};
|
|
49
|
+
export declare const theme: {
|
|
50
|
+
fg: (text: string) => string;
|
|
51
|
+
assistantText: (text: string) => string;
|
|
52
|
+
dim: (text: string) => string;
|
|
53
|
+
accent: (text: string) => string;
|
|
54
|
+
accentSoft: (text: string) => string;
|
|
55
|
+
success: (text: string) => string;
|
|
56
|
+
error: (text: string) => string;
|
|
57
|
+
header: (text: string) => string;
|
|
58
|
+
system: (text: string) => string;
|
|
59
|
+
userBg: (text: string) => string;
|
|
60
|
+
userText: (text: string) => string;
|
|
61
|
+
toolTitle: (text: string) => string;
|
|
62
|
+
toolOutput: (text: string) => string;
|
|
63
|
+
toolPendingBg: (text: string) => string;
|
|
64
|
+
toolSuccessBg: (text: string) => string;
|
|
65
|
+
toolErrorBg: (text: string) => string;
|
|
66
|
+
border: (text: string) => string;
|
|
67
|
+
bold: (text: string) => string;
|
|
68
|
+
italic: (text: string) => string;
|
|
69
|
+
};
|
|
70
|
+
export declare const markdownTheme: MarkdownTheme;
|
|
71
|
+
export declare const selectListTheme: SelectListTheme;
|
|
72
|
+
export declare const searchableSelectListTheme: SearchableSelectListTheme;
|
|
73
|
+
export declare const editorTheme: EditorTheme;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
//#region src/tui/theme.ts
|
|
3
|
+
const XTERM_LEVELS = [
|
|
4
|
+
0,
|
|
5
|
+
95,
|
|
6
|
+
135,
|
|
7
|
+
175,
|
|
8
|
+
215,
|
|
9
|
+
255
|
|
10
|
+
];
|
|
11
|
+
function channelToSrgb(value) {
|
|
12
|
+
const normalized = value / 255;
|
|
13
|
+
return normalized <= .03928 ? normalized / 12.92 : ((normalized + .055) / 1.055) ** 2.4;
|
|
14
|
+
}
|
|
15
|
+
function relativeLuminanceRgb(red, green, blue) {
|
|
16
|
+
return .2126 * channelToSrgb(red) + .7152 * channelToSrgb(green) + .0722 * channelToSrgb(blue);
|
|
17
|
+
}
|
|
18
|
+
function relativeLuminanceHex(hex) {
|
|
19
|
+
return relativeLuminanceRgb(Number.parseInt(hex.slice(1, 3), 16), Number.parseInt(hex.slice(3, 5), 16), Number.parseInt(hex.slice(5, 7), 16));
|
|
20
|
+
}
|
|
21
|
+
function contrastRatio(bgLuminance, fgHex) {
|
|
22
|
+
const fgLuminance = relativeLuminanceHex(fgHex);
|
|
23
|
+
const lighter = Math.max(bgLuminance, fgLuminance);
|
|
24
|
+
const darker = Math.min(bgLuminance, fgLuminance);
|
|
25
|
+
return (lighter + .05) / (darker + .05);
|
|
26
|
+
}
|
|
27
|
+
function isLightBackground() {
|
|
28
|
+
const explicit = (process.env.XOPC_THEME ?? "").toLowerCase().trim();
|
|
29
|
+
if (explicit === "light") return true;
|
|
30
|
+
if (explicit === "dark") return false;
|
|
31
|
+
const colorfgbg = process.env.COLORFGBG;
|
|
32
|
+
if (colorfgbg && colorfgbg.length <= 64) {
|
|
33
|
+
const sep = colorfgbg.lastIndexOf(";");
|
|
34
|
+
const bg = Number.parseInt(sep >= 0 ? colorfgbg.slice(sep + 1) : colorfgbg, 10);
|
|
35
|
+
if (bg >= 0 && bg <= 255) {
|
|
36
|
+
if (bg <= 15) return bg === 7 || bg === 15;
|
|
37
|
+
if (bg >= 232) return bg >= 244;
|
|
38
|
+
const cubeIndex = bg - 16;
|
|
39
|
+
const bVal = XTERM_LEVELS[cubeIndex % 6];
|
|
40
|
+
const gVal = XTERM_LEVELS[Math.floor(cubeIndex / 6) % 6];
|
|
41
|
+
const rVal = XTERM_LEVELS[Math.floor(cubeIndex / 36)];
|
|
42
|
+
const bgLum = relativeLuminanceRgb(rVal, gVal, bVal);
|
|
43
|
+
return contrastRatio(bgLum, "#1d1d1f") >= contrastRatio(bgLum, "#f5f5f7");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const lightMode = isLightBackground();
|
|
49
|
+
const palette = lightMode ? {
|
|
50
|
+
text: "#1d1d1f",
|
|
51
|
+
dim: "#6e6e73",
|
|
52
|
+
accent: "#2563eb",
|
|
53
|
+
accentSoft: "#3b82f6",
|
|
54
|
+
border: "#d2d2d7",
|
|
55
|
+
userBg: "#ffffff",
|
|
56
|
+
userText: "#1d1d1f",
|
|
57
|
+
systemText: "#86868b",
|
|
58
|
+
toolPendingBg: "#f0f5ff",
|
|
59
|
+
toolSuccessBg: "#ecfdf5",
|
|
60
|
+
toolErrorBg: "#fef2f2",
|
|
61
|
+
toolTitle: "#2563eb",
|
|
62
|
+
toolOutput: "#6e6e73",
|
|
63
|
+
quote: "#2563eb",
|
|
64
|
+
quoteBorder: "#d2d2d7",
|
|
65
|
+
code: "#92400e",
|
|
66
|
+
codeBlock: "#ffffff",
|
|
67
|
+
codeBorder: "#d2d2d7",
|
|
68
|
+
link: "#2563eb",
|
|
69
|
+
error: "#dc2626",
|
|
70
|
+
success: "#059669"
|
|
71
|
+
} : {
|
|
72
|
+
text: "#f5f5f7",
|
|
73
|
+
dim: "#a1a1a6",
|
|
74
|
+
accent: "#3b82f6",
|
|
75
|
+
accentSoft: "#60a5fa",
|
|
76
|
+
border: "#48484a",
|
|
77
|
+
userBg: "#3a3a3c",
|
|
78
|
+
userText: "#f5f5f7",
|
|
79
|
+
systemText: "#8e8e93",
|
|
80
|
+
toolPendingBg: "#2c2c2e",
|
|
81
|
+
toolSuccessBg: "#1e2a22",
|
|
82
|
+
toolErrorBg: "#2a2222",
|
|
83
|
+
toolTitle: "#3b82f6",
|
|
84
|
+
toolOutput: "#d1d1d6",
|
|
85
|
+
quote: "#60a5fa",
|
|
86
|
+
quoteBorder: "#48484a",
|
|
87
|
+
code: "#d1d1d6",
|
|
88
|
+
codeBlock: "#1c1c1e",
|
|
89
|
+
codeBorder: "#48484a",
|
|
90
|
+
link: "#60a5fa",
|
|
91
|
+
error: "#f87171",
|
|
92
|
+
success: "#34d399"
|
|
93
|
+
};
|
|
94
|
+
const fg = (hex) => (text) => chalk.hex(hex)(text);
|
|
95
|
+
const bg = (hex) => (text) => chalk.bgHex(hex)(text);
|
|
96
|
+
function highlightCode(code) {
|
|
97
|
+
return code.split("\n").map((line) => fg(palette.code)(line));
|
|
98
|
+
}
|
|
99
|
+
const theme = {
|
|
100
|
+
fg: fg(palette.text),
|
|
101
|
+
assistantText: (text) => text,
|
|
102
|
+
dim: fg(palette.dim),
|
|
103
|
+
accent: fg(palette.accent),
|
|
104
|
+
accentSoft: fg(palette.accentSoft),
|
|
105
|
+
success: fg(palette.success),
|
|
106
|
+
error: fg(palette.error),
|
|
107
|
+
header: (text) => chalk.bold(fg(palette.accent)(text)),
|
|
108
|
+
system: fg(palette.systemText),
|
|
109
|
+
userBg: bg(palette.userBg),
|
|
110
|
+
userText: fg(palette.userText),
|
|
111
|
+
toolTitle: fg(palette.toolTitle),
|
|
112
|
+
toolOutput: fg(palette.toolOutput),
|
|
113
|
+
toolPendingBg: bg(palette.toolPendingBg),
|
|
114
|
+
toolSuccessBg: bg(palette.toolSuccessBg),
|
|
115
|
+
toolErrorBg: bg(palette.toolErrorBg),
|
|
116
|
+
border: fg(palette.border),
|
|
117
|
+
bold: (text) => chalk.bold(text),
|
|
118
|
+
italic: (text) => chalk.italic(text)
|
|
119
|
+
};
|
|
120
|
+
const markdownTheme = {
|
|
121
|
+
heading: (text) => chalk.bold(fg(palette.accent)(text)),
|
|
122
|
+
link: (text) => fg(palette.link)(text),
|
|
123
|
+
linkUrl: (text) => chalk.dim(text),
|
|
124
|
+
code: (text) => fg(palette.code)(text),
|
|
125
|
+
codeBlock: (text) => fg(palette.code)(text),
|
|
126
|
+
codeBlockBorder: (text) => fg(palette.codeBorder)(text),
|
|
127
|
+
quote: (text) => fg(palette.quote)(text),
|
|
128
|
+
quoteBorder: (text) => fg(palette.quoteBorder)(text),
|
|
129
|
+
hr: (text) => fg(palette.border)(text),
|
|
130
|
+
listBullet: (text) => fg(palette.accentSoft)(text),
|
|
131
|
+
bold: (text) => chalk.bold(text),
|
|
132
|
+
italic: (text) => chalk.italic(text),
|
|
133
|
+
strikethrough: (text) => chalk.strikethrough(text),
|
|
134
|
+
underline: (text) => chalk.underline(text),
|
|
135
|
+
highlightCode
|
|
136
|
+
};
|
|
137
|
+
const selectListTheme = {
|
|
138
|
+
selectedPrefix: (text) => fg(palette.accent)(text),
|
|
139
|
+
selectedText: (text) => chalk.bold(fg(palette.accent)(text)),
|
|
140
|
+
description: (text) => fg(palette.dim)(text),
|
|
141
|
+
scrollInfo: (text) => fg(palette.dim)(text),
|
|
142
|
+
noMatch: (text) => fg(palette.dim)(text)
|
|
143
|
+
};
|
|
144
|
+
const searchableSelectListTheme = {
|
|
145
|
+
...selectListTheme,
|
|
146
|
+
searchPrompt: (text) => fg(palette.dim)(text),
|
|
147
|
+
searchInput: (text) => fg(palette.text)(text),
|
|
148
|
+
matchHighlight: (text) => fg(palette.accentSoft)(text)
|
|
149
|
+
};
|
|
150
|
+
const editorTheme = {
|
|
151
|
+
borderColor: (text) => fg(palette.border)(text),
|
|
152
|
+
selectList: selectListTheme
|
|
153
|
+
};
|
|
154
|
+
//#endregion
|
|
155
|
+
export { editorTheme, lightMode, markdownTheme, palette, searchableSelectListTheme, selectListTheme, theme };
|
|
156
|
+
|
|
157
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","names":[],"sources":["../../../src/tui/theme.ts"],"sourcesContent":["import type { EditorTheme, MarkdownTheme, SelectListTheme } from '@mariozechner/pi-tui';\nimport type { SearchableSelectListTheme } from './components/searchable-select-list.js';\nimport chalk from 'chalk';\n\nconst XTERM_LEVELS = [0, 95, 135, 175, 215, 255] as const;\n\nfunction channelToSrgb(value: number): number {\n const normalized = value / 255;\n return normalized <= 0.03928\n ? normalized / 12.92\n : ((normalized + 0.055) / 1.055) ** 2.4;\n}\n\nfunction relativeLuminanceRgb(red: number, green: number, blue: number): number {\n return (\n 0.2126 * channelToSrgb(red) +\n 0.7152 * channelToSrgb(green) +\n 0.0722 * channelToSrgb(blue)\n );\n}\n\nfunction relativeLuminanceHex(hex: string): number {\n return relativeLuminanceRgb(\n Number.parseInt(hex.slice(1, 3), 16),\n Number.parseInt(hex.slice(3, 5), 16),\n Number.parseInt(hex.slice(5, 7), 16),\n );\n}\n\nfunction contrastRatio(bgLuminance: number, fgHex: string): number {\n const fgLuminance = relativeLuminanceHex(fgHex);\n const lighter = Math.max(bgLuminance, fgLuminance);\n const darker = Math.min(bgLuminance, fgLuminance);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\nfunction isLightBackground(): boolean {\n const explicit = (process.env.XOPC_THEME ?? '').toLowerCase().trim();\n if (explicit === 'light') return true;\n if (explicit === 'dark') return false;\n\n const colorfgbg = process.env.COLORFGBG;\n if (colorfgbg && colorfgbg.length <= 64) {\n const sep = colorfgbg.lastIndexOf(';');\n const bg = Number.parseInt(sep >= 0 ? colorfgbg.slice(sep + 1) : colorfgbg, 10);\n if (bg >= 0 && bg <= 255) {\n if (bg <= 15) return bg === 7 || bg === 15;\n if (bg >= 232) return bg >= 244;\n const cubeIndex = bg - 16;\n const bVal = XTERM_LEVELS[cubeIndex % 6]!;\n const gVal = XTERM_LEVELS[Math.floor(cubeIndex / 6) % 6]!;\n const rVal = XTERM_LEVELS[Math.floor(cubeIndex / 36)]!;\n const bgLum = relativeLuminanceRgb(rVal, gVal, bVal);\n return (\n contrastRatio(bgLum, '#1d1d1f') >= contrastRatio(bgLum, '#f5f5f7')\n );\n }\n }\n return false;\n}\n\nexport const lightMode = isLightBackground();\n\n// Palette tokens align with DESIGN.md (§2 surface/text/border, §2.5 accent, §12.1).\nconst darkPalette = {\n text: '#f5f5f7',\n dim: '#a1a1a6',\n accent: '#3b82f6',\n accentSoft: '#60a5fa',\n border: '#48484a',\n userBg: '#3a3a3c',\n userText: '#f5f5f7',\n systemText: '#8e8e93',\n toolPendingBg: '#2c2c2e',\n toolSuccessBg: '#1e2a22',\n toolErrorBg: '#2a2222',\n toolTitle: '#3b82f6',\n toolOutput: '#d1d1d6',\n quote: '#60a5fa',\n quoteBorder: '#48484a',\n code: '#d1d1d6',\n codeBlock: '#1c1c1e',\n codeBorder: '#48484a',\n link: '#60a5fa',\n error: '#f87171',\n success: '#34d399',\n} as const;\n\nconst lightPalette = {\n text: '#1d1d1f',\n dim: '#6e6e73',\n accent: '#2563eb',\n accentSoft: '#3b82f6',\n border: '#d2d2d7',\n userBg: '#ffffff',\n userText: '#1d1d1f',\n systemText: '#86868b',\n toolPendingBg: '#f0f5ff',\n toolSuccessBg: '#ecfdf5',\n toolErrorBg: '#fef2f2',\n toolTitle: '#2563eb',\n toolOutput: '#6e6e73',\n quote: '#2563eb',\n quoteBorder: '#d2d2d7',\n code: '#92400e',\n codeBlock: '#ffffff',\n codeBorder: '#d2d2d7',\n link: '#2563eb',\n error: '#dc2626',\n success: '#059669',\n} as const;\n\nexport const palette = lightMode ? lightPalette : darkPalette;\n\nconst fg = (hex: string) => (text: string) => chalk.hex(hex)(text);\nconst bg = (hex: string) => (text: string) => chalk.bgHex(hex)(text);\n\nfunction highlightCode(code: string): string[] {\n return code.split('\\n').map((line) => fg(palette.code)(line));\n}\n\nexport const theme = {\n fg: fg(palette.text),\n assistantText: (text: string) => text,\n dim: fg(palette.dim),\n accent: fg(palette.accent),\n accentSoft: fg(palette.accentSoft),\n success: fg(palette.success),\n error: fg(palette.error),\n header: (text: string) => chalk.bold(fg(palette.accent)(text)),\n system: fg(palette.systemText),\n userBg: bg(palette.userBg),\n userText: fg(palette.userText),\n toolTitle: fg(palette.toolTitle),\n toolOutput: fg(palette.toolOutput),\n toolPendingBg: bg(palette.toolPendingBg),\n toolSuccessBg: bg(palette.toolSuccessBg),\n toolErrorBg: bg(palette.toolErrorBg),\n border: fg(palette.border),\n bold: (text: string) => chalk.bold(text),\n italic: (text: string) => chalk.italic(text),\n};\n\nexport const markdownTheme: MarkdownTheme = {\n heading: (text) => chalk.bold(fg(palette.accent)(text)),\n link: (text) => fg(palette.link)(text),\n linkUrl: (text) => chalk.dim(text),\n code: (text) => fg(palette.code)(text),\n codeBlock: (text) => fg(palette.code)(text),\n codeBlockBorder: (text) => fg(palette.codeBorder)(text),\n quote: (text) => fg(palette.quote)(text),\n quoteBorder: (text) => fg(palette.quoteBorder)(text),\n hr: (text) => fg(palette.border)(text),\n listBullet: (text) => fg(palette.accentSoft)(text),\n bold: (text) => chalk.bold(text),\n italic: (text) => chalk.italic(text),\n strikethrough: (text) => chalk.strikethrough(text),\n underline: (text) => chalk.underline(text),\n highlightCode,\n};\n\nexport const selectListTheme: SelectListTheme = {\n selectedPrefix: (text) => fg(palette.accent)(text),\n selectedText: (text) => chalk.bold(fg(palette.accent)(text)),\n description: (text) => fg(palette.dim)(text),\n scrollInfo: (text) => fg(palette.dim)(text),\n noMatch: (text) => fg(palette.dim)(text),\n};\n\nexport const searchableSelectListTheme: SearchableSelectListTheme = {\n ...selectListTheme,\n searchPrompt: (text) => fg(palette.dim)(text),\n searchInput: (text) => fg(palette.text)(text),\n matchHighlight: (text) => fg(palette.accentSoft)(text),\n};\n\nexport const editorTheme: EditorTheme = {\n borderColor: (text) => fg(palette.border)(text),\n selectList: selectListTheme,\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TUI } from '@mariozechner/pi-tui';
|
|
2
|
+
import type { ChatLog } from './components/chat-log.js';
|
|
3
|
+
import type { StreamAssembler } from './stream-assembler.js';
|
|
4
|
+
import type { TuiState } from './tui-types.js';
|
|
5
|
+
export declare function clearPendingToolCallIds(): void;
|
|
6
|
+
export declare function dispatchAgentSSE(event: string, data: Record<string, unknown>, state: TuiState, chatLog: ChatLog, assembler: StreamAssembler, tui: TUI, setActivityStatus: (status: string) => void, touchStreamingActivity?: () => void): void;
|
|
7
|
+
export declare const DEFAULT_STREAMING_WATCHDOG_MS = 30000;
|