codemini-cli 0.5.10 → 0.5.12

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.
Files changed (59) hide show
  1. package/OPERATIONS.md +242 -242
  2. package/README.md +588 -588
  3. package/codemini-web/dist/assets/{highlighted-body-OFNGDK62-7HL7yft8.js → highlighted-body-OFNGDK62-B-G99D0A.js} +1 -1
  4. package/codemini-web/dist/assets/{index-BK75hMb2.js → index-DIGUEzan.js} +108 -108
  5. package/codemini-web/dist/assets/index-Dkq1DdDX.css +2 -0
  6. package/codemini-web/dist/assets/mermaid-GHXKKRXX-va2Kl89u.js +1 -0
  7. package/codemini-web/dist/index.html +35 -23
  8. package/codemini-web/lib/approval-manager.js +32 -32
  9. package/codemini-web/lib/runtime-bridge.js +17 -11
  10. package/codemini-web/server.js +534 -205
  11. package/deployment.md +212 -212
  12. package/package.json +2 -2
  13. package/skills/brainstorm/SKILL.md +77 -77
  14. package/skills/codemini.skills.json +40 -40
  15. package/skills/grill-me/SKILL.md +30 -30
  16. package/skills/superpowers-lite/SKILL.md +82 -82
  17. package/src/cli.js +74 -74
  18. package/src/commands/chat.js +210 -210
  19. package/src/commands/run.js +313 -313
  20. package/src/commands/skill.js +438 -304
  21. package/src/commands/web.js +57 -57
  22. package/src/core/agent-loop.js +980 -980
  23. package/src/core/ast.js +309 -307
  24. package/src/core/chat-runtime.js +6261 -6253
  25. package/src/core/command-evaluator.js +72 -72
  26. package/src/core/command-loader.js +311 -311
  27. package/src/core/command-policy.js +301 -301
  28. package/src/core/command-risk.js +156 -156
  29. package/src/core/config-store.js +286 -285
  30. package/src/core/constants.js +18 -1
  31. package/src/core/context-compact.js +365 -365
  32. package/src/core/default-system-prompt.js +114 -107
  33. package/src/core/dream-audit.js +105 -105
  34. package/src/core/dream-consolidate.js +229 -229
  35. package/src/core/dream-evaluator.js +185 -185
  36. package/src/core/fff-adapter.js +383 -383
  37. package/src/core/memory-store.js +543 -543
  38. package/src/core/project-index.js +737 -548
  39. package/src/core/project-instructions.js +98 -98
  40. package/src/core/provider/anthropic.js +514 -514
  41. package/src/core/provider/openai-compatible.js +501 -501
  42. package/src/core/reflect-skill.js +178 -178
  43. package/src/core/reply-language.js +40 -40
  44. package/src/core/session-store.js +474 -474
  45. package/src/core/shell-profile.js +237 -237
  46. package/src/core/shell.js +323 -323
  47. package/src/core/soul.js +69 -69
  48. package/src/core/system-prompt-composer.js +52 -52
  49. package/src/core/tool-args.js +199 -154
  50. package/src/core/tool-output.js +184 -184
  51. package/src/core/tool-result-store.js +206 -206
  52. package/src/core/tools.js +3024 -2893
  53. package/src/core/version.js +11 -11
  54. package/src/tui/chat-app.js +5173 -5171
  55. package/src/tui/tool-activity/presenters/misc.js +30 -30
  56. package/src/tui/tool-activity/presenters/system.js +20 -20
  57. package/templates/project-requirements/report-shell.html +582 -582
  58. package/codemini-web/dist/assets/index-BSdIdn3L.css +0 -2
  59. package/codemini-web/dist/assets/mermaid-GHXKKRXX-Dg9qh8mg.js +0 -1
