botmux 3.0.0 → 3.1.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/dist/adapters/backend/herdr-backend.d.ts +9 -7
- package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
- package/dist/adapters/backend/herdr-backend.js +63 -53
- package/dist/adapters/backend/herdr-backend.js.map +1 -1
- package/dist/adapters/backend/riff-backend.d.ts +6 -1
- package/dist/adapters/backend/riff-backend.d.ts.map +1 -1
- package/dist/adapters/backend/riff-backend.js +7 -2
- package/dist/adapters/backend/riff-backend.js.map +1 -1
- package/dist/adapters/backend/sandbox.d.ts +20 -16
- package/dist/adapters/backend/sandbox.d.ts.map +1 -1
- package/dist/adapters/backend/sandbox.js +192 -65
- package/dist/adapters/backend/sandbox.js.map +1 -1
- package/dist/adapters/backend/tmux-backend.d.ts +39 -2
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +55 -5
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +2 -2
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
- package/dist/adapters/backend/zellij-backend.d.ts.map +1 -1
- package/dist/adapters/backend/zellij-backend.js +9 -3
- package/dist/adapters/backend/zellij-backend.js.map +1 -1
- package/dist/adapters/cli/claude-code.d.ts +25 -0
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +79 -9
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/read-isolation.d.ts +2 -1
- package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
- package/dist/adapters/cli/read-isolation.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +2 -2
- package/dist/adapters/hook-installer.d.ts +11 -0
- package/dist/adapters/hook-installer.d.ts.map +1 -1
- package/dist/adapters/hook-installer.js +72 -11
- package/dist/adapters/hook-installer.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +15 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -0
- package/dist/config.js.map +1 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +211 -57
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +12 -5
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts +5 -0
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +2 -0
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/doc-comment-prompt.d.ts +2 -0
- package/dist/core/doc-comment-prompt.d.ts.map +1 -1
- package/dist/core/doc-comment-prompt.js +30 -0
- package/dist/core/doc-comment-prompt.js.map +1 -1
- package/dist/core/github-auth.d.ts +8 -0
- package/dist/core/github-auth.d.ts.map +1 -0
- package/dist/core/github-auth.js +44 -0
- package/dist/core/github-auth.js.map +1 -0
- package/dist/core/managed-origin-capability.d.ts +7 -0
- package/dist/core/managed-origin-capability.d.ts.map +1 -1
- package/dist/core/managed-origin-capability.js +12 -0
- package/dist/core/managed-origin-capability.js.map +1 -1
- package/dist/core/passthrough-commands.d.ts.map +1 -1
- package/dist/core/passthrough-commands.js +1 -1
- package/dist/core/passthrough-commands.js.map +1 -1
- package/dist/core/restart-report.d.ts +7 -1
- package/dist/core/restart-report.d.ts.map +1 -1
- package/dist/core/restart-report.js +19 -5
- package/dist/core/restart-report.js.map +1 -1
- package/dist/core/session-activity.d.ts +8 -0
- package/dist/core/session-activity.d.ts.map +1 -1
- package/dist/core/session-activity.js +16 -0
- package/dist/core/session-activity.js.map +1 -1
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +4 -2
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/update-check.d.ts +11 -0
- package/dist/core/update-check.d.ts.map +1 -1
- package/dist/core/update-check.js +6 -1
- package/dist/core/update-check.js.map +1 -1
- package/dist/core/vc-meeting-prepare-command.d.ts +22 -0
- package/dist/core/vc-meeting-prepare-command.d.ts.map +1 -0
- package/dist/core/vc-meeting-prepare-command.js +50 -0
- package/dist/core/vc-meeting-prepare-command.js.map +1 -0
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +11 -2
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +15 -5
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +555 -41
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +6 -1
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +34 -0
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/preferences.d.ts +1 -1
- package/dist/dashboard/web/preferences.d.ts.map +1 -1
- package/dist/dashboard/web/preferences.js +1 -1
- package/dist/dashboard/web/preferences.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts +19 -0
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +66 -7
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts +31 -0
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +82 -0
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/{bot-defaults-page-MBORWWP7.js → bot-defaults-page-KLDCZNLP.js} +5 -5
- package/dist/dashboard-web/chunks/{chunk-G43RUPUN.js → chunk-EZAW2EPM.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-EIO5AWDA.js → chunk-FMJNOATE.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-4QTBR7UF.js → chunk-KEAOTUL3.js} +7 -7
- package/dist/dashboard-web/chunks/{chunk-7STGZ5BX.js → chunk-MLNI5BKE.js} +1 -1
- package/dist/dashboard-web/chunks/{connectors-page-LKDT4WBG.js → connectors-page-O32LFAL5.js} +1 -1
- package/dist/dashboard-web/chunks/{groups-page-XKIWJ2TP.js → groups-page-PSAFIZ6M.js} +1 -1
- package/dist/dashboard-web/chunks/{insights-page-CBEZCYKV.js → insights-page-V23LLATX.js} +1 -1
- package/dist/dashboard-web/chunks/{monitor-room-AQTHAWXA.js → monitor-room-7X5AKYOF.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-2R4NCNBQ.js → monitoring-page-CBA3CQYL.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-5M6MQIIL.js → office-page-RL6QSEM7.js} +1 -1
- package/dist/dashboard-web/chunks/{overview-page-N22HDZ2V.js → overview-page-XQIPO6KH.js} +1 -1
- package/dist/dashboard-web/chunks/{roles-page-J6K2HWFX.js → roles-page-ACIWV7QS.js} +1 -1
- package/dist/dashboard-web/chunks/{schedules-page-CGAQCB4J.js → schedules-page-KJDUKOJV.js} +1 -1
- package/dist/dashboard-web/chunks/sessions-page-2WDWHSP4.js +3 -0
- package/dist/dashboard-web/chunks/{settings-page-GLRWV5KU.js → settings-page-6VX4OUGG.js} +1 -1
- package/dist/dashboard-web/chunks/{skills-page-KQVW42QU.js → skills-page-WXE3UYLT.js} +1 -1
- package/dist/dashboard-web/chunks/{team-federation-page-5PYUOV5M.js → team-federation-page-PYTF4FLM.js} +1 -1
- package/dist/dashboard-web/chunks/{v3-page-DXPFILRZ.js → v3-page-G6CD6O3I.js} +1 -1
- package/dist/dashboard-web/chunks/{whiteboards-page-NUH6VZ4I.js → whiteboards-page-6SG33GP4.js} +1 -1
- package/dist/dashboard-web/style.css +167 -2
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +18 -3
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +18 -3
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +11 -2
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +4 -0
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +249 -5
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/forward-followup-buffer.d.ts +26 -0
- package/dist/im/lark/forward-followup-buffer.d.ts.map +1 -0
- package/dist/im/lark/forward-followup-buffer.js +48 -0
- package/dist/im/lark/forward-followup-buffer.js.map +1 -0
- package/dist/im/lark/forward-followup-content.d.ts +6 -0
- package/dist/im/lark/forward-followup-content.d.ts.map +1 -0
- package/dist/im/lark/forward-followup-content.js +46 -0
- package/dist/im/lark/forward-followup-content.js.map +1 -0
- package/dist/im/lark/forward-followup-store.d.ts +9 -0
- package/dist/im/lark/forward-followup-store.d.ts.map +1 -0
- package/dist/im/lark/forward-followup-store.js +48 -0
- package/dist/im/lark/forward-followup-store.js.map +1 -0
- package/dist/im/lark/message-parser.d.ts +1 -1
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +1 -2
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/platform/tunnel-client.js +3 -3
- package/dist/platform/tunnel-client.js.map +1 -1
- package/dist/services/local-cli-opener.d.ts +7 -0
- package/dist/services/local-cli-opener.d.ts.map +1 -1
- package/dist/services/local-cli-opener.js +111 -3
- package/dist/services/local-cli-opener.js.map +1 -1
- package/dist/services/skill-registry-store.d.ts.map +1 -1
- package/dist/services/skill-registry-store.js +15 -2
- package/dist/services/skill-registry-store.js.map +1 -1
- package/dist/services/vc-meeting-consumer-isolation.d.ts +7 -5
- package/dist/services/vc-meeting-consumer-isolation.d.ts.map +1 -1
- package/dist/services/vc-meeting-consumer-isolation.js +7 -5
- package/dist/services/vc-meeting-consumer-isolation.js.map +1 -1
- package/dist/services/vc-meeting-preparations-store.d.ts +22 -0
- package/dist/services/vc-meeting-preparations-store.d.ts.map +1 -0
- package/dist/services/vc-meeting-preparations-store.js +131 -0
- package/dist/services/vc-meeting-preparations-store.js.map +1 -0
- package/dist/services/vc-meeting-runtime-store.d.ts +9 -0
- package/dist/services/vc-meeting-runtime-store.d.ts.map +1 -1
- package/dist/services/vc-meeting-runtime-store.js +16 -0
- package/dist/services/vc-meeting-runtime-store.js.map +1 -1
- package/dist/setup/ensure-tmux.d.ts.map +1 -1
- package/dist/setup/ensure-tmux.js +9 -11
- package/dist/setup/ensure-tmux.js.map +1 -1
- package/dist/utils/child-env.d.ts +16 -8
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +30 -8
- package/dist/utils/child-env.js.map +1 -1
- package/dist/utils/daemon-discovery.d.ts +8 -0
- package/dist/utils/daemon-discovery.d.ts.map +1 -1
- package/dist/utils/daemon-discovery.js +19 -0
- package/dist/utils/daemon-discovery.js.map +1 -1
- package/dist/utils/ready-gate.d.ts +9 -3
- package/dist/utils/ready-gate.d.ts.map +1 -1
- package/dist/utils/ready-gate.js +12 -4
- package/dist/utils/ready-gate.js.map +1 -1
- package/dist/worker.js +131 -28
- package/dist/worker.js.map +1 -1
- package/dist/workflows/ops-projection.d.ts.map +1 -1
- package/dist/workflows/ops-projection.js +27 -5
- package/dist/workflows/ops-projection.js.map +1 -1
- package/dist/workflows/v3/distillation-runner.d.ts +4 -0
- package/dist/workflows/v3/distillation-runner.d.ts.map +1 -1
- package/dist/workflows/v3/distillation-runner.js +4 -2
- package/dist/workflows/v3/distillation-runner.js.map +1 -1
- package/package.json +1 -1
- package/dist/dashboard-web/chunks/sessions-page-WJ2QYTIE.js +0 -3
package/dist/worker.js
CHANGED
|
@@ -72,7 +72,7 @@ import { createCliAdapterSync, locateOnPath } from './adapters/cli/registry.js';
|
|
|
72
72
|
import { buildWrappedLaunch, parseWrapperCli, isTtadkWrapper } from './setup/cli-selection.js';
|
|
73
73
|
import { cliUnavailableMessage } from './setup/cli-availability.js';
|
|
74
74
|
import { findLaunchedCliPid, scheduleWrapperRealCliPid, readComm, isBareShellComm, bareShellLaunchKind } from './core/session-discovery.js';
|
|
75
|
-
import { claudeJsonlPathForSession, resolveJsonlFromPid, findOpenClaudeSessionIds, DEFAULT_CLAUDE_DATA_DIR } from './adapters/cli/claude-code.js';
|
|
75
|
+
import { claudeJsonlPathForSession, resolveJsonlFromPid, findOpenClaudeSessionIds, syncClaudeResumeTargetToCwd, DEFAULT_CLAUDE_DATA_DIR } from './adapters/cli/claude-code.js';
|
|
76
76
|
import { sessionReadyHookCommand } from './adapters/hook-command.js';
|
|
77
77
|
import { mtrSessionIdForBotmuxSession } from './adapters/cli/mtr.js';
|
|
78
78
|
import { HerdrBackend } from './adapters/backend/herdr-backend.js';
|
|
@@ -83,7 +83,7 @@ import { ZellijObserveBackend } from './adapters/backend/zellij-observe-backend.
|
|
|
83
83
|
import { zellijEnv } from './setup/ensure-zellij.js';
|
|
84
84
|
import { isObserveBackend } from './adapters/backend/types.js';
|
|
85
85
|
import { selectSessionBackend, decideBackendGate, backendGateUserMessage } from './adapters/backend/session-backend-selector.js';
|
|
86
|
-
import { deriveRiffReposFromDirs, deriveRiffRepoFromWorkingDir, isValidRiffBaseUrl } from './adapters/backend/riff-backend.js';
|
|
86
|
+
import { deriveRiffReposFromDirs, deriveRiffRepoFromWorkingDir, isValidRiffBaseUrl, isValidRiffSandboxCluster, } from './adapters/backend/riff-backend.js';
|
|
87
87
|
import { prepareSandbox, attachSandboxOutbox, startOutboxWatcher, sandboxEnabled, sandboxedClaudeDataDir, localSandboxApplies } from './adapters/backend/sandbox.js';
|
|
88
88
|
import { tmuxEnv, probeTmuxFunctionalWithRetry } from './setup/ensure-tmux.js';
|
|
89
89
|
import { tmuxRestartJitterMs } from './core/tmux-recovery.js';
|
|
@@ -102,12 +102,13 @@ import { config, resolveChatBotDiscoveryConfig } from './config.js';
|
|
|
102
102
|
import * as sessionStore from './services/session-store.js';
|
|
103
103
|
import * as pty from 'node-pty';
|
|
104
104
|
import { createHash } from 'node:crypto';
|
|
105
|
-
import { installHook } from './adapters/hook-installer.js';
|
|
105
|
+
import { hasInstalledSessionReadyHook, installHook, } from './adapters/hook-installer.js';
|
|
106
106
|
import { hookCommandFor } from './adapters/hook-command.js';
|
|
107
|
+
import { parseDaemonIpcPort } from './utils/daemon-discovery.js';
|
|
107
108
|
import { withCodexAppContext } from './utils/codex-app-context.js';
|
|
108
109
|
import { resolveCodexAppFinalTurnIdentity } from './adapters/cli/codex-app-turn.js';
|
|
109
110
|
import { RunnerControlDecoder } from './adapters/cli/runner-control-channel.js';
|
|
110
|
-
import { managedOriginCapabilityPath, RELAY_ORIGIN_CAPABILITY_BASENAME, replaceManagedOriginCapabilityFile, } from './core/managed-origin-capability.js';
|
|
111
|
+
import { hasMatchingManagedOriginCapability, managedOriginCapabilityPath, RELAY_ORIGIN_CAPABILITY_BASENAME, replaceManagedOriginCapabilityFile, } from './core/managed-origin-capability.js';
|
|
111
112
|
// ─── State ───────────────────────────────────────────────────────────────────
|
|
112
113
|
let cliAdapter = null;
|
|
113
114
|
let backend = null;
|
|
@@ -186,6 +187,24 @@ function provisionIsolatedBotHome(botHome, workingDir, isClaude, cliId, hookInst
|
|
|
186
187
|
if (isClaude) {
|
|
187
188
|
const cdir = join(botHome, 'claude');
|
|
188
189
|
mkdirSync(cdir, { recursive: true });
|
|
190
|
+
// Settings: read-isolated Claude uses a fresh CLAUDE_CONFIG_DIR, so it
|
|
191
|
+
// otherwise loses provider auth/model/proxy values held in the shared
|
|
192
|
+
// ~/.claude/settings.json `env` map. Merge that map on EVERY cold spawn,
|
|
193
|
+
// then install botmux hooks into the same per-bot file. Global hooks and
|
|
194
|
+
// unrelated top-level settings are not inherited.
|
|
195
|
+
const isolatedSettingsPath = join(cdir, 'settings.json');
|
|
196
|
+
if (hookInstall) {
|
|
197
|
+
try {
|
|
198
|
+
installHook(cliId, {
|
|
199
|
+
...hookInstall,
|
|
200
|
+
configPath: isolatedSettingsPath,
|
|
201
|
+
inheritClaudeEnvFrom: join(homedir(), '.claude', 'settings.json'),
|
|
202
|
+
}, hookCommandFor(cliId));
|
|
203
|
+
}
|
|
204
|
+
catch (e) {
|
|
205
|
+
log(`[read-isolation] WARN per-bot settings/hook install failed: ${e.message}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
189
208
|
// Auth: a fresh CLAUDE_CONFIG_DIR does NOT inherit the shared account's OAuth
|
|
190
209
|
// token → keep <cdir>/.credentials.json synced to the FRESHEST valid credential
|
|
191
210
|
// on EVERY spawn (verified: Claude logs in from that file). Refreshing here (not
|
|
@@ -194,24 +213,14 @@ function provisionIsolatedBotHome(botHome, workingDir, isClaude, cliId, hookInst
|
|
|
194
213
|
const fresh = freshestClaudeCred();
|
|
195
214
|
if (fresh)
|
|
196
215
|
writeCredIfChanged(join(cdir, '.credentials.json'), fresh);
|
|
197
|
-
else if (!existsSync(join(cdir, '.credentials.json'))
|
|
198
|
-
|
|
216
|
+
else if (!existsSync(join(cdir, '.credentials.json'))
|
|
217
|
+
&& !claudeSettingsHasProviderAuth(isolatedSettingsPath)) {
|
|
218
|
+
log(`[read-isolation] WARN no Claude provider auth found (global settings env, keychain, or ~/.claude/.credentials.json) — bot may hit login screen`);
|
|
199
219
|
}
|
|
200
220
|
// State: seed <cdir>/.claude.json from the GLOBAL one MINUS `projects` (keeps the
|
|
201
221
|
// onboarding/promo "seen" flags + account so no dialogs appear, without leaking
|
|
202
222
|
// other projects' data), then trust this bot's cwd. Merge-safe on resume.
|
|
203
223
|
seedAndTrustClaudeState(join(cdir, '.claude.json'), workingDir, log);
|
|
204
|
-
// Hooks: install the SessionStart-ready + askUserQuestion hooks into the PER-BOT
|
|
205
|
-
// settings.json (global ~/.claude/settings.json is Seatbelt-denied), else the
|
|
206
|
-
// worker's ready gate falls back to a slow timeout and AskUserQuestion won't relay.
|
|
207
|
-
if (hookInstall) {
|
|
208
|
-
try {
|
|
209
|
-
installHook(cliId, { ...hookInstall, configPath: join(cdir, 'settings.json') }, hookCommandFor(cliId));
|
|
210
|
-
}
|
|
211
|
-
catch (e) {
|
|
212
|
-
log(`[read-isolation] WARN per-bot hook install failed: ${e.message}`);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
224
|
}
|
|
216
225
|
else {
|
|
217
226
|
const cdir = join(botHome, 'codex');
|
|
@@ -232,6 +241,22 @@ function provisionIsolatedBotHome(botHome, workingDir, isClaude, cliId, hookInst
|
|
|
232
241
|
log(`[read-isolation] WARN provisioning bot home failed: ${e.message}`);
|
|
233
242
|
}
|
|
234
243
|
}
|
|
244
|
+
function claudeSettingsHasProviderAuth(settingsPath) {
|
|
245
|
+
try {
|
|
246
|
+
const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
247
|
+
const env = settings.env;
|
|
248
|
+
if (!env || typeof env !== 'object' || Array.isArray(env))
|
|
249
|
+
return false;
|
|
250
|
+
const record = env;
|
|
251
|
+
return ((typeof record.ANTHROPIC_AUTH_TOKEN === 'string' && record.ANTHROPIC_AUTH_TOKEN.length > 0)
|
|
252
|
+
|| (typeof record.ANTHROPIC_API_KEY === 'string' && record.ANTHROPIC_API_KEY.length > 0)
|
|
253
|
+
|| record.CLAUDE_CODE_USE_BEDROCK === '1'
|
|
254
|
+
|| record.CLAUDE_CODE_USE_VERTEX === '1');
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
235
260
|
/** Pick the FRESHEST valid Claude OAuth credential: macOS keychain vs the global
|
|
236
261
|
* `~/.claude/.credentials.json`, by `claudeAiOauth.expiresAt` (longest runway
|
|
237
262
|
* wins — a re-login updates one of the two, and this picks whichever is newer).
|
|
@@ -789,18 +814,28 @@ function publishSandboxRelayCapability(opts = {}) {
|
|
|
789
814
|
}]
|
|
790
815
|
: []),
|
|
791
816
|
];
|
|
817
|
+
let publishError;
|
|
792
818
|
for (const file of files) {
|
|
793
819
|
try {
|
|
794
820
|
replaceManagedOriginCapabilityFile(file.path, file.body);
|
|
795
821
|
}
|
|
796
822
|
catch (err) {
|
|
797
823
|
log(`Failed to publish managed origin capability: ${err?.message ?? err}`);
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
throw err;
|
|
801
|
-
}
|
|
824
|
+
publishError = err;
|
|
825
|
+
break;
|
|
802
826
|
}
|
|
803
827
|
}
|
|
828
|
+
if (publishError) {
|
|
829
|
+
// The disk/daemon/worker views must rotate as one authority generation. If
|
|
830
|
+
// the child-visible transport cannot publish the new token, revoke the old
|
|
831
|
+
// generation and leave no in-memory authority for ready/send preflights to
|
|
832
|
+
// mistake as usable. Any files written before a later failure are removed
|
|
833
|
+
// by the revocation helper as well.
|
|
834
|
+
completeManagedTurnOriginRevocation(sandboxRelayCapability, currentBotmuxTurnId, currentBotmuxDispatchAttempt);
|
|
835
|
+
if (opts.failClosed)
|
|
836
|
+
throw publishError;
|
|
837
|
+
return false;
|
|
838
|
+
}
|
|
804
839
|
sandboxRelayCapability = capability;
|
|
805
840
|
if (sessionId) {
|
|
806
841
|
send({
|
|
@@ -813,6 +848,7 @@ function publishSandboxRelayCapability(opts = {}) {
|
|
|
813
848
|
: {}),
|
|
814
849
|
});
|
|
815
850
|
}
|
|
851
|
+
return true;
|
|
816
852
|
}
|
|
817
853
|
function unlinkManagedOriginCapabilityFiles() {
|
|
818
854
|
const files = [
|
|
@@ -4381,8 +4417,14 @@ function detectBareShellLaunch() {
|
|
|
4381
4417
|
else {
|
|
4382
4418
|
message =
|
|
4383
4419
|
`⚠️ 会话没能启动:pane 里还停在 \`${comm}\`,${cli} 没真正跑起来——我没把消息打进去(否则会被当 shell 命令执行)。\n\n` +
|
|
4384
|
-
|
|
4385
|
-
|
|
4420
|
+
`最常见原因:rc 文件里有交互式提示卡住了 shell 启动,例如:\n` +
|
|
4421
|
+
`① Oh My Zsh 升级提示("Would you like to update Oh My Zsh? [Y/n]")——${comm} source ~/.zshrc 时弹出,等你按 Y/n,CLI 的启动命令没机会跑\n` +
|
|
4422
|
+
`② git 凭据弹窗(GIT_TERMINAL_PROMPT)或其它需要交互输入的启动脚本\n` +
|
|
4423
|
+
`③ ${cli} 的可执行文件不在 PATH 上(CLI 没找到)\n\n` +
|
|
4424
|
+
`修法(任选其一,改完重启 daemon 再发一条消息):\n` +
|
|
4425
|
+
`• 最省事:升级 botmux 到含自动注入 DISABLE_AUTO_UPDATE=true 的版本(仅 botmux 托管 shell 启动时跳过 oh-my-zsh 升级检查,不影响你自己的终端)\n` +
|
|
4426
|
+
`• 手动修:在 ~/.zshrc 的 source $ZSH/oh-my-zsh.sh 之前加一行 DISABLE_UPDATE_PROMPT="true"(自动升级不弹提示);或加 DISABLE_AUTO_UPDATE="true"(完全跳过升级检查)\n` +
|
|
4427
|
+
`• 在 web 终端里手动敲一下启动命令看报什么错;确认 CLI 二进制能在 PATH 上找到;或精简 rc 启动逻辑后重启 daemon 再试`;
|
|
4386
4428
|
}
|
|
4387
4429
|
send({ type: 'user_notify', turnId: currentBotmuxTurnId, dispatchAttempt: currentBotmuxDispatchAttempt, message });
|
|
4388
4430
|
return true;
|
|
@@ -5300,6 +5342,9 @@ function spawnCli(cfg) {
|
|
|
5300
5342
|
if (!isValidRiffBaseUrl(cfg.backendConfig.baseUrl)) {
|
|
5301
5343
|
throw new Error(`riff baseUrl 未配置或非法(需 http(s) URL,当前: ${JSON.stringify(cfg.backendConfig.baseUrl ?? null)})——请在 dashboard 的 Riff 配置中填写`);
|
|
5302
5344
|
}
|
|
5345
|
+
if (cfg.backendConfig.sandboxCluster !== undefined && !isValidRiffSandboxCluster(cfg.backendConfig.sandboxCluster)) {
|
|
5346
|
+
throw new Error(`riff sandboxCluster 非法(仅支持 boe/cn,当前: ${JSON.stringify(cfg.backendConfig.sandboxCluster)})——请在 dashboard 的 Riff 配置中重新选择`);
|
|
5347
|
+
}
|
|
5303
5348
|
const sessionEnv = {
|
|
5304
5349
|
BOTMUX_SESSION_ID: cfg.sessionId,
|
|
5305
5350
|
BOTMUX_CHAT_ID: cfg.chatId,
|
|
@@ -5372,6 +5417,7 @@ function spawnCli(cfg) {
|
|
|
5372
5417
|
// JSONL/pid/bridge gate below keys off it instead of `cliId === 'claude-code'`,
|
|
5373
5418
|
// so a fork inherits the whole submit-confirm + bridge-fallback machinery.
|
|
5374
5419
|
let claudeDataDir = cliAdapter.claudeDataDir;
|
|
5420
|
+
let effectiveReadyHookInstall = cliAdapter.hookInstall;
|
|
5375
5421
|
// When this session will be file-sandboxed, the CLI's session jsonl is written
|
|
5376
5422
|
// into the overlay's EPHEMERAL home upper (CLAUDE_CONFIG_DIR lives under $HOME),
|
|
5377
5423
|
// invisible at the real path the bridge normally watches → "Bridge mark expired"
|
|
@@ -5382,7 +5428,10 @@ function spawnCli(cfg) {
|
|
|
5382
5428
|
(effectiveBackendType === 'pty' || effectiveBackendType === 'tmux') &&
|
|
5383
5429
|
!!process.env.SESSION_DATA_DIR;
|
|
5384
5430
|
if (claudeDataDir && willFileSandbox) {
|
|
5385
|
-
const redirected = sandboxedClaudeDataDir(cfg.sessionId, claudeDataDir
|
|
5431
|
+
const redirected = sandboxedClaudeDataDir(cfg.sessionId, claudeDataDir, {
|
|
5432
|
+
sourceWorkingDir: cfg.workingDir,
|
|
5433
|
+
dataDir: process.env.SESSION_DATA_DIR,
|
|
5434
|
+
});
|
|
5386
5435
|
log(`[sandbox] redirecting Claude bridge dataDir → overlay upper: ${redirected}`);
|
|
5387
5436
|
claudeDataDir = redirected;
|
|
5388
5437
|
}
|
|
@@ -5465,6 +5514,12 @@ function spawnCli(cfg) {
|
|
|
5465
5514
|
// Provision the per-bot config dir (auth + onboarding/trust seed + hooks for claude;
|
|
5466
5515
|
// auth/config copy for codex) so the CLI starts fully set up under the Seatbelt wrapper.
|
|
5467
5516
|
provisionIsolatedBotHome(isolationBotHome, cfg.workingDir, isClaudeFam, cfg.cliId, cliAdapter.hookInstall, log);
|
|
5517
|
+
if (isClaudeFam && effectiveReadyHookInstall) {
|
|
5518
|
+
effectiveReadyHookInstall = {
|
|
5519
|
+
...effectiveReadyHookInstall,
|
|
5520
|
+
configPath: join(claudeDataDir, 'settings.json'),
|
|
5521
|
+
};
|
|
5522
|
+
}
|
|
5468
5523
|
if (cliAdapter.mcpGateway) {
|
|
5469
5524
|
const isolatedConfigPath = isClaudeFam
|
|
5470
5525
|
? join(claudeDataDir, '.claude.json')
|
|
@@ -5586,6 +5641,26 @@ function spawnCli(cfg) {
|
|
|
5586
5641
|
let effectiveResume = cfg.resume ?? false;
|
|
5587
5642
|
let effectiveCliSessionId = cfg.cliSessionId;
|
|
5588
5643
|
let effectiveAdapterSessionId = adapterSessionId;
|
|
5644
|
+
// Claude-family transcripts are scoped by cwd. `/cd` keeps the same Botmux /
|
|
5645
|
+
// CLI session id, so mirror the newest native transcript into the new cwd's
|
|
5646
|
+
// project directory before the adapter probes or launches `--resume`.
|
|
5647
|
+
// `claudeDataDir` is already the effective root here (global, per-bot read
|
|
5648
|
+
// isolation root, or a preserved sandbox upper), so this never crosses bot
|
|
5649
|
+
// isolation boundaries.
|
|
5650
|
+
if (effectiveResume && !willReattachPersistent && claudeDataDir) {
|
|
5651
|
+
const resumeSessionId = effectiveCliSessionId ?? effectiveAdapterSessionId;
|
|
5652
|
+
try {
|
|
5653
|
+
const synced = syncClaudeResumeTargetToCwd(resumeSessionId, cfg.workingDir, claudeDataDir);
|
|
5654
|
+
if (synced.copied && synced.sourcePath) {
|
|
5655
|
+
log(`Claude resume transcript synced for cwd change: ${synced.sourcePath} → ${synced.targetPath}`);
|
|
5656
|
+
}
|
|
5657
|
+
}
|
|
5658
|
+
catch (err) {
|
|
5659
|
+
// Preserve the existing fail-safe: the adapter probe / two-tier fallback
|
|
5660
|
+
// below still decides whether resume is possible.
|
|
5661
|
+
log(`WARN Claude resume transcript sync failed: ${err.message}`);
|
|
5662
|
+
}
|
|
5663
|
+
}
|
|
5589
5664
|
const tier2ForceFresh = effectiveResume && consecutiveInWorkerRestarts >= 2;
|
|
5590
5665
|
let tier1ProbeFalse = false;
|
|
5591
5666
|
if (effectiveResume && !tier2ForceFresh && !willReattachPersistent) {
|
|
@@ -6461,15 +6536,22 @@ function spawnCli(cfg) {
|
|
|
6461
6536
|
codexBridgeStartTimer();
|
|
6462
6537
|
}
|
|
6463
6538
|
}
|
|
6464
|
-
// Arm the ready-gate for FRESH
|
|
6465
|
-
// SessionStart hook via --settings; see claude-code.ts buildArgs). Until
|
|
6539
|
+
// Arm the ready-gate for FRESH ready-integrated spawns. Until
|
|
6466
6540
|
// `botmux session-ready` fires (daemon → 'session_ready' IPC → releaseReadyGate)
|
|
6467
6541
|
// we hold the first prompt so a cjadk-style startup selector's ❯ can't eat it.
|
|
6468
|
-
// shouldArmReadyGate() excludes adopt (pre-existing pane, no
|
|
6542
|
+
// shouldArmReadyGate() excludes adopt (pre-existing pane, no fresh hook) AND
|
|
6469
6543
|
// persistent-backend reattach (daemon restart re-attaches an already-running
|
|
6470
6544
|
// tmux/zellij/herdr Claude WITHOUT re-running its bin/args → no new
|
|
6471
6545
|
// SessionStart hook → arming would hold the first post-recovery message until
|
|
6472
|
-
// the timeout).
|
|
6546
|
+
// the timeout).
|
|
6547
|
+
//
|
|
6548
|
+
// Installation is best-effort, so verify the hook in the EFFECTIVE config
|
|
6549
|
+
// (global for ordinary sessions, per-bot CLAUDE_CONFIG_DIR under read
|
|
6550
|
+
// isolation) before arming. Isolated children also need the injected loopback
|
|
6551
|
+
// port plus a published rotating capability; without either the hook could
|
|
6552
|
+
// run but never reach the daemon. A failed preflight leaves the gate open and
|
|
6553
|
+
// immediately falls back to the adapter's normal readyPattern/quiescence path
|
|
6554
|
+
// instead of blindly waiting READY_SIGNAL_TIMEOUT_MS.
|
|
6473
6555
|
readyGate = new ReadyGate();
|
|
6474
6556
|
if (readySignalTimer) {
|
|
6475
6557
|
clearTimeout(readySignalTimer);
|
|
@@ -6483,8 +6565,29 @@ function spawnCli(cfg) {
|
|
|
6483
6565
|
promptReadyDetectedDuringSettle = false;
|
|
6484
6566
|
// Reset quiescence baseline so the settle measures silence from THIS spawn.
|
|
6485
6567
|
lastPtyOutputAtMs = Date.now();
|
|
6568
|
+
const readyHookAvailable = effectiveReadyHookInstall
|
|
6569
|
+
? hasInstalledSessionReadyHook(effectiveReadyHookInstall)
|
|
6570
|
+
: true; // Hermes emits BOTMUX_READY_COMMAND directly instead of a config hook.
|
|
6571
|
+
const isolatedReadyTransportRequired = sandboxOn || willReadIsolate;
|
|
6572
|
+
const readyPortAvailable = !isolatedReadyTransportRequired
|
|
6573
|
+
|| parseDaemonIpcPort(childEnv.BOTMUX_DAEMON_IPC_PORT) !== undefined;
|
|
6574
|
+
const readyCapabilityAvailable = !isolatedReadyTransportRequired
|
|
6575
|
+
|| hasMatchingManagedOriginCapability(process.env.SESSION_DATA_DIR ?? '', cfg.sessionId, sandboxRelayCapability?.token, sandboxRelayOutbox ?? undefined);
|
|
6576
|
+
const readySignalAvailable = readyHookAvailable && readyPortAvailable && readyCapabilityAvailable;
|
|
6577
|
+
const freshReadyGateCandidate = cliAdapter.injectsReadyHook === true
|
|
6578
|
+
&& cfg.adoptMode !== true
|
|
6579
|
+
&& !willReattachPersistent;
|
|
6580
|
+
if (freshReadyGateCandidate && !readySignalAvailable) {
|
|
6581
|
+
const reasons = [
|
|
6582
|
+
...(!readyHookAvailable ? ['SessionStart hook missing from effective config'] : []),
|
|
6583
|
+
...(!readyPortAvailable ? ['BOTMUX_DAEMON_IPC_PORT missing/invalid'] : []),
|
|
6584
|
+
...(!readyCapabilityAvailable ? ['ready capability transport missing, unreadable, or stale'] : []),
|
|
6585
|
+
];
|
|
6586
|
+
log(`Ready gate skipped — preflight failed: ${reasons.join('; ')}`);
|
|
6587
|
+
}
|
|
6486
6588
|
if (shouldArmReadyGate({
|
|
6487
6589
|
injectsReadyHook: cliAdapter.injectsReadyHook === true,
|
|
6590
|
+
readySignalAvailable,
|
|
6488
6591
|
adoptMode: cfg.adoptMode === true,
|
|
6489
6592
|
willReattachPersistent,
|
|
6490
6593
|
})) {
|