@yemi33/minions 0.1.1938 → 0.1.1940

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.
@@ -60,7 +60,9 @@ function formatToolSummary(name, input) {
60
60
  }
61
61
  default: {
62
62
  var keys = Object.keys(inp);
63
- if (keys.length === 0) return escHtml(name) + '()';
63
+ // No-input case (e.g. ACP chips that carry their full label in `name`
64
+ // like "Fetch /api/status") — render the name verbatim, no parens.
65
+ if (keys.length === 0) return escHtml(name);
64
66
  var firstKey = keys[0];
65
67
  var firstVal = String(inp[firstKey] || '');
66
68
  if (firstVal.length > 40) firstVal = firstVal.slice(0, 37) + '...';
@@ -1,6 +1,37 @@
1
1
  # Distribution & Publishing
2
2
 
3
- Minions is distributed as an npm package (`@yemi33/minions`) from a sanitized package boundary.
3
+ Minions is distributed as an npm package (`@yemi33/minions`) from a sanitized package boundary. The source lives across three GitHub remotes, with a strict one-way port direction (see [Three-Remote Topology](#three-remote-topology)).
4
+
5
+ ## Three-Remote Topology
6
+
7
+ | Remote (local name on `D:/squad`) | URL | Role |
8
+ |-----------------------------------|-----|------|
9
+ | `origin` | `https://github.com/yemi33/minions` | **Authoring source of truth.** All normal code changes (engine, dashboard, playbooks, agents, etc.) land here first. Triggers npm publish + downstream mirrors. |
10
+ | `emu` | `https://github.com/yemishin_microsoft/minions` | Microsoft-identity mirror of `yemi33/minions`. Automated via `.github/workflows/mirror-to-emu.yml`. |
11
+ | `opg` | `https://github.com/opg-microsoft/minions` | **Compliant store** under the `opg-microsoft` org. Automated mirror to a sync branch via `.github/workflows/mirror-to-opg.yml`; `main` is reconciled by a maintainer PR because it carries enterprise/compliance-only commits (see below). |
12
+
13
+ ### Port direction
14
+
15
+ **Strictly one-way: `yemi33` → `emu`, `yemi33` → `opg`.**
16
+
17
+ - **Do NOT port from `emu` or `opg` back into `yemi33`.** Their `main` branches may carry org-specific compliance content (`.github/policies/*`, `.github/acl/*`, `.github/compliance/*`, JIT access policy, internal access lists, MS-org issue templates) that has no business in the personal-fork authoring source.
18
+ - **Direct pushes to `opg-microsoft/minions` are allowed for enterprise/compliance-specific changes only.** Examples: editing `.github/policies/jit.yml`, updating `.github/acl/access.yml`, modifying `.github/compliance/inventory.yml`. These changes stay on `opg` and are not backported.
19
+ - Other teams (Microsoft infra, compliance review) may also push to `opg-microsoft/minions` directly. Treat its `main` as potentially ahead of `yemi33`/`emu` on policy files.
20
+
21
+ ### Why opg can't use the same direct-mirror pattern as emu
22
+
23
+ `mirror-to-emu.yml` does `git push emu HEAD:master` — direct overwrite, because `emu/master` is meant to be a 1:1 reflection of `yemi33/master`. `opg-microsoft/minions` is different: its `main` carries enterprise-only commits that don't exist on `yemi33/master`, so a force-push to `opg/main` would destroy them. Instead, `mirror-to-opg.yml` force-pushes `yemi33/master` to `opg/sync/yemi33-master` (a dedicated bot-owned branch), and a maintainer opens or updates a PR from `sync/yemi33-master` → `main` for review. The first such PR uses `--allow-unrelated-histories` to bridge the initial divergence; subsequent ones merge incrementally.
24
+
25
+ ### Required secrets on `yemi33/minions`
26
+
27
+ | Secret | Purpose | Workflow |
28
+ |--------|---------|----------|
29
+ | `NPM_TOKEN` | npm publish | `publish.yml` |
30
+ | `EMU_PUSH_TOKEN` | Push to `yemishin_microsoft/minions` | `mirror-to-emu.yml` |
31
+ | `EMU_PACKAGES_TOKEN` | Publish to `@yemishin_microsoft` internal registry | `publish-internal-github-packages.yml` |
32
+ | `OPG_PUSH_TOKEN` | Push to `opg-microsoft/minions` sync branch | `mirror-to-opg.yml` |
33
+
34
+ Each mirror workflow gracefully skips with a warning if its token secret is unset, so unconfigured downstreams never block the primary publish path.
4
35
 
5
36
  ## Distribution Boundary
6
37
 
@@ -252,9 +252,7 @@ class Worker {
252
252
  try { this.inflight.onChunk(text); } catch { /* swallow */ }
253
253
  }
254
254
  } else if (update.sessionUpdate === 'tool_call' && this.inflight.onToolUse) {
255
- // ACP `tool_call` (pending) → Claude-style {name, input} via
256
- // _mapAcpToolCallToToolUse so the dashboard's formatToolSummary
257
- // formatters (Bash → "$ <cmd>", etc.) work unchanged.
255
+ // ACP `tool_call` (pending) → chip label via _mapAcpToolCallToToolUse.
258
256
  const mapped = _mapAcpToolCallToToolUse(update);
259
257
  if (mapped) {
260
258
  try { this.inflight.onToolUse(mapped.name, mapped.input, update.toolCallId); }
@@ -447,50 +445,40 @@ function _extractChunkText(content) {
447
445
  // (Bash → "$ <cmd>", Read → "Reading <path>", etc.). Unknown kinds fall back
448
446
  // to ACP's human-readable `title` with the raw input attached, which renders
449
447
  // through the default `<title>(<key>: <val>)` formatter.
448
+ // Map an ACP `tool_call` notification to a chip label. Strategy:
449
+ //
450
+ // 1. Detect well-known shapes by rawInput field presence and route through
451
+ // formatToolSummary's Claude-tool formatters (Bash → "$ <cmd>",
452
+ // Grep → "Searching `pat` in path", Read → "Reading <path>"). Preserves
453
+ // the granular detail you actually want when reading the chip list.
454
+ //
455
+ // 2. Fall back to ACP's human-curated `title` for anything that doesn't
456
+ // match. Title is always populated and immune to field-name drift, so
457
+ // the empty-`$` failure mode (kind:execute with no `command`) becomes
458
+ // a clean "Find work item W-..." chip instead of a broken stub.
459
+ //
460
+ // Kind-based routing is intentionally NOT used — ACP overloads `kind:read`
461
+ // for both file-view and grep, and `kind:execute` sometimes arrives without
462
+ // a `command`. Field-detection on rawInput is more reliable.
450
463
  function _mapAcpToolCallToToolUse(update) {
451
464
  if (!update || update.sessionUpdate !== 'tool_call') return null;
452
465
  const rawInput = (update.rawInput && typeof update.rawInput === 'object') ? update.rawInput : {};
453
- const kind = String(update.kind || '').toLowerCase();
454
- const title = update.title || '';
455
-
456
- // Field-name normalization: Copilot ACP and Claude tool_use use different
457
- // keys for the same concept (Copilot `path`, Claude `file_path`). Normalize
458
- // here so the dashboard's formatToolSummary — written against Claude's
459
- // names — produces the same chip text on both runtimes.
460
- const filePath = rawInput.file_path || rawInput.path || rawInput.filePath || '';
461
-
462
- // Pattern (Grep) — Copilot uses `paths` (plural) for the search scope where
463
- // Claude's Grep takes `path`.
464
- if (typeof rawInput.pattern === 'string') {
465
- return {
466
- name: 'Grep',
467
- input: { pattern: rawInput.pattern, path: rawInput.paths || rawInput.path || '.' },
468
- };
469
- }
466
+ const title = update.title || update.kind || 'Tool';
470
467
 
471
- switch (kind) {
472
- case 'execute':
473
- return { name: 'Bash', input: rawInput };
474
- case 'read':
475
- // ACP overloads `read` for both file-view and grep the pattern check
476
- // above already handled grep, so this branch is the file-view case.
477
- return { name: 'Read', input: { file_path: filePath } };
478
- case 'edit':
479
- return { name: 'Edit', input: { file_path: filePath } };
480
- case 'search':
481
- // Pattern check above handled the grep case; arriving here means glob.
482
- return { name: 'Glob', input: rawInput };
483
- case 'fetch':
484
- return { name: 'WebFetch', input: rawInput };
485
- case 'think':
486
- return { name: title || 'Think', input: rawInput };
487
- default:
488
- // Unknown kind — use ACP's human-readable title as the chip label and
489
- // drop rawInput so formatToolSummary's default branch shows just the
490
- // title (avoids `<title>(<key>: <val>)` clutter when the input shape
491
- // is unfamiliar).
492
- return { name: title || kind || 'Tool', input: {} };
468
+ if (typeof rawInput.command === 'string' && rawInput.command) {
469
+ return { name: 'Bash', input: { command: rawInput.command } };
470
+ }
471
+ if (typeof rawInput.pattern === 'string' && rawInput.pattern) {
472
+ return { name: 'Grep', input: { pattern: rawInput.pattern, path: rawInput.paths || rawInput.path || '.' } };
473
+ }
474
+ if (typeof rawInput.path === 'string' && rawInput.path) {
475
+ const isEdit = String(update.kind || '').toLowerCase() === 'edit';
476
+ return { name: isEdit ? 'Edit' : 'Read', input: { file_path: rawInput.path } };
477
+ }
478
+ if (typeof rawInput.url === 'string' && rawInput.url) {
479
+ return { name: 'WebFetch', input: { url: rawInput.url } };
493
480
  }
481
+ return { name: title, input: {} };
494
482
  }
495
483
 
496
484
  // ── Public API ────────────────────────────────────────────────────────────
@@ -0,0 +1,5 @@
1
+ {
2
+ "runtime": "copilot",
3
+ "models": null,
4
+ "cachedAt": "2026-05-14T21:44:50.675Z"
5
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1938",
3
+ "version": "0.1.1940",
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"