@getlore/cli 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.
- package/LICENSE +13 -0
- package/README.md +80 -0
- package/dist/cli/colors.d.ts +48 -0
- package/dist/cli/colors.js +48 -0
- package/dist/cli/commands/ask.d.ts +7 -0
- package/dist/cli/commands/ask.js +97 -0
- package/dist/cli/commands/auth.d.ts +10 -0
- package/dist/cli/commands/auth.js +484 -0
- package/dist/cli/commands/daemon.d.ts +22 -0
- package/dist/cli/commands/daemon.js +244 -0
- package/dist/cli/commands/docs.d.ts +7 -0
- package/dist/cli/commands/docs.js +188 -0
- package/dist/cli/commands/extensions.d.ts +7 -0
- package/dist/cli/commands/extensions.js +204 -0
- package/dist/cli/commands/misc.d.ts +7 -0
- package/dist/cli/commands/misc.js +172 -0
- package/dist/cli/commands/pending.d.ts +7 -0
- package/dist/cli/commands/pending.js +63 -0
- package/dist/cli/commands/projects.d.ts +7 -0
- package/dist/cli/commands/projects.js +136 -0
- package/dist/cli/commands/search.d.ts +7 -0
- package/dist/cli/commands/search.js +102 -0
- package/dist/cli/commands/skills.d.ts +24 -0
- package/dist/cli/commands/skills.js +447 -0
- package/dist/cli/commands/sources.d.ts +7 -0
- package/dist/cli/commands/sources.js +121 -0
- package/dist/cli/commands/sync.d.ts +31 -0
- package/dist/cli/commands/sync.js +768 -0
- package/dist/cli/helpers.d.ts +30 -0
- package/dist/cli/helpers.js +119 -0
- package/dist/core/auth.d.ts +62 -0
- package/dist/core/auth.js +330 -0
- package/dist/core/config.d.ts +41 -0
- package/dist/core/config.js +96 -0
- package/dist/core/data-repo.d.ts +31 -0
- package/dist/core/data-repo.js +146 -0
- package/dist/core/embedder.d.ts +22 -0
- package/dist/core/embedder.js +104 -0
- package/dist/core/git.d.ts +37 -0
- package/dist/core/git.js +140 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +5 -0
- package/dist/core/insight-extractor.d.ts +26 -0
- package/dist/core/insight-extractor.js +114 -0
- package/dist/core/local-search.d.ts +43 -0
- package/dist/core/local-search.js +221 -0
- package/dist/core/themes.d.ts +15 -0
- package/dist/core/themes.js +77 -0
- package/dist/core/types.d.ts +177 -0
- package/dist/core/types.js +9 -0
- package/dist/core/user-settings.d.ts +15 -0
- package/dist/core/user-settings.js +42 -0
- package/dist/core/vector-store-lance.d.ts +98 -0
- package/dist/core/vector-store-lance.js +384 -0
- package/dist/core/vector-store-supabase.d.ts +89 -0
- package/dist/core/vector-store-supabase.js +295 -0
- package/dist/core/vector-store.d.ts +131 -0
- package/dist/core/vector-store.js +503 -0
- package/dist/daemon-runner.d.ts +8 -0
- package/dist/daemon-runner.js +246 -0
- package/dist/extensions/config.d.ts +22 -0
- package/dist/extensions/config.js +102 -0
- package/dist/extensions/proposals.d.ts +30 -0
- package/dist/extensions/proposals.js +178 -0
- package/dist/extensions/registry.d.ts +35 -0
- package/dist/extensions/registry.js +309 -0
- package/dist/extensions/sandbox.d.ts +16 -0
- package/dist/extensions/sandbox.js +17 -0
- package/dist/extensions/types.d.ts +114 -0
- package/dist/extensions/types.js +4 -0
- package/dist/extensions/worker.d.ts +1 -0
- package/dist/extensions/worker.js +49 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +105 -0
- package/dist/mcp/handlers/archive-project.d.ts +51 -0
- package/dist/mcp/handlers/archive-project.js +112 -0
- package/dist/mcp/handlers/get-quotes.d.ts +27 -0
- package/dist/mcp/handlers/get-quotes.js +61 -0
- package/dist/mcp/handlers/get-source.d.ts +9 -0
- package/dist/mcp/handlers/get-source.js +40 -0
- package/dist/mcp/handlers/ingest.d.ts +25 -0
- package/dist/mcp/handlers/ingest.js +305 -0
- package/dist/mcp/handlers/list-projects.d.ts +4 -0
- package/dist/mcp/handlers/list-projects.js +16 -0
- package/dist/mcp/handlers/list-sources.d.ts +11 -0
- package/dist/mcp/handlers/list-sources.js +20 -0
- package/dist/mcp/handlers/research-agent.d.ts +21 -0
- package/dist/mcp/handlers/research-agent.js +369 -0
- package/dist/mcp/handlers/research.d.ts +22 -0
- package/dist/mcp/handlers/research.js +225 -0
- package/dist/mcp/handlers/retain.d.ts +18 -0
- package/dist/mcp/handlers/retain.js +92 -0
- package/dist/mcp/handlers/search.d.ts +52 -0
- package/dist/mcp/handlers/search.js +145 -0
- package/dist/mcp/handlers/sync.d.ts +47 -0
- package/dist/mcp/handlers/sync.js +211 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.js +268 -0
- package/dist/mcp/tools.d.ts +16 -0
- package/dist/mcp/tools.js +297 -0
- package/dist/sync/config.d.ts +26 -0
- package/dist/sync/config.js +140 -0
- package/dist/sync/discover.d.ts +51 -0
- package/dist/sync/discover.js +190 -0
- package/dist/sync/index.d.ts +11 -0
- package/dist/sync/index.js +11 -0
- package/dist/sync/process.d.ts +50 -0
- package/dist/sync/process.js +285 -0
- package/dist/sync/processors.d.ts +24 -0
- package/dist/sync/processors.js +351 -0
- package/dist/tui/browse-handlers-ask.d.ts +30 -0
- package/dist/tui/browse-handlers-ask.js +372 -0
- package/dist/tui/browse-handlers-autocomplete.d.ts +49 -0
- package/dist/tui/browse-handlers-autocomplete.js +270 -0
- package/dist/tui/browse-handlers-extensions.d.ts +18 -0
- package/dist/tui/browse-handlers-extensions.js +107 -0
- package/dist/tui/browse-handlers-pending.d.ts +22 -0
- package/dist/tui/browse-handlers-pending.js +100 -0
- package/dist/tui/browse-handlers-research.d.ts +32 -0
- package/dist/tui/browse-handlers-research.js +363 -0
- package/dist/tui/browse-handlers-tools.d.ts +42 -0
- package/dist/tui/browse-handlers-tools.js +289 -0
- package/dist/tui/browse-handlers.d.ts +239 -0
- package/dist/tui/browse-handlers.js +1944 -0
- package/dist/tui/browse-render-extensions.d.ts +14 -0
- package/dist/tui/browse-render-extensions.js +114 -0
- package/dist/tui/browse-render-tools.d.ts +18 -0
- package/dist/tui/browse-render-tools.js +259 -0
- package/dist/tui/browse-render.d.ts +51 -0
- package/dist/tui/browse-render.js +599 -0
- package/dist/tui/browse-types.d.ts +142 -0
- package/dist/tui/browse-types.js +70 -0
- package/dist/tui/browse-ui.d.ts +10 -0
- package/dist/tui/browse-ui.js +432 -0
- package/dist/tui/browse.d.ts +17 -0
- package/dist/tui/browse.js +625 -0
- package/dist/tui/markdown.d.ts +22 -0
- package/dist/tui/markdown.js +223 -0
- package/package.json +71 -0
- package/plugins/claude-code/.claude-plugin/plugin.json +10 -0
- package/plugins/claude-code/.mcp.json +6 -0
- package/plugins/claude-code/skills/lore/SKILL.md +63 -0
- package/plugins/codex/SKILL.md +36 -0
- package/plugins/codex/agents/openai.yaml +10 -0
- package/plugins/gemini/GEMINI.md +31 -0
- package/plugins/gemini/gemini-extension.json +11 -0
- package/skills/generic-agent.md +99 -0
- package/skills/openclaw.md +67 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension-related rendering functions for the Lore Document Browser TUI
|
|
3
|
+
*
|
|
4
|
+
* Handles rendering of extension lists and details.
|
|
5
|
+
*/
|
|
6
|
+
import type { BrowserState, UIComponents } from './browse-types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Render the extensions list
|
|
9
|
+
*/
|
|
10
|
+
export declare function renderExtensionsList(ui: UIComponents, state: BrowserState): void;
|
|
11
|
+
/**
|
|
12
|
+
* Render the extension details panel
|
|
13
|
+
*/
|
|
14
|
+
export declare function renderExtensionDetails(ui: UIComponents, state: BrowserState): void;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension-related rendering functions for the Lore Document Browser TUI
|
|
3
|
+
*
|
|
4
|
+
* Handles rendering of extension lists and details.
|
|
5
|
+
*/
|
|
6
|
+
import { escapeForBlessed, truncate } from './browse-render.js';
|
|
7
|
+
/**
|
|
8
|
+
* Render the extensions list
|
|
9
|
+
*/
|
|
10
|
+
export function renderExtensionsList(ui, state) {
|
|
11
|
+
const width = ui.listContent.width - 2;
|
|
12
|
+
const height = ui.listContent.height - 1;
|
|
13
|
+
const lines = [];
|
|
14
|
+
if (state.extensionsList.length === 0) {
|
|
15
|
+
lines.push('');
|
|
16
|
+
lines.push('{blue-fg} No extensions installed{/blue-fg}');
|
|
17
|
+
lines.push('');
|
|
18
|
+
lines.push('{blue-fg} Install with:{/blue-fg}');
|
|
19
|
+
lines.push('{cyan-fg} lore extension install <package>{/cyan-fg}');
|
|
20
|
+
ui.listContent.setContent(lines.join('\n'));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const visibleStart = Math.max(0, state.selectedExtensionIndex - Math.floor(height / 3));
|
|
24
|
+
const visibleEnd = Math.min(state.extensionsList.length, visibleStart + height);
|
|
25
|
+
for (let i = visibleStart; i < visibleEnd; i++) {
|
|
26
|
+
const ext = state.extensionsList[i];
|
|
27
|
+
const isSelected = i === state.selectedExtensionIndex;
|
|
28
|
+
const accent = isSelected ? '{cyan-fg}>{/cyan-fg}' : ' ';
|
|
29
|
+
const status = ext.enabled ? '{green-fg}[ok]{/green-fg}' : '{red-fg}[off]{/red-fg}';
|
|
30
|
+
const name = truncate(ext.name, width - 10);
|
|
31
|
+
const version = `v${ext.version}`;
|
|
32
|
+
lines.push(`${accent} ${status} {bold}${escapeForBlessed(name)}{/bold}`);
|
|
33
|
+
lines.push(` {blue-fg}${escapeForBlessed(version)}{/blue-fg}`);
|
|
34
|
+
lines.push('');
|
|
35
|
+
}
|
|
36
|
+
ui.listContent.setContent(lines.join('\n'));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Render the extension details panel
|
|
40
|
+
*/
|
|
41
|
+
export function renderExtensionDetails(ui, state) {
|
|
42
|
+
if (state.extensionsList.length === 0) {
|
|
43
|
+
ui.previewContent.setContent('{blue-fg}No extensions{/blue-fg}');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const ext = state.extensionsList[state.selectedExtensionIndex];
|
|
47
|
+
if (!ext) {
|
|
48
|
+
ui.previewContent.setContent('{blue-fg}Select an extension{/blue-fg}');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const lines = [];
|
|
52
|
+
const previewWidth = ui.previewContent.width - 2;
|
|
53
|
+
// Header
|
|
54
|
+
lines.push(`{bold}${truncate(escapeForBlessed(ext.name), previewWidth)}{/bold}`);
|
|
55
|
+
lines.push(`{blue-fg}v${escapeForBlessed(ext.version)}{/blue-fg}`);
|
|
56
|
+
lines.push('');
|
|
57
|
+
// Status
|
|
58
|
+
const statusColor = ext.enabled ? 'green' : 'red';
|
|
59
|
+
const statusText = ext.enabled ? 'Enabled' : 'Disabled';
|
|
60
|
+
lines.push(`{${statusColor}-fg}Status: ${statusText}{/${statusColor}-fg}`);
|
|
61
|
+
lines.push('');
|
|
62
|
+
// Hooks
|
|
63
|
+
lines.push('{cyan-fg}Hooks:{/cyan-fg}');
|
|
64
|
+
if (ext.hooks.length === 0) {
|
|
65
|
+
lines.push(' {blue-fg}(none){/blue-fg}');
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
for (const hook of ext.hooks) {
|
|
69
|
+
lines.push(` {green-fg}*{/green-fg} ${escapeForBlessed(hook)}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
lines.push('');
|
|
73
|
+
// Middleware
|
|
74
|
+
lines.push('{cyan-fg}Middleware:{/cyan-fg}');
|
|
75
|
+
if (ext.middleware.length === 0) {
|
|
76
|
+
lines.push(' {blue-fg}(none){/blue-fg}');
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
for (const mw of ext.middleware) {
|
|
80
|
+
lines.push(` {green-fg}*{/green-fg} ${escapeForBlessed(mw)}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
lines.push('');
|
|
84
|
+
// Commands
|
|
85
|
+
lines.push('{cyan-fg}Commands:{/cyan-fg}');
|
|
86
|
+
if (ext.commands.length === 0) {
|
|
87
|
+
lines.push(' {blue-fg}(none){/blue-fg}');
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
for (const cmd of ext.commands) {
|
|
91
|
+
lines.push(` {green-fg}*{/green-fg} ${escapeForBlessed(cmd)}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
lines.push('');
|
|
95
|
+
// Permissions
|
|
96
|
+
lines.push('{cyan-fg}Permissions:{/cyan-fg}');
|
|
97
|
+
if (!ext.permissions) {
|
|
98
|
+
lines.push(' {blue-fg}read: true (default){/blue-fg}');
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const perms = ext.permissions;
|
|
102
|
+
lines.push(` read: ${perms.read !== false ? 'true' : 'false'}`);
|
|
103
|
+
if (perms.proposeCreate)
|
|
104
|
+
lines.push(' proposeCreate: true');
|
|
105
|
+
if (perms.proposeModify)
|
|
106
|
+
lines.push(' proposeModify: true');
|
|
107
|
+
if (perms.proposeDelete)
|
|
108
|
+
lines.push(' proposeDelete: true');
|
|
109
|
+
}
|
|
110
|
+
lines.push('');
|
|
111
|
+
// Instructions
|
|
112
|
+
lines.push('{blue-fg}Press Enter to toggle enabled/disabled{/blue-fg}');
|
|
113
|
+
ui.previewContent.setContent(lines.join('\n'));
|
|
114
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-related rendering functions for the Lore Document Browser TUI
|
|
3
|
+
*
|
|
4
|
+
* Handles rendering of tool lists, forms, and results.
|
|
5
|
+
*/
|
|
6
|
+
import type { BrowserState, UIComponents } from './browse-types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Render the tool form overlay
|
|
9
|
+
*/
|
|
10
|
+
export declare function renderToolForm(ui: UIComponents, state: BrowserState): void;
|
|
11
|
+
/**
|
|
12
|
+
* Render the tools list
|
|
13
|
+
*/
|
|
14
|
+
export declare function renderToolsList(ui: UIComponents, state: BrowserState): void;
|
|
15
|
+
/**
|
|
16
|
+
* Render the tool preview (schema + result)
|
|
17
|
+
*/
|
|
18
|
+
export declare function renderToolResult(ui: UIComponents, state: BrowserState): void;
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-related rendering functions for the Lore Document Browser TUI
|
|
3
|
+
*
|
|
4
|
+
* Handles rendering of tool lists, forms, and results.
|
|
5
|
+
*/
|
|
6
|
+
import { escapeForBlessed, truncate, formatJsonForPreview } from './browse-render.js';
|
|
7
|
+
function formatToolFormValue(fieldType, value) {
|
|
8
|
+
if (fieldType === 'boolean') {
|
|
9
|
+
return value ? '[x]' : '[ ]';
|
|
10
|
+
}
|
|
11
|
+
const text = value === undefined || value === null ? '' : String(value);
|
|
12
|
+
return `[${escapeForBlessed(text)}]`;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Render the tool form overlay
|
|
16
|
+
*/
|
|
17
|
+
export function renderToolForm(ui, state) {
|
|
18
|
+
const width = ui.toolFormContent.width - 2;
|
|
19
|
+
const lines = [];
|
|
20
|
+
if (state.toolFormFields.length === 0) {
|
|
21
|
+
lines.push('{blue-fg}No input fields for this tool.{/blue-fg}');
|
|
22
|
+
lines.push('');
|
|
23
|
+
lines.push('{blue-fg}[Enter: run] [Esc: back]{/blue-fg}');
|
|
24
|
+
ui.toolFormContent.setContent(lines.join('\n'));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
for (let i = 0; i < state.toolFormFields.length; i++) {
|
|
28
|
+
const field = state.toolFormFields[i];
|
|
29
|
+
const isFocused = i === state.toolFormIndex;
|
|
30
|
+
const name = escapeForBlessed(field.name);
|
|
31
|
+
const reqLabel = field.required ? '{red-fg}(required){/red-fg}' : '{green-fg}(optional){/green-fg}';
|
|
32
|
+
const valueText = formatToolFormValue(field.type, field.value);
|
|
33
|
+
const line = truncate(`${name}: ${valueText} ${reqLabel}`, width);
|
|
34
|
+
lines.push(isFocused ? `{inverse}${line}{/inverse}` : line);
|
|
35
|
+
if (field.description) {
|
|
36
|
+
const hint = truncate(escapeForBlessed(field.description), Math.max(0, width - 2));
|
|
37
|
+
lines.push(` {blue-fg}${hint}{/blue-fg}`);
|
|
38
|
+
}
|
|
39
|
+
lines.push('');
|
|
40
|
+
}
|
|
41
|
+
lines.push('{blue-fg}[Tab: next field] [Shift+Tab: prev] [Enter: run] [Esc: back]{/blue-fg}');
|
|
42
|
+
ui.toolFormContent.setContent(lines.join('\n'));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Render the tools list
|
|
46
|
+
*/
|
|
47
|
+
export function renderToolsList(ui, state) {
|
|
48
|
+
const width = ui.listContent.width - 2;
|
|
49
|
+
const height = ui.listContent.height - 1;
|
|
50
|
+
const lines = [];
|
|
51
|
+
if (state.toolsList.length === 0) {
|
|
52
|
+
lines.push('');
|
|
53
|
+
lines.push('{blue-fg} No tools available{/blue-fg}');
|
|
54
|
+
lines.push('');
|
|
55
|
+
lines.push('{blue-fg} Install extensions with tools{/blue-fg}');
|
|
56
|
+
ui.listContent.setContent(lines.join('\n'));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const visibleStart = Math.max(0, state.selectedToolIndex - Math.floor(height / 3));
|
|
60
|
+
const visibleEnd = Math.min(state.toolsList.length, visibleStart + height);
|
|
61
|
+
for (let i = visibleStart; i < visibleEnd; i++) {
|
|
62
|
+
const tool = state.toolsList[i];
|
|
63
|
+
const isSelected = i === state.selectedToolIndex;
|
|
64
|
+
const accent = isSelected ? '{cyan-fg}▌{/cyan-fg}' : ' ';
|
|
65
|
+
const name = truncate(tool.name, width - 4);
|
|
66
|
+
const description = truncate(tool.description || '', width - 6);
|
|
67
|
+
lines.push(`${accent} {bold}${escapeForBlessed(name)}{/bold}`);
|
|
68
|
+
if (description) {
|
|
69
|
+
lines.push(`${accent} {cyan-fg}${escapeForBlessed(description)}{/cyan-fg}`);
|
|
70
|
+
}
|
|
71
|
+
lines.push('');
|
|
72
|
+
}
|
|
73
|
+
ui.listContent.setContent(lines.join('\n'));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Format tool result in a human-readable way
|
|
77
|
+
*/
|
|
78
|
+
function formatToolResultNicely(result, maxWidth) {
|
|
79
|
+
const lines = [];
|
|
80
|
+
if (result === null || result === undefined) {
|
|
81
|
+
lines.push('{blue-fg}(no result){/blue-fg}');
|
|
82
|
+
return lines;
|
|
83
|
+
}
|
|
84
|
+
if (typeof result !== 'object') {
|
|
85
|
+
lines.push(escapeForBlessed(String(result)));
|
|
86
|
+
return lines;
|
|
87
|
+
}
|
|
88
|
+
const obj = result;
|
|
89
|
+
// Handle running state
|
|
90
|
+
if ('status' in obj && obj.status === 'running') {
|
|
91
|
+
lines.push('{yellow-fg}⏳ Running...{/yellow-fg}');
|
|
92
|
+
if ('message' in obj) {
|
|
93
|
+
lines.push(`{cyan-fg}${escapeForBlessed(String(obj.message))}{/cyan-fg}`);
|
|
94
|
+
}
|
|
95
|
+
return lines;
|
|
96
|
+
}
|
|
97
|
+
// Handle common patterns
|
|
98
|
+
if ('status' in obj && obj.status === 'ok') {
|
|
99
|
+
lines.push(`{green-fg}Status:{/green-fg} ${escapeForBlessed(String(obj.status))}`);
|
|
100
|
+
}
|
|
101
|
+
if ('status' in obj && obj.status === 'error') {
|
|
102
|
+
lines.push(`{red-fg}Status:{/red-fg} error`);
|
|
103
|
+
}
|
|
104
|
+
if ('message' in obj && obj.status !== 'running') {
|
|
105
|
+
lines.push(`{cyan-fg}Message:{/cyan-fg} ${escapeForBlessed(String(obj.message))}`);
|
|
106
|
+
}
|
|
107
|
+
// Handle proposal notification
|
|
108
|
+
if ('proposal_id' in obj) {
|
|
109
|
+
lines.push('');
|
|
110
|
+
lines.push(`{yellow-fg}📋 Proposal created:{/yellow-fg} ${escapeForBlessed(String(obj.proposal_id))}`);
|
|
111
|
+
if ('proposal_note' in obj) {
|
|
112
|
+
lines.push(`{yellow-fg}${escapeForBlessed(String(obj.proposal_note))}{/yellow-fg}`);
|
|
113
|
+
}
|
|
114
|
+
lines.push(`{yellow-fg}Press 'r' to review and approve{/yellow-fg}`);
|
|
115
|
+
}
|
|
116
|
+
// Handle analysis output
|
|
117
|
+
if ('analysis' in obj) {
|
|
118
|
+
lines.push('');
|
|
119
|
+
lines.push('{cyan-fg}Analysis:{/cyan-fg}');
|
|
120
|
+
const analysisText = String(obj.analysis);
|
|
121
|
+
// Wrap long analysis text
|
|
122
|
+
const analysisLines = analysisText.split('\n');
|
|
123
|
+
for (const line of analysisLines.slice(0, 30)) { // Limit to 30 lines
|
|
124
|
+
lines.push(escapeForBlessed(truncate(line, maxWidth)));
|
|
125
|
+
}
|
|
126
|
+
if (analysisLines.length > 30) {
|
|
127
|
+
lines.push('{blue-fg}... (truncated){/blue-fg}');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if ('total_sources_analyzed' in obj) {
|
|
131
|
+
lines.push(`{cyan-fg}Sources analyzed:{/cyan-fg} ${obj.total_sources_analyzed}`);
|
|
132
|
+
}
|
|
133
|
+
if ('total_speakers' in obj) {
|
|
134
|
+
lines.push(`{cyan-fg}Total speakers:{/cyan-fg} ${obj.total_speakers}`);
|
|
135
|
+
}
|
|
136
|
+
if ('top_pain_point' in obj) {
|
|
137
|
+
lines.push(`{cyan-fg}Top pain point:{/cyan-fg} ${escapeForBlessed(String(obj.top_pain_point))}`);
|
|
138
|
+
}
|
|
139
|
+
if ('verdict' in obj) {
|
|
140
|
+
const verdict = String(obj.verdict);
|
|
141
|
+
const color = verdict === 'SUPPORTED' ? 'green' : verdict === 'CONTRADICTED' ? 'red' : 'yellow';
|
|
142
|
+
lines.push(`{${color}-fg}Verdict:{/${color}-fg} ${verdict}`);
|
|
143
|
+
}
|
|
144
|
+
if ('confidence' in obj) {
|
|
145
|
+
lines.push(`{cyan-fg}Confidence:{/cyan-fg} ${escapeForBlessed(String(obj.confidence))}`);
|
|
146
|
+
}
|
|
147
|
+
if ('coverage_note' in obj && obj.coverage_note) {
|
|
148
|
+
lines.push('');
|
|
149
|
+
lines.push(`{yellow-fg}⚠ ${escapeForBlessed(String(obj.coverage_note))}{/yellow-fg}`);
|
|
150
|
+
}
|
|
151
|
+
if ('features_tested' in obj && Array.isArray(obj.features_tested)) {
|
|
152
|
+
lines.push('');
|
|
153
|
+
lines.push('{cyan-fg}Features tested:{/cyan-fg}');
|
|
154
|
+
for (const feature of obj.features_tested) {
|
|
155
|
+
lines.push(` • ${escapeForBlessed(String(feature))}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if ('pain_points' in obj && Array.isArray(obj.pain_points)) {
|
|
159
|
+
const painPoints = obj.pain_points;
|
|
160
|
+
if (painPoints.length > 0) {
|
|
161
|
+
lines.push('');
|
|
162
|
+
lines.push('{cyan-fg}Pain points:{/cyan-fg}');
|
|
163
|
+
for (const pp of painPoints.slice(0, 5)) {
|
|
164
|
+
lines.push(` • ${escapeForBlessed(pp.category || 'Unknown')} (${pp.frequency || 0}x)`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if ('profiles' in obj && Array.isArray(obj.profiles)) {
|
|
169
|
+
const profiles = obj.profiles;
|
|
170
|
+
if (profiles.length > 0) {
|
|
171
|
+
lines.push('');
|
|
172
|
+
lines.push('{cyan-fg}Speakers:{/cyan-fg}');
|
|
173
|
+
for (const p of profiles.slice(0, 5)) {
|
|
174
|
+
lines.push(` • ${escapeForBlessed(p.name || 'Unknown')} (${p.appearances || 0} appearances)`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if ('supporting' in obj && Array.isArray(obj.supporting)) {
|
|
179
|
+
const supporting = obj.supporting;
|
|
180
|
+
if (supporting.length > 0) {
|
|
181
|
+
lines.push('');
|
|
182
|
+
lines.push(`{green-fg}Supporting evidence:{/green-fg} ${supporting.length} sources`);
|
|
183
|
+
for (const s of supporting.slice(0, 3)) {
|
|
184
|
+
lines.push(` • ${escapeForBlessed(s.source || 'Unknown source')}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if ('contradicting' in obj && Array.isArray(obj.contradicting)) {
|
|
189
|
+
const contradicting = obj.contradicting;
|
|
190
|
+
if (contradicting.length > 0) {
|
|
191
|
+
lines.push('');
|
|
192
|
+
lines.push(`{red-fg}Contradicting evidence:{/red-fg} ${contradicting.length} sources`);
|
|
193
|
+
for (const c of contradicting.slice(0, 3)) {
|
|
194
|
+
lines.push(` • ${escapeForBlessed(c.source || 'Unknown source')}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// If we didn't format anything special, fall back to JSON
|
|
199
|
+
if (lines.length === 0) {
|
|
200
|
+
const jsonText = formatJsonForPreview(result);
|
|
201
|
+
for (const line of jsonText.split('\n')) {
|
|
202
|
+
lines.push(truncate(escapeForBlessed(line), maxWidth));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return lines;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Render the tool preview (schema + result)
|
|
209
|
+
*/
|
|
210
|
+
export function renderToolResult(ui, state) {
|
|
211
|
+
if (state.toolsList.length === 0) {
|
|
212
|
+
ui.previewContent.setContent('{blue-fg}No tools{/blue-fg}');
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const tool = state.toolsList[state.selectedToolIndex];
|
|
216
|
+
if (!tool) {
|
|
217
|
+
ui.previewContent.setContent('{blue-fg}Select a tool{/blue-fg}');
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const lines = [];
|
|
221
|
+
const previewWidth = ui.previewContent.width - 2;
|
|
222
|
+
lines.push(`{bold}${truncate(escapeForBlessed(tool.name), previewWidth)}{/bold}`);
|
|
223
|
+
if (tool.description) {
|
|
224
|
+
lines.push(escapeForBlessed(tool.description));
|
|
225
|
+
}
|
|
226
|
+
lines.push('');
|
|
227
|
+
lines.push('{cyan-fg}Input Schema{/cyan-fg}');
|
|
228
|
+
lines.push('{cyan-fg}─────────────────────────────────{/cyan-fg}');
|
|
229
|
+
const schemaText = formatJsonForPreview(tool.inputSchema);
|
|
230
|
+
for (const line of schemaText.split('\n')) {
|
|
231
|
+
lines.push(truncate(escapeForBlessed(line), previewWidth));
|
|
232
|
+
}
|
|
233
|
+
const matchingResult = state.toolResult && state.toolResult.toolName === tool.name
|
|
234
|
+
? state.toolResult
|
|
235
|
+
: null;
|
|
236
|
+
if (matchingResult) {
|
|
237
|
+
lines.push('');
|
|
238
|
+
if (matchingResult.ok) {
|
|
239
|
+
lines.push('{green-fg}✓ Result{/green-fg}');
|
|
240
|
+
lines.push('{cyan-fg}─────────────────────────────────{/cyan-fg}');
|
|
241
|
+
const formattedResult = formatToolResultNicely(matchingResult.result, previewWidth);
|
|
242
|
+
lines.push(...formattedResult);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
lines.push('{red-fg}✗ Error{/red-fg}');
|
|
246
|
+
lines.push('{cyan-fg}─────────────────────────────────{/cyan-fg}');
|
|
247
|
+
lines.push(`{red-fg}${escapeForBlessed(String(matchingResult.result))}{/red-fg}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else if (state.toolRunning) {
|
|
251
|
+
lines.push('');
|
|
252
|
+
lines.push('{yellow-fg}⏳ Running...{/yellow-fg}');
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
lines.push('');
|
|
256
|
+
lines.push('{cyan-fg}Press Enter to run tool{/cyan-fg}');
|
|
257
|
+
}
|
|
258
|
+
ui.previewContent.setContent(lines.join('\n'));
|
|
259
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rendering functions for the Lore Document Browser TUI
|
|
3
|
+
*
|
|
4
|
+
* Functions for formatting and rendering content to the UI.
|
|
5
|
+
*/
|
|
6
|
+
import type { SourceItem, BrowserState, UIComponents, ListItem } from './browse-types.js';
|
|
7
|
+
import type { SourceType } from '../core/types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Format a date for display
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatDate(dateStr: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Truncate a string to a maximum length
|
|
14
|
+
*/
|
|
15
|
+
export declare function truncate(str: string, len: number): string;
|
|
16
|
+
/**
|
|
17
|
+
* Escape text for blessed tags - must escape curly braces and handle special chars
|
|
18
|
+
*/
|
|
19
|
+
export declare function escapeForBlessed(text: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Format value as JSON for preview display
|
|
22
|
+
*/
|
|
23
|
+
export declare function formatJsonForPreview(value: unknown): string;
|
|
24
|
+
/**
|
|
25
|
+
* Simple markdown to blessed tags converter (no ANSI codes)
|
|
26
|
+
*/
|
|
27
|
+
export declare function markdownToBlessed(text: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Update the status bar
|
|
30
|
+
*/
|
|
31
|
+
export declare function updateStatus(ui: UIComponents, state: BrowserState, project?: string, sourceType?: SourceType): void;
|
|
32
|
+
/**
|
|
33
|
+
* Build flattened list items from grouped sources
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildListItems(state: BrowserState): ListItem[];
|
|
36
|
+
/**
|
|
37
|
+
* Get the currently selected source (if any)
|
|
38
|
+
*/
|
|
39
|
+
export declare function getSelectedSource(state: BrowserState): SourceItem | null;
|
|
40
|
+
/**
|
|
41
|
+
* Render the document list (supports both flat and grouped views)
|
|
42
|
+
*/
|
|
43
|
+
export declare function renderList(ui: UIComponents, state: BrowserState): void;
|
|
44
|
+
/**
|
|
45
|
+
* Render the preview pane
|
|
46
|
+
*/
|
|
47
|
+
export declare function renderPreview(ui: UIComponents, state: BrowserState): void;
|
|
48
|
+
/**
|
|
49
|
+
* Render the full view pane
|
|
50
|
+
*/
|
|
51
|
+
export declare function renderFullView(ui: UIComponents, state: BrowserState): void;
|