oh-my-copilot 4.13.73 → 4.13.79
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-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/bridge/cli.cjs +198 -66
- package/bridge/runtime-cli.cjs +68 -4
- package/bridge/team.js +85 -5
- package/dist/__tests__/hud-cache-wrapper.test.js +3 -1
- package/dist/__tests__/hud-cache-wrapper.test.js.map +1 -1
- package/dist/__tests__/pre-tool-enforcer.test.js +45 -0
- package/dist/__tests__/pre-tool-enforcer.test.js.map +1 -1
- package/dist/cli/__tests__/launch.test.js +118 -3
- package/dist/cli/__tests__/launch.test.js.map +1 -1
- package/dist/cli/__tests__/tmux-clipboard.test.d.ts +2 -0
- package/dist/cli/__tests__/tmux-clipboard.test.d.ts.map +1 -0
- package/dist/cli/__tests__/tmux-clipboard.test.js +66 -0
- package/dist/cli/__tests__/tmux-clipboard.test.js.map +1 -0
- package/dist/cli/autoresearch-guided.d.ts.map +1 -1
- package/dist/cli/autoresearch-guided.js +9 -0
- package/dist/cli/autoresearch-guided.js.map +1 -1
- package/dist/cli/commands/__tests__/team-role-shorthand.test.js +2 -2
- package/dist/cli/commands/__tests__/team-role-shorthand.test.js.map +1 -1
- package/dist/cli/commands/__tests__/team.test.js +83 -1
- package/dist/cli/commands/__tests__/team.test.js.map +1 -1
- package/dist/cli/commands/team.d.ts +12 -1
- package/dist/cli/commands/team.d.ts.map +1 -1
- package/dist/cli/commands/team.js +72 -38
- package/dist/cli/commands/team.js.map +1 -1
- package/dist/cli/launch.d.ts.map +1 -1
- package/dist/cli/launch.js +33 -1
- package/dist/cli/launch.js.map +1 -1
- package/dist/cli/tmux-clipboard.d.ts +9 -0
- package/dist/cli/tmux-clipboard.d.ts.map +1 -0
- package/dist/cli/tmux-clipboard.js +42 -0
- package/dist/cli/tmux-clipboard.js.map +1 -0
- package/dist/installer/__tests__/hud-cache-wrapper.test.js +33 -2
- package/dist/installer/__tests__/hud-cache-wrapper.test.js.map +1 -1
- package/dist/team/__tests__/api-interop.cwd-resolution.test.js +24 -0
- package/dist/team/__tests__/api-interop.cwd-resolution.test.js.map +1 -1
- package/dist/team/__tests__/runtime-v2.dispatch.test.js +27 -2
- package/dist/team/__tests__/runtime-v2.dispatch.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.create-team.test.js +4 -0
- package/dist/team/__tests__/tmux-session.create-team.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +34 -1
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-canonicalization.test.js +11 -0
- package/dist/team/__tests__/worker-canonicalization.test.js.map +1 -1
- package/dist/team/runtime-v2.d.ts.map +1 -1
- package/dist/team/runtime-v2.js +19 -1
- package/dist/team/runtime-v2.js.map +1 -1
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js +19 -1
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +19 -1
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-canonicalization.js +1 -1
- package/dist/team/worker-canonicalization.js.map +1 -1
- package/docs/copilot-instructions.md +1 -1
- package/package.json +1 -1
- package/scripts/lib/hud-cache-wrapper.sh +33 -23
- package/scripts/pre-tool-enforcer.mjs +3 -0
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
{
|
|
11
11
|
"name": "oh-my-copilot",
|
|
12
12
|
"description": "Copilot CLI native multi-agent orchestration with intelligent model routing, 18 agent variants, and 32 powerful skills. Zero learning curve. Maximum power.",
|
|
13
|
-
"version": "4.13.
|
|
13
|
+
"version": "4.13.79",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "Robin Norberg",
|
|
16
16
|
"email": "github@platypus.se"
|
|
@@ -27,5 +27,5 @@
|
|
|
27
27
|
]
|
|
28
28
|
}
|
|
29
29
|
],
|
|
30
|
-
"version": "4.13.
|
|
30
|
+
"version": "4.13.79"
|
|
31
31
|
}
|
package/bridge/cli.cjs
CHANGED
|
@@ -20540,7 +20540,7 @@ function canonicalizeTeamConfigWorkers(config2) {
|
|
|
20540
20540
|
return {
|
|
20541
20541
|
...config2,
|
|
20542
20542
|
workers,
|
|
20543
|
-
worker_count: workers.length
|
|
20543
|
+
worker_count: workers.length > 0 ? workers.length : config2.worker_count ?? 0
|
|
20544
20544
|
};
|
|
20545
20545
|
}
|
|
20546
20546
|
var init_worker_canonicalization = __esm({
|
|
@@ -34369,6 +34369,7 @@ function isTeamTask(value) {
|
|
|
34369
34369
|
}
|
|
34370
34370
|
async function withLock(lockDir, fn) {
|
|
34371
34371
|
const STALE_MS = 3e4;
|
|
34372
|
+
await (0, import_promises5.mkdir)((0, import_node_path5.dirname)(lockDir), { recursive: true });
|
|
34372
34373
|
try {
|
|
34373
34374
|
await (0, import_promises5.mkdir)(lockDir, { recursive: false });
|
|
34374
34375
|
} catch (err) {
|
|
@@ -34580,7 +34581,22 @@ async function teamClaimTask(teamName, taskId, workerName2, expectedVersion, cwd
|
|
|
34580
34581
|
teamName,
|
|
34581
34582
|
cwd,
|
|
34582
34583
|
readTask: teamReadTask,
|
|
34583
|
-
readTeamConfig:
|
|
34584
|
+
readTeamConfig: (async (tn, c) => {
|
|
34585
|
+
const cfg = await teamReadConfig(tn, c);
|
|
34586
|
+
if (!cfg) return null;
|
|
34587
|
+
if (cfg.workers.length > 0) return cfg;
|
|
34588
|
+
const match = /^worker-(\d+)$/.exec(workerName2);
|
|
34589
|
+
const workerIndex = match ? Number.parseInt(match[1], 10) : 0;
|
|
34590
|
+
if (workerIndex >= 1 && workerIndex <= (cfg.worker_count ?? 0)) {
|
|
34591
|
+
return {
|
|
34592
|
+
...cfg,
|
|
34593
|
+
workers: Array.from({ length: cfg.worker_count ?? 0 }, (_, index) => ({
|
|
34594
|
+
name: `worker-${index + 1}`
|
|
34595
|
+
}))
|
|
34596
|
+
};
|
|
34597
|
+
}
|
|
34598
|
+
return cfg;
|
|
34599
|
+
}),
|
|
34584
34600
|
withTaskClaimLock,
|
|
34585
34601
|
normalizeTask,
|
|
34586
34602
|
isTerminalTaskStatus: isTerminalTeamTaskStatus,
|
|
@@ -35548,6 +35564,50 @@ var init_model_contract = __esm({
|
|
|
35548
35564
|
}
|
|
35549
35565
|
});
|
|
35550
35566
|
|
|
35567
|
+
// src/cli/tmux-clipboard.ts
|
|
35568
|
+
function hasUniversalClipboardTerminalFeature(features) {
|
|
35569
|
+
return features.split(/\r?\n|,/).map((feature) => feature.trim()).some((feature) => feature === UNIVERSAL_CLIPBOARD_FEATURE || feature.startsWith(`${UNIVERSAL_CLIPBOARD_FEATURE}:`));
|
|
35570
|
+
}
|
|
35571
|
+
function configureTmuxClipboardForSession(sessionName2, opts) {
|
|
35572
|
+
tmuxExec(["set-option", "-t", sessionName2, "set-clipboard", "on"], opts);
|
|
35573
|
+
let terminalFeatures = "";
|
|
35574
|
+
try {
|
|
35575
|
+
terminalFeatures = String(tmuxExec(["show-options", "-t", sessionName2, "-v", "terminal-features"], opts) ?? "");
|
|
35576
|
+
} catch {
|
|
35577
|
+
terminalFeatures = "";
|
|
35578
|
+
}
|
|
35579
|
+
if (!hasUniversalClipboardTerminalFeature(terminalFeatures)) {
|
|
35580
|
+
tmuxExec(["set-option", "-at", sessionName2, "terminal-features", `,${UNIVERSAL_CLIPBOARD_FEATURE}`], opts);
|
|
35581
|
+
}
|
|
35582
|
+
}
|
|
35583
|
+
function configureTmuxClipboardForCurrentSession(opts) {
|
|
35584
|
+
const sessionName2 = String(tmuxExec(["display-message", "-p", "#S"], opts) ?? "").trim();
|
|
35585
|
+
if (sessionName2) {
|
|
35586
|
+
configureTmuxClipboardForSession(sessionName2, opts);
|
|
35587
|
+
}
|
|
35588
|
+
}
|
|
35589
|
+
async function configureTmuxClipboardForSessionAsync(sessionName2, opts) {
|
|
35590
|
+
await tmuxExecAsync(["set-option", "-t", sessionName2, "set-clipboard", "on"], opts);
|
|
35591
|
+
let terminalFeatures = "";
|
|
35592
|
+
try {
|
|
35593
|
+
const result = await tmuxExecAsync(["show-options", "-t", sessionName2, "-v", "terminal-features"], opts);
|
|
35594
|
+
terminalFeatures = String(result.stdout ?? "");
|
|
35595
|
+
} catch {
|
|
35596
|
+
terminalFeatures = "";
|
|
35597
|
+
}
|
|
35598
|
+
if (!hasUniversalClipboardTerminalFeature(terminalFeatures)) {
|
|
35599
|
+
await tmuxExecAsync(["set-option", "-at", sessionName2, "terminal-features", `,${UNIVERSAL_CLIPBOARD_FEATURE}`], opts);
|
|
35600
|
+
}
|
|
35601
|
+
}
|
|
35602
|
+
var UNIVERSAL_CLIPBOARD_FEATURE;
|
|
35603
|
+
var init_tmux_clipboard = __esm({
|
|
35604
|
+
"src/cli/tmux-clipboard.ts"() {
|
|
35605
|
+
"use strict";
|
|
35606
|
+
init_tmux_utils();
|
|
35607
|
+
UNIVERSAL_CLIPBOARD_FEATURE = "*:clipboard";
|
|
35608
|
+
}
|
|
35609
|
+
});
|
|
35610
|
+
|
|
35551
35611
|
// src/team/tmux-session.ts
|
|
35552
35612
|
var tmux_session_exports = {};
|
|
35553
35613
|
__export(tmux_session_exports, {
|
|
@@ -35809,6 +35869,10 @@ function createSession(teamName, workerName2, workingDirectory) {
|
|
|
35809
35869
|
args.push("-c", workingDirectory);
|
|
35810
35870
|
}
|
|
35811
35871
|
tmuxExec(args, { stripTmux: true, stdio: "pipe", timeout: 5e3 });
|
|
35872
|
+
try {
|
|
35873
|
+
configureTmuxClipboardForSession(name, { stripTmux: true, stdio: "pipe", timeout: 5e3 });
|
|
35874
|
+
} catch {
|
|
35875
|
+
}
|
|
35812
35876
|
return name;
|
|
35813
35877
|
}
|
|
35814
35878
|
function killSession(teamName, workerName2) {
|
|
@@ -35935,6 +35999,10 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
35935
35999
|
}
|
|
35936
36000
|
const teamTarget = sessionAndWindow;
|
|
35937
36001
|
const resolvedSessionName = teamTarget.split(":")[0];
|
|
36002
|
+
try {
|
|
36003
|
+
await configureTmuxClipboardForSessionAsync(resolvedSessionName);
|
|
36004
|
+
} catch {
|
|
36005
|
+
}
|
|
35938
36006
|
const workerPaneIds = [];
|
|
35939
36007
|
if (workerCount <= 0) {
|
|
35940
36008
|
try {
|
|
@@ -36017,10 +36085,11 @@ function paneHasTrustPrompt(captured) {
|
|
|
36017
36085
|
function paneHasClaudeStartupBanner(captured) {
|
|
36018
36086
|
const lines = captured.split("\n").map((line) => line.replace(/\r/g, "").trim()).filter((line) => line.length > 0).slice(-20);
|
|
36019
36087
|
const lastPromptIndex = lines.findLastIndex((line) => /^\s*[›>❯]\s*/u.test(line));
|
|
36088
|
+
if (lastPromptIndex >= 0) return false;
|
|
36020
36089
|
const lastStartupBannerIndex = lines.findLastIndex(
|
|
36021
36090
|
(line) => /bypass\s+permissions\s+on/i.test(line) || /shift\+tab\s+to\s+cycle/i.test(line) || /^⏵⏵\s+/.test(line)
|
|
36022
36091
|
);
|
|
36023
|
-
return lastStartupBannerIndex >= 0
|
|
36092
|
+
return lastStartupBannerIndex >= 0;
|
|
36024
36093
|
}
|
|
36025
36094
|
function paneIsBootstrapping(captured) {
|
|
36026
36095
|
if (paneHasClaudeStartupBanner(captured)) return true;
|
|
@@ -36306,6 +36375,7 @@ var init_tmux_session = __esm({
|
|
|
36306
36375
|
import_promises8 = __toESM(require("fs/promises"), 1);
|
|
36307
36376
|
init_team_name();
|
|
36308
36377
|
init_tmux_utils();
|
|
36378
|
+
init_tmux_clipboard();
|
|
36309
36379
|
sleep4 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
36310
36380
|
TMUX_SESSION_PREFIX = "omcp-team";
|
|
36311
36381
|
SUPPORTED_POSIX_SHELLS = /* @__PURE__ */ new Set(["sh", "bash", "zsh", "fish", "ksh"]);
|
|
@@ -39345,13 +39415,27 @@ async function spawnV2Worker(opts) {
|
|
|
39345
39415
|
};
|
|
39346
39416
|
}
|
|
39347
39417
|
if (opts.agentType === "claude") {
|
|
39348
|
-
|
|
39418
|
+
let settled = await waitForWorkerStartupEvidence(
|
|
39349
39419
|
opts.teamName,
|
|
39350
39420
|
opts.workerName,
|
|
39351
39421
|
opts.taskId,
|
|
39352
39422
|
opts.cwd,
|
|
39353
39423
|
6
|
|
39354
39424
|
);
|
|
39425
|
+
for (let attempt = 1; !settled && attempt <= 4; attempt++) {
|
|
39426
|
+
try {
|
|
39427
|
+
await tmuxExecAsync(["send-keys", "-t", paneId, "Enter"]);
|
|
39428
|
+
} catch {
|
|
39429
|
+
break;
|
|
39430
|
+
}
|
|
39431
|
+
settled = await waitForWorkerStartupEvidence(
|
|
39432
|
+
opts.teamName,
|
|
39433
|
+
opts.workerName,
|
|
39434
|
+
opts.taskId,
|
|
39435
|
+
opts.cwd,
|
|
39436
|
+
12
|
|
39437
|
+
);
|
|
39438
|
+
}
|
|
39355
39439
|
if (!settled) {
|
|
39356
39440
|
return {
|
|
39357
39441
|
paneId,
|
|
@@ -39505,6 +39589,7 @@ async function startTeamV2(config2) {
|
|
|
39505
39589
|
status: "pending",
|
|
39506
39590
|
owner: null,
|
|
39507
39591
|
result: null,
|
|
39592
|
+
...config2.tasks[i].role ? { role: config2.tasks[i].role } : {},
|
|
39508
39593
|
...config2.tasks[i].delegation ? { delegation: config2.tasks[i].delegation } : {},
|
|
39509
39594
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
39510
39595
|
}, null, 2), "utf-8");
|
|
@@ -39540,7 +39625,8 @@ async function startTeamV2(config2) {
|
|
|
39540
39625
|
const allocationTasks = unownedTaskIndices.map((idx) => ({
|
|
39541
39626
|
id: String(idx),
|
|
39542
39627
|
subject: config2.tasks[idx].subject,
|
|
39543
|
-
description: config2.tasks[idx].description
|
|
39628
|
+
description: config2.tasks[idx].description,
|
|
39629
|
+
...config2.tasks[idx].role ? { role: config2.tasks[idx].role } : {}
|
|
39544
39630
|
}));
|
|
39545
39631
|
const allocationWorkers = workerNames.map((name, i) => ({
|
|
39546
39632
|
name,
|
|
@@ -51711,9 +51797,9 @@ function renderCwd(cwd, format = "relative", useHyperlinks = false) {
|
|
|
51711
51797
|
displayPath = cwd;
|
|
51712
51798
|
break;
|
|
51713
51799
|
case "folder": {
|
|
51714
|
-
const parent = (0,
|
|
51715
|
-
const folder = (0,
|
|
51716
|
-
displayPath = parent ? (0,
|
|
51800
|
+
const parent = (0, import_node_path14.basename)((0, import_node_path14.dirname)(cwd));
|
|
51801
|
+
const folder = (0, import_node_path14.basename)(cwd);
|
|
51802
|
+
displayPath = parent ? (0, import_node_path14.join)(parent, folder) : folder;
|
|
51717
51803
|
break;
|
|
51718
51804
|
}
|
|
51719
51805
|
default:
|
|
@@ -51726,12 +51812,12 @@ function renderCwd(cwd, format = "relative", useHyperlinks = false) {
|
|
|
51726
51812
|
}
|
|
51727
51813
|
return rendered;
|
|
51728
51814
|
}
|
|
51729
|
-
var import_node_os4,
|
|
51815
|
+
var import_node_os4, import_node_path14;
|
|
51730
51816
|
var init_cwd = __esm({
|
|
51731
51817
|
"src/hud/elements/cwd.ts"() {
|
|
51732
51818
|
"use strict";
|
|
51733
51819
|
import_node_os4 = require("node:os");
|
|
51734
|
-
|
|
51820
|
+
import_node_path14 = require("node:path");
|
|
51735
51821
|
init_colors();
|
|
51736
51822
|
}
|
|
51737
51823
|
});
|
|
@@ -51755,7 +51841,7 @@ var init_hostname = __esm({
|
|
|
51755
51841
|
|
|
51756
51842
|
// src/hud/elements/git.ts
|
|
51757
51843
|
function getGitRepoName(cwd) {
|
|
51758
|
-
const key = cwd ? (0,
|
|
51844
|
+
const key = cwd ? (0, import_node_path15.resolve)(cwd) : process.cwd();
|
|
51759
51845
|
const cached2 = repoCache.get(key);
|
|
51760
51846
|
if (cached2 && Date.now() < cached2.expiresAt) {
|
|
51761
51847
|
return cached2.value;
|
|
@@ -51782,7 +51868,7 @@ function getGitRepoName(cwd) {
|
|
|
51782
51868
|
return result;
|
|
51783
51869
|
}
|
|
51784
51870
|
function getGitBranch(cwd) {
|
|
51785
|
-
const key = cwd ? (0,
|
|
51871
|
+
const key = cwd ? (0, import_node_path15.resolve)(cwd) : process.cwd();
|
|
51786
51872
|
const cached2 = branchCache.get(key);
|
|
51787
51873
|
if (cached2 && Date.now() < cached2.expiresAt) {
|
|
51788
51874
|
return cached2.value;
|
|
@@ -51804,7 +51890,7 @@ function getGitBranch(cwd) {
|
|
|
51804
51890
|
return result;
|
|
51805
51891
|
}
|
|
51806
51892
|
function getWorktreeInfo(cwd) {
|
|
51807
|
-
const key = cwd ? (0,
|
|
51893
|
+
const key = cwd ? (0, import_node_path15.resolve)(cwd) : process.cwd();
|
|
51808
51894
|
const cached2 = worktreeCache.get(key);
|
|
51809
51895
|
if (cached2 && Date.now() < cached2.expiresAt) {
|
|
51810
51896
|
return cached2.value;
|
|
@@ -51820,18 +51906,18 @@ function getWorktreeInfo(cwd) {
|
|
|
51820
51906
|
try {
|
|
51821
51907
|
const gitDir = (0, import_node_child_process10.execSync)("git rev-parse --git-dir", execOpts).trim();
|
|
51822
51908
|
const gitCommonDir = (0, import_node_child_process10.execSync)("git rev-parse --git-common-dir", execOpts).trim();
|
|
51823
|
-
let resolvedGitDir = (0,
|
|
51824
|
-
let resolvedCommonDir = (0,
|
|
51909
|
+
let resolvedGitDir = (0, import_node_path15.resolve)(key, gitDir);
|
|
51910
|
+
let resolvedCommonDir = (0, import_node_path15.resolve)(key, gitCommonDir);
|
|
51825
51911
|
try {
|
|
51826
|
-
resolvedGitDir = (0,
|
|
51912
|
+
resolvedGitDir = (0, import_node_fs11.realpathSync)(resolvedGitDir);
|
|
51827
51913
|
} catch {
|
|
51828
51914
|
}
|
|
51829
51915
|
try {
|
|
51830
|
-
resolvedCommonDir = (0,
|
|
51916
|
+
resolvedCommonDir = (0, import_node_fs11.realpathSync)(resolvedCommonDir);
|
|
51831
51917
|
} catch {
|
|
51832
51918
|
}
|
|
51833
51919
|
if (resolvedGitDir !== resolvedCommonDir) {
|
|
51834
|
-
result = { isWorktree: true, worktreeName: (0,
|
|
51920
|
+
result = { isWorktree: true, worktreeName: (0, import_node_path15.basename)(resolvedGitDir) };
|
|
51835
51921
|
}
|
|
51836
51922
|
} catch {
|
|
51837
51923
|
}
|
|
@@ -51853,7 +51939,7 @@ function renderGitBranch(cwd) {
|
|
|
51853
51939
|
return `${dim("branch:")}${cyan(branch)}`;
|
|
51854
51940
|
}
|
|
51855
51941
|
function getGitStatusCounts(cwd) {
|
|
51856
|
-
const key = cwd ? (0,
|
|
51942
|
+
const key = cwd ? (0, import_node_path15.resolve)(cwd) : process.cwd();
|
|
51857
51943
|
const cached2 = statusCache.get(key);
|
|
51858
51944
|
if (cached2 && Date.now() < cached2.expiresAt) {
|
|
51859
51945
|
return cached2.value;
|
|
@@ -51910,13 +51996,13 @@ function renderGitStatus(cwd, labels = DEFAULT_HUD_LABELS) {
|
|
|
51910
51996
|
if (behind > 0) parts.push(`${red(labels.behind)}${behind}`);
|
|
51911
51997
|
return parts.join(" ");
|
|
51912
51998
|
}
|
|
51913
|
-
var import_node_child_process10,
|
|
51999
|
+
var import_node_child_process10, import_node_fs11, import_node_path15, CACHE_TTL_MS3, repoCache, branchCache, worktreeCache, statusCache;
|
|
51914
52000
|
var init_git = __esm({
|
|
51915
52001
|
"src/hud/elements/git.ts"() {
|
|
51916
52002
|
"use strict";
|
|
51917
52003
|
import_node_child_process10 = require("node:child_process");
|
|
51918
|
-
|
|
51919
|
-
|
|
52004
|
+
import_node_fs11 = require("node:fs");
|
|
52005
|
+
import_node_path15 = require("node:path");
|
|
51920
52006
|
init_colors();
|
|
51921
52007
|
init_types4();
|
|
51922
52008
|
CACHE_TTL_MS3 = 3e4;
|
|
@@ -89095,13 +89181,15 @@ function inferDelegationPlanForTeamTask(text) {
|
|
|
89095
89181
|
|
|
89096
89182
|
// src/cli/commands/team.ts
|
|
89097
89183
|
init_loader();
|
|
89184
|
+
var import_node_fs8 = require("node:fs");
|
|
89185
|
+
var import_node_path11 = require("node:path");
|
|
89098
89186
|
var HELP_TOKENS = /* @__PURE__ */ new Set(["--help", "-h", "help"]);
|
|
89099
89187
|
var MIN_WORKER_COUNT = 1;
|
|
89100
89188
|
var MAX_WORKER_COUNT = 20;
|
|
89101
89189
|
var VALID_TEAM_CLI_AGENT_TYPES = /* @__PURE__ */ new Set(["claude", "copilot", "codex", "gemini"]);
|
|
89102
89190
|
var DEFAULT_TEAM_CLI_AGENT_TYPE = "claude";
|
|
89103
89191
|
var TEAM_HELP = `
|
|
89104
|
-
Usage: omcp team [N:agent-type[:role]] [--new-window] [--auto-merge] "<task description>"
|
|
89192
|
+
Usage: omcp team [N:agent-type[:role]] [--new-window] [--auto-merge] [--no-decompose] "<task description>"
|
|
89105
89193
|
omcp team status <team-name>
|
|
89106
89194
|
omcp team shutdown <team-name> [--force]
|
|
89107
89195
|
omcp team api <operation> [--input <json>] [--json]
|
|
@@ -89118,6 +89206,7 @@ Examples:
|
|
|
89118
89206
|
omcp team api send-message --input '{"team_name":"my-team","from_worker":"worker-1","to_worker":"leader-fixed","body":"ACK"}' --json
|
|
89119
89207
|
|
|
89120
89208
|
Auto-merge (v2-only):
|
|
89209
|
+
--no-decompose Treat the launch text as pre-authored/fixed worker scope; do not split by commas/lists.
|
|
89121
89210
|
--auto-merge Enable per-commit auto-merge to leader and auto-rebase fanout.
|
|
89122
89211
|
Each worker runs in a dedicated git worktree on omc-team/{team}/{worker}.
|
|
89123
89212
|
Bursts of rapid worker commits coalesce to a single merge of HEAD.
|
|
@@ -89195,7 +89284,8 @@ var TEAM_API_OPERATION_NOTES = {
|
|
|
89195
89284
|
var NUMBERED_LINE_RE = /^\s*\d+[.)]\s+(.+)$/;
|
|
89196
89285
|
var BULLETED_LINE_RE = /^\s*[-*•]\s+(.+)$/;
|
|
89197
89286
|
var CONJUNCTION_SPLIT_RE = /\s+(?:and|,\s*and|,)\s+/i;
|
|
89198
|
-
function resolveTeamFanoutLimit(requestedWorkerCount, _explicitAgentType,
|
|
89287
|
+
function resolveTeamFanoutLimit(requestedWorkerCount, _explicitAgentType, explicitWorkerCount, plan, noDecompose = false) {
|
|
89288
|
+
if (explicitWorkerCount !== void 0 || noDecompose) return requestedWorkerCount;
|
|
89199
89289
|
if (plan.strategy === "atomic") return requestedWorkerCount;
|
|
89200
89290
|
const subtaskCount = plan.subtasks.length;
|
|
89201
89291
|
if (subtaskCount > 0 && subtaskCount < requestedWorkerCount) {
|
|
@@ -89240,7 +89330,20 @@ function splitTaskString(task) {
|
|
|
89240
89330
|
};
|
|
89241
89331
|
}
|
|
89242
89332
|
function slugifyTask(task) {
|
|
89243
|
-
|
|
89333
|
+
const compact = task.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
89334
|
+
return compact.slice(0, 30).replace(/^-|-$/g, "") || "team-task";
|
|
89335
|
+
}
|
|
89336
|
+
function resolveAvailableTeamName(baseName, cwd) {
|
|
89337
|
+
const sanitizedBase = slugifyTask(baseName);
|
|
89338
|
+
const stateRoot2 = (0, import_node_path11.join)(cwd, ".omcp", "state", "team");
|
|
89339
|
+
const teamDir2 = (name) => (0, import_node_path11.join)(stateRoot2, name);
|
|
89340
|
+
if (!(0, import_node_fs8.existsSync)(teamDir2(sanitizedBase))) return sanitizedBase;
|
|
89341
|
+
for (let suffix = 2; suffix <= 99; suffix++) {
|
|
89342
|
+
const suffixText = `-${suffix}`;
|
|
89343
|
+
const candidate = `${sanitizedBase.slice(0, 30 - suffixText.length).replace(/-$/g, "")}${suffixText}`;
|
|
89344
|
+
if (!(0, import_node_fs8.existsSync)(teamDir2(candidate))) return candidate;
|
|
89345
|
+
}
|
|
89346
|
+
throw new Error(`Unable to allocate a fresh team name for ${sanitizedBase}; remove stale .omcp/state/team entries or choose a more specific launch task.`);
|
|
89244
89347
|
}
|
|
89245
89348
|
function getTeamWorkerIdentityFromEnv(env2 = process.env) {
|
|
89246
89349
|
const omg = typeof env2.OMC_TEAM_WORKER === "string" ? env2.OMC_TEAM_WORKER.trim() : "";
|
|
@@ -89280,6 +89383,7 @@ function parseTeamArgs(tokens, defaultAgentType = "copilot") {
|
|
|
89280
89383
|
let json2 = false;
|
|
89281
89384
|
let newWindow = false;
|
|
89282
89385
|
let autoMerge = process.env.OMC_TEAMS_AUTO_MERGE === "1";
|
|
89386
|
+
let noDecompose = false;
|
|
89283
89387
|
const normalizedDefaultAgentType = VALID_TEAM_CLI_AGENT_TYPES.has(defaultAgentType) ? defaultAgentType : DEFAULT_TEAM_CLI_AGENT_TYPE;
|
|
89284
89388
|
const filteredArgs = [];
|
|
89285
89389
|
for (const arg of args) {
|
|
@@ -89289,6 +89393,8 @@ function parseTeamArgs(tokens, defaultAgentType = "copilot") {
|
|
|
89289
89393
|
newWindow = true;
|
|
89290
89394
|
} else if (arg === "--auto-merge") {
|
|
89291
89395
|
autoMerge = true;
|
|
89396
|
+
} else if (arg === "--no-decompose" || arg === "--fixed-workers" || arg === "--preformed-plan") {
|
|
89397
|
+
noDecompose = true;
|
|
89292
89398
|
} else {
|
|
89293
89399
|
filteredArgs.push(arg);
|
|
89294
89400
|
}
|
|
@@ -89296,6 +89402,7 @@ function parseTeamArgs(tokens, defaultAgentType = "copilot") {
|
|
|
89296
89402
|
const first = filteredArgs[0] || "";
|
|
89297
89403
|
let role;
|
|
89298
89404
|
let specMatched = false;
|
|
89405
|
+
let explicitWorkerSpec = false;
|
|
89299
89406
|
if (first.includes(",")) {
|
|
89300
89407
|
const segments = first.split(",");
|
|
89301
89408
|
const parsedSegments = [];
|
|
@@ -89324,6 +89431,7 @@ function parseTeamArgs(tokens, defaultAgentType = "copilot") {
|
|
|
89324
89431
|
const uniqueRoles = [...new Set(roles)];
|
|
89325
89432
|
if (uniqueRoles.length === 1 && uniqueRoles[0]) role = uniqueRoles[0];
|
|
89326
89433
|
specMatched = true;
|
|
89434
|
+
explicitWorkerSpec = true;
|
|
89327
89435
|
filteredArgs.shift();
|
|
89328
89436
|
}
|
|
89329
89437
|
}
|
|
@@ -89338,6 +89446,7 @@ function parseTeamArgs(tokens, defaultAgentType = "copilot") {
|
|
|
89338
89446
|
agentType: normalized.agentType,
|
|
89339
89447
|
...role ? { role } : {}
|
|
89340
89448
|
}));
|
|
89449
|
+
explicitWorkerSpec = true;
|
|
89341
89450
|
filteredArgs.shift();
|
|
89342
89451
|
}
|
|
89343
89452
|
}
|
|
@@ -89350,7 +89459,32 @@ function parseTeamArgs(tokens, defaultAgentType = "copilot") {
|
|
|
89350
89459
|
throw new Error('Usage: omcp team [N:agent-type] "<task description>"');
|
|
89351
89460
|
}
|
|
89352
89461
|
const teamName = slugifyTask(task);
|
|
89353
|
-
return { workerCount, agentTypes, workerSpecs, role, task, teamName, json: json2, newWindow, autoMerge };
|
|
89462
|
+
return { workerCount, agentTypes, workerSpecs, role, task, teamName, json: json2, newWindow, autoMerge, explicitWorkerSpec, noDecompose };
|
|
89463
|
+
}
|
|
89464
|
+
function buildTeamLaunchTasks(parsed, decomposition, effectiveWorkerCount) {
|
|
89465
|
+
const tasks = [];
|
|
89466
|
+
if (parsed.explicitWorkerSpec && !parsed.noDecompose && decomposition.strategy !== "atomic" && decomposition.subtasks.length > 1 && decomposition.subtasks.length !== effectiveWorkerCount) {
|
|
89467
|
+
throw new Error(
|
|
89468
|
+
`Pre-authored task scope count (${decomposition.subtasks.length}) must match explicit worker count (${effectiveWorkerCount}); use --no-decompose to give every worker the full launch text.`
|
|
89469
|
+
);
|
|
89470
|
+
}
|
|
89471
|
+
const canUseDecomposition = !parsed.noDecompose && decomposition.strategy !== "atomic" && decomposition.subtasks.length > 1 && (!parsed.explicitWorkerSpec || decomposition.subtasks.length === effectiveWorkerCount);
|
|
89472
|
+
for (let i = 0; i < effectiveWorkerCount; i++) {
|
|
89473
|
+
const workerSpec = parsed.workerSpecs[i];
|
|
89474
|
+
const roleLabel = workerSpec?.role ? ` (${workerSpec.role})` : "";
|
|
89475
|
+
const source = canUseDecomposition ? decomposition.subtasks[i] : void 0;
|
|
89476
|
+
const description = source?.description ?? parsed.task;
|
|
89477
|
+
const subject = source?.subject ?? (effectiveWorkerCount === 1 ? parsed.task.slice(0, 80) : `Worker ${i + 1}${roleLabel}: ${parsed.task}`.slice(0, 80));
|
|
89478
|
+
const delegation = inferDelegationPlanForTeamTask(description);
|
|
89479
|
+
tasks.push({
|
|
89480
|
+
subject,
|
|
89481
|
+
description,
|
|
89482
|
+
owner: `worker-${i + 1}`,
|
|
89483
|
+
...workerSpec?.role ? { role: workerSpec.role } : {},
|
|
89484
|
+
...delegation ? { delegation } : {}
|
|
89485
|
+
});
|
|
89486
|
+
}
|
|
89487
|
+
return tasks;
|
|
89354
89488
|
}
|
|
89355
89489
|
function sampleValueForField(field) {
|
|
89356
89490
|
switch (field) {
|
|
@@ -89499,32 +89633,12 @@ async function handleTeamStart(parsed, cwd) {
|
|
|
89499
89633
|
const effectiveWorkerCount = resolveTeamFanoutLimit(
|
|
89500
89634
|
parsed.workerCount,
|
|
89501
89635
|
parsed.agentTypes[0],
|
|
89502
|
-
parsed.workerCount,
|
|
89503
|
-
decomposition
|
|
89636
|
+
parsed.explicitWorkerSpec ? parsed.workerCount : void 0,
|
|
89637
|
+
decomposition,
|
|
89638
|
+
parsed.noDecompose
|
|
89504
89639
|
);
|
|
89505
|
-
const tasks =
|
|
89506
|
-
|
|
89507
|
-
const subtasks = decomposition.subtasks.slice(0, effectiveWorkerCount);
|
|
89508
|
-
for (let i = 0; i < subtasks.length; i++) {
|
|
89509
|
-
const delegation = inferDelegationPlanForTeamTask(subtasks[i].description);
|
|
89510
|
-
tasks.push({
|
|
89511
|
-
subject: subtasks[i].subject,
|
|
89512
|
-
description: subtasks[i].description,
|
|
89513
|
-
owner: `worker-${i + 1}`,
|
|
89514
|
-
...delegation ? { delegation } : {}
|
|
89515
|
-
});
|
|
89516
|
-
}
|
|
89517
|
-
} else {
|
|
89518
|
-
for (let i = 0; i < effectiveWorkerCount; i++) {
|
|
89519
|
-
const delegation = inferDelegationPlanForTeamTask(parsed.task);
|
|
89520
|
-
tasks.push({
|
|
89521
|
-
subject: effectiveWorkerCount === 1 ? parsed.task.slice(0, 80) : `Worker ${i + 1}: ${parsed.task}`.slice(0, 80),
|
|
89522
|
-
description: parsed.task,
|
|
89523
|
-
owner: `worker-${i + 1}`,
|
|
89524
|
-
...delegation ? { delegation } : {}
|
|
89525
|
-
});
|
|
89526
|
-
}
|
|
89527
|
-
}
|
|
89640
|
+
const tasks = buildTeamLaunchTasks(parsed, decomposition, effectiveWorkerCount);
|
|
89641
|
+
const launchTeamName = resolveAvailableTeamName(parsed.teamName, cwd);
|
|
89528
89642
|
let rolePrompt;
|
|
89529
89643
|
if (parsed.role) {
|
|
89530
89644
|
const { loadAgentPrompt: loadAgentPrompt2 } = await Promise.resolve().then(() => (init_utils(), utils_exports));
|
|
@@ -89534,7 +89648,7 @@ async function handleTeamStart(parsed, cwd) {
|
|
|
89534
89648
|
if (isRuntimeV2Enabled2()) {
|
|
89535
89649
|
const { startTeamV2: startTeamV22, monitorTeamV2: monitorTeamV22 } = await Promise.resolve().then(() => (init_runtime_v2(), runtime_v2_exports));
|
|
89536
89650
|
const runtime2 = await startTeamV22({
|
|
89537
|
-
teamName:
|
|
89651
|
+
teamName: launchTeamName,
|
|
89538
89652
|
workerCount: effectiveWorkerCount,
|
|
89539
89653
|
agentTypes: parsed.agentTypes.slice(0, effectiveWorkerCount),
|
|
89540
89654
|
tasks,
|
|
@@ -89568,7 +89682,7 @@ async function handleTeamStart(parsed, cwd) {
|
|
|
89568
89682
|
}
|
|
89569
89683
|
const { startTeam: startTeam2, monitorTeam: monitorTeam2 } = await Promise.resolve().then(() => (init_runtime(), runtime_exports));
|
|
89570
89684
|
const runtime = await startTeam2({
|
|
89571
|
-
teamName:
|
|
89685
|
+
teamName: launchTeamName,
|
|
89572
89686
|
workerCount: effectiveWorkerCount,
|
|
89573
89687
|
agentTypes: parsed.agentTypes.slice(0, effectiveWorkerCount),
|
|
89574
89688
|
tasks,
|
|
@@ -89741,9 +89855,9 @@ async function teamCommand(args) {
|
|
|
89741
89855
|
var import_promises18 = require("node:fs/promises");
|
|
89742
89856
|
|
|
89743
89857
|
// src/goal-workflows/claude-goal-snapshot.ts
|
|
89744
|
-
var
|
|
89858
|
+
var import_node_fs9 = require("node:fs");
|
|
89745
89859
|
var import_promises16 = require("node:fs/promises");
|
|
89746
|
-
var
|
|
89860
|
+
var import_node_path12 = require("node:path");
|
|
89747
89861
|
var ClaudeGoalSnapshotError = class extends Error {
|
|
89748
89862
|
};
|
|
89749
89863
|
function safeObject(value) {
|
|
@@ -89796,8 +89910,8 @@ async function readClaudeGoalSnapshotInput(raw, cwd = process.cwd()) {
|
|
|
89796
89910
|
try {
|
|
89797
89911
|
return parseClaudeGoalSnapshot(JSON.parse(trimmed));
|
|
89798
89912
|
} catch {
|
|
89799
|
-
const path22 = (0,
|
|
89800
|
-
if (!(0,
|
|
89913
|
+
const path22 = (0, import_node_path12.resolve)(cwd, trimmed);
|
|
89914
|
+
if (!(0, import_node_fs9.existsSync)(path22)) {
|
|
89801
89915
|
throw new ClaudeGoalSnapshotError(`Claude goal snapshot is neither valid JSON nor a readable path: ${trimmed}`);
|
|
89802
89916
|
}
|
|
89803
89917
|
try {
|
|
@@ -89840,9 +89954,9 @@ function formatClaudeGoalReconciliation(reconciliation) {
|
|
|
89840
89954
|
}
|
|
89841
89955
|
|
|
89842
89956
|
// src/ultragoal/artifacts.ts
|
|
89843
|
-
var
|
|
89957
|
+
var import_node_fs10 = require("node:fs");
|
|
89844
89958
|
var import_promises17 = require("node:fs/promises");
|
|
89845
|
-
var
|
|
89959
|
+
var import_node_path13 = require("node:path");
|
|
89846
89960
|
var ULTRAGOAL_DIR = ".omcp/ultragoal";
|
|
89847
89961
|
var ULTRAGOAL_BRIEF = "brief.md";
|
|
89848
89962
|
var ULTRAGOAL_GOALS = "goals.json";
|
|
@@ -89853,19 +89967,19 @@ function iso(now = /* @__PURE__ */ new Date()) {
|
|
|
89853
89967
|
return now.toISOString();
|
|
89854
89968
|
}
|
|
89855
89969
|
function ultragoalDir(cwd) {
|
|
89856
|
-
return (0,
|
|
89970
|
+
return (0, import_node_path13.join)(cwd, ULTRAGOAL_DIR);
|
|
89857
89971
|
}
|
|
89858
89972
|
function ultragoalBriefPath(cwd) {
|
|
89859
|
-
return (0,
|
|
89973
|
+
return (0, import_node_path13.join)(ultragoalDir(cwd), ULTRAGOAL_BRIEF);
|
|
89860
89974
|
}
|
|
89861
89975
|
function ultragoalGoalsPath(cwd) {
|
|
89862
|
-
return (0,
|
|
89976
|
+
return (0, import_node_path13.join)(ultragoalDir(cwd), ULTRAGOAL_GOALS);
|
|
89863
89977
|
}
|
|
89864
89978
|
function ultragoalLedgerPath(cwd) {
|
|
89865
|
-
return (0,
|
|
89979
|
+
return (0, import_node_path13.join)(ultragoalDir(cwd), ULTRAGOAL_LEDGER);
|
|
89866
89980
|
}
|
|
89867
89981
|
function repoRelative(cwd, path22) {
|
|
89868
|
-
return (0,
|
|
89982
|
+
return (0, import_node_path13.relative)(cwd, path22).split("\\").join("/");
|
|
89869
89983
|
}
|
|
89870
89984
|
function cleanLine(line) {
|
|
89871
89985
|
return line.replace(/^\s*(?:[-*+]\s+|\d+[.)]\s+)/, "").trim();
|
|
@@ -89991,7 +90105,7 @@ async function writePlan(cwd, plan) {
|
|
|
89991
90105
|
`);
|
|
89992
90106
|
}
|
|
89993
90107
|
async function createUltragoalPlan(cwd, options) {
|
|
89994
|
-
if (!options.force && (0,
|
|
90108
|
+
if (!options.force && (0, import_node_fs10.existsSync)(ultragoalGoalsPath(cwd))) {
|
|
89995
90109
|
throw new UltragoalError(`Refusing to overwrite existing ${ULTRAGOAL_DIR}/${ULTRAGOAL_GOALS}; pass --force to recreate it.`);
|
|
89996
90110
|
}
|
|
89997
90111
|
const now = iso(options.now);
|
|
@@ -91188,6 +91302,7 @@ var import_path111 = require("path");
|
|
|
91188
91302
|
init_paths3();
|
|
91189
91303
|
init_config_dir();
|
|
91190
91304
|
init_tmux_utils();
|
|
91305
|
+
init_tmux_clipboard();
|
|
91191
91306
|
var MADMAX_FLAG = "--madmax";
|
|
91192
91307
|
var YOLO_FLAG = "--yolo";
|
|
91193
91308
|
var COPILOT_BYPASS_FLAG = "--dangerously-skip-permissions";
|
|
@@ -91364,6 +91479,10 @@ function runCopilot(cwd, args, sessionId) {
|
|
|
91364
91479
|
}
|
|
91365
91480
|
}
|
|
91366
91481
|
function runCopilotInsideTmux(cwd, args) {
|
|
91482
|
+
try {
|
|
91483
|
+
configureTmuxClipboardForCurrentSession({ stdio: "ignore" });
|
|
91484
|
+
} catch {
|
|
91485
|
+
}
|
|
91367
91486
|
try {
|
|
91368
91487
|
tmuxExec(["set-option", "mouse", "on"], { stdio: "ignore" });
|
|
91369
91488
|
} catch {
|
|
@@ -91424,7 +91543,20 @@ function runCopilotOutsideTmux(cwd, args, _sessionId) {
|
|
|
91424
91543
|
"-t",
|
|
91425
91544
|
sessionName2,
|
|
91426
91545
|
"mouse",
|
|
91427
|
-
"on"
|
|
91546
|
+
"on",
|
|
91547
|
+
// Enable OSC 52 clipboard forwarding so terminal-side copy-on-select keeps working.
|
|
91548
|
+
";",
|
|
91549
|
+
"set-option",
|
|
91550
|
+
"-t",
|
|
91551
|
+
sessionName2,
|
|
91552
|
+
"set-clipboard",
|
|
91553
|
+
"on",
|
|
91554
|
+
";",
|
|
91555
|
+
"set-option",
|
|
91556
|
+
"-at",
|
|
91557
|
+
sessionName2,
|
|
91558
|
+
"terminal-features",
|
|
91559
|
+
",*:clipboard"
|
|
91428
91560
|
];
|
|
91429
91561
|
tmuxArgs.push(";", "attach-session", "-t", sessionName2);
|
|
91430
91562
|
try {
|