codemini-cli 0.4.6 → 0.4.8
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/deployment.md +5 -5
- package/package.json +1 -1
- package/src/cli.js +5 -5
- package/src/commands/chat.js +8 -2
- package/src/commands/run.js +9 -3
- package/src/commands/skill.js +1 -1
- package/src/core/agent-loop.js +53 -13
- package/src/core/chat-runtime.js +622 -83
- package/src/core/config-store.js +9 -2
- package/src/core/fff-adapter.js +1 -1
- package/src/core/session-store.js +104 -9
- package/src/core/soul.js +13 -0
- package/templates/project-requirements/report-shell.html +2 -1
package/deployment.md
CHANGED
|
@@ -13,13 +13,13 @@ npm pack
|
|
|
13
13
|
Expected output:
|
|
14
14
|
|
|
15
15
|
```text
|
|
16
|
-
codemini-cli-0.4.
|
|
16
|
+
codemini-cli-0.4.8.tgz
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
If you want to verify the package contents:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
tar -tf codemini-cli-0.4.
|
|
22
|
+
tar -tf codemini-cli-0.4.8.tgz
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## 2. Copy To The Target Machine
|
|
@@ -34,7 +34,7 @@ Copy the generated `.tgz` file to the Win10 machine by one of these methods:
|
|
|
34
34
|
Recommended target path:
|
|
35
35
|
|
|
36
36
|
```powershell
|
|
37
|
-
C:\temp\codemini-cli-0.4.
|
|
37
|
+
C:\temp\codemini-cli-0.4.8.tgz
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
## 3. Environment Requirements
|
|
@@ -58,7 +58,7 @@ npm -v
|
|
|
58
58
|
Global install:
|
|
59
59
|
|
|
60
60
|
```powershell
|
|
61
|
-
npm install -g C:\temp\codemini-cli-0.4.
|
|
61
|
+
npm install -g C:\temp\codemini-cli-0.4.8.tgz
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
If global install is blocked by company policy, install in a working directory instead:
|
|
@@ -66,7 +66,7 @@ If global install is blocked by company policy, install in a working directory i
|
|
|
66
66
|
```powershell
|
|
67
67
|
mkdir C:\temp\coder-test
|
|
68
68
|
cd C:\temp\coder-test
|
|
69
|
-
npm install C:\temp\codemini-cli-0.4.
|
|
69
|
+
npm install C:\temp\codemini-cli-0.4.8.tgz
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
## 5. Confirm Installation
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -10,11 +10,11 @@ const VERSION = pkg.version;
|
|
|
10
10
|
function printHelp() {
|
|
11
11
|
console.log(`codemini ${VERSION}
|
|
12
12
|
Usage:
|
|
13
|
-
codemini [prompt] [--plain]
|
|
14
|
-
codemini chat [prompt] [--plain]
|
|
15
|
-
codemini run <task> [--max-steps N] [--model <name>]
|
|
16
|
-
codemini run --harness <role> <task> [--max-steps N] [--model <name>]
|
|
17
|
-
codemini run --pipeline <task> [--model <name>]
|
|
13
|
+
codemini [prompt] [--plain] [--model <name>] [--fast]
|
|
14
|
+
codemini chat [prompt] [--plain] [--model <name>] [--fast]
|
|
15
|
+
codemini run <task> [--max-steps N] [--model <name>] [--fast]
|
|
16
|
+
codemini run --harness <role> <task> [--max-steps N] [--model <name>] [--fast]
|
|
17
|
+
codemini run --pipeline <task> [--model <name>] [--fast]
|
|
18
18
|
codemini config set|get|list <key> [value]
|
|
19
19
|
codemini doctor
|
|
20
20
|
codemini skill list|install|enable|disable|inspect|reindex [--scope=project|global]
|
package/src/commands/chat.js
CHANGED
|
@@ -11,6 +11,7 @@ function parseChatArgs(args) {
|
|
|
11
11
|
prompt: '',
|
|
12
12
|
sessionId: undefined,
|
|
13
13
|
model: undefined,
|
|
14
|
+
fast: false,
|
|
14
15
|
system: undefined,
|
|
15
16
|
plain: false
|
|
16
17
|
};
|
|
@@ -27,6 +28,10 @@ function parseChatArgs(args) {
|
|
|
27
28
|
i += 1;
|
|
28
29
|
continue;
|
|
29
30
|
}
|
|
31
|
+
if (arg === '--fast' || arg === '--lite') {
|
|
32
|
+
parsed.fast = true;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
30
35
|
if (arg === '--system') {
|
|
31
36
|
parsed.system = args[i + 1];
|
|
32
37
|
i += 1;
|
|
@@ -134,6 +139,7 @@ export async function handleChat(args) {
|
|
|
134
139
|
const parsed = parseChatArgs(args);
|
|
135
140
|
const config = await loadConfig();
|
|
136
141
|
const session = await resolveSession(parsed.sessionId);
|
|
142
|
+
const selectedModel = parsed.fast ? (config.model?.fast_name || config.model?.name) : parsed.model;
|
|
137
143
|
const systemPrompt =
|
|
138
144
|
parsed.system ||
|
|
139
145
|
buildDefaultSystemPrompt(config);
|
|
@@ -141,7 +147,7 @@ export async function handleChat(args) {
|
|
|
141
147
|
const runtime = await createChatRuntime({
|
|
142
148
|
session,
|
|
143
149
|
config,
|
|
144
|
-
model:
|
|
150
|
+
model: selectedModel,
|
|
145
151
|
systemPrompt
|
|
146
152
|
});
|
|
147
153
|
|
|
@@ -164,7 +170,7 @@ export async function handleChat(args) {
|
|
|
164
170
|
React.createElement(ChatApp, {
|
|
165
171
|
runtime,
|
|
166
172
|
sessionId: session.id,
|
|
167
|
-
model:
|
|
173
|
+
model: selectedModel || config.model.name,
|
|
168
174
|
sdkProvider: config.sdk?.provider || 'openai-compatible',
|
|
169
175
|
language: config.ui?.language || 'zh',
|
|
170
176
|
shellName: config.shell?.default || 'powershell',
|
package/src/commands/run.js
CHANGED
|
@@ -22,6 +22,7 @@ function parseRunArgs(args) {
|
|
|
22
22
|
const parsed = {
|
|
23
23
|
task: '',
|
|
24
24
|
model: undefined,
|
|
25
|
+
fast: false,
|
|
25
26
|
maxSteps: 8,
|
|
26
27
|
harness: null,
|
|
27
28
|
pipeline: false
|
|
@@ -33,6 +34,10 @@ function parseRunArgs(args) {
|
|
|
33
34
|
i += 1;
|
|
34
35
|
continue;
|
|
35
36
|
}
|
|
37
|
+
if (arg === '--fast' || arg === '--lite') {
|
|
38
|
+
parsed.fast = true;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
36
41
|
if (arg === '--max-steps') {
|
|
37
42
|
parsed.maxSteps = Number(args[i + 1] || 8);
|
|
38
43
|
i += 1;
|
|
@@ -239,6 +244,7 @@ export async function handleRun(args) {
|
|
|
239
244
|
}
|
|
240
245
|
|
|
241
246
|
const config = await loadConfig();
|
|
247
|
+
const selectedModel = parsed.fast ? (config.model?.fast_name || config.model?.name) : parsed.model;
|
|
242
248
|
const systemPrompt = await buildSystemPrompt(config);
|
|
243
249
|
|
|
244
250
|
if (parsed.pipeline) {
|
|
@@ -246,7 +252,7 @@ export async function handleRun(args) {
|
|
|
246
252
|
task: parsed.task,
|
|
247
253
|
config,
|
|
248
254
|
systemPrompt,
|
|
249
|
-
model:
|
|
255
|
+
model: selectedModel
|
|
250
256
|
});
|
|
251
257
|
for (const step of state.steps) {
|
|
252
258
|
console.log(`\n--- [${step.role}] ${step.title} ---`);
|
|
@@ -261,7 +267,7 @@ export async function handleRun(args) {
|
|
|
261
267
|
task: parsed.task,
|
|
262
268
|
config,
|
|
263
269
|
systemPrompt,
|
|
264
|
-
model:
|
|
270
|
+
model: selectedModel,
|
|
265
271
|
maxSteps: parsed.maxSteps
|
|
266
272
|
});
|
|
267
273
|
console.log(result.text);
|
|
@@ -276,7 +282,7 @@ export async function handleRun(args) {
|
|
|
276
282
|
const result = await runAgentLoop({
|
|
277
283
|
systemPrompt,
|
|
278
284
|
userPrompt: parsed.task,
|
|
279
|
-
model:
|
|
285
|
+
model: selectedModel || config.model.name,
|
|
280
286
|
toolDefinitions: definitions,
|
|
281
287
|
toolHandlers: handlers,
|
|
282
288
|
toolFormatters: formatters,
|
package/src/commands/skill.js
CHANGED
|
@@ -65,7 +65,7 @@ async function setSkillEnabledConfig(name, enabled) {
|
|
|
65
65
|
await saveConfig(config);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
async function listSkillEntries({ scope = 'all', cwd = process.cwd() } = {}) {
|
|
68
|
+
export async function listSkillEntries({ scope = 'all', cwd = process.cwd() } = {}) {
|
|
69
69
|
const commands = await loadCommandsAndSkills(cwd);
|
|
70
70
|
const config = await loadConfig();
|
|
71
71
|
const entries = [];
|
package/src/core/agent-loop.js
CHANGED
|
@@ -753,13 +753,17 @@ export async function runAgentLoop({
|
|
|
753
753
|
const effectiveArgs = approvalState.args || args;
|
|
754
754
|
|
|
755
755
|
if (approvalState.errorContent) {
|
|
756
|
+
const summary = trimInline(approvalState.errorContent, 120);
|
|
756
757
|
if (onEvent) {
|
|
757
|
-
onEvent({ type: 'tool:error', name: displayName, id: call.id, arguments: effectiveArgs, durationMs: 0, summary
|
|
758
|
+
onEvent({ type: 'tool:error', name: displayName, id: call.id, arguments: effectiveArgs, durationMs: 0, summary });
|
|
758
759
|
}
|
|
759
760
|
return {
|
|
760
761
|
callId: call.id,
|
|
761
762
|
content: approvalState.errorContent,
|
|
762
|
-
error: true
|
|
763
|
+
error: true,
|
|
764
|
+
durationMs: 0,
|
|
765
|
+
summary,
|
|
766
|
+
status: 'error'
|
|
763
767
|
};
|
|
764
768
|
}
|
|
765
769
|
|
|
@@ -772,27 +776,46 @@ export async function runAgentLoop({
|
|
|
772
776
|
return {
|
|
773
777
|
callId: call.id,
|
|
774
778
|
content: JSON.stringify(blockedPayload),
|
|
775
|
-
blocked: true
|
|
779
|
+
blocked: true,
|
|
780
|
+
summary: 'Tool call requires approval',
|
|
781
|
+
status: 'blocked'
|
|
776
782
|
};
|
|
777
783
|
}
|
|
778
784
|
|
|
779
785
|
if (onEvent) onEvent({ type: 'tool:start', name: displayName, id: call.id, arguments: effectiveArgs });
|
|
780
786
|
const handler = toolHandlers[toolName];
|
|
781
787
|
if (!handler) {
|
|
782
|
-
|
|
788
|
+
const available = Object.keys(toolHandlers).join(', ');
|
|
789
|
+
const msg = `Unknown tool: "${toolName}". Available tools: ${available || '(none)'}`;
|
|
790
|
+
const summary = trimInline(msg, 200);
|
|
791
|
+
if (onEvent) {
|
|
792
|
+
onEvent({ type: 'tool:error', name: displayName, id: call.id, arguments: effectiveArgs, durationMs: 0, summary });
|
|
793
|
+
}
|
|
794
|
+
return {
|
|
795
|
+
callId: call.id,
|
|
796
|
+
content: JSON.stringify({ error: msg }),
|
|
797
|
+
error: true,
|
|
798
|
+
durationMs: 0,
|
|
799
|
+
summary,
|
|
800
|
+
status: 'error'
|
|
801
|
+
};
|
|
783
802
|
}
|
|
784
803
|
|
|
785
804
|
const blockedReason = blockedExplorationReason(toolName, effectiveArgs, analysisGuard);
|
|
786
805
|
if (blockedReason) {
|
|
787
806
|
analysisGuard.blockedExplorations += 1;
|
|
788
807
|
const content = clipToolResult({ error: blockedReason }, toolResultMaxChars);
|
|
808
|
+
const summary = trimInline(blockedReason, 120);
|
|
789
809
|
if (onEvent) {
|
|
790
|
-
onEvent({ type: 'tool:error', name: displayName, id: call.id, arguments: effectiveArgs, durationMs: 0, summary
|
|
810
|
+
onEvent({ type: 'tool:error', name: displayName, id: call.id, arguments: effectiveArgs, durationMs: 0, summary });
|
|
791
811
|
}
|
|
792
812
|
return {
|
|
793
813
|
callId: call.id,
|
|
794
814
|
content,
|
|
795
|
-
error: true
|
|
815
|
+
error: true,
|
|
816
|
+
durationMs: 0,
|
|
817
|
+
summary,
|
|
818
|
+
status: 'error'
|
|
796
819
|
};
|
|
797
820
|
}
|
|
798
821
|
|
|
@@ -802,8 +825,9 @@ export async function runAgentLoop({
|
|
|
802
825
|
} catch (error) {
|
|
803
826
|
const durationMs = Date.now() - startedAt;
|
|
804
827
|
const message = error instanceof Error ? error.message : String(error);
|
|
828
|
+
const summary = trimInline(message, 120);
|
|
805
829
|
if (onEvent) {
|
|
806
|
-
onEvent({ type: 'tool:error', name: displayName, id: call.id, arguments: effectiveArgs, durationMs, summary
|
|
830
|
+
onEvent({ type: 'tool:error', name: displayName, id: call.id, arguments: effectiveArgs, durationMs, summary });
|
|
807
831
|
}
|
|
808
832
|
if (isAutoCaptureEnabled(config) && shouldAutoCaptureError(toolName, message)) {
|
|
809
833
|
await captureToolFailure(toolName, message, effectiveArgs, config).catch(() => {});
|
|
@@ -811,15 +835,19 @@ export async function runAgentLoop({
|
|
|
811
835
|
return {
|
|
812
836
|
callId: call.id,
|
|
813
837
|
content: clipToolResult({ error: message }, toolResultMaxChars),
|
|
814
|
-
error: true
|
|
838
|
+
error: true,
|
|
839
|
+
durationMs,
|
|
840
|
+
summary,
|
|
841
|
+
status: 'error'
|
|
815
842
|
};
|
|
816
843
|
}
|
|
817
844
|
|
|
818
845
|
const durationMs = Date.now() - startedAt;
|
|
846
|
+
const summary = summarizeToolResult(toolResult);
|
|
819
847
|
/* 提取文件改动统计 */
|
|
820
848
|
const fileChange = extractFileChange(toolName, toolResult);
|
|
821
849
|
if (onEvent) {
|
|
822
|
-
onEvent({ type: 'tool:end', name: displayName, id: call.id, arguments: effectiveArgs, durationMs, summary
|
|
850
|
+
onEvent({ type: 'tool:end', name: displayName, id: call.id, arguments: effectiveArgs, durationMs, summary, fileChange });
|
|
823
851
|
}
|
|
824
852
|
|
|
825
853
|
// Auto-capture non-throwing tool failures (e.g. shell non-zero exit)
|
|
@@ -857,7 +885,7 @@ export async function runAgentLoop({
|
|
|
857
885
|
// P0: Persist to disk if still large
|
|
858
886
|
formatted = await storeResultIfNeeded(call.id, formatted, toolResult);
|
|
859
887
|
|
|
860
|
-
return { callId: call.id, content: formatted };
|
|
888
|
+
return { callId: call.id, content: formatted, durationMs, summary, status: 'done' };
|
|
861
889
|
}
|
|
862
890
|
|
|
863
891
|
// Separate read-only and write calls, preserving order
|
|
@@ -884,7 +912,8 @@ export async function runAgentLoop({
|
|
|
884
912
|
if (!entry) continue;
|
|
885
913
|
|
|
886
914
|
if (entry.blocked) {
|
|
887
|
-
|
|
915
|
+
attachToolCallSessionMeta(assistantMessage, call.id, { summary: entry.summary || '', status: entry.status || 'blocked' });
|
|
916
|
+
messages.push({ role: 'tool', tool_call_id: call.id, content: entry.content, tool_summary: entry.summary || '', tool_status: entry.status || 'blocked' });
|
|
888
917
|
if (onEvent) {
|
|
889
918
|
onEvent({ type: 'tool:result', name: displayName, id: call.id, arguments: args, content: entry.content, blocked: true });
|
|
890
919
|
}
|
|
@@ -892,14 +921,16 @@ export async function runAgentLoop({
|
|
|
892
921
|
}
|
|
893
922
|
|
|
894
923
|
if (entry.error) {
|
|
895
|
-
|
|
924
|
+
attachToolCallSessionMeta(assistantMessage, call.id, { durationMs: entry.durationMs, summary: entry.summary || '', status: entry.status || 'error' });
|
|
925
|
+
messages.push({ role: 'tool', tool_call_id: call.id, content: entry.content, tool_duration_ms: entry.durationMs, tool_summary: entry.summary || '', tool_status: entry.status || 'error' });
|
|
896
926
|
if (onEvent) {
|
|
897
927
|
onEvent({ type: 'tool:result', name: displayName, id: call.id, arguments: args, content: entry.content, error: true });
|
|
898
928
|
}
|
|
899
929
|
continue;
|
|
900
930
|
}
|
|
901
931
|
|
|
902
|
-
|
|
932
|
+
attachToolCallSessionMeta(assistantMessage, call.id, { durationMs: entry.durationMs, summary: entry.summary || '', status: entry.status || 'done' });
|
|
933
|
+
messages.push({ role: 'tool', tool_call_id: call.id, content: entry.content, tool_duration_ms: entry.durationMs, tool_summary: entry.summary || '', tool_status: entry.status || 'done' });
|
|
903
934
|
if (onEvent) {
|
|
904
935
|
onEvent({ type: 'tool:result', name: displayName, id: call.id, arguments: args, content: entry.content });
|
|
905
936
|
}
|
|
@@ -934,3 +965,12 @@ function callsToPlanSummary(toolCalls = []) {
|
|
|
934
965
|
return `- ${formatToolDisplayName(normalizeToolCallName(call?.name), args)}`;
|
|
935
966
|
});
|
|
936
967
|
}
|
|
968
|
+
|
|
969
|
+
function attachToolCallSessionMeta(assistantMessage, callId, meta = {}) {
|
|
970
|
+
if (!assistantMessage || !Array.isArray(assistantMessage.tool_calls)) return;
|
|
971
|
+
const call = assistantMessage.tool_calls.find((tc) => String(tc?.id || '') === String(callId || ''));
|
|
972
|
+
if (!call) return;
|
|
973
|
+
if (Number.isFinite(Number(meta.durationMs))) call.durationMs = Number(meta.durationMs);
|
|
974
|
+
if (typeof meta.summary === 'string' && meta.summary.trim()) call.summary = meta.summary.trim();
|
|
975
|
+
if (typeof meta.status === 'string' && meta.status.trim()) call.status = meta.status.trim();
|
|
976
|
+
}
|