@yemi33/minions 0.1.2346 → 0.1.2347
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 +62 -7
- package/docs/command-center.md +3 -1
- package/package.json +1 -1
package/dashboard.js
CHANGED
|
@@ -6973,12 +6973,35 @@ const server = http.createServer(async (req, res) => {
|
|
|
6973
6973
|
if (target.error) return jsonReply(res, 404, { error: target.error });
|
|
6974
6974
|
const wiPath = target.wiPath;
|
|
6975
6975
|
|
|
6976
|
+
// W-mrazefzz000358e3 — body.project reassigns which projects/<name>/
|
|
6977
|
+
// work-items.json (or central) file owns this item. Resolve + validate
|
|
6978
|
+
// it up front (mirrors resolveWorkItemsCreateTarget's create-path
|
|
6979
|
+
// contract) so an unknown project name 400s cleanly instead of the
|
|
6980
|
+
// historical silent no-op. `projectMove` stays null when body.project
|
|
6981
|
+
// is omitted (no location change requested).
|
|
6982
|
+
let projectMove = null;
|
|
6983
|
+
if (body.project !== undefined) {
|
|
6984
|
+
const projTarget = resolveProjectSourceTarget(body.project, PROJECTS);
|
|
6985
|
+
if (projTarget.error) {
|
|
6986
|
+
return jsonReply(res, 400, {
|
|
6987
|
+
error: projTarget.error,
|
|
6988
|
+
knownProjects: PROJECTS.map(p => p.name),
|
|
6989
|
+
});
|
|
6990
|
+
}
|
|
6991
|
+
projectMove = { wiPath: projTarget.wiPath, projectName: projTarget.project ? projTarget.project.name : null };
|
|
6992
|
+
}
|
|
6993
|
+
|
|
6976
6994
|
let result = null;
|
|
6977
6995
|
let agentChanged = false;
|
|
6996
|
+
// Set inside the source-file lock below when a project move is needed;
|
|
6997
|
+
// inserted into the target file's own lock scope afterward so we never
|
|
6998
|
+
// hold both files' locks at once.
|
|
6999
|
+
let movedItem = null;
|
|
6978
7000
|
mutateJsonFileLocked(wiPath, (items) => {
|
|
6979
7001
|
if (!Array.isArray(items)) items = [];
|
|
6980
|
-
const
|
|
6981
|
-
if (
|
|
7002
|
+
const idx = items.findIndex(i => i.id === id);
|
|
7003
|
+
if (idx === -1) { result = { code: 404, body: { error: 'item not found' } }; return items; }
|
|
7004
|
+
const item = items[idx];
|
|
6982
7005
|
if (item.status === WI_STATUS.DISPATCHED) { result = { code: 400, body: { error: 'Cannot edit dispatched items' } }; return items; }
|
|
6983
7006
|
|
|
6984
7007
|
if (title !== undefined) item.title = title;
|
|
@@ -7010,10 +7033,32 @@ const server = http.createServer(async (req, res) => {
|
|
|
7010
7033
|
}
|
|
7011
7034
|
}
|
|
7012
7035
|
item.updatedAt = new Date().toISOString();
|
|
7036
|
+
|
|
7037
|
+
// W-mrazefzz000358e3 — actually MOVE the item between work-items.json
|
|
7038
|
+
// files when the resolved target differs from where it lives today,
|
|
7039
|
+
// rather than just stamping item.project in place. Only trip this
|
|
7040
|
+
// when the resolved wiPath actually changes — re-assigning the same
|
|
7041
|
+
// project the item already lives in is a no-op move.
|
|
7042
|
+
if (projectMove && path.resolve(projectMove.wiPath) !== path.resolve(wiPath)) {
|
|
7043
|
+
if (projectMove.projectName) item.project = projectMove.projectName;
|
|
7044
|
+
else delete item.project;
|
|
7045
|
+
movedItem = item;
|
|
7046
|
+
items.splice(idx, 1);
|
|
7047
|
+
}
|
|
7048
|
+
|
|
7013
7049
|
result = { code: 200, body: { ok: true, item } };
|
|
7014
7050
|
return items;
|
|
7015
7051
|
});
|
|
7016
7052
|
if (!result) return jsonReply(res, 500, { error: 'unexpected state' });
|
|
7053
|
+
|
|
7054
|
+
if (movedItem) {
|
|
7055
|
+
mutateJsonFileLocked(projectMove.wiPath, (targetItems) => {
|
|
7056
|
+
if (!Array.isArray(targetItems)) targetItems = [];
|
|
7057
|
+
targetItems.push(movedItem);
|
|
7058
|
+
return targetItems;
|
|
7059
|
+
});
|
|
7060
|
+
}
|
|
7061
|
+
|
|
7017
7062
|
// Clear stale pending dispatch entries outside lock
|
|
7018
7063
|
if (agentChanged) cleanDispatchEntries(d => d.meta?.item?.id === id);
|
|
7019
7064
|
return jsonReply(res, result.code, result.body);
|
|
@@ -9886,10 +9931,20 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
9886
9931
|
* test enforces engine.js does not import cc-worker-pool).
|
|
9887
9932
|
*/
|
|
9888
9933
|
function _invokeCcStream({ prompt, sessionId, liveState, toolUses, model, effort, maxTurns, engineConfig, systemPrompt = CC_STATIC_SYSTEM_PROMPT, tabId, images }) {
|
|
9889
|
-
|
|
9890
|
-
|
|
9891
|
-
|
|
9892
|
-
|
|
9934
|
+
// W-mray463s001zcee2 — image-bearing turns bypass the worker pool.
|
|
9935
|
+
// Copilot itself supports images fine (imageInput: true, `--attachment
|
|
9936
|
+
// <path>` in engine/runtimes/copilot.js buildArgs), but the ACP worker-pool
|
|
9937
|
+
// protocol (engine/cc-worker-pool.js session/prompt) only ever sends
|
|
9938
|
+
// `[{ type: 'text', text: prompt }]` — it has no image/attachment
|
|
9939
|
+
// content-block support today. That is a worker-pool PROTOCOL gap, not a
|
|
9940
|
+
// Copilot capability gap (the old comment here claiming "copilot has
|
|
9941
|
+
// imageInput:false" was factually wrong). Until the pool's ACP session
|
|
9942
|
+
// protocol is extended to carry attachments, route image turns around the
|
|
9943
|
+
// pool for THIS TURN ONLY: cold-spawn a one-off CLI process via the
|
|
9944
|
+
// already-working --attachment path below, while image-less turns keep
|
|
9945
|
+
// using the fast warm pool.
|
|
9946
|
+
const hasImages = Array.isArray(images) && images.length > 0;
|
|
9947
|
+
if (!hasImages && shared.resolveCcUseWorkerPool(engineConfig)) {
|
|
9893
9948
|
return _invokeCcStreamViaPool({ prompt, liveState, toolUses, model, effort, engineConfig, systemPrompt, tabId });
|
|
9894
9949
|
}
|
|
9895
9950
|
const { callLLMStreaming } = require('./engine/llm');
|
|
@@ -13514,7 +13569,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
13514
13569
|
|
|
13515
13570
|
// Work items
|
|
13516
13571
|
{ method: 'POST', path: '/api/work-items', desc: 'Create a new work item', params: 'title, type?, description?, priority?, project?, agent?, agents?, scope?, references?, acceptanceCriteria?, skipPr?, oneShot?, meta?, meta.pr_followup?, meta.workdir?, X-Minions-Agent?, X-Minions-Origin-Wi?', handler: handleWorkItemsCreate },
|
|
13517
|
-
{ method: 'POST', path: '/api/work-items/update', desc: 'Edit a pending/failed work item', params: 'id, source?, title?, description?, type?, priority?, agent?, references?, acceptanceCriteria?, depends_on?, workdir?, meta?', handler: handleWorkItemsUpdate },
|
|
13572
|
+
{ method: 'POST', path: '/api/work-items/update', desc: 'Edit a pending/failed work item', params: 'id, source?, title?, description?, type?, priority?, agent?, project?, references?, acceptanceCriteria?, depends_on?, workdir?, meta?', handler: handleWorkItemsUpdate },
|
|
13518
13573
|
{ method: 'POST', path: '/api/work-items/retry', desc: 'Reset a failed/dispatched item to pending', params: 'id, source?', handler: handleWorkItemsRetry },
|
|
13519
13574
|
{ method: 'POST', path: '/api/work-items/delete', desc: 'Remove a work item, kill agent, clear dispatch', params: 'id, source?', handler: handleWorkItemsDelete },
|
|
13520
13575
|
{ method: 'POST', path: '/api/work-items/cancel', desc: 'Cancel a work item, kill agent, clear dispatch', params: 'id, source?, reason?', handler: handleWorkItemsCancel },
|
package/docs/command-center.md
CHANGED
|
@@ -65,9 +65,11 @@ Any violation rejects the **whole turn** with a typed error envelope (`code: 'in
|
|
|
65
65
|
| Runtime | `imageInput` | Behavior |
|
|
66
66
|
|---------|--------------|----------|
|
|
67
67
|
| claude | `true` | Images delivered as an Anthropic Messages `content[]` envelope of base64 blocks over stream-json (`claude.buildPrompt` + `--input-format stream-json` in `claude.buildArgs`). |
|
|
68
|
-
| copilot | `true` | Images materialized to tmp files and passed as `--attachment <path>` (W-mqv7324u0021db5d).
|
|
68
|
+
| copilot | `true` | Images materialized to tmp files and passed as `--attachment <path>` (W-mqv7324u0021db5d). |
|
|
69
69
|
| codex | `false` | Degraded — same typed `model-unavailable` envelope. |
|
|
70
70
|
|
|
71
|
+
**Worker-pool interaction (W-mray463s001zcee2).** The opt-in Copilot ACP worker pool (`engine.ccUseWorkerPool: true`, default ON for Copilot CC) is a **separate protocol path** from the table above — `engine/cc-worker-pool.js`'s `session/prompt` call only ever sends a single text content block (`[{ type: 'text', text: prompt }]`) and has no image/attachment content-block support today. This used to mean image turns were silently dropped whenever the pool was active, with a comment incorrectly blaming a Copilot capability gap (`imageInput:false`) that doesn't exist — Copilot's `imageInput` is `true` and fully supports images on the direct spawn path. The fix: `_invokeCcStream` (dashboard.js) now checks for a non-empty `images` array **before** routing through `resolveCcUseWorkerPool` — image-bearing turns bypass the warm pool for that turn only and cold-spawn a one-off CLI process via the working `--attachment` path (same as the non-pooled path always used), while image-less turns keep using the fast warm pool. If `engine/cc-worker-pool.js`'s ACP session protocol is later extended to carry attachments (Option A), this per-turn bypass in `_invokeCcStream` should be revisited/removed.
|
|
72
|
+
|
|
71
73
|
`_resolveImageOpts` (in `engine/llm.js`) is pure and unit-tested: it forwards the `images` list only when `runtime.capabilities.imageInput` is truthy, otherwise returns the typed error so CC/doc-chat surface the envelope instead of a silently-text-only reply. `_spawnProcess` re-applies the same gate (`if (!caps.imageInput) adapterOpts.images = undefined`) as defense in depth. Image **filenames** are run through the untrusted-input fence (`buildSource('cc-image-filename', …)`) before they reach prompt text, since they are user-supplied.
|
|
72
74
|
|
|
73
75
|
**No new `engine.*` flag.** The limits above are module-level constants in `dashboard.js` (`CC_IMAGE_MAX_COUNT`, `CC_IMAGE_MAX_DECODED_BYTES`, `CC_IMAGE_MIME_ALLOWLIST`), not config keys; `engine/shared.js` `ENGINE_DEFAULTS` was not touched. Per CLAUDE.md Best Practice #9 (Settings parity), no Settings toggle is added because no new `engine.*` flag was introduced. Runtime selection that determines whether images are accepted is the existing `engine.ccCli` / `ccModel` override, which already has a Settings control.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2347",
|
|
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"
|