switchroom 0.19.22 → 0.19.23

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.
Files changed (37) hide show
  1. package/dist/agent-scheduler/index.js +2 -1
  2. package/dist/auth-broker/index.js +68 -1
  3. package/dist/cli/notion-write-pretool.mjs +2 -1
  4. package/dist/cli/switchroom.js +552 -320
  5. package/dist/host-control/main.js +69 -2
  6. package/dist/vault/approvals/kernel-server.js +71 -4
  7. package/dist/vault/broker/server.js +71 -4
  8. package/package.json +5 -4
  9. package/profiles/_base/start.sh.hbs +101 -0
  10. package/profiles/_shared/agent-self-service.md.hbs +64 -109
  11. package/profiles/_shared/delegation-golden-rule.md.hbs +5 -5
  12. package/profiles/_shared/dev-protocol.md.hbs +13 -42
  13. package/profiles/_shared/execution-discipline.md.hbs +7 -14
  14. package/profiles/coding/CLAUDE.md.hbs +0 -6
  15. package/profiles/default/CLAUDE.md.hbs +21 -50
  16. package/skills/dev-protocol/SKILL.md +90 -107
  17. package/telegram-plugin/bunfig.toml +10 -0
  18. package/telegram-plugin/dist/gateway/gateway.js +108 -16
  19. package/telegram-plugin/gateway/backstop-delivery.ts +97 -16
  20. package/telegram-plugin/gateway/captured-answer-resume.ts +46 -17
  21. package/telegram-plugin/gateway/gateway.ts +9 -7
  22. package/telegram-plugin/gateway/outbound-send-path.ts +8 -1
  23. package/telegram-plugin/gateway/stream-render.ts +6 -0
  24. package/telegram-plugin/gateway/turn-record-status.ts +19 -0
  25. package/telegram-plugin/gateway/turns-jsonl-rotate.ts +65 -0
  26. package/telegram-plugin/tests/agent-state-dir-preload.test.ts +33 -0
  27. package/telegram-plugin/tests/backstop-delivery.test.ts +204 -7
  28. package/telegram-plugin/tests/backstop-readback-probe.test.ts +12 -0
  29. package/telegram-plugin/tests/captured-answer-resume.test.ts +104 -0
  30. package/telegram-plugin/tests/turns-jsonl-rotate.test.ts +92 -1
  31. package/vendor/hindsight-memory/scripts/drain_pending.py +113 -11
  32. package/vendor/hindsight-memory/scripts/lib/pending.py +802 -65
  33. package/vendor/hindsight-memory/scripts/lib/retain_split.py +54 -7
  34. package/vendor/hindsight-memory/scripts/tests/test_pending_drops.py +1445 -11
  35. package/vendor/hindsight-memory/scripts/tests/test_retain_split.py +78 -6
  36. package/vendor/hindsight-memory/tests/test_drain_pending.py +17 -2
  37. package/vendor/hindsight-memory/tests/test_pending.py +12 -4
@@ -2120,7 +2120,7 @@ var init_esm = __esm(() => {
2120
2120
  });
2121
2121
 
2122
2122
  // src/build-info.ts
2123
- var VERSION = "0.19.22", COMMIT_SHA = "50ef9fb5";
2123
+ var VERSION = "0.19.23", COMMIT_SHA = "56e3c01e";
2124
2124
 
2125
2125
  // src/cli/resolve-version.ts
2126
2126
  import { existsSync, readFileSync } from "node:fs";
@@ -13948,7 +13948,8 @@ var init_schema = __esm(() => {
13948
13948
  retain: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `retain` LLM op (memory ingestion). Emits " + "`HINDSIGHT_API_RETAIN_LLM_*`. Absent \u2192 uses the global model/provider."),
13949
13949
  reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent \u2192 uses global."),
13950
13950
  consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent \u2192 global.")
13951
- }).optional().describe("LLM knob for the hindsight container. The flat `provider`/`model` set " + "the global default (backward-compatible); optional `retain`/`reflect`/" + "`consolidation` blocks override individual ops. All fields optional; " + "unset fields fall back to the hard-coded defaults.")
13951
+ }).optional().describe("LLM knob for the hindsight container. The flat `provider`/`model` set " + "the global default (backward-compatible); optional `retain`/`reflect`/" + "`consolidation` blocks override individual ops. All fields optional; " + "unset fields fall back to the hard-coded defaults."),
13952
+ env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "LLM_MAX_CONCURRENT, RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS \u2014 a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED \u2014 a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
13952
13953
  });
13953
13954
  MicrosoftWorkspaceConfigSchema = exports_external.object({
13954
13955
  microsoft_client_id: exports_external.string().min(1).optional().describe("Microsoft OAuth application (client) ID from Entra portal " + "(literal string or vault reference e.g. " + "'vault:microsoft-oauth-client-id'). OPTIONAL \u2014 omit it to use " + "switchroom's shipped default Microsoft app (zero-config). " + "Set it only to bring your own Entra app (BYO)."),
@@ -15555,6 +15556,181 @@ var init_timeout_budget = __esm(() => {
15555
15556
  };
15556
15557
  });
15557
15558
 
15559
+ // src/setup/host-capabilities.ts
15560
+ import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync5, writeFileSync } from "node:fs";
15561
+ import { dirname as dirname2 } from "node:path";
15562
+ function hostCapabilitiesPath() {
15563
+ return resolveStatePath("host-capabilities.json");
15564
+ }
15565
+ function saveVoiceCapability(caps, now = () => new Date) {
15566
+ const doc = {
15567
+ version: HOST_CAPABILITIES_VERSION,
15568
+ voice: {
15569
+ gpuPresent: caps.gpuPresent,
15570
+ containerToolkit: caps.containerToolkit,
15571
+ engine: caps.engine,
15572
+ detectedAt: now().toISOString()
15573
+ }
15574
+ };
15575
+ const path = hostCapabilitiesPath();
15576
+ mkdirSync(dirname2(path), { recursive: true });
15577
+ writeFileSync(path, JSON.stringify(doc, null, 2) + `
15578
+ `, {
15579
+ encoding: "utf-8",
15580
+ mode: 384
15581
+ });
15582
+ return doc;
15583
+ }
15584
+ function loadHostCapabilities() {
15585
+ const path = hostCapabilitiesPath();
15586
+ if (!existsSync5(path))
15587
+ return null;
15588
+ try {
15589
+ const parsed = JSON.parse(readFileSync5(path, "utf-8"));
15590
+ if (parsed && typeof parsed === "object" && "voice" in parsed && typeof parsed.voice === "object") {
15591
+ return parsed;
15592
+ }
15593
+ return null;
15594
+ } catch {
15595
+ return null;
15596
+ }
15597
+ }
15598
+ var HOST_CAPABILITIES_VERSION = 1;
15599
+ var init_host_capabilities = __esm(() => {
15600
+ init_paths();
15601
+ });
15602
+
15603
+ // src/setup/hindsight-perf-defaults.ts
15604
+ function resolveHindsightPerfOverrides(configEnv, processEnv = process.env) {
15605
+ const out = new Map;
15606
+ for (const key of HINDSIGHT_PERF_ENV_KEYS) {
15607
+ const fromProcess = processEnv[key];
15608
+ if (typeof fromProcess === "string" && fromProcess.trim() !== "") {
15609
+ out.set(key, fromProcess.trim());
15610
+ }
15611
+ }
15612
+ for (const [key, raw] of Object.entries(configEnv ?? {})) {
15613
+ if (!HINDSIGHT_PERF_ENV_KEYS.has(key))
15614
+ continue;
15615
+ const value = String(raw).trim();
15616
+ if (value === "")
15617
+ continue;
15618
+ out.set(key, value);
15619
+ }
15620
+ return out;
15621
+ }
15622
+ function hindsightPerfEnv(caps, overrides = new Map) {
15623
+ const groups = [
15624
+ HINDSIGHT_PERF_DEFAULTS_UNGATED
15625
+ ];
15626
+ if (caps.gpu === true)
15627
+ groups.push(HINDSIGHT_PERF_DEFAULTS_GPU);
15628
+ if (caps.localLlm === true)
15629
+ groups.push(HINDSIGHT_PERF_DEFAULTS_LOCAL_LLM);
15630
+ const out = [];
15631
+ const emitted = new Set;
15632
+ for (const group of groups) {
15633
+ for (const [key, value] of group) {
15634
+ if (emitted.has(key))
15635
+ continue;
15636
+ emitted.add(key);
15637
+ out.push([key, overrides.get(key) ?? value]);
15638
+ }
15639
+ }
15640
+ for (const key of [...overrides.keys()].sort()) {
15641
+ if (emitted.has(key))
15642
+ continue;
15643
+ emitted.add(key);
15644
+ out.push([key, overrides.get(key)]);
15645
+ }
15646
+ return out;
15647
+ }
15648
+ var HINDSIGHT_RERANKER_MAX_CANDIDATES_FOR_DERIVATION = 150, HINDSIGHT_DEFAULT_RECALL_MAX_CANDIDATES_PER_SOURCE, HINDSIGHT_DEFAULT_LINK_EXPANSION_PER_ENTITY_LIMIT = 50, HINDSIGHT_DEFAULT_LINK_EXPANSION_TIMEOUT_S = 2, HINDSIGHT_DEFAULT_LLM_REASONING_EFFORT = "low", HINDSIGHT_DEFAULT_LLM_MAX_CONCURRENT = 4, HINDSIGHT_DEFAULT_RETAIN_LLM_MAX_CONCURRENT = 1, HINDSIGHT_DEFAULT_CONSOLIDATION_LLM_MAX_CONCURRENT = 1, HINDSIGHT_DEFAULT_RERANKER_LOCAL_FP16 = "true", HINDSIGHT_PERF_DEFAULTS_UNGATED, HINDSIGHT_PERF_DEFAULTS_GPU, HINDSIGHT_PERF_DEFAULTS_LOCAL_LLM, HINDSIGHT_PERF_ENV_KEYS;
15649
+ var init_hindsight_perf_defaults = __esm(() => {
15650
+ HINDSIGHT_DEFAULT_RECALL_MAX_CANDIDATES_PER_SOURCE = Math.ceil(HINDSIGHT_RERANKER_MAX_CANDIDATES_FOR_DERIVATION * 0.4);
15651
+ HINDSIGHT_PERF_DEFAULTS_UNGATED = [
15652
+ [
15653
+ "HINDSIGHT_API_RECALL_MAX_CANDIDATES_PER_SOURCE",
15654
+ String(HINDSIGHT_DEFAULT_RECALL_MAX_CANDIDATES_PER_SOURCE)
15655
+ ],
15656
+ [
15657
+ "HINDSIGHT_API_LINK_EXPANSION_PER_ENTITY_LIMIT",
15658
+ String(HINDSIGHT_DEFAULT_LINK_EXPANSION_PER_ENTITY_LIMIT)
15659
+ ],
15660
+ [
15661
+ "HINDSIGHT_API_LINK_EXPANSION_TIMEOUT",
15662
+ String(HINDSIGHT_DEFAULT_LINK_EXPANSION_TIMEOUT_S)
15663
+ ],
15664
+ ["HINDSIGHT_API_LLM_REASONING_EFFORT", HINDSIGHT_DEFAULT_LLM_REASONING_EFFORT]
15665
+ ];
15666
+ HINDSIGHT_PERF_DEFAULTS_GPU = [
15667
+ ["HINDSIGHT_API_RERANKER_LOCAL_FP16", HINDSIGHT_DEFAULT_RERANKER_LOCAL_FP16]
15668
+ ];
15669
+ HINDSIGHT_PERF_DEFAULTS_LOCAL_LLM = [
15670
+ ["HINDSIGHT_API_LLM_MAX_CONCURRENT", String(HINDSIGHT_DEFAULT_LLM_MAX_CONCURRENT)],
15671
+ [
15672
+ "HINDSIGHT_API_RETAIN_LLM_MAX_CONCURRENT",
15673
+ String(HINDSIGHT_DEFAULT_RETAIN_LLM_MAX_CONCURRENT)
15674
+ ],
15675
+ [
15676
+ "HINDSIGHT_API_CONSOLIDATION_LLM_MAX_CONCURRENT",
15677
+ String(HINDSIGHT_DEFAULT_CONSOLIDATION_LLM_MAX_CONCURRENT)
15678
+ ]
15679
+ ];
15680
+ HINDSIGHT_PERF_ENV_KEYS = new Set([
15681
+ ...HINDSIGHT_PERF_DEFAULTS_UNGATED,
15682
+ ...HINDSIGHT_PERF_DEFAULTS_GPU,
15683
+ ...HINDSIGHT_PERF_DEFAULTS_LOCAL_LLM
15684
+ ].map(([k]) => k));
15685
+ });
15686
+
15687
+ // src/setup/hindsight-pg-defaults.ts
15688
+ function pgMib(mib) {
15689
+ return `${mib}MB`;
15690
+ }
15691
+ function resolveHindsightPgOverrides(configEnv, processEnv = process.env) {
15692
+ const out = new Map;
15693
+ for (const key of HINDSIGHT_PG_ENV_KEYS) {
15694
+ const fromProcess = processEnv[key];
15695
+ if (typeof fromProcess === "string" && fromProcess.trim() !== "") {
15696
+ out.set(key, fromProcess.trim());
15697
+ }
15698
+ }
15699
+ for (const [key, raw] of Object.entries(configEnv ?? {})) {
15700
+ if (!HINDSIGHT_PG_ENV_KEYS.has(key))
15701
+ continue;
15702
+ const value = String(raw).trim();
15703
+ if (value === "")
15704
+ continue;
15705
+ out.set(key, value);
15706
+ }
15707
+ return out;
15708
+ }
15709
+ function hindsightPgEnv(overrides = new Map) {
15710
+ const out = [];
15711
+ const emitted = new Set;
15712
+ for (const [key, value] of HINDSIGHT_PG_DEFAULTS) {
15713
+ if (emitted.has(key))
15714
+ continue;
15715
+ emitted.add(key);
15716
+ out.push([key, overrides.get(key) ?? value]);
15717
+ }
15718
+ return out;
15719
+ }
15720
+ var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION, HINDSIGHT_PG_APP_ANON_MIB = 2560, HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB = 2048, HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB, HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 1536, HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 4096, HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE_ENV = "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE", HINDSIGHT_PG_SHARED_BUFFERS_ENV = "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS", HINDSIGHT_PG_DEFAULTS, HINDSIGHT_PG_ENV_KEYS;
15721
+ var init_hindsight_pg_defaults = __esm(() => {
15722
+ HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 8 * 1024;
15723
+ HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB = HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION - HINDSIGHT_PG_APP_ANON_MIB - HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
15724
+ HINDSIGHT_PG_DEFAULTS = [
15725
+ [
15726
+ HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE_ENV,
15727
+ pgMib(HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB)
15728
+ ],
15729
+ [HINDSIGHT_PG_SHARED_BUFFERS_ENV, pgMib(HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB)]
15730
+ ];
15731
+ HINDSIGHT_PG_ENV_KEYS = new Set(HINDSIGHT_PG_DEFAULTS.map(([k]) => k));
15732
+ });
15733
+
15558
15734
  // src/util/atomic.ts
15559
15735
  var exports_atomic = {};
