guardlink 1.0.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/CHANGELOG.md +30 -0
- package/LICENSE +21 -0
- package/README.md +344 -0
- package/dist/agents/config.d.ts +46 -0
- package/dist/agents/config.d.ts.map +1 -0
- package/dist/agents/config.js +189 -0
- package/dist/agents/config.js.map +1 -0
- package/dist/agents/index.d.ts +24 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +42 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/launcher.d.ts +54 -0
- package/dist/agents/launcher.d.ts.map +1 -0
- package/dist/agents/launcher.js +152 -0
- package/dist/agents/launcher.js.map +1 -0
- package/dist/agents/prompts.d.ts +14 -0
- package/dist/agents/prompts.d.ts.map +1 -0
- package/dist/agents/prompts.js +120 -0
- package/dist/agents/prompts.js.map +1 -0
- package/dist/analyze/index.d.ts +80 -0
- package/dist/analyze/index.d.ts.map +1 -0
- package/dist/analyze/index.js +306 -0
- package/dist/analyze/index.js.map +1 -0
- package/dist/analyze/llm.d.ts +52 -0
- package/dist/analyze/llm.d.ts.map +1 -0
- package/dist/analyze/llm.js +295 -0
- package/dist/analyze/llm.js.map +1 -0
- package/dist/analyze/prompts.d.ts +14 -0
- package/dist/analyze/prompts.d.ts.map +1 -0
- package/dist/analyze/prompts.js +205 -0
- package/dist/analyze/prompts.js.map +1 -0
- package/dist/analyzer/index.d.ts +5 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +5 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/analyzer/sarif.d.ts +84 -0
- package/dist/analyzer/sarif.d.ts.map +1 -0
- package/dist/analyzer/sarif.js +149 -0
- package/dist/analyzer/sarif.js.map +1 -0
- package/dist/cli/index.d.ts +25 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +821 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/dashboard/data.d.ts +52 -0
- package/dist/dashboard/data.d.ts.map +1 -0
- package/dist/dashboard/data.js +93 -0
- package/dist/dashboard/data.js.map +1 -0
- package/dist/dashboard/diagrams.d.ts +25 -0
- package/dist/dashboard/diagrams.d.ts.map +1 -0
- package/dist/dashboard/diagrams.js +243 -0
- package/dist/dashboard/diagrams.js.map +1 -0
- package/dist/dashboard/generate.d.ts +17 -0
- package/dist/dashboard/generate.d.ts.map +1 -0
- package/dist/dashboard/generate.js +1258 -0
- package/dist/dashboard/generate.js.map +1 -0
- package/dist/dashboard/index.d.ts +7 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +7 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/diff/engine.d.ts +51 -0
- package/dist/diff/engine.d.ts.map +1 -0
- package/dist/diff/engine.js +153 -0
- package/dist/diff/engine.js.map +1 -0
- package/dist/diff/format.d.ts +10 -0
- package/dist/diff/format.d.ts.map +1 -0
- package/dist/diff/format.js +111 -0
- package/dist/diff/format.js.map +1 -0
- package/dist/diff/git.d.ts +24 -0
- package/dist/diff/git.d.ts.map +1 -0
- package/dist/diff/git.js +85 -0
- package/dist/diff/git.js.map +1 -0
- package/dist/diff/index.d.ts +7 -0
- package/dist/diff/index.d.ts.map +1 -0
- package/dist/diff/index.js +7 -0
- package/dist/diff/index.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/init/detect.d.ts +42 -0
- package/dist/init/detect.d.ts.map +1 -0
- package/dist/init/detect.js +185 -0
- package/dist/init/detect.js.map +1 -0
- package/dist/init/index.d.ts +39 -0
- package/dist/init/index.d.ts.map +1 -0
- package/dist/init/index.js +228 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/picker.d.ts +32 -0
- package/dist/init/picker.d.ts.map +1 -0
- package/dist/init/picker.js +105 -0
- package/dist/init/picker.js.map +1 -0
- package/dist/init/templates.d.ts +25 -0
- package/dist/init/templates.d.ts.map +1 -0
- package/dist/init/templates.js +263 -0
- package/dist/init/templates.js.map +1 -0
- package/dist/mcp/index.d.ts +12 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +18 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/lookup.d.ts +27 -0
- package/dist/mcp/lookup.d.ts.map +1 -0
- package/dist/mcp/lookup.js +282 -0
- package/dist/mcp/lookup.js.map +1 -0
- package/dist/mcp/server.d.ts +41 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +388 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/suggest.d.ts +35 -0
- package/dist/mcp/suggest.d.ts.map +1 -0
- package/dist/mcp/suggest.js +268 -0
- package/dist/mcp/suggest.js.map +1 -0
- package/dist/parser/comment-strip.d.ts +15 -0
- package/dist/parser/comment-strip.d.ts.map +1 -0
- package/dist/parser/comment-strip.js +76 -0
- package/dist/parser/comment-strip.js.map +1 -0
- package/dist/parser/index.d.ts +10 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +9 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/normalize.d.ts +22 -0
- package/dist/parser/normalize.d.ts.map +1 -0
- package/dist/parser/normalize.js +42 -0
- package/dist/parser/normalize.js.map +1 -0
- package/dist/parser/parse-file.d.ts +18 -0
- package/dist/parser/parse-file.d.ts.map +1 -0
- package/dist/parser/parse-file.js +68 -0
- package/dist/parser/parse-file.js.map +1 -0
- package/dist/parser/parse-line.d.ts +21 -0
- package/dist/parser/parse-line.d.ts.map +1 -0
- package/dist/parser/parse-line.js +230 -0
- package/dist/parser/parse-line.js.map +1 -0
- package/dist/parser/parse-project.d.ts +31 -0
- package/dist/parser/parse-project.d.ts.map +1 -0
- package/dist/parser/parse-project.js +281 -0
- package/dist/parser/parse-project.js.map +1 -0
- package/dist/report/index.d.ts +6 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +6 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/mermaid.d.ts +15 -0
- package/dist/report/mermaid.d.ts.map +1 -0
- package/dist/report/mermaid.js +260 -0
- package/dist/report/mermaid.js.map +1 -0
- package/dist/report/report.d.ts +16 -0
- package/dist/report/report.d.ts.map +1 -0
- package/dist/report/report.js +211 -0
- package/dist/report/report.js.map +1 -0
- package/dist/tui/commands.d.ts +42 -0
- package/dist/tui/commands.d.ts.map +1 -0
- package/dist/tui/commands.js +1216 -0
- package/dist/tui/commands.js.map +1 -0
- package/dist/tui/config.d.ts +27 -0
- package/dist/tui/config.d.ts.map +1 -0
- package/dist/tui/config.js +27 -0
- package/dist/tui/config.js.map +1 -0
- package/dist/tui/format.d.ts +63 -0
- package/dist/tui/format.d.ts.map +1 -0
- package/dist/tui/format.js +253 -0
- package/dist/tui/format.js.map +1 -0
- package/dist/tui/index.d.ts +18 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +470 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/input.d.ts +63 -0
- package/dist/tui/input.d.ts.map +1 -0
- package/dist/tui/input.js +454 -0
- package/dist/tui/input.js.map +1 -0
- package/dist/types/index.d.ts +254 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +97 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* GuardLink TUI — Interactive terminal interface.
|
|
4
|
+
*
|
|
5
|
+
* Claude Code-style inline REPL: stays in your terminal,
|
|
6
|
+
* slash commands + freeform AI chat, Ctrl+C to exit.
|
|
7
|
+
*
|
|
8
|
+
* @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "Accepts directory path as startup argument"
|
|
9
|
+
* @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "User input passed to AI chat mode"
|
|
10
|
+
* @accepts #prompt-injection on #tui -- "Freeform AI chat is an intentional feature"
|
|
11
|
+
* @mitigates #tui against #path-traversal using #path-validation -- "resolve() normalizes directory path"
|
|
12
|
+
* @boundary between #tui and #llm-client (#tui-llm-boundary) -- "Freeform chat input crosses trust boundary to LLM"
|
|
13
|
+
* @flows User -> #tui via readline -- "Interactive command input from terminal"
|
|
14
|
+
* @flows #tui -> #parser via parseProject -- "Commands trigger parsing operations"
|
|
15
|
+
* @flows #tui -> #llm-client via cmdChat -- "Freeform text dispatched to AI provider"
|
|
16
|
+
*/
|
|
17
|
+
import { createInterface } from 'node:readline';
|
|
18
|
+
import { resolve, basename } from 'node:path';
|
|
19
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
20
|
+
import { parseProject } from '../parser/index.js';
|
|
21
|
+
import { C, computeGrade, gradeColored } from './format.js';
|
|
22
|
+
import { computeSeverity } from '../dashboard/data.js';
|
|
23
|
+
import { resolveLLMConfig } from './config.js';
|
|
24
|
+
import { InputBox } from './input.js';
|
|
25
|
+
import gradient from 'gradient-string';
|
|
26
|
+
import { cmdHelp, cmdStatus, cmdExposures, cmdShow, cmdAssets, cmdFiles, cmdView, cmdInit, cmdParse, cmdScan, cmdValidate, cmdDiff, cmdSarif, cmdModel, cmdThreatReport, cmdThreatReports, cmdAnnotate, cmdChat, cmdReport, cmdDashboard, cmdGal, } from './commands.js';
|
|
27
|
+
// ─── Command registry ────────────────────────────────────────────────
|
|
28
|
+
const COMMANDS = [
|
|
29
|
+
'/help', '/gal', '/init', '/parse', '/run', '/status', '/scan',
|
|
30
|
+
'/validate', '/diff', '/sarif',
|
|
31
|
+
'/exposures', '/show', '/assets', '/files', '/view',
|
|
32
|
+
'/threat-report', '/threat-reports', '/annotate', '/model',
|
|
33
|
+
'/report', '/dashboard',
|
|
34
|
+
'/quit',
|
|
35
|
+
];
|
|
36
|
+
const ANALYZE_FRAMEWORKS = ['stride', 'dread', 'pasta', 'attacker', 'rapid', 'general'];
|
|
37
|
+
const ASCII_LOGO = `
|
|
38
|
+
██████ ██ ██ █████ ██████ ██████ ██ ██ ███ ██ ██ ██
|
|
39
|
+
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██
|
|
40
|
+
██ ███ ██ ██ ███████ ██████ ██ ██ ██ ██ ██ ██ ██ █████
|
|
41
|
+
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
|
42
|
+
██████ ██████ ██ ██ ██ ██ ██████ ███████ ██ ██ ████ ██ ██
|
|
43
|
+
`;
|
|
44
|
+
/** Command palette entries for InputBox */
|
|
45
|
+
const PALETTE_COMMANDS = [
|
|
46
|
+
{ command: '/init', label: 'Initialize project' },
|
|
47
|
+
{ command: '/parse', label: 'Parse annotations', aliases: ['/run'] },
|
|
48
|
+
{ command: '/status', label: 'Risk grade + stats' },
|
|
49
|
+
{ command: '/scan', label: 'Find unannotated code' },
|
|
50
|
+
{ command: '/validate', label: 'Syntax + ref checks' },
|
|
51
|
+
{ command: '/exposures', label: 'List exposures by severity' },
|
|
52
|
+
{ command: '/show', label: 'Exposure detail + code context' },
|
|
53
|
+
{ command: '/assets', label: 'Asset tree' },
|
|
54
|
+
{ command: '/files', label: 'Annotated file tree' },
|
|
55
|
+
{ command: '/view', label: 'File annotations + code' },
|
|
56
|
+
{ command: '/threat-report', label: 'AI threat report' },
|
|
57
|
+
{ command: '/threat-reports', label: 'List saved threat reports' },
|
|
58
|
+
{ command: '/annotate', label: 'Launch coding agent' },
|
|
59
|
+
{ command: '/model', label: 'Set AI provider' },
|
|
60
|
+
{ command: '/report', label: 'Generate markdown report' },
|
|
61
|
+
{ command: '/dashboard', label: 'HTML dashboard' },
|
|
62
|
+
{ command: '/diff', label: 'Compare vs git ref' },
|
|
63
|
+
{ command: '/sarif', label: 'Export SARIF 2.1.0' },
|
|
64
|
+
{ command: '/gal', label: 'GAL annotation language guide' },
|
|
65
|
+
{ command: '/help', label: 'Show all commands' },
|
|
66
|
+
{ command: '/quit', label: 'Exit GuardLink CLI', aliases: ['/exit', '/q'] },
|
|
67
|
+
];
|
|
68
|
+
// ─── Welcome banner ──────────────────────────────────────────────────
|
|
69
|
+
function printBanner(ctx) {
|
|
70
|
+
console.log(gradient(['#00ff41', '#00d4ff'])(ASCII_LOGO));
|
|
71
|
+
const version = getVersion();
|
|
72
|
+
const LW = 34; // left column inner width
|
|
73
|
+
const RW = 34; // right column inner width
|
|
74
|
+
// Total visible box width: │ _(LW)_ │ _(RW)_ │ = LW+RW+7
|
|
75
|
+
const W = LW + RW + 7;
|
|
76
|
+
// Box-drawing helpers
|
|
77
|
+
const pad = (s, visLen, w) => s + ' '.repeat(Math.max(0, w - visLen));
|
|
78
|
+
// Borders — all exactly W visible chars (Bravos teal theme)
|
|
79
|
+
const title = ` GuardLink v${version} `;
|
|
80
|
+
const topDashes = W - 3 - title.length; // 3 = ┌─ (2) + ┐ (1)
|
|
81
|
+
const topBorder = C.teal('┌─') + C.bold(title) + C.teal('─'.repeat(Math.max(0, topDashes)) + '┐');
|
|
82
|
+
const midBorder = C.teal('├' + '─'.repeat(LW + 2) + '┼' + '─'.repeat(RW + 2) + '┤');
|
|
83
|
+
const botBorder = C.teal('└' + '─'.repeat(W - 2) + '┘');
|
|
84
|
+
// Row helper: │ left(LW) │ right(RW) │
|
|
85
|
+
const row = (left, leftVis, right, rightVis) => {
|
|
86
|
+
return C.teal('│') + ' ' + pad(left, leftVis, LW) + ' ' + C.teal('│') + ' ' + pad(right, rightVis, RW) + ' ' + C.teal('│');
|
|
87
|
+
};
|
|
88
|
+
const emptyRow = () => row('', 0, '', 0);
|
|
89
|
+
// Build left & right column content
|
|
90
|
+
const leftLines = [];
|
|
91
|
+
const rightLines = [];
|
|
92
|
+
if (ctx.model) {
|
|
93
|
+
const sev = computeSeverity(ctx.model);
|
|
94
|
+
const open = sev.critical + sev.high + sev.medium + sev.low;
|
|
95
|
+
const grade = computeGrade(ctx.model.exposures.length, ctx.model.mitigations.length);
|
|
96
|
+
// Left: project identity
|
|
97
|
+
const projLine = ctx.projectName;
|
|
98
|
+
leftLines.push({ text: C.bold(projLine), vis: projLine.length });
|
|
99
|
+
const gradeVis = `Grade: ${grade} · ${open} open exposures`;
|
|
100
|
+
leftLines.push({ text: `Grade: ${gradeColored(grade)} · ${open} open exposures`, vis: gradeVis.length });
|
|
101
|
+
leftLines.push({ text: '', vis: 0 }); // spacer
|
|
102
|
+
// Severity breakdown
|
|
103
|
+
const sevParts = [];
|
|
104
|
+
if (sev.critical > 0)
|
|
105
|
+
sevParts.push({ text: C.red.bold(String(sev.critical)) + ' critical', vis: `${sev.critical} critical` });
|
|
106
|
+
if (sev.high > 0)
|
|
107
|
+
sevParts.push({ text: C.yellow.bold(String(sev.high)) + ' high', vis: `${sev.high} high` });
|
|
108
|
+
if (sev.medium > 0)
|
|
109
|
+
sevParts.push({ text: C.yellow(String(sev.medium)) + ' medium', vis: `${sev.medium} medium` });
|
|
110
|
+
if (sev.low > 0)
|
|
111
|
+
sevParts.push({ text: C.blue(String(sev.low)) + ' low', vis: `${sev.low} low` });
|
|
112
|
+
if (sevParts.length <= 2) {
|
|
113
|
+
const sevLine = sevParts.map(p => p.text).join(C.dim(' · '));
|
|
114
|
+
const sevVis = sevParts.map(p => p.vis).join(' · ');
|
|
115
|
+
leftLines.push({ text: sevLine, vis: sevVis.length });
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const l1 = sevParts.slice(0, 2);
|
|
119
|
+
const l2 = sevParts.slice(2);
|
|
120
|
+
leftLines.push({ text: l1.map(p => p.text).join(C.dim(' · ')), vis: l1.map(p => p.vis).join(' · ').length });
|
|
121
|
+
leftLines.push({ text: l2.map(p => p.text).join(C.dim(' · ')), vis: l2.map(p => p.vis).join(' · ').length });
|
|
122
|
+
}
|
|
123
|
+
leftLines.push({ text: '', vis: 0 }); // spacer
|
|
124
|
+
// Stats
|
|
125
|
+
const s1 = `${ctx.model.assets.length} assets · ${ctx.model.threats.length} threats`;
|
|
126
|
+
leftLines.push({ text: C.dim(s1), vis: s1.length });
|
|
127
|
+
const s2 = `${ctx.model.controls.length} controls · ${ctx.model.annotations_parsed} ann`;
|
|
128
|
+
leftLines.push({ text: C.dim(s2), vis: s2.length });
|
|
129
|
+
// Right: top threats
|
|
130
|
+
const threatFreq = new Map();
|
|
131
|
+
for (const e of ctx.model.exposures) {
|
|
132
|
+
const prev = threatFreq.get(e.threat);
|
|
133
|
+
if (prev) {
|
|
134
|
+
prev.count++;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const def = ctx.model.threats.find(t => t.id === e.threat);
|
|
138
|
+
threatFreq.set(e.threat, { count: 1, sev: def?.severity || 'medium' });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const topThreats = [...threatFreq.entries()]
|
|
142
|
+
.sort((a, b) => b[1].count - a[1].count)
|
|
143
|
+
.slice(0, 3);
|
|
144
|
+
if (topThreats.length) {
|
|
145
|
+
rightLines.push({ text: C.yellow.bold('Top threats'), vis: 'Top threats'.length });
|
|
146
|
+
for (const [id, { count, sev: s }] of topThreats) {
|
|
147
|
+
const sevC = s === 'critical' ? C.red : s === 'high' ? C.yellow : C.dim;
|
|
148
|
+
const countStr = `x${count}`;
|
|
149
|
+
const gap = Math.max(2, RW - id.length - countStr.length);
|
|
150
|
+
rightLines.push({ text: sevC(id) + ' '.repeat(gap) + C.dim(countStr), vis: id.length + gap + countStr.length });
|
|
151
|
+
}
|
|
152
|
+
rightLines.push({ text: '', vis: 0 });
|
|
153
|
+
}
|
|
154
|
+
// Right: quick start
|
|
155
|
+
rightLines.push({ text: C.cyan.bold('Quick start'), vis: 'Quick start'.length });
|
|
156
|
+
const tips = [
|
|
157
|
+
['/init', 'Initialize project'],
|
|
158
|
+
['/exposures', 'List by severity'],
|
|
159
|
+
['/files', 'Browse files'],
|
|
160
|
+
['/show <n>', 'Detail + code'],
|
|
161
|
+
['/threat-report', 'AI threat report'],
|
|
162
|
+
];
|
|
163
|
+
for (const [cmd, desc] of tips) {
|
|
164
|
+
const tipVis = cmd + ' ' + desc;
|
|
165
|
+
rightLines.push({ text: C.bold(cmd) + ' ' + C.dim(desc), vis: tipVis.length });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// No model state
|
|
170
|
+
leftLines.push({ text: C.bold(ctx.projectName || 'No project'), vis: (ctx.projectName || 'No project').length });
|
|
171
|
+
leftLines.push({ text: C.dim('No threat model found'), vis: 'No threat model found'.length });
|
|
172
|
+
leftLines.push({ text: '', vis: 0 });
|
|
173
|
+
leftLines.push({ text: C.dim('Run /init to get started'), vis: 'Run /init to get started'.length });
|
|
174
|
+
rightLines.push({ text: C.cyan.bold('Getting started'), vis: 'Getting started'.length });
|
|
175
|
+
const tips = [
|
|
176
|
+
['/init', 'Initialize project'],
|
|
177
|
+
['/annotate', 'Add annotations'],
|
|
178
|
+
['/parse', 'Build threat model'],
|
|
179
|
+
];
|
|
180
|
+
for (const [cmd, desc] of tips) {
|
|
181
|
+
const tipVis = cmd + ' ' + desc;
|
|
182
|
+
rightLines.push({ text: C.bold(cmd) + ' ' + C.dim(desc), vis: tipVis.length });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// AI provider (bottom of left column)
|
|
186
|
+
const llm = resolveLLMConfig(ctx.root);
|
|
187
|
+
if (llm) {
|
|
188
|
+
leftLines.push({ text: '', vis: 0 });
|
|
189
|
+
const aiVis = `AI: ${llm.provider}/${llm.model}`;
|
|
190
|
+
leftLines.push({ text: C.dim('AI: ') + C.cyan(`${llm.provider}/${llm.model}`), vis: aiVis.length });
|
|
191
|
+
}
|
|
192
|
+
// Equalize heights
|
|
193
|
+
const maxRows = Math.max(leftLines.length, rightLines.length);
|
|
194
|
+
while (leftLines.length < maxRows)
|
|
195
|
+
leftLines.push({ text: '', vis: 0 });
|
|
196
|
+
while (rightLines.length < maxRows)
|
|
197
|
+
rightLines.push({ text: '', vis: 0 });
|
|
198
|
+
// Render
|
|
199
|
+
console.log('');
|
|
200
|
+
console.log(topBorder);
|
|
201
|
+
console.log(emptyRow()); // breathing room below title
|
|
202
|
+
for (let i = 0; i < maxRows; i++) {
|
|
203
|
+
console.log(row(leftLines[i].text, leftLines[i].vis, rightLines[i].text, rightLines[i].vis));
|
|
204
|
+
}
|
|
205
|
+
console.log(botBorder);
|
|
206
|
+
console.log('');
|
|
207
|
+
console.log(C.dim(' GuardLink CLI · /help for commands · /gal for annotation guide · Ctrl+C to exit.'));
|
|
208
|
+
console.log('');
|
|
209
|
+
}
|
|
210
|
+
function getVersion() {
|
|
211
|
+
try {
|
|
212
|
+
// Try relative to this file
|
|
213
|
+
const dir = new URL('.', import.meta.url).pathname;
|
|
214
|
+
const pkgPath = resolve(dir, '../../package.json');
|
|
215
|
+
if (existsSync(pkgPath)) {
|
|
216
|
+
return JSON.parse(readFileSync(pkgPath, 'utf-8')).version || '0.0.0';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch { /* ignore */ }
|
|
220
|
+
try {
|
|
221
|
+
// Try from cwd
|
|
222
|
+
const cwdPkg = resolve(process.cwd(), 'node_modules/guardlink/package.json');
|
|
223
|
+
if (existsSync(cwdPkg)) {
|
|
224
|
+
return JSON.parse(readFileSync(cwdPkg, 'utf-8')).version || '0.0.0';
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
catch { /* ignore */ }
|
|
228
|
+
return '0.0.0';
|
|
229
|
+
}
|
|
230
|
+
// ─── Compact command list (shown on bare "/") ───────────────────────
|
|
231
|
+
function printCommandList() {
|
|
232
|
+
const cmds = [
|
|
233
|
+
['/init', 'Initialize project'],
|
|
234
|
+
['/parse', 'Parse annotations'],
|
|
235
|
+
['/status', 'Risk grade + stats'],
|
|
236
|
+
['/scan', 'Find unannotated code'],
|
|
237
|
+
['/validate', 'Syntax + ref checks'],
|
|
238
|
+
['/exposures', 'List exposures'],
|
|
239
|
+
['/show <n>', 'Exposure detail + code'],
|
|
240
|
+
['/assets', 'Asset tree'],
|
|
241
|
+
['/files', 'Annotated file tree'],
|
|
242
|
+
['/view <file>', 'File annotations + code'],
|
|
243
|
+
['/threat-report', 'AI threat report'],
|
|
244
|
+
['/threat-reports', 'List saved reports'],
|
|
245
|
+
['/annotate', 'Launch coding agent'],
|
|
246
|
+
['/model', 'Set AI provider'],
|
|
247
|
+
['/report', 'Generate reports'],
|
|
248
|
+
['/dashboard', 'HTML dashboard'],
|
|
249
|
+
['/diff [ref]', 'Compare vs git ref'],
|
|
250
|
+
['/sarif', 'Export SARIF'],
|
|
251
|
+
['/gal', 'GAL annotation language guide'],
|
|
252
|
+
['/help', 'Full help'],
|
|
253
|
+
['/quit', 'Exit GuardLink CLI'],
|
|
254
|
+
];
|
|
255
|
+
console.log('');
|
|
256
|
+
for (const [cmd, desc] of cmds) {
|
|
257
|
+
console.log(` ${C.cyan(cmd.padEnd(16))}${C.dim(desc)}`);
|
|
258
|
+
}
|
|
259
|
+
console.log('');
|
|
260
|
+
}
|
|
261
|
+
// ─── Command dispatch ────────────────────────────────────────────────
|
|
262
|
+
async function dispatch(input, ctx) {
|
|
263
|
+
const trimmed = input.trim();
|
|
264
|
+
if (!trimmed)
|
|
265
|
+
return true; // continue
|
|
266
|
+
// Quit
|
|
267
|
+
if (trimmed === '/quit' || trimmed === '/exit' || trimmed === '/q') {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
// Slash commands
|
|
271
|
+
if (trimmed.startsWith('/')) {
|
|
272
|
+
// Bare "/" — show command list inline
|
|
273
|
+
if (trimmed === '/') {
|
|
274
|
+
printCommandList();
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
const spaceIdx = trimmed.indexOf(' ');
|
|
278
|
+
const cmd = spaceIdx === -1 ? trimmed.toLowerCase() : trimmed.slice(0, spaceIdx).toLowerCase();
|
|
279
|
+
const args = spaceIdx === -1 ? '' : trimmed.slice(spaceIdx + 1);
|
|
280
|
+
try {
|
|
281
|
+
switch (cmd) {
|
|
282
|
+
case '/help':
|
|
283
|
+
cmdHelp();
|
|
284
|
+
break;
|
|
285
|
+
case '/gal':
|
|
286
|
+
cmdGal();
|
|
287
|
+
break;
|
|
288
|
+
case '/status':
|
|
289
|
+
cmdStatus(ctx);
|
|
290
|
+
break;
|
|
291
|
+
case '/exposures':
|
|
292
|
+
cmdExposures(args, ctx);
|
|
293
|
+
break;
|
|
294
|
+
case '/show':
|
|
295
|
+
cmdShow(args, ctx);
|
|
296
|
+
break;
|
|
297
|
+
case '/assets':
|
|
298
|
+
cmdAssets(ctx);
|
|
299
|
+
break;
|
|
300
|
+
case '/files':
|
|
301
|
+
cmdFiles(ctx);
|
|
302
|
+
break;
|
|
303
|
+
case '/view':
|
|
304
|
+
cmdView(args, ctx);
|
|
305
|
+
break;
|
|
306
|
+
case '/init':
|
|
307
|
+
await cmdInit(args, ctx);
|
|
308
|
+
break;
|
|
309
|
+
case '/parse':
|
|
310
|
+
case '/run':
|
|
311
|
+
await cmdParse(ctx);
|
|
312
|
+
break;
|
|
313
|
+
case '/scan':
|
|
314
|
+
cmdScan(ctx);
|
|
315
|
+
break;
|
|
316
|
+
case '/validate':
|
|
317
|
+
await cmdValidate(ctx);
|
|
318
|
+
break;
|
|
319
|
+
case '/diff':
|
|
320
|
+
await cmdDiff(args, ctx);
|
|
321
|
+
break;
|
|
322
|
+
case '/sarif':
|
|
323
|
+
await cmdSarif(args, ctx);
|
|
324
|
+
break;
|
|
325
|
+
case '/model':
|
|
326
|
+
await cmdModel(ctx);
|
|
327
|
+
break;
|
|
328
|
+
case '/threat-report':
|
|
329
|
+
await cmdThreatReport(args, ctx);
|
|
330
|
+
break;
|
|
331
|
+
case '/threat-reports':
|
|
332
|
+
cmdThreatReports(ctx);
|
|
333
|
+
break;
|
|
334
|
+
case '/annotate':
|
|
335
|
+
await cmdAnnotate(args, ctx);
|
|
336
|
+
break;
|
|
337
|
+
case '/report':
|
|
338
|
+
await cmdReport(ctx);
|
|
339
|
+
break;
|
|
340
|
+
case '/dashboard':
|
|
341
|
+
await cmdDashboard(ctx);
|
|
342
|
+
break;
|
|
343
|
+
default:
|
|
344
|
+
// Fuzzy match
|
|
345
|
+
const matches = COMMANDS.filter(c => c.startsWith(cmd));
|
|
346
|
+
if (matches.length === 1) {
|
|
347
|
+
// Re-dispatch with full command
|
|
348
|
+
return dispatch(matches[0] + ' ' + args, ctx);
|
|
349
|
+
}
|
|
350
|
+
else if (matches.length > 1) {
|
|
351
|
+
console.log(C.warn(` Ambiguous: ${matches.join(', ')}`));
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
console.log(C.warn(` Unknown command: ${cmd}. Type /help.`));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
catch (err) {
|
|
359
|
+
console.log(C.error(` Error: ${err.message}`));
|
|
360
|
+
}
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
// Freeform text → AI chat
|
|
364
|
+
await cmdChat(trimmed, ctx);
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
// ─── Main entry point ────────────────────────────────────────────────
|
|
368
|
+
let exiting = false;
|
|
369
|
+
export async function startTui(dir) {
|
|
370
|
+
const root = resolve(dir || process.cwd());
|
|
371
|
+
const projectName = detectProjectName(root);
|
|
372
|
+
// Create a readline interface for sub-prompts (ask() in commands)
|
|
373
|
+
// This is only used when InputBox is paused during command execution
|
|
374
|
+
const rl = createInterface({
|
|
375
|
+
input: process.stdin,
|
|
376
|
+
output: process.stdout,
|
|
377
|
+
terminal: process.stdin.isTTY ?? false,
|
|
378
|
+
});
|
|
379
|
+
rl.pause(); // starts paused — InputBox handles primary input
|
|
380
|
+
const ctx = {
|
|
381
|
+
root,
|
|
382
|
+
model: null,
|
|
383
|
+
projectName,
|
|
384
|
+
lastExposures: [],
|
|
385
|
+
rl,
|
|
386
|
+
};
|
|
387
|
+
// Try loading existing model
|
|
388
|
+
try {
|
|
389
|
+
const { model } = await parseProject({ root, project: projectName });
|
|
390
|
+
if (model.annotations_parsed > 0) {
|
|
391
|
+
ctx.model = model;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
catch {
|
|
395
|
+
// No model yet — that's fine
|
|
396
|
+
}
|
|
397
|
+
// Welcome
|
|
398
|
+
printBanner(ctx);
|
|
399
|
+
// Create InputBox
|
|
400
|
+
const inputBox = new InputBox({
|
|
401
|
+
placeholder: 'Type a command or ask a question...',
|
|
402
|
+
prompt: '›',
|
|
403
|
+
commands: PALETTE_COMMANDS,
|
|
404
|
+
maxPaletteItems: 21,
|
|
405
|
+
});
|
|
406
|
+
function goodbye() {
|
|
407
|
+
if (exiting)
|
|
408
|
+
return;
|
|
409
|
+
exiting = true;
|
|
410
|
+
process.exit(0);
|
|
411
|
+
}
|
|
412
|
+
inputBox.start(
|
|
413
|
+
// onSubmit — called when user presses Enter
|
|
414
|
+
async (line) => {
|
|
415
|
+
inputBox.pause();
|
|
416
|
+
const shouldContinue = await dispatch(line, ctx);
|
|
417
|
+
if (shouldContinue) {
|
|
418
|
+
inputBox.resume();
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
goodbye();
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
// onClose — called on Ctrl+C
|
|
425
|
+
() => goodbye());
|
|
426
|
+
}
|
|
427
|
+
const GENERIC_PKG_NAMES = new Set([
|
|
428
|
+
'my-v0-project', 'my-app', 'my-project', 'my-next-app', 'vite-project',
|
|
429
|
+
'react-app', 'create-react-app', 'starter', 'app', 'project', 'unknown',
|
|
430
|
+
]);
|
|
431
|
+
function detectProjectName(root) {
|
|
432
|
+
// Try git remote origin URL first (most reliable repo name)
|
|
433
|
+
try {
|
|
434
|
+
const gitConfigPath = resolve(root, '.git', 'config');
|
|
435
|
+
if (existsSync(gitConfigPath)) {
|
|
436
|
+
const gitConfig = readFileSync(gitConfigPath, 'utf-8');
|
|
437
|
+
const m = gitConfig.match(/url\s*=\s*.*[/:]([^/\s]+?)(?:\.git)?\s*$/m);
|
|
438
|
+
if (m)
|
|
439
|
+
return m[1];
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
catch { /* ignore */ }
|
|
443
|
+
// Try package.json (skip generic scaffold names)
|
|
444
|
+
const pkgPath = resolve(root, 'package.json');
|
|
445
|
+
if (existsSync(pkgPath)) {
|
|
446
|
+
try {
|
|
447
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
448
|
+
if (pkg.name && !GENERIC_PKG_NAMES.has(pkg.name))
|
|
449
|
+
return pkg.name;
|
|
450
|
+
}
|
|
451
|
+
catch { /* ignore */ }
|
|
452
|
+
}
|
|
453
|
+
// Try Cargo.toml
|
|
454
|
+
const cargoPath = resolve(root, 'Cargo.toml');
|
|
455
|
+
if (existsSync(cargoPath)) {
|
|
456
|
+
try {
|
|
457
|
+
const cargo = readFileSync(cargoPath, 'utf-8');
|
|
458
|
+
const match = cargo.match(/name\s*=\s*"([^"]+)"/);
|
|
459
|
+
if (match)
|
|
460
|
+
return match[1];
|
|
461
|
+
}
|
|
462
|
+
catch { /* ignore */ }
|
|
463
|
+
}
|
|
464
|
+
return basename(root);
|
|
465
|
+
}
|
|
466
|
+
// Allow direct execution
|
|
467
|
+
if (import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith('/tui/index.ts') || process.argv[1]?.endsWith('/tui/index.js')) {
|
|
468
|
+
startTui(process.argv[2]).catch(console.error);
|
|
469
|
+
}
|
|
470
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tui/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GuardLink TUI — Enhanced input box with bordered frame,
|
|
3
|
+
* placeholder text, and slash command palette.
|
|
4
|
+
*
|
|
5
|
+
* Inspired by Claude Code's input UX:
|
|
6
|
+
* ┌──────────────────────────────────────┐
|
|
7
|
+
* │ › type a command or question... │
|
|
8
|
+
* └──────────────────────────────────────┘
|
|
9
|
+
* /exposures List by severity
|
|
10
|
+
* /files Browse files
|
|
11
|
+
* /show <n> Detail + code
|
|
12
|
+
*
|
|
13
|
+
* Uses raw stdin mode for full keystroke control.
|
|
14
|
+
*/
|
|
15
|
+
export interface InputBoxOptions {
|
|
16
|
+
/** Placeholder shown when input is empty */
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
/** Prompt character (default: ›) */
|
|
19
|
+
prompt?: string;
|
|
20
|
+
/** Available slash commands for palette */
|
|
21
|
+
commands?: CommandEntry[];
|
|
22
|
+
/** Max palette items to show */
|
|
23
|
+
maxPaletteItems?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface CommandEntry {
|
|
26
|
+
command: string;
|
|
27
|
+
label: string;
|
|
28
|
+
aliases?: string[];
|
|
29
|
+
}
|
|
30
|
+
export declare class InputBox {
|
|
31
|
+
private buffer;
|
|
32
|
+
private cursor;
|
|
33
|
+
private placeholder;
|
|
34
|
+
private prompt;
|
|
35
|
+
private commands;
|
|
36
|
+
private maxPalette;
|
|
37
|
+
private palette;
|
|
38
|
+
private lastRenderHeight;
|
|
39
|
+
private lastCursorFromBottom;
|
|
40
|
+
private active;
|
|
41
|
+
private onSubmit;
|
|
42
|
+
private onClose;
|
|
43
|
+
private paused;
|
|
44
|
+
private rawHandler;
|
|
45
|
+
private ctrlCPending;
|
|
46
|
+
private ctrlCTimer;
|
|
47
|
+
private showExitHint;
|
|
48
|
+
constructor(opts?: InputBoxOptions);
|
|
49
|
+
/** Start listening for input. Returns cleanup function. */
|
|
50
|
+
start(onSubmit: (line: string) => void, onClose: () => void): void;
|
|
51
|
+
/** Pause input (while command executes) */
|
|
52
|
+
pause(): void;
|
|
53
|
+
/** Resume input after command completes */
|
|
54
|
+
resume(): void;
|
|
55
|
+
/** Stop listening entirely */
|
|
56
|
+
stop(): void;
|
|
57
|
+
private handleKey;
|
|
58
|
+
private updatePalette;
|
|
59
|
+
private getTermWidth;
|
|
60
|
+
private clearRender;
|
|
61
|
+
private render;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/tui/input.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,MAAM,WAAW,eAAe;IAC9B,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,gCAAgC;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAoBD,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAA4D;IAC3E,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,oBAAoB,CAAa;IACzC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAyC;IACzD,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAAyC;IAC3D,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,YAAY,CAAkB;gBAE1B,IAAI,GAAE,eAAoB;IAOtC,2DAA2D;IAC3D,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAiBlE,2CAA2C;IAC3C,KAAK,IAAI,IAAI;IAYb,2CAA2C;IAC3C,MAAM,IAAI,IAAI;IAoBd,8BAA8B;IAC9B,IAAI,IAAI,IAAI;IAcZ,OAAO,CAAC,SAAS;IAsLjB,OAAO,CAAC,aAAa;IA8BrB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,MAAM;CAyGf"}
|