switchroom 0.13.2 → 0.13.4
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/agent-scheduler/index.js +2 -2
- package/dist/auth-broker/index.js +2 -2
- package/dist/cli/switchroom.js +132 -214
- package/dist/host-control/main.js +2 -2
- package/dist/vault/approvals/kernel-server.js +2 -2
- package/dist/vault/broker/server.js +2 -2
- package/package.json +1 -1
- package/profiles/_base/start.sh.hbs +8 -8
- package/profiles/default/CLAUDE.md.hbs +1 -1
- package/telegram-plugin/dist/gateway/gateway.js +42 -10
- package/telegram-plugin/gateway/boot-probes.ts +13 -6
- package/telegram-plugin/gateway/gateway.ts +44 -6
- package/telegram-plugin/hooks/silent-end-interrupt-stop.mjs +5 -1
- package/telegram-plugin/silent-end.ts +56 -0
- package/telegram-plugin/tests/boot-probes.test.ts +26 -2
- package/telegram-plugin/tests/silent-end.test.ts +69 -0
- package/telegram-plugin/uat/scenarios/bridge-flap-resilience-dm.test.ts +166 -0
- package/skills/buildkite-agent-infrastructure/SKILL.md +0 -321
- package/skills/buildkite-agent-infrastructure/agents/openai.yaml +0 -6
- package/skills/buildkite-agent-infrastructure/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-agent-infrastructure/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-agent-infrastructure/references/audit-logging.md +0 -87
- package/skills/buildkite-agent-infrastructure/references/graphql-mutations.md +0 -690
- package/skills/buildkite-agent-infrastructure/references/instance-shapes.md +0 -38
- package/skills/buildkite-agent-infrastructure/references/pipeline-templates.md +0 -73
- package/skills/buildkite-agent-infrastructure/references/self-hosted-agents.md +0 -137
- package/skills/buildkite-agent-infrastructure/references/sso-saml.md +0 -92
- package/skills/buildkite-agent-runtime/SKILL.md +0 -509
- package/skills/buildkite-agent-runtime/agents/openai.yaml +0 -6
- package/skills/buildkite-agent-runtime/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-agent-runtime/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-agent-runtime/references/flag-reference.md +0 -417
- package/skills/buildkite-agent-runtime/references/patterns-and-recipes.md +0 -555
- package/skills/buildkite-api/SKILL.md +0 -308
- package/skills/buildkite-api/agents/openai.yaml +0 -6
- package/skills/buildkite-api/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-api/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-api/references/graphql-reference.md +0 -195
- package/skills/buildkite-api/references/patterns.md +0 -44
- package/skills/buildkite-api/references/webhooks.md +0 -161
- package/skills/buildkite-cli/SKILL.md +0 -397
- package/skills/buildkite-cli/agents/openai.yaml +0 -6
- package/skills/buildkite-cli/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-cli/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-cli/references/command-reference.md +0 -181
- package/skills/buildkite-migration/SKILL.md +0 -195
- package/skills/buildkite-pipelines/SKILL.md +0 -481
- package/skills/buildkite-pipelines/agents/openai.yaml +0 -6
- package/skills/buildkite-pipelines/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-pipelines/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-pipelines/examples/basic-pipeline.yml +0 -24
- package/skills/buildkite-pipelines/examples/optimized-pipeline.yml +0 -100
- package/skills/buildkite-pipelines/references/advanced-patterns.md +0 -286
- package/skills/buildkite-pipelines/references/retry-and-error-codes.md +0 -131
- package/skills/buildkite-pipelines/references/step-types-reference.md +0 -225
- package/skills/buildkite-secure-delivery/SKILL.md +0 -182
- package/skills/buildkite-secure-delivery/agents/openai.yaml +0 -6
- package/skills/buildkite-secure-delivery/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-secure-delivery/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-secure-delivery/references/oidc-cloud-providers.md +0 -83
- package/skills/buildkite-secure-delivery/references/package-publishing.md +0 -100
- package/skills/buildkite-test-engine/SKILL.md +0 -256
- package/skills/buildkite-test-engine/agents/openai.yaml +0 -6
- package/skills/buildkite-test-engine/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-test-engine/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-test-engine/examples/bktec-splitting.yml +0 -16
- package/skills/buildkite-test-engine/examples/collector-pipeline.yml +0 -11
- package/skills/buildkite-test-engine/references/collectors.md +0 -198
- package/skills/buildkite-test-engine/references/splitting-examples.md +0 -93
package/dist/cli/switchroom.js
CHANGED
|
@@ -13694,7 +13694,7 @@ var init_schema = __esm(() => {
|
|
|
13694
13694
|
extends: exports_external.string().optional(),
|
|
13695
13695
|
bot_token: exports_external.string().optional(),
|
|
13696
13696
|
release: ReleaseBlock.optional().describe("Release-channel pin / pointer. Either `channel` (dev|rc|latest) or " + "`pin` (sha-<hex>|v<semver>) \u2014 mutually exclusive. Per-agent value " + "REPLACES the root entirely (no field merge)."),
|
|
13697
|
-
timezone: exports_external.string().regex(TIMEZONE_REGEX, "timezone must be an IANA zone name like 'Australia/Melbourne' or 'UTC' " + "(three-letter aliases like EST/PST and bare offsets like UTC+10 are not accepted)").optional().describe("IANA timezone name (e.g. 'Australia/Melbourne', 'America/New_York', " + "'UTC'). Used to generate the per-turn local-time hint the agent's " + "UserPromptSubmit timezone hook emits, and baked into the
|
|
13697
|
+
timezone: exports_external.string().regex(TIMEZONE_REGEX, "timezone must be an IANA zone name like 'Australia/Melbourne' or 'UTC' " + "(three-letter aliases like EST/PST and bare offsets like UTC+10 are not accepted)").optional().describe("IANA timezone name (e.g. 'Australia/Melbourne', 'America/New_York', " + "'UTC'). Used to generate the per-turn local-time hint the agent's " + "UserPromptSubmit timezone hook emits, and baked into the agent " + "container's `environment.TZ` in compose so subprocess `date`/" + "`Date.now()` are correct. If unset at every cascade layer, switchroom " + "auto-detects from /etc/timezone and warns on `reconcile` when the " + "detected zone is UTC."),
|
|
13698
13698
|
soul: exports_external.object({
|
|
13699
13699
|
name: exports_external.string().optional(),
|
|
13700
13700
|
style: exports_external.string().optional(),
|
|
@@ -13755,7 +13755,7 @@ var init_schema = __esm(() => {
|
|
|
13755
13755
|
bot_token: exports_external.string().optional().describe("Per-agent Telegram bot token or vault reference (overrides global telegram.bot_token)"),
|
|
13756
13756
|
release: ReleaseBlock.optional().describe("Per-agent release-channel pin / pointer. REPLACES the root " + "`release` block entirely (no field merge) \u2014 a pinned agent does " + "not inherit the fleet channel, and vice versa."),
|
|
13757
13757
|
bot_username: exports_external.string().optional().describe("Per-agent Telegram bot username (without leading @) when it doesn't " + "contain the agent slug. Replaces the default 'username includes slug' " + "preflight check with an exact (case-insensitive) match. Use when an " + "agent and its bot have intentionally divergent names (e.g. agent " + "'lawgpt' paired with bot '@meken_law_bot')."),
|
|
13758
|
-
timezone: exports_external.string().regex(TIMEZONE_REGEX, "timezone must be an IANA zone name like 'Australia/Melbourne' or 'UTC' " + "(three-letter aliases like EST/PST and bare offsets like UTC+10 are not accepted)").optional().describe("Per-agent IANA timezone override. Wins over any profile/defaults " + "value and over the top-level switchroom.timezone global. Controls " + "the UserPromptSubmit timezone hook's emitted local time and the " + "
|
|
13758
|
+
timezone: exports_external.string().regex(TIMEZONE_REGEX, "timezone must be an IANA zone name like 'Australia/Melbourne' or 'UTC' " + "(three-letter aliases like EST/PST and bare offsets like UTC+10 are not accepted)").optional().describe("Per-agent IANA timezone override. Wins over any profile/defaults " + "value and over the top-level switchroom.timezone global. Controls " + "the UserPromptSubmit timezone hook's emitted local time and the " + "agent container's `environment.TZ` in compose."),
|
|
13759
13759
|
auth: exports_external.object({
|
|
13760
13760
|
override: exports_external.string().min(1).optional().describe("Per-agent override of the fleet-wide `auth.active`. Edge-case use only \u2014 " + "this agent talks to the named account regardless of fleet active. See RFC H \u00a74.5.")
|
|
13761
13761
|
}).optional().describe("Account routing for switchroom-auth-broker. RFC H schema uses " + "fleet-wide `auth.active` plus per-agent `override:` for edge cases. " + "Pre-RFC-H `auth.accounts: [..]` and `auth_label:` are migrated in-place " + "on first apply (see src/auth/migrate-schema.ts)."),
|
|
@@ -23872,7 +23872,7 @@ import {
|
|
|
23872
23872
|
existsSync as existsSync17,
|
|
23873
23873
|
mkdirSync as mkdirSync12,
|
|
23874
23874
|
readFileSync as readFileSync17,
|
|
23875
|
-
readdirSync as
|
|
23875
|
+
readdirSync as readdirSync8,
|
|
23876
23876
|
renameSync as renameSync5,
|
|
23877
23877
|
rmSync as rmSync4,
|
|
23878
23878
|
statSync as statSync11,
|
|
@@ -23943,7 +23943,7 @@ function listSlots(agentDir) {
|
|
|
23943
23943
|
if (!existsSync17(dir))
|
|
23944
23944
|
return [];
|
|
23945
23945
|
try {
|
|
23946
|
-
return
|
|
23946
|
+
return readdirSync8(dir).filter((name) => {
|
|
23947
23947
|
try {
|
|
23948
23948
|
return statSync11(join13(dir, name)).isDirectory();
|
|
23949
23949
|
} catch {
|
|
@@ -24115,7 +24115,7 @@ var init_accounts = __esm(() => {
|
|
|
24115
24115
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
24116
24116
|
import {
|
|
24117
24117
|
readFileSync as readFileSync18,
|
|
24118
|
-
readdirSync as
|
|
24118
|
+
readdirSync as readdirSync9,
|
|
24119
24119
|
existsSync as existsSync18,
|
|
24120
24120
|
writeFileSync as writeFileSync10,
|
|
24121
24121
|
mkdirSync as mkdirSync13,
|
|
@@ -24272,7 +24272,7 @@ function cleanupAuthTempDirs(agentDir) {
|
|
|
24272
24272
|
if (!existsSync18(dir))
|
|
24273
24273
|
return;
|
|
24274
24274
|
try {
|
|
24275
|
-
for (const entry of
|
|
24275
|
+
for (const entry of readdirSync9(dir)) {
|
|
24276
24276
|
if (entry.startsWith(".setup-token-tmp-")) {
|
|
24277
24277
|
rmSync5(join14(dir, entry), { recursive: true, force: true });
|
|
24278
24278
|
}
|
|
@@ -25226,7 +25226,7 @@ class AuthBrokerClient {
|
|
|
25226
25226
|
closed = false;
|
|
25227
25227
|
constructor(opts = {}) {
|
|
25228
25228
|
this.socketPath = resolveAuthBrokerSocketPath(opts);
|
|
25229
|
-
this.timeoutMs = opts.timeoutMs ??
|
|
25229
|
+
this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
25230
25230
|
}
|
|
25231
25231
|
getSocketPath() {
|
|
25232
25232
|
return this.socketPath;
|
|
@@ -25477,7 +25477,7 @@ async function withAuthBrokerClient(fn, opts) {
|
|
|
25477
25477
|
function authBrokerSocketExists(opts) {
|
|
25478
25478
|
return existsSync25(resolveAuthBrokerSocketPath(opts));
|
|
25479
25479
|
}
|
|
25480
|
-
var
|
|
25480
|
+
var DEFAULT_TIMEOUT_MS2 = 5000, AuthBrokerError, AuthBrokerUnreachableError;
|
|
25481
25481
|
var init_client2 = __esm(() => {
|
|
25482
25482
|
init_protocol2();
|
|
25483
25483
|
AuthBrokerError = class AuthBrokerError extends Error {
|
|
@@ -25537,7 +25537,7 @@ import {
|
|
|
25537
25537
|
existsSync as existsSync26,
|
|
25538
25538
|
mkdirSync as mkdirSync15,
|
|
25539
25539
|
readFileSync as readFileSync22,
|
|
25540
|
-
readdirSync as
|
|
25540
|
+
readdirSync as readdirSync13,
|
|
25541
25541
|
renameSync as renameSync6,
|
|
25542
25542
|
rmSync as rmSync10,
|
|
25543
25543
|
statSync as statSync15,
|
|
@@ -25568,7 +25568,7 @@ function listAccounts(home2 = homedir8()) {
|
|
|
25568
25568
|
if (!existsSync26(root))
|
|
25569
25569
|
return [];
|
|
25570
25570
|
try {
|
|
25571
|
-
return
|
|
25571
|
+
return readdirSync13(root).filter((name) => {
|
|
25572
25572
|
try {
|
|
25573
25573
|
return statSync15(join19(root, name)).isDirectory();
|
|
25574
25574
|
} catch {
|
|
@@ -25730,7 +25730,7 @@ __export(exports_oauth, {
|
|
|
25730
25730
|
});
|
|
25731
25731
|
import * as http from "node:http";
|
|
25732
25732
|
import * as crypto2 from "node:crypto";
|
|
25733
|
-
import { spawn as
|
|
25733
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
25734
25734
|
function detectHeadless(env2) {
|
|
25735
25735
|
const hasDisplay = Boolean(env2.DISPLAY && env2.DISPLAY.trim() !== "" || env2.WAYLAND_DISPLAY && env2.WAYLAND_DISPLAY.trim() !== "");
|
|
25736
25736
|
const inSsh = Boolean(env2.SSH_CONNECTION && env2.SSH_CONNECTION.trim() !== "" || env2.SSH_TTY && env2.SSH_TTY.trim() !== "");
|
|
@@ -25890,7 +25890,7 @@ function buildLoopbackAuthUrl(cfg, redirectUri, state) {
|
|
|
25890
25890
|
u.searchParams.set("state", state);
|
|
25891
25891
|
return u.toString();
|
|
25892
25892
|
}
|
|
25893
|
-
async function openBrowser(url, platform = process.platform, spawnImpl =
|
|
25893
|
+
async function openBrowser(url, platform = process.platform, spawnImpl = spawn2) {
|
|
25894
25894
|
let cmd;
|
|
25895
25895
|
let args;
|
|
25896
25896
|
if (platform === "darwin") {
|
|
@@ -26407,7 +26407,7 @@ async function waitForApproval(opts) {
|
|
|
26407
26407
|
const request = opts._request ?? approvalRequest;
|
|
26408
26408
|
const lookup = opts._lookup ?? approvalLookup;
|
|
26409
26409
|
const sleep3 = opts._sleep ?? defaultSleep;
|
|
26410
|
-
const timeoutMs = opts.timeout_ms ??
|
|
26410
|
+
const timeoutMs = opts.timeout_ms ?? DEFAULT_TIMEOUT_MS3;
|
|
26411
26411
|
const initialPoll = opts.initial_poll_ms ?? DEFAULT_INITIAL_POLL_MS;
|
|
26412
26412
|
const maxPoll = opts.max_poll_ms ?? DEFAULT_MAX_POLL_MS;
|
|
26413
26413
|
const backoff = opts.backoff ?? DEFAULT_BACKOFF;
|
|
@@ -26495,7 +26495,7 @@ async function waitForApproval(opts) {
|
|
|
26495
26495
|
}
|
|
26496
26496
|
}
|
|
26497
26497
|
}
|
|
26498
|
-
var
|
|
26498
|
+
var DEFAULT_TIMEOUT_MS3 = 600000, DEFAULT_INITIAL_POLL_MS = 2000, DEFAULT_MAX_POLL_MS = 30000, DEFAULT_BACKOFF = 1.5, DENY_MODES;
|
|
26499
26499
|
var init_wait = __esm(() => {
|
|
26500
26500
|
init_client3();
|
|
26501
26501
|
DENY_MODES = new Set(["deny", "deny_perm"]);
|
|
@@ -27053,7 +27053,7 @@ async function runViaClaude(opts) {
|
|
|
27053
27053
|
if (tmuxHasSession(SESSION))
|
|
27054
27054
|
tmuxKillSession(SESSION);
|
|
27055
27055
|
}
|
|
27056
|
-
const
|
|
27056
|
+
const spawn3 = opts.spawnClaude ?? (() => {
|
|
27057
27057
|
execFileSync11("tmux", [
|
|
27058
27058
|
"new-session",
|
|
27059
27059
|
"-d",
|
|
@@ -27069,7 +27069,7 @@ async function runViaClaude(opts) {
|
|
|
27069
27069
|
], { stdio: "ignore", timeout: 5000 });
|
|
27070
27070
|
});
|
|
27071
27071
|
log(" Spawning claude in a tmux session to mint a broader-scope OAuth token\u2026");
|
|
27072
|
-
|
|
27072
|
+
spawn3();
|
|
27073
27073
|
try {
|
|
27074
27074
|
const preFired = new Set;
|
|
27075
27075
|
const phase1Deadline = Date.now() + urlTimeout;
|
|
@@ -27605,7 +27605,7 @@ var init_doctor_status = __esm(() => {
|
|
|
27605
27605
|
import {
|
|
27606
27606
|
existsSync as existsSync46,
|
|
27607
27607
|
readFileSync as readFileSync42,
|
|
27608
|
-
readdirSync as
|
|
27608
|
+
readdirSync as readdirSync17
|
|
27609
27609
|
} from "node:fs";
|
|
27610
27610
|
import { dirname as dirname11, join as join38 } from "node:path";
|
|
27611
27611
|
import { execSync as execSync2 } from "node:child_process";
|
|
@@ -27686,7 +27686,7 @@ function probePlaywrightMcpVersion() {
|
|
|
27686
27686
|
if (!existsSync46(npxCache))
|
|
27687
27687
|
return null;
|
|
27688
27688
|
try {
|
|
27689
|
-
const entries =
|
|
27689
|
+
const entries = readdirSync17(npxCache);
|
|
27690
27690
|
for (const entry of entries) {
|
|
27691
27691
|
const pkgPath = join38(npxCache, entry, "node_modules/@playwright/mcp/package.json");
|
|
27692
27692
|
if (existsSync46(pkgPath)) {
|
|
@@ -28834,7 +28834,7 @@ import { join as join42 } from "node:path";
|
|
|
28834
28834
|
function runCredentialsMigrationChecks(config, deps = {}) {
|
|
28835
28835
|
const credDir = deps.credentialsDir ?? join42(homedir23(), ".switchroom", "credentials");
|
|
28836
28836
|
const existsSync49 = deps.existsSync ?? ((p) => realExistsSync2(p));
|
|
28837
|
-
const
|
|
28837
|
+
const readdirSync19 = deps.readdirSync ?? ((p) => realReaddirSync(p));
|
|
28838
28838
|
const isDirectory = deps.isDirectory ?? ((p) => {
|
|
28839
28839
|
try {
|
|
28840
28840
|
return realStatSync(p).isDirectory();
|
|
@@ -28847,7 +28847,7 @@ function runCredentialsMigrationChecks(config, deps = {}) {
|
|
|
28847
28847
|
const agentNames = new Set(Object.keys(config.agents ?? {}));
|
|
28848
28848
|
let entries;
|
|
28849
28849
|
try {
|
|
28850
|
-
entries =
|
|
28850
|
+
entries = readdirSync19(credDir);
|
|
28851
28851
|
} catch {
|
|
28852
28852
|
return [
|
|
28853
28853
|
{
|
|
@@ -29403,7 +29403,7 @@ import {
|
|
|
29403
29403
|
lstatSync as lstatSync5,
|
|
29404
29404
|
mkdirSync as mkdirSync27,
|
|
29405
29405
|
readFileSync as readFileSync45,
|
|
29406
|
-
readdirSync as
|
|
29406
|
+
readdirSync as readdirSync19,
|
|
29407
29407
|
statSync as statSync22
|
|
29408
29408
|
} from "node:fs";
|
|
29409
29409
|
import { dirname as dirname12, join as join45, resolve as resolve29 } from "node:path";
|
|
@@ -29413,7 +29413,7 @@ function findInNvm(bin) {
|
|
|
29413
29413
|
if (!existsSync50(nvmRoot))
|
|
29414
29414
|
return null;
|
|
29415
29415
|
try {
|
|
29416
|
-
const versions =
|
|
29416
|
+
const versions = readdirSync19(nvmRoot).sort().reverse();
|
|
29417
29417
|
for (const v of versions) {
|
|
29418
29418
|
const candidate = join45(nvmRoot, v, "bin", bin);
|
|
29419
29419
|
try {
|
|
@@ -29585,7 +29585,7 @@ function findChromium(homeDir = process.env.HOME ?? "", envBrowsersPath = proces
|
|
|
29585
29585
|
if (!existsSync50(cacheDir))
|
|
29586
29586
|
continue;
|
|
29587
29587
|
try {
|
|
29588
|
-
const entries =
|
|
29588
|
+
const entries = readdirSync19(cacheDir).filter((e) => e.startsWith("chromium"));
|
|
29589
29589
|
for (const entry of entries) {
|
|
29590
29590
|
const candidates2 = [
|
|
29591
29591
|
join45(cacheDir, entry, "chrome-linux64", "chrome"),
|
|
@@ -29898,7 +29898,7 @@ function checkPendingRetainsQueue(dir) {
|
|
|
29898
29898
|
}
|
|
29899
29899
|
let names;
|
|
29900
29900
|
try {
|
|
29901
|
-
names =
|
|
29901
|
+
names = readdirSync19(pendingDir);
|
|
29902
29902
|
} catch (err) {
|
|
29903
29903
|
return {
|
|
29904
29904
|
name: "pending-retains queue",
|
|
@@ -30158,7 +30158,7 @@ function checkRepoHygiene(repoRoot) {
|
|
|
30158
30158
|
});
|
|
30159
30159
|
}
|
|
30160
30160
|
try {
|
|
30161
|
-
const entries =
|
|
30161
|
+
const entries = readdirSync19(repoRoot);
|
|
30162
30162
|
for (const name of entries) {
|
|
30163
30163
|
if (name === "clerk-export-with-secrets.tar.gz")
|
|
30164
30164
|
continue;
|
|
@@ -47248,8 +47248,8 @@ var {
|
|
|
47248
47248
|
} = import__.default;
|
|
47249
47249
|
|
|
47250
47250
|
// src/build-info.ts
|
|
47251
|
-
var VERSION = "0.13.
|
|
47252
|
-
var COMMIT_SHA = "
|
|
47251
|
+
var VERSION = "0.13.4";
|
|
47252
|
+
var COMMIT_SHA = "b4fd0264";
|
|
47253
47253
|
|
|
47254
47254
|
// src/cli/agent.ts
|
|
47255
47255
|
init_source();
|
|
@@ -50468,13 +50468,11 @@ import { join as join12 } from "node:path";
|
|
|
50468
50468
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
50469
50469
|
|
|
50470
50470
|
// src/agents/handoff-summarizer.ts
|
|
50471
|
-
import { readFileSync as readFileSync14, writeFileSync as writeFileSync8, renameSync as renameSync4, mkdirSync as mkdirSync11, existsSync as existsSync14, statSync as statSync9 } from "node:fs";
|
|
50471
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync8, renameSync as renameSync4, mkdirSync as mkdirSync11, existsSync as existsSync14, statSync as statSync9, readdirSync as readdirSync7 } from "node:fs";
|
|
50472
50472
|
import { join as join11 } from "node:path";
|
|
50473
|
-
import { spawn as spawn2 } from "node:child_process";
|
|
50474
|
-
var DEFAULT_SUMMARIZER_MODEL = "claude-haiku-4-5-20251001";
|
|
50475
50473
|
var DEFAULT_MAX_TURNS = 50;
|
|
50476
|
-
var DEFAULT_TIMEOUT_MS2 = 30000;
|
|
50477
50474
|
var TOPIC_MAX_CHARS = 117;
|
|
50475
|
+
var TURN_TEXT_MAX_CHARS = 1200;
|
|
50478
50476
|
function extractTurnsFromJsonl(path, maxTurns) {
|
|
50479
50477
|
let raw;
|
|
50480
50478
|
try {
|
|
@@ -50507,7 +50505,8 @@ function extractTurnsFromJsonl(path, maxTurns) {
|
|
|
50507
50505
|
}
|
|
50508
50506
|
if (obj.type === "user" && obj.message && typeof obj.message === "object") {
|
|
50509
50507
|
const content = obj.message.content;
|
|
50510
|
-
const
|
|
50508
|
+
const raw2 = extractTextBlocks(content);
|
|
50509
|
+
const text = raw2 ? extractChannelBody(raw2) : null;
|
|
50511
50510
|
if (text)
|
|
50512
50511
|
turns.push({ role: "user", text });
|
|
50513
50512
|
continue;
|
|
@@ -50520,9 +50519,16 @@ function extractTurnsFromJsonl(path, maxTurns) {
|
|
|
50520
50519
|
continue;
|
|
50521
50520
|
}
|
|
50522
50521
|
}
|
|
50523
|
-
|
|
50524
|
-
|
|
50525
|
-
|
|
50522
|
+
const deduped = [];
|
|
50523
|
+
for (const t of turns) {
|
|
50524
|
+
const prev = deduped[deduped.length - 1];
|
|
50525
|
+
if (prev && prev.role === t.role && prev.text === t.text)
|
|
50526
|
+
continue;
|
|
50527
|
+
deduped.push(t);
|
|
50528
|
+
}
|
|
50529
|
+
if (deduped.length <= maxTurns)
|
|
50530
|
+
return deduped;
|
|
50531
|
+
return deduped.slice(deduped.length - maxTurns);
|
|
50526
50532
|
}
|
|
50527
50533
|
function extractChannelBody(raw) {
|
|
50528
50534
|
const m = raw.match(/<channel[^>]*>([\s\S]*?)<\/channel>/);
|
|
@@ -50553,56 +50559,48 @@ function extractTextBlocks(content) {
|
|
|
50553
50559
|
`).trim();
|
|
50554
50560
|
return joined.length > 0 ? joined : null;
|
|
50555
50561
|
}
|
|
50556
|
-
function
|
|
50557
|
-
const
|
|
50558
|
-
|
|
50559
|
-
` + `Output format \u2014 EXACTLY this structure, no preamble:
|
|
50560
|
-
` + `## Topic: <one short line, max 100 chars, describing what the user and assistant were most recently focused on>
|
|
50561
|
-
|
|
50562
|
-
` + `## Summary
|
|
50563
|
-
<one paragraph, what we were working on>
|
|
50564
|
-
|
|
50565
|
-
` + `## Open threads
|
|
50566
|
-
- <bulleted list of pending/unresolved items; empty list ok>
|
|
50562
|
+
function formatTranscriptTail(turns) {
|
|
50563
|
+
const header = `# Handoff \u2014 previous session
|
|
50567
50564
|
|
|
50568
|
-
` +
|
|
50569
|
-
|
|
50570
|
-
|
|
50571
|
-
|
|
50572
|
-
|
|
50573
|
-
|
|
50574
|
-
|
|
50575
|
-
|
|
50576
|
-
|
|
50577
|
-
|
|
50578
|
-
|
|
50579
|
-
|
|
50580
|
-
|
|
50565
|
+
` + "You are resuming this agent's work. There is no generated summary " + "\u2014 below is the **raw tail of the previous session's transcript** " + "(oldest first, most recent last). Read it to reorient, then carry " + "on. Anything important worth keeping long-term should already be " + `in your memory files \u2014 check those too.
|
|
50566
|
+
`;
|
|
50567
|
+
if (turns.length === 0) {
|
|
50568
|
+
return header + `
|
|
50569
|
+
_(No recent turns were recoverable from the previous session.)_
|
|
50570
|
+
`;
|
|
50571
|
+
}
|
|
50572
|
+
const body = turns.map((t) => {
|
|
50573
|
+
let text = t.text;
|
|
50574
|
+
if (text.length > TURN_TEXT_MAX_CHARS) {
|
|
50575
|
+
text = text.slice(0, TURN_TEXT_MAX_CHARS) + `
|
|
50576
|
+
\u2026[truncated]`;
|
|
50577
|
+
}
|
|
50578
|
+
return `### ${t.role === "user" ? "User" : "Assistant"}
|
|
50579
|
+
${text}`;
|
|
50580
|
+
}).join(`
|
|
50581
50581
|
|
|
50582
50582
|
`);
|
|
50583
|
-
|
|
50583
|
+
return `${header}
|
|
50584
|
+
## Recent turns
|
|
50584
50585
|
|
|
50585
|
-
|
|
50586
|
-
|
|
50586
|
+
${body}
|
|
50587
|
+
`;
|
|
50587
50588
|
}
|
|
50588
|
-
function
|
|
50589
|
-
|
|
50590
|
-
|
|
50591
|
-
|
|
50592
|
-
start++;
|
|
50593
|
-
if (start >= lines.length)
|
|
50594
|
-
return null;
|
|
50595
|
-
const first = lines[start].trim();
|
|
50596
|
-
const m = first.match(/^##\s*Topic:\s*(.+)$/i);
|
|
50597
|
-
if (!m)
|
|
50598
|
-
return null;
|
|
50599
|
-
let topic = m[1].trim();
|
|
50600
|
-
if (topic.length > TOPIC_MAX_CHARS) {
|
|
50601
|
-
topic = topic.slice(0, TOPIC_MAX_CHARS) + "\u2026";
|
|
50589
|
+
function deriveTopic(turns) {
|
|
50590
|
+
for (let i = turns.length - 1;i >= 0; i--) {
|
|
50591
|
+
if (turns[i].role === "user")
|
|
50592
|
+
return clampTopic(firstLine(turns[i].text));
|
|
50602
50593
|
}
|
|
50603
|
-
|
|
50604
|
-
|
|
50605
|
-
return
|
|
50594
|
+
if (turns.length > 0)
|
|
50595
|
+
return clampTopic(firstLine(turns[turns.length - 1].text));
|
|
50596
|
+
return "previous session";
|
|
50597
|
+
}
|
|
50598
|
+
function firstLine(s) {
|
|
50599
|
+
const line = s.split(/\r?\n/).find((l) => l.trim().length > 0) ?? s;
|
|
50600
|
+
return line.trim();
|
|
50601
|
+
}
|
|
50602
|
+
function clampTopic(s) {
|
|
50603
|
+
return s.length > TOPIC_MAX_CHARS ? s.slice(0, TOPIC_MAX_CHARS) + "\u2026" : s;
|
|
50606
50604
|
}
|
|
50607
50605
|
function writeSidecarsAtomic(agentDir, briefing, topic) {
|
|
50608
50606
|
mkdirSync11(agentDir, { recursive: true });
|
|
@@ -50615,99 +50613,24 @@ function writeSidecarsAtomic(agentDir, briefing, topic) {
|
|
|
50615
50613
|
renameSync4(handoffTmp, handoffPath);
|
|
50616
50614
|
renameSync4(topicTmp, topicPath);
|
|
50617
50615
|
}
|
|
50618
|
-
async function
|
|
50619
|
-
const model = opts.model ?? DEFAULT_SUMMARIZER_MODEL;
|
|
50616
|
+
async function buildHandoff(opts) {
|
|
50620
50617
|
const maxTurns = opts.maxTurns ?? DEFAULT_MAX_TURNS;
|
|
50621
|
-
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
50622
50618
|
const turns = extractTurnsFromJsonl(opts.jsonlPath, maxTurns);
|
|
50623
50619
|
if (turns.length === 0) {
|
|
50624
50620
|
return "no-turns";
|
|
50625
50621
|
}
|
|
50626
|
-
const
|
|
50627
|
-
const
|
|
50628
|
-
let raw;
|
|
50629
|
-
try {
|
|
50630
|
-
raw = await runner.run({
|
|
50631
|
-
model,
|
|
50632
|
-
system: prompt.system,
|
|
50633
|
-
user: prompt.user,
|
|
50634
|
-
timeoutMs
|
|
50635
|
-
});
|
|
50636
|
-
} catch (err) {
|
|
50637
|
-
process.stderr.write(`handoff-summarizer: claude -p call failed \u2014 ${errMsg(err)}
|
|
50638
|
-
`);
|
|
50639
|
-
return "cli-error";
|
|
50640
|
-
}
|
|
50641
|
-
raw = raw.trim();
|
|
50642
|
-
if (!raw) {
|
|
50643
|
-
return "empty-response";
|
|
50644
|
-
}
|
|
50645
|
-
const parsed = parseHandoffResponse(raw);
|
|
50646
|
-
if (!parsed) {
|
|
50647
|
-
process.stderr.write(`handoff-summarizer: response missing '## Topic:' header; skipping
|
|
50648
|
-
`);
|
|
50649
|
-
return "parse-error";
|
|
50650
|
-
}
|
|
50622
|
+
const briefing = formatTranscriptTail(turns);
|
|
50623
|
+
const topic = deriveTopic(turns);
|
|
50651
50624
|
try {
|
|
50652
|
-
writeSidecarsAtomic(opts.agentDir,
|
|
50625
|
+
writeSidecarsAtomic(opts.agentDir, briefing, topic);
|
|
50653
50626
|
} catch (err) {
|
|
50654
|
-
process.stderr.write(`handoff
|
|
50627
|
+
process.stderr.write(`handoff: sidecar write failed \u2014 ${errMsg(err)}
|
|
50655
50628
|
`);
|
|
50656
50629
|
return "write-error";
|
|
50657
50630
|
}
|
|
50658
|
-
await mirrorToHindsight(
|
|
50631
|
+
await mirrorToHindsight(briefing, opts).catch(() => {});
|
|
50659
50632
|
return "ok";
|
|
50660
50633
|
}
|
|
50661
|
-
var defaultClaudeCliRunner = {
|
|
50662
|
-
async run({ model, system, user, timeoutMs }) {
|
|
50663
|
-
return await new Promise((resolve14, reject) => {
|
|
50664
|
-
const args = [
|
|
50665
|
-
"-p",
|
|
50666
|
-
user,
|
|
50667
|
-
"--model",
|
|
50668
|
-
model,
|
|
50669
|
-
"--append-system-prompt",
|
|
50670
|
-
system,
|
|
50671
|
-
"--no-session-persistence"
|
|
50672
|
-
];
|
|
50673
|
-
const env2 = {
|
|
50674
|
-
...process.env,
|
|
50675
|
-
FORCE_COLOR: "0",
|
|
50676
|
-
NO_COLOR: "1"
|
|
50677
|
-
};
|
|
50678
|
-
const child = spawn2("claude", args, {
|
|
50679
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
50680
|
-
env: env2
|
|
50681
|
-
});
|
|
50682
|
-
let stdout = "";
|
|
50683
|
-
let stderr = "";
|
|
50684
|
-
const timer = setTimeout(() => {
|
|
50685
|
-
child.kill("SIGTERM");
|
|
50686
|
-
reject(new Error(`timeout after ${timeoutMs}ms`));
|
|
50687
|
-
}, timeoutMs);
|
|
50688
|
-
child.stdout.on("data", (d) => {
|
|
50689
|
-
stdout += d.toString("utf-8");
|
|
50690
|
-
});
|
|
50691
|
-
child.stderr.on("data", (d) => {
|
|
50692
|
-
stderr += d.toString("utf-8");
|
|
50693
|
-
});
|
|
50694
|
-
child.on("error", (err) => {
|
|
50695
|
-
clearTimeout(timer);
|
|
50696
|
-
reject(err);
|
|
50697
|
-
});
|
|
50698
|
-
child.on("close", (code) => {
|
|
50699
|
-
clearTimeout(timer);
|
|
50700
|
-
if (code === 0) {
|
|
50701
|
-
resolve14(stdout);
|
|
50702
|
-
} else {
|
|
50703
|
-
const tail = stderr.trim().split(`
|
|
50704
|
-
`).slice(-3).join(" | ");
|
|
50705
|
-
reject(new Error(`claude -p exited ${code}: ${tail || "(no stderr)"}`));
|
|
50706
|
-
}
|
|
50707
|
-
});
|
|
50708
|
-
});
|
|
50709
|
-
}
|
|
50710
|
-
};
|
|
50711
50634
|
function errMsg(err) {
|
|
50712
50635
|
if (err && typeof err === "object" && "message" in err) {
|
|
50713
50636
|
return String(err.message);
|
|
@@ -50738,7 +50661,7 @@ async function mirrorToHindsight(briefing, opts) {
|
|
|
50738
50661
|
body: JSON.stringify(body)
|
|
50739
50662
|
});
|
|
50740
50663
|
} catch (err) {
|
|
50741
|
-
process.stderr.write(`handoff
|
|
50664
|
+
process.stderr.write(`handoff: hindsight mirror failed \u2014 ${errMsg(err)}
|
|
50742
50665
|
`);
|
|
50743
50666
|
}
|
|
50744
50667
|
}
|
|
@@ -50750,7 +50673,7 @@ function findLatestSessionJsonl(claudeConfigDir) {
|
|
|
50750
50673
|
const walk = (dir) => {
|
|
50751
50674
|
let entries;
|
|
50752
50675
|
try {
|
|
50753
|
-
entries =
|
|
50676
|
+
entries = readdirSync7(dir);
|
|
50754
50677
|
} catch {
|
|
50755
50678
|
return;
|
|
50756
50679
|
}
|
|
@@ -51704,7 +51627,7 @@ function enforceUsername(username, agentSlug, expectedUsername, loose, warn) {
|
|
|
51704
51627
|
}
|
|
51705
51628
|
|
|
51706
51629
|
// src/setup/profile-picker.ts
|
|
51707
|
-
import { existsSync as existsSync20, readdirSync as
|
|
51630
|
+
import { existsSync as existsSync20, readdirSync as readdirSync10, statSync as statSync13 } from "node:fs";
|
|
51708
51631
|
import { resolve as resolve16 } from "node:path";
|
|
51709
51632
|
var PROFILE_GLOSSES = {
|
|
51710
51633
|
default: "minimal baseline \u2014 generic chat helper, no opinion.",
|
|
@@ -51720,7 +51643,7 @@ function defaultListProfileSkills(profileName) {
|
|
|
51720
51643
|
return [];
|
|
51721
51644
|
}
|
|
51722
51645
|
try {
|
|
51723
|
-
return
|
|
51646
|
+
return readdirSync10(skillsDir).filter((entry) => {
|
|
51724
51647
|
try {
|
|
51725
51648
|
return statSync13(resolve16(skillsDir, entry)).isDirectory();
|
|
51726
51649
|
} catch {
|
|
@@ -53330,7 +53253,6 @@ Scaffolding agent: ${name}
|
|
|
53330
53253
|
}
|
|
53331
53254
|
try {
|
|
53332
53255
|
const result = reconcileAgent(n, agentConfig, agentsDir, config.telegram, config, configPath, { preserveClaudeMd: opts.preserveClaudeMd });
|
|
53333
|
-
const unitChanges = [];
|
|
53334
53256
|
const allChanges = [...result.changes];
|
|
53335
53257
|
if (allChanges.length === 0) {
|
|
53336
53258
|
console.log(source_default.gray(` ${n}: already in sync`));
|
|
@@ -53341,7 +53263,7 @@ Scaffolding agent: ${name}
|
|
|
53341
53263
|
const semantics = result.changesBySemantics;
|
|
53342
53264
|
if (semantics) {
|
|
53343
53265
|
const { hot, staleTillRestart } = semantics;
|
|
53344
|
-
const restartRequired = [...semantics.restartRequired
|
|
53266
|
+
const restartRequired = [...semantics.restartRequired];
|
|
53345
53267
|
if (restartRequired.length > 0) {
|
|
53346
53268
|
console.log(source_default.yellow(`
|
|
53347
53269
|
Changed (restart required \u2014 soul/MCP/settings/start.sh):`));
|
|
@@ -53384,7 +53306,7 @@ Restart: switchroom agent restart ${n}`));
|
|
|
53384
53306
|
}
|
|
53385
53307
|
}
|
|
53386
53308
|
const changesBySemantics = result.changesBySemantics;
|
|
53387
|
-
const autoRestartNeeded = !opts.noRestart &&
|
|
53309
|
+
const autoRestartNeeded = !opts.noRestart && changesBySemantics !== undefined && changesBySemantics.restartRequired.length > 0;
|
|
53388
53310
|
const shouldRestart = (opts.restart || opts.gracefulRestart || autoRestartNeeded) && allChanges.length > 0;
|
|
53389
53311
|
if (shouldRestart) {
|
|
53390
53312
|
try {
|
|
@@ -53815,7 +53737,7 @@ switchroom agent add: ${name}
|
|
|
53815
53737
|
process.exit(1);
|
|
53816
53738
|
}
|
|
53817
53739
|
}));
|
|
53818
|
-
agent.command("rename <old> <new>").description("Rename an agent slug: stop, snapshot, rename dir +
|
|
53740
|
+
agent.command("rename <old> <new>").description("Rename an agent slug: stop, snapshot, rename dir + vault key, " + "update switchroom.yaml, reconcile, start. Rolls back on any failure.").option("--hindsight <mode>", 'Hindsight bank handling: "preserve" (default, keep old bank) or "fresh" (drop, recreate on first run). "migrate" is deferred.', "preserve").option("-y, --yes", "Skip confirmation prompt").action(withConfigError(async (oldName, newName, opts) => {
|
|
53819
53741
|
const configPath = getConfigPath(program3);
|
|
53820
53742
|
const config = getConfig(program3);
|
|
53821
53743
|
if (!config.agents[oldName]) {
|
|
@@ -53834,7 +53756,7 @@ switchroom agent add: ${name}
|
|
|
53834
53756
|
if (!opts.yes) {
|
|
53835
53757
|
process.stdout.write(source_default.yellow(`
|
|
53836
53758
|
Rename agent "${oldName}" \u2192 "${newName}"?
|
|
53837
|
-
` + ` This will: stop ${oldName}, copy dir,
|
|
53759
|
+
` + ` This will: stop ${oldName}, copy dir,
|
|
53838
53760
|
` + ` rename vault keys (if passphrase available), update switchroom.yaml,
|
|
53839
53761
|
` + ` reconcile, and start ${newName}.
|
|
53840
53762
|
` + ` Hindsight mode: ${hindsightMode}
|
|
@@ -55387,7 +55309,7 @@ init_source();
|
|
|
55387
55309
|
init_loader();
|
|
55388
55310
|
init_vault();
|
|
55389
55311
|
init_hindsight();
|
|
55390
|
-
import { readFileSync as readFileSync26, writeFileSync as writeFileSync16, copyFileSync as copyFileSync6, existsSync as existsSync30, readdirSync as
|
|
55312
|
+
import { readFileSync as readFileSync26, writeFileSync as writeFileSync16, copyFileSync as copyFileSync6, existsSync as existsSync30, readdirSync as readdirSync14, statSync as statSync17 } from "node:fs";
|
|
55391
55313
|
import { execFileSync as execFileSync12 } from "node:child_process";
|
|
55392
55314
|
import { join as join23 } from "node:path";
|
|
55393
55315
|
import { homedir as homedir10 } from "node:os";
|
|
@@ -55412,7 +55334,7 @@ function findClaudeTranscripts() {
|
|
|
55412
55334
|
const walk = (dir) => {
|
|
55413
55335
|
let entries;
|
|
55414
55336
|
try {
|
|
55415
|
-
entries =
|
|
55337
|
+
entries = readdirSync14(dir);
|
|
55416
55338
|
} catch {
|
|
55417
55339
|
return;
|
|
55418
55340
|
}
|
|
@@ -55771,13 +55693,13 @@ init_loader();
|
|
|
55771
55693
|
init_loader();
|
|
55772
55694
|
init_client();
|
|
55773
55695
|
import { readFileSync as readFileSync31, existsSync as existsSync34, unlinkSync as unlinkSync9 } from "node:fs";
|
|
55774
|
-
import { spawn as
|
|
55696
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
55775
55697
|
|
|
55776
55698
|
// src/vault/broker/server.ts
|
|
55777
55699
|
init_compose();
|
|
55778
55700
|
init_vault();
|
|
55779
55701
|
import * as net3 from "node:net";
|
|
55780
|
-
import { mkdirSync as mkdirSync20, chmodSync as chmodSync7, chownSync, existsSync as existsSync33, readFileSync as readFileSync29, readdirSync as
|
|
55702
|
+
import { mkdirSync as mkdirSync20, chmodSync as chmodSync7, chownSync, existsSync as existsSync33, readFileSync as readFileSync29, readdirSync as readdirSync15, statSync as statSync19, unlinkSync as unlinkSync8, writeFileSync as writeFileSync18, renameSync as renameSync9 } from "node:fs";
|
|
55781
55703
|
import { dirname as dirname6, resolve as resolve24, basename as basename5 } from "node:path";
|
|
55782
55704
|
import * as os4 from "node:os";
|
|
55783
55705
|
import * as path3 from "node:path";
|
|
@@ -59841,7 +59763,7 @@ async function main() {
|
|
|
59841
59763
|
let perAgentTargets = [];
|
|
59842
59764
|
try {
|
|
59843
59765
|
if (existsSync33(perAgentDir)) {
|
|
59844
|
-
const entries =
|
|
59766
|
+
const entries = readdirSync15(perAgentDir, { withFileTypes: true });
|
|
59845
59767
|
const flat = [];
|
|
59846
59768
|
const subdirs = [];
|
|
59847
59769
|
for (const e of entries) {
|
|
@@ -60121,7 +60043,7 @@ function registerVaultBrokerCommand(vaultCmd, program3) {
|
|
|
60121
60043
|
const args = ["vault", "broker", "start", "--foreground"];
|
|
60122
60044
|
if (parentOpts.config)
|
|
60123
60045
|
args.unshift("--config", parentOpts.config);
|
|
60124
|
-
const child =
|
|
60046
|
+
const child = spawn3(process.execPath, [self2, ...args], {
|
|
60125
60047
|
detached: true,
|
|
60126
60048
|
stdio: "ignore"
|
|
60127
60049
|
});
|
|
@@ -60408,11 +60330,11 @@ function levelLabel(level) {
|
|
|
60408
60330
|
function printDiagnostic(d) {
|
|
60409
60331
|
const glyph = levelGlyph(d.level);
|
|
60410
60332
|
const label = levelLabel(d.level);
|
|
60411
|
-
const
|
|
60333
|
+
const firstLine2 = d.message.split(`
|
|
60412
60334
|
`)[0];
|
|
60413
60335
|
const rest = d.message.split(`
|
|
60414
60336
|
`).slice(1);
|
|
60415
|
-
console.log(` ${glyph} [${label}] ${
|
|
60337
|
+
console.log(` ${glyph} [${label}] ${firstLine2}`);
|
|
60416
60338
|
for (const line of rest) {
|
|
60417
60339
|
console.log(` ${source_default.gray(line)}`);
|
|
60418
60340
|
}
|
|
@@ -60807,7 +60729,7 @@ import {
|
|
|
60807
60729
|
fsyncSync as fsyncSync5,
|
|
60808
60730
|
mkdirSync as mkdirSync21,
|
|
60809
60731
|
openSync as openSync9,
|
|
60810
|
-
readdirSync as
|
|
60732
|
+
readdirSync as readdirSync16,
|
|
60811
60733
|
readFileSync as readFileSync33,
|
|
60812
60734
|
renameSync as renameSync10,
|
|
60813
60735
|
statSync as statSync20,
|
|
@@ -60915,7 +60837,7 @@ function listBackupFiles(dir) {
|
|
|
60915
60837
|
return [];
|
|
60916
60838
|
let entries;
|
|
60917
60839
|
try {
|
|
60918
|
-
entries =
|
|
60840
|
+
entries = readdirSync16(dir);
|
|
60919
60841
|
} catch {
|
|
60920
60842
|
return [];
|
|
60921
60843
|
}
|
|
@@ -60938,7 +60860,7 @@ function backupVault(opts) {
|
|
|
60938
60860
|
throw new Error(`vault backup refused: source is not a valid vault envelope: ${validationError}`);
|
|
60939
60861
|
}
|
|
60940
60862
|
mkdirSync21(opts.destDir, { recursive: true, mode: 448 });
|
|
60941
|
-
const dirEntries =
|
|
60863
|
+
const dirEntries = readdirSync16(opts.destDir);
|
|
60942
60864
|
const offender = findAutoUnlockSibling(dirEntries);
|
|
60943
60865
|
if (offender) {
|
|
60944
60866
|
throw new Error(`vault backup refused: destination '${opts.destDir}' contains a file ` + `that looks like an auto-unlock credential ('${offender}'). The ` + `machine-bound auto-unlock blob MUST NOT be co-located with the ` + `encrypted vault \u2014 if they're together in version control, the ` + `passphrase gate is bypassed. Move/remove that file and retry.`);
|
|
@@ -62707,7 +62629,7 @@ import {
|
|
|
62707
62629
|
} from "node:fs";
|
|
62708
62630
|
import { resolve as resolve26, extname, join as join37, relative, dirname as dirname9 } from "node:path";
|
|
62709
62631
|
import { homedir as homedir19 } from "node:os";
|
|
62710
|
-
import { spawn as
|
|
62632
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
62711
62633
|
import { timingSafeEqual as timingSafeEqual2, randomBytes as randomBytes10 } from "node:crypto";
|
|
62712
62634
|
|
|
62713
62635
|
// src/web/api.ts
|
|
@@ -68623,7 +68545,7 @@ function startWebServer(config, port, hostname = "127.0.0.1", configPath) {
|
|
|
68623
68545
|
existing.kill();
|
|
68624
68546
|
ws._logProcess = null;
|
|
68625
68547
|
}
|
|
68626
|
-
const child =
|
|
68548
|
+
const child = spawn4("docker", ["logs", "-f", "--tail", "20", containerName(agentName)], { stdio: ["ignore", "pipe", "pipe"] });
|
|
68627
68549
|
child.on("error", (err) => {
|
|
68628
68550
|
try {
|
|
68629
68551
|
ws.send(JSON.stringify({
|
|
@@ -70230,7 +70152,7 @@ init_helpers();
|
|
|
70230
70152
|
init_loader();
|
|
70231
70153
|
import { resolve as resolve32 } from "node:path";
|
|
70232
70154
|
function registerHandoffCommand(program3) {
|
|
70233
|
-
program3.command("handoff <agent>", { hidden: true }).description("
|
|
70155
|
+
program3.command("handoff <agent>", { hidden: true }).description("Build the agent's session handoff sidecars \u2014 a transcript-tail " + "briefing (.handoff.md) and topic line (.handoff-topic). " + "[internal \u2014 used by the Stop hook]").option("--max-turns <n>", "Max turns kept in the handoff transcript tail", String(DEFAULT_MAX_TURNS)).action(withConfigError(async (agentName, opts) => {
|
|
70234
70156
|
const config = getConfig(program3);
|
|
70235
70157
|
const agentConfig = config.agents[agentName];
|
|
70236
70158
|
if (!agentConfig) {
|
|
@@ -70253,17 +70175,13 @@ function registerHandoffCommand(program3) {
|
|
|
70253
70175
|
`);
|
|
70254
70176
|
return;
|
|
70255
70177
|
}
|
|
70256
|
-
const timeoutMs = Math.max(1, parseInt(opts.timeout, 10)) * 1000;
|
|
70257
70178
|
const maxTurns = Math.max(1, parseInt(opts.maxTurns, 10));
|
|
70258
|
-
const model = continuity?.summarizer_model ?? opts.model;
|
|
70259
70179
|
const cappedMaxTurns = continuity?.max_turns_in_briefing ?? maxTurns;
|
|
70260
|
-
const status = await
|
|
70180
|
+
const status = await buildHandoff({
|
|
70261
70181
|
jsonlPath: jsonl,
|
|
70262
70182
|
agentDir,
|
|
70263
70183
|
agentName,
|
|
70264
|
-
|
|
70265
|
-
maxTurns: cappedMaxTurns,
|
|
70266
|
-
timeoutMs
|
|
70184
|
+
maxTurns: cappedMaxTurns
|
|
70267
70185
|
});
|
|
70268
70186
|
process.stderr.write(`handoff: ${status}
|
|
70269
70187
|
`);
|
|
@@ -70276,7 +70194,7 @@ import {
|
|
|
70276
70194
|
existsSync as existsSync53,
|
|
70277
70195
|
mkdirSync as mkdirSync29,
|
|
70278
70196
|
openSync as openSync11,
|
|
70279
|
-
readdirSync as
|
|
70197
|
+
readdirSync as readdirSync20,
|
|
70280
70198
|
readFileSync as readFileSync48,
|
|
70281
70199
|
renameSync as renameSync11,
|
|
70282
70200
|
statSync as statSync24,
|
|
@@ -70765,7 +70683,7 @@ var TMP_PREFIX = `${ISSUES_FILE}.tmp-`;
|
|
|
70765
70683
|
function sweepOrphanTmpFiles(stateDir) {
|
|
70766
70684
|
let entries;
|
|
70767
70685
|
try {
|
|
70768
|
-
entries =
|
|
70686
|
+
entries = readdirSync20(stateDir);
|
|
70769
70687
|
} catch {
|
|
70770
70688
|
return;
|
|
70771
70689
|
}
|
|
@@ -72338,7 +72256,7 @@ function registerSoulCommand(program3) {
|
|
|
72338
72256
|
// src/cli/debug.ts
|
|
72339
72257
|
init_helpers();
|
|
72340
72258
|
init_loader();
|
|
72341
|
-
import { existsSync as existsSync59, readFileSync as readFileSync52, readdirSync as
|
|
72259
|
+
import { existsSync as existsSync59, readFileSync as readFileSync52, readdirSync as readdirSync21, statSync as statSync25 } from "node:fs";
|
|
72342
72260
|
import { resolve as resolve37, join as join53 } from "node:path";
|
|
72343
72261
|
import { createHash as createHash12 } from "node:crypto";
|
|
72344
72262
|
init_merge();
|
|
@@ -72357,7 +72275,7 @@ function findLatestTranscriptJsonl(claudeConfigDir) {
|
|
|
72357
72275
|
if (!existsSync59(projectsDir))
|
|
72358
72276
|
return;
|
|
72359
72277
|
try {
|
|
72360
|
-
const entries =
|
|
72278
|
+
const entries = readdirSync21(projectsDir, { withFileTypes: true });
|
|
72361
72279
|
let latest;
|
|
72362
72280
|
for (const entry of entries) {
|
|
72363
72281
|
if (!entry.isDirectory())
|
|
@@ -72595,7 +72513,7 @@ import {
|
|
|
72595
72513
|
mkdirSync as mkdirSync32,
|
|
72596
72514
|
writeFileSync as writeFileSync29,
|
|
72597
72515
|
readFileSync as readFileSync53,
|
|
72598
|
-
readdirSync as
|
|
72516
|
+
readdirSync as readdirSync22,
|
|
72599
72517
|
unlinkSync as unlinkSync12,
|
|
72600
72518
|
existsSync as existsSync60,
|
|
72601
72519
|
renameSync as renameSync12
|
|
@@ -72638,7 +72556,7 @@ function listRecords() {
|
|
|
72638
72556
|
ensureDir2();
|
|
72639
72557
|
const dir = registryDir();
|
|
72640
72558
|
const records = [];
|
|
72641
|
-
for (const entry of
|
|
72559
|
+
for (const entry of readdirSync22(dir)) {
|
|
72642
72560
|
if (!entry.endsWith(".json"))
|
|
72643
72561
|
continue;
|
|
72644
72562
|
const id = entry.slice(0, -5);
|
|
@@ -72985,7 +72903,7 @@ init_scaffold_integration();
|
|
|
72985
72903
|
import {
|
|
72986
72904
|
chmodSync as chmodSync9,
|
|
72987
72905
|
mkdirSync as mkdirSync34,
|
|
72988
|
-
readdirSync as
|
|
72906
|
+
readdirSync as readdirSync23,
|
|
72989
72907
|
rmSync as rmSync15,
|
|
72990
72908
|
writeFileSync as writeFileSync30
|
|
72991
72909
|
} from "node:fs";
|
|
@@ -73158,7 +73076,7 @@ function resolveCredentialsDir(env2) {
|
|
|
73158
73076
|
function writeSeedFile(dir, email, seed) {
|
|
73159
73077
|
mkdirSync34(dir, { recursive: true, mode: 448 });
|
|
73160
73078
|
chmodSync9(dir, 448);
|
|
73161
|
-
for (const name of
|
|
73079
|
+
for (const name of readdirSync23(dir)) {
|
|
73162
73080
|
rmSync15(join56(dir, name), { force: true, recursive: true });
|
|
73163
73081
|
}
|
|
73164
73082
|
const filename = encodeCredentialsFilename(email);
|
|
@@ -73278,9 +73196,9 @@ async function runDriveMcpLauncher(opts) {
|
|
|
73278
73196
|
const tier = opts.tier ?? configSecrets.tier;
|
|
73279
73197
|
const args = buildUvxArgs(tier);
|
|
73280
73198
|
const env2 = buildChildEnv(process.env, credentialsDir, brokerCreds.accountEmail);
|
|
73281
|
-
const { spawn:
|
|
73199
|
+
const { spawn: spawn5 } = await import("node:child_process");
|
|
73282
73200
|
const os5 = await import("node:os");
|
|
73283
|
-
const child =
|
|
73201
|
+
const child = spawn5("uvx", args, {
|
|
73284
73202
|
stdio: ["pipe", "pipe", "inherit"],
|
|
73285
73203
|
env: env2
|
|
73286
73204
|
});
|
|
@@ -73315,7 +73233,7 @@ function registerDriveMcpLauncherCommand(program3) {
|
|
|
73315
73233
|
|
|
73316
73234
|
// src/cli/apply.ts
|
|
73317
73235
|
init_source();
|
|
73318
|
-
import { accessSync as accessSync3, constants as fsConstants6, copyFileSync as copyFileSync11, existsSync as existsSync67, mkdirSync as mkdirSync36, readdirSync as
|
|
73236
|
+
import { accessSync as accessSync3, constants as fsConstants6, copyFileSync as copyFileSync11, existsSync as existsSync67, mkdirSync as mkdirSync36, readdirSync as readdirSync25, renameSync as renameSync13, writeFileSync as writeFileSync32 } from "node:fs";
|
|
73319
73237
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
73320
73238
|
import { spawnSync as childSpawnSync } from "node:child_process";
|
|
73321
73239
|
import readline from "node:readline";
|
|
@@ -73872,7 +73790,7 @@ import {
|
|
|
73872
73790
|
chownSync as chownSync2,
|
|
73873
73791
|
existsSync as existsSync66,
|
|
73874
73792
|
lstatSync as lstatSync7,
|
|
73875
|
-
readdirSync as
|
|
73793
|
+
readdirSync as readdirSync24,
|
|
73876
73794
|
realpathSync as realpathSync6,
|
|
73877
73795
|
statSync as statSync26
|
|
73878
73796
|
} from "node:fs";
|
|
@@ -73928,7 +73846,7 @@ function restoreOperatorOwnership(home2, operatorUid, deps = {}) {
|
|
|
73928
73846
|
});
|
|
73929
73847
|
const readdir2 = deps.readdir ?? ((p) => {
|
|
73930
73848
|
try {
|
|
73931
|
-
return
|
|
73849
|
+
return readdirSync24(p);
|
|
73932
73850
|
} catch {
|
|
73933
73851
|
return [];
|
|
73934
73852
|
}
|
|
@@ -73974,7 +73892,7 @@ function resolveVaultBindMountDir(homeDir, ctx) {
|
|
|
73974
73892
|
function inspectVaultBindMountDir(vaultDir) {
|
|
73975
73893
|
if (!existsSync67(vaultDir))
|
|
73976
73894
|
return { kind: "missing" };
|
|
73977
|
-
const entries =
|
|
73895
|
+
const entries = readdirSync25(vaultDir);
|
|
73978
73896
|
const unknown = [];
|
|
73979
73897
|
for (const name of entries) {
|
|
73980
73898
|
if (KNOWN_VAULT_ARTIFACT_NAMES.has(name))
|
|
@@ -74544,7 +74462,7 @@ function runRedactStdin() {
|
|
|
74544
74462
|
}
|
|
74545
74463
|
|
|
74546
74464
|
// src/cli/status-ask.ts
|
|
74547
|
-
import { readFileSync as readFileSync55, existsSync as existsSync68, readdirSync as
|
|
74465
|
+
import { readFileSync as readFileSync55, existsSync as existsSync68, readdirSync as readdirSync26 } from "node:fs";
|
|
74548
74466
|
import { join as join61 } from "node:path";
|
|
74549
74467
|
import { homedir as homedir34 } from "node:os";
|
|
74550
74468
|
|
|
@@ -74888,7 +74806,7 @@ function resolveSources(explicitPath) {
|
|
|
74888
74806
|
const sources = [];
|
|
74889
74807
|
let entries;
|
|
74890
74808
|
try {
|
|
74891
|
-
entries =
|
|
74809
|
+
entries = readdirSync26(agentsDir);
|
|
74892
74810
|
} catch {
|
|
74893
74811
|
return [];
|
|
74894
74812
|
}
|
|
@@ -75176,7 +75094,7 @@ import {
|
|
|
75176
75094
|
fsyncSync as fsyncSync6,
|
|
75177
75095
|
mkdirSync as mkdirSync38,
|
|
75178
75096
|
openSync as openSync13,
|
|
75179
|
-
readdirSync as
|
|
75097
|
+
readdirSync as readdirSync27,
|
|
75180
75098
|
readFileSync as readFileSync57,
|
|
75181
75099
|
renameSync as renameSync14,
|
|
75182
75100
|
statSync as statSync27,
|
|
@@ -75296,7 +75214,7 @@ function listSkillsOverlayEntries(agent, opts = {}) {
|
|
|
75296
75214
|
if (!existsSync70(paths.skillsDir))
|
|
75297
75215
|
return [];
|
|
75298
75216
|
const out = [];
|
|
75299
|
-
for (const name of
|
|
75217
|
+
for (const name of readdirSync27(paths.skillsDir)) {
|
|
75300
75218
|
if (!/\.ya?ml$/i.test(name))
|
|
75301
75219
|
continue;
|
|
75302
75220
|
const full = join63(paths.skillsDir, name);
|
|
@@ -75323,7 +75241,7 @@ function listOverlayEntries(agent, opts = {}) {
|
|
|
75323
75241
|
if (!existsSync70(paths.scheduleDir))
|
|
75324
75242
|
return [];
|
|
75325
75243
|
const out = [];
|
|
75326
|
-
for (const name of
|
|
75244
|
+
for (const name of readdirSync27(paths.scheduleDir)) {
|
|
75327
75245
|
if (!/\.ya?ml$/i.test(name))
|
|
75328
75246
|
continue;
|
|
75329
75247
|
const full = join63(paths.scheduleDir, name);
|
|
@@ -75475,7 +75393,7 @@ import {
|
|
|
75475
75393
|
fsyncSync as fsyncSync7,
|
|
75476
75394
|
mkdirSync as mkdirSync39,
|
|
75477
75395
|
openSync as openSync14,
|
|
75478
|
-
readdirSync as
|
|
75396
|
+
readdirSync as readdirSync28,
|
|
75479
75397
|
readFileSync as readFileSync58,
|
|
75480
75398
|
renameSync as renameSync15,
|
|
75481
75399
|
unlinkSync as unlinkSync15,
|
|
@@ -75531,7 +75449,7 @@ function listPendingScheduleEntries(agent, opts = {}) {
|
|
|
75531
75449
|
if (!existsSync71(dir))
|
|
75532
75450
|
return [];
|
|
75533
75451
|
const out = [];
|
|
75534
|
-
for (const name of
|
|
75452
|
+
for (const name of readdirSync28(dir).sort()) {
|
|
75535
75453
|
if (!name.endsWith(".meta.json"))
|
|
75536
75454
|
continue;
|
|
75537
75455
|
const stageId = name.slice(0, -".meta.json".length);
|
|
@@ -76269,7 +76187,7 @@ init_helpers();
|
|
|
76269
76187
|
init_loader();
|
|
76270
76188
|
import {
|
|
76271
76189
|
existsSync as existsSync75,
|
|
76272
|
-
readdirSync as
|
|
76190
|
+
readdirSync as readdirSync29,
|
|
76273
76191
|
readFileSync as readFileSync61,
|
|
76274
76192
|
renameSync as renameSync16,
|
|
76275
76193
|
statSync as statSync28,
|
|
@@ -76288,7 +76206,7 @@ function planCronUnitRenames(agentsDir, agents) {
|
|
|
76288
76206
|
continue;
|
|
76289
76207
|
let entries;
|
|
76290
76208
|
try {
|
|
76291
|
-
entries =
|
|
76209
|
+
entries = readdirSync29(telegramDir);
|
|
76292
76210
|
} catch {
|
|
76293
76211
|
continue;
|
|
76294
76212
|
}
|
|
@@ -76443,7 +76361,7 @@ function registerMigrateCommand(program3) {
|
|
|
76443
76361
|
// src/cli/hostd.ts
|
|
76444
76362
|
init_source();
|
|
76445
76363
|
init_helpers();
|
|
76446
|
-
import { existsSync as existsSync76, mkdirSync as mkdirSync40, readdirSync as
|
|
76364
|
+
import { existsSync as existsSync76, mkdirSync as mkdirSync40, readdirSync as readdirSync30, readFileSync as readFileSync62, writeFileSync as writeFileSync34, statSync as statSync29, copyFileSync as copyFileSync12 } from "node:fs";
|
|
76447
76365
|
import { homedir as homedir36 } from "node:os";
|
|
76448
76366
|
import { join as join67 } from "node:path";
|
|
76449
76367
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
@@ -76644,7 +76562,7 @@ function doStatus() {
|
|
|
76644
76562
|
if (existsSync76(dir)) {
|
|
76645
76563
|
const entries = [];
|
|
76646
76564
|
try {
|
|
76647
|
-
for (const name of
|
|
76565
|
+
for (const name of readdirSync30(dir)) {
|
|
76648
76566
|
if (name === "docker-compose.yml" || name.startsWith("docker-compose.yml."))
|
|
76649
76567
|
continue;
|
|
76650
76568
|
const sockPath = join67(dir, name, "sock");
|