@akon-labs/nexus-cli 0.1.10 → 0.1.11
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/cli/require-login.d.ts.map +1 -1
- package/dist/cli/require-login.js +2 -2
- package/dist/cli/require-login.js.map +1 -1
- package/dist/cli.js +2492 -1088
- package/dist/core/agent-session.d.ts +3 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +4 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +6 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +7 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +14 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +18 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/graph-rail-store.d.ts +10 -0
- package/dist/core/graph-rail-store.d.ts.map +1 -1
- package/dist/core/graph-rail-store.js +9 -0
- package/dist/core/graph-rail-store.js.map +1 -1
- package/dist/core/keybindings.d.ts +2 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +4 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/extensions/gitnexus/client.d.ts.map +1 -1
- package/dist/extensions/gitnexus/client.js +45 -14
- package/dist/extensions/gitnexus/client.js.map +1 -1
- package/dist/extensions/gitnexus/config.d.ts +15 -1
- package/dist/extensions/gitnexus/config.d.ts.map +1 -1
- package/dist/extensions/gitnexus/config.js +86 -2
- package/dist/extensions/gitnexus/config.js.map +1 -1
- package/dist/extensions/gitnexus/hub-api.d.ts +56 -0
- package/dist/extensions/gitnexus/hub-api.d.ts.map +1 -0
- package/dist/extensions/gitnexus/hub-api.js +105 -0
- package/dist/extensions/gitnexus/hub-api.js.map +1 -0
- package/dist/extensions/gitnexus/index-repo.d.ts +50 -0
- package/dist/extensions/gitnexus/index-repo.d.ts.map +1 -0
- package/dist/extensions/gitnexus/index-repo.js +162 -0
- package/dist/extensions/gitnexus/index-repo.js.map +1 -0
- package/dist/extensions/gitnexus/index.d.ts.map +1 -1
- package/dist/extensions/gitnexus/index.js +137 -17
- package/dist/extensions/gitnexus/index.js.map +1 -1
- package/dist/extensions/gitnexus/observatory.d.ts.map +1 -1
- package/dist/extensions/gitnexus/observatory.js +2 -2
- package/dist/extensions/gitnexus/observatory.js.map +1 -1
- package/dist/extensions/gitnexus/resolve.d.ts +9 -0
- package/dist/extensions/gitnexus/resolve.d.ts.map +1 -1
- package/dist/extensions/gitnexus/resolve.js +52 -2
- package/dist/extensions/gitnexus/resolve.js.map +1 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +3 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/mcp/commands.d.ts +22 -2
- package/dist/extensions/mcp/commands.d.ts.map +1 -1
- package/dist/extensions/mcp/commands.js +201 -9
- package/dist/extensions/mcp/commands.js.map +1 -1
- package/dist/extensions/mcp/config.d.ts +2 -0
- package/dist/extensions/mcp/config.d.ts.map +1 -1
- package/dist/extensions/mcp/config.js +6 -1
- package/dist/extensions/mcp/config.js.map +1 -1
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +54 -5
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/mcp-setup-panel.d.ts +63 -2
- package/dist/extensions/mcp/mcp-setup-panel.d.ts.map +1 -1
- package/dist/extensions/mcp/mcp-setup-panel.js +563 -77
- package/dist/extensions/mcp/mcp-setup-panel.js.map +1 -1
- package/dist/extensions/subagent/index.d.ts +2 -1
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +19 -6
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent-render.d.ts +3 -0
- package/dist/extensions/subagent-render.d.ts.map +1 -0
- package/dist/extensions/subagent-render.js +39 -0
- package/dist/extensions/subagent-render.js.map +1 -0
- package/dist/index.js +2524 -1120
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +2 -0
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/command-palette.d.ts +2 -1
- package/dist/modes/interactive/components/command-palette.d.ts.map +1 -1
- package/dist/modes/interactive/components/command-palette.js +11 -4
- package/dist/modes/interactive/components/command-palette.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +9 -3
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/graph-rail.d.ts.map +1 -1
- package/dist/modes/interactive/components/graph-rail.js +18 -3
- package/dist/modes/interactive/components/graph-rail.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts +1 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +7 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/landing-panel.d.ts.map +1 -1
- package/dist/modes/interactive/components/landing-panel.js +15 -2
- package/dist/modes/interactive/components/landing-panel.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +3 -2
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +12 -2
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +42 -8
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/rpc-entry.js +2492 -1088
- package/dist/utils/hidden-spawn.d.ts +29 -0
- package/dist/utils/hidden-spawn.d.ts.map +1 -0
- package/dist/utils/hidden-spawn.js +101 -0
- package/dist/utils/hidden-spawn.js.map +1 -0
- package/dist/vendor/ai.js +233 -233
- package/dist/vendor/tui.js +1 -1
- package/native/win32/build.mjs +95 -0
- package/native/win32/prebuilds/win32-x64/hidden-spawn.exe +0 -0
- package/native/win32/src/hidden-spawn.c +157 -0
- package/npm-shrinkwrap.json +2 -37
- package/package.json +7 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-rail.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/graph-rail.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Component } from \"@earendil-works/pi-tui\";\nimport { visibleWidth } from \"@earendil-works/pi-tui\";\nimport { type GraphRailState, graphRailStore } from \"../../../core/graph-rail-store.ts\";\nimport { diagonalFill, gradientText } from \"../theme/brand.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { NEXUS_SMALL } from \"./nexus-logo.ts\";\n\n/**\n * GitNexus side rail (fullscreen UI mode, terminals >= MIN_TERMINAL_WIDTH).\n * Renders repo status, the latest blast radius, latest flows, and session\n * changes as stacked cards. Pure view over graphRailStore.\n */\n\nexport const RAIL_WIDTH = 36;\nexport const MIN_TERMINAL_WIDTH = 110;\n\nfunction clipVisible(line: string, width: number): string {\n\tif (visibleWidth(line) <= width) return line;\n\tlet out = \"\";\n\tlet visible = 0;\n\tfor (let i = 0; i < line.length; i++) {\n\t\tif (line[i] === \"\\x1b\") {\n\t\t\tconst match = line.slice(i).match(/^\\x1b\\[[0-9;]*m/);\n\t\t\tif (match) {\n\t\t\t\tout += match[0];\n\t\t\t\ti += match[0].length - 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (visible >= width) break;\n\t\tout += line[i];\n\t\tvisible++;\n\t}\n\treturn `${out}\\x1b[0m`;\n}\n\nfunction basename(filePath: string | undefined): string {\n\tif (!filePath) return \"\";\n\treturn filePath.split(\"/\").pop() ?? filePath;\n}\n\nexport type GraphRailCard = \"status\" | \"repos\" | \"impact\" | \"flows\" | \"changes\" | \"skills\";\n\n/** Dim low-confidence graph edges below this threshold. */\nconst CONFIDENCE_DIM_THRESHOLD = 0.7;\n\nfunction formatSymbolCount(symbols: string): string {\n\tconst n = Number(symbols.replace(/,/g, \"\"));\n\tif (Number.isNaN(n)) return symbols;\n\tif (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n\tif (n >= 1_000) return `${Math.round(n / 1_000)}k`;\n\treturn String(n);\n}\n\nexport interface GraphRailSessionStatus {\n\ttitle?: string;\n\tcwd?: string;\n\tmodel?: string;\n\tprovider?: string;\n\treasoning?: string;\n\tcontext?: string;\n\tcost?: string;\n}\n\nexport interface GraphRailHostInfo {\n\tskills: string[];\n\tversion: string;\n\t/** Live session status for the crush-style sidebar header. */\n\tgetSessionStatus?: () => GraphRailSessionStatus;\n}\n\nexport class GraphRailComponent implements Component {\n\t/** Set by the host: invoked when a card is clicked (fullscreen mouse routing). */\n\tonCardClick: ((card: GraphRailCard) => void) | undefined;\n\n\tprivate hostInfo: GraphRailHostInfo | undefined;\n\n\tsetHostInfo(info: GraphRailHostInfo): void {\n\t\tthis.hostInfo = info;\n\t}\n\n\tgetHostInfo(): GraphRailHostInfo | undefined {\n\t\treturn this.hostInfo;\n\t}\n\n\tprivate cardRanges: Array<{ start: number; end: number; card: GraphRailCard }> = [];\n\n\tinvalidate(): void {\n\t\t// Stateless view over graphRailStore — nothing cached.\n\t}\n\n\thandleClick(_x: number, y: number): boolean {\n\t\tconst hit = this.cardRanges.find((range) => y >= range.start && y < range.end);\n\t\tif (!hit || !this.onCardClick) return false;\n\t\tthis.onCardClick(hit.card);\n\t\treturn true;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width < 20) return [];\n\t\tconst inner = Math.min(width, RAIL_WIDTH) - 2;\n\t\tconst s = graphRailStore.getState();\n\t\tconst lines: string[] = [];\n\t\tthis.cardRanges = [];\n\t\tlet cardStart = 0;\n\t\tconst beginCard = () => {\n\t\t\tcardStart = lines.length;\n\t\t};\n\t\tconst commitCard = (card: GraphRailCard) => {\n\t\t\tthis.cardRanges.push({ start: cardStart, end: lines.length, card });\n\t\t};\n\t\t// Crush-style section header: `Title ────────` (no card frames).\n\t\tconst rule = (title: string) =>\n\t\t\tlines.push(\n\t\t\t\t`${theme.fg(\"muted\", title)} ${theme.fg(\"dim\", \"─\".repeat(Math.max(0, inner - [...title].length - 1)))}`,\n\t\t\t);\n\t\tconst row = (text: string) => lines.push(clipVisible(text, inner));\n\t\tconst end = () => lines.push(\"\");\n\n\t\t// Logo band (small crush-style: hatch, wordmark, version).\n\t\tconst hatch = diagonalFill(inner + 2);\n\t\tlines.push(hatch);\n\t\tfor (const logoLine of NEXUS_SMALL) lines.push(` ${gradientText(logoLine)}`);\n\t\tif (this.hostInfo?.version) {\n\t\t\tlines.push(` ${theme.fg(\"muted\", `v${this.hostInfo.version}`)}`);\n\t\t}\n\t\tlines.push(hatch);\n\t\tlines.push(\"\");\n\n\t\t// Session header: title, cwd, model block (crush sidebar order).\n\t\tconst status = this.hostInfo?.getSessionStatus?.();\n\t\tif (status) {\n\t\t\tif (status.title) {\n\t\t\t\trow(theme.bold(status.title));\n\t\t\t\tlines.push(\"\");\n\t\t\t}\n\t\t\tif (status.cwd) {\n\t\t\t\trow(theme.fg(\"muted\", status.cwd));\n\t\t\t\tlines.push(\"\");\n\t\t\t}\n\t\t\tif (status.model) {\n\t\t\t\trow(\n\t\t\t\t\t`${theme.fg(\"muted\", \"◇\")} ${theme.bold(status.model)}${status.provider ? theme.fg(\"muted\", ` via ${status.provider}`) : \"\"}`,\n\t\t\t\t);\n\t\t\t\tif (status.reasoning) row(` ${theme.fg(\"muted\", `Reasoning ${status.reasoning}`)}`);\n\t\t\t\tif (status.context || status.cost) {\n\t\t\t\t\trow(` ${theme.fg(\"muted\", [status.context, status.cost].filter(Boolean).join(\" \"))}`);\n\t\t\t\t}\n\t\t\t\tlines.push(\"\");\n\t\t\t}\n\t\t}\n\n\t\tbeginCard();\n\t\tthis.renderChanges(s, rule, row, end);\n\t\tcommitCard(\"changes\");\n\t\tbeginCard();\n\t\tthis.renderStatus(s, rule, row, end);\n\t\tcommitCard(\"status\");\n\t\tbeginCard();\n\t\tthis.renderRepos(s, rule, row, end);\n\t\tcommitCard(\"repos\");\n\t\tbeginCard();\n\t\tthis.renderImpact(s, rule, row, end);\n\t\tcommitCard(\"impact\");\n\t\tbeginCard();\n\t\tthis.renderQuery(s, rule, row, end);\n\t\tcommitCard(\"flows\");\n\t\tbeginCard();\n\t\tthis.renderSkills(rule, row, end);\n\t\tcommitCard(\"skills\");\n\t\treturn lines;\n\t}\n\n\tprivate renderRepos(\n\t\ts: Readonly<GraphRailState>,\n\t\trule: (t: string) => void,\n\t\trow: (t: string) => void,\n\t\tend: () => void,\n\t): void {\n\t\tif (s.repos.length === 0) return;\n\t\trule(\"Repos\");\n\t\tconst activeName = s.repo?.name;\n\t\tfor (const repo of s.repos.slice(0, 5)) {\n\t\t\tconst short = repo.name.split(\"/\").pop() ?? repo.name;\n\t\t\tconst count = theme.fg(\"muted\", formatSymbolCount(repo.symbols));\n\t\t\tif (repo.name === activeName) {\n\t\t\t\trow(`${theme.fg(\"accent\", \"●\")} ${theme.fg(\"accent\", short)} ${count}`);\n\t\t\t} else {\n\t\t\t\trow(`${theme.fg(\"muted\", \"○\")} ${theme.fg(\"muted\", short)} ${count}`);\n\t\t\t}\n\t\t}\n\t\tif (s.repos.length > 5) row(theme.fg(\"muted\", ` … +${s.repos.length - 5} more`));\n\t\tend();\n\t}\n\n\tprivate renderStatus(\n\t\ts: Readonly<GraphRailState>,\n\t\trule: (t: string) => void,\n\t\trow: (t: string) => void,\n\t\tend: () => void,\n\t): void {\n\t\trule(\"GitNexus\");\n\t\tif (!s.repo) {\n\t\t\trow(theme.fg(\"muted\", \"not connected\"));\n\t\t\tend();\n\t\t\treturn;\n\t\t}\n\t\tif (s.currentIndexed) {\n\t\t\trow(theme.bold(s.repo.name.split(\"/\").pop() ?? s.repo.name));\n\t\t\trow(theme.fg(\"muted\", `${s.repo.symbols} symbols · ${s.repo.repoCount} repos`));\n\t\t\trow(theme.fg(\"muted\", `indexed ${s.repo.indexedAt.split(\" GMT\")[0] ?? s.repo.indexedAt}`));\n\t\t} else {\n\t\t\trow(theme.fg(\"warning\", \"repo not indexed\"));\n\t\t\trow(theme.fg(\"muted\", `${s.repo.repoCount} repos queryable`));\n\t\t}\n\t\trow(theme.fg(\"muted\", `graph calls ${s.graphCalls} · impact ${s.impactChecks}`));\n\t\tend();\n\t}\n\n\tprivate renderImpact(\n\t\ts: Readonly<GraphRailState>,\n\t\trule: (t: string) => void,\n\t\trow: (t: string) => void,\n\t\tend: () => void,\n\t): void {\n\t\tconst impact = s.impact;\n\t\tif (!impact) return;\n\t\trule(\"Blast Radius\");\n\t\tconst risk = impact.risk.toUpperCase();\n\t\tconst riskColor = risk === \"HIGH\" || risk === \"CRITICAL\" ? \"error\" : risk === \"MEDIUM\" ? \"warning\" : \"success\";\n\t\trow(`${theme.fg(\"accent\", \"◉\")} ${theme.bold(impact.target)}`);\n\t\trow(theme.fg(riskColor, `risk: ${risk}`));\n\t\tconst depths = Object.keys(impact.byDepth)\n\t\t\t.map(Number)\n\t\t\t.filter((d) => !Number.isNaN(d))\n\t\t\t.sort((a, b) => a - b);\n\t\tfor (const depth of depths.slice(0, 3)) {\n\t\t\tconst nodes = impact.byDepth[String(depth)] ?? [];\n\t\t\tif (nodes.length === 0) continue;\n\t\t\tconst color = depth === 1 ? \"error\" : depth === 2 ? \"warning\" : \"muted\";\n\t\t\tconst label = depth === 1 ? \"breaks\" : depth === 2 ? \"test\" : \"transitive\";\n\t\t\trow(theme.fg(color, `d${depth} ${label} (${nodes.length})`));\n\t\t\tfor (const node of nodes.slice(0, 3)) {\n\t\t\t\tconst lowConfidence = node.confidence !== undefined && node.confidence < CONFIDENCE_DIM_THRESHOLD;\n\t\t\t\tconst name = lowConfidence ? theme.fg(\"dim\", `${node.name}?`) : node.name;\n\t\t\t\trow(` ${theme.fg(lowConfidence ? \"dim\" : color, depth === 1 ? \"●\" : \"○\")} ${name}`);\n\t\t\t}\n\t\t\tif (nodes.length > 3) row(theme.fg(\"muted\", ` … +${nodes.length - 3}`));\n\t\t}\n\t\tif (impact.processes.length > 0) row(theme.fg(\"muted\", `flows: ${impact.processes.slice(0, 2).join(\", \")}`));\n\t\tif (impact.modules.length > 0) {\n\t\t\tconst maxHits = Math.max(...impact.modules.map((m) => m.hits), 1);\n\t\t\tfor (const module of impact.modules.slice(0, 3)) {\n\t\t\t\tconst filled = Math.max(1, Math.round((module.hits / maxHits) * 5));\n\t\t\t\tconst bar =\n\t\t\t\t\ttheme.fg(module.direct ? \"accent\" : \"muted\", \"▮\".repeat(filled)) +\n\t\t\t\t\ttheme.fg(\"dim\", \"▯\".repeat(5 - filled));\n\t\t\t\trow(`${bar} ${theme.fg(\"muted\", module.name)} ${theme.fg(\"dim\", String(module.hits))}`);\n\t\t\t}\n\t\t}\n\t\tend();\n\t}\n\n\tprivate renderQuery(\n\t\ts: Readonly<GraphRailState>,\n\t\trule: (t: string) => void,\n\t\trow: (t: string) => void,\n\t\tend: () => void,\n\t): void {\n\t\tconst query = s.query;\n\t\tif (!query) return;\n\t\trule(\"Flows\");\n\t\trow(theme.fg(\"muted\", clipQuery(query.query)));\n\t\tquery.flows.slice(0, 3).forEach((flow, i) => {\n\t\t\tconst marker = i === 0 ? theme.fg(\"accent\", \"◉\") : theme.fg(\"muted\", \"○\");\n\t\t\tconst steps = flow.stepCount ? theme.fg(\"muted\", ` ·${flow.stepCount}`) : \"\";\n\t\t\trow(`${marker} ${flow.summary}${steps}`);\n\t\t});\n\t\tend();\n\t}\n\n\tprivate renderSkills(rule: (t: string) => void, row: (t: string) => void, end: () => void): void {\n\t\tconst skills = this.hostInfo?.skills ?? [];\n\t\tif (skills.length === 0) return;\n\t\trule(\"Skills\");\n\t\tfor (const skill of skills.slice(0, 8)) {\n\t\t\trow(`${theme.fg(\"success\", \"\\u25cf\")} ${theme.fg(\"muted\", skill)}`);\n\t\t}\n\t\tif (skills.length > 8) row(theme.fg(\"muted\", ` \\u2026 +${skills.length - 8} more`));\n\t\tend();\n\t}\n\n\tprivate renderChanges(\n\t\ts: Readonly<GraphRailState>,\n\t\trule: (t: string) => void,\n\t\trow: (t: string) => void,\n\t\tend: () => void,\n\t): void {\n\t\trule(\"Modified Files\");\n\t\tif (s.changes.length === 0) {\n\t\t\trow(theme.fg(\"muted\", \"None\"));\n\t\t\tend();\n\t\t\treturn;\n\t\t}\n\t\tfor (const change of s.changes.slice(-5)) {\n\t\t\trow(\n\t\t\t\t`${basename(change.path)} ${theme.fg(\"success\", `+${change.added}`)} ${theme.fg(\"error\", `-${change.removed}`)}`,\n\t\t\t);\n\t\t}\n\t\tend();\n\t}\n}\n\nfunction clipQuery(query: string): string {\n\treturn query.length > 30 ? `${query.slice(0, 29)}…` : `“${query}”`;\n}\n\n/** Full-width expansion of a rail card, appended to the transcript on click. */\nexport function renderExpandedCard(card: GraphRailCard, hostInfo?: GraphRailHostInfo): string | undefined {\n\tconst s = graphRailStore.getState();\n\tconst header = (title: string) => theme.bold(theme.fg(\"accent\", `── GitNexus · ${title} ──`));\n\tif (card === \"repos\" && s.repos.length > 0) {\n\t\tconst lines: string[] = [header(\"indexed repos\")];\n\t\tfor (const repo of s.repos) {\n\t\t\tconst marker = repo.name === s.repo?.name ? theme.fg(\"accent\", \"●\") : theme.fg(\"muted\", \"○\");\n\t\t\tlines.push(`${marker} ${repo.name} ${theme.fg(\"muted\", `${repo.symbols} symbols`)}`);\n\t\t}\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (card === \"skills\" && hostInfo && hostInfo.skills.length > 0) {\n\t\tconst lines: string[] = [header(\"skills\")];\n\t\tfor (const skill of hostInfo.skills) {\n\t\t\tlines.push(`${theme.fg(\"success\", \"●\")} ${skill}`);\n\t\t}\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (card === \"impact\" && s.impact) {\n\t\tconst lines: string[] = [header(\"blast radius\")];\n\t\tconst risk = s.impact.risk.toUpperCase();\n\t\tconst riskColor = risk === \"HIGH\" || risk === \"CRITICAL\" ? \"error\" : risk === \"MEDIUM\" ? \"warning\" : \"success\";\n\t\tlines.push(\n\t\t\t`${theme.fg(\"accent\", \"◉\")} ${theme.bold(s.impact.target)} ${theme.fg(\"muted\", s.impact.filePath ?? \"\")} ${theme.bold(theme.fg(riskColor, `RISK: ${risk}`))}`,\n\t\t);\n\t\tconst depths = Object.keys(s.impact.byDepth)\n\t\t\t.map(Number)\n\t\t\t.filter((d) => !Number.isNaN(d))\n\t\t\t.sort((a, b) => a - b);\n\t\tfor (const depth of depths) {\n\t\t\tconst nodes = s.impact.byDepth[String(depth)] ?? [];\n\t\t\tif (nodes.length === 0) continue;\n\t\t\tconst color = depth === 1 ? \"error\" : depth === 2 ? \"warning\" : \"muted\";\n\t\t\tconst label = depth === 1 ? \"WILL BREAK\" : depth === 2 ? \"should test\" : \"transitive\";\n\t\t\tlines.push(theme.fg(color, `d=${depth} ${label} (${nodes.length})`));\n\t\t\tfor (const node of nodes) {\n\t\t\t\tconst rel = node.relationType ? theme.fg(\"muted\", ` (${node.relationType})`) : \"\";\n\t\t\t\tlines.push(\n\t\t\t\t\t` ${theme.fg(color, depth === 1 ? \"●\" : \"○\")} ${node.name} ${theme.fg(\"muted\", node.filePath ?? \"\")}${rel}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (s.impact.processes.length > 0)\n\t\t\tlines.push(theme.fg(\"muted\", `flows affected: ${s.impact.processes.join(\", \")}`));\n\t\tif (s.impact.modules.length > 0)\n\t\t\tlines.push(\n\t\t\t\ttheme.fg(\n\t\t\t\t\t\"muted\",\n\t\t\t\t\t`modules: ${s.impact.modules.map((m) => `${m.name} (${m.hits}${m.direct ? \", direct\" : \"\"})`).join(\", \")}`,\n\t\t\t\t),\n\t\t\t);\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (card === \"flows\" && s.query) {\n\t\tconst lines: string[] = [header(\"flows\"), theme.fg(\"muted\", `query: “${s.query.query}”`)];\n\t\ts.query.flows.forEach((flow, i) => {\n\t\t\tconst marker = i === 0 ? theme.fg(\"accent\", \"◉\") : theme.fg(\"muted\", \"○\");\n\t\t\tlines.push(\n\t\t\t\t`${marker} ${flow.summary}${flow.stepCount ? theme.fg(\"muted\", ` · ${flow.stepCount} steps`) : \"\"}`,\n\t\t\t);\n\t\t});\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (card === \"changes\" && s.changes.length > 0) {\n\t\tconst lines: string[] = [header(\"session changes\")];\n\t\tfor (const change of s.changes) {\n\t\t\tlines.push(\n\t\t\t\t`${theme.fg(\"success\", `+${change.added}`)} ${theme.fg(\"error\", `-${change.removed}`)} ${change.path}`,\n\t\t\t);\n\t\t}\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (card === \"status\" && s.repo) {\n\t\treturn [\n\t\t\theader(\"status\"),\n\t\t\t`repo: ${s.repo.name || \"(current dir not indexed)\"} · ${s.repo.symbols} symbols`,\n\t\t\t`indexed: ${s.repo.indexedAt || \"n/a\"} · ${s.repo.repoCount} repos on hub`,\n\t\t\t`graph calls: ${s.graphCalls} · impact checks: ${s.impactChecks}`,\n\t\t].join(\"\\n\");\n\t}\n\treturn undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"graph-rail.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/graph-rail.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Component } from \"@earendil-works/pi-tui\";\nimport { visibleWidth } from \"@earendil-works/pi-tui\";\nimport { formatCompactIndexPhase, type GraphRailState, graphRailStore } from \"../../../core/graph-rail-store.ts\";\nimport { diagonalFill, gradientText } from \"../theme/brand.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { NEXUS_SMALL } from \"./nexus-logo.ts\";\n\n/**\n * GitNexus side rail (fullscreen UI mode, terminals >= MIN_TERMINAL_WIDTH).\n * Renders repo status, the latest blast radius, latest flows, and session\n * changes as stacked cards. Pure view over graphRailStore.\n */\n\nexport const RAIL_WIDTH = 36;\nexport const MIN_TERMINAL_WIDTH = 110;\n\nfunction clipVisible(line: string, width: number): string {\n\tif (visibleWidth(line) <= width) return line;\n\tlet out = \"\";\n\tlet visible = 0;\n\tfor (let i = 0; i < line.length; i++) {\n\t\tif (line[i] === \"\\x1b\") {\n\t\t\tconst match = line.slice(i).match(/^\\x1b\\[[0-9;]*m/);\n\t\t\tif (match) {\n\t\t\t\tout += match[0];\n\t\t\t\ti += match[0].length - 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (visible >= width) break;\n\t\tout += line[i];\n\t\tvisible++;\n\t}\n\treturn `${out}\\x1b[0m`;\n}\n\nfunction basename(filePath: string | undefined): string {\n\tif (!filePath) return \"\";\n\treturn filePath.split(\"/\").pop() ?? filePath;\n}\n\nexport type GraphRailCard = \"status\" | \"repos\" | \"impact\" | \"flows\" | \"changes\" | \"skills\";\n\n/** Dim low-confidence graph edges below this threshold. */\nconst CONFIDENCE_DIM_THRESHOLD = 0.7;\n\nfunction formatSymbolCount(symbols: string): string {\n\tconst n = Number(symbols.replace(/,/g, \"\"));\n\tif (Number.isNaN(n)) return symbols;\n\tif (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n\tif (n >= 1_000) return `${Math.round(n / 1_000)}k`;\n\treturn String(n);\n}\n\nexport interface GraphRailSessionStatus {\n\ttitle?: string;\n\tcwd?: string;\n\tmodel?: string;\n\tprovider?: string;\n\treasoning?: string;\n\tcontext?: string;\n\tcost?: string;\n}\n\nexport interface GraphRailHostInfo {\n\tskills: string[];\n\tversion: string;\n\t/** Live session status for the crush-style sidebar header. */\n\tgetSessionStatus?: () => GraphRailSessionStatus;\n}\n\nexport class GraphRailComponent implements Component {\n\t/** Set by the host: invoked when a card is clicked (fullscreen mouse routing). */\n\tonCardClick: ((card: GraphRailCard) => void) | undefined;\n\n\tprivate hostInfo: GraphRailHostInfo | undefined;\n\n\tsetHostInfo(info: GraphRailHostInfo): void {\n\t\tthis.hostInfo = info;\n\t}\n\n\tgetHostInfo(): GraphRailHostInfo | undefined {\n\t\treturn this.hostInfo;\n\t}\n\n\tprivate cardRanges: Array<{ start: number; end: number; card: GraphRailCard }> = [];\n\n\tinvalidate(): void {\n\t\t// Stateless view over graphRailStore — nothing cached.\n\t}\n\n\thandleClick(_x: number, y: number): boolean {\n\t\tconst hit = this.cardRanges.find((range) => y >= range.start && y < range.end);\n\t\tif (!hit || !this.onCardClick) return false;\n\t\tthis.onCardClick(hit.card);\n\t\treturn true;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width < 20) return [];\n\t\tconst inner = Math.min(width, RAIL_WIDTH) - 2;\n\t\tconst s = graphRailStore.getState();\n\t\tconst lines: string[] = [];\n\t\tthis.cardRanges = [];\n\t\tlet cardStart = 0;\n\t\tconst beginCard = () => {\n\t\t\tcardStart = lines.length;\n\t\t};\n\t\tconst commitCard = (card: GraphRailCard) => {\n\t\t\tthis.cardRanges.push({ start: cardStart, end: lines.length, card });\n\t\t};\n\t\t// Crush-style section header: `Title ────────` (no card frames).\n\t\tconst rule = (title: string) =>\n\t\t\tlines.push(\n\t\t\t\t`${theme.fg(\"muted\", title)} ${theme.fg(\"dim\", \"─\".repeat(Math.max(0, inner - [...title].length - 1)))}`,\n\t\t\t);\n\t\tconst row = (text: string) => lines.push(clipVisible(text, inner));\n\t\tconst end = () => lines.push(\"\");\n\n\t\t// Logo band (small crush-style: hatch, wordmark, version).\n\t\tconst hatch = diagonalFill(inner + 2);\n\t\tlines.push(hatch);\n\t\tfor (const logoLine of NEXUS_SMALL) lines.push(` ${gradientText(logoLine)}`);\n\t\tif (this.hostInfo?.version) {\n\t\t\tlines.push(` ${theme.fg(\"muted\", `v${this.hostInfo.version}`)}`);\n\t\t}\n\t\tlines.push(hatch);\n\t\tlines.push(\"\");\n\n\t\t// Session header: title, cwd, model block (crush sidebar order).\n\t\tconst status = this.hostInfo?.getSessionStatus?.();\n\t\tif (status) {\n\t\t\tif (status.title) {\n\t\t\t\trow(theme.bold(status.title));\n\t\t\t\tlines.push(\"\");\n\t\t\t}\n\t\t\tif (status.cwd) {\n\t\t\t\trow(theme.fg(\"muted\", status.cwd));\n\t\t\t\tlines.push(\"\");\n\t\t\t}\n\t\t\tif (status.model) {\n\t\t\t\trow(\n\t\t\t\t\t`${theme.fg(\"muted\", \"◇\")} ${theme.bold(status.model)}${status.provider ? theme.fg(\"muted\", ` via ${status.provider}`) : \"\"}`,\n\t\t\t\t);\n\t\t\t\tif (status.reasoning) row(` ${theme.fg(\"muted\", `Reasoning ${status.reasoning}`)}`);\n\t\t\t\tif (status.context || status.cost) {\n\t\t\t\t\trow(` ${theme.fg(\"muted\", [status.context, status.cost].filter(Boolean).join(\" \"))}`);\n\t\t\t\t}\n\t\t\t\tlines.push(\"\");\n\t\t\t}\n\t\t}\n\n\t\tbeginCard();\n\t\tthis.renderChanges(s, rule, row, end);\n\t\tcommitCard(\"changes\");\n\t\tbeginCard();\n\t\tthis.renderStatus(s, inner, rule, row, end);\n\t\tcommitCard(\"status\");\n\t\tbeginCard();\n\t\tthis.renderRepos(s, rule, row, end);\n\t\tcommitCard(\"repos\");\n\t\tbeginCard();\n\t\tthis.renderImpact(s, rule, row, end);\n\t\tcommitCard(\"impact\");\n\t\tbeginCard();\n\t\tthis.renderQuery(s, rule, row, end);\n\t\tcommitCard(\"flows\");\n\t\tbeginCard();\n\t\tthis.renderSkills(rule, row, end);\n\t\tcommitCard(\"skills\");\n\t\treturn lines;\n\t}\n\n\tprivate renderRepos(\n\t\ts: Readonly<GraphRailState>,\n\t\trule: (t: string) => void,\n\t\trow: (t: string) => void,\n\t\tend: () => void,\n\t): void {\n\t\tif (s.repos.length === 0) return;\n\t\trule(\"Repos\");\n\t\tconst activeName = s.repo?.name;\n\t\tfor (const repo of s.repos.slice(0, 5)) {\n\t\t\tconst short = repo.name.split(\"/\").pop() ?? repo.name;\n\t\t\tconst count = theme.fg(\"muted\", formatSymbolCount(repo.symbols));\n\t\t\tif (repo.name === activeName) {\n\t\t\t\trow(`${theme.fg(\"accent\", \"●\")} ${theme.fg(\"accent\", short)} ${count}`);\n\t\t\t} else {\n\t\t\t\trow(`${theme.fg(\"muted\", \"○\")} ${theme.fg(\"muted\", short)} ${count}`);\n\t\t\t}\n\t\t}\n\t\tif (s.repos.length > 5) row(theme.fg(\"muted\", ` … +${s.repos.length - 5} more`));\n\t\tend();\n\t}\n\n\tprivate renderStatus(\n\t\ts: Readonly<GraphRailState>,\n\t\twidth: number,\n\t\trule: (t: string) => void,\n\t\trow: (t: string) => void,\n\t\tend: () => void,\n\t): void {\n\t\trule(\"GitNexus\");\n\t\tif (s.indexProgress) {\n\t\t\tconst progress = s.indexProgress;\n\t\t\tconst phase = formatCompactIndexPhase(progress.phase);\n\t\t\trow(theme.bold(progress.fullName.split(\"/\").pop() ?? progress.fullName));\n\t\t\tconst percent =\n\t\t\t\tprogress.percent === undefined ? undefined : Math.max(0, Math.min(100, Math.round(progress.percent)));\n\t\t\trow(\n\t\t\t\tpercent === undefined\n\t\t\t\t\t? theme.fg(\"muted\", phase)\n\t\t\t\t\t: `${theme.fg(\"muted\", phase)} ${theme.fg(\"accent\", `${percent}%`)}`,\n\t\t\t);\n\t\t\tif (percent !== undefined) {\n\t\t\t\tconst filled = Math.round((percent / 100) * width);\n\t\t\t\trow(theme.fg(\"accent\", \"━\".repeat(filled)) + theme.fg(\"dim\", \"─\".repeat(width - filled)));\n\t\t\t}\n\t\t\tend();\n\t\t\treturn;\n\t\t}\n\t\tif (!s.repo) {\n\t\t\trow(theme.fg(\"muted\", \"not connected\"));\n\t\t\tend();\n\t\t\treturn;\n\t\t}\n\t\tif (s.currentIndexed) {\n\t\t\trow(theme.bold(s.repo.name.split(\"/\").pop() ?? s.repo.name));\n\t\t\trow(theme.fg(\"muted\", `${s.repo.symbols} symbols · ${s.repo.repoCount} repos`));\n\t\t\trow(theme.fg(\"muted\", `indexed ${s.repo.indexedAt.split(\" GMT\")[0] ?? s.repo.indexedAt}`));\n\t\t} else {\n\t\t\trow(theme.fg(\"warning\", \"repo not indexed\"));\n\t\t\trow(theme.fg(\"muted\", `${s.repo.repoCount} repos queryable`));\n\t\t}\n\t\trow(theme.fg(\"muted\", `graph calls ${s.graphCalls} · impact ${s.impactChecks}`));\n\t\tend();\n\t}\n\n\tprivate renderImpact(\n\t\ts: Readonly<GraphRailState>,\n\t\trule: (t: string) => void,\n\t\trow: (t: string) => void,\n\t\tend: () => void,\n\t): void {\n\t\tconst impact = s.impact;\n\t\tif (!impact) return;\n\t\trule(\"Blast Radius\");\n\t\tconst risk = impact.risk.toUpperCase();\n\t\tconst riskColor = risk === \"HIGH\" || risk === \"CRITICAL\" ? \"error\" : risk === \"MEDIUM\" ? \"warning\" : \"success\";\n\t\trow(`${theme.fg(\"accent\", \"◉\")} ${theme.bold(impact.target)}`);\n\t\trow(theme.fg(riskColor, `risk: ${risk}`));\n\t\tconst depths = Object.keys(impact.byDepth)\n\t\t\t.map(Number)\n\t\t\t.filter((d) => !Number.isNaN(d))\n\t\t\t.sort((a, b) => a - b);\n\t\tfor (const depth of depths.slice(0, 3)) {\n\t\t\tconst nodes = impact.byDepth[String(depth)] ?? [];\n\t\t\tif (nodes.length === 0) continue;\n\t\t\tconst color = depth === 1 ? \"error\" : depth === 2 ? \"warning\" : \"muted\";\n\t\t\tconst label = depth === 1 ? \"breaks\" : depth === 2 ? \"test\" : \"transitive\";\n\t\t\trow(theme.fg(color, `d${depth} ${label} (${nodes.length})`));\n\t\t\tfor (const node of nodes.slice(0, 3)) {\n\t\t\t\tconst lowConfidence = node.confidence !== undefined && node.confidence < CONFIDENCE_DIM_THRESHOLD;\n\t\t\t\tconst name = lowConfidence ? theme.fg(\"dim\", `${node.name}?`) : node.name;\n\t\t\t\trow(` ${theme.fg(lowConfidence ? \"dim\" : color, depth === 1 ? \"●\" : \"○\")} ${name}`);\n\t\t\t}\n\t\t\tif (nodes.length > 3) row(theme.fg(\"muted\", ` … +${nodes.length - 3}`));\n\t\t}\n\t\tif (impact.processes.length > 0) row(theme.fg(\"muted\", `flows: ${impact.processes.slice(0, 2).join(\", \")}`));\n\t\tif (impact.modules.length > 0) {\n\t\t\tconst maxHits = Math.max(...impact.modules.map((m) => m.hits), 1);\n\t\t\tfor (const module of impact.modules.slice(0, 3)) {\n\t\t\t\tconst filled = Math.max(1, Math.round((module.hits / maxHits) * 5));\n\t\t\t\tconst bar =\n\t\t\t\t\ttheme.fg(module.direct ? \"accent\" : \"muted\", \"▮\".repeat(filled)) +\n\t\t\t\t\ttheme.fg(\"dim\", \"▯\".repeat(5 - filled));\n\t\t\t\trow(`${bar} ${theme.fg(\"muted\", module.name)} ${theme.fg(\"dim\", String(module.hits))}`);\n\t\t\t}\n\t\t}\n\t\tend();\n\t}\n\n\tprivate renderQuery(\n\t\ts: Readonly<GraphRailState>,\n\t\trule: (t: string) => void,\n\t\trow: (t: string) => void,\n\t\tend: () => void,\n\t): void {\n\t\tconst query = s.query;\n\t\tif (!query) return;\n\t\trule(\"Flows\");\n\t\trow(theme.fg(\"muted\", clipQuery(query.query)));\n\t\tquery.flows.slice(0, 3).forEach((flow, i) => {\n\t\t\tconst marker = i === 0 ? theme.fg(\"accent\", \"◉\") : theme.fg(\"muted\", \"○\");\n\t\t\tconst steps = flow.stepCount ? theme.fg(\"muted\", ` ·${flow.stepCount}`) : \"\";\n\t\t\trow(`${marker} ${flow.summary}${steps}`);\n\t\t});\n\t\tend();\n\t}\n\n\tprivate renderSkills(rule: (t: string) => void, row: (t: string) => void, end: () => void): void {\n\t\tconst skills = this.hostInfo?.skills ?? [];\n\t\tif (skills.length === 0) return;\n\t\trule(\"Skills\");\n\t\tfor (const skill of skills.slice(0, 8)) {\n\t\t\trow(`${theme.fg(\"success\", \"\\u25cf\")} ${theme.fg(\"muted\", skill)}`);\n\t\t}\n\t\tif (skills.length > 8) row(theme.fg(\"muted\", ` \\u2026 +${skills.length - 8} more`));\n\t\tend();\n\t}\n\n\tprivate renderChanges(\n\t\ts: Readonly<GraphRailState>,\n\t\trule: (t: string) => void,\n\t\trow: (t: string) => void,\n\t\tend: () => void,\n\t): void {\n\t\trule(\"Modified Files\");\n\t\tif (s.changes.length === 0) {\n\t\t\trow(theme.fg(\"muted\", \"None\"));\n\t\t\tend();\n\t\t\treturn;\n\t\t}\n\t\tfor (const change of s.changes.slice(-5)) {\n\t\t\trow(\n\t\t\t\t`${basename(change.path)} ${theme.fg(\"success\", `+${change.added}`)} ${theme.fg(\"error\", `-${change.removed}`)}`,\n\t\t\t);\n\t\t}\n\t\tend();\n\t}\n}\n\nfunction clipQuery(query: string): string {\n\treturn query.length > 30 ? `${query.slice(0, 29)}…` : `“${query}”`;\n}\n\n/** Full-width expansion of a rail card, appended to the transcript on click. */\nexport function renderExpandedCard(card: GraphRailCard, hostInfo?: GraphRailHostInfo): string | undefined {\n\tconst s = graphRailStore.getState();\n\tconst header = (title: string) => theme.bold(theme.fg(\"accent\", `── GitNexus · ${title} ──`));\n\tif (card === \"repos\" && s.repos.length > 0) {\n\t\tconst lines: string[] = [header(\"indexed repos\")];\n\t\tfor (const repo of s.repos) {\n\t\t\tconst marker = repo.name === s.repo?.name ? theme.fg(\"accent\", \"●\") : theme.fg(\"muted\", \"○\");\n\t\t\tlines.push(`${marker} ${repo.name} ${theme.fg(\"muted\", `${repo.symbols} symbols`)}`);\n\t\t}\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (card === \"skills\" && hostInfo && hostInfo.skills.length > 0) {\n\t\tconst lines: string[] = [header(\"skills\")];\n\t\tfor (const skill of hostInfo.skills) {\n\t\t\tlines.push(`${theme.fg(\"success\", \"●\")} ${skill}`);\n\t\t}\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (card === \"impact\" && s.impact) {\n\t\tconst lines: string[] = [header(\"blast radius\")];\n\t\tconst risk = s.impact.risk.toUpperCase();\n\t\tconst riskColor = risk === \"HIGH\" || risk === \"CRITICAL\" ? \"error\" : risk === \"MEDIUM\" ? \"warning\" : \"success\";\n\t\tlines.push(\n\t\t\t`${theme.fg(\"accent\", \"◉\")} ${theme.bold(s.impact.target)} ${theme.fg(\"muted\", s.impact.filePath ?? \"\")} ${theme.bold(theme.fg(riskColor, `RISK: ${risk}`))}`,\n\t\t);\n\t\tconst depths = Object.keys(s.impact.byDepth)\n\t\t\t.map(Number)\n\t\t\t.filter((d) => !Number.isNaN(d))\n\t\t\t.sort((a, b) => a - b);\n\t\tfor (const depth of depths) {\n\t\t\tconst nodes = s.impact.byDepth[String(depth)] ?? [];\n\t\t\tif (nodes.length === 0) continue;\n\t\t\tconst color = depth === 1 ? \"error\" : depth === 2 ? \"warning\" : \"muted\";\n\t\t\tconst label = depth === 1 ? \"WILL BREAK\" : depth === 2 ? \"should test\" : \"transitive\";\n\t\t\tlines.push(theme.fg(color, `d=${depth} ${label} (${nodes.length})`));\n\t\t\tfor (const node of nodes) {\n\t\t\t\tconst rel = node.relationType ? theme.fg(\"muted\", ` (${node.relationType})`) : \"\";\n\t\t\t\tlines.push(\n\t\t\t\t\t` ${theme.fg(color, depth === 1 ? \"●\" : \"○\")} ${node.name} ${theme.fg(\"muted\", node.filePath ?? \"\")}${rel}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (s.impact.processes.length > 0)\n\t\t\tlines.push(theme.fg(\"muted\", `flows affected: ${s.impact.processes.join(\", \")}`));\n\t\tif (s.impact.modules.length > 0)\n\t\t\tlines.push(\n\t\t\t\ttheme.fg(\n\t\t\t\t\t\"muted\",\n\t\t\t\t\t`modules: ${s.impact.modules.map((m) => `${m.name} (${m.hits}${m.direct ? \", direct\" : \"\"})`).join(\", \")}`,\n\t\t\t\t),\n\t\t\t);\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (card === \"flows\" && s.query) {\n\t\tconst lines: string[] = [header(\"flows\"), theme.fg(\"muted\", `query: “${s.query.query}”`)];\n\t\ts.query.flows.forEach((flow, i) => {\n\t\t\tconst marker = i === 0 ? theme.fg(\"accent\", \"◉\") : theme.fg(\"muted\", \"○\");\n\t\t\tlines.push(\n\t\t\t\t`${marker} ${flow.summary}${flow.stepCount ? theme.fg(\"muted\", ` · ${flow.stepCount} steps`) : \"\"}`,\n\t\t\t);\n\t\t});\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (card === \"changes\" && s.changes.length > 0) {\n\t\tconst lines: string[] = [header(\"session changes\")];\n\t\tfor (const change of s.changes) {\n\t\t\tlines.push(\n\t\t\t\t`${theme.fg(\"success\", `+${change.added}`)} ${theme.fg(\"error\", `-${change.removed}`)} ${change.path}`,\n\t\t\t);\n\t\t}\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (card === \"status\" && s.repo) {\n\t\treturn [\n\t\t\theader(\"status\"),\n\t\t\t`repo: ${s.repo.name || \"(current dir not indexed)\"} · ${s.repo.symbols} symbols`,\n\t\t\t`indexed: ${s.repo.indexedAt || \"n/a\"} · ${s.repo.repoCount} repos on hub`,\n\t\t\t`graph calls: ${s.graphCalls} · impact checks: ${s.impactChecks}`,\n\t\t].join(\"\\n\");\n\t}\n\treturn undefined;\n}\n"]}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { type Keybinding } from "@earendil-works/pi-tui";
|
|
5
5
|
export interface KeyTextFormatOptions {
|
|
6
6
|
capitalize?: boolean;
|
|
7
|
+
platform?: NodeJS.Platform;
|
|
7
8
|
}
|
|
8
9
|
export declare function formatKeyText(key: string, options?: KeyTextFormatOptions): string;
|
|
9
10
|
export declare function keyText(keybinding: Keybinding): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keybinding-hints.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/keybinding-hints.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAkB,KAAK,UAAU,EAAc,MAAM,wBAAwB,CAAC;AAGrF,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"keybinding-hints.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/keybinding-hints.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAkB,KAAK,UAAU,EAAc,MAAM,wBAAwB,CAAC;AAGrF,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC3B;AAcD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAUrF;AAOD,wBAAgB,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAEtD;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAE7D;AAED,wBAAgB,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEnE","sourcesContent":["/**\n * Utilities for formatting keybinding hints in the UI.\n */\n\nimport { getKeybindings, type Keybinding, type KeyId } from \"@earendil-works/pi-tui\";\nimport { theme } from \"../theme/theme.ts\";\n\nexport interface KeyTextFormatOptions {\n\tcapitalize?: boolean;\n\tplatform?: NodeJS.Platform;\n}\n\nfunction formatKeyPart(part: string, options: KeyTextFormatOptions): string {\n\tconst platform = options.platform ?? process.platform;\n\tconst normalizedPart = part.toLowerCase();\n\tconst displayPart =\n\t\tplatform === \"darwin\" && normalizedPart === \"alt\"\n\t\t\t? \"option\"\n\t\t\t: platform === \"darwin\" && normalizedPart === \"super\"\n\t\t\t\t? \"cmd\"\n\t\t\t\t: part;\n\treturn options.capitalize ? displayPart.charAt(0).toUpperCase() + displayPart.slice(1) : displayPart;\n}\n\nexport function formatKeyText(key: string, options: KeyTextFormatOptions = {}): string {\n\treturn key\n\t\t.split(\"/\")\n\t\t.map((k) =>\n\t\t\tk\n\t\t\t\t.split(\"+\")\n\t\t\t\t.map((part) => formatKeyPart(part, options))\n\t\t\t\t.join(\"+\"),\n\t\t)\n\t\t.join(\"/\");\n}\n\nfunction formatKeys(keys: KeyId[], options: KeyTextFormatOptions = {}): string {\n\tif (keys.length === 0) return \"\";\n\treturn formatKeyText(keys.join(\"/\"), options);\n}\n\nexport function keyText(keybinding: Keybinding): string {\n\treturn formatKeys(getKeybindings().getKeys(keybinding));\n}\n\nexport function keyDisplayText(keybinding: Keybinding): string {\n\treturn formatKeys(getKeybindings().getKeys(keybinding), { capitalize: true });\n}\n\nexport function keyHint(keybinding: Keybinding, description: string): string {\n\treturn theme.fg(\"dim\", keyText(keybinding)) + theme.fg(\"muted\", ` ${description}`);\n}\n\nexport function rawKeyHint(key: string, description: string): string {\n\treturn theme.fg(\"dim\", formatKeyText(key)) + theme.fg(\"muted\", ` ${description}`);\n}\n"]}
|
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
import { getKeybindings } from "@earendil-works/pi-tui";
|
|
5
5
|
import { theme } from "../theme/theme.js";
|
|
6
6
|
function formatKeyPart(part, options) {
|
|
7
|
-
const
|
|
7
|
+
const platform = options.platform ?? process.platform;
|
|
8
|
+
const normalizedPart = part.toLowerCase();
|
|
9
|
+
const displayPart = platform === "darwin" && normalizedPart === "alt"
|
|
10
|
+
? "option"
|
|
11
|
+
: platform === "darwin" && normalizedPart === "super"
|
|
12
|
+
? "cmd"
|
|
13
|
+
: part;
|
|
8
14
|
return options.capitalize ? displayPart.charAt(0).toUpperCase() + displayPart.slice(1) : displayPart;
|
|
9
15
|
}
|
|
10
16
|
export function formatKeyText(key, options = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keybinding-hints.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/keybinding-hints.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAA+B,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"keybinding-hints.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/keybinding-hints.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAA+B,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAO1C,SAAS,aAAa,CAAC,IAAY,EAAE,OAA6B,EAAU;IAC3E,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACtD,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC1C,MAAM,WAAW,GAChB,QAAQ,KAAK,QAAQ,IAAI,cAAc,KAAK,KAAK;QAChD,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,cAAc,KAAK,OAAO;YACpD,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,IAAI,CAAC;IACV,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;AAAA,CACrG;AAED,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,OAAO,GAAyB,EAAE,EAAU;IACtF,OAAO,GAAG;SACR,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACV,CAAC;SACC,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;SAC3C,IAAI,CAAC,GAAG,CAAC,CACX;SACA,IAAI,CAAC,GAAG,CAAC,CAAC;AAAA,CACZ;AAED,SAAS,UAAU,CAAC,IAAa,EAAE,OAAO,GAAyB,EAAE,EAAU;IAC9E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AAAA,CAC9C;AAED,MAAM,UAAU,OAAO,CAAC,UAAsB,EAAU;IACvD,OAAO,UAAU,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;AAAA,CACxD;AAED,MAAM,UAAU,cAAc,CAAC,UAAsB,EAAU;IAC9D,OAAO,UAAU,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;AAAA,CAC9E;AAED,MAAM,UAAU,OAAO,CAAC,UAAsB,EAAE,WAAmB,EAAU;IAC5E,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,WAAW,EAAE,CAAC,CAAC;AAAA,CACnF;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,WAAmB,EAAU;IACpE,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,WAAW,EAAE,CAAC,CAAC;AAAA,CAClF","sourcesContent":["/**\n * Utilities for formatting keybinding hints in the UI.\n */\n\nimport { getKeybindings, type Keybinding, type KeyId } from \"@earendil-works/pi-tui\";\nimport { theme } from \"../theme/theme.ts\";\n\nexport interface KeyTextFormatOptions {\n\tcapitalize?: boolean;\n\tplatform?: NodeJS.Platform;\n}\n\nfunction formatKeyPart(part: string, options: KeyTextFormatOptions): string {\n\tconst platform = options.platform ?? process.platform;\n\tconst normalizedPart = part.toLowerCase();\n\tconst displayPart =\n\t\tplatform === \"darwin\" && normalizedPart === \"alt\"\n\t\t\t? \"option\"\n\t\t\t: platform === \"darwin\" && normalizedPart === \"super\"\n\t\t\t\t? \"cmd\"\n\t\t\t\t: part;\n\treturn options.capitalize ? displayPart.charAt(0).toUpperCase() + displayPart.slice(1) : displayPart;\n}\n\nexport function formatKeyText(key: string, options: KeyTextFormatOptions = {}): string {\n\treturn key\n\t\t.split(\"/\")\n\t\t.map((k) =>\n\t\t\tk\n\t\t\t\t.split(\"+\")\n\t\t\t\t.map((part) => formatKeyPart(part, options))\n\t\t\t\t.join(\"+\"),\n\t\t)\n\t\t.join(\"/\");\n}\n\nfunction formatKeys(keys: KeyId[], options: KeyTextFormatOptions = {}): string {\n\tif (keys.length === 0) return \"\";\n\treturn formatKeyText(keys.join(\"/\"), options);\n}\n\nexport function keyText(keybinding: Keybinding): string {\n\treturn formatKeys(getKeybindings().getKeys(keybinding));\n}\n\nexport function keyDisplayText(keybinding: Keybinding): string {\n\treturn formatKeys(getKeybindings().getKeys(keybinding), { capitalize: true });\n}\n\nexport function keyHint(keybinding: Keybinding, description: string): string {\n\treturn theme.fg(\"dim\", keyText(keybinding)) + theme.fg(\"muted\", ` ${description}`);\n}\n\nexport function rawKeyHint(key: string, description: string): string {\n\treturn theme.fg(\"dim\", formatKeyText(key)) + theme.fg(\"muted\", ` ${description}`);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"landing-panel.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/landing-panel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAgCxD,qBAAa,qBAAsB,YAAW,SAAS;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,gBAAgB,CAAc;IAEtC,YAAY,SAAS,EAAE,MAAM,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,IAAI,EAW/D;IAED,OAAO,CAAC,aAAa;IAKrB,OAAO,IAAI,IAAI,CAId;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ9B;IAED,OAAO,CAAC,YAAY;
|
|
1
|
+
{"version":3,"file":"landing-panel.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/landing-panel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAgCxD,qBAAa,qBAAsB,YAAW,SAAS;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,gBAAgB,CAAc;IAEtC,YAAY,SAAS,EAAE,MAAM,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,IAAI,EAW/D;IAED,OAAO,CAAC,aAAa;IAKrB,OAAO,IAAI,IAAI,CAId;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ9B;IAED,OAAO,CAAC,YAAY;CAyEpB","sourcesContent":["import type { Component } from \"@earendil-works/pi-tui\";\nimport { visibleWidth } from \"@earendil-works/pi-tui\";\nimport { formatCompactIndexPhase, type GraphRailState, graphRailStore } from \"../../../core/graph-rail-store.ts\";\nimport { tryLoadObservatoryCache } from \"../../../core/observatory-cache.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\n/** Startup resource summary: GitNexus graph, skills, and indexed repositories. */\n\nconst COLUMN_GAP = 3;\nconst MIN_COLUMN_WIDTH = 22;\nconst MAX_COLUMN_WIDTH = 32;\n\nfunction clipTo(text: string, width: number): string {\n\tif (visibleWidth(text) <= width) return text;\n\tlet out = \"\";\n\tlet visible = 0;\n\tfor (let i = 0; i < text.length; i++) {\n\t\tif (text[i] === \"\\x1b\") {\n\t\t\tconst match = text.slice(i).match(/^\\x1b\\[[0-9;]*m/);\n\t\t\tif (match) {\n\t\t\t\tout += match[0];\n\t\t\t\ti += match[0].length - 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (visible >= width - 1) break;\n\t\tout += text[i];\n\t\tvisible++;\n\t}\n\treturn `${out}…\\x1b[0m`;\n}\n\nexport class LandingPanelComponent implements Component {\n\tprivate readonly getSkills: () => string[];\n\tprivate unsubscribe: (() => void) | undefined;\n\tprivate cachePoll: ReturnType<typeof setInterval> | undefined;\n\tprivate cachePollStarted = Date.now();\n\n\tconstructor(getSkills: () => string[], onDataChanged: () => void) {\n\t\tthis.getSkills = getSkills;\n\t\tthis.unsubscribe = graphRailStore.subscribe(onDataChanged);\n\t\tthis.cachePoll = setInterval(() => {\n\t\t\tconst s = graphRailStore.getState();\n\t\t\tif (Date.now() - this.cachePollStarted > 60_000) {\n\t\t\t\tthis.stopCachePoll();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (s.repo?.name && s.currentIndexed) tryLoadObservatoryCache(s.repo.name);\n\t\t}, 1500);\n\t}\n\n\tprivate stopCachePoll(): void {\n\t\tif (this.cachePoll) clearInterval(this.cachePoll);\n\t\tthis.cachePoll = undefined;\n\t}\n\n\tdispose(): void {\n\t\tthis.unsubscribe?.();\n\t\tthis.unsubscribe = undefined;\n\t\tthis.stopCachePoll();\n\t}\n\n\tinvalidate(): void {\n\t\t// Pure view over graphRailStore and loaded skills.\n\t}\n\n\trender(width: number): string[] {\n\t\tconst s = graphRailStore.getState();\n\t\tconst skillNames = this.getSkills();\n\t\tif (!s.repo && s.repos.length === 0 && skillNames.length === 0) return [];\n\t\tif (s.repo?.name && s.currentIndexed) tryLoadObservatoryCache(s.repo.name);\n\n\t\tconst lines: string[] = [\"\", ...this.buildColumns(s, width, skillNames)];\n\t\treturn lines.map((line) => clipTo(line, width));\n\t}\n\n\tprivate buildColumns(s: Readonly<GraphRailState>, width: number, skillNames: string[]): string[] {\n\t\tconst columnWidth = Math.min(\n\t\t\tMAX_COLUMN_WIDTH,\n\t\t\tMath.max(MIN_COLUMN_WIDTH, Math.floor((width - 2 * COLUMN_GAP) / 3)),\n\t\t);\n\t\tconst graph: string[] = [theme.fg(\"muted\", \"Graph\")];\n\t\tif (s.indexProgress) {\n\t\t\tconst progress = s.indexProgress;\n\t\t\tconst phase = formatCompactIndexPhase(progress.phase);\n\t\t\tgraph.push(\n\t\t\t\t`${theme.fg(\"accent\", \"●\")} ${theme.bold(progress.fullName.split(\"/\").pop() ?? progress.fullName)}`,\n\t\t\t);\n\t\t\tconst percent =\n\t\t\t\tprogress.percent === undefined ? undefined : Math.max(0, Math.min(100, Math.round(progress.percent)));\n\t\t\tgraph.push(\n\t\t\t\tpercent === undefined\n\t\t\t\t\t? theme.fg(\"muted\", phase)\n\t\t\t\t\t: `${theme.fg(\"muted\", phase)} ${theme.fg(\"accent\", `${percent}%`)}`,\n\t\t\t);\n\t\t\tif (percent !== undefined) {\n\t\t\t\tconst filled = Math.round((percent / 100) * columnWidth);\n\t\t\t\tgraph.push(theme.fg(\"accent\", \"━\".repeat(filled)) + theme.fg(\"dim\", \"─\".repeat(columnWidth - filled)));\n\t\t\t}\n\t\t} else if (s.repo && s.currentIndexed) {\n\t\t\tgraph.push(`${theme.fg(\"success\", \"●\")} ${theme.bold(s.repo.name.split(\"/\").pop() ?? s.repo.name)}`);\n\t\t\tgraph.push(theme.fg(\"muted\", `${s.repo.symbols} symbols`));\n\t\t\tgraph.push(theme.fg(\"muted\", `${s.repo.relationships} relationships`));\n\t\t\tif (s.observatory) {\n\t\t\t\tconst flows = s.observatory.flowCount !== undefined ? ` · ${s.observatory.flowCount} flows` : \"\";\n\t\t\t\tgraph.push(theme.fg(\"muted\", `${s.observatory.communities.length} communities${flows}`));\n\t\t\t}\n\t\t} else if (s.repo) {\n\t\t\tgraph.push(`${theme.fg(\"warning\", \"○\")} ${theme.fg(\"warning\", \"repo not indexed\")}`);\n\t\t\tgraph.push(theme.fg(\"muted\", `${s.repo.repoCount} repos queryable`));\n\t\t} else {\n\t\t\tgraph.push(theme.fg(\"muted\", \"not connected\"));\n\t\t}\n\n\t\tconst skills: string[] = [theme.fg(\"muted\", \"Skills\")];\n\t\tfor (const name of skillNames.slice(0, 6)) {\n\t\t\tskills.push(`${theme.fg(\"success\", \"●\")} ${name}`);\n\t\t}\n\t\tif (skillNames.length > 6) skills.push(theme.fg(\"muted\", ` +${skillNames.length - 6} more`));\n\t\tif (skillNames.length === 0) skills.push(theme.fg(\"muted\", \"none\"));\n\n\t\tconst repos: string[] = [theme.fg(\"muted\", \"Indexed repos\")];\n\t\tconst activeName = s.repo?.name;\n\t\tconst ordered = activeName\n\t\t\t? [\n\t\t\t\t\t...s.repos.filter((repo) => repo.name === activeName),\n\t\t\t\t\t...s.repos.filter((repo) => repo.name !== activeName),\n\t\t\t\t]\n\t\t\t: s.repos;\n\t\tfor (const repo of ordered.slice(0, 6)) {\n\t\t\tconst short = repo.name.split(\"/\").pop() ?? repo.name;\n\t\t\tconst active = repo.name === s.repo?.name;\n\t\t\tconst marker = active ? theme.fg(\"accent\", \"●\") : theme.fg(\"muted\", \"○\");\n\t\t\tconst label = active ? theme.fg(\"accent\", short) : short;\n\t\t\trepos.push(`${marker} ${label} ${theme.fg(\"dim\", formatCount(repo.symbols))}`);\n\t\t}\n\t\tif (s.repos.length > 6) repos.push(theme.fg(\"muted\", ` +${s.repos.length - 6} more`));\n\t\tif (s.repos.length === 0) repos.push(theme.fg(\"muted\", \"none\"));\n\n\t\tconst rows = Math.max(graph.length, skills.length, repos.length);\n\t\tconst lines: string[] = [];\n\t\tfor (let i = 0; i < rows; i++) {\n\t\t\tconst graphCell = padTo(clipTo(graph[i] ?? \"\", columnWidth), columnWidth);\n\t\t\tconst skillCell = padTo(clipTo(skills[i] ?? \"\", columnWidth), columnWidth);\n\t\t\tconst repoCell = clipTo(repos[i] ?? \"\", columnWidth);\n\t\t\tlines.push(` ${graphCell}${\" \".repeat(COLUMN_GAP)}${skillCell}${\" \".repeat(COLUMN_GAP)}${repoCell}`);\n\t\t}\n\t\treturn lines;\n\t}\n}\n\nfunction padTo(text: string, width: number): string {\n\treturn text + \" \".repeat(Math.max(0, width - visibleWidth(text)));\n}\n\nfunction formatCount(symbols: string): string {\n\tconst count = Number(symbols.replace(/,/g, \"\"));\n\tif (Number.isNaN(count)) return symbols;\n\tif (count >= 1_000_000) return `${(count / 1_000_000).toFixed(1)}M`;\n\tif (count >= 1_000) return `${Math.round(count / 1_000)}k`;\n\treturn String(count);\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
2
|
-
import { graphRailStore } from "../../../core/graph-rail-store.js";
|
|
2
|
+
import { formatCompactIndexPhase, graphRailStore } from "../../../core/graph-rail-store.js";
|
|
3
3
|
import { tryLoadObservatoryCache } from "../../../core/observatory-cache.js";
|
|
4
4
|
import { theme } from "../theme/theme.js";
|
|
5
5
|
/** Startup resource summary: GitNexus graph, skills, and indexed repositories. */
|
|
@@ -71,7 +71,20 @@ export class LandingPanelComponent {
|
|
|
71
71
|
buildColumns(s, width, skillNames) {
|
|
72
72
|
const columnWidth = Math.min(MAX_COLUMN_WIDTH, Math.max(MIN_COLUMN_WIDTH, Math.floor((width - 2 * COLUMN_GAP) / 3)));
|
|
73
73
|
const graph = [theme.fg("muted", "Graph")];
|
|
74
|
-
if (s.
|
|
74
|
+
if (s.indexProgress) {
|
|
75
|
+
const progress = s.indexProgress;
|
|
76
|
+
const phase = formatCompactIndexPhase(progress.phase);
|
|
77
|
+
graph.push(`${theme.fg("accent", "●")} ${theme.bold(progress.fullName.split("/").pop() ?? progress.fullName)}`);
|
|
78
|
+
const percent = progress.percent === undefined ? undefined : Math.max(0, Math.min(100, Math.round(progress.percent)));
|
|
79
|
+
graph.push(percent === undefined
|
|
80
|
+
? theme.fg("muted", phase)
|
|
81
|
+
: `${theme.fg("muted", phase)} ${theme.fg("accent", `${percent}%`)}`);
|
|
82
|
+
if (percent !== undefined) {
|
|
83
|
+
const filled = Math.round((percent / 100) * columnWidth);
|
|
84
|
+
graph.push(theme.fg("accent", "━".repeat(filled)) + theme.fg("dim", "─".repeat(columnWidth - filled)));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (s.repo && s.currentIndexed) {
|
|
75
88
|
graph.push(`${theme.fg("success", "●")} ${theme.bold(s.repo.name.split("/").pop() ?? s.repo.name)}`);
|
|
76
89
|
graph.push(theme.fg("muted", `${s.repo.symbols} symbols`));
|
|
77
90
|
graph.push(theme.fg("muted", `${s.repo.relationships} relationships`));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"landing-panel.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/landing-panel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAuB,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,kFAAkF;AAElF,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B,SAAS,MAAM,CAAC,IAAY,EAAE,KAAa,EAAU;IACpD,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,KAAK;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACrD,IAAI,KAAK,EAAE,CAAC;gBACX,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;gBAChB,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;gBACzB,SAAS;YACV,CAAC;QACF,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,GAAG,CAAC;YAAE,MAAM;QAChC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QACf,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,GAAG,GAAG,YAAU,CAAC;AAAA,CACxB;AAED,MAAM,OAAO,qBAAqB;IAChB,SAAS,CAAiB;IACnC,WAAW,CAA2B;IACtC,SAAS,CAA6C;IACtD,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEtC,YAAY,SAAyB,EAAE,aAAyB,EAAE;QACjE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC3D,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,gBAAgB,GAAG,MAAM,EAAE,CAAC;gBACjD,IAAI,CAAC,aAAa,EAAE,CAAC;gBACrB,OAAO;YACR,CAAC;YACD,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,cAAc;gBAAE,uBAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAA,CAC3E,EAAE,IAAI,CAAC,CAAC;IAAA,CACT;IAEO,aAAa,GAAS;QAC7B,IAAI,IAAI,CAAC,SAAS;YAAE,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAAA,CAC3B;IAED,OAAO,GAAS;QACf,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED,UAAU,GAAS;QAClB,mDAAmD;IADhC,CAEnB;IAED,MAAM,CAAC,KAAa,EAAY;QAC/B,MAAM,CAAC,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACpC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAC1E,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,cAAc;YAAE,uBAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE3E,MAAM,KAAK,GAAa,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;QACzE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAAA,CAChD;IAEO,YAAY,CAAC,CAA2B,EAAE,KAAa,EAAE,UAAoB,EAAY;QAChG,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAC3B,gBAAgB,EAChB,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CACpE,CAAC;QACF,MAAM,KAAK,GAAa,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,KAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC;YAC3D,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,aAAa,gBAAgB,CAAC,CAAC,CAAC;YACvE,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;gBACnB,MAAM,KAAK,GAAG,CAAC,CAAC,WAAW,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,OAAM,CAAC,CAAC,WAAW,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,eAAe,KAAK,EAAE,CAAC,CAAC,CAAC;YAC1F,CAAC;QACF,CAAC;aAAM,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,KAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,kBAAkB,CAAC,EAAE,CAAC,CAAC;YACrF,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,kBAAkB,CAAC,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACP,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,MAAM,GAAa,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;QACvD,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,KAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,UAAU,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9F,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAEpE,MAAM,KAAK,GAAa,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC;QAChC,MAAM,OAAO,GAAG,UAAU;YACzB,CAAC,CAAC;gBACA,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC;gBACrD,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC;aACrD;YACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACX,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC;YACtD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAG,CAAC,CAAC;YACzE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YACzD,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QACvF,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAEhE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACjE,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;YAC1E,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;YAC3E,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC;YACrD,KAAK,CAAC,IAAI,CAAC,IAAI,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,EAAE,CAAC,CAAC;QACtG,CAAC;QACD,OAAO,KAAK,CAAC;IAAA,CACb;CACD;AAED,SAAS,KAAK,CAAC,IAAY,EAAE,KAAa,EAAU;IACnD,OAAO,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAAA,CAClE;AAED,SAAS,WAAW,CAAC,OAAe,EAAU;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAChD,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,IAAI,KAAK,IAAI,SAAS;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACpE,IAAI,KAAK,IAAI,KAAK;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC;IAC3D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AAAA,CACrB","sourcesContent":["import type { Component } from \"@earendil-works/pi-tui\";\nimport { visibleWidth } from \"@earendil-works/pi-tui\";\nimport { type GraphRailState, graphRailStore } from \"../../../core/graph-rail-store.ts\";\nimport { tryLoadObservatoryCache } from \"../../../core/observatory-cache.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\n/** Startup resource summary: GitNexus graph, skills, and indexed repositories. */\n\nconst COLUMN_GAP = 3;\nconst MIN_COLUMN_WIDTH = 22;\nconst MAX_COLUMN_WIDTH = 32;\n\nfunction clipTo(text: string, width: number): string {\n\tif (visibleWidth(text) <= width) return text;\n\tlet out = \"\";\n\tlet visible = 0;\n\tfor (let i = 0; i < text.length; i++) {\n\t\tif (text[i] === \"\\x1b\") {\n\t\t\tconst match = text.slice(i).match(/^\\x1b\\[[0-9;]*m/);\n\t\t\tif (match) {\n\t\t\t\tout += match[0];\n\t\t\t\ti += match[0].length - 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (visible >= width - 1) break;\n\t\tout += text[i];\n\t\tvisible++;\n\t}\n\treturn `${out}…\\x1b[0m`;\n}\n\nexport class LandingPanelComponent implements Component {\n\tprivate readonly getSkills: () => string[];\n\tprivate unsubscribe: (() => void) | undefined;\n\tprivate cachePoll: ReturnType<typeof setInterval> | undefined;\n\tprivate cachePollStarted = Date.now();\n\n\tconstructor(getSkills: () => string[], onDataChanged: () => void) {\n\t\tthis.getSkills = getSkills;\n\t\tthis.unsubscribe = graphRailStore.subscribe(onDataChanged);\n\t\tthis.cachePoll = setInterval(() => {\n\t\t\tconst s = graphRailStore.getState();\n\t\t\tif (Date.now() - this.cachePollStarted > 60_000) {\n\t\t\t\tthis.stopCachePoll();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (s.repo?.name && s.currentIndexed) tryLoadObservatoryCache(s.repo.name);\n\t\t}, 1500);\n\t}\n\n\tprivate stopCachePoll(): void {\n\t\tif (this.cachePoll) clearInterval(this.cachePoll);\n\t\tthis.cachePoll = undefined;\n\t}\n\n\tdispose(): void {\n\t\tthis.unsubscribe?.();\n\t\tthis.unsubscribe = undefined;\n\t\tthis.stopCachePoll();\n\t}\n\n\tinvalidate(): void {\n\t\t// Pure view over graphRailStore and loaded skills.\n\t}\n\n\trender(width: number): string[] {\n\t\tconst s = graphRailStore.getState();\n\t\tconst skillNames = this.getSkills();\n\t\tif (!s.repo && s.repos.length === 0 && skillNames.length === 0) return [];\n\t\tif (s.repo?.name && s.currentIndexed) tryLoadObservatoryCache(s.repo.name);\n\n\t\tconst lines: string[] = [\"\", ...this.buildColumns(s, width, skillNames)];\n\t\treturn lines.map((line) => clipTo(line, width));\n\t}\n\n\tprivate buildColumns(s: Readonly<GraphRailState>, width: number, skillNames: string[]): string[] {\n\t\tconst columnWidth = Math.min(\n\t\t\tMAX_COLUMN_WIDTH,\n\t\t\tMath.max(MIN_COLUMN_WIDTH, Math.floor((width - 2 * COLUMN_GAP) / 3)),\n\t\t);\n\t\tconst graph: string[] = [theme.fg(\"muted\", \"Graph\")];\n\t\tif (s.repo && s.currentIndexed) {\n\t\t\tgraph.push(`${theme.fg(\"success\", \"●\")} ${theme.bold(s.repo.name.split(\"/\").pop() ?? s.repo.name)}`);\n\t\t\tgraph.push(theme.fg(\"muted\", `${s.repo.symbols} symbols`));\n\t\t\tgraph.push(theme.fg(\"muted\", `${s.repo.relationships} relationships`));\n\t\t\tif (s.observatory) {\n\t\t\t\tconst flows = s.observatory.flowCount !== undefined ? ` · ${s.observatory.flowCount} flows` : \"\";\n\t\t\t\tgraph.push(theme.fg(\"muted\", `${s.observatory.communities.length} communities${flows}`));\n\t\t\t}\n\t\t} else if (s.repo) {\n\t\t\tgraph.push(`${theme.fg(\"warning\", \"○\")} ${theme.fg(\"warning\", \"repo not indexed\")}`);\n\t\t\tgraph.push(theme.fg(\"muted\", `${s.repo.repoCount} repos queryable`));\n\t\t} else {\n\t\t\tgraph.push(theme.fg(\"muted\", \"not connected\"));\n\t\t}\n\n\t\tconst skills: string[] = [theme.fg(\"muted\", \"Skills\")];\n\t\tfor (const name of skillNames.slice(0, 6)) {\n\t\t\tskills.push(`${theme.fg(\"success\", \"●\")} ${name}`);\n\t\t}\n\t\tif (skillNames.length > 6) skills.push(theme.fg(\"muted\", ` +${skillNames.length - 6} more`));\n\t\tif (skillNames.length === 0) skills.push(theme.fg(\"muted\", \"none\"));\n\n\t\tconst repos: string[] = [theme.fg(\"muted\", \"Indexed repos\")];\n\t\tconst activeName = s.repo?.name;\n\t\tconst ordered = activeName\n\t\t\t? [\n\t\t\t\t\t...s.repos.filter((repo) => repo.name === activeName),\n\t\t\t\t\t...s.repos.filter((repo) => repo.name !== activeName),\n\t\t\t\t]\n\t\t\t: s.repos;\n\t\tfor (const repo of ordered.slice(0, 6)) {\n\t\t\tconst short = repo.name.split(\"/\").pop() ?? repo.name;\n\t\t\tconst active = repo.name === s.repo?.name;\n\t\t\tconst marker = active ? theme.fg(\"accent\", \"●\") : theme.fg(\"muted\", \"○\");\n\t\t\tconst label = active ? theme.fg(\"accent\", short) : short;\n\t\t\trepos.push(`${marker} ${label} ${theme.fg(\"dim\", formatCount(repo.symbols))}`);\n\t\t}\n\t\tif (s.repos.length > 6) repos.push(theme.fg(\"muted\", ` +${s.repos.length - 6} more`));\n\t\tif (s.repos.length === 0) repos.push(theme.fg(\"muted\", \"none\"));\n\n\t\tconst rows = Math.max(graph.length, skills.length, repos.length);\n\t\tconst lines: string[] = [];\n\t\tfor (let i = 0; i < rows; i++) {\n\t\t\tconst graphCell = padTo(clipTo(graph[i] ?? \"\", columnWidth), columnWidth);\n\t\t\tconst skillCell = padTo(clipTo(skills[i] ?? \"\", columnWidth), columnWidth);\n\t\t\tconst repoCell = clipTo(repos[i] ?? \"\", columnWidth);\n\t\t\tlines.push(` ${graphCell}${\" \".repeat(COLUMN_GAP)}${skillCell}${\" \".repeat(COLUMN_GAP)}${repoCell}`);\n\t\t}\n\t\treturn lines;\n\t}\n}\n\nfunction padTo(text: string, width: number): string {\n\treturn text + \" \".repeat(Math.max(0, width - visibleWidth(text)));\n}\n\nfunction formatCount(symbols: string): string {\n\tconst count = Number(symbols.replace(/,/g, \"\"));\n\tif (Number.isNaN(count)) return symbols;\n\tif (count >= 1_000_000) return `${(count / 1_000_000).toFixed(1)}M`;\n\tif (count >= 1_000) return `${Math.round(count / 1_000)}k`;\n\treturn String(count);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"landing-panel.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/landing-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Component } from \"@earendil-works/pi-tui\";\nimport { visibleWidth } from \"@earendil-works/pi-tui\";\nimport { formatCompactIndexPhase, type GraphRailState, graphRailStore } from \"../../../core/graph-rail-store.ts\";\nimport { tryLoadObservatoryCache } from \"../../../core/observatory-cache.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\n/** Startup resource summary: GitNexus graph, skills, and indexed repositories. */\n\nconst COLUMN_GAP = 3;\nconst MIN_COLUMN_WIDTH = 22;\nconst MAX_COLUMN_WIDTH = 32;\n\nfunction clipTo(text: string, width: number): string {\n\tif (visibleWidth(text) <= width) return text;\n\tlet out = \"\";\n\tlet visible = 0;\n\tfor (let i = 0; i < text.length; i++) {\n\t\tif (text[i] === \"\\x1b\") {\n\t\t\tconst match = text.slice(i).match(/^\\x1b\\[[0-9;]*m/);\n\t\t\tif (match) {\n\t\t\t\tout += match[0];\n\t\t\t\ti += match[0].length - 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (visible >= width - 1) break;\n\t\tout += text[i];\n\t\tvisible++;\n\t}\n\treturn `${out}…\\x1b[0m`;\n}\n\nexport class LandingPanelComponent implements Component {\n\tprivate readonly getSkills: () => string[];\n\tprivate unsubscribe: (() => void) | undefined;\n\tprivate cachePoll: ReturnType<typeof setInterval> | undefined;\n\tprivate cachePollStarted = Date.now();\n\n\tconstructor(getSkills: () => string[], onDataChanged: () => void) {\n\t\tthis.getSkills = getSkills;\n\t\tthis.unsubscribe = graphRailStore.subscribe(onDataChanged);\n\t\tthis.cachePoll = setInterval(() => {\n\t\t\tconst s = graphRailStore.getState();\n\t\t\tif (Date.now() - this.cachePollStarted > 60_000) {\n\t\t\t\tthis.stopCachePoll();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (s.repo?.name && s.currentIndexed) tryLoadObservatoryCache(s.repo.name);\n\t\t}, 1500);\n\t}\n\n\tprivate stopCachePoll(): void {\n\t\tif (this.cachePoll) clearInterval(this.cachePoll);\n\t\tthis.cachePoll = undefined;\n\t}\n\n\tdispose(): void {\n\t\tthis.unsubscribe?.();\n\t\tthis.unsubscribe = undefined;\n\t\tthis.stopCachePoll();\n\t}\n\n\tinvalidate(): void {\n\t\t// Pure view over graphRailStore and loaded skills.\n\t}\n\n\trender(width: number): string[] {\n\t\tconst s = graphRailStore.getState();\n\t\tconst skillNames = this.getSkills();\n\t\tif (!s.repo && s.repos.length === 0 && skillNames.length === 0) return [];\n\t\tif (s.repo?.name && s.currentIndexed) tryLoadObservatoryCache(s.repo.name);\n\n\t\tconst lines: string[] = [\"\", ...this.buildColumns(s, width, skillNames)];\n\t\treturn lines.map((line) => clipTo(line, width));\n\t}\n\n\tprivate buildColumns(s: Readonly<GraphRailState>, width: number, skillNames: string[]): string[] {\n\t\tconst columnWidth = Math.min(\n\t\t\tMAX_COLUMN_WIDTH,\n\t\t\tMath.max(MIN_COLUMN_WIDTH, Math.floor((width - 2 * COLUMN_GAP) / 3)),\n\t\t);\n\t\tconst graph: string[] = [theme.fg(\"muted\", \"Graph\")];\n\t\tif (s.indexProgress) {\n\t\t\tconst progress = s.indexProgress;\n\t\t\tconst phase = formatCompactIndexPhase(progress.phase);\n\t\t\tgraph.push(\n\t\t\t\t`${theme.fg(\"accent\", \"●\")} ${theme.bold(progress.fullName.split(\"/\").pop() ?? progress.fullName)}`,\n\t\t\t);\n\t\t\tconst percent =\n\t\t\t\tprogress.percent === undefined ? undefined : Math.max(0, Math.min(100, Math.round(progress.percent)));\n\t\t\tgraph.push(\n\t\t\t\tpercent === undefined\n\t\t\t\t\t? theme.fg(\"muted\", phase)\n\t\t\t\t\t: `${theme.fg(\"muted\", phase)} ${theme.fg(\"accent\", `${percent}%`)}`,\n\t\t\t);\n\t\t\tif (percent !== undefined) {\n\t\t\t\tconst filled = Math.round((percent / 100) * columnWidth);\n\t\t\t\tgraph.push(theme.fg(\"accent\", \"━\".repeat(filled)) + theme.fg(\"dim\", \"─\".repeat(columnWidth - filled)));\n\t\t\t}\n\t\t} else if (s.repo && s.currentIndexed) {\n\t\t\tgraph.push(`${theme.fg(\"success\", \"●\")} ${theme.bold(s.repo.name.split(\"/\").pop() ?? s.repo.name)}`);\n\t\t\tgraph.push(theme.fg(\"muted\", `${s.repo.symbols} symbols`));\n\t\t\tgraph.push(theme.fg(\"muted\", `${s.repo.relationships} relationships`));\n\t\t\tif (s.observatory) {\n\t\t\t\tconst flows = s.observatory.flowCount !== undefined ? ` · ${s.observatory.flowCount} flows` : \"\";\n\t\t\t\tgraph.push(theme.fg(\"muted\", `${s.observatory.communities.length} communities${flows}`));\n\t\t\t}\n\t\t} else if (s.repo) {\n\t\t\tgraph.push(`${theme.fg(\"warning\", \"○\")} ${theme.fg(\"warning\", \"repo not indexed\")}`);\n\t\t\tgraph.push(theme.fg(\"muted\", `${s.repo.repoCount} repos queryable`));\n\t\t} else {\n\t\t\tgraph.push(theme.fg(\"muted\", \"not connected\"));\n\t\t}\n\n\t\tconst skills: string[] = [theme.fg(\"muted\", \"Skills\")];\n\t\tfor (const name of skillNames.slice(0, 6)) {\n\t\t\tskills.push(`${theme.fg(\"success\", \"●\")} ${name}`);\n\t\t}\n\t\tif (skillNames.length > 6) skills.push(theme.fg(\"muted\", ` +${skillNames.length - 6} more`));\n\t\tif (skillNames.length === 0) skills.push(theme.fg(\"muted\", \"none\"));\n\n\t\tconst repos: string[] = [theme.fg(\"muted\", \"Indexed repos\")];\n\t\tconst activeName = s.repo?.name;\n\t\tconst ordered = activeName\n\t\t\t? [\n\t\t\t\t\t...s.repos.filter((repo) => repo.name === activeName),\n\t\t\t\t\t...s.repos.filter((repo) => repo.name !== activeName),\n\t\t\t\t]\n\t\t\t: s.repos;\n\t\tfor (const repo of ordered.slice(0, 6)) {\n\t\t\tconst short = repo.name.split(\"/\").pop() ?? repo.name;\n\t\t\tconst active = repo.name === s.repo?.name;\n\t\t\tconst marker = active ? theme.fg(\"accent\", \"●\") : theme.fg(\"muted\", \"○\");\n\t\t\tconst label = active ? theme.fg(\"accent\", short) : short;\n\t\t\trepos.push(`${marker} ${label} ${theme.fg(\"dim\", formatCount(repo.symbols))}`);\n\t\t}\n\t\tif (s.repos.length > 6) repos.push(theme.fg(\"muted\", ` +${s.repos.length - 6} more`));\n\t\tif (s.repos.length === 0) repos.push(theme.fg(\"muted\", \"none\"));\n\n\t\tconst rows = Math.max(graph.length, skills.length, repos.length);\n\t\tconst lines: string[] = [];\n\t\tfor (let i = 0; i < rows; i++) {\n\t\t\tconst graphCell = padTo(clipTo(graph[i] ?? \"\", columnWidth), columnWidth);\n\t\t\tconst skillCell = padTo(clipTo(skills[i] ?? \"\", columnWidth), columnWidth);\n\t\t\tconst repoCell = clipTo(repos[i] ?? \"\", columnWidth);\n\t\t\tlines.push(` ${graphCell}${\" \".repeat(COLUMN_GAP)}${skillCell}${\" \".repeat(COLUMN_GAP)}${repoCell}`);\n\t\t}\n\t\treturn lines;\n\t}\n}\n\nfunction padTo(text: string, width: number): string {\n\treturn text + \" \".repeat(Math.max(0, width - visibleWidth(text)));\n}\n\nfunction formatCount(symbols: string): string {\n\tconst count = Number(symbols.replace(/,/g, \"\"));\n\tif (Number.isNaN(count)) return symbols;\n\tif (count >= 1_000_000) return `${(count / 1_000_000).toFixed(1)}M`;\n\tif (count >= 1_000) return `${Math.round(count / 1_000)}k`;\n\treturn String(count);\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Container, type TUI } from "@earendil-works/pi-tui";
|
|
2
|
-
import type { ToolDefinition } from "../../../core/extensions/types.ts";
|
|
2
|
+
import type { ToolDefinition, ToolRendererOverride } from "../../../core/extensions/types.ts";
|
|
3
3
|
export interface ToolExecutionOptions {
|
|
4
4
|
showImages?: boolean;
|
|
5
5
|
imageWidthCells?: number;
|
|
@@ -23,6 +23,7 @@ export declare class ToolExecutionComponent extends Container {
|
|
|
23
23
|
private isPartial;
|
|
24
24
|
private toolDefinition?;
|
|
25
25
|
private builtInToolDefinition?;
|
|
26
|
+
private toolRenderer?;
|
|
26
27
|
private ui;
|
|
27
28
|
private cwd;
|
|
28
29
|
private executionStarted;
|
|
@@ -32,7 +33,7 @@ export declare class ToolExecutionComponent extends Container {
|
|
|
32
33
|
private hideComponent;
|
|
33
34
|
/** True when the result is the generic Text fallback, which clampBody may trim. */
|
|
34
35
|
private resultIsFallback;
|
|
35
|
-
constructor(toolName: string, toolCallId: string, args: any, options: ToolExecutionOptions | undefined, toolDefinition: ToolDefinition<any, any> | undefined, ui: TUI, cwd: string);
|
|
36
|
+
constructor(toolName: string, toolCallId: string, args: any, options: ToolExecutionOptions | undefined, toolDefinition: ToolDefinition<any, any> | undefined, ui: TUI, cwd: string, toolRenderer?: ToolRendererOverride);
|
|
36
37
|
private getCallRenderer;
|
|
37
38
|
private getResultRenderer;
|
|
38
39
|
private hasRendererDefinition;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import { Box, type Component, Container, getCapabilities, Image, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.ts\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.ts\";\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.ts\";\nimport { convertToPng } from \"../../../utils/image-convert.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { panelize } from \"./panel.ts\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\tprivate static readonly COLLAPSED_OUTPUT_LINES = 10;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\t/** True when the result is the generic Text fallback, which clampBody may trim. */\n\tprivate resultIsFallback = false;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\tthis.contentBox = new Box(1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.contentText = new Text(\"\", 1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox);\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(this.toolName)), 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\t// Clamped at render time instead of here: this counts newlines, but tools\n\t\t// that answer with one long JSON line (every MCP tool, gitnexus_context\n\t\t// among them) have almost none, so a newline-based clamp never fires and\n\t\t// the whole payload wraps across the transcript. render() knows the width\n\t\t// and therefore the real row count.\n\t\treturn new Text(theme.fg(\"toolOutput\", output), 0, 0);\n\t}\n\n\t/** Clamp wrapped rows, so a single long line collapses like many short ones. */\n\tprivate clampBody(rows: string[]): string[] {\n\t\tif (!this.resultIsFallback || this.expanded) return rows;\n\t\tif (rows.length <= ToolExecutionComponent.COLLAPSED_OUTPUT_LINES) return rows;\n\t\tconst hidden = rows.length - ToolExecutionComponent.COLLAPSED_OUTPUT_LINES;\n\t\treturn [\n\t\t\t...rows.slice(0, ToolExecutionComponent.COLLAPSED_OUTPUT_LINES),\n\t\t\ttheme.fg(\"dim\", `… ${hidden} more lines (click or ctrl+o)`),\n\t\t];\n\t}\n\n\t/** Click toggles this tool's output expansion (fullscreen mouse routing). */\n\thandleClick(_x: number, _y: number): boolean {\n\t\tthis.expanded = !this.expanded;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t\treturn true;\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && this.getRenderShell() === \"self\") {\n\t\t\tconst contentLines = this.selfRenderContainer.render(width);\n\t\t\tif (contentLines.length === 0 && this.imageComponents.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst lines: string[] = [];\n\t\t\tif (contentLines.length > 0) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(...contentLines);\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) {\n\t\t\t\t\tlines.push(...spacer.render(width));\n\t\t\t\t}\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) {\n\t\t\t\t\tlines.push(...imageComponent.render(width));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\t// Crush-style block: status glyph + header on the default background,\n\t\t\t// tool output in a neutral content-width panel underneath.\n\t\t\tconst lines: string[] = [\"\"];\n\t\t\tconst glyph = this.isPartial\n\t\t\t\t? theme.fg(\"accent\", \"●\")\n\t\t\t\t: this.result?.isError\n\t\t\t\t\t? theme.fg(\"error\", \"×\")\n\t\t\t\t\t: theme.fg(\"success\", \"✓\");\n\t\t\tconst headerLines = this.callRendererComponent?.render(Math.max(1, width - 3)) ?? [];\n\t\t\theaderLines.forEach((line, i) => {\n\t\t\t\tlines.push(i === 0 ? ` ${glyph} ${line}` : ` ${line}`);\n\t\t\t});\n\t\t\tif (headerLines.length === 0) {\n\t\t\t\tlines.push(` ${glyph} ${theme.fg(\"toolTitle\", theme.bold(this.toolName))}`);\n\t\t\t}\n\t\t\tconst bodyLines = this.clampBody(this.resultRendererComponent?.render(Math.max(1, width - 6)) ?? []);\n\t\t\tif (bodyLines.length > 0) {\n\t\t\t\t// Crush-style ERROR pill above failed output.\n\t\t\t\tconst body = this.result?.isError\n\t\t\t\t\t? [`${theme.inverse(theme.bold(theme.fg(\"error\", \" ERROR \")))} `, ...bodyLines]\n\t\t\t\t\t: bodyLines;\n\t\t\t\tlines.push(...panelize(body, width, this.result?.isError ? \"toolErrorBg\" : \"toolPendingBg\", 3));\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) lines.push(...spacer.render(width));\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) lines.push(...imageComponent.render(width));\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tconst bgFn = this.isPartial\n\t\t\t? (text: string) => theme.bg(\"toolPendingBg\", text)\n\t\t\t: this.result?.isError\n\t\t\t\t? (text: string) => theme.bg(\"toolErrorBg\", text)\n\t\t\t\t: (text: string) => theme.bg(\"toolSuccessBg\", text);\n\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tconst renderContainer = this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(bgFn);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\tif (!callRenderer) {\n\t\t\t\tthis.callRendererComponent = this.createCallFallback();\n\t\t\t\trenderContainer.addChild(this.callRendererComponent);\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\thasContent = true;\n\t\t\t\t} catch {\n\t\t\t\t\tthis.callRendererComponent = this.createCallFallback();\n\t\t\t\t\trenderContainer.addChild(this.callRendererComponent);\n\t\t\t\t\thasContent = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\tthis.resultIsFallback = true;\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\tthis.resultIsFallback = false;\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\tthis.resultIsFallback = true;\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.contentText.setCustomBgFn(bgFn);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tlet text = theme.fg(\"toolTitle\", theme.bold(this.toolName));\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.getTextOutput();\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import { Box, type Component, Container, getCapabilities, Image, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { ToolDefinition, ToolRenderContext, ToolRendererOverride } from \"../../../core/extensions/types.ts\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.ts\";\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.ts\";\nimport { convertToPng } from \"../../../utils/image-convert.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { panelize } from \"./panel.ts\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\tprivate static readonly COLLAPSED_OUTPUT_LINES = 10;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate toolRenderer?: ToolRendererOverride;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\t/** True when the result is the generic Text fallback, which clampBody may trim. */\n\tprivate resultIsFallback = false;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t\ttoolRenderer?: ToolRendererOverride,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.toolRenderer = toolRenderer;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\tthis.contentBox = new Box(1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.contentText = new Text(\"\", 1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox);\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (this.toolRenderer?.renderCall) return this.toolRenderer.renderCall;\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (this.toolRenderer?.renderResult) return this.toolRenderer.renderResult;\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn (\n\t\t\tthis.builtInToolDefinition !== undefined ||\n\t\t\tthis.toolDefinition !== undefined ||\n\t\t\tthis.toolRenderer !== undefined\n\t\t);\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (this.toolRenderer?.renderShell) return this.toolRenderer.renderShell;\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(this.toolName)), 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\t// Clamped at render time instead of here: this counts newlines, but tools\n\t\t// that answer with one long JSON line (every MCP tool, gitnexus_context\n\t\t// among them) have almost none, so a newline-based clamp never fires and\n\t\t// the whole payload wraps across the transcript. render() knows the width\n\t\t// and therefore the real row count.\n\t\treturn new Text(theme.fg(\"toolOutput\", output), 0, 0);\n\t}\n\n\t/** Clamp wrapped rows, so a single long line collapses like many short ones. */\n\tprivate clampBody(rows: string[]): string[] {\n\t\tif (!this.resultIsFallback || this.expanded) return rows;\n\t\tif (rows.length <= ToolExecutionComponent.COLLAPSED_OUTPUT_LINES) return rows;\n\t\tconst hidden = rows.length - ToolExecutionComponent.COLLAPSED_OUTPUT_LINES;\n\t\treturn [\n\t\t\t...rows.slice(0, ToolExecutionComponent.COLLAPSED_OUTPUT_LINES),\n\t\t\ttheme.fg(\"dim\", `… ${hidden} more lines (click or ctrl+o)`),\n\t\t];\n\t}\n\n\t/** Click toggles this tool's output expansion (fullscreen mouse routing). */\n\thandleClick(_x: number, _y: number): boolean {\n\t\tthis.expanded = !this.expanded;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t\treturn true;\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && this.getRenderShell() === \"self\") {\n\t\t\tconst contentLines = this.selfRenderContainer.render(width);\n\t\t\tif (contentLines.length === 0 && this.imageComponents.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst lines: string[] = [];\n\t\t\tif (contentLines.length > 0) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(...contentLines);\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) {\n\t\t\t\t\tlines.push(...spacer.render(width));\n\t\t\t\t}\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) {\n\t\t\t\t\tlines.push(...imageComponent.render(width));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\t// Crush-style block: status glyph + header on the default background,\n\t\t\t// tool output in a neutral content-width panel underneath.\n\t\t\tconst lines: string[] = [\"\"];\n\t\t\tconst glyph = this.isPartial\n\t\t\t\t? theme.fg(\"accent\", \"●\")\n\t\t\t\t: this.result?.isError\n\t\t\t\t\t? theme.fg(\"error\", \"×\")\n\t\t\t\t\t: theme.fg(\"success\", \"✓\");\n\t\t\tconst headerLines = this.callRendererComponent?.render(Math.max(1, width - 3)) ?? [];\n\t\t\theaderLines.forEach((line, i) => {\n\t\t\t\tlines.push(i === 0 ? ` ${glyph} ${line}` : ` ${line}`);\n\t\t\t});\n\t\t\tif (headerLines.length === 0) {\n\t\t\t\tlines.push(` ${glyph} ${theme.fg(\"toolTitle\", theme.bold(this.toolName))}`);\n\t\t\t}\n\t\t\tconst bodyLines = this.clampBody(this.resultRendererComponent?.render(Math.max(1, width - 6)) ?? []);\n\t\t\tif (bodyLines.length > 0) {\n\t\t\t\t// Crush-style ERROR pill above failed output.\n\t\t\t\tconst body = this.result?.isError\n\t\t\t\t\t? [`${theme.inverse(theme.bold(theme.fg(\"error\", \" ERROR \")))} `, ...bodyLines]\n\t\t\t\t\t: bodyLines;\n\t\t\t\tlines.push(...panelize(body, width, this.result?.isError ? \"toolErrorBg\" : \"toolPendingBg\", 3));\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) lines.push(...spacer.render(width));\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) lines.push(...imageComponent.render(width));\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tconst bgFn = this.isPartial\n\t\t\t? (text: string) => theme.bg(\"toolPendingBg\", text)\n\t\t\t: this.result?.isError\n\t\t\t\t? (text: string) => theme.bg(\"toolErrorBg\", text)\n\t\t\t\t: (text: string) => theme.bg(\"toolSuccessBg\", text);\n\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tconst renderContainer = this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(bgFn);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\tif (!callRenderer) {\n\t\t\t\tthis.callRendererComponent = this.createCallFallback();\n\t\t\t\trenderContainer.addChild(this.callRendererComponent);\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\thasContent = true;\n\t\t\t\t} catch {\n\t\t\t\t\tthis.callRendererComponent = this.createCallFallback();\n\t\t\t\t\trenderContainer.addChild(this.callRendererComponent);\n\t\t\t\t\thasContent = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\tthis.resultIsFallback = true;\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\tthis.resultIsFallback = false;\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\tthis.resultIsFallback = true;\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.contentText.setCustomBgFn(bgFn);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tlet text = theme.fg(\"toolTitle\", theme.bold(this.toolName));\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.getTextOutput();\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
|
|
@@ -23,6 +23,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
23
23
|
isPartial = true;
|
|
24
24
|
toolDefinition;
|
|
25
25
|
builtInToolDefinition;
|
|
26
|
+
toolRenderer;
|
|
26
27
|
ui;
|
|
27
28
|
cwd;
|
|
28
29
|
executionStarted = false;
|
|
@@ -32,12 +33,13 @@ export class ToolExecutionComponent extends Container {
|
|
|
32
33
|
hideComponent = false;
|
|
33
34
|
/** True when the result is the generic Text fallback, which clampBody may trim. */
|
|
34
35
|
resultIsFallback = false;
|
|
35
|
-
constructor(toolName, toolCallId, args, options = {}, toolDefinition, ui, cwd) {
|
|
36
|
+
constructor(toolName, toolCallId, args, options = {}, toolDefinition, ui, cwd, toolRenderer) {
|
|
36
37
|
super();
|
|
37
38
|
this.toolName = toolName;
|
|
38
39
|
this.toolCallId = toolCallId;
|
|
39
40
|
this.args = args;
|
|
40
41
|
this.toolDefinition = toolDefinition;
|
|
42
|
+
this.toolRenderer = toolRenderer;
|
|
41
43
|
this.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName];
|
|
42
44
|
this.showImages = options.showImages ?? true;
|
|
43
45
|
this.imageWidthCells = options.imageWidthCells ?? 60;
|
|
@@ -59,6 +61,8 @@ export class ToolExecutionComponent extends Container {
|
|
|
59
61
|
this.updateDisplay();
|
|
60
62
|
}
|
|
61
63
|
getCallRenderer() {
|
|
64
|
+
if (this.toolRenderer?.renderCall)
|
|
65
|
+
return this.toolRenderer.renderCall;
|
|
62
66
|
if (!this.builtInToolDefinition) {
|
|
63
67
|
return this.toolDefinition?.renderCall;
|
|
64
68
|
}
|
|
@@ -68,6 +72,8 @@ export class ToolExecutionComponent extends Container {
|
|
|
68
72
|
return this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;
|
|
69
73
|
}
|
|
70
74
|
getResultRenderer() {
|
|
75
|
+
if (this.toolRenderer?.renderResult)
|
|
76
|
+
return this.toolRenderer.renderResult;
|
|
71
77
|
if (!this.builtInToolDefinition) {
|
|
72
78
|
return this.toolDefinition?.renderResult;
|
|
73
79
|
}
|
|
@@ -77,9 +83,13 @@ export class ToolExecutionComponent extends Container {
|
|
|
77
83
|
return this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;
|
|
78
84
|
}
|
|
79
85
|
hasRendererDefinition() {
|
|
80
|
-
return this.builtInToolDefinition !== undefined ||
|
|
86
|
+
return (this.builtInToolDefinition !== undefined ||
|
|
87
|
+
this.toolDefinition !== undefined ||
|
|
88
|
+
this.toolRenderer !== undefined);
|
|
81
89
|
}
|
|
82
90
|
getRenderShell() {
|
|
91
|
+
if (this.toolRenderer?.renderShell)
|
|
92
|
+
return this.toolRenderer.renderShell;
|
|
83
93
|
if (!this.builtInToolDefinition) {
|
|
84
94
|
return this.toolDefinition?.renderShell ?? "default";
|
|
85
95
|
}
|