oh-my-copilot 5.6.2 → 5.7.0
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/README.md +1 -0
- package/bridge/__pycache__/gyoshu_bridge.cpython-312.pyc +0 -0
- package/bridge/claude-md-coordinator.cjs +2 -2
- package/bridge/cli.cjs +78578 -75769
- package/bridge/mcp-server.cjs +36510 -32259
- package/bridge/runtime-cli.cjs +95 -34
- package/bridge/team-mcp.cjs +95 -34
- package/bridge/team.js +131 -70
- package/dist/__tests__/run-cjs-fail-closed-timeout.test.d.ts +2 -0
- package/dist/__tests__/run-cjs-fail-closed-timeout.test.d.ts.map +1 -0
- package/dist/__tests__/run-cjs-fail-closed-timeout.test.js +68 -0
- package/dist/__tests__/run-cjs-fail-closed-timeout.test.js.map +1 -0
- package/dist/__tests__/session-end-process-exit.test.js +70 -2
- package/dist/__tests__/session-end-process-exit.test.js.map +1 -1
- package/dist/cli/commands/__tests__/smoke-tier2.test.d.ts +2 -0
- package/dist/cli/commands/__tests__/smoke-tier2.test.d.ts.map +1 -0
- package/dist/cli/commands/__tests__/smoke-tier2.test.js +72 -0
- package/dist/cli/commands/__tests__/smoke-tier2.test.js.map +1 -0
- package/dist/cli/commands/smoke.d.ts +36 -0
- package/dist/cli/commands/smoke.d.ts.map +1 -0
- package/dist/cli/commands/smoke.js +169 -0
- package/dist/cli/commands/smoke.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +39 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/constants/names.d.ts +1 -0
- package/dist/constants/names.d.ts.map +1 -1
- package/dist/constants/names.js +1 -0
- package/dist/constants/names.js.map +1 -1
- package/dist/hooks/session-end/index.d.ts +2 -3
- package/dist/hooks/session-end/index.d.ts.map +1 -1
- package/dist/hooks/session-end/index.js +3 -10
- package/dist/hooks/session-end/index.js.map +1 -1
- package/dist/hooks/session-end/wiki-foreground-bootstrap.d.ts +17 -0
- package/dist/hooks/session-end/wiki-foreground-bootstrap.d.ts.map +1 -0
- package/dist/hooks/session-end/wiki-foreground-bootstrap.js +20 -0
- package/dist/hooks/session-end/wiki-foreground-bootstrap.js.map +1 -0
- package/dist/lib/__tests__/atomic-write.test.js +32 -1
- package/dist/lib/__tests__/atomic-write.test.js.map +1 -1
- package/dist/lib/__tests__/mode-state-lock.test.js +121 -12
- package/dist/lib/__tests__/mode-state-lock.test.js.map +1 -1
- package/dist/lib/atomic-write.d.ts +13 -3
- package/dist/lib/atomic-write.d.ts.map +1 -1
- package/dist/lib/atomic-write.js +29 -15
- package/dist/lib/atomic-write.js.map +1 -1
- package/dist/lib/mode-state-io.d.ts +2 -2
- package/dist/lib/mode-state-io.d.ts.map +1 -1
- package/dist/lib/mode-state-io.js +16 -10
- package/dist/lib/mode-state-io.js.map +1 -1
- package/dist/mcp/__tests__/host-smoke-tool.test.d.ts +2 -0
- package/dist/mcp/__tests__/host-smoke-tool.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/host-smoke-tool.test.js +174 -0
- package/dist/mcp/__tests__/host-smoke-tool.test.js.map +1 -0
- package/dist/mcp/disable-tools.d.ts.map +1 -1
- package/dist/mcp/disable-tools.js +1 -0
- package/dist/mcp/disable-tools.js.map +1 -1
- package/dist/mcp/tool-registry.d.ts.map +1 -1
- package/dist/mcp/tool-registry.js +2 -0
- package/dist/mcp/tool-registry.js.map +1 -1
- package/dist/smoke/__tests__/copilot-sdk-driver.test.d.ts +2 -0
- package/dist/smoke/__tests__/copilot-sdk-driver.test.d.ts.map +1 -0
- package/dist/smoke/__tests__/copilot-sdk-driver.test.js +561 -0
- package/dist/smoke/__tests__/copilot-sdk-driver.test.js.map +1 -0
- package/dist/smoke/__tests__/copilot-sdk-scenarios.test.d.ts +2 -0
- package/dist/smoke/__tests__/copilot-sdk-scenarios.test.d.ts.map +1 -0
- package/dist/smoke/__tests__/copilot-sdk-scenarios.test.js +311 -0
- package/dist/smoke/__tests__/copilot-sdk-scenarios.test.js.map +1 -0
- package/dist/smoke/__tests__/copilot-session-eval.test.d.ts +2 -0
- package/dist/smoke/__tests__/copilot-session-eval.test.d.ts.map +1 -0
- package/dist/smoke/__tests__/copilot-session-eval.test.js +264 -0
- package/dist/smoke/__tests__/copilot-session-eval.test.js.map +1 -0
- package/dist/smoke/__tests__/copilot-smoke.test.d.ts +2 -0
- package/dist/smoke/__tests__/copilot-smoke.test.d.ts.map +1 -0
- package/dist/smoke/__tests__/copilot-smoke.test.js +482 -0
- package/dist/smoke/__tests__/copilot-smoke.test.js.map +1 -0
- package/dist/smoke/copilot-binary.d.ts +21 -0
- package/dist/smoke/copilot-binary.d.ts.map +1 -0
- package/dist/smoke/copilot-binary.js +46 -0
- package/dist/smoke/copilot-binary.js.map +1 -0
- package/dist/smoke/copilot-sdk-driver.d.ts +186 -0
- package/dist/smoke/copilot-sdk-driver.d.ts.map +1 -0
- package/dist/smoke/copilot-sdk-driver.js +622 -0
- package/dist/smoke/copilot-sdk-driver.js.map +1 -0
- package/dist/smoke/copilot-sdk-scenarios.d.ts +159 -0
- package/dist/smoke/copilot-sdk-scenarios.d.ts.map +1 -0
- package/dist/smoke/copilot-sdk-scenarios.js +510 -0
- package/dist/smoke/copilot-sdk-scenarios.js.map +1 -0
- package/dist/smoke/copilot-session-eval.d.ts +90 -0
- package/dist/smoke/copilot-session-eval.d.ts.map +1 -0
- package/dist/smoke/copilot-session-eval.js +323 -0
- package/dist/smoke/copilot-session-eval.js.map +1 -0
- package/dist/smoke/copilot-smoke.d.ts +228 -0
- package/dist/smoke/copilot-smoke.d.ts.map +1 -0
- package/dist/smoke/copilot-smoke.js +818 -0
- package/dist/smoke/copilot-smoke.js.map +1 -0
- package/dist/smoke/process-utils.d.ts +47 -0
- package/dist/smoke/process-utils.d.ts.map +1 -0
- package/dist/smoke/process-utils.js +99 -0
- package/dist/smoke/process-utils.js.map +1 -0
- package/dist/team/__tests__/tmux-session.pane-env.test.d.ts +2 -0
- package/dist/team/__tests__/tmux-session.pane-env.test.d.ts.map +1 -0
- package/dist/team/__tests__/tmux-session.pane-env.test.js +52 -0
- package/dist/team/__tests__/tmux-session.pane-env.test.js.map +1 -0
- package/dist/team/tmux-session.d.ts +7 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +80 -18
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/tools/host-smoke-tool.d.ts +34 -0
- package/dist/tools/host-smoke-tool.d.ts.map +1 -0
- package/dist/tools/host-smoke-tool.js +133 -0
- package/dist/tools/host-smoke-tool.js.map +1 -0
- package/docs/CLAUDE.md +1 -1
- package/docs/DEVELOPERS.md +101 -0
- package/docs/HOOKS.md +1 -1
- package/docs/MIGRATION.md +71 -0
- package/docs/REFERENCE.md +42 -1
- package/docs/TOOLS.md +32 -1
- package/package.json +11 -2
- package/plugin.json +1 -1
- package/scripts/dev/repro-state-lock.mjs +1 -1
- package/scripts/lib/atomic-write.mjs +4 -2
- package/scripts/lib/state-lock.mjs +21 -12
- package/scripts/run.cjs +13 -3
- package/scripts/wiki-session-end.mjs +2 -1
- package/templates/hooks/lib/atomic-write.mjs +4 -2
package/bridge/runtime-cli.cjs
CHANGED
|
@@ -7343,33 +7343,33 @@ function ensureDirSync(dir) {
|
|
|
7343
7343
|
}
|
|
7344
7344
|
}
|
|
7345
7345
|
function verifyPrivateTempFile(fd, tempPath, label, operations) {
|
|
7346
|
-
const fdStats =
|
|
7346
|
+
const fdStats = descriptorStats(fd, operations);
|
|
7347
7347
|
let pathStats;
|
|
7348
7348
|
try {
|
|
7349
|
-
pathStats = (operations
|
|
7349
|
+
pathStats = pathnameStats(tempPath, operations);
|
|
7350
7350
|
} catch {
|
|
7351
7351
|
throw new Error(`${label} temporary file was replaced before rename`);
|
|
7352
7352
|
}
|
|
7353
7353
|
const isWindows = process.platform === "win32";
|
|
7354
|
-
const isPrivateRegularSingleLink = (stats) => stats.isFile() && (isWindows ? stats.nlink <= 1 : stats.nlink === 1) && (isWindows || (stats.mode & 511) === 384);
|
|
7354
|
+
const isPrivateRegularSingleLink = (stats) => stats.isFile() && (isWindows ? Number(stats.nlink) <= 1 : Number(stats.nlink) === 1) && (isWindows || (Number(stats.mode) & 511) === 384);
|
|
7355
7355
|
if (!isPrivateRegularSingleLink(fdStats) || !isPrivateRegularSingleLink(pathStats)) {
|
|
7356
7356
|
throw new Error(
|
|
7357
7357
|
`${label} temporary file must be a private regular single-link file`
|
|
7358
7358
|
);
|
|
7359
7359
|
}
|
|
7360
|
-
if (!sameFileIdentity(fdStats, pathStats)) {
|
|
7360
|
+
if (!sameFileIdentity(fileIdentityOf(fdStats), fileIdentityOf(pathStats))) {
|
|
7361
7361
|
throw new Error(`${label} temporary file was replaced before rename`);
|
|
7362
7362
|
}
|
|
7363
7363
|
}
|
|
7364
7364
|
function verifyPublishedFile(fd, filePath, label, operations) {
|
|
7365
|
-
const fdStats =
|
|
7365
|
+
const fdStats = descriptorStats(fd, operations);
|
|
7366
7366
|
let pathStats;
|
|
7367
7367
|
try {
|
|
7368
|
-
pathStats = (operations
|
|
7368
|
+
pathStats = pathnameStats(filePath, operations);
|
|
7369
7369
|
} catch {
|
|
7370
7370
|
throw new Error(`${label} target was replaced at publication`);
|
|
7371
7371
|
}
|
|
7372
|
-
if (!pathStats.isFile() || !sameFileIdentity(fdStats, pathStats)) {
|
|
7372
|
+
if (!pathStats.isFile() || !sameFileIdentity(fileIdentityOf(fdStats), fileIdentityOf(pathStats))) {
|
|
7373
7373
|
throw new Error(`${label} target was replaced at publication`);
|
|
7374
7374
|
}
|
|
7375
7375
|
}
|
|
@@ -7393,26 +7393,33 @@ function preservePriorTarget(filePath, operations) {
|
|
|
7393
7393
|
return null;
|
|
7394
7394
|
}
|
|
7395
7395
|
}
|
|
7396
|
+
function descriptorStats(fd, operations) {
|
|
7397
|
+
return operations ? fsSync.fstatSync(fd) : fsSync.fstatSync(fd, { bigint: true });
|
|
7398
|
+
}
|
|
7399
|
+
function pathnameStats(filePath, operations) {
|
|
7400
|
+
return operations ? operations.lstat(filePath) : fsSync.lstatSync(filePath, { bigint: true });
|
|
7401
|
+
}
|
|
7402
|
+
function fileIdentityOf(stats) {
|
|
7403
|
+
return { dev: BigInt(stats.dev), ino: BigInt(stats.ino) };
|
|
7404
|
+
}
|
|
7396
7405
|
function sameFileIdentity(a, b) {
|
|
7397
7406
|
if (a.ino !== b.ino) return false;
|
|
7398
7407
|
const isWindows = process.platform === "win32";
|
|
7399
|
-
if (isWindows && (a.dev ===
|
|
7408
|
+
if (isWindows && (a.dev === 0n || b.dev === 0n)) {
|
|
7400
7409
|
return true;
|
|
7401
7410
|
}
|
|
7402
7411
|
return a.dev === b.dev;
|
|
7403
7412
|
}
|
|
7404
7413
|
function currentFileIdentity(filePath, operations) {
|
|
7405
7414
|
try {
|
|
7406
|
-
|
|
7407
|
-
return { dev: stats.dev, ino: stats.ino };
|
|
7415
|
+
return fileIdentityOf(pathnameStats(filePath, operations));
|
|
7408
7416
|
} catch {
|
|
7409
7417
|
return null;
|
|
7410
7418
|
}
|
|
7411
7419
|
}
|
|
7412
|
-
function descriptorIdentity(fd) {
|
|
7420
|
+
function descriptorIdentity(fd, operations) {
|
|
7413
7421
|
try {
|
|
7414
|
-
|
|
7415
|
-
return { dev: stats.dev, ino: stats.ino };
|
|
7422
|
+
return fileIdentityOf(descriptorStats(fd, operations));
|
|
7416
7423
|
} catch {
|
|
7417
7424
|
return null;
|
|
7418
7425
|
}
|
|
@@ -10173,7 +10180,8 @@ __export(tmux_session_exports, {
|
|
|
10173
10180
|
waitForPaneReady: () => waitForPaneReady,
|
|
10174
10181
|
waitForStartupPaneReady: () => waitForStartupPaneReady,
|
|
10175
10182
|
workerPaneBelongsToOwnedProviderTarget: () => workerPaneBelongsToOwnedProviderTarget,
|
|
10176
|
-
workerPaneBelongsToProviderTarget: () => workerPaneBelongsToProviderTarget
|
|
10183
|
+
workerPaneBelongsToProviderTarget: () => workerPaneBelongsToProviderTarget,
|
|
10184
|
+
workerPaneShellCommand: () => workerPaneShellCommand
|
|
10177
10185
|
});
|
|
10178
10186
|
function tmuxArgsForIdentity(identity, args) {
|
|
10179
10187
|
return ["-S", identity.socket_path, ...args];
|
|
@@ -11048,23 +11056,66 @@ async function verifyWorkerStartCommandSubmitted(paneId, startCmd, opts = {}) {
|
|
|
11048
11056
|
}
|
|
11049
11057
|
return false;
|
|
11050
11058
|
}
|
|
11059
|
+
function writePaneEnvFile(values) {
|
|
11060
|
+
const directory = (0, import_fs24.mkdtempSync)((0, import_path25.join)((0, import_os8.tmpdir)(), "omc-pane-env-"));
|
|
11061
|
+
const file = (0, import_path25.join)(directory, "env");
|
|
11062
|
+
const body = Object.entries(values).map(([key, value]) => `export ${key}=${shellQuote(value)}
|
|
11063
|
+
`).join("");
|
|
11064
|
+
(0, import_fs24.writeFileSync)(file, body, { mode: 384, flag: "wx" });
|
|
11065
|
+
return file;
|
|
11066
|
+
}
|
|
11067
|
+
function discardPaneEnvFile(envFile) {
|
|
11068
|
+
if (!envFile) return;
|
|
11069
|
+
(0, import_fs24.rmSync)((0, import_path25.dirname)(envFile), { recursive: true, force: true });
|
|
11070
|
+
}
|
|
11051
11071
|
function workerPaneShellCommand() {
|
|
11052
11072
|
if (process.platform === "win32" && !isUnixLikeOnWindows()) {
|
|
11053
|
-
return [getDefaultShell()];
|
|
11073
|
+
return { args: [getDefaultShell()], envFile: null };
|
|
11054
11074
|
}
|
|
11055
|
-
if (process.platform === "win32") return [];
|
|
11075
|
+
if (process.platform === "win32") return { args: [], envFile: null };
|
|
11056
11076
|
const shell = getDefaultShell();
|
|
11057
11077
|
const baseline = buildProviderEnvironment({ SHELL: shell });
|
|
11078
|
+
const inline = buildProviderEnvironment({ SHELL: shell }, process.env, process.platform, []);
|
|
11079
|
+
const passthrough = Object.fromEntries(
|
|
11080
|
+
Object.entries(baseline).filter(([key, value]) => inline[key] !== value)
|
|
11081
|
+
);
|
|
11058
11082
|
const inheritedPaneEnvironment = ["TERM", "TMUX", "TMUX_PANE", "TMUX_TMPDIR", "LANG", "LC_ALL", "LC_CTYPE"].map((key) => `${key}="$${key}"`);
|
|
11083
|
+
const inlineAssignments = Object.entries(inline).map(([key, value]) => `${key}=${shellQuote(value)}`);
|
|
11084
|
+
if (Object.keys(passthrough).length === 0) {
|
|
11085
|
+
const command2 = [
|
|
11086
|
+
"/usr/bin/env",
|
|
11087
|
+
"-i",
|
|
11088
|
+
...inlineAssignments,
|
|
11089
|
+
...inheritedPaneEnvironment,
|
|
11090
|
+
shellQuote(shell),
|
|
11091
|
+
"-l"
|
|
11092
|
+
].join(" ");
|
|
11093
|
+
return { args: [command2], envFile: null };
|
|
11094
|
+
}
|
|
11095
|
+
const envFile = writePaneEnvFile(passthrough);
|
|
11096
|
+
const bootstrap = '. "$OMC_PANE_ENV_FILE" && rm -rf -- "${OMC_PANE_ENV_FILE%/*}" && unset OMC_PANE_ENV_FILE && exec "$SHELL" -l';
|
|
11059
11097
|
const command = [
|
|
11060
11098
|
"/usr/bin/env",
|
|
11061
11099
|
"-i",
|
|
11062
|
-
...
|
|
11100
|
+
...inlineAssignments,
|
|
11101
|
+
`OMC_PANE_ENV_FILE=${shellQuote(envFile)}`,
|
|
11063
11102
|
...inheritedPaneEnvironment,
|
|
11064
|
-
|
|
11065
|
-
"-
|
|
11103
|
+
"/bin/sh",
|
|
11104
|
+
"-c",
|
|
11105
|
+
shellQuote(bootstrap)
|
|
11066
11106
|
].join(" ");
|
|
11067
|
-
return [command];
|
|
11107
|
+
return { args: [command], envFile };
|
|
11108
|
+
}
|
|
11109
|
+
async function runPaneCreationCommand(identity, nativeCommand, paneShell) {
|
|
11110
|
+
let result;
|
|
11111
|
+
try {
|
|
11112
|
+
result = await runGuardedNativeTmuxCommand(identity, nativeCommand);
|
|
11113
|
+
} catch (error) {
|
|
11114
|
+
discardPaneEnvFile(paneShell.envFile);
|
|
11115
|
+
throw error;
|
|
11116
|
+
}
|
|
11117
|
+
if (result.outcome === "not_executed") discardPaneEnvFile(paneShell.envFile);
|
|
11118
|
+
return result;
|
|
11068
11119
|
}
|
|
11069
11120
|
function escapeForCmdSet(value) {
|
|
11070
11121
|
return value.replace(/(["%])/g, "$1$1");
|
|
@@ -11363,6 +11414,7 @@ async function splitTeamWorkerPaneWithEvidence(splitTarget, direction, cwd, prov
|
|
|
11363
11414
|
};
|
|
11364
11415
|
}
|
|
11365
11416
|
const splitType = direction === "right" ? "-h" : "-v";
|
|
11417
|
+
const splitPaneShell = workerPaneShellCommand();
|
|
11366
11418
|
const splitArgs = [
|
|
11367
11419
|
"split-window",
|
|
11368
11420
|
splitType,
|
|
@@ -11374,11 +11426,12 @@ async function splitTeamWorkerPaneWithEvidence(splitTarget, direction, cwd, prov
|
|
|
11374
11426
|
"#{pane_id} #{socket_path} #{pid}",
|
|
11375
11427
|
"-c",
|
|
11376
11428
|
cwd,
|
|
11377
|
-
...
|
|
11429
|
+
...splitPaneShell.args
|
|
11378
11430
|
];
|
|
11379
|
-
const splitResult = await
|
|
11431
|
+
const splitResult = await runPaneCreationCommand(
|
|
11380
11432
|
identity,
|
|
11381
|
-
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"])
|
|
11433
|
+
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"]),
|
|
11434
|
+
splitPaneShell
|
|
11382
11435
|
);
|
|
11383
11436
|
const parsed = splitResult.outcome === "executed" ? parseTmuxCreationRecord(
|
|
11384
11437
|
splitResult.stdout,
|
|
@@ -11480,6 +11533,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
11480
11533
|
sessionMode: "detached-session",
|
|
11481
11534
|
...tmuxServerIdentity ? { tmuxServerIdentity: { ...tmuxServerIdentity } } : {}
|
|
11482
11535
|
});
|
|
11536
|
+
const detachedPaneShell = workerPaneShellCommand();
|
|
11483
11537
|
const detachedArgs = [
|
|
11484
11538
|
"new-session",
|
|
11485
11539
|
"-d",
|
|
@@ -11490,7 +11544,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
11490
11544
|
detachedSessionName,
|
|
11491
11545
|
"-c",
|
|
11492
11546
|
cwd,
|
|
11493
|
-
...
|
|
11547
|
+
...detachedPaneShell.args
|
|
11494
11548
|
];
|
|
11495
11549
|
const cleanupFreshDetachedServer = async () => {
|
|
11496
11550
|
if (isPsmux() && freshSocketPathForEvidence) {
|
|
@@ -11519,9 +11573,10 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
11519
11573
|
if (existingDetachedIdentity) {
|
|
11520
11574
|
tmuxServerIdentity = existingDetachedIdentity;
|
|
11521
11575
|
try {
|
|
11522
|
-
detachedResult = await
|
|
11576
|
+
detachedResult = await runPaneCreationCommand(
|
|
11523
11577
|
existingDetachedIdentity,
|
|
11524
|
-
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"])
|
|
11578
|
+
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"]),
|
|
11579
|
+
detachedPaneShell
|
|
11525
11580
|
);
|
|
11526
11581
|
} catch (error) {
|
|
11527
11582
|
const cleaned = await cleanupDetachedSession();
|
|
@@ -11581,11 +11636,13 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
11581
11636
|
throw new Error("tmux_server_identity_unavailable");
|
|
11582
11637
|
}
|
|
11583
11638
|
freshDetachedServerIdentity = tmuxServerIdentity;
|
|
11584
|
-
detachedResult = await
|
|
11639
|
+
detachedResult = await runPaneCreationCommand(
|
|
11585
11640
|
tmuxServerIdentity,
|
|
11586
|
-
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"])
|
|
11641
|
+
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"]),
|
|
11642
|
+
detachedPaneShell
|
|
11587
11643
|
);
|
|
11588
11644
|
} catch (error) {
|
|
11645
|
+
discardPaneEnvFile(detachedPaneShell.envFile);
|
|
11589
11646
|
const cleaned = await cleanupDetachedSession();
|
|
11590
11647
|
if (!cleaned && freshDetachedServerStarted) {
|
|
11591
11648
|
throw new TeamSessionCreationError(
|
|
@@ -11765,6 +11822,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
11765
11822
|
if (useDedicatedWindow) {
|
|
11766
11823
|
const targetSession = sessionAndWindow.split(":")[0] ?? sessionAndWindow;
|
|
11767
11824
|
const windowName = `omc-${sanitizeName(teamName)}`.slice(0, 32);
|
|
11825
|
+
const newWindowPaneShell = workerPaneShellCommand();
|
|
11768
11826
|
const newWindowArgs = [
|
|
11769
11827
|
"new-window",
|
|
11770
11828
|
"-d",
|
|
@@ -11777,13 +11835,14 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
11777
11835
|
windowName,
|
|
11778
11836
|
"-c",
|
|
11779
11837
|
cwd,
|
|
11780
|
-
...
|
|
11838
|
+
...newWindowPaneShell.args
|
|
11781
11839
|
];
|
|
11782
11840
|
let newWindowResult;
|
|
11783
11841
|
try {
|
|
11784
|
-
newWindowResult = await
|
|
11842
|
+
newWindowResult = await runPaneCreationCommand(
|
|
11785
11843
|
tmuxServerIdentity,
|
|
11786
|
-
tmuxCommandString(newWindowArgs, ["#S:#I #{pane_id} #{socket_path} #{pid}"])
|
|
11844
|
+
tmuxCommandString(newWindowArgs, ["#S:#I #{pane_id} #{socket_path} #{pid}"]),
|
|
11845
|
+
newWindowPaneShell
|
|
11787
11846
|
);
|
|
11788
11847
|
} catch (error) {
|
|
11789
11848
|
const creationError = new TeamSessionCreationError(
|
|
@@ -11933,6 +11992,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
11933
11992
|
continue;
|
|
11934
11993
|
}
|
|
11935
11994
|
const splitType = i === 0 ? "-h" : "-v";
|
|
11995
|
+
const splitPaneShell = workerPaneShellCommand();
|
|
11936
11996
|
const splitArgs = [
|
|
11937
11997
|
"split-window",
|
|
11938
11998
|
splitType,
|
|
@@ -11944,11 +12004,12 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
11944
12004
|
"#{pane_id} #{socket_path} #{pid}",
|
|
11945
12005
|
"-c",
|
|
11946
12006
|
cwd,
|
|
11947
|
-
...
|
|
12007
|
+
...splitPaneShell.args
|
|
11948
12008
|
];
|
|
11949
|
-
const splitResult = await
|
|
12009
|
+
const splitResult = await runPaneCreationCommand(
|
|
11950
12010
|
tmuxServerIdentity,
|
|
11951
|
-
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"])
|
|
12011
|
+
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"]),
|
|
12012
|
+
splitPaneShell
|
|
11952
12013
|
);
|
|
11953
12014
|
if (splitResult.outcome !== "executed") {
|
|
11954
12015
|
const creationError = new TeamSessionCreationError(
|
package/bridge/team-mcp.cjs
CHANGED
|
@@ -12066,33 +12066,33 @@ function ensureDirSync(dir) {
|
|
|
12066
12066
|
}
|
|
12067
12067
|
}
|
|
12068
12068
|
function verifyPrivateTempFile(fd, tempPath, label, operations) {
|
|
12069
|
-
const fdStats =
|
|
12069
|
+
const fdStats = descriptorStats(fd, operations);
|
|
12070
12070
|
let pathStats;
|
|
12071
12071
|
try {
|
|
12072
|
-
pathStats = (operations
|
|
12072
|
+
pathStats = pathnameStats(tempPath, operations);
|
|
12073
12073
|
} catch {
|
|
12074
12074
|
throw new Error(`${label} temporary file was replaced before rename`);
|
|
12075
12075
|
}
|
|
12076
12076
|
const isWindows = process.platform === "win32";
|
|
12077
|
-
const isPrivateRegularSingleLink = (stats) => stats.isFile() && (isWindows ? stats.nlink <= 1 : stats.nlink === 1) && (isWindows || (stats.mode & 511) === 384);
|
|
12077
|
+
const isPrivateRegularSingleLink = (stats) => stats.isFile() && (isWindows ? Number(stats.nlink) <= 1 : Number(stats.nlink) === 1) && (isWindows || (Number(stats.mode) & 511) === 384);
|
|
12078
12078
|
if (!isPrivateRegularSingleLink(fdStats) || !isPrivateRegularSingleLink(pathStats)) {
|
|
12079
12079
|
throw new Error(
|
|
12080
12080
|
`${label} temporary file must be a private regular single-link file`
|
|
12081
12081
|
);
|
|
12082
12082
|
}
|
|
12083
|
-
if (!sameFileIdentity(fdStats, pathStats)) {
|
|
12083
|
+
if (!sameFileIdentity(fileIdentityOf(fdStats), fileIdentityOf(pathStats))) {
|
|
12084
12084
|
throw new Error(`${label} temporary file was replaced before rename`);
|
|
12085
12085
|
}
|
|
12086
12086
|
}
|
|
12087
12087
|
function verifyPublishedFile(fd, filePath, label, operations) {
|
|
12088
|
-
const fdStats =
|
|
12088
|
+
const fdStats = descriptorStats(fd, operations);
|
|
12089
12089
|
let pathStats;
|
|
12090
12090
|
try {
|
|
12091
|
-
pathStats = (operations
|
|
12091
|
+
pathStats = pathnameStats(filePath, operations);
|
|
12092
12092
|
} catch {
|
|
12093
12093
|
throw new Error(`${label} target was replaced at publication`);
|
|
12094
12094
|
}
|
|
12095
|
-
if (!pathStats.isFile() || !sameFileIdentity(fdStats, pathStats)) {
|
|
12095
|
+
if (!pathStats.isFile() || !sameFileIdentity(fileIdentityOf(fdStats), fileIdentityOf(pathStats))) {
|
|
12096
12096
|
throw new Error(`${label} target was replaced at publication`);
|
|
12097
12097
|
}
|
|
12098
12098
|
}
|
|
@@ -12116,26 +12116,33 @@ function preservePriorTarget(filePath, operations) {
|
|
|
12116
12116
|
return null;
|
|
12117
12117
|
}
|
|
12118
12118
|
}
|
|
12119
|
+
function descriptorStats(fd, operations) {
|
|
12120
|
+
return operations ? fsSync.fstatSync(fd) : fsSync.fstatSync(fd, { bigint: true });
|
|
12121
|
+
}
|
|
12122
|
+
function pathnameStats(filePath, operations) {
|
|
12123
|
+
return operations ? operations.lstat(filePath) : fsSync.lstatSync(filePath, { bigint: true });
|
|
12124
|
+
}
|
|
12125
|
+
function fileIdentityOf(stats) {
|
|
12126
|
+
return { dev: BigInt(stats.dev), ino: BigInt(stats.ino) };
|
|
12127
|
+
}
|
|
12119
12128
|
function sameFileIdentity(a, b) {
|
|
12120
12129
|
if (a.ino !== b.ino) return false;
|
|
12121
12130
|
const isWindows = process.platform === "win32";
|
|
12122
|
-
if (isWindows && (a.dev ===
|
|
12131
|
+
if (isWindows && (a.dev === 0n || b.dev === 0n)) {
|
|
12123
12132
|
return true;
|
|
12124
12133
|
}
|
|
12125
12134
|
return a.dev === b.dev;
|
|
12126
12135
|
}
|
|
12127
12136
|
function currentFileIdentity(filePath, operations) {
|
|
12128
12137
|
try {
|
|
12129
|
-
|
|
12130
|
-
return { dev: stats.dev, ino: stats.ino };
|
|
12138
|
+
return fileIdentityOf(pathnameStats(filePath, operations));
|
|
12131
12139
|
} catch {
|
|
12132
12140
|
return null;
|
|
12133
12141
|
}
|
|
12134
12142
|
}
|
|
12135
|
-
function descriptorIdentity(fd) {
|
|
12143
|
+
function descriptorIdentity(fd, operations) {
|
|
12136
12144
|
try {
|
|
12137
|
-
|
|
12138
|
-
return { dev: stats.dev, ino: stats.ino };
|
|
12145
|
+
return fileIdentityOf(descriptorStats(fd, operations));
|
|
12139
12146
|
} catch {
|
|
12140
12147
|
return null;
|
|
12141
12148
|
}
|
|
@@ -13433,7 +13440,8 @@ __export(tmux_session_exports, {
|
|
|
13433
13440
|
waitForPaneReady: () => waitForPaneReady,
|
|
13434
13441
|
waitForStartupPaneReady: () => waitForStartupPaneReady,
|
|
13435
13442
|
workerPaneBelongsToOwnedProviderTarget: () => workerPaneBelongsToOwnedProviderTarget,
|
|
13436
|
-
workerPaneBelongsToProviderTarget: () => workerPaneBelongsToProviderTarget
|
|
13443
|
+
workerPaneBelongsToProviderTarget: () => workerPaneBelongsToProviderTarget,
|
|
13444
|
+
workerPaneShellCommand: () => workerPaneShellCommand
|
|
13437
13445
|
});
|
|
13438
13446
|
function tmuxArgsForIdentity(identity, args) {
|
|
13439
13447
|
return ["-S", identity.socket_path, ...args];
|
|
@@ -14308,23 +14316,66 @@ async function verifyWorkerStartCommandSubmitted(paneId, startCmd, opts = {}) {
|
|
|
14308
14316
|
}
|
|
14309
14317
|
return false;
|
|
14310
14318
|
}
|
|
14319
|
+
function writePaneEnvFile(values) {
|
|
14320
|
+
const directory = (0, import_fs22.mkdtempSync)((0, import_path24.join)((0, import_os7.tmpdir)(), "omc-pane-env-"));
|
|
14321
|
+
const file = (0, import_path24.join)(directory, "env");
|
|
14322
|
+
const body = Object.entries(values).map(([key, value]) => `export ${key}=${shellQuote(value)}
|
|
14323
|
+
`).join("");
|
|
14324
|
+
(0, import_fs22.writeFileSync)(file, body, { mode: 384, flag: "wx" });
|
|
14325
|
+
return file;
|
|
14326
|
+
}
|
|
14327
|
+
function discardPaneEnvFile(envFile) {
|
|
14328
|
+
if (!envFile) return;
|
|
14329
|
+
(0, import_fs22.rmSync)((0, import_path24.dirname)(envFile), { recursive: true, force: true });
|
|
14330
|
+
}
|
|
14311
14331
|
function workerPaneShellCommand() {
|
|
14312
14332
|
if (process.platform === "win32" && !isUnixLikeOnWindows()) {
|
|
14313
|
-
return [getDefaultShell()];
|
|
14333
|
+
return { args: [getDefaultShell()], envFile: null };
|
|
14314
14334
|
}
|
|
14315
|
-
if (process.platform === "win32") return [];
|
|
14335
|
+
if (process.platform === "win32") return { args: [], envFile: null };
|
|
14316
14336
|
const shell = getDefaultShell();
|
|
14317
14337
|
const baseline = buildProviderEnvironment({ SHELL: shell });
|
|
14338
|
+
const inline = buildProviderEnvironment({ SHELL: shell }, process.env, process.platform, []);
|
|
14339
|
+
const passthrough = Object.fromEntries(
|
|
14340
|
+
Object.entries(baseline).filter(([key, value]) => inline[key] !== value)
|
|
14341
|
+
);
|
|
14318
14342
|
const inheritedPaneEnvironment = ["TERM", "TMUX", "TMUX_PANE", "TMUX_TMPDIR", "LANG", "LC_ALL", "LC_CTYPE"].map((key) => `${key}="$${key}"`);
|
|
14343
|
+
const inlineAssignments = Object.entries(inline).map(([key, value]) => `${key}=${shellQuote(value)}`);
|
|
14344
|
+
if (Object.keys(passthrough).length === 0) {
|
|
14345
|
+
const command2 = [
|
|
14346
|
+
"/usr/bin/env",
|
|
14347
|
+
"-i",
|
|
14348
|
+
...inlineAssignments,
|
|
14349
|
+
...inheritedPaneEnvironment,
|
|
14350
|
+
shellQuote(shell),
|
|
14351
|
+
"-l"
|
|
14352
|
+
].join(" ");
|
|
14353
|
+
return { args: [command2], envFile: null };
|
|
14354
|
+
}
|
|
14355
|
+
const envFile = writePaneEnvFile(passthrough);
|
|
14356
|
+
const bootstrap = '. "$OMC_PANE_ENV_FILE" && rm -rf -- "${OMC_PANE_ENV_FILE%/*}" && unset OMC_PANE_ENV_FILE && exec "$SHELL" -l';
|
|
14319
14357
|
const command = [
|
|
14320
14358
|
"/usr/bin/env",
|
|
14321
14359
|
"-i",
|
|
14322
|
-
...
|
|
14360
|
+
...inlineAssignments,
|
|
14361
|
+
`OMC_PANE_ENV_FILE=${shellQuote(envFile)}`,
|
|
14323
14362
|
...inheritedPaneEnvironment,
|
|
14324
|
-
|
|
14325
|
-
"-
|
|
14363
|
+
"/bin/sh",
|
|
14364
|
+
"-c",
|
|
14365
|
+
shellQuote(bootstrap)
|
|
14326
14366
|
].join(" ");
|
|
14327
|
-
return [command];
|
|
14367
|
+
return { args: [command], envFile };
|
|
14368
|
+
}
|
|
14369
|
+
async function runPaneCreationCommand(identity, nativeCommand, paneShell) {
|
|
14370
|
+
let result;
|
|
14371
|
+
try {
|
|
14372
|
+
result = await runGuardedNativeTmuxCommand(identity, nativeCommand);
|
|
14373
|
+
} catch (error2) {
|
|
14374
|
+
discardPaneEnvFile(paneShell.envFile);
|
|
14375
|
+
throw error2;
|
|
14376
|
+
}
|
|
14377
|
+
if (result.outcome === "not_executed") discardPaneEnvFile(paneShell.envFile);
|
|
14378
|
+
return result;
|
|
14328
14379
|
}
|
|
14329
14380
|
function escapeForCmdSet(value) {
|
|
14330
14381
|
return value.replace(/(["%])/g, "$1$1");
|
|
@@ -14623,6 +14674,7 @@ async function splitTeamWorkerPaneWithEvidence(splitTarget, direction, cwd, prov
|
|
|
14623
14674
|
};
|
|
14624
14675
|
}
|
|
14625
14676
|
const splitType = direction === "right" ? "-h" : "-v";
|
|
14677
|
+
const splitPaneShell = workerPaneShellCommand();
|
|
14626
14678
|
const splitArgs = [
|
|
14627
14679
|
"split-window",
|
|
14628
14680
|
splitType,
|
|
@@ -14634,11 +14686,12 @@ async function splitTeamWorkerPaneWithEvidence(splitTarget, direction, cwd, prov
|
|
|
14634
14686
|
"#{pane_id} #{socket_path} #{pid}",
|
|
14635
14687
|
"-c",
|
|
14636
14688
|
cwd,
|
|
14637
|
-
...
|
|
14689
|
+
...splitPaneShell.args
|
|
14638
14690
|
];
|
|
14639
|
-
const splitResult = await
|
|
14691
|
+
const splitResult = await runPaneCreationCommand(
|
|
14640
14692
|
identity,
|
|
14641
|
-
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"])
|
|
14693
|
+
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"]),
|
|
14694
|
+
splitPaneShell
|
|
14642
14695
|
);
|
|
14643
14696
|
const parsed = splitResult.outcome === "executed" ? parseTmuxCreationRecord(
|
|
14644
14697
|
splitResult.stdout,
|
|
@@ -14740,6 +14793,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
14740
14793
|
sessionMode: "detached-session",
|
|
14741
14794
|
...tmuxServerIdentity ? { tmuxServerIdentity: { ...tmuxServerIdentity } } : {}
|
|
14742
14795
|
});
|
|
14796
|
+
const detachedPaneShell = workerPaneShellCommand();
|
|
14743
14797
|
const detachedArgs = [
|
|
14744
14798
|
"new-session",
|
|
14745
14799
|
"-d",
|
|
@@ -14750,7 +14804,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
14750
14804
|
detachedSessionName,
|
|
14751
14805
|
"-c",
|
|
14752
14806
|
cwd,
|
|
14753
|
-
...
|
|
14807
|
+
...detachedPaneShell.args
|
|
14754
14808
|
];
|
|
14755
14809
|
const cleanupFreshDetachedServer = async () => {
|
|
14756
14810
|
if (isPsmux() && freshSocketPathForEvidence) {
|
|
@@ -14779,9 +14833,10 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
14779
14833
|
if (existingDetachedIdentity) {
|
|
14780
14834
|
tmuxServerIdentity = existingDetachedIdentity;
|
|
14781
14835
|
try {
|
|
14782
|
-
detachedResult = await
|
|
14836
|
+
detachedResult = await runPaneCreationCommand(
|
|
14783
14837
|
existingDetachedIdentity,
|
|
14784
|
-
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"])
|
|
14838
|
+
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"]),
|
|
14839
|
+
detachedPaneShell
|
|
14785
14840
|
);
|
|
14786
14841
|
} catch (error2) {
|
|
14787
14842
|
const cleaned = await cleanupDetachedSession();
|
|
@@ -14841,11 +14896,13 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
14841
14896
|
throw new Error("tmux_server_identity_unavailable");
|
|
14842
14897
|
}
|
|
14843
14898
|
freshDetachedServerIdentity = tmuxServerIdentity;
|
|
14844
|
-
detachedResult = await
|
|
14899
|
+
detachedResult = await runPaneCreationCommand(
|
|
14845
14900
|
tmuxServerIdentity,
|
|
14846
|
-
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"])
|
|
14901
|
+
tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"]),
|
|
14902
|
+
detachedPaneShell
|
|
14847
14903
|
);
|
|
14848
14904
|
} catch (error2) {
|
|
14905
|
+
discardPaneEnvFile(detachedPaneShell.envFile);
|
|
14849
14906
|
const cleaned = await cleanupDetachedSession();
|
|
14850
14907
|
if (!cleaned && freshDetachedServerStarted) {
|
|
14851
14908
|
throw new TeamSessionCreationError(
|
|
@@ -15025,6 +15082,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
15025
15082
|
if (useDedicatedWindow) {
|
|
15026
15083
|
const targetSession = sessionAndWindow.split(":")[0] ?? sessionAndWindow;
|
|
15027
15084
|
const windowName = `omc-${sanitizeName(teamName)}`.slice(0, 32);
|
|
15085
|
+
const newWindowPaneShell = workerPaneShellCommand();
|
|
15028
15086
|
const newWindowArgs = [
|
|
15029
15087
|
"new-window",
|
|
15030
15088
|
"-d",
|
|
@@ -15037,13 +15095,14 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
15037
15095
|
windowName,
|
|
15038
15096
|
"-c",
|
|
15039
15097
|
cwd,
|
|
15040
|
-
...
|
|
15098
|
+
...newWindowPaneShell.args
|
|
15041
15099
|
];
|
|
15042
15100
|
let newWindowResult;
|
|
15043
15101
|
try {
|
|
15044
|
-
newWindowResult = await
|
|
15102
|
+
newWindowResult = await runPaneCreationCommand(
|
|
15045
15103
|
tmuxServerIdentity,
|
|
15046
|
-
tmuxCommandString(newWindowArgs, ["#S:#I #{pane_id} #{socket_path} #{pid}"])
|
|
15104
|
+
tmuxCommandString(newWindowArgs, ["#S:#I #{pane_id} #{socket_path} #{pid}"]),
|
|
15105
|
+
newWindowPaneShell
|
|
15047
15106
|
);
|
|
15048
15107
|
} catch (error2) {
|
|
15049
15108
|
const creationError = new TeamSessionCreationError(
|
|
@@ -15193,6 +15252,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
15193
15252
|
continue;
|
|
15194
15253
|
}
|
|
15195
15254
|
const splitType = i === 0 ? "-h" : "-v";
|
|
15255
|
+
const splitPaneShell = workerPaneShellCommand();
|
|
15196
15256
|
const splitArgs = [
|
|
15197
15257
|
"split-window",
|
|
15198
15258
|
splitType,
|
|
@@ -15204,11 +15264,12 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
|
|
|
15204
15264
|
"#{pane_id} #{socket_path} #{pid}",
|
|
15205
15265
|
"-c",
|
|
15206
15266
|
cwd,
|
|
15207
|
-
...
|
|
15267
|
+
...splitPaneShell.args
|
|
15208
15268
|
];
|
|
15209
|
-
const splitResult = await
|
|
15269
|
+
const splitResult = await runPaneCreationCommand(
|
|
15210
15270
|
tmuxServerIdentity,
|
|
15211
|
-
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"])
|
|
15271
|
+
tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"]),
|
|
15272
|
+
splitPaneShell
|
|
15212
15273
|
);
|
|
15213
15274
|
if (splitResult.outcome !== "executed") {
|
|
15214
15275
|
const creationError = new TeamSessionCreationError(
|