@jx-grxf/patchpilot 0.2.0

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.
Files changed (95) hide show
  1. package/.env.example +13 -0
  2. package/LICENSE +21 -0
  3. package/README.md +314 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +71 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/core/agent.d.ts +21 -0
  8. package/dist/core/agent.js +346 -0
  9. package/dist/core/agent.js.map +1 -0
  10. package/dist/core/codex.d.ts +22 -0
  11. package/dist/core/codex.js +242 -0
  12. package/dist/core/codex.js.map +1 -0
  13. package/dist/core/compute.d.ts +9 -0
  14. package/dist/core/compute.js +18 -0
  15. package/dist/core/compute.js.map +1 -0
  16. package/dist/core/doctor.d.ts +7 -0
  17. package/dist/core/doctor.js +226 -0
  18. package/dist/core/doctor.js.map +1 -0
  19. package/dist/core/env.d.ts +6 -0
  20. package/dist/core/env.js +103 -0
  21. package/dist/core/env.js.map +1 -0
  22. package/dist/core/gemini.d.ts +20 -0
  23. package/dist/core/gemini.js +177 -0
  24. package/dist/core/gemini.js.map +1 -0
  25. package/dist/core/json.d.ts +3 -0
  26. package/dist/core/json.js +95 -0
  27. package/dist/core/json.js.map +1 -0
  28. package/dist/core/modelClient.d.ts +8 -0
  29. package/dist/core/modelClient.js +42 -0
  30. package/dist/core/modelClient.js.map +1 -0
  31. package/dist/core/nvidia.d.ts +19 -0
  32. package/dist/core/nvidia.js +160 -0
  33. package/dist/core/nvidia.js.map +1 -0
  34. package/dist/core/ollama.d.ts +31 -0
  35. package/dist/core/ollama.js +176 -0
  36. package/dist/core/ollama.js.map +1 -0
  37. package/dist/core/openrouter.d.ts +27 -0
  38. package/dist/core/openrouter.js +168 -0
  39. package/dist/core/openrouter.js.map +1 -0
  40. package/dist/core/subagents.d.ts +14 -0
  41. package/dist/core/subagents.js +89 -0
  42. package/dist/core/subagents.js.map +1 -0
  43. package/dist/core/tokenAccounting.d.ts +6 -0
  44. package/dist/core/tokenAccounting.js +134 -0
  45. package/dist/core/tokenAccounting.js.map +1 -0
  46. package/dist/core/types.d.ts +90 -0
  47. package/dist/core/types.js +2 -0
  48. package/dist/core/types.js.map +1 -0
  49. package/dist/core/workspace.d.ts +28 -0
  50. package/dist/core/workspace.js +616 -0
  51. package/dist/core/workspace.js.map +1 -0
  52. package/dist/tui/App.d.ts +6 -0
  53. package/dist/tui/App.js +1717 -0
  54. package/dist/tui/App.js.map +1 -0
  55. package/dist/tui/commands.d.ts +14 -0
  56. package/dist/tui/commands.js +210 -0
  57. package/dist/tui/commands.js.map +1 -0
  58. package/dist/tui/components/CommandSuggestions.d.ts +12 -0
  59. package/dist/tui/components/CommandSuggestions.js +12 -0
  60. package/dist/tui/components/CommandSuggestions.js.map +1 -0
  61. package/dist/tui/components/Composer.d.ts +13 -0
  62. package/dist/tui/components/Composer.js +29 -0
  63. package/dist/tui/components/Composer.js.map +1 -0
  64. package/dist/tui/components/Header.d.ts +25 -0
  65. package/dist/tui/components/Header.js +62 -0
  66. package/dist/tui/components/Header.js.map +1 -0
  67. package/dist/tui/components/OnboardingPanel.d.ts +38 -0
  68. package/dist/tui/components/OnboardingPanel.js +85 -0
  69. package/dist/tui/components/OnboardingPanel.js.map +1 -0
  70. package/dist/tui/components/Sidebar.d.ts +22 -0
  71. package/dist/tui/components/Sidebar.js +133 -0
  72. package/dist/tui/components/Sidebar.js.map +1 -0
  73. package/dist/tui/components/Transcript.d.ts +10 -0
  74. package/dist/tui/components/Transcript.js +111 -0
  75. package/dist/tui/components/Transcript.js.map +1 -0
  76. package/dist/tui/format.d.ts +29 -0
  77. package/dist/tui/format.js +202 -0
  78. package/dist/tui/format.js.map +1 -0
  79. package/dist/tui/hosts.d.ts +34 -0
  80. package/dist/tui/hosts.js +338 -0
  81. package/dist/tui/hosts.js.map +1 -0
  82. package/dist/tui/inputRouting.d.ts +8 -0
  83. package/dist/tui/inputRouting.js +94 -0
  84. package/dist/tui/inputRouting.js.map +1 -0
  85. package/dist/tui/platform.d.ts +2 -0
  86. package/dist/tui/platform.js +13 -0
  87. package/dist/tui/platform.js.map +1 -0
  88. package/dist/tui/systemStats.d.ts +25 -0
  89. package/dist/tui/systemStats.js +88 -0
  90. package/dist/tui/systemStats.js.map +1 -0
  91. package/dist/tui/types.d.ts +16 -0
  92. package/dist/tui/types.js +2 -0
  93. package/dist/tui/types.js.map +1 -0
  94. package/docs/showcase/patchpilot-showcase.svg +39 -0
  95. package/package.json +63 -0