15560
15736
  __export(exports_atomic, {
@@ -15841,7 +16017,7 @@ function resolveHindsightLlm(llm, litellm) {
15841
16017
  function isLoopbackHttpUrl(url) {
15842
16018
  try {
15843
16019
  const u = new URL(url.includes("://") ? url : `http://${url}`);
15844
- const h = (u.hostname || "").toLowerCase();
16020
+ const h = (u.hostname || "").toLowerCase().replace(/^\[|\]$/g, "");
15845
16021
  return h === "localhost" || h === "127.0.0.1" || h === "::1";
15846
16022
  } catch {
15847
16023
  return false;
@@ -15869,6 +16045,45 @@ function hindsightNeedsHostNetwork(llm, litellm) {
15869
16045
  return true;
15870
16046
  return collectHindsightLlmBaseUrls(llm).some(isLoopbackHttpUrl);
15871
16047
  }
16048
+ function isSelfHostedHttpUrl(url) {
16049
+ let host;
16050
+ try {
16051
+ const u = new URL(url.includes("://") ? url : `http://${url}`);
16052
+ host = (u.hostname || "").toLowerCase().replace(/^\[|\]$/g, "");
16053
+ } catch {
16054
+ return false;
16055
+ }
16056
+ if (!host)
16057
+ return false;
16058
+ if (isLoopbackHttpUrl(url))
16059
+ return true;
16060
+ if (host === "host.docker.internal" || host === "gateway.docker.internal")
16061
+ return true;
16062
+ if (host.endsWith(".local") || host.endsWith(".internal"))
16063
+ return true;
16064
+ if (/^f[cd][0-9a-f]{2}:/.test(host) || /^fe[89ab][0-9a-f]:/.test(host))
16065
+ return true;
16066
+ const v4 = host.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
16067
+ if (!v4)
16068
+ return false;
16069
+ const [a, b] = [Number(v4[1]), Number(v4[2])];
16070
+ if (a === 10)
16071
+ return true;
16072
+ if (a === 127)
16073
+ return true;
16074
+ if (a === 192 && b === 168)
16075
+ return true;
16076
+ if (a === 172 && b >= 16 && b <= 31)
16077
+ return true;
16078
+ if (a === 169 && b === 254)
16079
+ return true;
16080
+ return false;
16081
+ }
16082
+ function hindsightLocalLlmEnabled(llm, litellm, override) {
16083
+ if (override !== undefined)
16084
+ return override;
16085
+ return collectHindsightLlmBaseUrls(llm, litellm).some(isSelfHostedHttpUrl);
16086
+ }
15872
16087
  function pickHindsightLiteLlmProbeUrl(llm, litellm) {
15873
16088
  return collectHindsightLlmBaseUrls(llm, litellm)[0];
15874
16089
  }
@@ -15885,7 +16100,22 @@ function buildLiteLlmAwareHealthPy(apiPort, litellmBaseUrl) {
15885
16100
  function buildLiteLlmAwareHealthCmd(apiPort, litellmBaseUrl) {
15886
16101
  return `python3 -c "${buildLiteLlmAwareHealthPy(apiPort, litellmBaseUrl)}"`;
15887
16102
  }
15888
- function startHindsight(ports, litellm, imageTag, llm, mirrorDir) {
16103
+ function hindsightGpuEnabled(override) {
16104
+ if (override !== undefined)
16105
+ return override;
16106
+ const caps = loadHostCapabilities();
16107
+ return caps?.voice?.gpuPresent === true && caps?.voice?.containerToolkit === true;
16108
+ }
16109
+ function hindsightPerfEnvPairs(llm, litellm, gpu, perf) {
16110
+ return hindsightPerfEnv({
16111
+ gpu: hindsightGpuEnabled(gpu),
16112
+ localLlm: hindsightLocalLlmEnabled(llm, litellm, perf?.localLlm)
16113
+ }, resolveHindsightPerfOverrides(perf?.env, perf?.processEnv));
16114
+ }
16115
+ function hindsightPgEnvPairs(perf) {
16116
+ return hindsightPgEnv(resolveHindsightPgOverrides(perf?.env, perf?.processEnv));
16117
+ }
16118
+ function startHindsight(ports, litellm, imageTag, llm, mirrorDir, gpu, perf) {
15889
16119
  const apiPort = ports?.apiPort ?? HINDSIGHT_DEFAULT_API_PORT;
15890
16120
  const uiPort = ports?.uiPort ?? HINDSIGHT_DEFAULT_UI_PORT;
15891
16121
  const { provider: llmProvider, model: llmModel } = resolveHindsightLlm(llm, litellm);
@@ -15920,7 +16150,9 @@ function startHindsight(ports, litellm, imageTag, llm, mirrorDir) {
15920
16150
  "-e",
15921
16151
  `HINDSIGHT_API_CONSOLIDATION_MAX_MEMORIES_PER_ROUND=${HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND}`,
15922
16152
  "-e",
15923
- `HINDSIGHT_API_WORKER_ID=${HINDSIGHT_DEFAULT_WORKER_ID}`
16153
+ `HINDSIGHT_API_WORKER_ID=${HINDSIGHT_DEFAULT_WORKER_ID}`,
16154
+ ...hindsightPerfEnvPairs(llm, litellm, gpu, perf).flatMap(([k, v]) => ["-e", `${k}=${v}`]),
16155
+ ...hindsightPgEnvPairs(perf).flatMap(([k, v]) => ["-e", `${k}=${v}`])
15924
16156
  ];
15925
16157
  if (llmProvider === "claude-code") {
15926
16158
  envArgs.push("-e", `ANTHROPIC_MODEL=${llmModel}`);
@@ -15943,6 +16175,7 @@ x-litellm-tags: service:hindsight`);
15943
16175
  `--memory-reservation=${HINDSIGHT_DEFAULT_MEM_RESERVATION}`,
15944
16176
  `--pids-limit=${HINDSIGHT_DEFAULT_PIDS_LIMIT}`,
15945
16177
  `--shm-size=${HINDSIGHT_DEFAULT_SHM_SIZE}`,
16178
+ ...hindsightGpuEnabled(gpu) ? ["--gpus", "all"] : [],
15946
16179
  ...(() => {
15947
16180
  const hostNet = hindsightNeedsHostNetwork(llm, litellm);
15948
16181
  const healthApiPort = hostNet ? apiPort : 8888;
@@ -16078,10 +16311,11 @@ function getHindsightStatus() {
16078
16311
  return null;
16079
16312
  }
16080
16313
  }
16081
- function generateHindsightComposeSnippet(llm, mirrorDir, litellm) {
16314
+ function generateHindsightComposeSnippet(llm, mirrorDir, litellm, gpu, perf) {
16082
16315
  const { provider: llmProvider, model: llmModel } = resolveHindsightLlm(llm, litellm);
16083
16316
  const perOpLlm = resolveHindsightPerOpLlm(llm);
16084
16317
  const hostNetwork = hindsightNeedsHostNetwork(llm, litellm);
16318
+ const gpuEnabled = hindsightGpuEnabled(gpu);
16085
16319
  const apiPort = HINDSIGHT_DEFAULT_API_PORT;
16086
16320
  const internalApiPort = hostNetwork ? apiPort : 8888;
16087
16321
  const probeUrl = pickHindsightLiteLlmProbeUrl(llm, litellm);
@@ -16147,10 +16381,21 @@ function generateHindsightComposeSnippet(llm, mirrorDir, litellm) {
16147
16381
  ` - HINDSIGHT_API_CONSOLIDATION_LLM_PARALLELISM=${HINDSIGHT_DEFAULT_CONSOLIDATION_LLM_PARALLELISM}`,
16148
16382
  ` - HINDSIGHT_API_CONSOLIDATION_MAX_MEMORIES_PER_ROUND=${HINDSIGHT_DEFAULT_CONSOLIDATION_MAX_MEMORIES_PER_ROUND}`,
16149
16383
  ` - HINDSIGHT_API_WORKER_ID=${HINDSIGHT_DEFAULT_WORKER_ID}`,
16384
+ ...hindsightPerfEnvPairs(llm, litellm, gpu, perf).map(([k, v]) => ` - ${k}=${v}`),
16385
+ ...hindsightPgEnvPairs(perf).map(([k, v]) => ` - ${k}=${v}`),
16150
16386
  ` mem_limit: ${HINDSIGHT_DEFAULT_MEM_LIMIT}`,
16151
16387
  ` mem_reservation: ${HINDSIGHT_DEFAULT_MEM_RESERVATION}`,
16152
16388
  ` pids_limit: ${HINDSIGHT_DEFAULT_PIDS_LIMIT}`,
16153
16389
  ` shm_size: ${HINDSIGHT_DEFAULT_SHM_SIZE}`,
16390
+ ...gpuEnabled ? [
16391
+ " deploy:",
16392
+ " resources:",
16393
+ " reservations:",
16394
+ " devices:",
16395
+ " - driver: nvidia",
16396
+ " count: 1",
16397
+ ' capabilities: ["gpu"]'
16398
+ ] : [],
16154
16399
  " healthcheck:",
16155
16400
  ` test: ${JSON.stringify(["CMD", "python3", "-c", healthPy])}`,
16156
16401
  " interval: 30s",
@@ -16251,6 +16496,9 @@ var HINDSIGHT_DEFAULT_API_PORT = 18888, HINDSIGHT_DEFAULT_UI_PORT = 9999, HINDSI
16251
16496
  var init_hindsight = __esm(() => {
16252
16497
  init_model_command();
16253
16498
  init_timeout_budget();
16499
+ init_host_capabilities();
16500
+ init_hindsight_perf_defaults();
16501
+ init_hindsight_pg_defaults();
16254
16502
  HINDSIGHT_DEFAULT_MCP_URL = `http://127.0.0.1:${HINDSIGHT_DEFAULT_API_PORT}/mcp/`;
16255
16503
  HINDSIGHT_DEFAULT_API_BASE_URL = HINDSIGHT_DEFAULT_MCP_URL.replace(/\/mcp\/?$/, "");
16256
16504
  HINDSIGHT_IMAGE = `${HINDSIGHT_IMAGE_REPO}:latest`;
@@ -17021,7 +17269,7 @@ function parseSocketIdentity(socketPath, spec) {
17021
17269
 
17022
17270
  // src/vault/broker/peercred.ts
17023
17271
  import { execFileSync as execFileSync2 } from "node:child_process";
17024
- import { readFileSync as readFileSync5, readlinkSync as readlinkSync2, fstatSync } from "node:fs";
17272
+ import { readFileSync as readFileSync6, readlinkSync as readlinkSync2, fstatSync } from "node:fs";
17025
17273
  function socketPathToIdentity(socketPath) {
17026
17274
  return parseSocketIdentity(socketPath, {
17027
17275
  patterns: [SOCKET_PATH_AGENT_RE, SOCKET_PATH_AGENT_SUBDIR_RE],
@@ -17102,7 +17350,7 @@ function findClientPidByServerInode(rows, socketPath, serverInode) {
17102
17350
  }
17103
17351
  function readUid(pid) {
17104
17352
  try {
17105
- const status = readFileSync5(`/proc/${pid}/status`, "utf8");
17353
+ const status = readFileSync6(`/proc/${pid}/status`, "utf8");
17106
17354
  const m = status.match(/^Uid:\s+(\d+)/m);
17107
17355
  if (!m)
17108
17356
  return null;
@@ -17120,7 +17368,7 @@ function readExe(pid) {
17120
17368
  }
17121
17369
  function readSystemdUnit(pid) {
17122
17370
  try {
17123
- const content = readFileSync5(`/proc/${pid}/cgroup`, "utf8");
17371
+ const content = readFileSync6(`/proc/${pid}/cgroup`, "utf8");
17124
17372
  const lines = content.split(`
17125
17373
  `);
17126
17374
  for (const line of lines) {
@@ -17287,7 +17535,7 @@ var init_agent_uid = __esm(() => {
17287
17535
 
17288
17536
  // src/agents/agent-owned-tree.ts
17289
17537
  import { execFileSync as execFileSync3 } from "node:child_process";
17290
- import { existsSync as existsSync5, lstatSync, readdirSync as readdirSync2, statSync as statSync3 } from "node:fs";
17538
+ import { existsSync as existsSync6, lstatSync, readdirSync as readdirSync2, statSync as statSync3 } from "node:fs";
17291
17539
  import { join as join3 } from "node:path";
17292
17540
  function scopedAssertCandidates(agentDir) {
17293
17541
  return [
@@ -17306,7 +17554,7 @@ function chownScopedTree(uid, gid, agentDir) {
17306
17554
  ownershipRuntime.chownShallow(uid, gid, [agentDir, ...children]);
17307
17555
  for (const sub of SCOPED_RECURSIVE_SUBDIRS) {
17308
17556
  const subPath = join3(agentDir, sub);
17309
- if (existsSync5(subPath)) {
17557
+ if (existsSync6(subPath)) {
17310
17558
  ownershipRuntime.chownTree(uid, gid, subPath);
17311
17559
  }
17312
17560
  }
@@ -17314,7 +17562,7 @@ function chownScopedTree(uid, gid, agentDir) {
17314
17562
  function alignAgentTreeOwnershipIfRoot(name, agentDir) {
17315
17563
  if (ownershipRuntime.geteuid() !== 0)
17316
17564
  return null;
17317
- if (!existsSync5(agentDir))
17565
+ if (!existsSync6(agentDir))
17318
17566
  return null;
17319
17567
  const uid = allocateAgentUid(name);
17320
17568
  const scoped = ownershipRuntime.scopedSweepEnabled();
@@ -17401,7 +17649,7 @@ var init_agent_owned_tree = __esm(() => {
17401
17649
 
17402
17650
  // src/agents/generation-stamp.ts
17403
17651
  import { createHash as createHash3 } from "node:crypto";
17404
- import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync } from "node:fs";
17652
+ import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync2 } from "node:fs";
17405
17653
  import { join as join4 } from "node:path";
17406
17654
  function sha256Text(s) {
17407
17655
  return createHash3("sha256").update(s, "utf-8").digest("hex");
@@ -17424,11 +17672,11 @@ function hashManagedClaudeMd(content) {
17424
17672
  }
17425
17673
  function hashStampedFileOnDisk(agentDir, rel) {
17426
17674
  const p = join4(agentDir, rel);
17427
- if (!existsSync6(p))
17675
+ if (!existsSync7(p))
17428
17676
  return null;
17429
17677
  let content;
17430
17678
  try {
17431
- content = readFileSync6(p, "utf-8");
17679
+ content = readFileSync7(p, "utf-8");
17432
17680
  } catch {
17433
17681
  return null;
17434
17682
  }
@@ -17451,15 +17699,15 @@ function writeGenerationStamp(agentDir, stamp) {
17451
17699
  configHash: stamp.configHash,
17452
17700
  files: stamp.files
17453
17701
  };
17454
- writeFileSync(join4(agentDir, GENERATION_STAMP_FILE), JSON.stringify(full, null, 2) + `
17702
+ writeFileSync2(join4(agentDir, GENERATION_STAMP_FILE), JSON.stringify(full, null, 2) + `
17455
17703
  `, "utf-8");
17456
17704
  }
17457
17705
  function readGenerationStamp(agentDir) {
17458
17706
  const p = join4(agentDir, GENERATION_STAMP_FILE);
17459
- if (!existsSync6(p))
17707
+ if (!existsSync7(p))
17460
17708
  return null;
17461
17709
  try {
17462
- const parsed = JSON.parse(readFileSync6(p, "utf-8"));
17710
+ const parsed = JSON.parse(readFileSync7(p, "utf-8"));
17463
17711
  if (parsed?.version !== 1 || typeof parsed.files !== "object" || parsed.files === null || Array.isArray(parsed.files)) {
17464
17712
  return null;
17465
17713
  }
@@ -17976,10 +18224,10 @@ var init_cron_introspect = __esm(() => {
17976
18224
  import { join as join5 } from "node:path";
17977
18225
  import { homedir as homedir2 } from "node:os";
17978
18226
  import {
17979
- existsSync as existsSync7,
17980
- mkdirSync,
18227
+ existsSync as existsSync8,
18228
+ mkdirSync as mkdirSync2,
17981
18229
  appendFileSync,
17982
- readFileSync as readFileSync7
18230
+ readFileSync as readFileSync8
17983
18231
  } from "node:fs";
17984
18232
  function auditPathFor(agent) {
17985
18233
  return join5(AUDIT_ROOT, agent, "agent-config.jsonl");
@@ -17996,8 +18244,8 @@ function appendAudit(agent, cmd, args, exit, opts = {}) {
17996
18244
  const path = opts.auditPath ?? auditPathFor(agent);
17997
18245
  const dir = path.slice(0, path.lastIndexOf("/"));
17998
18246
  try {
17999
- if (!existsSync7(dir)) {
18000
- mkdirSync(dir, { recursive: true });
18247
+ if (!existsSync8(dir)) {
18248
+ mkdirSync2(dir, { recursive: true });
18001
18249
  }
18002
18250
  appendFileSync(path, JSON.stringify(row) + `
18003
18251
  `, { flag: "a" });
@@ -18008,7 +18256,7 @@ function isContainerContext(env2 = process.env, opts = {}) {
18008
18256
  return true;
18009
18257
  const probe = opts.dockerEnvPath ?? "/.dockerenv";
18010
18258
  try {
18011
- if (existsSync7(probe))
18259
+ if (existsSync8(probe))
18012
18260
  return true;
18013
18261
  } catch {}
18014
18262
  return false;
@@ -18136,11 +18384,11 @@ function getAgentSlice(config, agent) {
18136
18384
  }
18137
18385
  function readAuditTail(agent, limit, opts = {}) {
18138
18386
  const path = opts.auditPath ?? auditPathFor(agent);
18139
- if (!existsSync7(path))
18387
+ if (!existsSync8(path))
18140
18388
  return [];
18141
18389
  let raw;
18142
18390
  try {
18143
- raw = readFileSync7(path, "utf-8");
18391
+ raw = readFileSync8(path, "utf-8");
18144
18392
  } catch {
18145
18393
  return [];
18146
18394
  }
@@ -23946,7 +24194,7 @@ var require_lib = __commonJS((exports, module) => {
23946
24194
  });
23947
24195
 
23948
24196
  // src/agents/profiles.ts
23949
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync2, existsSync as existsSync8, readdirSync as readdirSync3, statSync as statSync4, copyFileSync, mkdirSync as mkdirSync2, realpathSync } from "node:fs";
24197
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync3, existsSync as existsSync9, readdirSync as readdirSync3, statSync as statSync4, copyFileSync, mkdirSync as mkdirSync3, realpathSync } from "node:fs";
23950
24198
  import { resolve as resolve4, join as join6, sep as pathSep } from "node:path";
23951
24199
  function resolveProfilesRoot() {
23952
24200
  const envOverride = process.env.SWITCHROOM_PROFILES_ROOT?.trim();
@@ -23958,7 +24206,7 @@ function resolveProfilesRoot() {
23958
24206
  resolve4(import.meta.dirname, "profiles")
23959
24207
  ];
23960
24208
  for (const candidate of candidates) {
23961
- if (existsSync8(candidate)) {
24209
+ if (existsSync9(candidate)) {
23962
24210
  return candidate;
23963
24211
  }
23964
24212
  }
@@ -23978,11 +24226,11 @@ function getProfilePath(profileName) {
23978
24226
  if (real !== PROFILES_ROOT && !real.startsWith(PROFILES_ROOT + pathSep)) {
23979
24227
  throw new Error(`Invalid profile name: ${profileName}`);
23980
24228
  }
23981
- if (existsSync8(requested) && hasProfileFiles(requested)) {
24229
+ if (existsSync9(requested) && hasProfileFiles(requested)) {
23982
24230
  return requested;
23983
24231
  }
23984
24232
  const fallback = resolve4(PROFILES_ROOT, "default");
23985
- if (existsSync8(fallback)) {
24233
+ if (existsSync9(fallback)) {
23986
24234
  return fallback;
23987
24235
  }
23988
24236
  throw new Error(`Profile not found: ${profileName} (searched ${PROFILES_ROOT})`);
@@ -24012,19 +24260,19 @@ function getBaseProfilePath() {
24012
24260
  return resolve4(PROFILES_ROOT, "_base");
24013
24261
  }
24014
24262
  function renderTemplate(templatePath, context) {
24015
- const source = readFileSync8(templatePath, "utf-8");
24263
+ const source = readFileSync9(templatePath, "utf-8");
24016
24264
  const template = import_handlebars.default.compile(source, { noEscape: true });
24017
24265
  return template(context);
24018
24266
  }
24019
24267
  function copyProfileSkills(profilePath, destPath) {
24020
24268
  const skillsSrc = join6(profilePath, "skills");
24021
- if (!existsSync8(skillsSrc)) {
24269
+ if (!existsSync9(skillsSrc)) {
24022
24270
  return;
24023
24271
  }
24024
24272
  copyDirRecursive(skillsSrc, destPath);
24025
24273
  }
24026
24274
  function copyDirRecursive(src, dest) {
24027
- mkdirSync2(dest, { recursive: true });
24275
+ mkdirSync3(dest, { recursive: true });
24028
24276
  const entries = readdirSync3(src);
24029
24277
  for (const entry of entries) {
24030
24278
  const srcPath = join6(src, entry);
@@ -24033,7 +24281,7 @@ function copyDirRecursive(src, dest) {
24033
24281
  if (stat.isDirectory()) {
24034
24282
  copyDirRecursive(srcPath, destPath);
24035
24283
  } else {
24036
- if (!existsSync8(destPath)) {
24284
+ if (!existsSync9(destPath)) {
24037
24285
  copyFileSync(srcPath, destPath);
24038
24286
  }
24039
24287
  }
@@ -24041,49 +24289,49 @@ function copyDirRecursive(src, dest) {
24041
24289
  }
24042
24290
  function renderVaultProtocolFragment(context = {}, profilesRoot = PROFILES_ROOT) {
24043
24291
  const fragPath = join6(resolve4(profilesRoot, "_shared"), "vault-protocol.md.hbs");
24044
- if (!existsSync8(fragPath))
24292
+ if (!existsSync9(fragPath))
24045
24293
  return "";
24046
- const source = readFileSync8(fragPath, "utf-8");
24294
+ const source = readFileSync9(fragPath, "utf-8");
24047
24295
  const template = import_handlebars.default.compile(source, { noEscape: true });
24048
24296
  return template(context).trimEnd();
24049
24297
  }
24050
24298
  function renderAgentSelfServiceFragment(context = {}, profilesRoot = PROFILES_ROOT) {
24051
24299
  const fragPath = join6(resolve4(profilesRoot, "_shared"), "agent-self-service.md.hbs");
24052
- if (!existsSync8(fragPath))
24300
+ if (!existsSync9(fragPath))
24053
24301
  return "";
24054
- const source = readFileSync8(fragPath, "utf-8");
24302
+ const source = readFileSync9(fragPath, "utf-8");
24055
24303
  const template = import_handlebars.default.compile(source, { noEscape: true });
24056
24304
  return template(context).trimEnd();
24057
24305
  }
24058
24306
  function renderExecutionDisciplineFragment(context = {}, profilesRoot = PROFILES_ROOT) {
24059
24307
  const fragPath = join6(resolve4(profilesRoot, "_shared"), "execution-discipline.md.hbs");
24060
- if (!existsSync8(fragPath))
24308
+ if (!existsSync9(fragPath))
24061
24309
  return "";
24062
- const source = readFileSync8(fragPath, "utf-8");
24310
+ const source = readFileSync9(fragPath, "utf-8");
24063
24311
  const template = import_handlebars.default.compile(source, { noEscape: true });
24064
24312
  return template(context).trimEnd();
24065
24313
  }
24066
24314
  function renderDevProtocolFragment(context = {}, profilesRoot = PROFILES_ROOT) {
24067
24315
  const fragPath = join6(resolve4(profilesRoot, "_shared"), "dev-protocol.md.hbs");
24068
- if (!existsSync8(fragPath))
24316
+ if (!existsSync9(fragPath))
24069
24317
  return "";
24070
- const source = readFileSync8(fragPath, "utf-8");
24318
+ const source = readFileSync9(fragPath, "utf-8");
24071
24319
  const template = import_handlebars.default.compile(source, { noEscape: true });
24072
24320
  return template(context).trimEnd();
24073
24321
  }
24074
24322
  function renderDelegationGoldenRuleFragment(context = {}, profilesRoot = PROFILES_ROOT) {
24075
24323
  const fragPath = join6(resolve4(profilesRoot, "_shared"), "delegation-golden-rule.md.hbs");
24076
- if (!existsSync8(fragPath))
24324
+ if (!existsSync9(fragPath))
24077
24325
  return "";
24078
- const source = readFileSync8(fragPath, "utf-8");
24326
+ const source = readFileSync9(fragPath, "utf-8");
24079
24327
  const template = import_handlebars.default.compile(source, { noEscape: true });
24080
24328
  return template(context).trimEnd();
24081
24329
  }
24082
24330
  function renderReplyDisciplineFragment(context = {}, profilesRoot = PROFILES_ROOT) {
24083
24331
  const fragPath = join6(resolve4(profilesRoot, "_shared"), "reply-discipline.md.hbs");
24084
- if (!existsSync8(fragPath))
24332
+ if (!existsSync9(fragPath))
24085
24333
  return "";
24086
- const source = readFileSync8(fragPath, "utf-8");
24334
+ const source = readFileSync9(fragPath, "utf-8");
24087
24335
  const template = import_handlebars.default.compile(source, { noEscape: true });
24088
24336
  return template(context).trimEnd();
24089
24337
  }
@@ -24091,14 +24339,14 @@ function renderProfileClaudeTemplate(profileName, profilesRoot = PROFILES_ROOT)
24091
24339
  const profileDir = resolve4(profilesRoot, profileName);
24092
24340
  const hbsPath = join6(profileDir, "CLAUDE.md.hbs");
24093
24341
  const outPath = join6(profileDir, "CLAUDE.md");
24094
- if (!existsSync8(hbsPath)) {
24342
+ if (!existsSync9(hbsPath)) {
24095
24343
  return { wrote: false, path: outPath };
24096
24344
  }
24097
- const source = readFileSync8(hbsPath, "utf-8");
24345
+ const source = readFileSync9(hbsPath, "utf-8");
24098
24346
  const template = import_handlebars.default.compile(source, { noEscape: true });
24099
24347
  const rendered = template({ profile: profileName });
24100
24348
  try {
24101
- writeFileSync2(outPath, rendered, "utf-8");
24349
+ writeFileSync3(outPath, rendered, "utf-8");
24102
24350
  return { wrote: true, path: outPath };
24103
24351
  } catch (err) {
24104
24352
  const code = err.code;
@@ -24123,8 +24371,8 @@ var init_profiles = __esm(() => {
24123
24371
  SHARED_FRAGMENTS = ["vault-protocol", "agent-self-service", "execution-discipline", "reply-discipline", "dev-protocol"];
24124
24372
  for (const name of SHARED_FRAGMENTS) {
24125
24373
  const fragPath = join6(SHARED_FRAGMENTS_DIR, `${name}.md.hbs`);
24126
- if (existsSync8(fragPath)) {
24127
- import_handlebars.default.registerPartial(name, readFileSync8(fragPath, "utf-8"));
24374
+ if (existsSync9(fragPath)) {
24375
+ import_handlebars.default.registerPartial(name, readFileSync9(fragPath, "utf-8"));
24128
24376
  }
24129
24377
  }
24130
24378
  });
@@ -24289,9 +24537,9 @@ function bindingsForAgent(agentName, mw, microsoftAccounts) {
24289
24537
  }
24290
24538
 
24291
24539
  // src/agents/reconcile-default-skills.ts
24292
- import { existsSync as existsSync9, lstatSync as lstatSync2, mkdirSync as mkdirSync3, readdirSync as readdirSync4, readlinkSync as readlinkSync3, rmSync as rmSync2, symlinkSync } from "node:fs";
24540
+ import { existsSync as existsSync10, lstatSync as lstatSync2, mkdirSync as mkdirSync4, readdirSync as readdirSync4, readlinkSync as readlinkSync3, rmSync as rmSync2, symlinkSync } from "node:fs";
24293
24541
  import { homedir as homedir3 } from "node:os";
24294
- import { dirname as dirname2, isAbsolute, join as join7, relative, resolve as resolve5 } from "node:path";
24542
+ import { dirname as dirname3, isAbsolute, join as join7, relative, resolve as resolve5 } from "node:path";
24295
24543
  function warnMissingPoolDir(poolDir) {
24296
24544
  if (warnedMissingPool.has(poolDir))
24297
24545
  return;
@@ -24322,10 +24570,10 @@ function isOwnedStaleLink(target, poolDir) {
24322
24570
  return false;
24323
24571
  }
24324
24572
  function absoluteLinkTarget(linkPath, storedTarget) {
24325
- return isAbsolute(storedTarget) ? storedTarget : resolve5(dirname2(linkPath), storedTarget);
24573
+ return isAbsolute(storedTarget) ? storedTarget : resolve5(dirname3(linkPath), storedTarget);
24326
24574
  }
24327
24575
  function linkTargetFor(dest, src) {
24328
- return relative(dirname2(dest), src);
24576
+ return relative(dirname3(dest), src);
24329
24577
  }
24330
24578
  function isOwnedBundledLink(dest, poolDir) {
24331
24579
  let stored = null;
@@ -24338,7 +24586,7 @@ function isOwnedBundledLink(dest, poolDir) {
24338
24586
  }
24339
24587
  if (!stored)
24340
24588
  return false;
24341
- const resolved = isAbsolute(stored) ? stored : resolve5(dirname2(dest), stored);
24589
+ const resolved = isAbsolute(stored) ? stored : resolve5(dirname3(dest), stored);
24342
24590
  const poolPrefix = poolDir.endsWith("/") ? poolDir : poolDir + "/";
24343
24591
  return resolved === poolDir || resolved.startsWith(poolPrefix);
24344
24592
  }
@@ -24355,12 +24603,12 @@ function reconcileAgentDefaultSkills(agentDir, optOuts = {}, defaults = getBuilt
24355
24603
  changed: false
24356
24604
  };
24357
24605
  const claudeDir = join7(agentDir, ".claude");
24358
- if (!existsSync9(claudeDir)) {
24606
+ if (!existsSync10(claudeDir)) {
24359
24607
  return result;
24360
24608
  }
24361
24609
  const targetDir = join7(claudeDir, "skills");
24362
- mkdirSync3(targetDir, { recursive: true });
24363
- if (!existsSync9(poolDir)) {
24610
+ mkdirSync4(targetDir, { recursive: true });
24611
+ if (!existsSync10(poolDir)) {
24364
24612
  warnMissingPoolDir(poolDir);
24365
24613
  return result;
24366
24614
  }
@@ -24378,7 +24626,7 @@ function reconcileAgentDefaultSkills(agentDir, optOuts = {}, defaults = getBuilt
24378
24626
  continue;
24379
24627
  }
24380
24628
  const src = join7(poolDir, entry.key);
24381
- if (!existsSync9(src)) {
24629
+ if (!existsSync10(src)) {
24382
24630
  result.missingFromPool.push(entry.key);
24383
24631
  warnMissingBuiltinDefault(poolDir, entry.key);
24384
24632
  if (isOwnedBundledLink(dest, poolDir)) {
@@ -24439,7 +24687,7 @@ function reconcileAgentDefaultSkills(agentDir, optOuts = {}, defaults = getBuilt
24439
24687
  continue;
24440
24688
  try {
24441
24689
  const st = lstatSync2(join7(poolDir, poolName));
24442
- if (st.isDirectory() && existsSync9(join7(poolDir, poolName, "SKILL.md"))) {
24690
+ if (st.isDirectory() && existsSync10(join7(poolDir, poolName, "SKILL.md"))) {
24443
24691
  legitimate.add(poolName);
24444
24692
  }
24445
24693
  } catch {}
@@ -24518,25 +24766,25 @@ function applyTelegramProgressGuidance(body, args) {
24518
24766
 
24519
24767
  // src/telegram/state.ts
24520
24768
  import {
24521
- readFileSync as readFileSync9,
24522
- writeFileSync as writeFileSync3,
24523
- mkdirSync as mkdirSync4,
24524
- existsSync as existsSync10,
24769
+ readFileSync as readFileSync10,
24770
+ writeFileSync as writeFileSync4,
24771
+ mkdirSync as mkdirSync5,
24772
+ existsSync as existsSync11,
24525
24773
  renameSync as renameSync2,
24526
24774
  copyFileSync as copyFileSync2,
24527
24775
  unlinkSync
24528
24776
  } from "node:fs";
24529
- import { basename as basename2, dirname as dirname3, resolve as resolve6 } from "node:path";
24777
+ import { basename as basename2, dirname as dirname4, resolve as resolve6 } from "node:path";
24530
24778
  function defaultStatePath() {
24531
24779
  return resolveStatePath("topics.json");
24532
24780
  }
24533
24781
  function loadTopicState(statePath) {
24534
24782
  const path = statePath ?? defaultStatePath();
24535
- if (!existsSync10(path)) {
24783
+ if (!existsSync11(path)) {
24536
24784
  return { topics: {} };
24537
24785
  }
24538
24786
  try {
24539
- const raw = readFileSync9(path, "utf-8");
24787
+ const raw = readFileSync10(path, "utf-8");
24540
24788
  const parsed = JSON.parse(raw);
24541
24789
  if (parsed && typeof parsed === "object" && parsed.topics && typeof parsed.topics === "object") {
24542
24790
  return parsed;
@@ -24553,19 +24801,19 @@ function loadTopicState(statePath) {
24553
24801
  }
24554
24802
  function saveTopicState(state, statePath) {
24555
24803
  const path = statePath ?? defaultStatePath();
24556
- const dir = dirname3(path);
24557
- if (!existsSync10(dir)) {
24558
- mkdirSync4(dir, { recursive: true });
24804
+ const dir = dirname4(path);
24805
+ if (!existsSync11(dir)) {
24806
+ mkdirSync5(dir, { recursive: true });
24559
24807
  }
24560
24808
  const absDir = resolve6(dir);
24561
24809
  const tmp = resolve6(absDir, `.${basename2(path)}.${process.pid}.${Date.now()}.tmp`);
24562
24810
  try {
24563
- writeFileSync3(tmp, JSON.stringify(state, null, 2) + `
24811
+ writeFileSync4(tmp, JSON.stringify(state, null, 2) + `
24564
24812
  `, "utf-8");
24565
24813
  renameSync2(tmp, path);
24566
24814
  } catch (err) {
24567
24815
  try {
24568
- if (existsSync10(tmp))
24816
+ if (existsSync11(tmp))
24569
24817
  unlinkSync(tmp);
24570
24818
  } catch {}
24571
24819
  throw err;
@@ -24577,13 +24825,13 @@ var init_state = __esm(() => {
24577
24825
 
24578
24826
  // src/vault/flock.ts
24579
24827
  import {
24580
- existsSync as existsSync11,
24828
+ existsSync as existsSync12,
24581
24829
  openSync as openSync3,
24582
24830
  closeSync as closeSync3,
24583
24831
  writeSync as writeSync2,
24584
24832
  fsyncSync as fsyncSync2,
24585
24833
  unlinkSync as unlinkSync2,
24586
- readFileSync as readFileSync10,
24834
+ readFileSync as readFileSync11,
24587
24835
  readdirSync as readdirSync5,
24588
24836
  rmdirSync,
24589
24837
  statSync as statSync5,
@@ -24594,7 +24842,7 @@ function lockPathFor(vaultPath) {
24594
24842
  }
24595
24843
  function readLockHolder(lockPath) {
24596
24844
  try {
24597
- const raw = readFileSync10(lockPath, "utf8");
24845
+ const raw = readFileSync11(lockPath, "utf8");
24598
24846
  const lines = raw.split(`
24599
24847
  `);
24600
24848
  const pid = Number.parseInt(lines[0] ?? "", 10);
@@ -24610,7 +24858,7 @@ function readLockHolder(lockPath) {
24610
24858
  }
24611
24859
  function pidIsLive(pid) {
24612
24860
  if (process.platform === "linux") {
24613
- return existsSync11(`/proc/${pid}`);
24861
+ return existsSync12(`/proc/${pid}`);
24614
24862
  }
24615
24863
  try {
24616
24864
  process.kill(pid, 0);
@@ -24646,8 +24894,8 @@ function pidStartTimeMs(pid) {
24646
24894
  if (process.platform !== "linux")
24647
24895
  return null;
24648
24896
  try {
24649
- const statLine = readFileSync10(`/proc/${pid}/stat`, "utf8");
24650
- const procStat = readFileSync10("/proc/stat", "utf8");
24897
+ const statLine = readFileSync11(`/proc/${pid}/stat`, "utf8");
24898
+ const procStat = readFileSync11("/proc/stat", "utf8");
24651
24899
  return parseProcStartTimeMs(statLine, procStat, Date.now());
24652
24900
  } catch {
24653
24901
  return null;
@@ -24670,7 +24918,7 @@ function lockFileMtimeIsOlderThan(lockPath, budgetMs) {
24670
24918
  }
24671
24919
  function clearStaleSentinelDir(lockPath) {
24672
24920
  try {
24673
- if (!existsSync11(lockPath))
24921
+ if (!existsSync12(lockPath))
24674
24922
  return true;
24675
24923
  const s = statSync5(lockPath);
24676
24924
  if (!s.isDirectory())
@@ -24813,11 +25061,11 @@ __export(exports_vault, {
24813
25061
  });
24814
25062
  import { randomBytes as randomBytes2, scryptSync, createCipheriv, createDecipheriv } from "node:crypto";
24815
25063
  import {
24816
- readFileSync as readFileSync11,
25064
+ readFileSync as readFileSync12,
24817
25065
  writeSync as writeSync3,
24818
- existsSync as existsSync12,
25066
+ existsSync as existsSync13,
24819
25067
  renameSync as renameSync3,
24820
- mkdirSync as mkdirSync5,
25068
+ mkdirSync as mkdirSync6,
24821
25069
  unlinkSync as unlinkSync3,
24822
25070
  fsyncSync as fsyncSync3,
24823
25071
  openSync as openSync4,
@@ -24825,15 +25073,15 @@ import {
24825
25073
  lstatSync as lstatSync3,
24826
25074
  realpathSync as realpathSync2
24827
25075
  } from "node:fs";
24828
- import { dirname as dirname4, basename as basename3, resolve as resolve7 } from "node:path";
25076
+ import { dirname as dirname5, basename as basename3, resolve as resolve7 } from "node:path";
24829
25077
  function atomicWriteFileSync2(path, data, mode) {
24830
25078
  let effectivePath = path;
24831
25079
  try {
24832
- if (existsSync12(path) && lstatSync3(path).isSymbolicLink()) {
25080
+ if (existsSync13(path) && lstatSync3(path).isSymbolicLink()) {
24833
25081
  effectivePath = realpathSync2(path);
24834
25082
  }
24835
25083
  } catch {}
24836
- const dir = dirname4(resolve7(effectivePath));
25084
+ const dir = dirname5(resolve7(effectivePath));
24837
25085
  const tmp = resolve7(dir, `.${basename3(effectivePath)}.${process.pid}.${Date.now()}.tmp`);
24838
25086
  try {
24839
25087
  const fd = openSync4(tmp, "wx", mode);
@@ -24854,7 +25102,7 @@ function atomicWriteFileSync2(path, data, mode) {
24854
25102
  } catch {}
24855
25103
  } catch (err) {
24856
25104
  try {
24857
- if (existsSync12(tmp))
25105
+ if (existsSync13(tmp))
24858
25106
  unlinkSync3(tmp);
24859
25107
  } catch {}
24860
25108
  throw err;
@@ -24967,12 +25215,12 @@ function detectFormat(value) {
24967
25215
  return null;
24968
25216
  }
24969
25217
  function createVault(passphrase, vaultPath) {
24970
- if (existsSync12(vaultPath)) {
25218
+ if (existsSync13(vaultPath)) {
24971
25219
  throw new VaultError(`Vault file already exists: ${vaultPath}`);
24972
25220
  }
24973
- const dir = dirname4(vaultPath);
24974
- if (!existsSync12(dir)) {
24975
- mkdirSync5(dir, { recursive: true, mode: 448 });
25221
+ const dir = dirname5(vaultPath);
25222
+ if (!existsSync13(dir)) {
25223
+ mkdirSync6(dir, { recursive: true, mode: 448 });
24976
25224
  }
24977
25225
  const salt = randomBytes2(16);
24978
25226
  const key = deriveKey(passphrase, salt);
@@ -24988,12 +25236,12 @@ function createVault(passphrase, vaultPath) {
24988
25236
  atomicWriteFileSync2(vaultPath, JSON.stringify(vaultFile, null, 2), 384);
24989
25237
  }
24990
25238
  function openVault(passphrase, vaultPath) {
24991
- if (!existsSync12(vaultPath)) {
25239
+ if (!existsSync13(vaultPath)) {
24992
25240
  throw new VaultError(`Vault file not found: ${vaultPath}`);
24993
25241
  }
24994
25242
  let vaultFile;
24995
25243
  try {
24996
- vaultFile = JSON.parse(readFileSync11(vaultPath, "utf8"));
25244
+ vaultFile = JSON.parse(readFileSync12(vaultPath, "utf8"));
24997
25245
  } catch {
24998
25246
  throw new VaultError(`Failed to read vault file: ${vaultPath}`);
24999
25247
  }
@@ -25015,7 +25263,7 @@ function openVault(passphrase, vaultPath) {
25015
25263
  return normalizeSecrets(vaultData.secrets ?? {});
25016
25264
  }
25017
25265
  function saveVault(passphrase, vaultPath, secrets) {
25018
- if (!existsSync12(vaultPath)) {
25266
+ if (!existsSync13(vaultPath)) {
25019
25267
  throw new VaultError(`Vault file not found: ${vaultPath}`);
25020
25268
  }
25021
25269
  let releaseLock = null;
@@ -25030,7 +25278,7 @@ function saveVault(passphrase, vaultPath, secrets) {
25030
25278
  try {
25031
25279
  let vaultFile;
25032
25280
  try {
25033
- vaultFile = JSON.parse(readFileSync11(vaultPath, "utf8"));
25281
+ vaultFile = JSON.parse(readFileSync12(vaultPath, "utf8"));
25034
25282
  } catch {
25035
25283
  throw new VaultError(`Failed to read vault file: ${vaultPath}`);
25036
25284
  }
@@ -25937,7 +26185,7 @@ __export(exports_resolver, {
25937
26185
  import {
25938
26186
  chmodSync,
25939
26187
  closeSync as closeSync5,
25940
- mkdirSync as mkdirSync6,
26188
+ mkdirSync as mkdirSync7,
25941
26189
  mkdtempSync,
25942
26190
  openSync as openSync5,
25943
26191
  rmSync as rmSync3,
@@ -25997,7 +26245,7 @@ function materializationRoot() {
25997
26245
  const xdg = process.env.XDG_RUNTIME_DIR;
25998
26246
  if (xdg) {
25999
26247
  const base = join9(xdg, "switchroom", "vault");
26000
- mkdirSync6(base, { recursive: true, mode: 448 });
26248
+ mkdirSync7(base, { recursive: true, mode: 448 });
26001
26249
  cachedRoot = mkdtempSync(join9(base, "run-"));
26002
26250
  } else {
26003
26251
  cachedRoot = mkdtempSync(join9(tmpdir(), "switchroom-vault-"));
@@ -26021,7 +26269,7 @@ function materializeFilesEntry(key, files) {
26021
26269
  rmSync3(dir, { recursive: true, force: true });
26022
26270
  } catch {}
26023
26271
  }
26024
- mkdirSync6(dir, { recursive: true, mode: 448 });
26272
+ mkdirSync7(dir, { recursive: true, mode: 448 });
26025
26273
  chmodSync(dir, 448);
26026
26274
  const st = statSync7(dir);
26027
26275
  if (typeof process.getuid === "function" && st.uid !== process.getuid()) {
@@ -26178,7 +26426,7 @@ var init_resolver = __esm(() => {
26178
26426
  });
26179
26427
 
26180
26428
  // src/setup/onboarding.ts
26181
- import { existsSync as existsSync14, copyFileSync as copyFileSync3, mkdirSync as mkdirSync7, writeFileSync as writeFileSync4, readFileSync as readFileSync13 } from "node:fs";
26429
+ import { existsSync as existsSync15, copyFileSync as copyFileSync3, mkdirSync as mkdirSync8, writeFileSync as writeFileSync5, readFileSync as readFileSync14 } from "node:fs";
26182
26430
  import { resolve as resolve8, join as join10 } from "node:path";
26183
26431
  function findExistingClaudeJson() {
26184
26432
  const home2 = process.env.HOME ?? "/root";
@@ -26190,7 +26438,7 @@ function findExistingClaudeJson() {
26190
26438
  resolve8(home2, ".claude", "config.json")
26191
26439
  ];
26192
26440
  for (const candidate of candidates) {
26193
- if (existsSync14(candidate)) {
26441
+ if (existsSync15(candidate)) {
26194
26442
  return candidate;
26195
26443
  }
26196
26444
  }
@@ -26202,9 +26450,9 @@ function findExistingClaudeJson() {
26202
26450
  }
26203
26451
  function copyOnboardingState(sourcePath, agentDir, configDirName = ".claude") {
26204
26452
  const claudeDir = join10(agentDir, configDirName);
26205
- mkdirSync7(claudeDir, { recursive: true });
26453
+ mkdirSync8(claudeDir, { recursive: true });
26206
26454
  const destPath = join10(claudeDir, ".claude.json");
26207
- if (!existsSync14(destPath)) {
26455
+ if (!existsSync15(destPath)) {
26208
26456
  copyFileSync3(sourcePath, destPath);
26209
26457
  }
26210
26458
  }
@@ -26227,18 +26475,18 @@ function buildAccessJson(userId, forumChatId, topicId, opts = {}) {
26227
26475
  }
26228
26476
  function writeAccessJson(agentDir, userId, forumChatId, topicId, opts = {}) {
26229
26477
  const telegramDir = join10(agentDir, "telegram");
26230
- mkdirSync7(telegramDir, { recursive: true });
26478
+ mkdirSync8(telegramDir, { recursive: true });
26231
26479
  const accessPath = join10(telegramDir, "access.json");
26232
- writeFileSync4(accessPath, buildAccessJson(userId, forumChatId, topicId, opts), {
26480
+ writeFileSync5(accessPath, buildAccessJson(userId, forumChatId, topicId, opts), {
26233
26481
  encoding: "utf-8",
26234
26482
  mode: 384
26235
26483
  });
26236
26484
  }
26237
26485
  function writeAgentEnv(agentDir, botToken) {
26238
26486
  const telegramDir = join10(agentDir, "telegram");
26239
- mkdirSync7(telegramDir, { recursive: true });
26487
+ mkdirSync8(telegramDir, { recursive: true });
26240
26488
  const envPath = join10(telegramDir, ".env");
26241
- writeFileSync4(envPath, `TELEGRAM_BOT_TOKEN=${botToken}
26489
+ writeFileSync5(envPath, `TELEGRAM_BOT_TOKEN=${botToken}
26242
26490
  `, {
26243
26491
  encoding: "utf-8",
26244
26492
  mode: 384
@@ -26250,12 +26498,12 @@ function userConfigPath() {
26250
26498
  function saveUserConfig(userId, username) {
26251
26499
  const configPath = userConfigPath();
26252
26500
  const dir = join10(configPath, "..");
26253
- mkdirSync7(dir, { recursive: true });
26501
+ mkdirSync8(dir, { recursive: true });
26254
26502
  const config = { userId };
26255
26503
  if (username) {
26256
26504
  config.username = username;
26257
26505
  }
26258
- writeFileSync4(configPath, JSON.stringify(config, null, 2) + `
26506
+ writeFileSync5(configPath, JSON.stringify(config, null, 2) + `
26259
26507
  `, {
26260
26508
  encoding: "utf-8",
26261
26509
  mode: 384
@@ -26263,11 +26511,11 @@ function saveUserConfig(userId, username) {
26263
26511
  }
26264
26512
  function loadUserConfig() {
26265
26513
  const configPath = userConfigPath();
26266
- if (!existsSync14(configPath)) {
26514
+ if (!existsSync15(configPath)) {
26267
26515
  return null;
26268
26516
  }
26269
26517
  try {
26270
- const raw = readFileSync13(configPath, "utf-8");
26518
+ const raw = readFileSync14(configPath, "utf-8");
26271
26519
  const parsed = JSON.parse(raw);
26272
26520
  if (parsed && typeof parsed === "object") {
26273
26521
  return parsed;
@@ -26279,11 +26527,11 @@ function loadUserConfig() {
26279
26527
  }
26280
26528
  function preTrustWorkspace(agentDir, configDirName = ".claude") {
26281
26529
  const configPath = join10(agentDir, configDirName, ".claude.json");
26282
- if (!existsSync14(configPath)) {
26530
+ if (!existsSync15(configPath)) {
26283
26531
  return;
26284
26532
  }
26285
26533
  try {
26286
- const raw = readFileSync13(configPath, "utf-8");
26534
+ const raw = readFileSync14(configPath, "utf-8");
26287
26535
  const config = JSON.parse(raw);
26288
26536
  if (!config.projects) {
26289
26537
  config.projects = {};
@@ -26295,7 +26543,7 @@ function preTrustWorkspace(agentDir, configDirName = ".claude") {
26295
26543
  allowedTools: []
26296
26544
  };
26297
26545
  }
26298
- writeFileSync4(configPath, JSON.stringify(config, null, 2) + `
26546
+ writeFileSync5(configPath, JSON.stringify(config, null, 2) + `
26299
26547
  `, {
26300
26548
  encoding: "utf-8",
26301
26549
  mode: 384
@@ -26304,11 +26552,11 @@ function preTrustWorkspace(agentDir, configDirName = ".claude") {
26304
26552
  }
26305
26553
  function ensureMcpServersTrusted(agentDir, serverKeys, configDirName = ".claude") {
26306
26554
  const configPath = join10(agentDir, configDirName, ".claude.json");
26307
- if (!existsSync14(configPath)) {
26555
+ if (!existsSync15(configPath)) {
26308
26556
  return;
26309
26557
  }
26310
26558
  try {
26311
- const raw = readFileSync13(configPath, "utf-8");
26559
+ const raw = readFileSync14(configPath, "utf-8");
26312
26560
  const config = JSON.parse(raw);
26313
26561
  if (!config.projects) {
26314
26562
  config.projects = {};
@@ -26322,7 +26570,7 @@ function ensureMcpServersTrusted(agentDir, serverKeys, configDirName = ".claude"
26322
26570
  const existing = Array.isArray(project.enabledMcpjsonServers) ? project.enabledMcpjsonServers : [];
26323
26571
  project.enabledMcpjsonServers = Array.from(new Set([...existing, ...serverKeys]));
26324
26572
  config.projects[absDir] = project;
26325
- writeFileSync4(configPath, JSON.stringify(config, null, 2) + `
26573
+ writeFileSync5(configPath, JSON.stringify(config, null, 2) + `
26326
26574
  `, {
26327
26575
  encoding: "utf-8",
26328
26576
  mode: 384
@@ -26333,14 +26581,14 @@ function ensureMcpServersTrusted(agentDir, serverKeys, configDirName = ".claude"
26333
26581
  }
26334
26582
  function createMinimalClaudeConfig(agentDir, configDirName = ".claude") {
26335
26583
  const claudeDir = join10(agentDir, configDirName);
26336
- mkdirSync7(claudeDir, { recursive: true });
26584
+ mkdirSync8(claudeDir, { recursive: true });
26337
26585
  const configPath = join10(claudeDir, ".claude.json");
26338
- if (!existsSync14(configPath)) {
26586
+ if (!existsSync15(configPath)) {
26339
26587
  const minimal = {
26340
26588
  hasCompletedOnboarding: true,
26341
26589
  numStartups: 1
26342
26590
  };
26343
- writeFileSync4(configPath, JSON.stringify(minimal, null, 2) + `
26591
+ writeFileSync5(configPath, JSON.stringify(minimal, null, 2) + `
26344
26592
  `, {
26345
26593
  encoding: "utf-8",
26346
26594
  mode: 384
@@ -26351,8 +26599,8 @@ function seedCronConfigDir(agentDir, serverKeys) {
26351
26599
  const mainConfig = join10(agentDir, ".claude", ".claude.json");
26352
26600
  const cronDir = join10(agentDir, ".claude-cron");
26353
26601
  const cronConfig = join10(cronDir, ".claude.json");
26354
- mkdirSync7(cronDir, { recursive: true });
26355
- if (existsSync14(mainConfig)) {
26602
+ mkdirSync8(cronDir, { recursive: true });
26603
+ if (existsSync15(mainConfig)) {
26356
26604
  try {
26357
26605
  copyFileSync3(mainConfig, cronConfig);
26358
26606
  } catch {
@@ -26370,16 +26618,16 @@ var init_onboarding = __esm(() => {
26370
26618
 
26371
26619
  // src/repos/bare-clone.ts
26372
26620
  import { execFileSync as execFileSync4 } from "node:child_process";
26373
- import { existsSync as existsSync15, mkdirSync as mkdirSync8 } from "node:fs";
26621
+ import { existsSync as existsSync16, mkdirSync as mkdirSync9 } from "node:fs";
26374
26622
  import { resolve as resolve9 } from "node:path";
26375
26623
  function bareClonePath(slug) {
26376
26624
  return resolveStatePath(`repos/${slug}.git`);
26377
26625
  }
26378
26626
  function ensureBareClone(slug, url) {
26379
26627
  const reposDir = resolveStatePath("repos");
26380
- mkdirSync8(reposDir, { recursive: true });
26628
+ mkdirSync9(reposDir, { recursive: true });
26381
26629
  const clonePath = bareClonePath(slug);
26382
- if (!existsSync15(clonePath)) {
26630
+ if (!existsSync16(clonePath)) {
26383
26631
  process.stderr.write(`[switchroom] repo "${slug}": cloning ${url} \u2026
26384
26632
  `);
26385
26633
  execFileSync4("git", ["clone", "--bare", url, clonePath], {
@@ -26409,7 +26657,7 @@ var init_bare_clone = __esm(() => {
26409
26657
 
26410
26658
  // src/repos/agent-worktree.ts
26411
26659
  import { execFileSync as execFileSync5 } from "node:child_process";
26412
- import { existsSync as existsSync16, mkdirSync as mkdirSync9, readdirSync as readdirSync6 } from "node:fs";
26660
+ import { existsSync as existsSync17, mkdirSync as mkdirSync10, readdirSync as readdirSync6 } from "node:fs";
26413
26661
  import { join as join11, resolve as resolve10 } from "node:path";
26414
26662
  function agentBranchName(agentName) {
26415
26663
  return `agent/${agentName}/main`;
@@ -26468,8 +26716,8 @@ function ensureAgentWorktree(agentName, slug, bareClonePath2, agentDir) {
26468
26716
  const worktreePath = agentWorktreePath(agentDir, slug);
26469
26717
  const branch = agentBranchName(agentName);
26470
26718
  const defaultBranch = resolveDefaultBranch(bareClonePath2);
26471
- if (!existsSync16(worktreePath)) {
26472
- mkdirSync9(join11(agentDir, "work"), { recursive: true });
26719
+ if (!existsSync17(worktreePath)) {
26720
+ mkdirSync10(join11(agentDir, "work"), { recursive: true });
26473
26721
  if (branchExistsInBare(bareClonePath2, branch)) {
26474
26722
  execFileSync5("git", ["worktree", "add", worktreePath, branch], {
26475
26723
  cwd: bareClonePath2,
@@ -26524,7 +26772,7 @@ function ensureAgentWorktree(agentName, slug, bareClonePath2, agentDir) {
26524
26772
  function removeAgentWorktree(agentName, slug, bareClonePath2, agentDir) {
26525
26773
  const worktreePath = agentWorktreePath(agentDir, slug);
26526
26774
  const branch = agentBranchName(agentName);
26527
- if (existsSync16(worktreePath)) {
26775
+ if (existsSync17(worktreePath)) {
26528
26776
  try {
26529
26777
  execFileSync5("git", ["worktree", "remove", "--force", worktreePath], {
26530
26778
  cwd: bareClonePath2,
@@ -26561,11 +26809,11 @@ var init_agent_worktree = () => {};
26561
26809
 
26562
26810
  // src/agents/scaffold.ts
26563
26811
  import {
26564
- existsSync as existsSync17,
26565
- mkdirSync as mkdirSync10,
26566
- writeFileSync as writeFileSync5,
26812
+ existsSync as existsSync18,
26813
+ mkdirSync as mkdirSync11,
26814
+ writeFileSync as writeFileSync6,
26567
26815
  appendFileSync as appendFileSync2,
26568
- readFileSync as readFileSync14,
26816
+ readFileSync as readFileSync15,
26569
26817
  renameSync as renameSync4,
26570
26818
  chmodSync as chmodSync2,
26571
26819
  symlinkSync as symlinkSync2,
@@ -26579,7 +26827,7 @@ import {
26579
26827
  } from "node:fs";
26580
26828
  import { homedir as homedir5 } from "node:os";
26581
26829
  import { execSync, execFileSync as execFileSync6 } from "node:child_process";
26582
- import { dirname as dirname5, isAbsolute as isAbsolute2, join as join12, relative as relative2, resolve as resolve11 } from "node:path";
26830
+ import { dirname as dirname6, isAbsolute as isAbsolute2, join as join12, relative as relative2, resolve as resolve11 } from "node:path";
26583
26831
  import { createHash as createHash4 } from "node:crypto";
26584
26832
  function prependReplyDiscipline(rendered, context) {
26585
26833
  const replyDiscipline = renderReplyDisciplineFragment(context);
@@ -26661,12 +26909,12 @@ function maybeWriteCronMcp(agentDir, mcpServers, cronSessionEnabled) {
26661
26909
  "switchroom-telegram": cronTelegram
26662
26910
  };
26663
26911
  const cronDir = join12(agentDir, ".claude-cron");
26664
- mkdirSync10(cronDir, { recursive: true });
26912
+ mkdirSync11(cronDir, { recursive: true });
26665
26913
  const path = join12(cronDir, ".mcp.json");
26666
26914
  const content = JSON.stringify({ mcpServers: cronServers }, null, 2) + `
26667
26915
  `;
26668
- if (!existsSync17(path) || readFileSync14(path, "utf-8") !== content) {
26669
- writeFileSync5(path, content, { encoding: "utf-8", mode: 384 });
26916
+ if (!existsSync18(path) || readFileSync15(path, "utf-8") !== content) {
26917
+ writeFileSync6(path, content, { encoding: "utf-8", mode: 384 });
26670
26918
  }
26671
26919
  seedCronConfigDir(agentDir, Object.keys(cronServers));
26672
26920
  return path;
@@ -26677,13 +26925,13 @@ function alignAgentUid(name, agentDir, uid, opts = {}) {
26677
26925
  const auditDir = join12(homedir5(), ".switchroom", "audit", name);
26678
26926
  const configMirrorDir = join12(homedir5(), ".switchroom-config", "agents", name, "personal-skills");
26679
26927
  const paths = [];
26680
- if (existsSync17(agentDir))
26928
+ if (existsSync18(agentDir))
26681
26929
  paths.push(agentDir);
26682
- if (existsSync17(logsDir))
26930
+ if (existsSync18(logsDir))
26683
26931
  paths.push(logsDir);
26684
- if (existsSync17(auditDir))
26932
+ if (existsSync18(auditDir))
26685
26933
  paths.push(auditDir);
26686
- if (existsSync17(configMirrorDir))
26934
+ if (existsSync18(configMirrorDir))
26687
26935
  paths.push(configMirrorDir);
26688
26936
  if (paths.length === 0)
26689
26937
  return { chowned: false, paths: [] };
@@ -26700,7 +26948,7 @@ function alignAgentUid(name, agentDir, uid, opts = {}) {
26700
26948
  return { chowned: false, paths };
26701
26949
  try {
26702
26950
  const logPath = join12(homedir5(), ".switchroom", ".uid-alignment.log");
26703
- mkdirSync10(join12(homedir5(), ".switchroom"), { recursive: true });
26951
+ mkdirSync11(join12(homedir5(), ".switchroom"), { recursive: true });
26704
26952
  const ts = new Date().toISOString();
26705
26953
  for (const prior of priors) {
26706
26954
  if (prior.uid !== undefined && prior.gid !== undefined && (prior.uid !== uid || prior.gid !== uid)) {
@@ -26756,16 +27004,16 @@ function refreshTelegramBotTokenEnv(agentDir, resolvedBotToken, changes) {
26756
27004
  if (!resolvedBotToken)
26757
27005
  return;
26758
27006
  const envPath = join12(agentDir, "telegram", ".env");
26759
- if (!existsSync17(envPath))
27007
+ if (!existsSync18(envPath))
26760
27008
  return;
26761
- const current = readFileSync14(envPath, "utf-8");
27009
+ const current = readFileSync15(envPath, "utf-8");
26762
27010
  if (!isTelegramEnvPlaceholder(current))
26763
27011
  return;
26764
27012
  const next = `TELEGRAM_BOT_TOKEN=${resolvedBotToken}
26765
27013
  `;
26766
27014
  if (next === current)
26767
27015
  return;
26768
- writeFileSync5(envPath, next, { encoding: "utf-8", mode: 384 });
27016
+ writeFileSync6(envPath, next, { encoding: "utf-8", mode: 384 });
26769
27017
  changes.push(envPath);
26770
27018
  }
26771
27019
  function stripOfficialTelegramPlugin(payload) {
@@ -26793,10 +27041,10 @@ function setupPlugins(agentDir, useSwitchroomPlugin = false) {
26793
27041
  const globalPluginsDir = join12(home2, ".claude", "plugins");
26794
27042
  const agentPluginsDir = join12(agentDir, ".claude", "plugins");
26795
27043
  const agentMarketplacesDir = join12(agentPluginsDir, "marketplaces");
26796
- mkdirSync10(agentMarketplacesDir, { recursive: true });
27044
+ mkdirSync11(agentMarketplacesDir, { recursive: true });
26797
27045
  const globalMarketplace = join12(globalPluginsDir, "marketplaces", "claude-plugins-official");
26798
27046
  const agentMarketplace = join12(agentMarketplacesDir, "claude-plugins-official");
26799
- if (existsSync17(globalMarketplace) && !existsSync17(agentMarketplace)) {
27047
+ if (existsSync18(globalMarketplace) && !existsSync18(agentMarketplace)) {
26800
27048
  try {
26801
27049
  symlinkSync2(globalMarketplace, agentMarketplace);
26802
27050
  } catch {}
@@ -26805,11 +27053,11 @@ function setupPlugins(agentDir, useSwitchroomPlugin = false) {
26805
27053
  for (const file of configFiles) {
26806
27054
  const globalFile = join12(globalPluginsDir, file);
26807
27055
  const agentFile = join12(agentPluginsDir, file);
26808
- if (existsSync17(globalFile) && !existsSync17(agentFile)) {
27056
+ if (existsSync18(globalFile) && !existsSync18(agentFile)) {
26809
27057
  try {
26810
27058
  if (useSwitchroomPlugin && file === "installed_plugins.json") {
26811
- const scrubbed = stripOfficialTelegramPlugin(readFileSync14(globalFile, "utf8"));
26812
- writeFileSync5(agentFile, scrubbed);
27059
+ const scrubbed = stripOfficialTelegramPlugin(readFileSync15(globalFile, "utf8"));
27060
+ writeFileSync6(agentFile, scrubbed);
26813
27061
  } else {
26814
27062
  copyFileSync4(globalFile, agentFile);
26815
27063
  }
@@ -26820,9 +27068,9 @@ function setupPlugins(agentDir, useSwitchroomPlugin = false) {
26820
27068
  function webkiteBinaryAvailable() {
26821
27069
  const override = process.env.SWITCHROOM_WEBKITE_BINARY;
26822
27070
  if (override !== undefined && override !== "") {
26823
- return existsSync17(override);
27071
+ return existsSync18(override);
26824
27072
  }
26825
- return existsSync17(join12(homedir5(), ".switchroom", "bin", "webkite")) || existsSync17(WEBKITE_BINARY_CONTAINER_PATH);
27073
+ return existsSync18(join12(homedir5(), ".switchroom", "bin", "webkite")) || existsSync18(WEBKITE_BINARY_CONTAINER_PATH);
26826
27074
  }
26827
27075
  function webkiteDenyForAgent(agentConfig) {
26828
27076
  if (agentConfig.mcp_servers?.["webkite"] === false)
@@ -26875,9 +27123,9 @@ function toHostHomePath(p) {
26875
27123
  return p;
26876
27124
  }
26877
27125
  function composeWithSidecar(renderedBase, sidecarPath) {
26878
- if (!existsSync17(sidecarPath))
27126
+ if (!existsSync18(sidecarPath))
26879
27127
  return renderedBase;
26880
- const sidecar = readFileSync14(sidecarPath, "utf-8").trimEnd();
27128
+ const sidecar = readFileSync15(sidecarPath, "utf-8").trimEnd();
26881
27129
  if (sidecar.length === 0)
26882
27130
  return renderedBase;
26883
27131
  return `${renderedBase.trimEnd()}
@@ -26895,8 +27143,8 @@ function resolveClaudeMdYoursSection(existingFileContent, sidecarPath) {
26895
27143
  return afterMarker.trimEnd();
26896
27144
  }
26897
27145
  }
26898
- if (existsSync17(sidecarPath)) {
26899
- const sidecar = readFileSync14(sidecarPath, "utf-8").trimEnd();
27146
+ if (existsSync18(sidecarPath)) {
27147
+ const sidecar = readFileSync15(sidecarPath, "utf-8").trimEnd();
26900
27148
  if (sidecar.length > 0) {
26901
27149
  const deprecatedPath = sidecarPath + ".deprecated";
26902
27150
  try {
@@ -26919,7 +27167,7 @@ ${yours.trimEnd()}
26919
27167
  }
26920
27168
  function renderSoulMd(profilePath, agentWorkspaceDir, soul) {
26921
27169
  const soulMdSrc = join12(profilePath, "workspace", "SOUL.md.hbs");
26922
- if (!existsSync17(soulMdSrc))
27170
+ if (!existsSync18(soulMdSrc))
26923
27171
  return null;
26924
27172
  const rendered = renderTemplate(soulMdSrc, { soul });
26925
27173
  const customSoulPath = join12(agentWorkspaceDir, "SOUL.custom.md");
@@ -27007,7 +27255,7 @@ function migrateLegacySkillsDir(agentDir, skillsPool) {
27007
27255
  } catch {
27008
27256
  continue;
27009
27257
  }
27010
- const resolved = target ? isAbsolute2(target) ? target : resolve11(dirname5(entryPath), target) : null;
27258
+ const resolved = target ? isAbsolute2(target) ? target : resolve11(dirname6(entryPath), target) : null;
27011
27259
  if (resolved && resolved.startsWith(skillsPool)) {
27012
27260
  try {
27013
27261
  rmSync4(entryPath, { force: true });
@@ -27018,7 +27266,7 @@ function migrateLegacySkillsDir(agentDir, skillsPool) {
27018
27266
  function syncGlobalSkills(agentDir, declared, skillsDirOverride) {
27019
27267
  const skillsPool = resolveSkillsPoolDir(skillsDirOverride);
27020
27268
  const agentSkillsDir = join12(agentDir, ".claude", "skills");
27021
- mkdirSync10(agentSkillsDir, { recursive: true });
27269
+ mkdirSync11(agentSkillsDir, { recursive: true });
27022
27270
  migrateLegacySkillsDir(agentDir, skillsPool);
27023
27271
  for (const name of declared) {
27024
27272
  if (!name || name.includes("/") || name === "." || name === "..") {
@@ -27027,11 +27275,11 @@ function syncGlobalSkills(agentDir, declared, skillsDirOverride) {
27027
27275
  }
27028
27276
  const src = join12(skillsPool, name);
27029
27277
  const dest = join12(agentSkillsDir, name);
27030
- if (!existsSync17(src)) {
27278
+ if (!existsSync18(src)) {
27031
27279
  console.warn(` WARNING: skill "${name}" not found in pool (${skillsPool}) \u2014 skipping`);
27032
27280
  continue;
27033
27281
  }
27034
- const relTarget = relative2(dirname5(dest), src);
27282
+ const relTarget = relative2(dirname6(dest), src);
27035
27283
  let linkStat;
27036
27284
  try {
27037
27285
  linkStat = lstatSync4(dest);
@@ -27047,7 +27295,7 @@ function syncGlobalSkills(agentDir, declared, skillsDirOverride) {
27047
27295
  if (target === relTarget) {
27048
27296
  continue;
27049
27297
  }
27050
- const resolved = target ? isAbsolute2(target) ? target : resolve11(dirname5(dest), target) : null;
27298
+ const resolved = target ? isAbsolute2(target) ? target : resolve11(dirname6(dest), target) : null;
27051
27299
  if (resolved && resolved.startsWith(skillsPool)) {
27052
27300
  try {
27053
27301
  rmSync4(dest, { force: true });
@@ -27076,7 +27324,7 @@ function syncGlobalSkills(agentDir, declared, skillsDirOverride) {
27076
27324
  } catch {
27077
27325
  continue;
27078
27326
  }
27079
- const resolved = linkTarget ? isAbsolute2(linkTarget) ? linkTarget : resolve11(dirname5(entryPath), linkTarget) : null;
27327
+ const resolved = linkTarget ? isAbsolute2(linkTarget) ? linkTarget : resolve11(dirname6(entryPath), linkTarget) : null;
27080
27328
  if (resolved && resolved.includes("/.switchroom/skills/_bundled/")) {
27081
27329
  continue;
27082
27330
  }
@@ -27087,13 +27335,13 @@ function syncGlobalSkills(agentDir, declared, skillsDirOverride) {
27087
27335
  }
27088
27336
  function installSwitchroomSkills(agentDir, opts = {}) {
27089
27337
  const builtinSkillsDir = resolve11(homedir5(), ".switchroom/skills/_bundled");
27090
- if (!existsSync17(builtinSkillsDir)) {
27338
+ if (!existsSync18(builtinSkillsDir)) {
27091
27339
  process.stderr.write(`switchroom: bundled skills pool dir not found at ${builtinSkillsDir} \u2014 run \`switchroom update\` to install it.
27092
27340
  `);
27093
27341
  return;
27094
27342
  }
27095
27343
  const targetDir = join12(agentDir, ".claude", "skills");
27096
- mkdirSync10(targetDir, { recursive: true });
27344
+ mkdirSync11(targetDir, { recursive: true });
27097
27345
  let entries;
27098
27346
  try {
27099
27347
  entries = readdirSync7(builtinSkillsDir);
@@ -27113,7 +27361,7 @@ function installSwitchroomSkills(agentDir, opts = {}) {
27113
27361
  const src = join12(builtinSkillsDir, name);
27114
27362
  try {
27115
27363
  const st = lstatSync4(src);
27116
- return st.isDirectory() && existsSync17(join12(src, "SKILL.md"));
27364
+ return st.isDirectory() && existsSync18(join12(src, "SKILL.md"));
27117
27365
  } catch {
27118
27366
  return false;
27119
27367
  }
@@ -27135,7 +27383,7 @@ function installSwitchroomSkills(agentDir, opts = {}) {
27135
27383
  } catch {}
27136
27384
  if (!currentTarget)
27137
27385
  continue;
27138
- const resolvedTarget = isAbsolute2(currentTarget) ? currentTarget : resolve11(dirname5(dest), currentTarget);
27386
+ const resolvedTarget = isAbsolute2(currentTarget) ? currentTarget : resolve11(dirname6(dest), currentTarget);
27139
27387
  if (resolvedTarget !== join12(builtinSkillsDir, name))
27140
27388
  continue;
27141
27389
  try {
@@ -27147,7 +27395,7 @@ function installSwitchroomSkills(agentDir, opts = {}) {
27147
27395
  for (const name of switchroomSkillNames) {
27148
27396
  const src = join12(builtinSkillsDir, name);
27149
27397
  const dest = join12(targetDir, name);
27150
- const relTarget = relative2(dirname5(dest), src);
27398
+ const relTarget = relative2(dirname6(dest), src);
27151
27399
  let existing;
27152
27400
  try {
27153
27401
  existing = lstatSync4(dest);
@@ -27289,9 +27537,9 @@ function filterMcpServers(servers) {
27289
27537
  return Object.keys(out).length > 0 ? out : undefined;
27290
27538
  }
27291
27539
  function copyDirRecursive2(src, dest) {
27292
- if (!existsSync17(src))
27540
+ if (!existsSync18(src))
27293
27541
  return;
27294
- mkdirSync10(dest, { recursive: true });
27542
+ mkdirSync11(dest, { recursive: true });
27295
27543
  for (const entry of readdirSync7(src)) {
27296
27544
  const srcPath = join12(src, entry);
27297
27545
  const destPath = join12(dest, entry);
@@ -27307,17 +27555,17 @@ function copyDirRecursive2(src, dest) {
27307
27555
  }
27308
27556
  }
27309
27557
  function writeFileSyncIfChanged(filePath, content, mode) {
27310
- if (existsSync17(filePath)) {
27558
+ if (existsSync18(filePath)) {
27311
27559
  try {
27312
- if (readFileSync14(filePath, "utf-8") === content)
27560
+ if (readFileSync15(filePath, "utf-8") === content)
27313
27561
  return false;
27314
27562
  } catch {}
27315
27563
  }
27316
- writeFileSync5(filePath, content, mode !== undefined ? { encoding: "utf-8", mode } : "utf-8");
27564
+ writeFileSync6(filePath, content, mode !== undefined ? { encoding: "utf-8", mode } : "utf-8");
27317
27565
  return true;
27318
27566
  }
27319
27567
  function dirContentEquals(src, dest, topLevelOverrides) {
27320
- if (!existsSync17(src) || !existsSync17(dest))
27568
+ if (!existsSync18(src) || !existsSync18(dest))
27321
27569
  return false;
27322
27570
  let srcEntries;
27323
27571
  let destEntries;
@@ -27355,9 +27603,9 @@ function dirContentEquals(src, dest, topLevelOverrides) {
27355
27603
  try {
27356
27604
  const expected = topLevelOverrides?.[entry];
27357
27605
  if (expected !== undefined) {
27358
- if (readFileSync14(d, "utf-8") !== expected)
27606
+ if (readFileSync15(d, "utf-8") !== expected)
27359
27607
  return false;
27360
- } else if (!readFileSync14(s).equals(readFileSync14(d))) {
27608
+ } else if (!readFileSync15(s).equals(readFileSync15(d))) {
27361
27609
  return false;
27362
27610
  }
27363
27611
  } catch {
@@ -27369,14 +27617,14 @@ function dirContentEquals(src, dest, topLevelOverrides) {
27369
27617
  }
27370
27618
  function seedWorkspaceBootstrapFiles(params) {
27371
27619
  const profileWorkspaceDir = join12(params.profilePath, "workspace");
27372
- if (!existsSync17(profileWorkspaceDir)) {
27620
+ if (!existsSync18(profileWorkspaceDir)) {
27373
27621
  return;
27374
27622
  }
27375
27623
  const agentWorkspaceDir = join12(params.agentDir, "workspace");
27376
- mkdirSync10(agentWorkspaceDir, { recursive: true });
27624
+ mkdirSync11(agentWorkspaceDir, { recursive: true });
27377
27625
  const walk = (relDir) => {
27378
27626
  const srcDir = join12(profileWorkspaceDir, relDir);
27379
- if (!existsSync17(srcDir))
27627
+ if (!existsSync18(srcDir))
27380
27628
  return;
27381
27629
  for (const entry of readdirSync7(srcDir)) {
27382
27630
  if (entry.startsWith(".") && entry !== ".gitkeep")
@@ -27385,7 +27633,7 @@ function seedWorkspaceBootstrapFiles(params) {
27385
27633
  const srcPath = join12(profileWorkspaceDir, relPath);
27386
27634
  const srcStat = statSync8(srcPath);
27387
27635
  if (srcStat.isDirectory()) {
27388
- mkdirSync10(join12(agentWorkspaceDir, relPath), { recursive: true });
27636
+ mkdirSync11(join12(agentWorkspaceDir, relPath), { recursive: true });
27389
27637
  walk(relPath);
27390
27638
  continue;
27391
27639
  }
@@ -27400,10 +27648,10 @@ function seedWorkspaceBootstrapFiles(params) {
27400
27648
  const destPath = join12(agentWorkspaceDir, destRel);
27401
27649
  if (destRel === "SOUL.default.md") {
27402
27650
  const rendered = renderTemplate(srcPath, params.context);
27403
- const existed = existsSync17(destPath);
27404
- const current = existed ? readFileSync14(destPath, "utf8") : null;
27651
+ const existed = existsSync18(destPath);
27652
+ const current = existed ? readFileSync15(destPath, "utf8") : null;
27405
27653
  if (current !== rendered) {
27406
- writeFileSync5(destPath, rendered);
27654
+ writeFileSync6(destPath, rendered);
27407
27655
  params.created.push(destPath);
27408
27656
  } else {
27409
27657
  params.skipped.push(destPath);
@@ -27419,7 +27667,7 @@ function seedWorkspaceBootstrapFiles(params) {
27419
27667
  writeIfMissing(destPath, renderFn, params.created, params.skipped);
27420
27668
  } else {
27421
27669
  const destPath = join12(agentWorkspaceDir, relPath);
27422
- if (!existsSync17(destPath)) {
27670
+ if (!existsSync18(destPath)) {
27423
27671
  copyFileSync4(srcPath, destPath);
27424
27672
  params.created.push(destPath);
27425
27673
  } else {
@@ -27433,27 +27681,27 @@ function seedWorkspaceBootstrapFiles(params) {
27433
27681
  function migrateLegacyAgentsMdIfPresent(agentWorkspaceDir, created) {
27434
27682
  const agentsMd = join12(agentWorkspaceDir, "AGENTS.md");
27435
27683
  const claudeMd = join12(agentWorkspaceDir, "CLAUDE.md");
27436
- if (!existsSync17(agentsMd))
27684
+ if (!existsSync18(agentsMd))
27437
27685
  return;
27438
27686
  const stat = lstatSync4(agentsMd);
27439
27687
  if (stat.isSymbolicLink())
27440
27688
  return;
27441
- if (existsSync17(claudeMd)) {
27689
+ if (existsSync18(claudeMd)) {
27442
27690
  return;
27443
27691
  }
27444
- const content = readFileSync14(agentsMd, "utf-8");
27445
- writeFileSync5(claudeMd, content, "utf-8");
27692
+ const content = readFileSync15(agentsMd, "utf-8");
27693
+ writeFileSync6(claudeMd, content, "utf-8");
27446
27694
  rmSync4(agentsMd);
27447
27695
  created.push(claudeMd);
27448
27696
  console.log(source_default.dim(` migrated legacy workspace/AGENTS.md \u2192 workspace/CLAUDE.md (content preserved)`));
27449
27697
  }
27450
27698
  function ensureClaudeMdSymlinks(agentWorkspaceDir, changes) {
27451
27699
  const claudeMd = join12(agentWorkspaceDir, "CLAUDE.md");
27452
- if (!existsSync17(claudeMd))
27700
+ if (!existsSync18(claudeMd))
27453
27701
  return;
27454
27702
  for (const name of ["AGENTS.md", "AGENT.md"]) {
27455
27703
  const linkPath = join12(agentWorkspaceDir, name);
27456
- if (existsSync17(linkPath) || lstatExists(linkPath)) {
27704
+ if (existsSync18(linkPath) || lstatExists(linkPath)) {
27457
27705
  const stat = lstatSync4(linkPath);
27458
27706
  if (stat.isSymbolicLink()) {
27459
27707
  const target = readlinkSync4(linkPath);
@@ -27484,7 +27732,7 @@ function initWorkspaceGitRepo(workspaceDir, agentName) {
27484
27732
  return false;
27485
27733
  }
27486
27734
  const gitDir = join12(workspaceDir, ".git");
27487
- if (existsSync17(gitDir)) {
27735
+ if (existsSync18(gitDir)) {
27488
27736
  return true;
27489
27737
  }
27490
27738
  const gitignore = `# Ephemeral runtime state
@@ -27496,7 +27744,7 @@ Thumbs.db
27496
27744
  *.swp
27497
27745
  *~
27498
27746
  `;
27499
- writeFileSync5(join12(workspaceDir, ".gitignore"), gitignore, "utf-8");
27747
+ writeFileSync6(join12(workspaceDir, ".gitignore"), gitignore, "utf-8");
27500
27748
  try {
27501
27749
  execSync("git init --quiet", { cwd: workspaceDir, stdio: "pipe" });
27502
27750
  execSync("git add -A", { cwd: workspaceDir, stdio: "pipe" });
@@ -27533,7 +27781,7 @@ function installHindsightPlugin(agentName, agentDir, switchroomConfig) {
27533
27781
  if (agentMemory?.auto_recall === false)
27534
27782
  return null;
27535
27783
  const sourcePath = resolveHindsightVendorPath();
27536
- if (!existsSync17(sourcePath)) {
27784
+ if (!existsSync18(sourcePath)) {
27537
27785
  process.stderr.write(`installHindsightPlugin: vendor source missing at ${sourcePath} ` + `\u2014 hindsight plugin NOT installed for ${agentName}. ` + `Likely a packaging regression: check the npm tarball's files array.
27538
27786
  `);
27539
27787
  return null;
@@ -27544,13 +27792,13 @@ function installHindsightPlugin(agentName, agentDir, switchroomConfig) {
27544
27792
  let expectedSettings = null;
27545
27793
  try {
27546
27794
  const vendorSettingsPath = join12(sourcePath, "settings.json");
27547
- if (existsSync17(vendorSettingsPath)) {
27548
- expectedSettings = renderHindsightSettingsOverrides(readFileSync14(vendorSettingsPath, "utf-8"), additionalBanks, retainConfig);
27795
+ if (existsSync18(vendorSettingsPath)) {
27796
+ expectedSettings = renderHindsightSettingsOverrides(readFileSync15(vendorSettingsPath, "utf-8"), additionalBanks, retainConfig);
27549
27797
  }
27550
27798
  } catch {}
27551
27799
  const upToDate = dirContentEquals(sourcePath, destPath, expectedSettings != null ? { "settings.json": expectedSettings } : undefined);
27552
27800
  if (!upToDate) {
27553
- if (existsSync17(destPath)) {
27801
+ if (existsSync18(destPath)) {
27554
27802
  rmSync4(destPath, { recursive: true, force: true });
27555
27803
  }
27556
27804
  copyDirRecursive2(sourcePath, destPath);
@@ -27571,11 +27819,11 @@ function resolveHindsightRetainConfig(switchroomConfig, agentName) {
27571
27819
  }
27572
27820
  function applyHindsightSettingsOverrides(pluginDestPath, additionalBanks, retainConfig) {
27573
27821
  const settingsPath = join12(pluginDestPath, "settings.json");
27574
- if (!existsSync17(settingsPath))
27822
+ if (!existsSync18(settingsPath))
27575
27823
  return;
27576
27824
  let raw;
27577
27825
  try {
27578
- raw = readFileSync14(settingsPath, "utf-8");
27826
+ raw = readFileSync15(settingsPath, "utf-8");
27579
27827
  } catch {
27580
27828
  return;
27581
27829
  }
@@ -27974,23 +28222,23 @@ function scaffoldAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchro
27974
28222
  join12(agentDir, "telegram")
27975
28223
  ];
27976
28224
  for (const dir of dirs) {
27977
- mkdirSync10(dir, { recursive: true });
28225
+ mkdirSync11(dir, { recursive: true });
27978
28226
  }
27979
28227
  writeIfChanged(join12(agentDir, "start.sh"), () => renderTemplate(join12(basePath, "start.sh.hbs"), context), created, skipped);
27980
- if (existsSync17(join12(agentDir, "start.sh"))) {
28228
+ if (existsSync18(join12(agentDir, "start.sh"))) {
27981
28229
  chmodSync2(join12(agentDir, "start.sh"), 448);
27982
28230
  }
27983
28231
  if (context.cronSessionEnabled) {
27984
28232
  writeIfChanged(join12(agentDir, "cron-session.sh"), () => renderTemplate(join12(basePath, "cron-session.sh.hbs"), context), created, skipped);
27985
- if (existsSync17(join12(agentDir, "cron-session.sh"))) {
28233
+ if (existsSync18(join12(agentDir, "cron-session.sh"))) {
27986
28234
  chmodSync2(join12(agentDir, "cron-session.sh"), 448);
27987
28235
  }
27988
28236
  }
27989
28237
  writeIfMissing(join12(agentDir, ".claude", "settings.json"), () => renderTemplate(join12(basePath, "settings.json.hbs"), context), created, skipped, 384);
27990
28238
  if (switchroomConfig) {
27991
28239
  const settingsPath = join12(agentDir, ".claude", "settings.json");
27992
- if (existsSync17(settingsPath)) {
27993
- const settings = JSON.parse(readFileSync14(settingsPath, "utf-8"));
28240
+ if (existsSync18(settingsPath)) {
28241
+ const settings = JSON.parse(readFileSync15(settingsPath, "utf-8"));
27994
28242
  if (!settings.mcpServers) {
27995
28243
  settings.mcpServers = {};
27996
28244
  }
@@ -28133,7 +28381,7 @@ function scaffoldAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchro
28133
28381
  ];
28134
28382
  for (const { src, dest } of templateFiles) {
28135
28383
  const srcPath = join12(profilePath, src);
28136
- if (existsSync17(srcPath)) {
28384
+ if (existsSync18(srcPath)) {
28137
28385
  const renderManaged = () => {
28138
28386
  let rendered = renderTemplate(srcPath, context);
28139
28387
  if (dest === "CLAUDE.md") {
@@ -28190,7 +28438,7 @@ function scaffoldAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchro
28190
28438
  }
28191
28439
  }
28192
28440
  const phase5WorkspaceDir = join12(agentDir, "workspace");
28193
- mkdirSync10(phase5WorkspaceDir, { recursive: true });
28441
+ mkdirSync11(phase5WorkspaceDir, { recursive: true });
28194
28442
  migrateLegacyAgentsMdIfPresent(phase5WorkspaceDir, created);
28195
28443
  seedWorkspaceBootstrapFiles({
28196
28444
  profilePath,
@@ -28203,9 +28451,9 @@ function scaffoldAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchro
28203
28451
  });
28204
28452
  ensureClaudeMdSymlinks(phase5WorkspaceDir, created);
28205
28453
  const persistentHomeDir = join12(agentDir, "home");
28206
- mkdirSync10(persistentHomeDir, { recursive: true });
28454
+ mkdirSync11(persistentHomeDir, { recursive: true });
28207
28455
  for (const sub of [".local/bin", ".npm-global", "bin"]) {
28208
- mkdirSync10(join12(persistentHomeDir, sub), { recursive: true });
28456
+ mkdirSync11(join12(persistentHomeDir, sub), { recursive: true });
28209
28457
  }
28210
28458
  if (!isContainerContext() && process.env.HOME) {
28211
28459
  const dotSwitchroomLink = join12(persistentHomeDir, ".switchroom");
@@ -28247,7 +28495,7 @@ function scaffoldAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchro
28247
28495
  const existingClaudeJson = findExistingClaudeJson();
28248
28496
  if (existingClaudeJson) {
28249
28497
  copyOnboardingState(existingClaudeJson, agentDir);
28250
- if (!existsSync17(join12(agentDir, ".claude", "config.json"))) {
28498
+ if (!existsSync18(join12(agentDir, ".claude", "config.json"))) {
28251
28499
  writeIfMissing(join12(agentDir, ".claude", "config.json"), () => JSON.stringify({ hasCompletedOnboarding: true, numStartups: 1 }, null, 2) + `
28252
28500
  `, created, skipped, 384);
28253
28501
  }
@@ -28274,7 +28522,7 @@ This file is auto-maintained. Do not edit manually.
28274
28522
  writeFileSyncIfChanged(join12(agentDir, "telegram", "people.json"), buildPeopleJson(switchroomConfig), 384);
28275
28523
  if (agentConfig.subagents) {
28276
28524
  const agentsDir2 = join12(agentDir, ".claude", "agents");
28277
- mkdirSync10(agentsDir2, { recursive: true });
28525
+ mkdirSync11(agentsDir2, { recursive: true });
28278
28526
  for (const [saName, saDef] of Object.entries(agentConfig.subagents)) {
28279
28527
  const mdPath = join12(agentsDir2, `${saName}.md`);
28280
28528
  if (!saDef.description) {
@@ -28331,13 +28579,13 @@ ${body}
28331
28579
  }
28332
28580
  {
28333
28581
  const telegramDir = join12(agentDir, "telegram");
28334
- if (existsSync17(telegramDir)) {
28582
+ if (existsSync18(telegramDir)) {
28335
28583
  for (const file of readdirSync7(telegramDir)) {
28336
28584
  const isCronScript = CRON_SCRIPT_BASENAME_RE.test(file) || LEGACY_CRON_SCRIPT_BASENAME_RE.test(file);
28337
28585
  if (isCronScript) {
28338
28586
  unlinkSync4(join12(telegramDir, file));
28339
28587
  const sidecar = join12(telegramDir, file.replace(/\.sh$/, ".source"));
28340
- if (existsSync17(sidecar))
28588
+ if (existsSync18(sidecar))
28341
28589
  unlinkSync4(sidecar);
28342
28590
  }
28343
28591
  }
@@ -28353,8 +28601,8 @@ ${body}
28353
28601
  setupPlugins(agentDir, usesSwitchroomTelegramPlugin(agentConfig));
28354
28602
  const agentSoulPath = join12(agentDir, "SOUL.md");
28355
28603
  const workspaceSoulPath = join12(agentDir, "workspace", "SOUL.md");
28356
- if (existsSync17(workspaceSoulPath)) {
28357
- if (existsSync17(agentSoulPath)) {
28604
+ if (existsSync18(workspaceSoulPath)) {
28605
+ if (existsSync18(agentSoulPath)) {
28358
28606
  const stat = lstatSync4(agentSoulPath);
28359
28607
  if (stat.isSymbolicLink()) {
28360
28608
  const target = readlinkSync4(agentSoulPath);
@@ -28829,13 +29077,13 @@ function reconcileAgentInner(name, agentConfigRaw, agentsDir, telegramConfig, sw
28829
29077
  }
28830
29078
  });
28831
29079
  }
28832
- if (!existsSync17(agentDir)) {
29080
+ if (!existsSync18(agentDir)) {
28833
29081
  throw new Error(`Agent directory does not exist: ${agentDir}. Run \`switchroom agent create ${name}\` first.`);
28834
29082
  }
28835
29083
  {
28836
29084
  const explicitResumeMode = agentConfig.session_continuity?.resume_mode;
28837
29085
  const markerPath = join12(agentDir, ".resume-mode-migration-warned");
28838
- if (!explicitResumeMode && !existsSync17(markerPath)) {
29086
+ if (!explicitResumeMode && !existsSync18(markerPath)) {
28839
29087
  console.warn(` ${source_default.yellow("\u26a0")} [${name}] resume_mode default changed from 'auto' to 'handoff' (switchroom #362).`);
28840
29088
  console.warn(` Your agent will now start a fresh Claude session on every restart, using a`);
28841
29089
  console.warn(` context briefing instead of --continue. This prevents stale MCP servers`);
@@ -28845,7 +29093,7 @@ function reconcileAgentInner(name, agentConfigRaw, agentsDir, telegramConfig, sw
28845
29093
  console.warn(` resume_mode: auto`);
28846
29094
  console.warn(` (This warning fires once per agent directory and is then suppressed.)`);
28847
29095
  try {
28848
- writeFileSync5(markerPath, `resume_mode default changed to handoff at reconcile
29096
+ writeFileSync6(markerPath, `resume_mode default changed to handoff at reconcile
28849
29097
  `, "utf-8");
28850
29098
  } catch {}
28851
29099
  }
@@ -28853,10 +29101,10 @@ function reconcileAgentInner(name, agentConfigRaw, agentsDir, telegramConfig, sw
28853
29101
  const legacyCustomPath = join12(agentDir, "CLAUDE.custom.md");
28854
29102
  const workspaceDir = join12(agentDir, "workspace");
28855
29103
  const newCustomPath = join12(workspaceDir, "CLAUDE.custom.md");
28856
- if (existsSync17(legacyCustomPath) && !existsSync17(newCustomPath)) {
28857
- mkdirSync10(workspaceDir, { recursive: true });
28858
- const legacyContent = readFileSync14(legacyCustomPath, "utf-8");
28859
- writeFileSync5(newCustomPath, legacyContent, "utf-8");
29104
+ if (existsSync18(legacyCustomPath) && !existsSync18(newCustomPath)) {
29105
+ mkdirSync11(workspaceDir, { recursive: true });
29106
+ const legacyContent = readFileSync15(legacyCustomPath, "utf-8");
29107
+ writeFileSync6(newCustomPath, legacyContent, "utf-8");
28860
29108
  rmSync4(legacyCustomPath);
28861
29109
  console.log(source_default.green(` moved CLAUDE.custom.md \u2192 workspace/CLAUDE.custom.md`));
28862
29110
  }
@@ -28989,19 +29237,19 @@ ${baseAppend}` : TELEGRAM_FORMATTING_FLOOR_CARD;
28989
29237
  resumeMaxBytes: agentConfig.session_continuity?.resume_max_bytes ?? 2000000,
28990
29238
  bootResumeMode: agentConfig.session_continuity?.boot_resume ?? "in-flight"
28991
29239
  };
28992
- const beforeStartSh = existsSync17(startShPath) ? readFileSync14(startShPath, "utf-8") : "";
29240
+ const beforeStartSh = existsSync18(startShPath) ? readFileSync15(startShPath, "utf-8") : "";
28993
29241
  const afterStartSh = renderTemplate(join12(basePath, "start.sh.hbs"), startShContext);
28994
29242
  if (afterStartSh !== beforeStartSh) {
28995
- writeFileSync5(startShPath, afterStartSh, "utf-8");
29243
+ writeFileSync6(startShPath, afterStartSh, "utf-8");
28996
29244
  chmodSync2(startShPath, 493);
28997
29245
  changes.push(startShPath);
28998
29246
  }
28999
29247
  if (startShContext.cronSessionEnabled) {
29000
29248
  const cronShPath = join12(agentDir, "cron-session.sh");
29001
- const beforeCronSh = existsSync17(cronShPath) ? readFileSync14(cronShPath, "utf-8") : "";
29249
+ const beforeCronSh = existsSync18(cronShPath) ? readFileSync15(cronShPath, "utf-8") : "";
29002
29250
  const afterCronSh = renderTemplate(join12(basePath, "cron-session.sh.hbs"), startShContext);
29003
29251
  if (afterCronSh !== beforeCronSh) {
29004
- writeFileSync5(cronShPath, afterCronSh, "utf-8");
29252
+ writeFileSync6(cronShPath, afterCronSh, "utf-8");
29005
29253
  chmodSync2(cronShPath, 493);
29006
29254
  changes.push(cronShPath);
29007
29255
  }
@@ -29012,7 +29260,7 @@ ${baseAppend}` : TELEGRAM_FORMATTING_FLOOR_CARD;
29012
29260
  const claudeMdSrc = join12(profilePath, "CLAUDE.md.hbs");
29013
29261
  const claudeMdDest = join12(agentDir, "CLAUDE.md");
29014
29262
  const claudeCustomPath = join12(agentDir, "workspace", "CLAUDE.custom.md");
29015
- if (existsSync17(claudeMdSrc)) {
29263
+ if (existsSync18(claudeMdSrc)) {
29016
29264
  const claudeContext = {
29017
29265
  name,
29018
29266
  agentDir,
@@ -29071,17 +29319,17 @@ ${baseAppend}` : TELEGRAM_FORMATTING_FLOOR_CARD;
29071
29319
  ` + agentConfig.claude_md_raw + `
29072
29320
  `;
29073
29321
  }
29074
- const before = existsSync17(claudeMdDest) ? readFileSync14(claudeMdDest, "utf-8") : "";
29322
+ const before = existsSync18(claudeMdDest) ? readFileSync15(claudeMdDest, "utf-8") : "";
29075
29323
  const composed = composeTwoSectionClaudeMd(rendered, before.length > 0 ? before : null, claudeCustomPath);
29076
29324
  if (composed !== before) {
29077
- writeFileSync5(claudeMdDest, composed, "utf-8");
29325
+ writeFileSync6(claudeMdDest, composed, "utf-8");
29078
29326
  changes.push(claudeMdDest);
29079
29327
  }
29080
29328
  }
29081
29329
  }
29082
29330
  const settingsPath = join12(agentDir, ".claude", "settings.json");
29083
- if (existsSync17(settingsPath)) {
29084
- const before = readFileSync14(settingsPath, "utf-8");
29331
+ if (existsSync18(settingsPath)) {
29332
+ const before = readFileSync15(settingsPath, "utf-8");
29085
29333
  const settings = JSON.parse(before);
29086
29334
  settings.permissions = settings.permissions ?? {};
29087
29335
  settings.permissions.allow = desiredAllow;
@@ -29143,15 +29391,15 @@ ${baseAppend}` : TELEGRAM_FORMATTING_FLOOR_CARD;
29143
29391
  });
29144
29392
  let greetingUserId;
29145
29393
  const accessPath = join12(agentDir, "telegram", "access.json");
29146
- if (existsSync17(accessPath)) {
29394
+ if (existsSync18(accessPath)) {
29147
29395
  try {
29148
- const access = JSON.parse(readFileSync14(accessPath, "utf-8"));
29396
+ const access = JSON.parse(readFileSync15(accessPath, "utf-8"));
29149
29397
  greetingUserId = access.allowFrom?.[0];
29150
29398
  } catch {}
29151
29399
  }
29152
29400
  if (agentConfig.subagents) {
29153
29401
  const saDir = join12(agentDir, ".claude", "agents");
29154
- mkdirSync10(saDir, { recursive: true });
29402
+ mkdirSync11(saDir, { recursive: true });
29155
29403
  for (const [saName, saDef] of Object.entries(agentConfig.subagents)) {
29156
29404
  const mdPath = join12(saDir, `${saName}.md`);
29157
29405
  if (!saDef.description) {
@@ -29203,9 +29451,9 @@ ${fmLines}
29203
29451
 
29204
29452
  ${body}
29205
29453
  `;
29206
- const before2 = existsSync17(mdPath) ? readFileSync14(mdPath, "utf-8") : "";
29454
+ const before2 = existsSync18(mdPath) ? readFileSync15(mdPath, "utf-8") : "";
29207
29455
  if (content !== before2) {
29208
- writeFileSync5(mdPath, content, "utf-8");
29456
+ writeFileSync6(mdPath, content, "utf-8");
29209
29457
  changes.push(mdPath);
29210
29458
  }
29211
29459
  }
@@ -29223,7 +29471,7 @@ ${body}
29223
29471
  }
29224
29472
  }
29225
29473
  const telegramDir = join12(agentDir, "telegram");
29226
- if (existsSync17(telegramDir)) {
29474
+ if (existsSync18(telegramDir)) {
29227
29475
  const files = readdirSync7(telegramDir);
29228
29476
  for (const file of files) {
29229
29477
  const isCronScript = CRON_SCRIPT_BASENAME_RE.test(file) || LEGACY_CRON_SCRIPT_BASENAME_RE.test(file);
@@ -29232,7 +29480,7 @@ ${body}
29232
29480
  unlinkSync4(staleScript);
29233
29481
  changes.push(staleScript);
29234
29482
  const sourceSidecar = staleScript.replace(/\.sh$/, ".source");
29235
- if (existsSync17(sourceSidecar)) {
29483
+ if (existsSync18(sourceSidecar)) {
29236
29484
  unlinkSync4(sourceSidecar);
29237
29485
  changes.push(sourceSidecar);
29238
29486
  }
@@ -29310,7 +29558,7 @@ ${body}
29310
29558
  const mcpJson = { mcpServers };
29311
29559
  const after = JSON.stringify(mcpJson, null, 2) + `
29312
29560
  `;
29313
- const before = existsSync17(mcpJsonPath) ? readFileSync14(mcpJsonPath, "utf-8") : "";
29561
+ const before = existsSync18(mcpJsonPath) ? readFileSync15(mcpJsonPath, "utf-8") : "";
29314
29562
  if (after !== before) {
29315
29563
  atomicWriteFileSync(mcpJsonPath, after, 384);
29316
29564
  changes.push(mcpJsonPath);
@@ -29349,7 +29597,7 @@ ${body}
29349
29597
  hindsightSenderBanksJson,
29350
29598
  hindsightTopicFilterMode
29351
29599
  });
29352
- mkdirSync10(reconcileWorkspaceDir, { recursive: true });
29600
+ mkdirSync11(reconcileWorkspaceDir, { recursive: true });
29353
29601
  migrateLegacyAgentsMdIfPresent(reconcileWorkspaceDir, changes);
29354
29602
  seedWorkspaceBootstrapFiles({
29355
29603
  profilePath: reconcileProfilePath,
@@ -29362,13 +29610,13 @@ ${body}
29362
29610
  });
29363
29611
  ensureClaudeMdSymlinks(reconcileWorkspaceDir, changes);
29364
29612
  }
29365
- if (existsSync17(reconcileWorkspaceDir)) {
29613
+ if (existsSync18(reconcileWorkspaceDir)) {
29366
29614
  initWorkspaceGitRepo(reconcileWorkspaceDir, name);
29367
29615
  }
29368
29616
  const agentSoulPath = join12(agentDir, "SOUL.md");
29369
29617
  const workspaceSoulPath = join12(agentDir, "workspace", "SOUL.md");
29370
- if (existsSync17(workspaceSoulPath)) {
29371
- if (existsSync17(agentSoulPath)) {
29618
+ if (existsSync18(workspaceSoulPath)) {
29619
+ if (existsSync18(agentSoulPath)) {
29372
29620
  const stat = lstatSync4(agentSoulPath);
29373
29621
  if (stat.isSymbolicLink()) {
29374
29622
  const target = readlinkSync4(agentSoulPath);
@@ -29479,7 +29727,7 @@ ${body}
29479
29727
  };
29480
29728
  }
29481
29729
  function writeIfMissing(filePath, contentFn, created, skipped, mode) {
29482
- if (existsSync17(filePath)) {
29730
+ if (existsSync18(filePath)) {
29483
29731
  skipped.push(filePath);
29484
29732
  return;
29485
29733
  }
@@ -29488,12 +29736,12 @@ function writeIfMissing(filePath, contentFn, created, skipped, mode) {
29488
29736
  }
29489
29737
  function writeIfChanged(filePath, contentFn, created, skipped, mode) {
29490
29738
  const next = contentFn();
29491
- const prev = existsSync17(filePath) ? readFileSync14(filePath, "utf-8") : null;
29739
+ const prev = existsSync18(filePath) ? readFileSync15(filePath, "utf-8") : null;
29492
29740
  if (prev === next) {
29493
29741
  skipped.push(filePath);
29494
29742
  return;
29495
29743
  }
29496
- writeFileSync5(filePath, next, mode !== undefined ? { encoding: "utf-8", mode } : "utf-8");
29744
+ writeFileSync6(filePath, next, mode !== undefined ? { encoding: "utf-8", mode } : "utf-8");
29497
29745
  created.push(filePath);
29498
29746
  }
29499
29747
  function claudeMdManagedSection(content) {
@@ -29503,42 +29751,42 @@ function claudeMdManagedSection(content) {
29503
29751
  return content.slice(0, idx + CLAUDE_MD_YOURS_MARKER.length);
29504
29752
  }
29505
29753
  function writeTwoSectionClaudeMdWithFingerprint(filePath, managedFn, sidecarPath, created, skipped, rewrittenWithBackup) {
29506
- const prev = existsSync17(filePath) ? readFileSync14(filePath, "utf-8") : null;
29754
+ const prev = existsSync18(filePath) ? readFileSync15(filePath, "utf-8") : null;
29507
29755
  const next = composeTwoSectionClaudeMd(managedFn(), prev, sidecarPath);
29508
29756
  const nextManagedHash = createHash4("sha256").update(claudeMdManagedSection(next), "utf-8").digest("hex");
29509
29757
  const fingerprintPath = filePath + ".fingerprint";
29510
29758
  if (prev === null) {
29511
- writeFileSync5(filePath, next, "utf-8");
29512
- writeFileSync5(fingerprintPath, nextManagedHash, "utf-8");
29759
+ writeFileSync6(filePath, next, "utf-8");
29760
+ writeFileSync6(fingerprintPath, nextManagedHash, "utf-8");
29513
29761
  created.push(filePath);
29514
29762
  return;
29515
29763
  }
29516
29764
  if (prev === next) {
29517
29765
  try {
29518
- writeFileSync5(fingerprintPath, nextManagedHash, "utf-8");
29766
+ writeFileSync6(fingerprintPath, nextManagedHash, "utf-8");
29519
29767
  } catch {}
29520
29768
  skipped.push(filePath);
29521
29769
  return;
29522
29770
  }
29523
29771
  const prevManagedHash = createHash4("sha256").update(claudeMdManagedSection(prev), "utf-8").digest("hex");
29524
- const recordedFingerprint = existsSync17(fingerprintPath) ? readFileSync14(fingerprintPath, "utf-8").trim() : null;
29772
+ const recordedFingerprint = existsSync18(fingerprintPath) ? readFileSync15(fingerprintPath, "utf-8").trim() : null;
29525
29773
  if (recordedFingerprint === prevManagedHash) {
29526
- writeFileSync5(filePath, next, "utf-8");
29527
- writeFileSync5(fingerprintPath, nextManagedHash, "utf-8");
29774
+ writeFileSync6(filePath, next, "utf-8");
29775
+ writeFileSync6(fingerprintPath, nextManagedHash, "utf-8");
29528
29776
  created.push(filePath);
29529
29777
  return;
29530
29778
  }
29531
29779
  const backupPath = `${filePath}.before-rerender.${Date.now()}`;
29532
29780
  try {
29533
- writeFileSync5(backupPath, prev, "utf-8");
29781
+ writeFileSync6(backupPath, prev, "utf-8");
29534
29782
  } catch (err) {
29535
29783
  process.stderr.write(`scaffold: refusing to overwrite ${filePath} \u2014 backup write failed ` + `(${err.message}). Operator edits preserved.
29536
29784
  `);
29537
29785
  skipped.push(filePath);
29538
29786
  return;
29539
29787
  }
29540
- writeFileSync5(filePath, next, "utf-8");
29541
- writeFileSync5(fingerprintPath, nextManagedHash, "utf-8");
29788
+ writeFileSync6(filePath, next, "utf-8");
29789
+ writeFileSync6(fingerprintPath, nextManagedHash, "utf-8");
29542
29790
  rewrittenWithBackup.push(filePath);
29543
29791
  created.push(filePath);
29544
29792
  }
@@ -29547,39 +29795,39 @@ function rerenderWithFingerprint(filePath, contentFn, created, skipped, rewritte
29547
29795
  const nextHash = createHash4("sha256").update(next, "utf-8").digest("hex");
29548
29796
  const fingerprintPath = filePath + ".fingerprint";
29549
29797
  const writeMode = mode !== undefined ? { encoding: "utf-8", mode } : "utf-8";
29550
- if (!existsSync17(filePath)) {
29551
- writeFileSync5(filePath, next, writeMode);
29552
- writeFileSync5(fingerprintPath, nextHash, "utf-8");
29798
+ if (!existsSync18(filePath)) {
29799
+ writeFileSync6(filePath, next, writeMode);
29800
+ writeFileSync6(fingerprintPath, nextHash, "utf-8");
29553
29801
  created.push(filePath);
29554
29802
  return;
29555
29803
  }
29556
- const prev = readFileSync14(filePath, "utf-8");
29804
+ const prev = readFileSync15(filePath, "utf-8");
29557
29805
  if (prev === next) {
29558
29806
  try {
29559
- writeFileSync5(fingerprintPath, nextHash, "utf-8");
29807
+ writeFileSync6(fingerprintPath, nextHash, "utf-8");
29560
29808
  } catch {}
29561
29809
  skipped.push(filePath);
29562
29810
  return;
29563
29811
  }
29564
29812
  const prevHash = createHash4("sha256").update(prev, "utf-8").digest("hex");
29565
- const recordedFingerprint = existsSync17(fingerprintPath) ? readFileSync14(fingerprintPath, "utf-8").trim() : null;
29813
+ const recordedFingerprint = existsSync18(fingerprintPath) ? readFileSync15(fingerprintPath, "utf-8").trim() : null;
29566
29814
  if (recordedFingerprint === prevHash) {
29567
- writeFileSync5(filePath, next, writeMode);
29568
- writeFileSync5(fingerprintPath, nextHash, "utf-8");
29815
+ writeFileSync6(filePath, next, writeMode);
29816
+ writeFileSync6(fingerprintPath, nextHash, "utf-8");
29569
29817
  created.push(filePath);
29570
29818
  return;
29571
29819
  }
29572
29820
  const backupPath = `${filePath}.before-rerender.${Date.now()}`;
29573
29821
  try {
29574
- writeFileSync5(backupPath, prev, "utf-8");
29822
+ writeFileSync6(backupPath, prev, "utf-8");
29575
29823
  } catch (err) {
29576
29824
  process.stderr.write(`scaffold: refusing to overwrite ${filePath} \u2014 backup write failed ` + `(${err.message}). Operator edits preserved.
29577
29825
  `);
29578
29826
  skipped.push(filePath);
29579
29827
  return;
29580
29828
  }
29581
- writeFileSync5(filePath, next, writeMode);
29582
- writeFileSync5(fingerprintPath, nextHash, "utf-8");
29829
+ writeFileSync6(filePath, next, writeMode);
29830
+ writeFileSync6(fingerprintPath, nextHash, "utf-8");
29583
29831
  rewrittenWithBackup.push(filePath);
29584
29832
  created.push(filePath);
29585
29833
  }
@@ -29590,7 +29838,7 @@ function resolveAgentForumChatId(agentConfig, telegramConfig) {
29590
29838
  return telegramConfig.forum_chat_id ?? "";
29591
29839
  }
29592
29840
  function reconcileConfiguredGroup(accessPath, agentConfig, telegramConfig) {
29593
- if (!existsSync17(accessPath))
29841
+ if (!existsSync18(accessPath))
29594
29842
  return;
29595
29843
  const forumChatId = resolveAgentForumChatId(agentConfig, telegramConfig);
29596
29844
  const hasRealForumChat = forumChatId !== "" && forumChatId !== "0";
@@ -29598,7 +29846,7 @@ function reconcileConfiguredGroup(accessPath, agentConfig, telegramConfig) {
29598
29846
  return;
29599
29847
  let access;
29600
29848
  try {
29601
- access = JSON.parse(readFileSync14(accessPath, "utf-8"));
29849
+ access = JSON.parse(readFileSync15(accessPath, "utf-8"));
29602
29850
  } catch {
29603
29851
  return;
29604
29852
  }
@@ -29608,7 +29856,7 @@ function reconcileConfiguredGroup(accessPath, agentConfig, telegramConfig) {
29608
29856
  const allowFrom = Array.isArray(access.allowFrom) ? access.allowFrom : [];
29609
29857
  groups[forumChatId] = { requireMention: false, allowFrom };
29610
29858
  const tmp = accessPath + ".tmp";
29611
- writeFileSync5(tmp, JSON.stringify(access, null, 2) + `
29859
+ writeFileSync6(tmp, JSON.stringify(access, null, 2) + `
29612
29860
  `, { mode: 384 });
29613
29861
  renameSync4(tmp, accessPath);
29614
29862
  console.log(source_default.green(` registered supergroup ${forumChatId} in access.json ` + `(responds to all topics; requireMention=false)`));
@@ -30200,50 +30448,6 @@ var init_scaffold = __esm(() => {
30200
30448
  ];
30201
30449
  });
30202
30450
 
30203
- // src/setup/host-capabilities.ts
30204
- import { existsSync as existsSync18, mkdirSync as mkdirSync11, readFileSync as readFileSync15, writeFileSync as writeFileSync6 } from "node:fs";
30205
- import { dirname as dirname6 } from "node:path";
30206
- function hostCapabilitiesPath() {
30207
- return resolveStatePath("host-capabilities.json");
30208
- }
30209
- function saveVoiceCapability(caps, now = () => new Date) {
30210
- const doc = {
30211
- version: HOST_CAPABILITIES_VERSION,
30212
- voice: {
30213
- gpuPresent: caps.gpuPresent,
30214
- containerToolkit: caps.containerToolkit,
30215
- engine: caps.engine,
30216
- detectedAt: now().toISOString()
30217
- }
30218
- };
30219
- const path = hostCapabilitiesPath();
30220
- mkdirSync11(dirname6(path), { recursive: true });
30221
- writeFileSync6(path, JSON.stringify(doc, null, 2) + `
30222
- `, {
30223
- encoding: "utf-8",
30224
- mode: 384
30225
- });
30226
- return doc;
30227
- }
30228
- function loadHostCapabilities() {
30229
- const path = hostCapabilitiesPath();
30230
- if (!existsSync18(path))
30231
- return null;
30232
- try {
30233
- const parsed = JSON.parse(readFileSync15(path, "utf-8"));
30234
- if (parsed && typeof parsed === "object" && "voice" in parsed && typeof parsed.voice === "object") {
30235
- return parsed;
30236
- }
30237
- return null;
30238
- } catch {
30239
- return null;
30240
- }
30241
- }
30242
- var HOST_CAPABILITIES_VERSION = 1;
30243
- var init_host_capabilities = __esm(() => {
30244
- init_paths();
30245
- });
30246
-
30247
30451
  // src/vault/grants-db-path.ts
30248
30452
  var exports_grants_db_path = {};
30249
30453
  __export(exports_grants_db_path, {
@@ -51186,7 +51390,7 @@ function probePendingRetainsQueue(agentName) {
51186
51390
  function buildPendingRetainsProbeScript(base, now = Date.now()) {
51187
51391
  const dir = `${base}/pending-retains`;
51188
51392
  const cutoff = new Date(now - PENDING_RETAINS_EVICTION_WINDOW_DAYS * 86400000).toISOString().replace(/\.\d+Z$/, "Z");
51189
- return `P=0; D=0; X=0; E=0; C=\${HINDSIGHT_PENDING_MAX_ENTRIES:-${PENDING_RETAINS_DEFAULT_MAX_ENTRIES}}; ` + `if [ -d '${dir}' ]; then ` + `P=$(ls -1 '${dir}' 2>/dev/null | grep -c '\\.json$' || true); ` + `D=$(ls -1 '${dir}' 2>/dev/null | grep -c '\\.json\\.dead$' || true); ` + `fi; ` + `for L in '${base}/pending-drops.json' '${dir}/.drops.json'; do ` + `if [ "$X" = 0 ] && [ -f "$L" ]; then ` + `X=$(grep -o '"count"[^0-9]*[0-9][0-9]*' "$L" 2>/dev/null ` + `| grep -o '[0-9][0-9]*$' | head -n1); ` + `[ -n "$X" ] || X=0; ` + `fi; done; ` + `if [ -f '${base}/pending-evictions.log' ]; then ` + `E=$(awk -v c='${cutoff}' '$1 >= c && /evicted=/ {n++} END {print n+0}' ` + `'${base}/pending-evictions.log' 2>/dev/null || echo 0); ` + `[ -n "$E" ] || E=0; ` + `fi; ` + `echo "P=$P D=$D X=$X E=$E C=$C"`;
51393
+ return `P=0; D=0; X=0; E=0; C=\${HINDSIGHT_PENDING_MAX_ENTRIES:-${PENDING_RETAINS_DEFAULT_MAX_ENTRIES}}; ` + `if [ -d '${dir}' ]; then ` + `P=$(ls -1 '${dir}' 2>/dev/null | grep -c '\\.json$' || true); ` + `D=$(ls -1 '${dir}' 2>/dev/null | grep -c '\\.json\\.dead$' || true); ` + `fi; ` + `if [ -d '${base}/pending-dead' ]; then ` + `D=$((D + $(ls -1 '${base}/pending-dead' 2>/dev/null | grep -c '\\.dead$' || true))); ` + `fi; ` + `for L in '${base}/pending-drops.json' '${dir}/.drops.json'; do ` + `if [ "$X" = 0 ] && [ -f "$L" ]; then ` + `X=$(grep -o '"count"[^0-9]*[0-9][0-9]*' "$L" 2>/dev/null ` + `| grep -o '[0-9][0-9]*$' | head -n1); ` + `[ -n "$X" ] || X=0; ` + `fi; done; ` + `if [ -f '${base}/pending-evictions.log' ]; then ` + `E=$(awk -v c='${cutoff}' '$1 >= c && /evicted=/ {n++} END {print n+0}' ` + `'${base}/pending-evictions.log' 2>/dev/null || echo 0); ` + `[ -n "$E" ] || E=0; ` + `fi; ` + `echo "P=$P D=$D X=$X E=$E C=$C"`;
51190
51394
  }
51191
51395
  function parsePendingRetainsProbeOutput(r) {
51192
51396
  const unreachable = {
@@ -66572,11 +66776,24 @@ function parseTurns(text) {
66572
66776
  if (!line)
66573
66777
  continue;
66574
66778
  try {
66575
- out.push(JSON.parse(line));
66779
+ const parsed = JSON.parse(line);
66780
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
66781
+ continue;
66782
+ out.push(parsed);
66576
66783
  } catch {}
66577
66784
  }
66578
66785
  return out;
66579
66786
  }
66787
+ function ownedTurns(agent, turns) {
66788
+ const slug = agent.trim().toLowerCase();
66789
+ return turns.filter((t) => {
66790
+ const raw = t?.agent;
66791
+ if (typeof raw !== "string")
66792
+ return true;
66793
+ const owner = raw.trim().toLowerCase();
66794
+ return owner === "" || owner === slug;
66795
+ });
66796
+ }
66580
66797
  function isoFromTs(ts) {
66581
66798
  if (typeof ts !== "number" || !Number.isFinite(ts))
66582
66799
  return null;
@@ -66585,8 +66802,8 @@ function isoFromTs(ts) {
66585
66802
  function detectTurnFindings(agent, turns, opts = {}) {
66586
66803
  const findings = [];
66587
66804
  const silentNoopFloorTs = opts.silentNoopFloorTs ?? SILENT_NOOP_FLOOR_TS;
66588
- for (const t of turns) {
66589
- const tid = t.turn_id ?? "?";
66805
+ for (const t of ownedTurns(agent, turns)) {
66806
+ const tid = typeof t.turn_id === "string" ? t.turn_id : "?";
66590
66807
  const st = t.status;
66591
66808
  const tl = typeof t.tools === "number" ? t.tools : 0;
66592
66809
  const dur = typeof t.duration_ms === "number" ? t.duration_ms : 0;
@@ -66667,7 +66884,7 @@ function extractTs(line) {
66667
66884
  return m ? m[0] : null;
66668
66885
  }
66669
66886
  function scanAgent(agent, turnsText, gatewayText, opts = {}) {
66670
- const turns = parseTurns(turnsText);
66887
+ const turns = ownedTurns(agent, parseTurns(turnsText));
66671
66888
  const status_mix = {};
66672
66889
  for (const t of turns) {
66673
66890
  const st = t.status ?? "unknown";
@@ -66677,7 +66894,16 @@ function scanAgent(agent, turnsText, gatewayText, opts = {}) {
66677
66894
  const { findings: gwFindings, gw_hits } = detectGatewayFindings(agent, gatewayText);
66678
66895
  const findings = [...turnFindings, ...gwFindings];
66679
66896
  const escalate = turnFindings.some((f) => f.signal === "killed-incomplete-turn" || f.signal === "hang-long-stalled" || f.signal === "silent-no-op-candidate" || f.signal === "send-failed-delivery") || gw_hits["duplicate-delivery-represent"] > 0 || gw_hits["reply-delivery-failure"] > 0;
66680
- return { agent, turns: turns.length, status_mix, findings, gw_hits, escalate };
66897
+ const landed_unconfirmed_turns = turns.filter((t) => (t.landed_unconfirmed ?? 0) > 0).length;
66898
+ return {
66899
+ agent,
66900
+ turns: turns.length,
66901
+ status_mix,
66902
+ findings,
66903
+ gw_hits,
66904
+ landed_unconfirmed_turns,
66905
+ escalate
66906
+ };
66681
66907
  }
66682
66908
  var HANG_MS = 360000, HANG_MAXTOOLS = 2, SILENT_NOOP_FLOOR_TS = 1783900800, GATEWAY_SIGNATURES;
66683
66909
  var init_detect = __esm(() => {
@@ -81563,7 +81789,7 @@ Cross-agent reflection plan
81563
81789
  try {
81564
81790
  const hindsightConfig = getConfig(program3);
81565
81791
  const litellmCfg = await resolveLiteLLMForHindsight(hindsightConfig);
81566
- startHindsight(ports, litellmCfg, effectiveTag, hindsightConfig.hindsight?.llm, hindsightConsumerMirrorDir(hindsightConfig));
81792
+ startHindsight(ports, litellmCfg, effectiveTag, hindsightConfig.hindsight?.llm, hindsightConsumerMirrorDir(hindsightConfig), undefined, { env: hindsightConfig.hindsight?.env });
81567
81793
  if (litellmCfg) {
81568
81794
  console.log(source_default.gray(" LiteLLM routing enabled for hindsight (--network host)."));
81569
81795
  }
@@ -81594,7 +81820,7 @@ Cross-agent reflection plan
81594
81820
  `));
81595
81821
  {
81596
81822
  const snippetConfig = getConfig(program3);
81597
- console.log(generateHindsightComposeSnippet(snippetConfig.hindsight?.llm, hindsightConsumerMirrorDir(snippetConfig)));
81823
+ console.log(generateHindsightComposeSnippet(snippetConfig.hindsight?.llm, hindsightConsumerMirrorDir(snippetConfig), undefined, undefined, { env: snippetConfig.hindsight?.env }));
81598
81824
  }
81599
81825
  console.log();
81600
81826
  });
@@ -99752,7 +99978,7 @@ var RING_MAX = 8;
99752
99978
  var MAX_SAMPLE_AGE_MS = 3 * 60 * 60000;
99753
99979
  var MIN_RETAIN_SAMPLES = 20;
99754
99980
  var RETAIN_FAILURE_RATE = 0.1;
99755
- var PARTS_PER_MEMORY = 4.4;
99981
+ var PARTS_PER_MEMORY = 6;
99756
99982
  function inParts(memories) {
99757
99983
  return Math.round(memories * PARTS_PER_MEMORY);
99758
99984
  }
@@ -99878,6 +100104,12 @@ function probeSpool(agentsDir = resolve61(process.env.SWITCHROOM_HOME ?? process
99878
100104
  evicted++;
99879
100105
  }
99880
100106
  } catch {}
100107
+ try {
100108
+ for (const f of readdirSync43(resolve61(hindsightDir, "pending-dead"))) {
100109
+ if (f.endsWith(".dead"))
100110
+ dead++;
100111
+ }
100112
+ } catch {}
99881
100113
  drops += readDropCount(hindsightDir);
99882
100114
  }
99883
100115
  return { pending, dead, evicted, drops, agents };