@@ -1,110 +1,117 @@
1
- import os from 'node:os';
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import { getShellSystemPrompt } from './shell-profile.js';
5
-
6
- function formatToolPath(...segments) {
7
- return JSON.stringify(path.join(process.cwd(), ...segments));
8
- }
9
-
10
- function getToolFewShotBlock() {
11
- const cwd = process.cwd();
12
- const authServicePath = formatToolPath('src', 'auth', 'service.ts');
13
- const reducerRangePath = JSON.stringify(`${path.join(cwd, 'src', 'store', 'reducer.ts')}:110-150`);
14
- const notesPath = formatToolPath('notes.txt');
15
- return `# Tool Examples
16
-
17
- Use these as style examples for tool calls:
18
-
19
- Current working directory: ${cwd}
20
- When a tool takes path, build it from the current working directory and prefer absolute paths.
21
- If the user mentions a project-relative path like src/app.ts, resolve it from ${cwd} instead of guessing parent directories.
22
-
23
- 1. File discovery then read
24
- User: compare the auth flow
25
- Assistant: first narrow the search with the project index
26
- Tool: query_project_index({"query":"auth flow","path":"src","max_results":3})
27
- Tool: read({"path":${authServicePath}})
28
-
29
- If the visible tool list does not include a needed capability, load it with tool_search instead of assuming it does not exist.
30
- Example:
31
- Tool: tool_search({"query":"glob"})
32
- Tool: glob({"pattern":"src/**/*.ts"})
33
-
34
- 2. Targeted search then exact text edit
35
- User: rename loginUser to signInUser
36
- Assistant: first find the exact occurrences
37
- Tool: grep({"pattern":"loginUser","path":"src"})
38
- Tool: edit({"path":${authServicePath},"old_text":"loginUser","new_text":"signInUser"})
39
-
40
- 3. Read a specific range
41
- User: inspect the reducer around line 120
42
- Assistant: read only the needed range
43
- Tool: read({"path":${reducerRangePath}})
44
-
45
- 4. Track a complex task with todos
46
- User: update the login flow and verify it
47
- Assistant: create a focused todo checklist before starting
48
- Tool: update_todos({"todos":[{"content":"Inspect the current login flow","activeForm":"Inspecting the current login flow","status":"in_progress"},{"content":"Implement the requested login changes","activeForm":"Implementing the requested login changes","status":"pending"},{"content":"Run focused verification for the login flow","activeForm":"Running focused verification for the login flow","status":"pending"}]})
49
- Assistant: keep the checklist updated as each phase finishes, and do not give a completion-style wrap-up until the checklist is complete or a blocker is recorded
50
-
51
- 5. Create a new file
52
- User: add a notes file
53
- Assistant: create the file directly
54
- Tool: write({"path":${notesPath},"content":"todo\\n"})
55
-
56
- 6. Save a high-signal observation to memory
57
- When you notice a reusable pattern, a user correction, a repeated failure, or a stable preference — save it to persistent memory. Choose scope carefully:
58
- - scope "user" for personal preferences (language, reply style, interaction habits)
59
- - scope "global" for cross-project lessons (environment quirks, general tool workflows)
60
- - scope "project" for project-specific knowledge (architecture conventions, local config, test commands, file locations)
61
-
62
- Examples:
63
- Tool: save_memory({"content":"User prefers tab size 2 for all JSON files","scope":"user","kind":"preference"})
64
- Tool: save_memory({"content":"This project uses vitest, not jest — run tests with npx vitest run","scope":"project","kind":"pattern"})
65
- Tool: save_memory({"content":"WSL2 bash exec prefix does not support cd as a command","scope":"global","kind":"correction"})
66
-
67
- 7. Run a dream loop consolidation pass
68
- When you want to review and consolidate inbox entries into long-term memory.
69
- Tool: dream_consolidate({})
70
-
71
- 8. Read a live web page by URL
72
- User: summarize https://example.com/docs
73
- Assistant: load the web fetch tool and read the page directly
74
- Tool: tool_search({"query":"web_fetch"})
75
- Tool: web_fetch({"url":"https://example.com/docs"})
76
-
77
- 9. Search the web
78
- User: search the web for latest pnpm release
79
- Assistant: load the web search tool and run a targeted search
80
- Tool: tool_search({"query":"web_search"})
81
- Tool: web_search({"query":"latest pnpm release","max_results":5})
82
-
83
- Prefer these direct tool shapes over multi-step metadata reads or shell fallbacks.
84
- Prefer explicit absolute path values when the current working directory is known.`;
1
+ import os from 'node:os';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { getShellSystemPrompt } from './shell-profile.js';
5
+
6
+ function formatToolPath(...segments) {
7
+ return JSON.stringify(path.join(process.cwd(), ...segments));
8
+ }
9
+
10
+ function getToolFewShotBlock() {
11
+ const cwd = process.cwd();
12
+ const authServicePath = formatToolPath('src', 'auth', 'service.ts');
13
+ const reducerRangePath = JSON.stringify(`${path.join(cwd, 'src', 'store', 'reducer.ts')}:110-150`);
14
+ const notesPath = formatToolPath('notes.txt');
15
+ return `# Tool Examples
16
+
17
+ Use these as style examples for tool calls:
18
+
19
+ Current working directory: ${cwd}
20
+ When a tool takes path, build it from the current working directory and prefer absolute paths.
21
+ If the user mentions a project-relative path like src/app.ts, resolve it from ${cwd} instead of guessing parent directories.
22
+
23
+ 1. File discovery then read
24
+ User: compare the auth flow
25
+ Assistant: first narrow the search with the project index
26
+ Tool: query_project_index({"query":"auth flow","path":"src","max_results":3})
27
+ Tool: read({"path":${authServicePath}})
28
+
29
+ If the visible tool list does not include a needed capability, load it with tool_search instead of assuming it does not exist.
30
+ Example:
31
+ Tool: tool_search({"query":"glob"})
32
+ Tool: glob({"pattern":"src/**/*.ts"})
33
+
34
+ 2. Targeted search then exact text edit
35
+ User: rename loginUser to signInUser
36
+ Assistant: first find the exact occurrences
37
+ Tool: grep({"pattern":"loginUser","path":"src"})
38
+ Tool: edit({"path":${authServicePath},"old_text":"loginUser","new_text":"signInUser"})
39
+
40
+ 3. Read a specific range
41
+ User: inspect the reducer around line 120
42
+ Assistant: read only the needed range
43
+ Tool: read({"path":${reducerRangePath}})
44
+
45
+ 4. Track a complex task with todos
46
+ User: update the login flow and verify it
47
+ Assistant: create a focused todo checklist before starting
48
+ Tool: update_todos({"todos":[{"content":"Inspect the current login flow","activeForm":"Inspecting the current login flow","status":"in_progress"},{"content":"Implement the requested login changes","activeForm":"Implementing the requested login changes","status":"pending"},{"content":"Run focused verification for the login flow","activeForm":"Running focused verification for the login flow","status":"pending"}]})
49
+ Assistant: keep the checklist updated as each phase finishes, and do not give a completion-style wrap-up until the checklist is complete or a blocker is recorded
50
+
51
+ 5. Create a new file
52
+ User: add a notes file
53
+ Assistant: create the file directly
54
+ Tool: write({"path":${notesPath},"content":"todo\\n"})
55
+
56
+ 6. Save a high-signal observation to memory
57
+ When you notice a reusable pattern, a user correction, a repeated failure, or a stable preference — save it to persistent memory. Choose scope carefully:
58
+ - scope "user" for personal preferences (language, reply style, interaction habits)
59
+ - scope "global" for cross-project lessons (environment quirks, general tool workflows)
60
+ - scope "project" for project-specific knowledge (architecture conventions, local config, test commands, file locations)
61
+
62
+ Examples:
63
+ Tool: save_memory({"content":"User prefers tab size 2 for all JSON files","scope":"user","kind":"preference"})
64
+ Tool: save_memory({"content":"This project uses vitest, not jest — run tests with npx vitest run","scope":"project","kind":"pattern"})
65
+ Tool: save_memory({"content":"WSL2 bash exec prefix does not support cd as a command","scope":"global","kind":"correction"})
66
+
67
+ 7. Run a dream loop consolidation pass
68
+ When you want to review and consolidate inbox entries into long-term memory.
69
+ Tool: dream_consolidate({})
70
+
71
+ 8. Read a live web page by URL
72
+ User: summarize https://example.com/docs
73
+ Assistant: load the web fetch tool and read the page directly
74
+ Tool: tool_search({"query":"web_fetch"})
75
+ Tool: web_fetch({"url":"https://example.com/docs"})
76
+
77
+ 9. Search the web
78
+ User: search the web for latest pnpm release
79
+ Assistant: load the web search tool and run a targeted search
80
+ Tool: tool_search({"query":"web_search"})
81
+ Tool: web_search({"query":"latest pnpm release","max_results":5})
82
+
83
+ Prefer these direct tool shapes over multi-step metadata reads or shell fallbacks.
84
+ Prefer explicit absolute path values when the current working directory is known.`;
85
+ }
86
+
87
+ function getEnvBlock() {
88
+ const cwd = process.cwd();
89
+ let isGitRepo = false;
90
+ try {
91
+ fs.accessSync(`${cwd}/.git`);
92
+ isGitRepo = true;
93
+ } catch {}
94
+
95
+ return `<env>
96
+ Working directory: ${cwd}
97
+ Is directory a git repo: ${isGitRepo ? 'Yes' : 'No'}
98
+ Platform: ${process.platform}
99
+ Shell: ${os.userInfo().shell || 'unknown'}
100
+ OS Version: ${os.version || os.release()}
101
+ </env>`;
102
+ }
103
+
104
+ function normalizePromptBlocks(blocks) {
105
+ if (!blocks) return [];
106
+ if (Array.isArray(blocks)) return blocks.filter(Boolean).map(String);
107
+ return [String(blocks)].filter(Boolean);
85
108
  }
86
109
 
87
- function getEnvBlock() {
88
- const cwd = process.cwd();
89
- let isGitRepo = false;
90
- try {
91
- fs.accessSync(`${cwd}/.git`);
92
- isGitRepo = true;
93
- } catch {}
94
-
95
- return `<env>
96
- Working directory: ${cwd}
97
- Is directory a git repo: ${isGitRepo ? 'Yes' : 'No'}
98
- Platform: ${process.platform}
99
- Shell: ${os.userInfo().shell || 'unknown'}
100
- OS Version: ${os.version || os.release()}
101
- </env>`;
102
- }
103
-
104
- export function buildDefaultSystemPrompt(config = {}) {
105
- return `${getShellSystemPrompt(config?.shell?.default)}
106
-
107
- ${getToolFewShotBlock()}
108
-
109
- ${getEnvBlock()}`;
110
+ export function buildDefaultSystemPrompt(config = {}, options = {}) {
111
+ return [
112
+ getShellSystemPrompt(config?.shell?.default),
113
+ getToolFewShotBlock(),
114
+ getEnvBlock(),
115
+ ...normalizePromptBlocks(options.extraPrompts)
116
+ ].filter(Boolean).join('\n\n');
110
117
  }
@@ -1,105 +1,105 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { getDreamAuditDir } from './paths.js';
4
-
5
- function nowStamp() {
6
- return new Date().toISOString().replace(/[:.]/g, '-');
7
- }
8
-
9
- function renderReport(report) {
10
- const lines = [
11
- `# Dream Consolidation Report`,
12
- `Date: ${report.timestamp}`,
13
- ``
14
- ];
15
-
16
- if (report.filesRead?.length) {
17
- lines.push('## Files Read');
18
- for (const f of report.filesRead) lines.push(`- ${f}`);
19
- lines.push('');
20
- }
21
-
22
- if (report.candidatesGenerated) {
23
- lines.push(`## Candidates Generated: ${report.candidatesGenerated}`);
24
- lines.push('');
25
- }
26
-
27
- if (report.promotions?.length) {
28
- lines.push('## Promotions');
29
- for (const p of report.promotions) {
30
- lines.push(`- [${p.lifecycle}] ${p.summary} (scope: ${p.scope})`);
31
- if (p.rationale) lines.push(` Rationale: ${p.rationale}`);
32
- }
33
- lines.push('');
34
- }
35
-
36
- if (report.rejections?.length) {
37
- lines.push('## Rejections');
38
- for (const r of report.rejections) {
39
- lines.push(`- ${r.summary}`);
40
- if (r.reason) lines.push(` Reason: ${r.reason}`);
41
- }
42
- lines.push('');
43
- }
44
-
45
- if (report.archives?.length) {
46
- lines.push('## Archives');
47
- for (const a of report.archives) {
48
- lines.push(`- ${a.summary} (reason: ${a.reason || 'expired'})`);
49
- }
50
- lines.push('');
51
- }
52
-
53
- if (report.filesChanged?.length) {
54
- lines.push('## Files Changed');
55
- for (const fc of report.filesChanged) lines.push(`- ${fc.file}: ${fc.why}`);
56
- lines.push('');
57
- }
58
-
59
- if (report.maintenance?.length) {
60
- lines.push('## Memory Maintenance');
61
- for (const item of report.maintenance) {
62
- if (item.skipped) {
63
- lines.push(`- [${item.scope}] skipped: ${item.reason}`);
64
- } else {
65
- lines.push(`- [${item.scope}] ${item.before} -> ${item.after} item(s)${item.changed ? ' changed' : ' marked clean'}`);
66
- }
67
- }
68
- lines.push('');
69
- }
70
-
71
- if (report.disagreements?.length) {
72
- lines.push('## Reviewer Disagreements');
73
- for (const d of report.disagreements) {
74
- lines.push(`- ${d.item}: main=${d.mainVerdict}, reviewer=${d.reviewerVerdict}, resolved=${d.resolution}`);
75
- }
76
- lines.push('');
77
- }
78
-
79
- return lines.join('\n');
80
- }
81
-
82
- export async function writeDreamAuditReport(report) {
83
- const dir = getDreamAuditDir();
84
- await fs.mkdir(dir, { recursive: true });
85
- const stamp = nowStamp();
86
- const filePath = path.join(dir, `dream-${stamp}.md`);
87
- const content = renderReport(report);
88
- await fs.writeFile(filePath, content, 'utf8');
89
- return filePath;
90
- }
91
-
92
- export async function listDreamAuditReports() {
93
- const dir = getDreamAuditDir();
94
- let entries;
95
- try {
96
- entries = await fs.readdir(dir);
97
- } catch {
98
- return [];
99
- }
100
- return entries
101
- .filter((e) => e.startsWith('dream-') && e.endsWith('.md'))
102
- .sort()
103
- .reverse()
104
- .map((e) => path.join(dir, e));
105
- }
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { getDreamAuditDir } from './paths.js';
4
+
5
+ function nowStamp() {
6
+ return new Date().toISOString().replace(/[:.]/g, '-');
7
+ }
8
+
9
+ function renderReport(report) {
10
+ const lines = [
11
+ `# Dream Consolidation Report`,
12
+ `Date: ${report.timestamp}`,
13
+ ``
14
+ ];
15
+
16
+ if (report.filesRead?.length) {
17
+ lines.push('## Files Read');
18
+ for (const f of report.filesRead) lines.push(`- ${f}`);
19
+ lines.push('');
20
+ }
21
+
22
+ if (report.candidatesGenerated) {
23
+ lines.push(`## Candidates Generated: ${report.candidatesGenerated}`);
24
+ lines.push('');
25
+ }
26
+
27
+ if (report.promotions?.length) {
28
+ lines.push('## Promotions');
29
+ for (const p of report.promotions) {
30
+ lines.push(`- [${p.lifecycle}] ${p.summary} (scope: ${p.scope})`);
31
+ if (p.rationale) lines.push(` Rationale: ${p.rationale}`);
32
+ }
33
+ lines.push('');
34
+ }
35
+
36
+ if (report.rejections?.length) {
37
+ lines.push('## Rejections');
38
+ for (const r of report.rejections) {
39
+ lines.push(`- ${r.summary}`);
40
+ if (r.reason) lines.push(` Reason: ${r.reason}`);
41
+ }
42
+ lines.push('');
43
+ }
44
+
45
+ if (report.archives?.length) {
46
+ lines.push('## Archives');
47
+ for (const a of report.archives) {
48
+ lines.push(`- ${a.summary} (reason: ${a.reason || 'expired'})`);
49
+ }
50
+ lines.push('');
51
+ }
52
+
53
+ if (report.filesChanged?.length) {
54
+ lines.push('## Files Changed');
55
+ for (const fc of report.filesChanged) lines.push(`- ${fc.file}: ${fc.why}`);
56
+ lines.push('');
57
+ }
58
+
59
+ if (report.maintenance?.length) {
60
+ lines.push('## Memory Maintenance');
61
+ for (const item of report.maintenance) {
62
+ if (item.skipped) {
63
+ lines.push(`- [${item.scope}] skipped: ${item.reason}`);
64
+ } else {
65
+ lines.push(`- [${item.scope}] ${item.before} -> ${item.after} item(s)${item.changed ? ' changed' : ' marked clean'}`);
66
+ }
67
+ }
68
+ lines.push('');
69
+ }
70
+
71
+ if (report.disagreements?.length) {
72
+ lines.push('## Reviewer Disagreements');
73
+ for (const d of report.disagreements) {
74
+ lines.push(`- ${d.item}: main=${d.mainVerdict}, reviewer=${d.reviewerVerdict}, resolved=${d.resolution}`);
75
+ }
76
+ lines.push('');
77
+ }
78
+
79
+ return lines.join('\n');
80
+ }
81
+
82
+ export async function writeDreamAuditReport(report) {
83
+ const dir = getDreamAuditDir();
84
+ await fs.mkdir(dir, { recursive: true });
85
+ const stamp = nowStamp();
86
+ const filePath = path.join(dir, `dream-${stamp}.md`);
87
+ const content = renderReport(report);
88
+ await fs.writeFile(filePath, content, 'utf8');
89
+ return filePath;
90
+ }
91
+
92
+ export async function listDreamAuditReports() {
93
+ const dir = getDreamAuditDir();
94
+ let entries;
95
+ try {
96
+ entries = await fs.readdir(dir);
97
+ } catch {
98
+ return [];
99
+ }
100
+ return entries
101
+ .filter((e) => e.startsWith('dream-') && e.endsWith('.md'))
102
+ .sort()
103
+ .reverse()
104
+ .map((e) => path.join(dir, e));
105
+ }