@@ -0,0 +1,85 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import TextInput from "ink-text-input";
4
+ const entryOptions = [
5
+ {
6
+ label: "This Device",
7
+ description: "Run Ollama locally on this machine"
8
+ },
9
+ {
10
+ label: "Remote Host",
11
+ description: "Use Ollama from another LAN or Tailscale machine"
12
+ },
13
+ {
14
+ label: "Gemini",
15
+ description: "Use the Google Gemini API key from PatchPilot config"
16
+ },
17
+ {
18
+ label: "OpenRouter",
19
+ description: "Use OpenRouter models, including auto and free variants"
20
+ },
21
+ {
22
+ label: "NVIDIA",
23
+ description: "Use NVIDIA NIM OpenAI-compatible endpoints"
24
+ },
25
+ {
26
+ label: "Codex",
27
+ description: "Use the ChatGPT login through Codex CLI"
28
+ }
29
+ ];
30
+ export function OnboardingPanel(props) {
31
+ const currentStepIndex = props.state.step === "entry"
32
+ ? 0
33
+ : props.state.step === "host" || props.state.step === "host-input"
34
+ ? 1
35
+ : props.state.step === "api-key-choice" || props.state.step === "gemini-key" || props.state.step === "openrouter-key" || props.state.step === "nvidia-key" || props.state.step === "codex-login"
36
+ ? 2
37
+ : 3;
38
+ const visibleModels = props.state.step === "model" ? filterModelRows(props.input, props.state.models) : [];
39
+ const selectedModel = props.state.step === "model" ? visibleModels[props.selectedIndex] ?? null : null;
40
+ return (_jsxs(Box, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 2, height: props.height, overflowY: "hidden", children: [_jsx(Text, { color: "cyan", bold: true, children: "PatchPilot Setup" }), _jsx(Text, { color: "gray", children: "Choose where inference runs before the workspace session starts." }), _jsx(Box, { marginTop: 1, children: ["mode", "host", "auth", "model"].map((step, index) => (_jsxs(Text, { color: index <= currentStepIndex ? "cyan" : "gray", children: [index > 0 ? " " : "", "[", index + 1, "] ", step] }, step))) }), props.busyMessage ? (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "yellow", children: props.busyMessage }) })) : null, props.state.step === "entry" ? (_jsx(SelectionList, { title: "Where should the model run?", subtitle: "Use up/down and Enter. Escape skips setup.", rows: entryOptions, selectedIndex: props.selectedIndex })) : null, props.state.step === "host" ? (_jsx(SelectionList, { title: "Choose a host", subtitle: "Top item lets you enter a host manually. Left arrow goes back.", rows: [
41
+ {
42
+ label: "Enter Host Manually",
43
+ description: "Type a LAN IP, Tailscale IP, MagicDNS name, or full URL"
44
+ },
45
+ ...props.state.hosts.map((host) => ({
46
+ label: host.deviceName,
47
+ description: `${host.kind} ${host.url}${host.version ? ` Ollama ${host.version}` : ""}`
48
+ }))
49
+ ], selectedIndex: props.selectedIndex })) : null, props.state.step === "host-input" ? (_jsx(InputStep, { title: "Connect to a host", description: "Enter a LAN IP, Tailscale IP, MagicDNS name, or full URL.", prompt: "host > ", value: props.input, onChange: props.onInputChange, onSubmit: props.onInputSubmit })) : null, props.state.step === "api-key-choice" ? (_jsx(SelectionList, { title: `${providerLabel(props.state.provider)} API key`, subtitle: "Use up/down and Enter. Existing keys stay in PatchPilot config.", rows: [
50
+ {
51
+ label: props.state.hasExistingKey ? "Use Existing Key" : "Enter New Key",
52
+ description: props.state.hasExistingKey ? "Continue with the saved key" : "No saved key found"
53
+ },
54
+ {
55
+ label: "Enter New Key",
56
+ description: "Replace or add the key in PatchPilot config"
57
+ }
58
+ ], selectedIndex: props.selectedIndex })) : null, props.state.step === "gemini-key" ? (_jsx(InputStep, { title: "Enter your Gemini API key", description: "It will be stored in PatchPilot's config directory, not in the repository.", prompt: "key > ", value: props.input, onChange: props.onInputChange, onSubmit: props.onInputSubmit, mask: "*" })) : null, props.state.step === "openrouter-key" ? (_jsx(InputStep, { title: "Enter your OpenRouter API key", description: "It will be stored in PatchPilot's config directory, not in the repository.", prompt: "key > ", value: props.input, onChange: props.onInputChange, onSubmit: props.onInputSubmit, mask: "*" })) : null, props.state.step === "nvidia-key" ? (_jsx(InputStep, { title: "Enter your NVIDIA API key", description: "It will be stored in PatchPilot's config directory, not in the repository.", prompt: "key > ", value: props.input, onChange: props.onInputChange, onSubmit: props.onInputSubmit, mask: "*" })) : null, props.state.step === "codex-login" ? (_jsxs(Box, { flexDirection: "column", marginTop: 2, children: [_jsx(Text, { color: "white", bold: true, children: "Connect Codex CLI" }), _jsx(Text, { color: "gray", children: "Run `codex login` in another terminal, then press Enter here to continue." }), _jsx(Text, { color: "gray", children: "Escape or left arrow goes back." })] })) : null, props.state.step === "model" ? (_jsxs(_Fragment, { children: [_jsx(InputStep, { title: `Choose a ${props.state.provider} model${props.state.deviceName ? ` on ${props.state.deviceName}` : ""}`, description: "Type to search. Use up/down and Enter. Left arrow goes back.", prompt: "find > ", value: props.input, onChange: props.onInputChange, onSubmit: props.onInputSubmit }), _jsx(SelectionList, { title: "", subtitle: `${visibleModels.length} matching model${visibleModels.length === 1 ? "" : "s"}`, rows: visibleModels.map((model) => ({
59
+ label: model,
60
+ description: model === selectedModel ? "selected" : "available"
61
+ })), selectedIndex: props.selectedIndex })] })) : null, _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Remote host mode keeps file reads, writes, shell, Git, and tests on this device. Only inference moves." }) })] }));
62
+ }
63
+ function providerLabel(provider) {
64
+ return provider === "openrouter" ? "OpenRouter" : provider === "nvidia" ? "NVIDIA" : "Gemini";
65
+ }
66
+ function filterModelRows(query, models) {
67
+ const normalizedQuery = query.trim().toLowerCase();
68
+ if (!normalizedQuery) {
69
+ return models;
70
+ }
71
+ return models.filter((model) => normalizedQuery.split(/\s+/).every((token) => model.toLowerCase().includes(token)));
72
+ }
73
+ function InputStep(props) {
74
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 2, children: [_jsx(Text, { color: "white", bold: true, children: props.title }), _jsx(Text, { color: "gray", children: props.description }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: props.prompt }), _jsx(TextInput, { value: props.value, onChange: props.onChange, onSubmit: props.onSubmit, mask: props.mask })] })] }));
75
+ }
76
+ function SelectionList(props) {
77
+ const startIndex = Math.max(0, Math.min(props.selectedIndex - 4, Math.max(0, props.rows.length - 8)));
78
+ const visibleRows = props.rows.slice(startIndex, startIndex + 8);
79
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 2, children: [_jsx(Text, { color: "white", bold: true, children: props.title }), _jsx(Text, { color: "gray", children: props.subtitle }), visibleRows.map((row, index) => {
80
+ const absoluteIndex = startIndex + index;
81
+ const isSelected = absoluteIndex === props.selectedIndex;
82
+ return (_jsxs(Box, { marginTop: 1, children: [_jsx(Box, { width: 3, children: _jsx(Text, { color: isSelected ? "cyan" : "gray", children: isSelected ? ">" : " " }) }), _jsx(Box, { width: 28, children: _jsx(Text, { color: isSelected ? "white" : "cyan", bold: isSelected, wrap: "truncate", children: row.label }) }), _jsx(Text, { color: isSelected ? "white" : "gray", wrap: "truncate", children: row.description })] }, `${absoluteIndex}-${row.label}`));
83
+ })] }));
84
+ }
85
+ //# sourceMappingURL=OnboardingPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OnboardingPanel.js","sourceRoot":"","sources":["../../../src/tui/components/OnboardingPanel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import React from "react";
2
+ import type { ModelProvider, ModelTelemetry, SessionTelemetry } from "../../core/types.js";
3
+ import type { OllamaHostDetails } from "../hosts.js";
4
+ import type { AgentMode, AdvisorNote } from "../types.js";
5
+ export declare function Sidebar(props: {
6
+ workspace: string;
7
+ model: string;
8
+ provider: ModelProvider;
9
+ ollamaUrl: string;
10
+ agentMode: AgentMode;
11
+ allowWrite: boolean;
12
+ allowShell: boolean;
13
+ subagents: boolean;
14
+ telemetry: ModelTelemetry | null;
15
+ sessionTelemetry: SessionTelemetry;
16
+ draftTokens: number;
17
+ advisors: AdvisorNote[];
18
+ height: number;
19
+ scrollOffset: number;
20
+ isActive: boolean;
21
+ activeHost: OllamaHostDetails | null;
22
+ }): React.ReactElement;
@@ -0,0 +1,133 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import { formatCost, formatOllamaHost, formatSessionTokens, formatTokens, shortenMiddle } from "../format.js";
4
+ export function Sidebar(props) {
5
+ const rows = buildSidebarRows(props);
6
+ const visibleRowCount = Math.max(1, props.height - 2);
7
+ const hasOverflow = rows.length > visibleRowCount;
8
+ const contentRowCount = hasOverflow ? Math.max(1, visibleRowCount - 1) : visibleRowCount;
9
+ const clampedOffset = clampScrollOffset(props.scrollOffset, rows.length, contentRowCount);
10
+ const visibleRows = rows.slice(Math.max(0, rows.length - contentRowCount - clampedOffset), rows.length - clampedOffset);
11
+ return (_jsxs(Box, { width: 32, height: props.height, overflowY: "hidden", borderStyle: "round", borderColor: props.isActive ? "cyan" : "gray", flexDirection: "column", paddingX: 1, marginRight: 1, children: [visibleRows.map((row, index) => (_jsx(Text, { color: row.color, bold: row.bold, wrap: "truncate", children: row.text }, `${index}-${row.text}`))), hasOverflow ? (_jsxs(Text, { color: "gray", wrap: "truncate", children: ["scroll ", Math.max(1, rows.length - contentRowCount - clampedOffset + 1), "-", Math.min(rows.length, rows.length - clampedOffset), "/", rows.length] })) : null] }));
12
+ }
13
+ function buildSidebarRows(props) {
14
+ const hostDeviceName = props.provider === "ollama" ? props.activeHost?.host.deviceName ?? formatOllamaHost(props.ollamaUrl) : `${props.provider} api`;
15
+ const hostRoute = props.provider === "ollama" ? props.activeHost?.host.url ?? props.ollamaUrl : `${props.provider} cloud`;
16
+ const hostNetwork = props.provider === "ollama" ? props.activeHost?.host.kind ?? "local" : "cloud";
17
+ const hostVersion = props.activeHost?.host.version ?? "-";
18
+ const hostModels = props.activeHost ? `${props.activeHost.models.length} available` : "-";
19
+ const hostLoaded = props.activeHost?.runningModels.length ? props.activeHost.runningModels.map((model) => formatRunningModel(model)).join(", ") : "idle";
20
+ const rows = [
21
+ section("Session"),
22
+ row("provider", props.provider, props.provider === "ollama" ? "green" : "cyan"),
23
+ row("mode", props.agentMode, props.agentMode === "build" ? "yellow" : "green"),
24
+ row("write", props.allowWrite ? "on" : "off", props.allowWrite ? "green" : "red"),
25
+ row("shell", props.allowShell ? "on" : "off", props.allowShell ? "green" : "red"),
26
+ row("agents", props.subagents ? "on" : "off", props.subagents ? "cyan" : "gray"),
27
+ spacer(),
28
+ section("Host"),
29
+ row("device", shortenMiddle(hostDeviceName, 19), "yellow"),
30
+ row("network", hostNetwork, "green"),
31
+ muted(shortenMiddle(hostRoute, 28)),
32
+ muted(`version ${hostVersion}`),
33
+ muted(`models ${hostModels}`),
34
+ ...wrapSidebarText(`loaded ${hostLoaded}`),
35
+ muted(shortenMiddle(props.model, 28)),
36
+ spacer(),
37
+ section("Workspace"),
38
+ ...wrapSidebarText(shortenMiddle(props.workspace, 58)),
39
+ spacer(),
40
+ section("Telemetry"),
41
+ muted(`draft ${props.draftTokens} tok`),
42
+ ...wrapSidebarText(formatTokens(props.telemetry)),
43
+ ...wrapSidebarText(formatSessionTokens(props.sessionTelemetry)),
44
+ muted(formatCost(props.sessionTelemetry.estimatedCostUsd)),
45
+ spacer(),
46
+ section("Advisors")
47
+ ];
48
+ if (props.advisors.length === 0) {
49
+ rows.push(muted("No advisor output yet."));
50
+ return rows;
51
+ }
52
+ for (const advisor of props.advisors) {
53
+ rows.push({
54
+ text: advisor.role,
55
+ color: "yellow"
56
+ });
57
+ rows.push(...summarizeAdvisorText(advisor.message));
58
+ rows.push(spacer());
59
+ }
60
+ return rows;
61
+ }
62
+ function section(text) {
63
+ return {
64
+ text,
65
+ color: "cyan",
66
+ bold: true
67
+ };
68
+ }
69
+ function row(label, value, color) {
70
+ return {
71
+ text: `${label.padEnd(9)}${value}`,
72
+ color
73
+ };
74
+ }
75
+ function muted(text) {
76
+ return {
77
+ text,
78
+ color: "gray"
79
+ };
80
+ }
81
+ function spacer() {
82
+ return muted("");
83
+ }
84
+ function wrapSidebarText(value) {
85
+ return wrapText(value, 28).map(muted);
86
+ }
87
+ function summarizeAdvisorText(value) {
88
+ const summary = value
89
+ .replace(/\*\*/g, "")
90
+ .split(/\r?\n/)
91
+ .map((line) => line.replace(/^[-*]\s*/, "").trim())
92
+ .filter(Boolean)
93
+ .slice(0, 3)
94
+ .join(" ");
95
+ const rows = wrapText(summary || "Advisor brief available in transcript.", 28).slice(0, 4);
96
+ return rows.map(muted);
97
+ }
98
+ function formatRunningModel(model) {
99
+ const vram = model.sizeVramBytes ? ` ${Math.round((model.sizeVramBytes / 1024 ** 3) * 10) / 10}G vram` : "";
100
+ return `${model.name}${vram}`;
101
+ }
102
+ function clampScrollOffset(offset, rowCount, visibleRowCount) {
103
+ return Math.max(0, Math.min(offset, Math.max(0, rowCount - visibleRowCount)));
104
+ }
105
+ function wrapText(value, width) {
106
+ return value
107
+ .split(/\r?\n/)
108
+ .flatMap((line) => wrapLine(line, width));
109
+ }
110
+ function wrapLine(value, width) {
111
+ const words = value.trimEnd().split(/\s+/).filter(Boolean);
112
+ if (words.length === 0) {
113
+ return [""];
114
+ }
115
+ const rows = [];
116
+ let currentRow = "";
117
+ for (const word of words) {
118
+ const nextRow = currentRow ? `${currentRow} ${word}` : word;
119
+ if (nextRow.length <= width) {
120
+ currentRow = nextRow;
121
+ continue;
122
+ }
123
+ if (currentRow) {
124
+ rows.push(currentRow);
125
+ }
126
+ currentRow = word.length > width ? shortenMiddle(word, width) : word;
127
+ }
128
+ if (currentRow) {
129
+ rows.push(currentRow);
130
+ }
131
+ return rows;
132
+ }
133
+ //# sourceMappingURL=Sidebar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sidebar.js","sourceRoot":"","sources":["../../../src/tui/components/Sidebar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import type { LogLine } from "../types.js";
3
+ export declare function Transcript(props: {
4
+ lines: LogLine[];
5
+ isRunning: boolean;
6
+ isActive: boolean;
7
+ height: number;
8
+ width: number;
9
+ scrollOffset: number;
10
+ }): React.ReactElement;
@@ -0,0 +1,111 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import { toneToColor, toneToMarker } from "../format.js";
4
+ export function Transcript(props) {
5
+ const rows = props.lines.length === 0 ? emptyRows() : buildTranscriptRows(props.lines, props.width);
6
+ const visibleRowCount = Math.max(1, props.height - 2);
7
+ const hasOverflow = rows.length > visibleRowCount;
8
+ const contentRowCount = hasOverflow ? Math.max(1, visibleRowCount - 1) : visibleRowCount;
9
+ const clampedOffset = clampScrollOffset(props.scrollOffset, rows.length, contentRowCount);
10
+ const visibleRows = rows.slice(Math.max(0, rows.length - contentRowCount - clampedOffset), rows.length - clampedOffset);
11
+ return (_jsxs(Box, { borderStyle: "round", borderColor: props.isActive ? "cyan" : props.isRunning ? "yellow" : "gray", flexDirection: "column", paddingX: 1, height: props.height, overflowY: "hidden", flexGrow: 1, children: [visibleRows.map((row, index) => (_jsx(TranscriptRowView, { row: row }, `${index}-${row.marker}-${row.label}-${row.text}`))), hasOverflow ? _jsx(ScrollHint, { offset: clampedOffset, total: rows.length, visible: contentRowCount }) : null] }));
12
+ }
13
+ function TranscriptRowView(props) {
14
+ return (_jsxs(Box, { children: [_jsx(Box, { width: 3, children: _jsx(Text, { color: props.row.color, children: props.row.marker }) }), _jsx(Box, { width: 13, children: _jsx(Text, { color: props.row.color, bold: props.row.bold, children: props.row.label }) }), _jsx(Text, { color: props.row.color, wrap: "truncate", children: props.row.text })] }));
15
+ }
16
+ function ScrollHint(props) {
17
+ const start = Math.max(1, props.total - props.visible - props.offset + 1);
18
+ const end = Math.min(props.total, props.total - props.offset);
19
+ return (_jsxs(Box, { children: [_jsx(Box, { width: 16, children: _jsx(Text, { color: "gray", children: "scroll" }) }), _jsxs(Text, { color: "gray", children: [start, "-", end, "/", props.total, " pgup/pgdn"] })] }));
20
+ }
21
+ function buildTranscriptRows(lines, width) {
22
+ const textWidth = Math.max(18, width - 18);
23
+ return lines.flatMap((line) => {
24
+ const color = toneToColor(line.tone);
25
+ const marker = toneToMarker(line.tone);
26
+ const textRows = wrapText(line.text, textWidth);
27
+ const detailRows = line.detail ? wrapText(line.detail, textWidth) : [];
28
+ const rows = textRows.map((text, index) => ({
29
+ marker: index === 0 ? marker : "",
30
+ label: index === 0 ? line.label : "",
31
+ text,
32
+ color,
33
+ bold: index === 0
34
+ }));
35
+ rows.push(...detailRows.map((text) => ({
36
+ marker: "",
37
+ label: "",
38
+ text,
39
+ color: "gray"
40
+ })));
41
+ if (line.detail) {
42
+ rows.push({
43
+ marker: "",
44
+ label: "",
45
+ text: "",
46
+ color: "gray"
47
+ });
48
+ }
49
+ return rows;
50
+ });
51
+ }
52
+ function emptyRows() {
53
+ return [
54
+ {
55
+ marker: "",
56
+ label: "",
57
+ text: "No session activity yet.",
58
+ color: "gray"
59
+ },
60
+ {
61
+ marker: "",
62
+ label: "",
63
+ text: "Ask for a repo summary, a focused patch, or type /help.",
64
+ color: "gray"
65
+ }
66
+ ];
67
+ }
68
+ function clampScrollOffset(offset, rowCount, visibleRowCount) {
69
+ return Math.max(0, Math.min(offset, Math.max(0, rowCount - visibleRowCount)));
70
+ }
71
+ function wrapText(value, width) {
72
+ const rows = value
73
+ .split(/\r?\n/)
74
+ .flatMap((line) => wrapLine(line, width));
75
+ return rows.length > 0 ? rows : [""];
76
+ }
77
+ function wrapLine(value, width) {
78
+ const words = value.trimEnd().split(/\s+/).filter(Boolean);
79
+ if (words.length === 0) {
80
+ return [""];
81
+ }
82
+ const rows = [];
83
+ let currentRow = "";
84
+ for (const word of words) {
85
+ const chunks = chunkWord(word, width);
86
+ for (const chunk of chunks) {
87
+ const nextRow = currentRow ? `${currentRow} ${chunk}` : chunk;
88
+ if (nextRow.length <= width) {
89
+ currentRow = nextRow;
90
+ continue;
91
+ }
92
+ rows.push(currentRow);
93
+ currentRow = chunk;
94
+ }
95
+ }
96
+ if (currentRow) {
97
+ rows.push(currentRow);
98
+ }
99
+ return rows;
100
+ }
101
+ function chunkWord(word, width) {
102
+ if (word.length <= width) {
103
+ return [word];
104
+ }
105
+ const chunks = [];
106
+ for (let index = 0; index < word.length; index += width) {
107
+ chunks.push(word.slice(index, index + width));
108
+ }
109
+ return chunks;
110
+ }
111
+ //# sourceMappingURL=Transcript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Transcript.js","sourceRoot":"","sources":["../../../src/tui/components/Transcript.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { ModelTelemetry, SessionTelemetry } from "../core/types.js";
2
+ import type { GpuStats } from "./systemStats.js";
3
+ import type { LogTone } from "./types.js";
4
+ export type InkColor = "gray" | "white" | "green" | "yellow" | "red" | "cyan";
5
+ export type StatusColor = "gray" | "green" | "yellow" | "red" | "cyan";
6
+ export declare function getModelHint(model: string): {
7
+ text: string;
8
+ color: "green" | "yellow";
9
+ };
10
+ export declare function formatOllamaHost(value: string): string;
11
+ export declare function formatTokens(telemetry: ModelTelemetry | null): string;
12
+ export declare function formatSessionTokens(session: SessionTelemetry): string;
13
+ export declare function formatCost(value: number | null): string;
14
+ export declare function formatSpeed(telemetry: ModelTelemetry | null): string;
15
+ export declare function formatLatency(telemetry: ModelTelemetry | null): string;
16
+ export declare function formatDuration(durationMs: number): string;
17
+ export declare function formatPercent(value: number | null): string;
18
+ export declare function usageColor(value: number | null): "gray" | "green" | "yellow" | "red";
19
+ export declare function gpuMemoryColor(stats: GpuStats | null): "gray" | "green" | "yellow" | "red";
20
+ export declare function temperatureColor(value: number | null): "gray" | "green" | "yellow" | "red";
21
+ export declare function formatGpuUtilization(stats: GpuStats | null): string;
22
+ export declare function formatGpuMemory(stats: GpuStats | null): string;
23
+ export declare function formatGpuTemperature(stats: GpuStats | null): string;
24
+ export declare function formatGpuPower(stats: GpuStats | null): string;
25
+ export declare function readToggle(value: string | undefined, fallback: boolean): boolean;
26
+ export declare function normalizeModelAlias(value: string): string;
27
+ export declare function shortenMiddle(value: string, maxLength: number): string;
28
+ export declare function toneToColor(tone: LogTone): InkColor;
29
+ export declare function toneToMarker(tone: LogTone): string;
@@ -0,0 +1,202 @@
1
+ export function getModelHint(model) {
2
+ const normalizedModel = model.toLowerCase();
3
+ if (/\bcoder\b|qwen.*coder|deepseek-coder|codestral|starcoder|dracarys/i.test(normalizedModel)) {
4
+ return {
5
+ text: "coding model ready",
6
+ color: "green"
7
+ };
8
+ }
9
+ if (/(llama-?3(\.\d+)?|nemotron|deepseek|qwen|mixtral|mistral|gemini|claude|gpt|o\d)/i.test(normalizedModel) &&
10
+ (/\b(49b|70b|72b|90b|120b|405b|large|pro|super|ultra|sonnet|opus|reason)\b/i.test(normalizedModel) || /gpt-[45]|claude|gemini-2\.5-pro|o\d/i.test(normalizedModel))) {
11
+ return {
12
+ text: "agent-capable model selected",
13
+ color: "green"
14
+ };
15
+ }
16
+ return {
17
+ text: "general model selected; coding reliability may be weak",
18
+ color: "yellow"
19
+ };
20
+ }
21
+ export function formatOllamaHost(value) {
22
+ if (!value) {
23
+ return "not connected";
24
+ }
25
+ try {
26
+ const url = new URL(value);
27
+ if (url.hostname === "127.0.0.1" || url.hostname === "localhost") {
28
+ return "local";
29
+ }
30
+ return url.host;
31
+ }
32
+ catch {
33
+ return value;
34
+ }
35
+ }
36
+ export function formatTokens(telemetry) {
37
+ if (!telemetry) {
38
+ return "-";
39
+ }
40
+ const cacheSuffix = telemetry.cachedPromptTokens > 0 && telemetry.promptTokens > 0
41
+ ? `/${telemetry.cachedPromptTokens} cached ${formatCacheHitRate(telemetry.cachedPromptTokens, telemetry.promptTokens)}`
42
+ : "";
43
+ const sourceSuffix = telemetry.tokenSource === "estimated" ? " est" : "";
44
+ return `${telemetry.promptTokens} in${cacheSuffix}/${telemetry.responseTokens} out/${telemetry.totalTokens} total${sourceSuffix}`;
45
+ }
46
+ export function formatSessionTokens(session) {
47
+ if (session.requests === 0) {
48
+ return "-";
49
+ }
50
+ const cacheSuffix = session.cachedPromptTokens > 0 && session.promptTokens > 0
51
+ ? `/${session.cachedPromptTokens} cached ${formatCacheHitRate(session.cachedPromptTokens, session.promptTokens)}`
52
+ : "";
53
+ return `${session.requests} req ${session.promptTokens} in${cacheSuffix}/${session.responseTokens} out`;
54
+ }
55
+ function formatCacheHitRate(cachedTokens, promptTokens) {
56
+ return `${Math.round((cachedTokens / promptTokens) * 100)}%`;
57
+ }
58
+ export function formatCost(value) {
59
+ if (value === null) {
60
+ return "-";
61
+ }
62
+ if (value === 0) {
63
+ return "$0 local";
64
+ }
65
+ if (value > 0 && value < 0.0001) {
66
+ return "<$0.0001 est";
67
+ }
68
+ return `$${value.toFixed(4)} est`;
69
+ }
70
+ export function formatSpeed(telemetry) {
71
+ if (!telemetry?.evalTokensPerSecond) {
72
+ return "-";
73
+ }
74
+ return `${telemetry.evalTokensPerSecond.toFixed(1)} tok/s`;
75
+ }
76
+ export function formatLatency(telemetry) {
77
+ if (!telemetry) {
78
+ return "-";
79
+ }
80
+ return formatDuration(telemetry.totalDurationMs);
81
+ }
82
+ export function formatDuration(durationMs) {
83
+ if (durationMs >= 1000) {
84
+ return `${(durationMs / 1000).toFixed(1)}s`;
85
+ }
86
+ return `${durationMs}ms`;
87
+ }
88
+ export function formatPercent(value) {
89
+ return value === null ? "-" : `${value}%`;
90
+ }
91
+ export function usageColor(value) {
92
+ if (value === null) {
93
+ return "gray";
94
+ }
95
+ if (value >= 85) {
96
+ return "red";
97
+ }
98
+ if (value >= 65) {
99
+ return "yellow";
100
+ }
101
+ return "green";
102
+ }
103
+ export function gpuMemoryColor(stats) {
104
+ if (!stats || stats.totalMemoryGb <= 0) {
105
+ return "gray";
106
+ }
107
+ return usageColor(Math.round((stats.usedMemoryGb / stats.totalMemoryGb) * 100));
108
+ }
109
+ export function temperatureColor(value) {
110
+ if (value === null) {
111
+ return "gray";
112
+ }
113
+ if (value >= 85) {
114
+ return "red";
115
+ }
116
+ if (value >= 75) {
117
+ return "yellow";
118
+ }
119
+ return "green";
120
+ }
121
+ export function formatGpuUtilization(stats) {
122
+ return stats ? `${stats.utilizationPercent}%` : "-";
123
+ }
124
+ export function formatGpuMemory(stats) {
125
+ return stats ? `${stats.usedMemoryGb}/${stats.totalMemoryGb}G` : "-";
126
+ }
127
+ export function formatGpuTemperature(stats) {
128
+ return stats?.temperatureCelsius !== null && stats?.temperatureCelsius !== undefined ? `${stats.temperatureCelsius}C` : "-";
129
+ }
130
+ export function formatGpuPower(stats) {
131
+ if (!stats?.powerDrawWatts) {
132
+ return "-";
133
+ }
134
+ return stats.powerLimitWatts ? `${Math.round(stats.powerDrawWatts)}/${Math.round(stats.powerLimitWatts)}W` : `${Math.round(stats.powerDrawWatts)}W`;
135
+ }
136
+ export function readToggle(value, fallback) {
137
+ if (!value) {
138
+ return fallback;
139
+ }
140
+ const normalizedValue = value.toLowerCase();
141
+ if (["on", "true", "yes", "1", "enable", "enabled"].includes(normalizedValue)) {
142
+ return true;
143
+ }
144
+ if (["off", "false", "no", "0", "disable", "disabled"].includes(normalizedValue)) {
145
+ return false;
146
+ }
147
+ return fallback;
148
+ }
149
+ export function normalizeModelAlias(value) {
150
+ if (value === "uncensored" || value === "abliterate" || value === "abliterated") {
151
+ return "huihui_ai/qwen2.5-coder-abliterate:7b";
152
+ }
153
+ if (value === "default" || value === "official") {
154
+ return "qwen2.5-coder:7b";
155
+ }
156
+ return value;
157
+ }
158
+ export function shortenMiddle(value, maxLength) {
159
+ if (value.length <= maxLength) {
160
+ return value;
161
+ }
162
+ if (maxLength <= 3) {
163
+ return value.slice(0, maxLength);
164
+ }
165
+ const keep = maxLength - 3;
166
+ const left = Math.ceil(keep / 2);
167
+ const right = Math.floor(keep / 2);
168
+ return `${value.slice(0, left)}...${value.slice(value.length - right)}`;
169
+ }
170
+ export function toneToColor(tone) {
171
+ switch (tone) {
172
+ case "muted":
173
+ return "gray";
174
+ case "success":
175
+ return "green";
176
+ case "warning":
177
+ return "yellow";
178
+ case "danger":
179
+ return "red";
180
+ case "accent":
181
+ return "cyan";
182
+ case "normal":
183
+ return "white";
184
+ }
185
+ }
186
+ export function toneToMarker(tone) {
187
+ switch (tone) {
188
+ case "muted":
189
+ return "-";
190
+ case "success":
191
+ return "+";
192
+ case "warning":
193
+ return "!";
194
+ case "danger":
195
+ return "x";
196
+ case "accent":
197
+ return ">";
198
+ case "normal":
199
+ return ":";
200
+ }
201
+ }
202
+ //# sourceMappingURL=format.js.map