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.
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-CANOG7Xg.js} +1 -1
  4. package/codemini-web/dist/assets/{index-BK75hMb2.js → index-B71xykPM.js} +108 -108
  5. package/codemini-web/dist/assets/index-Dkq1DdDX.css +2 -0
  6. package/codemini-web/dist/assets/mermaid-GHXKKRXX-Z_w7M93P.js +1 -0
  7. package/codemini-web/dist/index.html +23 -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 +1 -1
  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 +289 -289
  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 +5171 -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,229 +1,229 @@
1
- import {
2
- getMemoryBucketMaintenance,
3
- listMemories,
4
- listInbox,
5
- archiveEntry,
6
- promoteMemory,
7
- replaceMemoryBucket
8
- } from './memory-store.js';
9
- import { writeDreamAuditReport } from './dream-audit.js';
10
- import { evaluateInboxBatch, evaluateMemoryMaintenance } from './dream-evaluator.js';
11
-
12
- const LONGTERM_TYPES = new Set(['preference', 'pattern', 'win', 'decision']);
13
- const OPERATIONAL_TYPES = new Set(['correction', 'failure', 'gap', 'observation']);
14
-
15
- function normalizeText(value) {
16
- return String(value || '').trim().toLowerCase();
17
- }
18
-
19
- function chooseLifecycle(type) {
20
- const value = normalizeText(type);
21
- if (LONGTERM_TYPES.has(value)) return 'longterm';
22
- if (OPERATIONAL_TYPES.has(value)) return 'operational';
23
- return 'operational';
24
- }
25
-
26
- function memoryContainsSummary(memory, summaryKey) {
27
- const content = normalizeText(memory?.content);
28
- const summary = normalizeText(memory?.summary);
29
- return content.includes(summaryKey) || summary.includes(summaryKey);
30
- }
31
-
32
- function maintenanceScopes(scopeFilter) {
33
- const scope = normalizeText(scopeFilter);
34
- if (!scope) return ['user', 'global', 'project'];
35
- if (scope === 'repo') return ['project'];
36
- if (['user', 'global', 'project'].includes(scope)) return [scope];
37
- return ['user', 'global', 'project'];
38
- }
39
-
40
- async function runMemoryMaintenance({
41
- dryRun = false,
42
- scope = null,
43
- workspaceRoot = process.cwd(),
44
- config = {}
45
- } = {}) {
46
- const reports = [];
47
- const filesChanged = [];
48
-
49
- for (const memoryScope of maintenanceScopes(scope)) {
50
- const maintenance = await getMemoryBucketMaintenance({ scope: memoryScope, workspaceRoot });
51
- const items = await listMemories({ scope: memoryScope, workspaceRoot });
52
- if (items.length === 0) {
53
- reports.push({ scope: memoryScope, skipped: true, reason: 'empty' });
54
- continue;
55
- }
56
- if (maintenance.fresh) {
57
- reports.push({ scope: memoryScope, skipped: true, reason: 'already-maintained', itemCount: items.length });
58
- continue;
59
- }
60
-
61
- const evaluated = dryRun
62
- ? { items, archives: [] }
63
- : await evaluateMemoryMaintenance({ scope: memoryScope, items, config, workspaceRoot });
64
- if (evaluated.error) {
65
- reports.push({ scope: memoryScope, skipped: true, reason: `maintenance-error: ${evaluated.error}`, itemCount: items.length });
66
- continue;
67
- }
68
- const nextItems = Array.isArray(evaluated.items) && evaluated.items.length > 0 ? evaluated.items : items;
69
- const changed =
70
- JSON.stringify(nextItems.map((item) => [item.kind, item.content, item.summary, item.lifecycle || ''])) !==
71
- JSON.stringify(items.map((item) => [item.kind, item.content, item.summary, item.lifecycle || '']));
72
-
73
- if (!dryRun) {
74
- await replaceMemoryBucket({
75
- scope: memoryScope,
76
- items: nextItems,
77
- workspaceRoot,
78
- markMaintained: true
79
- });
80
- filesChanged.push({
81
- file: memoryScope === 'project' ? 'memory/project/*.json' : `memory/${memoryScope}.json`,
82
- why: changed
83
- ? `LLM-maintained ${items.length} item(s) into ${nextItems.length} item(s)`
84
- : `Marked ${items.length} item(s) as maintained`
85
- });
86
- }
87
-
88
- reports.push({
89
- scope: memoryScope,
90
- skipped: false,
91
- before: items.length,
92
- after: nextItems.length,
93
- changed,
94
- archives: evaluated.archives || [],
95
- dryRun
96
- });
97
- }
98
-
99
- return { reports, filesChanged };
100
- }
101
-
102
- export async function runDreamConsolidation({
103
- dryRun = false,
104
- scope = null,
105
- workspaceRoot = process.cwd(),
106
- config = {},
107
- writeAudit = true
108
- } = {}) {
109
- const scopeFilter = scope || null;
110
- const inbox = await listInbox({ scope: scopeFilter });
111
-
112
- const [globalMemories, userMemories, projectMemories] = await Promise.all([
113
- listMemories({ scope: 'global', workspaceRoot }),
114
- listMemories({ scope: 'user', workspaceRoot }),
115
- listMemories({ scope: 'project', workspaceRoot })
116
- ]);
117
- const knownMemories = [...globalMemories, ...userMemories, ...projectMemories];
118
-
119
- const promotions = [];
120
- const rejections = [];
121
- const archives = [];
122
- const filesRead = ['memory/inbox/*', 'memory/global.json', 'memory/user.json', 'memory/project/*.json'];
123
- const filesChanged = [];
124
-
125
- /* ── Phase 1: 规则预过滤(快速剔除明显垃圾) ─────────────────── */
126
- const candidates = [];
127
- const seen = new Map();
128
-
129
- for (const entry of inbox) {
130
- const summaryKey = normalizeText(entry.summary);
131
- if (!summaryKey) {
132
- if (!dryRun) await archiveEntry(entry, 'invalid-summary', 'Summary is empty after normalization');
133
- archives.push({ summary: String(entry.summary || ''), reason: 'invalid-summary' });
134
- continue;
135
- }
136
-
137
- if (seen.has(summaryKey)) {
138
- if (!dryRun) await archiveEntry(entry, 'duplicate', `Duplicate of ${seen.get(summaryKey)}`);
139
- archives.push({ summary: entry.summary, reason: 'duplicate' });
140
- continue;
141
- }
142
- seen.set(summaryKey, entry.id);
143
-
144
- const alreadyKnown = knownMemories.some((memory) => memoryContainsSummary(memory, summaryKey));
145
- if (alreadyKnown) {
146
- if (!dryRun) await archiveEntry(entry, 'already-known', 'Already present in memory');
147
- rejections.push({ summary: entry.summary, reason: 'already-known' });
148
- continue;
149
- }
150
-
151
- candidates.push(entry);
152
- }
153
-
154
- if (candidates.length > 0) {
155
- /* ── Phase 2: LLM 批量评估(质量门控 + scope 分类 + 内容提炼) ── */
156
- const llmResults = dryRun
157
- ? candidates.map((e) => ({ id: e.id, action: 'keep', scope: 'global', kind: e.type || 'observation', content: e.details || e.summary, summary: e.summary, confidence: 0.9 }))
158
- : await evaluateInboxBatch({ entries: candidates, config, workspaceRoot });
159
-
160
- const resultMap = new Map(llmResults.map((r) => [r.id, r]));
161
-
162
- /* ── Phase 3: 按评估结果 promote 或 archive ─────────────────── */
163
- for (const entry of candidates) {
164
- const evaluation = resultMap.get(entry.id);
165
-
166
- if (!evaluation || evaluation.action === 'discard') {
167
- const reason = evaluation?.reason || 'LLM discarded';
168
- if (!dryRun) await archiveEntry(entry, 'discarded-by-evaluator', reason);
169
- rejections.push({ summary: entry.summary, reason: `evaluator-discard: ${reason}` });
170
- continue;
171
- }
172
-
173
- const promoteScope = evaluation.scope || 'global';
174
- const lifecycle = chooseLifecycle(evaluation.kind);
175
- const enrichedEntry = {
176
- ...entry,
177
- /* 用 LLM 提炼后的内容覆盖原始报错 */
178
- summary: evaluation.summary || entry.summary,
179
- details: evaluation.content || entry.details || entry.summary,
180
- type: evaluation.kind || entry.type || 'observation'
181
- };
182
-
183
- if (!dryRun) {
184
- try {
185
- await promoteMemory({
186
- entry: enrichedEntry,
187
- scope: promoteScope,
188
- lifecycle,
189
- workspaceRoot,
190
- config,
191
- confidence: evaluation.confidence || 0.8
192
- });
193
- filesChanged.push({ file: `memory/${promoteScope}.json`, why: `Promoted "${enrichedEntry.summary}" as ${lifecycle} (${promoteScope})` });
194
- promotions.push({ summary: enrichedEntry.summary, scope: promoteScope, lifecycle, rationale: evaluation.kind, confidence: evaluation.confidence });
195
- } catch (error) {
196
- const reason = String(error?.message || error || 'promotion failed').slice(0, 180);
197
- await archiveEntry(entry, 'promotion-failed', reason);
198
- rejections.push({ summary: entry.summary, reason: `promotion-failed: ${reason}` });
199
- archives.push({ summary: entry.summary, reason: 'promotion-failed' });
200
- }
201
- continue;
202
- }
203
-
204
- promotions.push({ summary: enrichedEntry.summary, scope: promoteScope, lifecycle, rationale: evaluation.kind, confidence: evaluation.confidence, dryRun: true });
205
- }
206
- }
207
-
208
- const maintenance = await runMemoryMaintenance({ dryRun, scope: scopeFilter, workspaceRoot, config });
209
- filesChanged.push(...maintenance.filesChanged);
210
-
211
- const report = {
212
- timestamp: new Date().toISOString(),
213
- filesRead,
214
- filesChanged,
215
- candidatesGenerated: inbox.length,
216
- promotions,
217
- rejections,
218
- archives,
219
- maintenance: maintenance.reports,
220
- ...(inbox.length === 0 ? { message: 'No inbox entries to consolidate; maintained existing memory buckets.' } : {})
221
- };
222
-
223
- if (!dryRun && writeAudit) {
224
- const reportPath = await writeDreamAuditReport(report);
225
- report.auditReport = reportPath;
226
- }
227
-
228
- return { ok: true, dryRun, ...report };
229
- }
1
+ import {
2
+ getMemoryBucketMaintenance,
3
+ listMemories,
4
+ listInbox,
5
+ archiveEntry,
6
+ promoteMemory,
7
+ replaceMemoryBucket
8
+ } from './memory-store.js';
9
+ import { writeDreamAuditReport } from './dream-audit.js';
10
+ import { evaluateInboxBatch, evaluateMemoryMaintenance } from './dream-evaluator.js';
11
+
12
+ const LONGTERM_TYPES = new Set(['preference', 'pattern', 'win', 'decision']);
13
+ const OPERATIONAL_TYPES = new Set(['correction', 'failure', 'gap', 'observation']);
14
+
15
+ function normalizeText(value) {
16
+ return String(value || '').trim().toLowerCase();
17
+ }
18
+
19
+ function chooseLifecycle(type) {
20
+ const value = normalizeText(type);
21
+ if (LONGTERM_TYPES.has(value)) return 'longterm';
22
+ if (OPERATIONAL_TYPES.has(value)) return 'operational';
23
+ return 'operational';
24
+ }
25
+
26
+ function memoryContainsSummary(memory, summaryKey) {
27
+ const content = normalizeText(memory?.content);
28
+ const summary = normalizeText(memory?.summary);
29
+ return content.includes(summaryKey) || summary.includes(summaryKey);
30
+ }
31
+
32
+ function maintenanceScopes(scopeFilter) {
33
+ const scope = normalizeText(scopeFilter);
34
+ if (!scope) return ['user', 'global', 'project'];
35
+ if (scope === 'repo') return ['project'];
36
+ if (['user', 'global', 'project'].includes(scope)) return [scope];
37
+ return ['user', 'global', 'project'];
38
+ }
39
+
40
+ async function runMemoryMaintenance({
41
+ dryRun = false,
42
+ scope = null,
43
+ workspaceRoot = process.cwd(),
44
+ config = {}
45
+ } = {}) {
46
+ const reports = [];
47
+ const filesChanged = [];
48
+
49
+ for (const memoryScope of maintenanceScopes(scope)) {
50
+ const maintenance = await getMemoryBucketMaintenance({ scope: memoryScope, workspaceRoot });
51
+ const items = await listMemories({ scope: memoryScope, workspaceRoot });
52
+ if (items.length === 0) {
53
+ reports.push({ scope: memoryScope, skipped: true, reason: 'empty' });
54
+ continue;
55
+ }
56
+ if (maintenance.fresh) {
57
+ reports.push({ scope: memoryScope, skipped: true, reason: 'already-maintained', itemCount: items.length });
58
+ continue;
59
+ }
60
+
61
+ const evaluated = dryRun
62
+ ? { items, archives: [] }
63
+ : await evaluateMemoryMaintenance({ scope: memoryScope, items, config, workspaceRoot });
64
+ if (evaluated.error) {
65
+ reports.push({ scope: memoryScope, skipped: true, reason: `maintenance-error: ${evaluated.error}`, itemCount: items.length });
66
+ continue;
67
+ }
68
+ const nextItems = Array.isArray(evaluated.items) && evaluated.items.length > 0 ? evaluated.items : items;
69
+ const changed =
70
+ JSON.stringify(nextItems.map((item) => [item.kind, item.content, item.summary, item.lifecycle || ''])) !==
71
+ JSON.stringify(items.map((item) => [item.kind, item.content, item.summary, item.lifecycle || '']));
72
+
73
+ if (!dryRun) {
74
+ await replaceMemoryBucket({
75
+ scope: memoryScope,
76
+ items: nextItems,
77
+ workspaceRoot,
78
+ markMaintained: true
79
+ });
80
+ filesChanged.push({
81
+ file: memoryScope === 'project' ? 'memory/project/*.json' : `memory/${memoryScope}.json`,
82
+ why: changed
83
+ ? `LLM-maintained ${items.length} item(s) into ${nextItems.length} item(s)`
84
+ : `Marked ${items.length} item(s) as maintained`
85
+ });
86
+ }
87
+
88
+ reports.push({
89
+ scope: memoryScope,
90
+ skipped: false,
91
+ before: items.length,
92
+ after: nextItems.length,
93
+ changed,
94
+ archives: evaluated.archives || [],
95
+ dryRun
96
+ });
97
+ }
98
+
99
+ return { reports, filesChanged };
100
+ }
101
+
102
+ export async function runDreamConsolidation({
103
+ dryRun = false,
104
+ scope = null,
105
+ workspaceRoot = process.cwd(),
106
+ config = {},
107
+ writeAudit = true
108
+ } = {}) {
109
+ const scopeFilter = scope || null;
110
+ const inbox = await listInbox({ scope: scopeFilter });
111
+
112
+ const [globalMemories, userMemories, projectMemories] = await Promise.all([
113
+ listMemories({ scope: 'global', workspaceRoot }),
114
+ listMemories({ scope: 'user', workspaceRoot }),
115
+ listMemories({ scope: 'project', workspaceRoot })
116
+ ]);
117
+ const knownMemories = [...globalMemories, ...userMemories, ...projectMemories];
118
+
119
+ const promotions = [];
120
+ const rejections = [];
121
+ const archives = [];
122
+ const filesRead = ['memory/inbox/*', 'memory/global.json', 'memory/user.json', 'memory/project/*.json'];
123
+ const filesChanged = [];
124
+
125
+ /* ── Phase 1: 规则预过滤(快速剔除明显垃圾) ─────────────────── */
126
+ const candidates = [];
127
+ const seen = new Map();
128
+
129
+ for (const entry of inbox) {
130
+ const summaryKey = normalizeText(entry.summary);
131
+ if (!summaryKey) {
132
+ if (!dryRun) await archiveEntry(entry, 'invalid-summary', 'Summary is empty after normalization');
133
+ archives.push({ summary: String(entry.summary || ''), reason: 'invalid-summary' });
134
+ continue;
135
+ }
136
+
137
+ if (seen.has(summaryKey)) {
138
+ if (!dryRun) await archiveEntry(entry, 'duplicate', `Duplicate of ${seen.get(summaryKey)}`);
139
+ archives.push({ summary: entry.summary, reason: 'duplicate' });
140
+ continue;
141
+ }
142
+ seen.set(summaryKey, entry.id);
143
+
144
+ const alreadyKnown = knownMemories.some((memory) => memoryContainsSummary(memory, summaryKey));
145
+ if (alreadyKnown) {
146
+ if (!dryRun) await archiveEntry(entry, 'already-known', 'Already present in memory');
147
+ rejections.push({ summary: entry.summary, reason: 'already-known' });
148
+ continue;
149
+ }
150
+
151
+ candidates.push(entry);
152
+ }
153
+
154
+ if (candidates.length > 0) {
155
+ /* ── Phase 2: LLM 批量评估(质量门控 + scope 分类 + 内容提炼) ── */
156
+ const llmResults = dryRun
157
+ ? candidates.map((e) => ({ id: e.id, action: 'keep', scope: 'global', kind: e.type || 'observation', content: e.details || e.summary, summary: e.summary, confidence: 0.9 }))
158
+ : await evaluateInboxBatch({ entries: candidates, config, workspaceRoot });
159
+
160
+ const resultMap = new Map(llmResults.map((r) => [r.id, r]));
161
+
162
+ /* ── Phase 3: 按评估结果 promote 或 archive ─────────────────── */
163
+ for (const entry of candidates) {
164
+ const evaluation = resultMap.get(entry.id);
165
+
166
+ if (!evaluation || evaluation.action === 'discard') {
167
+ const reason = evaluation?.reason || 'LLM discarded';
168
+ if (!dryRun) await archiveEntry(entry, 'discarded-by-evaluator', reason);
169
+ rejections.push({ summary: entry.summary, reason: `evaluator-discard: ${reason}` });
170
+ continue;
171
+ }
172
+
173
+ const promoteScope = evaluation.scope || 'global';
174
+ const lifecycle = chooseLifecycle(evaluation.kind);
175
+ const enrichedEntry = {
176
+ ...entry,
177
+ /* 用 LLM 提炼后的内容覆盖原始报错 */
178
+ summary: evaluation.summary || entry.summary,
179
+ details: evaluation.content || entry.details || entry.summary,
180
+ type: evaluation.kind || entry.type || 'observation'
181
+ };
182
+
183
+ if (!dryRun) {
184
+ try {
185
+ await promoteMemory({
186
+ entry: enrichedEntry,
187
+ scope: promoteScope,
188
+ lifecycle,
189
+ workspaceRoot,
190
+ config,
191
+ confidence: evaluation.confidence || 0.8
192
+ });
193
+ filesChanged.push({ file: `memory/${promoteScope}.json`, why: `Promoted "${enrichedEntry.summary}" as ${lifecycle} (${promoteScope})` });
194
+ promotions.push({ summary: enrichedEntry.summary, scope: promoteScope, lifecycle, rationale: evaluation.kind, confidence: evaluation.confidence });
195
+ } catch (error) {
196
+ const reason = String(error?.message || error || 'promotion failed').slice(0, 180);
197
+ await archiveEntry(entry, 'promotion-failed', reason);
198
+ rejections.push({ summary: entry.summary, reason: `promotion-failed: ${reason}` });
199
+ archives.push({ summary: entry.summary, reason: 'promotion-failed' });
200
+ }
201
+ continue;
202
+ }
203
+
204
+ promotions.push({ summary: enrichedEntry.summary, scope: promoteScope, lifecycle, rationale: evaluation.kind, confidence: evaluation.confidence, dryRun: true });
205
+ }
206
+ }
207
+
208
+ const maintenance = await runMemoryMaintenance({ dryRun, scope: scopeFilter, workspaceRoot, config });
209
+ filesChanged.push(...maintenance.filesChanged);
210
+
211
+ const report = {
212
+ timestamp: new Date().toISOString(),
213
+ filesRead,
214
+ filesChanged,
215
+ candidatesGenerated: inbox.length,
216
+ promotions,
217
+ rejections,
218
+ archives,
219
+ maintenance: maintenance.reports,
220
+ ...(inbox.length === 0 ? { message: 'No inbox entries to consolidate; maintained existing memory buckets.' } : {})
221
+ };
222
+
223
+ if (!dryRun && writeAudit) {
224
+ const reportPath = await writeDreamAuditReport(report);
225
+ report.auditReport = reportPath;
226
+ }
227
+
228
+ return { ok: true, dryRun, ...report };
229
+ }