claude-code-workflow 6.3.24 → 6.3.26
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/.claude/commands/issue/discover-by-prompt.md +764 -0
- package/.claude/skills/text-formatter/SKILL.md +196 -0
- package/.claude/skills/text-formatter/phases/01-input-collection.md +111 -0
- package/.claude/skills/text-formatter/phases/02-content-analysis.md +248 -0
- package/.claude/skills/text-formatter/phases/03-format-transform.md +245 -0
- package/.claude/skills/text-formatter/phases/04-output-preview.md +183 -0
- package/.claude/skills/text-formatter/specs/callout-types.md +293 -0
- package/.claude/skills/text-formatter/specs/element-mapping.md +226 -0
- package/.claude/skills/text-formatter/specs/format-rules.md +273 -0
- package/.claude/skills/text-formatter/templates/bbcode-template.md +350 -0
- package/ccw/dist/core/routes/help-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/help-routes.js +43 -7
- package/ccw/dist/core/routes/help-routes.js.map +1 -1
- package/ccw/dist/core/routes/litellm-api-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/litellm-api-routes.js +31 -5
- package/ccw/dist/core/routes/litellm-api-routes.js.map +1 -1
- package/ccw/dist/core/routes/memory-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/memory-routes.js +73 -0
- package/ccw/dist/core/routes/memory-routes.js.map +1 -1
- package/ccw/dist/core/routes/status-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/status-routes.js +36 -4
- package/ccw/dist/core/routes/status-routes.js.map +1 -1
- package/ccw/dist/core/server.d.ts.map +1 -1
- package/ccw/dist/core/server.js +58 -0
- package/ccw/dist/core/server.js.map +1 -1
- package/ccw/dist/core/services/api-key-tester.d.ts.map +1 -1
- package/ccw/dist/core/services/api-key-tester.js +8 -3
- package/ccw/dist/core/services/api-key-tester.js.map +1 -1
- package/ccw/dist/tools/claude-cli-tools.d.ts +7 -0
- package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
- package/ccw/dist/tools/claude-cli-tools.js +11 -1
- package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
- package/ccw/dist/tools/cli-executor-core.d.ts +11 -0
- package/ccw/dist/tools/cli-executor-core.d.ts.map +1 -1
- package/ccw/dist/tools/cli-executor-core.js +89 -2
- package/ccw/dist/tools/cli-executor-core.js.map +1 -1
- package/ccw/dist/tools/codex-lens.d.ts +2 -1
- package/ccw/dist/tools/codex-lens.d.ts.map +1 -1
- package/ccw/dist/tools/codex-lens.js +51 -8
- package/ccw/dist/tools/codex-lens.js.map +1 -1
- package/ccw/dist/tools/index.d.ts.map +1 -1
- package/ccw/dist/tools/index.js +2 -0
- package/ccw/dist/tools/index.js.map +1 -1
- package/ccw/dist/tools/litellm-client.d.ts +6 -0
- package/ccw/dist/tools/litellm-client.d.ts.map +1 -1
- package/ccw/dist/tools/litellm-client.js +22 -1
- package/ccw/dist/tools/litellm-client.js.map +1 -1
- package/ccw/dist/tools/litellm-executor.js +2 -2
- package/ccw/dist/tools/litellm-executor.js.map +1 -1
- package/ccw/dist/tools/memory-update-queue.d.ts +172 -0
- package/ccw/dist/tools/memory-update-queue.d.ts.map +1 -0
- package/ccw/dist/tools/memory-update-queue.js +431 -0
- package/ccw/dist/tools/memory-update-queue.js.map +1 -0
- package/ccw/src/core/routes/help-routes.ts +46 -7
- package/ccw/src/core/routes/litellm-api-routes.ts +35 -4
- package/ccw/src/core/routes/memory-routes.ts +84 -0
- package/ccw/src/core/routes/status-routes.ts +39 -4
- package/ccw/src/core/server.ts +62 -0
- package/ccw/src/core/services/api-key-tester.ts +9 -3
- package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +45 -0
- package/ccw/src/templates/dashboard-js/components/cli-status.js +36 -5
- package/ccw/src/templates/dashboard-js/components/hook-manager.js +42 -81
- package/ccw/src/templates/dashboard-js/components/mcp-manager.js +170 -28
- package/ccw/src/templates/dashboard-js/components/notifications.js +14 -4
- package/ccw/src/templates/dashboard-js/i18n.js +26 -0
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +72 -2
- package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +11 -1
- package/ccw/src/tools/claude-cli-tools.ts +17 -1
- package/ccw/src/tools/cli-executor-core.ts +103 -2
- package/ccw/src/tools/codex-lens.ts +63 -8
- package/ccw/src/tools/index.ts +2 -0
- package/ccw/src/tools/litellm-client.ts +25 -3
- package/ccw/src/tools/litellm-executor.ts +2 -2
- package/ccw/src/tools/memory-update-queue.js +499 -0
- package/package.json +91 -91
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Update Queue Tool
|
|
3
|
+
* Queue mechanism for batching CLAUDE.md updates
|
|
4
|
+
*
|
|
5
|
+
* Configuration:
|
|
6
|
+
* - Threshold: 5 paths trigger update
|
|
7
|
+
* - Timeout: 5 minutes auto-trigger
|
|
8
|
+
* - Storage: ~/.claude/.memory-queue.json
|
|
9
|
+
* - Deduplication: Same path only kept once
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
13
|
+
import { join, dirname, resolve } from 'path';
|
|
14
|
+
import { homedir } from 'os';
|
|
15
|
+
|
|
16
|
+
// Default configuration
|
|
17
|
+
const DEFAULT_THRESHOLD = 5;
|
|
18
|
+
const DEFAULT_TIMEOUT_SECONDS = 300; // 5 minutes
|
|
19
|
+
const QUEUE_FILE_PATH = join(homedir(), '.claude', '.memory-queue.json');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get queue configuration (from file or defaults)
|
|
23
|
+
* @returns {{ threshold: number, timeoutMs: number }}
|
|
24
|
+
*/
|
|
25
|
+
function getQueueConfig() {
|
|
26
|
+
try {
|
|
27
|
+
if (existsSync(QUEUE_FILE_PATH)) {
|
|
28
|
+
const content = readFileSync(QUEUE_FILE_PATH, 'utf8');
|
|
29
|
+
const data = JSON.parse(content);
|
|
30
|
+
return {
|
|
31
|
+
threshold: data.config?.threshold || DEFAULT_THRESHOLD,
|
|
32
|
+
timeoutMs: (data.config?.timeout || DEFAULT_TIMEOUT_SECONDS) * 1000
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
} catch (e) {
|
|
36
|
+
// Use defaults
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
threshold: DEFAULT_THRESHOLD,
|
|
40
|
+
timeoutMs: DEFAULT_TIMEOUT_SECONDS * 1000
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// In-memory timeout reference (for cross-call persistence, we track via file timestamp)
|
|
45
|
+
let scheduledTimeoutId = null;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Ensure parent directory exists
|
|
49
|
+
*/
|
|
50
|
+
function ensureDir(filePath) {
|
|
51
|
+
const dir = dirname(filePath);
|
|
52
|
+
if (!existsSync(dir)) {
|
|
53
|
+
mkdirSync(dir, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Load queue from file
|
|
59
|
+
* @returns {{ items: Array<{path: string, tool: string, strategy: string, addedAt: string}>, createdAt: string | null, config?: { threshold: number, timeout: number } }}
|
|
60
|
+
*/
|
|
61
|
+
function loadQueue() {
|
|
62
|
+
try {
|
|
63
|
+
if (existsSync(QUEUE_FILE_PATH)) {
|
|
64
|
+
const content = readFileSync(QUEUE_FILE_PATH, 'utf8');
|
|
65
|
+
const data = JSON.parse(content);
|
|
66
|
+
return {
|
|
67
|
+
items: Array.isArray(data.items) ? data.items : [],
|
|
68
|
+
createdAt: data.createdAt || null,
|
|
69
|
+
config: data.config || null
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.error('[MemoryQueue] Failed to load queue:', e.message);
|
|
74
|
+
}
|
|
75
|
+
return { items: [], createdAt: null, config: null };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Save queue to file
|
|
80
|
+
* @param {{ items: Array<{path: string, tool: string, strategy: string, addedAt: string}>, createdAt: string | null }} data
|
|
81
|
+
*/
|
|
82
|
+
function saveQueue(data) {
|
|
83
|
+
try {
|
|
84
|
+
ensureDir(QUEUE_FILE_PATH);
|
|
85
|
+
writeFileSync(QUEUE_FILE_PATH, JSON.stringify(data, null, 2), 'utf8');
|
|
86
|
+
} catch (e) {
|
|
87
|
+
console.error('[MemoryQueue] Failed to save queue:', e.message);
|
|
88
|
+
throw e;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Normalize path for comparison (handle Windows/Unix differences)
|
|
94
|
+
* @param {string} p
|
|
95
|
+
* @returns {string}
|
|
96
|
+
*/
|
|
97
|
+
function normalizePath(p) {
|
|
98
|
+
return resolve(p).replace(/\\/g, '/').toLowerCase();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Add path to queue with deduplication
|
|
103
|
+
* @param {string} path - Module path to update
|
|
104
|
+
* @param {{ tool?: string, strategy?: string }} options
|
|
105
|
+
* @returns {{ queued: boolean, queueSize: number, willFlush: boolean, message: string }}
|
|
106
|
+
*/
|
|
107
|
+
function addToQueue(path, options = {}) {
|
|
108
|
+
const { tool = 'gemini', strategy = 'single-layer' } = options;
|
|
109
|
+
const queue = loadQueue();
|
|
110
|
+
const config = getQueueConfig();
|
|
111
|
+
const normalizedPath = normalizePath(path);
|
|
112
|
+
const now = new Date().toISOString();
|
|
113
|
+
|
|
114
|
+
// Check for duplicates
|
|
115
|
+
const existingIndex = queue.items.findIndex(
|
|
116
|
+
item => normalizePath(item.path) === normalizedPath
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
if (existingIndex !== -1) {
|
|
120
|
+
// Update existing entry timestamp but keep it deduplicated
|
|
121
|
+
queue.items[existingIndex].addedAt = now;
|
|
122
|
+
queue.items[existingIndex].tool = tool;
|
|
123
|
+
queue.items[existingIndex].strategy = strategy;
|
|
124
|
+
saveQueue(queue);
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
queued: false,
|
|
128
|
+
queueSize: queue.items.length,
|
|
129
|
+
willFlush: queue.items.length >= config.threshold,
|
|
130
|
+
message: `Path already in queue (updated): ${path}`
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Add new item
|
|
135
|
+
queue.items.push({
|
|
136
|
+
path,
|
|
137
|
+
tool,
|
|
138
|
+
strategy,
|
|
139
|
+
addedAt: now
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Set createdAt if this is the first item
|
|
143
|
+
if (!queue.createdAt) {
|
|
144
|
+
queue.createdAt = now;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
saveQueue(queue);
|
|
148
|
+
|
|
149
|
+
const willFlush = queue.items.length >= config.threshold;
|
|
150
|
+
|
|
151
|
+
// Schedule timeout if not already scheduled
|
|
152
|
+
scheduleTimeout();
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
queued: true,
|
|
156
|
+
queueSize: queue.items.length,
|
|
157
|
+
willFlush,
|
|
158
|
+
message: willFlush
|
|
159
|
+
? `Queue threshold reached (${queue.items.length}/${config.threshold}), will flush`
|
|
160
|
+
: `Added to queue (${queue.items.length}/${config.threshold})`
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get current queue status
|
|
166
|
+
* @returns {{ queueSize: number, threshold: number, items: Array, timeoutMs: number | null, createdAt: string | null }}
|
|
167
|
+
*/
|
|
168
|
+
function getQueueStatus() {
|
|
169
|
+
const queue = loadQueue();
|
|
170
|
+
const config = getQueueConfig();
|
|
171
|
+
let timeUntilTimeout = null;
|
|
172
|
+
|
|
173
|
+
if (queue.createdAt && queue.items.length > 0) {
|
|
174
|
+
const createdTime = new Date(queue.createdAt).getTime();
|
|
175
|
+
const elapsed = Date.now() - createdTime;
|
|
176
|
+
timeUntilTimeout = Math.max(0, config.timeoutMs - elapsed);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
queueSize: queue.items.length,
|
|
181
|
+
threshold: config.threshold,
|
|
182
|
+
items: queue.items,
|
|
183
|
+
timeoutMs: config.timeoutMs,
|
|
184
|
+
timeoutSeconds: config.timeoutMs / 1000,
|
|
185
|
+
timeUntilTimeout,
|
|
186
|
+
createdAt: queue.createdAt
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Configure queue settings
|
|
192
|
+
* @param {{ threshold?: number, timeout?: number }} settings
|
|
193
|
+
* @returns {{ success: boolean, config: { threshold: number, timeout: number } }}
|
|
194
|
+
*/
|
|
195
|
+
function configureQueue(settings) {
|
|
196
|
+
const queue = loadQueue();
|
|
197
|
+
const currentConfig = getQueueConfig();
|
|
198
|
+
|
|
199
|
+
const newConfig = {
|
|
200
|
+
threshold: settings.threshold || currentConfig.threshold,
|
|
201
|
+
timeout: settings.timeout || (currentConfig.timeoutMs / 1000)
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// Validate
|
|
205
|
+
if (newConfig.threshold < 1 || newConfig.threshold > 20) {
|
|
206
|
+
throw new Error('Threshold must be between 1 and 20');
|
|
207
|
+
}
|
|
208
|
+
if (newConfig.timeout < 60 || newConfig.timeout > 1800) {
|
|
209
|
+
throw new Error('Timeout must be between 60 and 1800 seconds');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
queue.config = newConfig;
|
|
213
|
+
saveQueue(queue);
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
success: true,
|
|
217
|
+
config: newConfig,
|
|
218
|
+
message: `Queue configured: threshold=${newConfig.threshold}, timeout=${newConfig.timeout}s`
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Flush queue - execute batch update
|
|
224
|
+
* @returns {Promise<{ success: boolean, processed: number, results: Array, errors: Array }>}
|
|
225
|
+
*/
|
|
226
|
+
async function flushQueue() {
|
|
227
|
+
const queue = loadQueue();
|
|
228
|
+
|
|
229
|
+
if (queue.items.length === 0) {
|
|
230
|
+
return {
|
|
231
|
+
success: true,
|
|
232
|
+
processed: 0,
|
|
233
|
+
results: [],
|
|
234
|
+
errors: [],
|
|
235
|
+
message: 'Queue is empty'
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Clear timeout
|
|
240
|
+
clearScheduledTimeout();
|
|
241
|
+
|
|
242
|
+
// Import update_module_claude dynamically to avoid circular deps
|
|
243
|
+
const { updateModuleClaudeTool } = await import('./update-module-claude.js');
|
|
244
|
+
|
|
245
|
+
const results = [];
|
|
246
|
+
const errors = [];
|
|
247
|
+
|
|
248
|
+
// Group by tool and strategy for efficiency
|
|
249
|
+
const groups = new Map();
|
|
250
|
+
for (const item of queue.items) {
|
|
251
|
+
const key = `${item.tool}:${item.strategy}`;
|
|
252
|
+
if (!groups.has(key)) {
|
|
253
|
+
groups.set(key, []);
|
|
254
|
+
}
|
|
255
|
+
groups.get(key).push(item);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Process each group
|
|
259
|
+
for (const [key, items] of groups) {
|
|
260
|
+
const [tool, strategy] = key.split(':');
|
|
261
|
+
console.log(`[MemoryQueue] Processing ${items.length} items with ${tool}/${strategy}`);
|
|
262
|
+
|
|
263
|
+
for (const item of items) {
|
|
264
|
+
try {
|
|
265
|
+
const result = await updateModuleClaudeTool.execute({
|
|
266
|
+
path: item.path,
|
|
267
|
+
tool: item.tool,
|
|
268
|
+
strategy: item.strategy
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
results.push({
|
|
272
|
+
path: item.path,
|
|
273
|
+
success: result.success !== false,
|
|
274
|
+
result
|
|
275
|
+
});
|
|
276
|
+
} catch (e) {
|
|
277
|
+
console.error(`[MemoryQueue] Failed to update ${item.path}:`, e.message);
|
|
278
|
+
errors.push({
|
|
279
|
+
path: item.path,
|
|
280
|
+
error: e.message
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Clear queue after processing
|
|
287
|
+
saveQueue({ items: [], createdAt: null });
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
success: errors.length === 0,
|
|
291
|
+
processed: queue.items.length,
|
|
292
|
+
results,
|
|
293
|
+
errors,
|
|
294
|
+
message: `Processed ${results.length} items, ${errors.length} errors`
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Schedule timeout for auto-flush
|
|
300
|
+
*/
|
|
301
|
+
function scheduleTimeout() {
|
|
302
|
+
// We use file-based timeout tracking for persistence across process restarts
|
|
303
|
+
// The actual timeout check happens on next add/status call
|
|
304
|
+
const queue = loadQueue();
|
|
305
|
+
const config = getQueueConfig();
|
|
306
|
+
|
|
307
|
+
if (!queue.createdAt || queue.items.length === 0) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const createdTime = new Date(queue.createdAt).getTime();
|
|
312
|
+
const elapsed = Date.now() - createdTime;
|
|
313
|
+
|
|
314
|
+
if (elapsed >= config.timeoutMs) {
|
|
315
|
+
// Timeout already exceeded, should flush
|
|
316
|
+
console.log('[MemoryQueue] Timeout exceeded, auto-flushing');
|
|
317
|
+
// Don't await here to avoid blocking
|
|
318
|
+
flushQueue().catch(e => {
|
|
319
|
+
console.error('[MemoryQueue] Auto-flush failed:', e.message);
|
|
320
|
+
});
|
|
321
|
+
} else if (!scheduledTimeoutId) {
|
|
322
|
+
// Schedule in-memory timeout for current process
|
|
323
|
+
const remaining = config.timeoutMs - elapsed;
|
|
324
|
+
scheduledTimeoutId = setTimeout(() => {
|
|
325
|
+
scheduledTimeoutId = null;
|
|
326
|
+
const currentQueue = loadQueue();
|
|
327
|
+
if (currentQueue.items.length > 0) {
|
|
328
|
+
console.log('[MemoryQueue] Timeout reached, auto-flushing');
|
|
329
|
+
flushQueue().catch(e => {
|
|
330
|
+
console.error('[MemoryQueue] Auto-flush failed:', e.message);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}, remaining);
|
|
334
|
+
|
|
335
|
+
// Prevent timeout from keeping process alive
|
|
336
|
+
if (scheduledTimeoutId.unref) {
|
|
337
|
+
scheduledTimeoutId.unref();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Clear scheduled timeout
|
|
344
|
+
*/
|
|
345
|
+
function clearScheduledTimeout() {
|
|
346
|
+
if (scheduledTimeoutId) {
|
|
347
|
+
clearTimeout(scheduledTimeoutId);
|
|
348
|
+
scheduledTimeoutId = null;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Check if timeout has expired and auto-flush if needed
|
|
354
|
+
* @returns {Promise<{ expired: boolean, flushed: boolean, result?: object }>}
|
|
355
|
+
*/
|
|
356
|
+
async function checkTimeout() {
|
|
357
|
+
const queue = loadQueue();
|
|
358
|
+
const config = getQueueConfig();
|
|
359
|
+
|
|
360
|
+
if (!queue.createdAt || queue.items.length === 0) {
|
|
361
|
+
return { expired: false, flushed: false };
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const createdTime = new Date(queue.createdAt).getTime();
|
|
365
|
+
const elapsed = Date.now() - createdTime;
|
|
366
|
+
|
|
367
|
+
if (elapsed >= config.timeoutMs) {
|
|
368
|
+
console.log('[MemoryQueue] Timeout expired, triggering flush');
|
|
369
|
+
const result = await flushQueue();
|
|
370
|
+
return { expired: true, flushed: true, result };
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return { expired: false, flushed: false };
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Main execute function for tool interface
|
|
378
|
+
* @param {Record<string, unknown>} params
|
|
379
|
+
* @returns {Promise<unknown>}
|
|
380
|
+
*/
|
|
381
|
+
async function execute(params) {
|
|
382
|
+
const { action, path, tool = 'gemini', strategy = 'single-layer', threshold, timeout } = params;
|
|
383
|
+
|
|
384
|
+
switch (action) {
|
|
385
|
+
case 'add':
|
|
386
|
+
if (!path) {
|
|
387
|
+
throw new Error('Parameter "path" is required for add action');
|
|
388
|
+
}
|
|
389
|
+
// Check timeout first
|
|
390
|
+
const timeoutCheck = await checkTimeout();
|
|
391
|
+
if (timeoutCheck.flushed) {
|
|
392
|
+
// Queue was flushed due to timeout, add to fresh queue
|
|
393
|
+
const result = addToQueue(path, { tool, strategy });
|
|
394
|
+
return {
|
|
395
|
+
...result,
|
|
396
|
+
timeoutFlushed: true,
|
|
397
|
+
flushResult: timeoutCheck.result
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const addResult = addToQueue(path, { tool, strategy });
|
|
402
|
+
|
|
403
|
+
// Auto-flush if threshold reached
|
|
404
|
+
if (addResult.willFlush) {
|
|
405
|
+
const flushResult = await flushQueue();
|
|
406
|
+
return {
|
|
407
|
+
...addResult,
|
|
408
|
+
flushed: true,
|
|
409
|
+
flushResult
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return addResult;
|
|
414
|
+
|
|
415
|
+
case 'status':
|
|
416
|
+
// Check timeout first
|
|
417
|
+
await checkTimeout();
|
|
418
|
+
return getQueueStatus();
|
|
419
|
+
|
|
420
|
+
case 'flush':
|
|
421
|
+
return await flushQueue();
|
|
422
|
+
|
|
423
|
+
case 'configure':
|
|
424
|
+
return configureQueue({ threshold, timeout });
|
|
425
|
+
|
|
426
|
+
default:
|
|
427
|
+
throw new Error(`Unknown action: ${action}. Valid actions: add, status, flush, configure`);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Tool Definition
|
|
433
|
+
*/
|
|
434
|
+
export const memoryQueueTool = {
|
|
435
|
+
name: 'memory_queue',
|
|
436
|
+
description: `Memory update queue management. Batches CLAUDE.md updates for efficiency.
|
|
437
|
+
|
|
438
|
+
Actions:
|
|
439
|
+
- add: Add path to queue (auto-flushes at configured threshold/timeout)
|
|
440
|
+
- status: Get queue status and configuration
|
|
441
|
+
- flush: Immediately execute all queued updates
|
|
442
|
+
- configure: Set threshold and timeout settings`,
|
|
443
|
+
parameters: {
|
|
444
|
+
type: 'object',
|
|
445
|
+
properties: {
|
|
446
|
+
action: {
|
|
447
|
+
type: 'string',
|
|
448
|
+
enum: ['add', 'status', 'flush', 'configure'],
|
|
449
|
+
description: 'Queue action to perform'
|
|
450
|
+
},
|
|
451
|
+
path: {
|
|
452
|
+
type: 'string',
|
|
453
|
+
description: 'Module directory path (required for add action)'
|
|
454
|
+
},
|
|
455
|
+
threshold: {
|
|
456
|
+
type: 'number',
|
|
457
|
+
description: 'Number of paths to trigger flush (1-20, for configure action)',
|
|
458
|
+
minimum: 1,
|
|
459
|
+
maximum: 20
|
|
460
|
+
},
|
|
461
|
+
timeout: {
|
|
462
|
+
type: 'number',
|
|
463
|
+
description: 'Timeout in seconds to trigger flush (60-1800, for configure action)',
|
|
464
|
+
minimum: 60,
|
|
465
|
+
maximum: 1800
|
|
466
|
+
},
|
|
467
|
+
tool: {
|
|
468
|
+
type: 'string',
|
|
469
|
+
enum: ['gemini', 'qwen', 'codex'],
|
|
470
|
+
description: 'CLI tool to use (default: gemini)',
|
|
471
|
+
default: 'gemini'
|
|
472
|
+
},
|
|
473
|
+
strategy: {
|
|
474
|
+
type: 'string',
|
|
475
|
+
enum: ['single-layer', 'multi-layer'],
|
|
476
|
+
description: 'Update strategy (default: single-layer)',
|
|
477
|
+
default: 'single-layer'
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
required: ['action']
|
|
481
|
+
},
|
|
482
|
+
execute
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// Export individual functions for direct use
|
|
486
|
+
export {
|
|
487
|
+
loadQueue,
|
|
488
|
+
saveQueue,
|
|
489
|
+
addToQueue,
|
|
490
|
+
getQueueStatus,
|
|
491
|
+
flushQueue,
|
|
492
|
+
configureQueue,
|
|
493
|
+
scheduleTimeout,
|
|
494
|
+
clearScheduledTimeout,
|
|
495
|
+
checkTimeout,
|
|
496
|
+
DEFAULT_THRESHOLD,
|
|
497
|
+
DEFAULT_TIMEOUT_SECONDS,
|
|
498
|
+
QUEUE_FILE_PATH
|
|
499
|
+
};
|
package/package.json
CHANGED
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "claude-code-workflow",
|
|
3
|
-
"version": "6.3.
|
|
4
|
-
"description": "JSON-driven multi-agent development framework with intelligent CLI orchestration (Gemini/Qwen/Codex), context-first architecture, and automated workflow execution",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "ccw/src/index.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"ccw": "./ccw/bin/ccw.js",
|
|
9
|
-
"ccw-mcp": "./ccw/bin/ccw-mcp.js"
|
|
10
|
-
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsc -p ccw/tsconfig.json",
|
|
13
|
-
"start": "node ccw/bin/ccw.js",
|
|
14
|
-
"test": "node --experimental-strip-types --test ccw/tests/*.test.js",
|
|
15
|
-
"test:visual": "node --experimental-strip-types --test ccw/tests/visual/**/*.visual.test.ts",
|
|
16
|
-
"test:e2e": "node --experimental-strip-types --test ccw/tests/e2e/*.e2e.test.ts",
|
|
17
|
-
"prepublishOnly": "npm run build && echo 'Ready to publish @dyw/claude-code-workflow'"
|
|
18
|
-
},
|
|
19
|
-
"keywords": [
|
|
20
|
-
"claude",
|
|
21
|
-
"workflow",
|
|
22
|
-
"ai",
|
|
23
|
-
"cli",
|
|
24
|
-
"dashboard",
|
|
25
|
-
"code-review",
|
|
26
|
-
"automation",
|
|
27
|
-
"development"
|
|
28
|
-
],
|
|
29
|
-
"author": "dyw",
|
|
30
|
-
"license": "MIT",
|
|
31
|
-
"engines": {
|
|
32
|
-
"node": ">=16.0.0"
|
|
33
|
-
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
36
|
-
"better-sqlite3": "^11.7.0",
|
|
37
|
-
"boxen": "^7.1.0",
|
|
38
|
-
"chalk": "^5.3.0",
|
|
39
|
-
"commander": "^11.0.0",
|
|
40
|
-
"figlet": "^1.7.0",
|
|
41
|
-
"glob": "^10.3.0",
|
|
42
|
-
"gradient-string": "^2.0.2",
|
|
43
|
-
"inquirer": "^9.2.0",
|
|
44
|
-
"jsonwebtoken": "^9.0.3",
|
|
45
|
-
"open": "^9.1.0",
|
|
46
|
-
"ora": "^7.0.0",
|
|
47
|
-
"zod": "^4.1.13"
|
|
48
|
-
},
|
|
49
|
-
"files": [
|
|
50
|
-
"ccw/bin/",
|
|
51
|
-
"ccw/dist/",
|
|
52
|
-
"ccw/src/",
|
|
53
|
-
".claude/agents/",
|
|
54
|
-
".claude/commands/",
|
|
55
|
-
".claude/output-styles/",
|
|
56
|
-
".claude/workflows/",
|
|
57
|
-
".claude/scripts/",
|
|
58
|
-
".claude/prompt-templates/",
|
|
59
|
-
".claude/python_script/",
|
|
60
|
-
".claude/skills/",
|
|
61
|
-
".codex/",
|
|
62
|
-
".gemini/",
|
|
63
|
-
".qwen/",
|
|
64
|
-
"codex-lens/src/codexlens/",
|
|
65
|
-
"codex-lens/pyproject.toml",
|
|
66
|
-
"ccw-litellm/src/ccw_litellm/",
|
|
67
|
-
"ccw-litellm/pyproject.toml",
|
|
68
|
-
"CLAUDE.md",
|
|
69
|
-
"README.md"
|
|
70
|
-
],
|
|
71
|
-
"repository": {
|
|
72
|
-
"type": "git",
|
|
73
|
-
"url": "git+https://github.com/catlog22/Claude-Code-Workflow.git"
|
|
74
|
-
},
|
|
75
|
-
"bugs": {
|
|
76
|
-
"url": "https://github.com/catlog22/Claude-Code-Workflow/issues"
|
|
77
|
-
},
|
|
78
|
-
"homepage": "https://github.com/catlog22/Claude-Code-Workflow#readme",
|
|
79
|
-
"devDependencies": {
|
|
80
|
-
"@playwright/test": "^1.57.0",
|
|
81
|
-
"@types/better-sqlite3": "^7.6.12",
|
|
82
|
-
"@types/gradient-string": "^1.1.6",
|
|
83
|
-
"@types/inquirer": "^9.0.9",
|
|
84
|
-
"@types/jsonwebtoken": "^9.0.10",
|
|
85
|
-
"@types/node": "^25.0.1",
|
|
86
|
-
"pixelmatch": "^7.1.0",
|
|
87
|
-
"playwright": "^1.57.0",
|
|
88
|
-
"pngjs": "^7.0.0",
|
|
89
|
-
"typescript": "^5.9.3"
|
|
90
|
-
}
|
|
91
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "claude-code-workflow",
|
|
3
|
+
"version": "6.3.26",
|
|
4
|
+
"description": "JSON-driven multi-agent development framework with intelligent CLI orchestration (Gemini/Qwen/Codex), context-first architecture, and automated workflow execution",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "ccw/src/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ccw": "./ccw/bin/ccw.js",
|
|
9
|
+
"ccw-mcp": "./ccw/bin/ccw-mcp.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc -p ccw/tsconfig.json",
|
|
13
|
+
"start": "node ccw/bin/ccw.js",
|
|
14
|
+
"test": "node --experimental-strip-types --test ccw/tests/*.test.js",
|
|
15
|
+
"test:visual": "node --experimental-strip-types --test ccw/tests/visual/**/*.visual.test.ts",
|
|
16
|
+
"test:e2e": "node --experimental-strip-types --test ccw/tests/e2e/*.e2e.test.ts",
|
|
17
|
+
"prepublishOnly": "npm run build && echo 'Ready to publish @dyw/claude-code-workflow'"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"claude",
|
|
21
|
+
"workflow",
|
|
22
|
+
"ai",
|
|
23
|
+
"cli",
|
|
24
|
+
"dashboard",
|
|
25
|
+
"code-review",
|
|
26
|
+
"automation",
|
|
27
|
+
"development"
|
|
28
|
+
],
|
|
29
|
+
"author": "dyw",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=16.0.0"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
36
|
+
"better-sqlite3": "^11.7.0",
|
|
37
|
+
"boxen": "^7.1.0",
|
|
38
|
+
"chalk": "^5.3.0",
|
|
39
|
+
"commander": "^11.0.0",
|
|
40
|
+
"figlet": "^1.7.0",
|
|
41
|
+
"glob": "^10.3.0",
|
|
42
|
+
"gradient-string": "^2.0.2",
|
|
43
|
+
"inquirer": "^9.2.0",
|
|
44
|
+
"jsonwebtoken": "^9.0.3",
|
|
45
|
+
"open": "^9.1.0",
|
|
46
|
+
"ora": "^7.0.0",
|
|
47
|
+
"zod": "^4.1.13"
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"ccw/bin/",
|
|
51
|
+
"ccw/dist/",
|
|
52
|
+
"ccw/src/",
|
|
53
|
+
".claude/agents/",
|
|
54
|
+
".claude/commands/",
|
|
55
|
+
".claude/output-styles/",
|
|
56
|
+
".claude/workflows/",
|
|
57
|
+
".claude/scripts/",
|
|
58
|
+
".claude/prompt-templates/",
|
|
59
|
+
".claude/python_script/",
|
|
60
|
+
".claude/skills/",
|
|
61
|
+
".codex/",
|
|
62
|
+
".gemini/",
|
|
63
|
+
".qwen/",
|
|
64
|
+
"codex-lens/src/codexlens/",
|
|
65
|
+
"codex-lens/pyproject.toml",
|
|
66
|
+
"ccw-litellm/src/ccw_litellm/",
|
|
67
|
+
"ccw-litellm/pyproject.toml",
|
|
68
|
+
"CLAUDE.md",
|
|
69
|
+
"README.md"
|
|
70
|
+
],
|
|
71
|
+
"repository": {
|
|
72
|
+
"type": "git",
|
|
73
|
+
"url": "git+https://github.com/catlog22/Claude-Code-Workflow.git"
|
|
74
|
+
},
|
|
75
|
+
"bugs": {
|
|
76
|
+
"url": "https://github.com/catlog22/Claude-Code-Workflow/issues"
|
|
77
|
+
},
|
|
78
|
+
"homepage": "https://github.com/catlog22/Claude-Code-Workflow#readme",
|
|
79
|
+
"devDependencies": {
|
|
80
|
+
"@playwright/test": "^1.57.0",
|
|
81
|
+
"@types/better-sqlite3": "^7.6.12",
|
|
82
|
+
"@types/gradient-string": "^1.1.6",
|
|
83
|
+
"@types/inquirer": "^9.0.9",
|
|
84
|
+
"@types/jsonwebtoken": "^9.0.10",
|
|
85
|
+
"@types/node": "^25.0.1",
|
|
86
|
+
"pixelmatch": "^7.1.0",
|
|
87
|
+
"playwright": "^1.57.0",
|
|
88
|
+
"pngjs": "^7.0.0",
|
|
89
|
+
"typescript": "^5.9.3"
|
|
90
|
+
}
|
|
91
|
+
}
|