@zhijiewang/openharness 2.1.0 → 2.3.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.
- package/README.md +4 -4
- package/dist/DeferredTool.js +3 -1
- package/dist/Tool.d.ts +1 -1
- package/dist/agents/roles.js +58 -62
- package/dist/commands/cybergotchi.d.ts +1 -1
- package/dist/commands/cybergotchi.js +30 -30
- package/dist/commands/index.js +288 -132
- package/dist/components/App.d.ts +1 -1
- package/dist/components/App.js +6 -6
- package/dist/components/CompanionFooter.d.ts +1 -1
- package/dist/components/CompanionFooter.js +6 -8
- package/dist/components/CybergotchiBubble.js +5 -5
- package/dist/components/CybergotchiPanel.d.ts +1 -1
- package/dist/components/CybergotchiPanel.js +7 -7
- package/dist/components/CybergotchiPanelConnected.js +2 -2
- package/dist/components/CybergotchiSetup.js +26 -24
- package/dist/components/CybergotchiSprite.d.ts +1 -1
- package/dist/components/CybergotchiSprite.js +8 -12
- package/dist/components/DiffView.d.ts +1 -1
- package/dist/components/DiffView.js +10 -10
- package/dist/components/ErrorBoundary.d.ts +1 -1
- package/dist/components/ErrorBoundary.js +1 -1
- package/dist/components/InitWizard.js +65 -33
- package/dist/components/Markdown.js +2 -4
- package/dist/components/Messages.js +4 -4
- package/dist/components/PermissionPrompt.d.ts +1 -1
- package/dist/components/PermissionPrompt.js +15 -17
- package/dist/components/REPL.d.ts +1 -1
- package/dist/components/REPL.js +74 -49
- package/dist/components/Spinner.js +2 -2
- package/dist/components/TextInput.js +35 -29
- package/dist/components/ToolCallDisplay.js +3 -5
- package/dist/cybergotchi/bones.d.ts +1 -1
- package/dist/cybergotchi/bones.js +8 -8
- package/dist/cybergotchi/config.d.ts +2 -2
- package/dist/cybergotchi/config.js +13 -13
- package/dist/cybergotchi/events.d.ts +5 -5
- package/dist/cybergotchi/events.js +7 -7
- package/dist/cybergotchi/needs.d.ts +2 -2
- package/dist/cybergotchi/needs.js +7 -9
- package/dist/cybergotchi/personality.d.ts +2 -2
- package/dist/cybergotchi/personality.js +2 -2
- package/dist/cybergotchi/species.d.ts +1 -1
- package/dist/cybergotchi/species.js +145 -217
- package/dist/cybergotchi/speech.d.ts +2 -2
- package/dist/cybergotchi/speech.js +43 -43
- package/dist/cybergotchi/types.d.ts +4 -4
- package/dist/cybergotchi/types.js +26 -26
- package/dist/cybergotchi/useCybergotchi.d.ts +1 -1
- package/dist/cybergotchi/useCybergotchi.js +29 -25
- package/dist/git/index.js +11 -9
- package/dist/harness/checkpoints.js +29 -21
- package/dist/harness/config.d.ts +3 -3
- package/dist/harness/config.js +15 -9
- package/dist/harness/context-warning.d.ts +1 -1
- package/dist/harness/context-warning.js +1 -1
- package/dist/harness/cost.js +1 -1
- package/dist/harness/credentials.js +13 -13
- package/dist/harness/hooks.js +7 -5
- package/dist/harness/keybindings.js +20 -18
- package/dist/harness/marketplace.d.ts +3 -3
- package/dist/harness/marketplace.js +55 -42
- package/dist/harness/memory.d.ts +23 -5
- package/dist/harness/memory.js +142 -41
- package/dist/harness/onboarding.js +30 -10
- package/dist/harness/plugins.d.ts +9 -1
- package/dist/harness/plugins.js +54 -30
- package/dist/harness/rules.js +12 -7
- package/dist/harness/sandbox.js +15 -15
- package/dist/harness/session-db.d.ts +55 -0
- package/dist/harness/session-db.js +165 -0
- package/dist/harness/session.d.ts +1 -1
- package/dist/harness/session.js +34 -15
- package/dist/harness/store.d.ts +3 -3
- package/dist/harness/store.js +6 -4
- package/dist/harness/submit-handler.d.ts +4 -4
- package/dist/harness/submit-handler.js +25 -23
- package/dist/harness/telemetry.d.ts +1 -1
- package/dist/harness/telemetry.js +23 -19
- package/dist/harness/traces.d.ts +2 -2
- package/dist/harness/traces.js +39 -33
- package/dist/harness/verification.d.ts +1 -1
- package/dist/harness/verification.js +50 -44
- package/dist/lsp/client.js +44 -40
- package/dist/main.js +98 -59
- package/dist/mcp/DeferredMcpTool.d.ts +4 -4
- package/dist/mcp/DeferredMcpTool.js +9 -5
- package/dist/mcp/McpTool.d.ts +4 -4
- package/dist/mcp/McpTool.js +8 -4
- package/dist/mcp/client.d.ts +2 -2
- package/dist/mcp/client.js +21 -21
- package/dist/mcp/loader.d.ts +1 -1
- package/dist/mcp/loader.js +17 -12
- package/dist/mcp/registry.d.ts +3 -3
- package/dist/mcp/registry.js +97 -97
- package/dist/mcp/schema.d.ts +1 -1
- package/dist/mcp/schema.js +16 -16
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +21 -21
- package/dist/mcp/types.d.ts +3 -3
- package/dist/providers/anthropic.d.ts +2 -2
- package/dist/providers/anthropic.js +10 -9
- package/dist/providers/base.d.ts +1 -1
- package/dist/providers/index.js +10 -3
- package/dist/providers/llamacpp.d.ts +2 -2
- package/dist/providers/llamacpp.js +1 -3
- package/dist/providers/ollama.d.ts +2 -2
- package/dist/providers/ollama.js +3 -4
- package/dist/providers/openai.d.ts +2 -2
- package/dist/providers/openai.js +3 -5
- package/dist/providers/openrouter.d.ts +2 -2
- package/dist/providers/router.d.ts +1 -1
- package/dist/providers/router.js +7 -7
- package/dist/query/compress.d.ts +2 -2
- package/dist/query/compress.js +22 -21
- package/dist/query/context-manager.d.ts +1 -1
- package/dist/query/context-manager.js +5 -5
- package/dist/query/errors.js +1 -1
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +30 -22
- package/dist/query/tools.js +15 -12
- package/dist/query/types.d.ts +1 -1
- package/dist/query.d.ts +1 -1
- package/dist/query.js +1 -1
- package/dist/remote/auth.d.ts +2 -2
- package/dist/remote/auth.js +8 -8
- package/dist/remote/server.d.ts +3 -3
- package/dist/remote/server.js +60 -60
- package/dist/renderer/cells.js +9 -9
- package/dist/renderer/colors.js +24 -6
- package/dist/renderer/diff.d.ts +2 -2
- package/dist/renderer/diff.js +27 -19
- package/dist/renderer/differ.d.ts +1 -1
- package/dist/renderer/differ.js +9 -9
- package/dist/renderer/image.js +19 -19
- package/dist/renderer/index.d.ts +6 -6
- package/dist/renderer/index.js +163 -93
- package/dist/renderer/input.js +66 -48
- package/dist/renderer/layout.d.ts +6 -6
- package/dist/renderer/layout.js +163 -124
- package/dist/renderer/markdown.d.ts +2 -2
- package/dist/renderer/markdown.js +173 -54
- package/dist/renderer/session-browser.d.ts +2 -2
- package/dist/renderer/session-browser.js +19 -21
- package/dist/repl.d.ts +5 -5
- package/dist/repl.js +300 -198
- package/dist/sdk/index.d.ts +5 -5
- package/dist/sdk/index.js +32 -26
- package/dist/services/AgentDispatcher.d.ts +3 -3
- package/dist/services/AgentDispatcher.js +33 -29
- package/dist/services/CronExecutor.d.ts +4 -4
- package/dist/services/CronExecutor.js +12 -8
- package/dist/services/EvaluatorLoop.d.ts +3 -3
- package/dist/services/EvaluatorLoop.js +29 -21
- package/dist/services/MetaHarness.d.ts +1 -1
- package/dist/services/MetaHarness.js +34 -32
- package/dist/services/PipelineExecutor.d.ts +1 -1
- package/dist/services/PipelineExecutor.js +23 -25
- package/dist/services/SkillExtractor.d.ts +43 -0
- package/dist/services/SkillExtractor.js +143 -0
- package/dist/services/StreamingToolExecutor.d.ts +2 -2
- package/dist/services/StreamingToolExecutor.js +11 -7
- package/dist/services/a2a.d.ts +8 -8
- package/dist/services/a2a.js +44 -34
- package/dist/services/agent-messaging.d.ts +33 -15
- package/dist/services/agent-messaging.js +65 -13
- package/dist/services/cron.js +16 -16
- package/dist/tools/AgentTool/index.d.ts +5 -2
- package/dist/tools/AgentTool/index.js +35 -15
- package/dist/tools/AskUserTool/index.js +1 -1
- package/dist/tools/BashTool/index.d.ts +2 -2
- package/dist/tools/BashTool/index.js +18 -10
- package/dist/tools/CronTool/index.d.ts +2 -2
- package/dist/tools/CronTool/index.js +30 -12
- package/dist/tools/DiagnosticsTool/index.js +28 -22
- package/dist/tools/EnterPlanModeTool/index.js +93 -14
- package/dist/tools/EnterWorktreeTool/index.js +7 -3
- package/dist/tools/ExitPlanModeTool/index.d.ts +22 -1
- package/dist/tools/ExitPlanModeTool/index.js +20 -5
- package/dist/tools/ExitWorktreeTool/index.js +11 -4
- package/dist/tools/FileEditTool/index.js +3 -5
- package/dist/tools/FileReadTool/index.js +16 -10
- package/dist/tools/FileWriteTool/index.js +2 -2
- package/dist/tools/GlobTool/index.js +5 -9
- package/dist/tools/GrepTool/index.d.ts +2 -2
- package/dist/tools/GrepTool/index.js +14 -9
- package/dist/tools/ImageReadTool/index.js +2 -2
- package/dist/tools/KillProcessTool/index.js +11 -7
- package/dist/tools/LSTool/index.js +3 -3
- package/dist/tools/MemoryTool/index.d.ts +11 -11
- package/dist/tools/MemoryTool/index.js +28 -14
- package/dist/tools/MonitorTool/index.js +24 -19
- package/dist/tools/MultiEditTool/index.js +9 -5
- package/dist/tools/NotebookEditTool/index.js +3 -3
- package/dist/tools/ParallelAgentTool/index.d.ts +4 -4
- package/dist/tools/ParallelAgentTool/index.js +12 -6
- package/dist/tools/PipelineTool/index.d.ts +4 -4
- package/dist/tools/PipelineTool/index.js +3 -3
- package/dist/tools/PowerShellTool/index.js +10 -6
- package/dist/tools/RemoteTriggerTool/index.js +8 -4
- package/dist/tools/ScheduleWakeupTool/index.d.ts +42 -0
- package/dist/tools/ScheduleWakeupTool/index.js +115 -0
- package/dist/tools/SendMessageTool/index.js +25 -7
- package/dist/tools/SessionSearchTool/index.d.ts +15 -0
- package/dist/tools/SessionSearchTool/index.js +36 -0
- package/dist/tools/SkillTool/index.d.ts +3 -0
- package/dist/tools/SkillTool/index.js +39 -9
- package/dist/tools/TaskCreateTool/index.d.ts +2 -2
- package/dist/tools/TaskCreateTool/index.js +2 -2
- package/dist/tools/TaskGetTool/index.js +2 -2
- package/dist/tools/TaskListTool/index.js +3 -5
- package/dist/tools/TaskOutputTool/index.js +2 -2
- package/dist/tools/TaskStopTool/index.js +3 -3
- package/dist/tools/TaskUpdateTool/index.d.ts +4 -4
- package/dist/tools/TaskUpdateTool/index.js +2 -2
- package/dist/tools/ToolSearchTool/index.js +9 -6
- package/dist/tools/WebFetchTool/index.js +1 -1
- package/dist/tools/WebSearchTool/index.js +2 -6
- package/dist/tools.js +31 -30
- package/dist/types/permissions.js +15 -9
- package/dist/utils/bash-safety.d.ts +1 -1
- package/dist/utils/bash-safety.js +64 -54
- package/dist/utils/diff-algorithm.d.ts +3 -3
- package/dist/utils/diff-algorithm.js +7 -7
- package/dist/utils/fs.js +3 -3
- package/dist/utils/safe-env.js +1 -1
- package/dist/utils/theme-data.d.ts +1 -1
- package/dist/utils/theme-data.js +1 -1
- package/dist/utils/theme.d.ts +1 -1
- package/dist/utils/theme.js +1 -1
- package/dist/utils/tool-summary.d.ts +1 -1
- package/dist/utils/tool-summary.js +27 -9
- package/package.json +10 -3
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* inline code, tables) and renders them with appropriate styles.
|
|
5
5
|
* No external dependencies — uses simple regex parsing.
|
|
6
6
|
*/
|
|
7
|
-
import type { CellGrid } from
|
|
7
|
+
import type { CellGrid } from "./cells.js";
|
|
8
8
|
export declare function resetMdStyleCache(): void;
|
|
9
9
|
/**
|
|
10
10
|
* Measure how many rows markdown text will consume without rendering.
|
|
@@ -18,5 +18,5 @@ export declare function measureMarkdown(text: string, width: number): number;
|
|
|
18
18
|
export declare function renderMarkdown(grid: CellGrid, row: number, col: number, text: string, width: number, codeBlocksExpanded?: boolean, maxRow?: number): number;
|
|
19
19
|
export declare const HIGHLIGHT_LANGS: Set<string>;
|
|
20
20
|
/** Render a line of code with basic syntax highlighting */
|
|
21
|
-
export declare function renderHighlightedCode(grid: CellGrid, row: number, col: number, line: string,
|
|
21
|
+
export declare function renderHighlightedCode(grid: CellGrid, row: number, col: number, line: string, _lang: string): void;
|
|
22
22
|
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* inline code, tables) and renders them with appropriate styles.
|
|
5
5
|
* No external dependencies — uses simple regex parsing.
|
|
6
6
|
*/
|
|
7
|
-
import { getTheme } from
|
|
7
|
+
import { getTheme } from "../utils/theme-data.js";
|
|
8
8
|
const s = (fg, bold = false, dim = false) => ({ fg, bg: null, bold, dim, underline: false });
|
|
9
9
|
// Theme-independent
|
|
10
10
|
const S_TEXT = s(null);
|
|
@@ -23,7 +23,9 @@ const RE_IDENT_CHAR = /[a-zA-Z0-9_$]/;
|
|
|
23
23
|
let S_HEADING, S_CODE, S_CODE_FENCE, S_BULLET;
|
|
24
24
|
let S_KW, S_STRING, S_COMMENT, S_NUMBER, S_TYPE;
|
|
25
25
|
let _mdStylesInit = false;
|
|
26
|
-
export function resetMdStyleCache() {
|
|
26
|
+
export function resetMdStyleCache() {
|
|
27
|
+
_mdStylesInit = false;
|
|
28
|
+
}
|
|
27
29
|
function ensureMdStyles() {
|
|
28
30
|
if (_mdStylesInit)
|
|
29
31
|
return;
|
|
@@ -44,17 +46,17 @@ function ensureMdStyles() {
|
|
|
44
46
|
* Uses the same logic as renderMarkdown but without writing to a grid.
|
|
45
47
|
*/
|
|
46
48
|
export function measureMarkdown(text, width) {
|
|
47
|
-
const lines = text.split(
|
|
49
|
+
const lines = text.split("\n");
|
|
48
50
|
let rows = 0;
|
|
49
51
|
let i = 0;
|
|
50
52
|
while (i < lines.length) {
|
|
51
53
|
const line = lines[i];
|
|
52
54
|
// Code block
|
|
53
|
-
if (line.trimStart().startsWith(
|
|
55
|
+
if (line.trimStart().startsWith("```")) {
|
|
54
56
|
rows++; // opening fence
|
|
55
57
|
i++;
|
|
56
58
|
while (i < lines.length) {
|
|
57
|
-
if (lines[i].trimStart().startsWith(
|
|
59
|
+
if (lines[i].trimStart().startsWith("```")) {
|
|
58
60
|
rows++; // closing fence
|
|
59
61
|
i++;
|
|
60
62
|
break;
|
|
@@ -65,10 +67,10 @@ export function measureMarkdown(text, width) {
|
|
|
65
67
|
continue;
|
|
66
68
|
}
|
|
67
69
|
// Table detection
|
|
68
|
-
if (line.includes(
|
|
70
|
+
if (line.includes("|") && i + 1 < lines.length && TABLE_SEPARATOR_RE.test(lines[i + 1])) {
|
|
69
71
|
rows += 2; // header + separator
|
|
70
72
|
i += 2; // skip header and separator
|
|
71
|
-
while (i < lines.length && lines[i].includes(
|
|
73
|
+
while (i < lines.length && lines[i].includes("|")) {
|
|
72
74
|
rows++;
|
|
73
75
|
i++;
|
|
74
76
|
}
|
|
@@ -76,7 +78,7 @@ export function measureMarkdown(text, width) {
|
|
|
76
78
|
}
|
|
77
79
|
// Empty line or any other line = 1 row (simplified, ignoring wrapping for measurement)
|
|
78
80
|
// For inline content, estimate wrapping
|
|
79
|
-
const contentLen = line.replace(/\*\*(.+?)\*\*/g,
|
|
81
|
+
const contentLen = line.replace(/\*\*(.+?)\*\*/g, "$1").replace(/`(.+?)`/g, "$1").length;
|
|
80
82
|
rows += Math.max(1, Math.ceil((contentLen || 1) / (width - 2)));
|
|
81
83
|
i++;
|
|
82
84
|
}
|
|
@@ -89,7 +91,7 @@ export function measureMarkdown(text, width) {
|
|
|
89
91
|
export function renderMarkdown(grid, row, col, text, width, codeBlocksExpanded = false, maxRow) {
|
|
90
92
|
ensureMdStyles();
|
|
91
93
|
const wrapWidth = width;
|
|
92
|
-
const lines = text.split(
|
|
94
|
+
const lines = text.split("\n");
|
|
93
95
|
let r = row;
|
|
94
96
|
let i = 0;
|
|
95
97
|
const rowLimit = maxRow ?? grid.height;
|
|
@@ -98,9 +100,9 @@ export function renderMarkdown(grid, row, col, text, width, codeBlocksExpanded =
|
|
|
98
100
|
break;
|
|
99
101
|
const line = lines[i];
|
|
100
102
|
// Code block (fenced)
|
|
101
|
-
if (line.trimStart().startsWith(
|
|
103
|
+
if (line.trimStart().startsWith("```")) {
|
|
102
104
|
const lang = line.trimStart().slice(3).trim();
|
|
103
|
-
const fenceLabel =
|
|
105
|
+
const fenceLabel = `\`\`\`${lang ? ` ${lang}` : ""}`;
|
|
104
106
|
grid.writeText(r, col, fenceLabel, S_CODE_FENCE);
|
|
105
107
|
r++;
|
|
106
108
|
i++;
|
|
@@ -112,12 +114,12 @@ export function renderMarkdown(grid, row, col, text, width, codeBlocksExpanded =
|
|
|
112
114
|
if (r >= rowLimit)
|
|
113
115
|
break;
|
|
114
116
|
const codeLine = lines[i];
|
|
115
|
-
if (codeLine.trimStart().startsWith(
|
|
117
|
+
if (codeLine.trimStart().startsWith("```")) {
|
|
116
118
|
if (skippedLines > 0) {
|
|
117
119
|
grid.writeText(r, col + 2, `… ${skippedLines} more lines (Ctrl+K to expand)`, S_CODE_FENCE);
|
|
118
120
|
r++;
|
|
119
121
|
}
|
|
120
|
-
grid.writeText(r, col,
|
|
122
|
+
grid.writeText(r, col, "```", S_CODE_FENCE);
|
|
121
123
|
r++;
|
|
122
124
|
i++;
|
|
123
125
|
break;
|
|
@@ -144,7 +146,7 @@ export function renderMarkdown(grid, row, col, text, width, codeBlocksExpanded =
|
|
|
144
146
|
// Heading
|
|
145
147
|
const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
146
148
|
if (headingMatch) {
|
|
147
|
-
const prefix = headingMatch[1]
|
|
149
|
+
const prefix = `${headingMatch[1]} `;
|
|
148
150
|
const content = headingMatch[2];
|
|
149
151
|
grid.writeText(r, col, prefix, S_HEADING);
|
|
150
152
|
r += writeInlineMarkdown(grid, r, col + prefix.length, content, wrapWidth, S_HEADING);
|
|
@@ -155,7 +157,7 @@ export function renderMarkdown(grid, row, col, text, width, codeBlocksExpanded =
|
|
|
155
157
|
if (/^(\*{3,}|-{3,}|_{3,})\s*$/.test(line)) {
|
|
156
158
|
const hrLen = Math.min(40, wrapWidth - col);
|
|
157
159
|
for (let c = 0; c < hrLen; c++) {
|
|
158
|
-
grid.setCell(r, col + c,
|
|
160
|
+
grid.setCell(r, col + c, "─", S_HR);
|
|
159
161
|
}
|
|
160
162
|
r++;
|
|
161
163
|
i++;
|
|
@@ -164,7 +166,7 @@ export function renderMarkdown(grid, row, col, text, width, codeBlocksExpanded =
|
|
|
164
166
|
// Blockquote
|
|
165
167
|
const bqMatch = line.match(/^>\s*(.*)$/);
|
|
166
168
|
if (bqMatch) {
|
|
167
|
-
grid.writeText(r, col,
|
|
169
|
+
grid.writeText(r, col, "│ ", S_BLOCKQUOTE);
|
|
168
170
|
r += writeInlineMarkdown(grid, r, col + 2, bqMatch[1], wrapWidth, S_BLOCKQUOTE);
|
|
169
171
|
i++;
|
|
170
172
|
continue;
|
|
@@ -173,7 +175,7 @@ export function renderMarkdown(grid, row, col, text, width, codeBlocksExpanded =
|
|
|
173
175
|
const ulMatch = line.match(/^(\s*)([-*+])\s+(.+)$/);
|
|
174
176
|
if (ulMatch) {
|
|
175
177
|
const indent = Math.min(ulMatch[1].length, 8);
|
|
176
|
-
grid.writeText(r, col + indent,
|
|
178
|
+
grid.writeText(r, col + indent, "• ", S_BULLET);
|
|
177
179
|
r += writeInlineMarkdown(grid, r, col + indent + 2, ulMatch[3], wrapWidth, S_TEXT);
|
|
178
180
|
i++;
|
|
179
181
|
continue;
|
|
@@ -182,23 +184,23 @@ export function renderMarkdown(grid, row, col, text, width, codeBlocksExpanded =
|
|
|
182
184
|
const olMatch = line.match(/^(\s*)(\d+)[.)]\s+(.+)$/);
|
|
183
185
|
if (olMatch) {
|
|
184
186
|
const indent = Math.min(olMatch[1].length, 8);
|
|
185
|
-
const num = olMatch[2]
|
|
187
|
+
const num = `${olMatch[2]}. `;
|
|
186
188
|
grid.writeText(r, col + indent, num, S_BULLET);
|
|
187
189
|
r += writeInlineMarkdown(grid, r, col + indent + num.length, olMatch[3], wrapWidth, S_TEXT);
|
|
188
190
|
i++;
|
|
189
191
|
continue;
|
|
190
192
|
}
|
|
191
193
|
// Table detection: line with | separators
|
|
192
|
-
if (line.includes(
|
|
194
|
+
if (line.includes("|") && i + 1 < lines.length && TABLE_SEPARATOR_RE.test(lines[i + 1])) {
|
|
193
195
|
r = renderTable(grid, r, col, lines, i, wrapWidth);
|
|
194
196
|
// Skip past the table: advance past header + separator first, then data rows
|
|
195
197
|
i += 2; // header + separator
|
|
196
|
-
while (i < lines.length && lines[i].includes(
|
|
198
|
+
while (i < lines.length && lines[i].includes("|"))
|
|
197
199
|
i++;
|
|
198
200
|
continue;
|
|
199
201
|
}
|
|
200
202
|
// Empty line
|
|
201
|
-
if (line.trim() ===
|
|
203
|
+
if (line.trim() === "") {
|
|
202
204
|
r++;
|
|
203
205
|
i++;
|
|
204
206
|
continue;
|
|
@@ -239,7 +241,7 @@ function parseInline(text, baseStyle) {
|
|
|
239
241
|
// Link: [text](url)
|
|
240
242
|
const linkMatch = remaining.match(/^\[([^\]]+)\]\(([^)]+)\)/);
|
|
241
243
|
if (linkMatch) {
|
|
242
|
-
segments.push({ text: linkMatch[1], style: { ...baseStyle, underline: true, fg:
|
|
244
|
+
segments.push({ text: linkMatch[1], style: { ...baseStyle, underline: true, fg: "cyan" } });
|
|
243
245
|
segments.push({ text: ` (${linkMatch[2]})`, style: { ...baseStyle, dim: true } });
|
|
244
246
|
remaining = remaining.slice(linkMatch[0].length);
|
|
245
247
|
continue;
|
|
@@ -290,7 +292,7 @@ function writeTableCells(grid, r, col, cells, colWidths, style, wrapWidth) {
|
|
|
290
292
|
grid.writeText(r, c, cell, style);
|
|
291
293
|
c += colWidths[j] + 3;
|
|
292
294
|
if (j < cells.length - 1 && c - 3 < wrapWidth) {
|
|
293
|
-
grid.writeText(r, c - 3,
|
|
295
|
+
grid.writeText(r, c - 3, " │ ", S_TABLE_BORDER);
|
|
294
296
|
}
|
|
295
297
|
}
|
|
296
298
|
}
|
|
@@ -301,10 +303,10 @@ function renderTable(grid, row, col, lines, startIdx, wrapWidth) {
|
|
|
301
303
|
const headerCells = parseTableRow(lines[startIdx]);
|
|
302
304
|
const separatorIdx = startIdx + 1;
|
|
303
305
|
// Calculate column widths
|
|
304
|
-
const colWidths = headerCells.map(c => c.length);
|
|
306
|
+
const colWidths = headerCells.map((c) => c.length);
|
|
305
307
|
const dataRows = [];
|
|
306
308
|
for (let i = separatorIdx + 1; i < lines.length; i++) {
|
|
307
|
-
if (!lines[i].includes(
|
|
309
|
+
if (!lines[i].includes("|"))
|
|
308
310
|
break;
|
|
309
311
|
const cells = parseTableRow(lines[i]);
|
|
310
312
|
dataRows.push(cells);
|
|
@@ -325,11 +327,11 @@ function renderTable(grid, row, col, lines, startIdx, wrapWidth) {
|
|
|
325
327
|
for (let j = 0; j < colWidths.length; j++) {
|
|
326
328
|
for (let k = 0; k < colWidths[j]; k++) {
|
|
327
329
|
if (c + k < wrapWidth)
|
|
328
|
-
grid.setCell(r, c + k,
|
|
330
|
+
grid.setCell(r, c + k, "─", S_TABLE_BORDER);
|
|
329
331
|
}
|
|
330
332
|
c += colWidths[j] + 3;
|
|
331
333
|
if (j < colWidths.length - 1 && c - 3 < wrapWidth) {
|
|
332
|
-
grid.writeText(r, c - 3,
|
|
334
|
+
grid.writeText(r, c - 3, "─┼─", S_TABLE_BORDER);
|
|
333
335
|
}
|
|
334
336
|
}
|
|
335
337
|
r++;
|
|
@@ -346,48 +348,165 @@ function renderTable(grid, row, col, lines, startIdx, wrapWidth) {
|
|
|
346
348
|
/** Parse a markdown table row into cells */
|
|
347
349
|
function parseTableRow(line) {
|
|
348
350
|
return line
|
|
349
|
-
.replace(/^\|/,
|
|
350
|
-
.replace(/\|$/,
|
|
351
|
-
.split(
|
|
352
|
-
.map(c => c.trim());
|
|
351
|
+
.replace(/^\|/, "")
|
|
352
|
+
.replace(/\|$/, "")
|
|
353
|
+
.split("|")
|
|
354
|
+
.map((c) => c.trim());
|
|
353
355
|
}
|
|
354
356
|
// ── Syntax highlighting ──
|
|
355
357
|
// Languages that should get keyword/string/comment coloring
|
|
356
358
|
export const HIGHLIGHT_LANGS = new Set([
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
359
|
+
"js",
|
|
360
|
+
"javascript",
|
|
361
|
+
"ts",
|
|
362
|
+
"typescript",
|
|
363
|
+
"jsx",
|
|
364
|
+
"tsx",
|
|
365
|
+
"py",
|
|
366
|
+
"python",
|
|
367
|
+
"rb",
|
|
368
|
+
"ruby",
|
|
369
|
+
"rs",
|
|
370
|
+
"rust",
|
|
371
|
+
"go",
|
|
372
|
+
"golang",
|
|
373
|
+
"java",
|
|
374
|
+
"c",
|
|
375
|
+
"cpp",
|
|
376
|
+
"c++",
|
|
377
|
+
"cs",
|
|
378
|
+
"csharp",
|
|
379
|
+
"swift",
|
|
380
|
+
"kotlin",
|
|
381
|
+
"sh",
|
|
382
|
+
"bash",
|
|
383
|
+
"shell",
|
|
384
|
+
"zsh",
|
|
385
|
+
"fish",
|
|
386
|
+
"sql",
|
|
387
|
+
"yaml",
|
|
388
|
+
"yml",
|
|
389
|
+
"json",
|
|
390
|
+
"toml",
|
|
391
|
+
"xml",
|
|
392
|
+
"html",
|
|
393
|
+
"css",
|
|
394
|
+
"php",
|
|
395
|
+
"lua",
|
|
396
|
+
"r",
|
|
397
|
+
"scala",
|
|
398
|
+
"dart",
|
|
399
|
+
"zig",
|
|
400
|
+
"nim",
|
|
401
|
+
"elixir",
|
|
363
402
|
]);
|
|
364
403
|
// Keywords — only unambiguous programming keywords (no common English words)
|
|
365
404
|
const KEYWORDS = new Set([
|
|
366
405
|
// JS/TS
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
406
|
+
"const",
|
|
407
|
+
"let",
|
|
408
|
+
"var",
|
|
409
|
+
"function",
|
|
410
|
+
"return",
|
|
411
|
+
"if",
|
|
412
|
+
"else",
|
|
413
|
+
"for",
|
|
414
|
+
"while",
|
|
415
|
+
"do",
|
|
416
|
+
"switch",
|
|
417
|
+
"case",
|
|
418
|
+
"break",
|
|
419
|
+
"continue",
|
|
420
|
+
"new",
|
|
421
|
+
"this",
|
|
422
|
+
"class",
|
|
423
|
+
"extends",
|
|
424
|
+
"import",
|
|
425
|
+
"export",
|
|
426
|
+
"from",
|
|
427
|
+
"default",
|
|
428
|
+
"async",
|
|
429
|
+
"await",
|
|
430
|
+
"try",
|
|
431
|
+
"catch",
|
|
432
|
+
"finally",
|
|
433
|
+
"throw",
|
|
434
|
+
"typeof",
|
|
435
|
+
"instanceof",
|
|
436
|
+
"of",
|
|
437
|
+
"yield",
|
|
438
|
+
"delete",
|
|
439
|
+
"void",
|
|
440
|
+
"super",
|
|
371
441
|
// Python
|
|
372
|
-
|
|
373
|
-
|
|
442
|
+
"def",
|
|
443
|
+
"elif",
|
|
444
|
+
"except",
|
|
445
|
+
"raise",
|
|
446
|
+
"pass",
|
|
447
|
+
"lambda",
|
|
448
|
+
"True",
|
|
449
|
+
"False",
|
|
450
|
+
"None",
|
|
451
|
+
"self",
|
|
374
452
|
// Rust/Go/general
|
|
375
|
-
|
|
376
|
-
|
|
453
|
+
"fn",
|
|
454
|
+
"mut",
|
|
455
|
+
"pub",
|
|
456
|
+
"impl",
|
|
457
|
+
"struct",
|
|
458
|
+
"enum",
|
|
459
|
+
"match",
|
|
460
|
+
"use",
|
|
461
|
+
"mod",
|
|
462
|
+
"func",
|
|
463
|
+
"interface",
|
|
464
|
+
"package",
|
|
465
|
+
"defer",
|
|
466
|
+
"select",
|
|
467
|
+
"chan",
|
|
377
468
|
]);
|
|
378
469
|
const TYPE_KEYWORDS = new Set([
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
470
|
+
"string",
|
|
471
|
+
"number",
|
|
472
|
+
"boolean",
|
|
473
|
+
"void",
|
|
474
|
+
"null",
|
|
475
|
+
"undefined",
|
|
476
|
+
"any",
|
|
477
|
+
"never",
|
|
478
|
+
"object",
|
|
479
|
+
"symbol",
|
|
480
|
+
"bigint",
|
|
481
|
+
"int",
|
|
482
|
+
"float",
|
|
483
|
+
"bool",
|
|
484
|
+
"str",
|
|
485
|
+
"i32",
|
|
486
|
+
"i64",
|
|
487
|
+
"u32",
|
|
488
|
+
"u64",
|
|
489
|
+
"f32",
|
|
490
|
+
"f64",
|
|
491
|
+
"usize",
|
|
492
|
+
"isize",
|
|
493
|
+
"String",
|
|
494
|
+
"Vec",
|
|
495
|
+
"Option",
|
|
496
|
+
"Result",
|
|
497
|
+
"Array",
|
|
498
|
+
"Map",
|
|
499
|
+
"Set",
|
|
500
|
+
"Promise",
|
|
501
|
+
"Record",
|
|
383
502
|
]);
|
|
384
503
|
/** Render a line of code with basic syntax highlighting */
|
|
385
|
-
export function renderHighlightedCode(grid, row, col, line,
|
|
504
|
+
export function renderHighlightedCode(grid, row, col, line, _lang) {
|
|
386
505
|
let c = col;
|
|
387
506
|
let i = 0;
|
|
388
507
|
while (i < line.length && c < grid.width) {
|
|
389
508
|
// Line comments: // or # (# only when at line start or after whitespace)
|
|
390
|
-
if (line[i] ===
|
|
509
|
+
if (line[i] === "/" && line[i + 1] === "/") {
|
|
391
510
|
const rest = line.slice(i);
|
|
392
511
|
for (let j = 0; j < rest.length && c < grid.width; j++) {
|
|
393
512
|
grid.setCell(row, c, rest[j], S_COMMENT);
|
|
@@ -395,7 +514,7 @@ export function renderHighlightedCode(grid, row, col, line, lang) {
|
|
|
395
514
|
}
|
|
396
515
|
return;
|
|
397
516
|
}
|
|
398
|
-
if (line[i] ===
|
|
517
|
+
if (line[i] === "#" && (line.slice(0, i).trim() === "" || line[i - 1] === " ")) {
|
|
399
518
|
const rest = line.slice(i);
|
|
400
519
|
for (let j = 0; j < rest.length && c < grid.width; j++) {
|
|
401
520
|
grid.setCell(row, c, rest[j], S_COMMENT);
|
|
@@ -404,14 +523,14 @@ export function renderHighlightedCode(grid, row, col, line, lang) {
|
|
|
404
523
|
return;
|
|
405
524
|
}
|
|
406
525
|
// Strings: "..." or '...' or `...`
|
|
407
|
-
if (line[i] === '"' || line[i] === "'" || line[i] ===
|
|
526
|
+
if (line[i] === '"' || line[i] === "'" || line[i] === "`") {
|
|
408
527
|
const quote = line[i];
|
|
409
528
|
grid.setCell(row, c, quote, S_STRING);
|
|
410
529
|
c++;
|
|
411
530
|
i++;
|
|
412
531
|
while (i < line.length && c < grid.width) {
|
|
413
532
|
grid.setCell(row, c, line[i], S_STRING);
|
|
414
|
-
if (line[i] === quote && line[i - 1] !==
|
|
533
|
+
if (line[i] === quote && line[i - 1] !== "\\") {
|
|
415
534
|
c++;
|
|
416
535
|
i++;
|
|
417
536
|
break;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Interactive session browser — renders in the cell grid.
|
|
3
3
|
* Navigate with ↑/↓, Enter to resume, Escape to cancel.
|
|
4
4
|
*/
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
5
|
+
import { listSessions } from "../harness/session.js";
|
|
6
|
+
import type { CellGrid } from "./cells.js";
|
|
7
7
|
type SessionSummary = ReturnType<typeof listSessions>[number];
|
|
8
8
|
export type SessionBrowserState = {
|
|
9
9
|
allSessions: SessionSummary[];
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
* Interactive session browser — renders in the cell grid.
|
|
3
3
|
* Navigate with ↑/↓, Enter to resume, Escape to cancel.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { homedir } from
|
|
8
|
-
import { join } from
|
|
5
|
+
import { listSessions, loadSession } from "../harness/session.js";
|
|
6
|
+
import { getTheme } from "../utils/theme-data.js";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
9
|
const s = (fg, bold = false, dim = false) => ({ fg, bg: null, bold, dim, underline: false });
|
|
10
10
|
/** Load sessions and create initial browser state */
|
|
11
11
|
export function createSessionBrowser() {
|
|
12
|
-
const sessionDir = join(homedir(),
|
|
12
|
+
const sessionDir = join(homedir(), ".oh", "sessions");
|
|
13
13
|
const allSessions = listSessions(sessionDir);
|
|
14
14
|
return {
|
|
15
15
|
allSessions,
|
|
@@ -17,14 +17,14 @@ export function createSessionBrowser() {
|
|
|
17
17
|
selectedIndex: 0,
|
|
18
18
|
scrollOffset: 0,
|
|
19
19
|
preview: null,
|
|
20
|
-
searchQuery:
|
|
20
|
+
searchQuery: "",
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
/** Update search query and filter sessions */
|
|
24
24
|
export function browserSearch(state, query) {
|
|
25
25
|
const q = query.toLowerCase();
|
|
26
26
|
const filtered = q
|
|
27
|
-
? state.allSessions.filter(s => s.model.toLowerCase().includes(q) ||
|
|
27
|
+
? state.allSessions.filter((s) => s.model.toLowerCase().includes(q) ||
|
|
28
28
|
s.id.toLowerCase().includes(q) ||
|
|
29
29
|
new Date(s.updatedAt).toLocaleDateString().includes(q))
|
|
30
30
|
: state.allSessions;
|
|
@@ -52,16 +52,14 @@ export function browserLoadPreview(state) {
|
|
|
52
52
|
if (!session)
|
|
53
53
|
return { ...state, preview: null };
|
|
54
54
|
try {
|
|
55
|
-
const sessionDir = join(homedir(),
|
|
55
|
+
const sessionDir = join(homedir(), ".oh", "sessions");
|
|
56
56
|
const full = loadSession(session.id, sessionDir);
|
|
57
57
|
const lastMsgs = full.messages.slice(-3);
|
|
58
|
-
const preview = lastMsgs
|
|
59
|
-
.map(m => `${m.role === 'user' ? '❯' : '◆'} ${m.content.slice(0, 100)}`)
|
|
60
|
-
.join('\n');
|
|
58
|
+
const preview = lastMsgs.map((m) => `${m.role === "user" ? "❯" : "◆"} ${m.content.slice(0, 100)}`).join("\n");
|
|
61
59
|
return { ...state, preview };
|
|
62
60
|
}
|
|
63
61
|
catch {
|
|
64
|
-
return { ...state, preview:
|
|
62
|
+
return { ...state, preview: "[could not load preview]" };
|
|
65
63
|
}
|
|
66
64
|
}
|
|
67
65
|
/**
|
|
@@ -72,15 +70,15 @@ export function renderSessionBrowser(grid, row, col, state, width, maxRows) {
|
|
|
72
70
|
const t = getTheme();
|
|
73
71
|
let r = row;
|
|
74
72
|
// Title + search
|
|
75
|
-
grid.writeText(r, col,
|
|
73
|
+
grid.writeText(r, col, "─── Session Browser (↑/↓ navigate, Enter resume, Esc cancel) ───", s(null, false, true));
|
|
76
74
|
r++;
|
|
77
75
|
if (state.searchQuery || state.allSessions.length > 5) {
|
|
78
|
-
grid.writeText(r, col,
|
|
79
|
-
grid.writeText(r, col + 3, state.searchQuery ||
|
|
76
|
+
grid.writeText(r, col, "🔍 ", s(null, false, true));
|
|
77
|
+
grid.writeText(r, col + 3, state.searchQuery || "(type to filter)", state.searchQuery ? s(null) : s(null, false, true));
|
|
80
78
|
r++;
|
|
81
79
|
}
|
|
82
80
|
if (state.sessions.length === 0) {
|
|
83
|
-
grid.writeText(r, col + 2,
|
|
81
|
+
grid.writeText(r, col + 2, "No saved sessions.", s(null, false, true));
|
|
84
82
|
return r - row + 1;
|
|
85
83
|
}
|
|
86
84
|
// Session list
|
|
@@ -100,10 +98,10 @@ export function renderSessionBrowser(grid, row, col, state, width, maxRows) {
|
|
|
100
98
|
const sess = state.sessions[idx];
|
|
101
99
|
const selected = idx === state.selectedIndex;
|
|
102
100
|
const date = new Date(sess.updatedAt).toLocaleDateString();
|
|
103
|
-
const cost = sess.cost > 0 ? ` $${sess.cost.toFixed(4)}` :
|
|
104
|
-
const model = (sess.model ||
|
|
101
|
+
const cost = sess.cost > 0 ? ` $${sess.cost.toFixed(4)}` : "";
|
|
102
|
+
const model = (sess.model || "?").slice(0, 20);
|
|
105
103
|
const msgs = String(sess.messages).padStart(3);
|
|
106
|
-
const prefix = selected ?
|
|
104
|
+
const prefix = selected ? "▶ " : " ";
|
|
107
105
|
const style = selected ? s(t.user, true) : s(null);
|
|
108
106
|
const dimStyle = selected ? s(t.user) : s(null, false, true);
|
|
109
107
|
grid.writeText(r, col, prefix, style);
|
|
@@ -116,9 +114,9 @@ export function renderSessionBrowser(grid, row, col, state, width, maxRows) {
|
|
|
116
114
|
// Preview
|
|
117
115
|
if (state.preview && r < row + maxRows - 1) {
|
|
118
116
|
r++;
|
|
119
|
-
grid.writeText(r, col,
|
|
117
|
+
grid.writeText(r, col, "─── Preview ───", s(null, false, true));
|
|
120
118
|
r++;
|
|
121
|
-
for (const line of state.preview.split(
|
|
119
|
+
for (const line of state.preview.split("\n")) {
|
|
122
120
|
if (r >= row + maxRows)
|
|
123
121
|
break;
|
|
124
122
|
grid.writeText(r, col + 2, line.slice(0, width - col - 4), s(null, false, true));
|
package/dist/repl.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Imperative REPL — extracted business logic from React REPL.tsx.
|
|
3
3
|
* Uses TerminalRenderer for display instead of Ink.
|
|
4
4
|
*/
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
7
|
-
import type {
|
|
8
|
-
import type { PermissionMode } from
|
|
5
|
+
import type { Provider } from "./providers/base.js";
|
|
6
|
+
import type { Tools } from "./Tool.js";
|
|
7
|
+
import type { Message } from "./types/message.js";
|
|
8
|
+
import type { PermissionMode } from "./types/permissions.js";
|
|
9
9
|
export type REPLConfig = {
|
|
10
10
|
provider: Provider;
|
|
11
11
|
tools: Tools;
|
|
@@ -14,7 +14,7 @@ export type REPLConfig = {
|
|
|
14
14
|
model?: string;
|
|
15
15
|
initialMessages?: Message[];
|
|
16
16
|
resumeSessionId?: string;
|
|
17
|
-
theme?:
|
|
17
|
+
theme?: "dark" | "light";
|
|
18
18
|
welcomeText?: string;
|
|
19
19
|
};
|
|
20
20
|
export declare function startREPL(config: REPLConfig): Promise<void>;
|