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,178 +1,178 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { getProjectSkillsDir, getSkillsDir } from './paths.js';
4
- import { createChatCompletion } from './provider/index.js';
5
-
6
- const REFLECT_TIMEOUT_MS = 45000;
7
-
8
- function slugifySkillName(value) {
9
- const slug = String(value || '')
10
- .trim()
11
- .toLowerCase()
12
- .replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-')
13
- .replace(/^-+|-+$/g, '');
14
- return slug || 'reflected-success-workflow';
15
- }
16
-
17
- function escapeFrontmatter(value) {
18
- return String(value || '').replace(/\r?\n/g, ' ').replace(/"/g, '\\"').trim();
19
- }
20
-
21
- function hasFrontmatter(content) {
22
- return /^---\r?\n[\s\S]*?\r?\n---\r?\n/.test(String(content || '').trimStart());
23
- }
24
-
25
- function renderSkillContent({ name, description, content }) {
26
- const body = String(content || '').trim() || [
27
- '## Workflow',
28
- '',
29
- '1. Recreate the successful chain from the recent task.',
30
- '2. Preserve the key decision that made it work.',
31
- '3. Verify with the narrowest relevant check.',
32
- '',
33
- '## Boundaries',
34
- '',
35
- 'Use this only when the current task matches the preserved workflow.'
36
- ].join('\n');
37
- if (hasFrontmatter(body)) return `${body.trim()}\n`;
38
- return [
39
- '---',
40
- `name: ${name}`,
41
- `description: ${escapeFrontmatter(description) || `Use when this reflected workflow applies.`}`,
42
- '---',
43
- '',
44
- body
45
- ].join('\n').trimEnd() + '\n';
46
- }
47
-
48
- export function normalizeReflectDraft(raw = {}) {
49
- const name = slugifySkillName(raw.name || raw.skillName || raw.title);
50
- const description = String(raw.description || raw.summary || `Use when the ${name} workflow applies.`).trim();
51
- const confidence = Math.min(1, Math.max(0, Number(raw.confidence ?? 0.75)));
52
- return {
53
- id: Number(raw.id || 1),
54
- name,
55
- description,
56
- confidence,
57
- content: renderSkillContent({ name, description, content: raw.content || raw.markdown || raw.body })
58
- };
59
- }
60
-
61
- export function buildReflectTargetPath({ scope = 'project', name, workspaceRoot = process.cwd() } = {}) {
62
- const safeName = slugifySkillName(name);
63
- const baseDir = String(scope || '').toLowerCase() === 'global'
64
- ? getSkillsDir()
65
- : getProjectSkillsDir(workspaceRoot);
66
- return path.join(baseDir, safeName, 'SKILL.md');
67
- }
68
-
69
- export function parseReflectScope(args = []) {
70
- let scope = 'project';
71
- const requestParts = [];
72
- for (let index = 0; index < args.length; index += 1) {
73
- const arg = String(args[index] || '');
74
- if (arg === '--scope') {
75
- const next = String(args[index + 1] || '').toLowerCase();
76
- if (next === 'global' || next === 'project') {
77
- scope = next;
78
- index += 1;
79
- }
80
- continue;
81
- }
82
- if (arg.startsWith('--scope=')) {
83
- const value = arg.slice('--scope='.length).toLowerCase();
84
- if (value === 'global' || value === 'project') scope = value;
85
- continue;
86
- }
87
- requestParts.push(arg);
88
- }
89
- return { scope, request: requestParts.join(' ').trim() };
90
- }
91
-
92
- function parseModelDrafts(text) {
93
- const raw = String(text || '').trim();
94
- if (!raw) return [];
95
- const unfenced = raw.replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/i, '').trim();
96
- try {
97
- const parsed = JSON.parse(unfenced);
98
- if (Array.isArray(parsed?.candidates)) return parsed.candidates.map((item, index) => normalizeReflectDraft({ id: index + 1, ...item }));
99
- if (Array.isArray(parsed)) return parsed.map((item, index) => normalizeReflectDraft({ id: index + 1, ...item }));
100
- if (parsed && typeof parsed === 'object') return [normalizeReflectDraft(parsed)];
101
- } catch {
102
- // Fall back to wrapping plain markdown below.
103
- }
104
- return [normalizeReflectDraft({
105
- name: 'reflected-success-workflow',
106
- description: 'Use when the reflected successful workflow applies.',
107
- content: raw
108
- })];
109
- }
110
-
111
- function recentContext(session, limit = 10) {
112
- const messages = Array.isArray(session?.messages) ? session.messages : [];
113
- return messages
114
- .slice(-limit)
115
- .map((message) => `${message.role}: ${String(message.content || '').slice(0, 1200)}`)
116
- .join('\n\n');
117
- }
118
-
119
- export async function buildReflectSkillDraft({
120
- request = '',
121
- scope = 'project',
122
- session,
123
- config = {},
124
- model,
125
- systemPrompt = '',
126
- previousDraft = null,
127
- feedback = ''
128
- } = {}) {
129
- const mode = String(request || '').trim() ? 'directed' : 'exploratory';
130
- const prompt = [
131
- 'Create a reusable Codex/Codemini SKILL.md draft from a successful workflow.',
132
- `Mode: ${mode}`,
133
- `Target scope: ${scope}`,
134
- request ? `User reflection request:\n${request}` : 'No explicit request was supplied. Be conservative and return no candidates if the recent context does not show a reusable success pattern.',
135
- previousDraft ? `Existing draft to revise:\n${previousDraft.content || ''}` : '',
136
- feedback ? `User edit feedback:\n${feedback}` : '',
137
- 'Recent session context:',
138
- recentContext(session),
139
- 'Return valid JSON only, no markdown fences.',
140
- 'Shape: {"candidates":[{"name":"kebab-case-name","description":"when to use this skill","confidence":0.0,"content":"full SKILL.md body or markdown body"}]}',
141
- 'The content must include trigger conditions, workflow/toolchain, key decisions, pitfalls, verification, and boundaries.',
142
- 'Do not write memory or inbox content. This is only a skill draft.'
143
- ].filter(Boolean).join('\n\n');
144
-
145
- const result = await createChatCompletion({
146
- sdkProvider: config?.sdk?.provider,
147
- baseUrl: config?.gateway?.base_url,
148
- apiKey: config?.gateway?.api_key,
149
- model: model || config?.model?.name,
150
- messages: [
151
- { role: 'system', content: systemPrompt || 'You draft concise, reusable coding workflow skills.' },
152
- { role: 'user', content: prompt }
153
- ],
154
- temperature: 0,
155
- timeoutMs: REFLECT_TIMEOUT_MS
156
- });
157
-
158
- return parseModelDrafts(result?.text || '');
159
- }
160
-
161
- export function attachReflectTargets({ candidates = [], scope = 'project', workspaceRoot = process.cwd() } = {}) {
162
- return candidates.map((candidate, index) => {
163
- const draft = normalizeReflectDraft({ id: index + 1, ...candidate });
164
- return {
165
- ...draft,
166
- targetPath: buildReflectTargetPath({ scope, name: draft.name, workspaceRoot })
167
- };
168
- });
169
- }
170
-
171
- export async function writeReflectSkillDraft({ draft, scope = 'project', workspaceRoot = process.cwd() } = {}) {
172
- const normalized = normalizeReflectDraft(draft);
173
- const filePath = buildReflectTargetPath({ scope, name: normalized.name, workspaceRoot });
174
- await fs.mkdir(path.dirname(filePath), { recursive: true });
175
- await fs.writeFile(filePath, normalized.content, 'utf8');
176
- return { filePath, draft: normalized };
177
- }
178
-
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { getProjectSkillsDir, getSkillsDir } from './paths.js';
4
+ import { createChatCompletion } from './provider/index.js';
5
+
6
+ const REFLECT_TIMEOUT_MS = 45000;
7
+
8
+ function slugifySkillName(value) {
9
+ const slug = String(value || '')
10
+ .trim()
11
+ .toLowerCase()
12
+ .replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-')
13
+ .replace(/^-+|-+$/g, '');
14
+ return slug || 'reflected-success-workflow';
15
+ }
16
+
17
+ function escapeFrontmatter(value) {
18
+ return String(value || '').replace(/\r?\n/g, ' ').replace(/"/g, '\\"').trim();
19
+ }
20
+
21
+ function hasFrontmatter(content) {
22
+ return /^---\r?\n[\s\S]*?\r?\n---\r?\n/.test(String(content || '').trimStart());
23
+ }
24
+
25
+ function renderSkillContent({ name, description, content }) {
26
+ const body = String(content || '').trim() || [
27
+ '## Workflow',
28
+ '',
29
+ '1. Recreate the successful chain from the recent task.',
30
+ '2. Preserve the key decision that made it work.',
31
+ '3. Verify with the narrowest relevant check.',
32
+ '',
33
+ '## Boundaries',
34
+ '',
35
+ 'Use this only when the current task matches the preserved workflow.'
36
+ ].join('\n');
37
+ if (hasFrontmatter(body)) return `${body.trim()}\n`;
38
+ return [
39
+ '---',
40
+ `name: ${name}`,
41
+ `description: ${escapeFrontmatter(description) || `Use when this reflected workflow applies.`}`,
42
+ '---',
43
+ '',
44
+ body
45
+ ].join('\n').trimEnd() + '\n';
46
+ }
47
+
48
+ export function normalizeReflectDraft(raw = {}) {
49
+ const name = slugifySkillName(raw.name || raw.skillName || raw.title);
50
+ const description = String(raw.description || raw.summary || `Use when the ${name} workflow applies.`).trim();
51
+ const confidence = Math.min(1, Math.max(0, Number(raw.confidence ?? 0.75)));
52
+ return {
53
+ id: Number(raw.id || 1),
54
+ name,
55
+ description,
56
+ confidence,
57
+ content: renderSkillContent({ name, description, content: raw.content || raw.markdown || raw.body })
58
+ };
59
+ }
60
+
61
+ export function buildReflectTargetPath({ scope = 'project', name, workspaceRoot = process.cwd() } = {}) {
62
+ const safeName = slugifySkillName(name);
63
+ const baseDir = String(scope || '').toLowerCase() === 'global'
64
+ ? getSkillsDir()
65
+ : getProjectSkillsDir(workspaceRoot);
66
+ return path.join(baseDir, safeName, 'SKILL.md');
67
+ }
68
+
69
+ export function parseReflectScope(args = []) {
70
+ let scope = 'project';
71
+ const requestParts = [];
72
+ for (let index = 0; index < args.length; index += 1) {
73
+ const arg = String(args[index] || '');
74
+ if (arg === '--scope') {
75
+ const next = String(args[index + 1] || '').toLowerCase();
76
+ if (next === 'global' || next === 'project') {
77
+ scope = next;
78
+ index += 1;
79
+ }
80
+ continue;
81
+ }
82
+ if (arg.startsWith('--scope=')) {
83
+ const value = arg.slice('--scope='.length).toLowerCase();
84
+ if (value === 'global' || value === 'project') scope = value;
85
+ continue;
86
+ }
87
+ requestParts.push(arg);
88
+ }
89
+ return { scope, request: requestParts.join(' ').trim() };
90
+ }
91
+
92
+ function parseModelDrafts(text) {
93
+ const raw = String(text || '').trim();
94
+ if (!raw) return [];
95
+ const unfenced = raw.replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/i, '').trim();
96
+ try {
97
+ const parsed = JSON.parse(unfenced);
98
+ if (Array.isArray(parsed?.candidates)) return parsed.candidates.map((item, index) => normalizeReflectDraft({ id: index + 1, ...item }));
99
+ if (Array.isArray(parsed)) return parsed.map((item, index) => normalizeReflectDraft({ id: index + 1, ...item }));
100
+ if (parsed && typeof parsed === 'object') return [normalizeReflectDraft(parsed)];
101
+ } catch {
102
+ // Fall back to wrapping plain markdown below.
103
+ }
104
+ return [normalizeReflectDraft({
105
+ name: 'reflected-success-workflow',
106
+ description: 'Use when the reflected successful workflow applies.',
107
+ content: raw
108
+ })];
109
+ }
110
+
111
+ function recentContext(session, limit = 10) {
112
+ const messages = Array.isArray(session?.messages) ? session.messages : [];
113
+ return messages
114
+ .slice(-limit)
115
+ .map((message) => `${message.role}: ${String(message.content || '').slice(0, 1200)}`)
116
+ .join('\n\n');
117
+ }
118
+
119
+ export async function buildReflectSkillDraft({
120
+ request = '',
121
+ scope = 'project',
122
+ session,
123
+ config = {},
124
+ model,
125
+ systemPrompt = '',
126
+ previousDraft = null,
127
+ feedback = ''
128
+ } = {}) {
129
+ const mode = String(request || '').trim() ? 'directed' : 'exploratory';
130
+ const prompt = [
131
+ 'Create a reusable Codex/Codemini SKILL.md draft from a successful workflow.',
132
+ `Mode: ${mode}`,
133
+ `Target scope: ${scope}`,
134
+ request ? `User reflection request:\n${request}` : 'No explicit request was supplied. Be conservative and return no candidates if the recent context does not show a reusable success pattern.',
135
+ previousDraft ? `Existing draft to revise:\n${previousDraft.content || ''}` : '',
136
+ feedback ? `User edit feedback:\n${feedback}` : '',
137
+ 'Recent session context:',
138
+ recentContext(session),
139
+ 'Return valid JSON only, no markdown fences.',
140
+ 'Shape: {"candidates":[{"name":"kebab-case-name","description":"when to use this skill","confidence":0.0,"content":"full SKILL.md body or markdown body"}]}',
141
+ 'The content must include trigger conditions, workflow/toolchain, key decisions, pitfalls, verification, and boundaries.',
142
+ 'Do not write memory or inbox content. This is only a skill draft.'
143
+ ].filter(Boolean).join('\n\n');
144
+
145
+ const result = await createChatCompletion({
146
+ sdkProvider: config?.sdk?.provider,
147
+ baseUrl: config?.gateway?.base_url,
148
+ apiKey: config?.gateway?.api_key,
149
+ model: model || config?.model?.name,
150
+ messages: [
151
+ { role: 'system', content: systemPrompt || 'You draft concise, reusable coding workflow skills.' },
152
+ { role: 'user', content: prompt }
153
+ ],
154
+ temperature: 0,
155
+ timeoutMs: REFLECT_TIMEOUT_MS
156
+ });
157
+
158
+ return parseModelDrafts(result?.text || '');
159
+ }
160
+
161
+ export function attachReflectTargets({ candidates = [], scope = 'project', workspaceRoot = process.cwd() } = {}) {
162
+ return candidates.map((candidate, index) => {
163
+ const draft = normalizeReflectDraft({ id: index + 1, ...candidate });
164
+ return {
165
+ ...draft,
166
+ targetPath: buildReflectTargetPath({ scope, name: draft.name, workspaceRoot })
167
+ };
168
+ });
169
+ }
170
+
171
+ export async function writeReflectSkillDraft({ draft, scope = 'project', workspaceRoot = process.cwd() } = {}) {
172
+ const normalized = normalizeReflectDraft(draft);
173
+ const filePath = buildReflectTargetPath({ scope, name: normalized.name, workspaceRoot });
174
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
175
+ await fs.writeFile(filePath, normalized.content, 'utf8');
176
+ return { filePath, draft: normalized };
177
+ }
178
+
@@ -1,40 +1,40 @@
1
- export function normalizeReplyLanguage(value) {
2
- const raw = String(value || '').trim().toLowerCase();
3
- if (!raw) return 'zh';
4
- if (['en', 'en-us', 'en_us', 'english'].includes(raw)) return 'en';
5
- if (['zh', 'zh-cn', 'zh_cn', 'cn', 'chinese', '中文', '简体中文'].includes(raw)) return 'zh';
6
- return 'zh';
7
- }
8
-
9
- export function getReplyLanguage(config = {}) {
10
- if (typeof config === 'string') return normalizeReplyLanguage(config);
11
- return normalizeReplyLanguage(config?.ui?.reply_language);
12
- }
13
-
14
- export function getReplyLanguageName(config = {}) {
15
- return getReplyLanguage(config) === 'en' ? 'English' : 'Simplified Chinese';
16
- }
17
-
18
- export function buildSystemPromptWithReplyLanguage(baseSystemPrompt, config = {}) {
19
- const replyLanguage = getReplyLanguage(config);
20
- const directive =
21
- replyLanguage === 'en'
22
- ? [
23
- '[Reply language]',
24
- 'Respond in English.',
25
- 'Write generated documentation, user-facing text, and code comments in English unless the user explicitly asks for a different language.'
26
- ].join('\n')
27
- : [
28
- '[Reply language]',
29
- 'Respond in Simplified Chinese.',
30
- 'Write generated documentation, user-facing text, and code comments in Simplified Chinese unless the user explicitly asks for a different language.'
31
- ].join('\n');
32
-
33
- return `${String(baseSystemPrompt || '').trim()}\n\n${directive}`.trim();
34
- }
35
-
36
- export function stripReplyLanguageDirective(systemPrompt) {
37
- return String(systemPrompt || '')
38
- .replace(/\n{0,2}\[Reply language\]\n(?:Respond in (?:English|Simplified Chinese)\.\n)?Write generated documentation, user-facing text, and code comments in (?:English|Simplified Chinese) unless the user explicitly asks for a different language\./g, '')
39
- .trim();
40
- }
1
+ export function normalizeReplyLanguage(value) {
2
+ const raw = String(value || '').trim().toLowerCase();
3
+ if (!raw) return 'zh';
4
+ if (['en', 'en-us', 'en_us', 'english'].includes(raw)) return 'en';
5
+ if (['zh', 'zh-cn', 'zh_cn', 'cn', 'chinese', '中文', '简体中文'].includes(raw)) return 'zh';
6
+ return 'zh';
7
+ }
8
+
9
+ export function getReplyLanguage(config = {}) {
10
+ if (typeof config === 'string') return normalizeReplyLanguage(config);
11
+ return normalizeReplyLanguage(config?.ui?.reply_language);
12
+ }
13
+
14
+ export function getReplyLanguageName(config = {}) {
15
+ return getReplyLanguage(config) === 'en' ? 'English' : 'Simplified Chinese';
16
+ }
17
+
18
+ export function buildSystemPromptWithReplyLanguage(baseSystemPrompt, config = {}) {
19
+ const replyLanguage = getReplyLanguage(config);
20
+ const directive =
21
+ replyLanguage === 'en'
22
+ ? [
23
+ '[Reply language]',
24
+ 'Respond in English.',
25
+ 'Write generated documentation, user-facing text, and code comments in English unless the user explicitly asks for a different language.'
26
+ ].join('\n')
27
+ : [
28
+ '[Reply language]',
29
+ 'Respond in Simplified Chinese.',
30
+ 'Write generated documentation, user-facing text, and code comments in Simplified Chinese unless the user explicitly asks for a different language.'
31
+ ].join('\n');
32
+
33
+ return `${String(baseSystemPrompt || '').trim()}\n\n${directive}`.trim();
34
+ }
35
+
36
+ export function stripReplyLanguageDirective(systemPrompt) {
37
+ return String(systemPrompt || '')
38
+ .replace(/\n{0,2}\[Reply language\]\n(?:Respond in (?:English|Simplified Chinese)\.\n)?Write generated documentation, user-facing text, and code comments in (?:English|Simplified Chinese) unless the user explicitly asks for a different language\./g, '')
39
+ .trim();
40
+ }