codemini-cli 0.5.10 → 0.5.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/OPERATIONS.md +242 -242
- package/README.md +588 -588
- package/codemini-web/dist/assets/{highlighted-body-OFNGDK62-7HL7yft8.js → highlighted-body-OFNGDK62-CANOG7Xg.js} +1 -1
- package/codemini-web/dist/assets/{index-BK75hMb2.js → index-B71xykPM.js} +108 -108
- package/codemini-web/dist/assets/index-Dkq1DdDX.css +2 -0
- package/codemini-web/dist/assets/mermaid-GHXKKRXX-Z_w7M93P.js +1 -0
- package/codemini-web/dist/index.html +23 -23
- package/codemini-web/lib/approval-manager.js +32 -32
- package/codemini-web/lib/runtime-bridge.js +17 -11
- package/codemini-web/server.js +534 -205
- package/deployment.md +212 -212
- package/package.json +1 -1
- package/skills/brainstorm/SKILL.md +77 -77
- package/skills/codemini.skills.json +40 -40
- package/skills/grill-me/SKILL.md +30 -30
- package/skills/superpowers-lite/SKILL.md +82 -82
- package/src/cli.js +74 -74
- package/src/commands/chat.js +210 -210
- package/src/commands/run.js +313 -313
- package/src/commands/skill.js +438 -304
- package/src/commands/web.js +57 -57
- package/src/core/agent-loop.js +980 -980
- package/src/core/ast.js +309 -307
- package/src/core/chat-runtime.js +6261 -6253
- package/src/core/command-evaluator.js +72 -72
- package/src/core/command-loader.js +311 -311
- package/src/core/command-policy.js +301 -301
- package/src/core/command-risk.js +156 -156
- package/src/core/config-store.js +289 -289
- package/src/core/constants.js +18 -1
- package/src/core/context-compact.js +365 -365
- package/src/core/default-system-prompt.js +114 -107
- package/src/core/dream-audit.js +105 -105
- package/src/core/dream-consolidate.js +229 -229
- package/src/core/dream-evaluator.js +185 -185
- package/src/core/fff-adapter.js +383 -383
- package/src/core/memory-store.js +543 -543
- package/src/core/project-index.js +737 -548
- package/src/core/project-instructions.js +98 -98
- package/src/core/provider/anthropic.js +514 -514
- package/src/core/provider/openai-compatible.js +501 -501
- package/src/core/reflect-skill.js +178 -178
- package/src/core/reply-language.js +40 -40
- package/src/core/session-store.js +474 -474
- package/src/core/shell-profile.js +237 -237
- package/src/core/shell.js +323 -323
- package/src/core/soul.js +69 -69
- package/src/core/system-prompt-composer.js +52 -52
- package/src/core/tool-args.js +199 -154
- package/src/core/tool-output.js +184 -184
- package/src/core/tool-result-store.js +206 -206
- package/src/core/tools.js +3024 -2893
- package/src/core/version.js +11 -11
- package/src/tui/chat-app.js +5171 -5171
- package/src/tui/tool-activity/presenters/misc.js +30 -30
- package/src/tui/tool-activity/presenters/system.js +20 -20
- package/templates/project-requirements/report-shell.html +582 -582
- package/codemini-web/dist/assets/index-BSdIdn3L.css +0 -2
- package/codemini-web/dist/assets/mermaid-GHXKKRXX-Dg9qh8mg.js +0 -1
package/src/core/tool-output.js
CHANGED
|
@@ -1,184 +1,184 @@
|
|
|
1
|
-
import cliTruncate from 'cli-truncate';
|
|
2
|
-
import stripAnsi from 'strip-ansi';
|
|
3
|
-
import { classifyCommandIntent } from './shell.js';
|
|
4
|
-
|
|
5
|
-
const CONTROL_CHARS_RE = /[\u0000-\u0008\u000B-\u001F\u007F]/g;
|
|
6
|
-
|
|
7
|
-
export function sanitizeTextForModel(
|
|
8
|
-
value,
|
|
9
|
-
{
|
|
10
|
-
maxChars = 0,
|
|
11
|
-
maxLineLength = 220,
|
|
12
|
-
maxConsecutiveBlankLines = 1
|
|
13
|
-
} = {}
|
|
14
|
-
) {
|
|
15
|
-
if (value == null) return '';
|
|
16
|
-
|
|
17
|
-
const lines = String(value)
|
|
18
|
-
.replace(/\r\n?/g, '\n')
|
|
19
|
-
.split('\n');
|
|
20
|
-
const output = [];
|
|
21
|
-
let blankRun = 0;
|
|
22
|
-
|
|
23
|
-
for (const rawLine of lines) {
|
|
24
|
-
const line = stripAnsi(rawLine).replace(CONTROL_CHARS_RE, '').replace(/[ \t]+$/g, '');
|
|
25
|
-
if (!line.trim()) {
|
|
26
|
-
blankRun += 1;
|
|
27
|
-
if (blankRun > maxConsecutiveBlankLines) continue;
|
|
28
|
-
output.push('');
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
blankRun = 0;
|
|
33
|
-
output.push(
|
|
34
|
-
maxLineLength > 0
|
|
35
|
-
? cliTruncate(line, maxLineLength, { position: 'end' })
|
|
36
|
-
: line
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
let sanitized = output.join('\n').trimEnd();
|
|
41
|
-
if (maxChars > 0 && sanitized.length > maxChars) {
|
|
42
|
-
sanitized = `${sanitized.slice(0, maxChars)}\n... [sanitized output truncated ${sanitized.length - maxChars} chars]`;
|
|
43
|
-
}
|
|
44
|
-
return sanitized;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function getToolOutputSanitizeOptions(toolName) {
|
|
48
|
-
const name = String(toolName || '').trim();
|
|
49
|
-
if (name === 'read' || name === 'read_ast_node' || name === 'run' || name === 'web_fetch') {
|
|
50
|
-
return {
|
|
51
|
-
maxLineLength: 0
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
return {};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function sanitizePreviewLines(value, { maxLineLength = 220 } = {}) {
|
|
58
|
-
const sanitized = sanitizeTextForModel(value, {
|
|
59
|
-
maxLineLength,
|
|
60
|
-
maxConsecutiveBlankLines: 0
|
|
61
|
-
});
|
|
62
|
-
if (!sanitized) return [];
|
|
63
|
-
return sanitized
|
|
64
|
-
.split('\n')
|
|
65
|
-
.map((line) => line.trim())
|
|
66
|
-
.filter(Boolean);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function summarizeGitStatusPorcelain(stdout) {
|
|
70
|
-
const modified = [];
|
|
71
|
-
const added = [];
|
|
72
|
-
const deleted = [];
|
|
73
|
-
const untracked = [];
|
|
74
|
-
|
|
75
|
-
for (const line of String(stdout || '').split('\n')) {
|
|
76
|
-
const trimmed = line.trimEnd();
|
|
77
|
-
if (!trimmed) continue;
|
|
78
|
-
const status = trimmed.slice(0, 2);
|
|
79
|
-
const file = trimmed.slice(3).trim();
|
|
80
|
-
if (!file) continue;
|
|
81
|
-
if (status === '??') {
|
|
82
|
-
untracked.push(file);
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
if (status.includes('A')) added.push(file);
|
|
86
|
-
else if (status.includes('D')) deleted.push(file);
|
|
87
|
-
else modified.push(file);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const total = modified.length + added.length + deleted.length + untracked.length;
|
|
91
|
-
if (total === 0) return '';
|
|
92
|
-
const lines = [`[git status: ${total} file(s)]`];
|
|
93
|
-
if (modified.length) lines.push(`modified: ${modified.join(', ')}`);
|
|
94
|
-
if (added.length) lines.push(`added: ${added.join(', ')}`);
|
|
95
|
-
if (deleted.length) lines.push(`deleted: ${deleted.join(', ')}`);
|
|
96
|
-
if (untracked.length) lines.push(`untracked: ${untracked.join(', ')}`);
|
|
97
|
-
return lines.join('\n');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function summarizeTestFailure(command, code, stdout, stderr) {
|
|
101
|
-
if (classifyCommandIntent(command).kind !== 'test') {
|
|
102
|
-
return '';
|
|
103
|
-
}
|
|
104
|
-
if (Number(code ?? 0) === 0) return '';
|
|
105
|
-
|
|
106
|
-
const lines = sanitizePreviewLines([stdout, stderr].filter(Boolean).join('\n'), { maxLineLength: 220 });
|
|
107
|
-
const kept = [];
|
|
108
|
-
|
|
109
|
-
for (const line of lines) {
|
|
110
|
-
if (
|
|
111
|
-
/^FAIL\b/.test(line) ||
|
|
112
|
-
/^Test Suites:/.test(line) ||
|
|
113
|
-
/^Tests:/.test(line) ||
|
|
114
|
-
/AssertionError|Error:|Expected|expected .* to /i.test(line) ||
|
|
115
|
-
/^\s*at\b/.test(line) ||
|
|
116
|
-
/:\d+:\d+\)?$/.test(line)
|
|
117
|
-
) {
|
|
118
|
-
kept.push(line);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (kept.length === 0) return '';
|
|
123
|
-
return [`[test failure: exit ${code ?? 1}]`, ...kept.slice(0, 8)].join('\n');
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function summarizeInstallOutput(command, code, stdout) {
|
|
127
|
-
if (classifyCommandIntent(command).kind !== 'install') return '';
|
|
128
|
-
|
|
129
|
-
const lines = sanitizePreviewLines(stdout, { maxLineLength: 220 });
|
|
130
|
-
const kept = [];
|
|
131
|
-
for (const line of lines) {
|
|
132
|
-
if (
|
|
133
|
-
/\b(?:added|removed|changed|audited) \d+ package/i.test(line) ||
|
|
134
|
-
/\bvulnerabilit(?:y|ies)\b/i.test(line) ||
|
|
135
|
-
/looking for funding/i.test(line)
|
|
136
|
-
) {
|
|
137
|
-
kept.push(line);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (kept.length === 0) return '';
|
|
141
|
-
return [`[install summary: exit ${code ?? 0}]`, ...kept.slice(0, 6)].join('\n');
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function summarizeBuildOutput(command, code, stdout, stderr) {
|
|
145
|
-
if (classifyCommandIntent(command).kind !== 'build') return '';
|
|
146
|
-
if (Number(code ?? 0) === 0) return '';
|
|
147
|
-
|
|
148
|
-
const lines = sanitizePreviewLines([stdout, stderr].filter(Boolean).join('\n'), { maxLineLength: 220 });
|
|
149
|
-
const kept = [];
|
|
150
|
-
for (const line of lines) {
|
|
151
|
-
if (
|
|
152
|
-
/\berror\b/i.test(line) ||
|
|
153
|
-
/Build failed/i.test(line) ||
|
|
154
|
-
/failed with/i.test(line)
|
|
155
|
-
) {
|
|
156
|
-
kept.push(line);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
if (kept.length === 0) return '';
|
|
160
|
-
return [`[build failure: exit ${code ?? 1}]`, ...kept.slice(0, 8)].join('\n');
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
export function summarizeRunOutput(result) {
|
|
164
|
-
const command = String(result?.command || '').trim();
|
|
165
|
-
const stdout = String(result?.stdout || '');
|
|
166
|
-
const stderr = String(result?.stderr || '');
|
|
167
|
-
const code = result?.code ?? 0;
|
|
168
|
-
|
|
169
|
-
if (/^git\s+status\b.*(?:--short|-s)\b/i.test(command)) {
|
|
170
|
-
const gitSummary = summarizeGitStatusPorcelain(stdout);
|
|
171
|
-
if (gitSummary) return gitSummary;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const installSummary = summarizeInstallOutput(command, code, stdout);
|
|
175
|
-
if (installSummary) return installSummary;
|
|
176
|
-
|
|
177
|
-
const buildSummary = summarizeBuildOutput(command, code, stdout, stderr);
|
|
178
|
-
if (buildSummary) return buildSummary;
|
|
179
|
-
|
|
180
|
-
const testSummary = summarizeTestFailure(command, code, stdout, stderr);
|
|
181
|
-
if (testSummary) return testSummary;
|
|
182
|
-
|
|
183
|
-
return '';
|
|
184
|
-
}
|
|
1
|
+
import cliTruncate from 'cli-truncate';
|
|
2
|
+
import stripAnsi from 'strip-ansi';
|
|
3
|
+
import { classifyCommandIntent } from './shell.js';
|
|
4
|
+
|
|
5
|
+
const CONTROL_CHARS_RE = /[\u0000-\u0008\u000B-\u001F\u007F]/g;
|
|
6
|
+
|
|
7
|
+
export function sanitizeTextForModel(
|
|
8
|
+
value,
|
|
9
|
+
{
|
|
10
|
+
maxChars = 0,
|
|
11
|
+
maxLineLength = 220,
|
|
12
|
+
maxConsecutiveBlankLines = 1
|
|
13
|
+
} = {}
|
|
14
|
+
) {
|
|
15
|
+
if (value == null) return '';
|
|
16
|
+
|
|
17
|
+
const lines = String(value)
|
|
18
|
+
.replace(/\r\n?/g, '\n')
|
|
19
|
+
.split('\n');
|
|
20
|
+
const output = [];
|
|
21
|
+
let blankRun = 0;
|
|
22
|
+
|
|
23
|
+
for (const rawLine of lines) {
|
|
24
|
+
const line = stripAnsi(rawLine).replace(CONTROL_CHARS_RE, '').replace(/[ \t]+$/g, '');
|
|
25
|
+
if (!line.trim()) {
|
|
26
|
+
blankRun += 1;
|
|
27
|
+
if (blankRun > maxConsecutiveBlankLines) continue;
|
|
28
|
+
output.push('');
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
blankRun = 0;
|
|
33
|
+
output.push(
|
|
34
|
+
maxLineLength > 0
|
|
35
|
+
? cliTruncate(line, maxLineLength, { position: 'end' })
|
|
36
|
+
: line
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let sanitized = output.join('\n').trimEnd();
|
|
41
|
+
if (maxChars > 0 && sanitized.length > maxChars) {
|
|
42
|
+
sanitized = `${sanitized.slice(0, maxChars)}\n... [sanitized output truncated ${sanitized.length - maxChars} chars]`;
|
|
43
|
+
}
|
|
44
|
+
return sanitized;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getToolOutputSanitizeOptions(toolName) {
|
|
48
|
+
const name = String(toolName || '').trim();
|
|
49
|
+
if (name === 'read' || name === 'read_ast_node' || name === 'run' || name === 'web_fetch') {
|
|
50
|
+
return {
|
|
51
|
+
maxLineLength: 0
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function sanitizePreviewLines(value, { maxLineLength = 220 } = {}) {
|
|
58
|
+
const sanitized = sanitizeTextForModel(value, {
|
|
59
|
+
maxLineLength,
|
|
60
|
+
maxConsecutiveBlankLines: 0
|
|
61
|
+
});
|
|
62
|
+
if (!sanitized) return [];
|
|
63
|
+
return sanitized
|
|
64
|
+
.split('\n')
|
|
65
|
+
.map((line) => line.trim())
|
|
66
|
+
.filter(Boolean);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function summarizeGitStatusPorcelain(stdout) {
|
|
70
|
+
const modified = [];
|
|
71
|
+
const added = [];
|
|
72
|
+
const deleted = [];
|
|
73
|
+
const untracked = [];
|
|
74
|
+
|
|
75
|
+
for (const line of String(stdout || '').split('\n')) {
|
|
76
|
+
const trimmed = line.trimEnd();
|
|
77
|
+
if (!trimmed) continue;
|
|
78
|
+
const status = trimmed.slice(0, 2);
|
|
79
|
+
const file = trimmed.slice(3).trim();
|
|
80
|
+
if (!file) continue;
|
|
81
|
+
if (status === '??') {
|
|
82
|
+
untracked.push(file);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (status.includes('A')) added.push(file);
|
|
86
|
+
else if (status.includes('D')) deleted.push(file);
|
|
87
|
+
else modified.push(file);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const total = modified.length + added.length + deleted.length + untracked.length;
|
|
91
|
+
if (total === 0) return '';
|
|
92
|
+
const lines = [`[git status: ${total} file(s)]`];
|
|
93
|
+
if (modified.length) lines.push(`modified: ${modified.join(', ')}`);
|
|
94
|
+
if (added.length) lines.push(`added: ${added.join(', ')}`);
|
|
95
|
+
if (deleted.length) lines.push(`deleted: ${deleted.join(', ')}`);
|
|
96
|
+
if (untracked.length) lines.push(`untracked: ${untracked.join(', ')}`);
|
|
97
|
+
return lines.join('\n');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function summarizeTestFailure(command, code, stdout, stderr) {
|
|
101
|
+
if (classifyCommandIntent(command).kind !== 'test') {
|
|
102
|
+
return '';
|
|
103
|
+
}
|
|
104
|
+
if (Number(code ?? 0) === 0) return '';
|
|
105
|
+
|
|
106
|
+
const lines = sanitizePreviewLines([stdout, stderr].filter(Boolean).join('\n'), { maxLineLength: 220 });
|
|
107
|
+
const kept = [];
|
|
108
|
+
|
|
109
|
+
for (const line of lines) {
|
|
110
|
+
if (
|
|
111
|
+
/^FAIL\b/.test(line) ||
|
|
112
|
+
/^Test Suites:/.test(line) ||
|
|
113
|
+
/^Tests:/.test(line) ||
|
|
114
|
+
/AssertionError|Error:|Expected|expected .* to /i.test(line) ||
|
|
115
|
+
/^\s*at\b/.test(line) ||
|
|
116
|
+
/:\d+:\d+\)?$/.test(line)
|
|
117
|
+
) {
|
|
118
|
+
kept.push(line);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (kept.length === 0) return '';
|
|
123
|
+
return [`[test failure: exit ${code ?? 1}]`, ...kept.slice(0, 8)].join('\n');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function summarizeInstallOutput(command, code, stdout) {
|
|
127
|
+
if (classifyCommandIntent(command).kind !== 'install') return '';
|
|
128
|
+
|
|
129
|
+
const lines = sanitizePreviewLines(stdout, { maxLineLength: 220 });
|
|
130
|
+
const kept = [];
|
|
131
|
+
for (const line of lines) {
|
|
132
|
+
if (
|
|
133
|
+
/\b(?:added|removed|changed|audited) \d+ package/i.test(line) ||
|
|
134
|
+
/\bvulnerabilit(?:y|ies)\b/i.test(line) ||
|
|
135
|
+
/looking for funding/i.test(line)
|
|
136
|
+
) {
|
|
137
|
+
kept.push(line);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (kept.length === 0) return '';
|
|
141
|
+
return [`[install summary: exit ${code ?? 0}]`, ...kept.slice(0, 6)].join('\n');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function summarizeBuildOutput(command, code, stdout, stderr) {
|
|
145
|
+
if (classifyCommandIntent(command).kind !== 'build') return '';
|
|
146
|
+
if (Number(code ?? 0) === 0) return '';
|
|
147
|
+
|
|
148
|
+
const lines = sanitizePreviewLines([stdout, stderr].filter(Boolean).join('\n'), { maxLineLength: 220 });
|
|
149
|
+
const kept = [];
|
|
150
|
+
for (const line of lines) {
|
|
151
|
+
if (
|
|
152
|
+
/\berror\b/i.test(line) ||
|
|
153
|
+
/Build failed/i.test(line) ||
|
|
154
|
+
/failed with/i.test(line)
|
|
155
|
+
) {
|
|
156
|
+
kept.push(line);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (kept.length === 0) return '';
|
|
160
|
+
return [`[build failure: exit ${code ?? 1}]`, ...kept.slice(0, 8)].join('\n');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function summarizeRunOutput(result) {
|
|
164
|
+
const command = String(result?.command || '').trim();
|
|
165
|
+
const stdout = String(result?.stdout || '');
|
|
166
|
+
const stderr = String(result?.stderr || '');
|
|
167
|
+
const code = result?.code ?? 0;
|
|
168
|
+
|
|
169
|
+
if (/^git\s+status\b.*(?:--short|-s)\b/i.test(command)) {
|
|
170
|
+
const gitSummary = summarizeGitStatusPorcelain(stdout);
|
|
171
|
+
if (gitSummary) return gitSummary;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const installSummary = summarizeInstallOutput(command, code, stdout);
|
|
175
|
+
if (installSummary) return installSummary;
|
|
176
|
+
|
|
177
|
+
const buildSummary = summarizeBuildOutput(command, code, stdout, stderr);
|
|
178
|
+
if (buildSummary) return buildSummary;
|
|
179
|
+
|
|
180
|
+
const testSummary = summarizeTestFailure(command, code, stdout, stderr);
|
|
181
|
+
if (testSummary) return testSummary;
|
|
182
|
+
|
|
183
|
+
return '';
|
|
184
|
+
}
|