codemini-cli 0.3.2 → 0.3.3

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.
@@ -136,10 +136,8 @@ const TUI_COPY = {
136
136
  doingGrep: '正在搜索关键词',
137
137
  doneCommand: '已执行命令',
138
138
  doingCommand: '正在执行命令',
139
- doneCreateTask: '已创建任务',
140
- doingCreateTask: '正在创建任务',
141
- doneUpdateTask: '已更新任务',
142
- doingUpdateTask: '正在更新任务',
139
+ doneUpdateTodos: '已更新待办',
140
+ doingUpdateTodos: '正在更新待办',
143
141
  doneGeneric: '已完成工具',
144
142
  doingGeneric: '正在执行工具',
145
143
  doneInstall: '已安装依赖',
@@ -156,14 +154,12 @@ const TUI_COPY = {
156
154
  doingDatabase: '正在启动数据库服务',
157
155
  doneDocker: '已完成 Docker 命令',
158
156
  doingDocker: '正在执行 Docker 命令',
159
- doneListServices: '已列出服务',
160
- doingListServices: '正在列出服务',
161
- doneServiceStatus: '已查看服务状态',
162
- doingServiceStatus: '正在查看服务状态',
163
- doneServiceLogs: '已查看服务日志',
164
- doingServiceLogs: '正在查看服务日志',
165
- doneStopService: '已停止服务',
166
- doingStopService: '正在停止服务',
157
+ doneListBackgroundTasks: '已列出后台任务',
158
+ doingListBackgroundTasks: '正在列出后台任务',
159
+ doneBackgroundTaskStatus: '已查看后台任务',
160
+ doingBackgroundTaskStatus: '正在查看后台任务',
161
+ doneStopBackgroundTask: '已停止后台任务',
162
+ doingStopBackgroundTask: '正在停止后台任务',
167
163
  doneCodeGeneration: '已生成代码',
168
164
  doingCodeGeneration: '正在生成代码',
169
165
  doneSkill: '已完成技能',
@@ -281,10 +277,8 @@ const TUI_COPY = {
281
277
  doingGrep: 'Searching keywords',
282
278
  doneCommand: 'Ran command',
283
279
  doingCommand: 'Running command',
284
- doneCreateTask: 'Created task',
285
- doingCreateTask: 'Creating task',
286
- doneUpdateTask: 'Updated task',
287
- doingUpdateTask: 'Updating task',
280
+ doneUpdateTodos: 'Updated todos',
281
+ doingUpdateTodos: 'Updating todos',
288
282
  doneGeneric: 'Completed tool',
289
283
  doingGeneric: 'Running tool',
290
284
  doneInstall: 'Dependencies installed',
@@ -301,14 +295,12 @@ const TUI_COPY = {
301
295
  doingDatabase: 'Starting database service',
302
296
  doneDocker: 'Docker command completed',
303
297
  doingDocker: 'Running Docker command',
304
- doneListServices: 'Listed services',
305
- doingListServices: 'Listing services',
306
- doneServiceStatus: 'Checked service status',
307
- doingServiceStatus: 'Checking service status',
308
- doneServiceLogs: 'Viewed service logs',
309
- doingServiceLogs: 'Viewing service logs',
310
- doneStopService: 'Stopped service',
311
- doingStopService: 'Stopping service',
298
+ doneListBackgroundTasks: 'Listed background tasks',
299
+ doingListBackgroundTasks: 'Listing background tasks',
300
+ doneBackgroundTaskStatus: 'Checked background task',
301
+ doingBackgroundTaskStatus: 'Checking background task',
302
+ doneStopBackgroundTask: 'Stopped background task',
303
+ doingStopBackgroundTask: 'Stopping background task',
312
304
  doneCodeGeneration: 'Code generated',
313
305
  doingCodeGeneration: 'Generating code',
314
306
  doneSkill: 'Completed skill',
@@ -883,7 +875,7 @@ function getActivityDisplayParts(activity) {
883
875
  };
884
876
  }
885
877
  const parsed = parseToolDisplayName(activity?.name);
886
- if (parsed.base === 'run' || parsed.base === 'start_service') {
878
+ if (parsed.base === 'run') {
887
879
  const intent = classifyCommandIntent(parsed.target);
888
880
  return {
889
881
  primary: getIntentLabel(intent.kind),
@@ -917,14 +909,11 @@ function getActivityDisplayParts(activity) {
917
909
  grep: 'Search',
918
910
  glob: 'Glob',
919
911
  list: 'List',
920
- start_service: 'Service',
921
- list_services: 'Services',
922
- get_service_status: 'Status',
923
- get_service_logs: 'Logs',
924
- stop_service: 'Stop',
912
+ list_background_tasks: 'Tasks',
913
+ get_background_task: 'Task',
914
+ stop_background_task: 'Stop',
925
915
  list_files: 'Glob',
926
- create_task: 'Task',
927
- update_task: 'Task'
916
+ update_todos: 'Update Todos'
928
917
  };
929
918
  return {
930
919
  primary: labels[parsed.base] || parsed.base || 'Tool',
@@ -1831,7 +1820,7 @@ export function normalizeActivitySpacingRows(inputRows) {
1831
1820
 
1832
1821
  if (isActivityRow(row) && !isActivityRow(next) && next) {
1833
1822
  const last = normalized.at(-1);
1834
- if (!isBlankTextRow(last) && !(next.kind === 'status')) {
1823
+ if (!isBlankTextRow(last) && !(next.kind === 'status') && !isTodoRow(next)) {
1835
1824
  normalized.push({
1836
1825
  kind: 'text',
1837
1826
  text: ' ',
@@ -1848,6 +1837,10 @@ export function normalizeActivitySpacingRows(inputRows) {
1848
1837
  return normalized;
1849
1838
  }
1850
1839
 
1840
+ function isTodoRow(row) {
1841
+ return row?.kind === 'todo-item';
1842
+ }
1843
+
1851
1844
  function isReadActivityName(name) {
1852
1845
  const parsed = parseToolDisplayName(name);
1853
1846
  return parsed.base === 'read' || parsed.base === 'Read';
@@ -2031,6 +2024,19 @@ function buildMessageRows(msg, showToolDetails, contentWidth = 72, copy) {
2031
2024
  durationText,
2032
2025
  isLatestTool: idx === total - 1
2033
2026
  });
2027
+ const todoItems = parseToolDisplayName(tool.name).base === 'update_todos' ? tool?.arguments?.todos : null;
2028
+ if (Array.isArray(todoItems) && todoItems.length > 0 && tool.status !== 'running') {
2029
+ for (const item of todoItems) {
2030
+ const status = String(item?.status || 'pending').trim();
2031
+ rows.push({
2032
+ kind: 'todo-item',
2033
+ status,
2034
+ text: String(item?.content || '').trim(),
2035
+ activeForm: String(item?.activeForm || '').trim()
2036
+ });
2037
+ }
2038
+ return;
2039
+ }
2034
2040
  if ((showToolDetails || idx === total - 1) && tool.summary && tool.status !== 'running') {
2035
2041
  for (const line of String(tool.summary).split('\n')) {
2036
2042
  pushWrappedRow(rows, { kind: 'activity-summary', text: line || ' ', color: 'gray' }, Math.max(8, contentWidth - 4));
@@ -2125,6 +2131,21 @@ function renderMessageRow(msg, row, idx, loaderTick) {
2125
2131
  h(Text, { color: 'gray' }, `└ ${row.text}`)
2126
2132
  );
2127
2133
  }
2134
+ if (row.kind === 'todo-item') {
2135
+ const marker =
2136
+ row.status === 'completed' ? '[✓]' : row.status === 'in_progress' ? '[*]' : '[ ]';
2137
+ const color =
2138
+ row.status === 'completed' ? 'gray' : row.status === 'in_progress' ? 'white' : 'gray';
2139
+ const dimColor = row.status === 'completed';
2140
+ return h(
2141
+ Box,
2142
+ { key: `row-todo-${msg.id}-${idx}`, marginLeft: 2, marginBottom: 1 },
2143
+ h(Text, { color: 'gray' }, ' '),
2144
+ h(Text, { color }, marker),
2145
+ h(Text, { color: 'gray' }, ' '),
2146
+ h(Text, { color, dimColor }, row.text || row.activeForm || ' ')
2147
+ );
2148
+ }
2128
2149
  if (row.kind === 'table') {
2129
2150
  return h(
2130
2151
  Box,
@@ -9,7 +9,7 @@ export function describeCommandToolActivity(copy, parsed, { done = false, blocke
9
9
  const target = parsed.target || 'command';
10
10
  const intent = classifyRunIntent(parsed.target);
11
11
 
12
- if (parsed.base === 'run' || parsed.base === 'start_service') {
12
+ if (parsed.base === 'run') {
13
13
  if (intent.kind === 'install') return phaseText(copy, blocked, done, target, copy.toolActivity.doingInstall, copy.toolActivity.doneInstall);
14
14
  if (intent.kind === 'build') return phaseText(copy, blocked, done, target, copy.toolActivity.doingBuild, copy.toolActivity.doneBuild);
15
15
  if (intent.kind === 'test') return phaseText(copy, blocked, done, target, copy.toolActivity.doingTest, copy.toolActivity.doneTest);
@@ -18,24 +18,17 @@ export function describeCommandToolActivity(copy, parsed, { done = false, blocke
18
18
  if (intent.kind === 'database-service') return phaseText(copy, blocked, done, target, copy.toolActivity.doingDatabase, copy.toolActivity.doneDatabase);
19
19
  if (intent.kind === 'docker-service') return phaseText(copy, blocked, done, target, copy.toolActivity.doingDocker, copy.toolActivity.doneDocker);
20
20
  if (intent.kind === 'service') return phaseText(copy, blocked, done, target, copy.toolActivity.doingGeneric, copy.toolActivity.doneGeneric);
21
- if (parsed.base === 'run') return phaseText(copy, blocked, done, trimText(target, 72) || parsed.base, copy.toolActivity.doingCommand, copy.toolActivity.doneCommand);
21
+ return phaseText(copy, blocked, done, trimText(target, 72) || parsed.base, copy.toolActivity.doingCommand, copy.toolActivity.doneCommand);
22
22
  }
23
23
 
24
- if (parsed.base === 'list_services') {
25
- return phaseText(copy, blocked, done, trimText(parsed.target, 72) || parsed.base, copy.toolActivity.doingListServices, copy.toolActivity.doneListServices);
24
+ if (parsed.base === 'list_background_tasks') {
25
+ return phaseText(copy, blocked, done, trimText(parsed.target, 72) || parsed.base, copy.toolActivity.doingListBackgroundTasks, copy.toolActivity.doneListBackgroundTasks);
26
26
  }
27
- if (parsed.base === 'get_service_status') {
28
- return phaseText(copy, blocked, done, trimText(parsed.target, 72) || parsed.base, copy.toolActivity.doingServiceStatus, copy.toolActivity.doneServiceStatus);
27
+ if (parsed.base === 'get_background_task') {
28
+ return phaseText(copy, blocked, done, trimText(parsed.target, 72) || parsed.base, copy.toolActivity.doingBackgroundTaskStatus, copy.toolActivity.doneBackgroundTaskStatus);
29
29
  }
30
- if (parsed.base === 'get_service_logs') {
31
- return phaseText(copy, blocked, done, trimText(parsed.target, 72) || parsed.base, copy.toolActivity.doingServiceLogs, copy.toolActivity.doneServiceLogs);
32
- }
33
- if (parsed.base === 'stop_service') {
34
- return phaseText(copy, blocked, done, trimText(parsed.target, 72) || parsed.base, copy.toolActivity.doingStopService, copy.toolActivity.doneStopService);
35
- }
36
-
37
- if (parsed.base === 'start_service') {
38
- return phaseText(copy, blocked, done, trimText(parsed.target, 72) || parsed.base, copy.toolActivity.doingGeneric, copy.toolActivity.doneGeneric);
30
+ if (parsed.base === 'stop_background_task') {
31
+ return phaseText(copy, blocked, done, trimText(parsed.target, 72) || parsed.base, copy.toolActivity.doingStopBackgroundTask, copy.toolActivity.doneStopBackgroundTask);
39
32
  }
40
33
 
41
34
  return '';
@@ -9,11 +9,8 @@ export function describeMiscToolActivity(copy, parsed, rawName, { done = false,
9
9
  if (blocked) return `${copy.toolActivity.blocked}: code generation`;
10
10
  return done ? copy.toolActivity.doneCodeGeneration : copy.toolActivity.doingCodeGeneration;
11
11
  }
12
- if (parsed.base === 'create_task') {
13
- return blocked ? makeBlocked(copy, 'create_task') : done ? copy.toolActivity.doneCreateTask : copy.toolActivity.doingCreateTask;
14
- }
15
- if (parsed.base === 'update_task') {
16
- return blocked ? makeBlocked(copy, 'update_task') : done ? copy.toolActivity.doneUpdateTask : copy.toolActivity.doingUpdateTask;
12
+ if (parsed.base === 'update_todos') {
13
+ return blocked ? makeBlocked(copy, 'update_todos') : done ? copy.toolActivity.doneUpdateTodos : copy.toolActivity.doingUpdateTodos;
17
14
  }
18
15
  return blocked ? `${copy.toolActivity.blocked}: ${parsed.raw}` : done ? `${copy.toolActivity.doneGeneric}: ${parsed.raw}` : `${copy.toolActivity.doingGeneric}: ${parsed.raw}`;
19
16
  }
@@ -1,117 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { getProjectLegacyTasksFilePath, getProjectTasksDir } from './paths.js';
4
-
5
- function legacyTasksFilePath(cwd = process.cwd()) {
6
- return getProjectLegacyTasksFilePath(cwd);
7
- }
8
-
9
- function tasksFilePath(cwd = process.cwd(), sessionId = '') {
10
- const sid = String(sessionId || '').trim();
11
- if (!sid) return legacyTasksFilePath(cwd);
12
- return path.join(getProjectTasksDir(cwd), `${sid}.json`);
13
- }
14
-
15
- async function ensureDir(filePath) {
16
- await fs.mkdir(path.dirname(filePath), { recursive: true });
17
- }
18
-
19
- function normalizeTasks(value) {
20
- if (!Array.isArray(value)) return [];
21
- return value
22
- .map((t) => ({
23
- id: String(t?.id || '').trim(),
24
- title: String(t?.title || '').trim(),
25
- status: String(t?.status || 'pending').trim() || 'pending',
26
- description: String(t?.description || '').trim(),
27
- createdAt: String(t?.createdAt || ''),
28
- updatedAt: String(t?.updatedAt || '')
29
- }))
30
- .filter((t) => t.id && t.title);
31
- }
32
-
33
- function createTaskId() {
34
- const ts = Date.now().toString(36);
35
- const rnd = Math.random().toString(36).slice(2, 7);
36
- return `task-${ts}-${rnd}`;
37
- }
38
-
39
- export async function loadTasks(cwd = process.cwd(), sessionId = '') {
40
- const filePath = tasksFilePath(cwd, sessionId);
41
- try {
42
- const raw = await fs.readFile(filePath, 'utf8');
43
- const parsed = JSON.parse(raw);
44
- return normalizeTasks(parsed?.tasks);
45
- } catch {
46
- if (sessionId) {
47
- try {
48
- const raw = await fs.readFile(legacyTasksFilePath(cwd), 'utf8');
49
- const parsed = JSON.parse(raw);
50
- return normalizeTasks(parsed?.tasks);
51
- } catch {
52
- return [];
53
- }
54
- }
55
- return [];
56
- }
57
- }
58
-
59
- export async function saveTasks(tasks, cwd = process.cwd(), sessionId = '') {
60
- const filePath = tasksFilePath(cwd, sessionId);
61
- await ensureDir(filePath);
62
- const normalized = normalizeTasks(tasks);
63
- await fs.writeFile(
64
- filePath,
65
- `${JSON.stringify({ updatedAt: new Date().toISOString(), tasks: normalized }, null, 2)}\n`,
66
- 'utf8'
67
- );
68
- return normalized;
69
- }
70
-
71
- export async function createTasks(items, cwd = process.cwd(), sessionId = '') {
72
- const existing = await loadTasks(cwd, sessionId);
73
- const now = new Date().toISOString();
74
- const input = Array.isArray(items) ? items : [];
75
- const add = input
76
- .map((t) => ({
77
- id: createTaskId(),
78
- title: String(t?.title || '').trim(),
79
- description: String(t?.description || '').trim(),
80
- status: 'pending',
81
- createdAt: now,
82
- updatedAt: now
83
- }))
84
- .filter((t) => t.title);
85
- const next = [...existing, ...add];
86
- await saveTasks(next, cwd, sessionId);
87
- return add;
88
- }
89
-
90
- export async function updateTask(taskId, patch, cwd = process.cwd(), sessionId = '') {
91
- const tasks = await loadTasks(cwd, sessionId);
92
- const idx = tasks.findIndex((t) => t.id === taskId);
93
- if (idx === -1) return null;
94
- const next = [...tasks];
95
- const status = String(patch?.status || next[idx].status).trim();
96
- next[idx] = {
97
- ...next[idx],
98
- ...(patch?.title ? { title: String(patch.title) } : {}),
99
- ...(patch?.description !== undefined ? { description: String(patch.description || '') } : {}),
100
- status: ['pending', 'in_progress', 'completed'].includes(status) ? status : next[idx].status,
101
- updatedAt: new Date().toISOString()
102
- };
103
- await saveTasks(next, cwd, sessionId);
104
- return next[idx];
105
- }
106
-
107
- export async function deleteTasks(ids, cwd = process.cwd(), sessionId = '') {
108
- const remove = new Set((Array.isArray(ids) ? ids : []).map((v) => String(v)));
109
- const before = await loadTasks(cwd, sessionId);
110
- const kept = before.filter((t) => !remove.has(t.id));
111
- await saveTasks(kept, cwd, sessionId);
112
- return { removed: before.length - kept.length, remaining: kept.length };
113
- }
114
-
115
- export async function clearTasks(cwd = process.cwd(), sessionId = '') {
116
- await saveTasks([], cwd, sessionId);
117
- }