@yemi33/minions 0.1.1931 → 0.1.1932
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/dashboard.js +25 -10
- package/engine/cc-worker-pool.js +56 -4
- package/engine/copilot-models.json +1 -1
- package/package.json +1 -1
package/dashboard.js
CHANGED
|
@@ -2480,8 +2480,10 @@ async function _preflightModelCheck({ runtime: cliOverride, model: modelOverride
|
|
|
2480
2480
|
* contract SSE consumers depend on).
|
|
2481
2481
|
* - `usage` is `{}` because ACP `session/update` notifications don't
|
|
2482
2482
|
* surface token counts; trackEngineUsage is a no-op on `{}`.
|
|
2483
|
-
* - Tool calls are
|
|
2484
|
-
*
|
|
2483
|
+
* - Tool calls are surfaced via the optional `onToolUse(name, input)`
|
|
2484
|
+
* callback (ACP `tool_call` notification, mapped to Claude-style
|
|
2485
|
+
* {name, input}). `tool_call_update` (results) is ignored to avoid
|
|
2486
|
+
* double chips.
|
|
2485
2487
|
* - Honors `timeoutMs`. On timeout: cancels the prompt, closes the tab
|
|
2486
2488
|
* (so the next call rebuilds against a clean process), resolves with
|
|
2487
2489
|
* `{ code: 1, stderr: 'doc-chat-pool: timeout after Xms' }`. The
|
|
@@ -2496,7 +2498,7 @@ async function _preflightModelCheck({ runtime: cliOverride, model: modelOverride
|
|
|
2496
2498
|
* document body. Always re-sending extraContext is correctness-safe; the
|
|
2497
2499
|
* pool's warm-process saving is preserved regardless.
|
|
2498
2500
|
*/
|
|
2499
|
-
function _invokeDocChatViaPool({ prompt, model, effort, engineConfig, systemPrompt, sessionKey, freshSession, timeoutMs, onChunk }) {
|
|
2501
|
+
function _invokeDocChatViaPool({ prompt, model, effort, engineConfig, systemPrompt, sessionKey, freshSession, timeoutMs, onChunk, onToolUse }) {
|
|
2500
2502
|
const oneShot = !!freshSession;
|
|
2501
2503
|
const tabKey = oneShot
|
|
2502
2504
|
? 'doc-chat:fresh:' + shared.uid()
|
|
@@ -2574,6 +2576,11 @@ function _invokeDocChatViaPool({ prompt, model, effort, engineConfig, systemProm
|
|
|
2574
2576
|
try { onChunk(accumulated); } catch { /* swallow */ }
|
|
2575
2577
|
}
|
|
2576
2578
|
},
|
|
2579
|
+
onToolUse: (name, input) => {
|
|
2580
|
+
if (onToolUse) {
|
|
2581
|
+
try { onToolUse(name, input || {}); } catch { /* swallow */ }
|
|
2582
|
+
}
|
|
2583
|
+
},
|
|
2577
2584
|
onDone: () => {
|
|
2578
2585
|
finalize({ text: accumulated, sessionId: sessionHandle.sessionId, code: 0, usage: {}, raw: accumulated, stderr: '' });
|
|
2579
2586
|
},
|
|
@@ -2786,7 +2793,7 @@ async function ccCallStreaming(message, { store = 'cc', sessionKey, extraContext
|
|
|
2786
2793
|
const p = _invokeDocChatViaPool({
|
|
2787
2794
|
prompt: poolPrompt, sessionKey, model, effort: ccEffort,
|
|
2788
2795
|
engineConfig: CONFIG.engine, systemPrompt,
|
|
2789
|
-
onChunk,
|
|
2796
|
+
onChunk, onToolUse,
|
|
2790
2797
|
freshSession, timeoutMs: timeout,
|
|
2791
2798
|
});
|
|
2792
2799
|
if (onAbortReady) onAbortReady(p.abort);
|
|
@@ -6311,7 +6318,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
6311
6318
|
*/
|
|
6312
6319
|
function _invokeCcStream({ prompt, sessionId, liveState, toolUses, model, effort, maxTurns, engineConfig, systemPrompt = CC_STATIC_SYSTEM_PROMPT, tabId }) {
|
|
6313
6320
|
if (shared.resolveCcUseWorkerPool(engineConfig)) {
|
|
6314
|
-
return _invokeCcStreamViaPool({ prompt, liveState, model, effort, engineConfig, systemPrompt, tabId });
|
|
6321
|
+
return _invokeCcStreamViaPool({ prompt, liveState, toolUses, model, effort, engineConfig, systemPrompt, tabId });
|
|
6315
6322
|
}
|
|
6316
6323
|
const { callLLMStreaming } = require('./engine/llm');
|
|
6317
6324
|
return callLLMStreaming(prompt, systemPrompt, {
|
|
@@ -6345,16 +6352,17 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
6345
6352
|
* callLLMStreaming's contract is "full accumulated text"; we accumulate
|
|
6346
6353
|
* here so `liveState.text` and downstream chunk events keep the same
|
|
6347
6354
|
* semantics consumers already depend on.
|
|
6348
|
-
* - Tool calls are
|
|
6349
|
-
* `tool_call`
|
|
6350
|
-
*
|
|
6351
|
-
*
|
|
6355
|
+
* - Tool calls are surfaced via the pool's `onToolUse` callback (ACP
|
|
6356
|
+
* `tool_call` notification, mapped to Claude-style {name, input} so the
|
|
6357
|
+
* dashboard's existing formatToolSummary chips render unchanged).
|
|
6358
|
+
* `tool_call_update` events (status: completed) are intentionally
|
|
6359
|
+
* ignored — surfacing results too would double the chip count.
|
|
6352
6360
|
* - `usage` is reported as an empty object — ACP doesn't expose token
|
|
6353
6361
|
* counts in the in-flight session/update notifications, and the pool's
|
|
6354
6362
|
* long-lived process makes per-turn usage attribution non-trivial.
|
|
6355
6363
|
* trackEngineUsage is a no-op on `{}`.
|
|
6356
6364
|
*/
|
|
6357
|
-
function _invokeCcStreamViaPool({ prompt, liveState, model, effort, engineConfig, systemPrompt, tabId }) {
|
|
6365
|
+
function _invokeCcStreamViaPool({ prompt, liveState, toolUses, model, effort, engineConfig, systemPrompt, tabId }) {
|
|
6358
6366
|
const resolvedTabId = tabId || 'default';
|
|
6359
6367
|
let cancelled = false;
|
|
6360
6368
|
let accumulated = '';
|
|
@@ -6396,6 +6404,13 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
6396
6404
|
liveState.text = accumulated;
|
|
6397
6405
|
if (liveState.writer) liveState.writer({ type: 'chunk', text: accumulated });
|
|
6398
6406
|
},
|
|
6407
|
+
onToolUse: (name, input) => {
|
|
6408
|
+
_touchCcLiveStream(liveState);
|
|
6409
|
+
const safeInput = input || {};
|
|
6410
|
+
if (Array.isArray(toolUses)) toolUses.push({ name, input: safeInput });
|
|
6411
|
+
if (Array.isArray(liveState.tools)) liveState.tools.push({ name, input: safeInput });
|
|
6412
|
+
if (liveState.writer) liveState.writer({ type: 'tool', name, input: _lightToolInput(safeInput) });
|
|
6413
|
+
},
|
|
6399
6414
|
onDone: () => {
|
|
6400
6415
|
resolveResult({ text: accumulated, sessionId: sessionHandle.sessionId, code: 0, usage: {}, raw: accumulated, stderr: '' });
|
|
6401
6416
|
},
|
package/engine/cc-worker-pool.js
CHANGED
|
@@ -251,10 +251,21 @@ class Worker {
|
|
|
251
251
|
if (text && this.inflight.onChunk) {
|
|
252
252
|
try { this.inflight.onChunk(text); } catch { /* swallow */ }
|
|
253
253
|
}
|
|
254
|
+
} else if (update.sessionUpdate === 'tool_call' && this.inflight.onToolUse) {
|
|
255
|
+
// ACP `tool_call` (status: pending, fired at invocation time) is the
|
|
256
|
+
// pool's equivalent of Claude's tool_use event. We map kinds to
|
|
257
|
+
// Claude-style tool names so the dashboard's existing
|
|
258
|
+
// formatToolSummary (Bash → "$ <cmd>", Read → "Reading <path>", etc.)
|
|
259
|
+
// works unchanged. Status updates (`tool_call_update`, status:
|
|
260
|
+
// completed) carry the result and are ignored here — surfacing
|
|
261
|
+
// results too would double the chip count without adding info the
|
|
262
|
+
// user can act on.
|
|
263
|
+
const mapped = _mapAcpToolCallToToolUse(update);
|
|
264
|
+
if (mapped) {
|
|
265
|
+
try { this.inflight.onToolUse(mapped.name, mapped.input); }
|
|
266
|
+
catch { /* swallow */ }
|
|
267
|
+
}
|
|
254
268
|
}
|
|
255
|
-
// Other update kinds (available_commands_update, tool_call, ...) are
|
|
256
|
-
// ignored in sub-task B. Sub-task C/D will surface tool_call to the
|
|
257
|
-
// dashboard's onToolUse callback.
|
|
258
269
|
}
|
|
259
270
|
}
|
|
260
271
|
|
|
@@ -279,7 +290,7 @@ class Worker {
|
|
|
279
290
|
|
|
280
291
|
// ── Stream a single turn ───────────────────────────────────────────────
|
|
281
292
|
stream(promptText, opts = {}) {
|
|
282
|
-
const { onChunk, onDone, onError, signal, systemPromptText } = opts;
|
|
293
|
+
const { onChunk, onToolUse, onDone, onError, signal, systemPromptText } = opts;
|
|
283
294
|
if (this.killed) {
|
|
284
295
|
const err = new Error('cc-worker-pool: tab is closed');
|
|
285
296
|
if (onError) try { onError(err); } catch { /* swallow */ }
|
|
@@ -307,6 +318,7 @@ class Worker {
|
|
|
307
318
|
id,
|
|
308
319
|
sessionId: this.sessionId,
|
|
309
320
|
onChunk,
|
|
321
|
+
onToolUse,
|
|
310
322
|
onDone,
|
|
311
323
|
onError,
|
|
312
324
|
signal,
|
|
@@ -425,6 +437,46 @@ function _extractChunkText(content) {
|
|
|
425
437
|
return '';
|
|
426
438
|
}
|
|
427
439
|
|
|
440
|
+
// Map an ACP `tool_call` session/update notification to the {name, input} shape
|
|
441
|
+
// the dashboard's formatToolSummary already understands. ACP's `kind` is a
|
|
442
|
+
// coarse category (execute|read|edit|search|fetch|think|other); we translate to
|
|
443
|
+
// the closest Claude tool name so the existing chip formatters keep working
|
|
444
|
+
// (Bash → "$ <cmd>", Read → "Reading <path>", etc.). Unknown kinds fall back
|
|
445
|
+
// to ACP's human-readable `title` with the raw input attached, which renders
|
|
446
|
+
// through the default `<title>(<key>: <val>)` formatter.
|
|
447
|
+
function _mapAcpToolCallToToolUse(update) {
|
|
448
|
+
if (!update || update.sessionUpdate !== 'tool_call') return null;
|
|
449
|
+
const rawInput = (update.rawInput && typeof update.rawInput === 'object') ? update.rawInput : {};
|
|
450
|
+
const kind = String(update.kind || '').toLowerCase();
|
|
451
|
+
const title = update.title || '';
|
|
452
|
+
// For kinds with a clear Claude-tool equivalent, use that name + raw input.
|
|
453
|
+
switch (kind) {
|
|
454
|
+
case 'execute':
|
|
455
|
+
return { name: 'Bash', input: rawInput };
|
|
456
|
+
case 'read':
|
|
457
|
+
return { name: 'Read', input: rawInput };
|
|
458
|
+
case 'edit':
|
|
459
|
+
return { name: 'Edit', input: rawInput };
|
|
460
|
+
case 'search': {
|
|
461
|
+
// Heuristic: Grep needs a pattern; Glob needs a glob pattern.
|
|
462
|
+
// ACP doesn't distinguish, so prefer Grep when a `path` hint is present
|
|
463
|
+
// (matches the dashboard's Grep formatter "Searching <pat> in <path>").
|
|
464
|
+
const isGrep = typeof rawInput.path === 'string' || typeof rawInput.regex === 'string';
|
|
465
|
+
return { name: isGrep ? 'Grep' : 'Glob', input: rawInput };
|
|
466
|
+
}
|
|
467
|
+
case 'fetch':
|
|
468
|
+
return { name: 'WebFetch', input: rawInput };
|
|
469
|
+
case 'think':
|
|
470
|
+
// No equivalent Claude tool; show the title so the user sees Copilot's
|
|
471
|
+
// own description of what it's thinking about.
|
|
472
|
+
return { name: title || 'Think', input: rawInput };
|
|
473
|
+
default:
|
|
474
|
+
// Fallback: show ACP's title and pass rawInput through. The dashboard's
|
|
475
|
+
// default formatter renders this as `<title>(<key>: <val>)`.
|
|
476
|
+
return { name: title || kind || 'Tool', input: rawInput };
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
428
480
|
// ── Public API ────────────────────────────────────────────────────────────
|
|
429
481
|
|
|
430
482
|
async function getSession({ tabId, model, effort, mcpServers, systemPromptHash, cwd } = {}) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1932",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|