codemini-cli 0.4.7 → 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 +45 -14
- package/src/core/chat-runtime.js +601 -81
- 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,7 +776,9 @@ 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
|
|
|
@@ -781,13 +787,17 @@ export async function runAgentLoop({
|
|
|
781
787
|
if (!handler) {
|
|
782
788
|
const available = Object.keys(toolHandlers).join(', ');
|
|
783
789
|
const msg = `Unknown tool: "${toolName}". Available tools: ${available || '(none)'}`;
|
|
790
|
+
const summary = trimInline(msg, 200);
|
|
784
791
|
if (onEvent) {
|
|
785
|
-
onEvent({ type: 'tool:error', name: displayName, id: call.id, arguments: effectiveArgs, durationMs: 0, summary
|
|
792
|
+
onEvent({ type: 'tool:error', name: displayName, id: call.id, arguments: effectiveArgs, durationMs: 0, summary });
|
|
786
793
|
}
|
|
787
794
|
return {
|
|
788
795
|
callId: call.id,
|
|
789
796
|
content: JSON.stringify({ error: msg }),
|
|
790
|
-
error: true
|
|
797
|
+
error: true,
|
|
798
|
+
durationMs: 0,
|
|
799
|
+
summary,
|
|
800
|
+
status: 'error'
|
|
791
801
|
};
|
|
792
802
|
}
|
|
793
803
|
|
|
@@ -795,13 +805,17 @@ export async function runAgentLoop({
|
|
|
795
805
|
if (blockedReason) {
|
|
796
806
|
analysisGuard.blockedExplorations += 1;
|
|
797
807
|
const content = clipToolResult({ error: blockedReason }, toolResultMaxChars);
|
|
808
|
+
const summary = trimInline(blockedReason, 120);
|
|
798
809
|
if (onEvent) {
|
|
799
|
-
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 });
|
|
800
811
|
}
|
|
801
812
|
return {
|
|
802
813
|
callId: call.id,
|
|
803
814
|
content,
|
|
804
|
-
error: true
|
|
815
|
+
error: true,
|
|
816
|
+
durationMs: 0,
|
|
817
|
+
summary,
|
|
818
|
+
status: 'error'
|
|
805
819
|
};
|
|
806
820
|
}
|
|
807
821
|
|
|
@@ -811,8 +825,9 @@ export async function runAgentLoop({
|
|
|
811
825
|
} catch (error) {
|
|
812
826
|
const durationMs = Date.now() - startedAt;
|
|
813
827
|
const message = error instanceof Error ? error.message : String(error);
|
|
828
|
+
const summary = trimInline(message, 120);
|
|
814
829
|
if (onEvent) {
|
|
815
|
-
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 });
|
|
816
831
|
}
|
|
817
832
|
if (isAutoCaptureEnabled(config) && shouldAutoCaptureError(toolName, message)) {
|
|
818
833
|
await captureToolFailure(toolName, message, effectiveArgs, config).catch(() => {});
|
|
@@ -820,15 +835,19 @@ export async function runAgentLoop({
|
|
|
820
835
|
return {
|
|
821
836
|
callId: call.id,
|
|
822
837
|
content: clipToolResult({ error: message }, toolResultMaxChars),
|
|
823
|
-
error: true
|
|
838
|
+
error: true,
|
|
839
|
+
durationMs,
|
|
840
|
+
summary,
|
|
841
|
+
status: 'error'
|
|
824
842
|
};
|
|
825
843
|
}
|
|
826
844
|
|
|
827
845
|
const durationMs = Date.now() - startedAt;
|
|
846
|
+
const summary = summarizeToolResult(toolResult);
|
|
828
847
|
/* 提取文件改动统计 */
|
|
829
848
|
const fileChange = extractFileChange(toolName, toolResult);
|
|
830
849
|
if (onEvent) {
|
|
831
|
-
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 });
|
|
832
851
|
}
|
|
833
852
|
|
|
834
853
|
// Auto-capture non-throwing tool failures (e.g. shell non-zero exit)
|
|
@@ -866,7 +885,7 @@ export async function runAgentLoop({
|
|
|
866
885
|
// P0: Persist to disk if still large
|
|
867
886
|
formatted = await storeResultIfNeeded(call.id, formatted, toolResult);
|
|
868
887
|
|
|
869
|
-
return { callId: call.id, content: formatted };
|
|
888
|
+
return { callId: call.id, content: formatted, durationMs, summary, status: 'done' };
|
|
870
889
|
}
|
|
871
890
|
|
|
872
891
|
// Separate read-only and write calls, preserving order
|
|
@@ -893,7 +912,8 @@ export async function runAgentLoop({
|
|
|
893
912
|
if (!entry) continue;
|
|
894
913
|
|
|
895
914
|
if (entry.blocked) {
|
|
896
|
-
|
|
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' });
|
|
897
917
|
if (onEvent) {
|
|
898
918
|
onEvent({ type: 'tool:result', name: displayName, id: call.id, arguments: args, content: entry.content, blocked: true });
|
|
899
919
|
}
|
|
@@ -901,14 +921,16 @@ export async function runAgentLoop({
|
|
|
901
921
|
}
|
|
902
922
|
|
|
903
923
|
if (entry.error) {
|
|
904
|
-
|
|
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' });
|
|
905
926
|
if (onEvent) {
|
|
906
927
|
onEvent({ type: 'tool:result', name: displayName, id: call.id, arguments: args, content: entry.content, error: true });
|
|
907
928
|
}
|
|
908
929
|
continue;
|
|
909
930
|
}
|
|
910
931
|
|
|
911
|
-
|
|
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' });
|
|
912
934
|
if (onEvent) {
|
|
913
935
|
onEvent({ type: 'tool:result', name: displayName, id: call.id, arguments: args, content: entry.content });
|
|
914
936
|
}
|
|
@@ -943,3 +965,12 @@ function callsToPlanSummary(toolCalls = []) {
|
|
|
943
965
|
return `- ${formatToolDisplayName(normalizeToolCallName(call?.name), args)}`;
|
|
944
966
|
});
|
|
945
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
|
+
}
|