@turmind/halo 2.2.4 → 2.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2121,7 +2121,7 @@ var init_init = __esm({
2121
2121
  path9.resolve(__dirname, "..", "bundled-docs"),
2122
2122
  path9.resolve(__dirname, "..", "..", "..", ".halo", "docs")
2123
2123
  ];
2124
- TEMPLATE_VERSION = 123;
2124
+ TEMPLATE_VERSION = 124;
2125
2125
  VERSION_FILE = ".template-version";
2126
2126
  SKIP_NAMES = /* @__PURE__ */ new Set([".DS_Store", "schema.sql", "__pycache__", ".pytest_cache"]);
2127
2127
  BUILTIN_AGENT_IDS = /* @__PURE__ */ new Set([
@@ -9350,27 +9350,27 @@ var init_workspace = __esm({
9350
9350
  constructor(projectRoot) {
9351
9351
  this.projectRoot = projectRoot;
9352
9352
  }
9353
- async readFile(path98) {
9354
- const fullPath = this.validatePath(path98);
9353
+ async readFile(path99) {
9354
+ const fullPath = this.validatePath(path99);
9355
9355
  return readFile(fullPath, "utf-8");
9356
9356
  }
9357
- async writeFile(path98, content) {
9358
- const fullPath = this.validatePath(path98);
9357
+ async writeFile(path99, content) {
9358
+ const fullPath = this.validatePath(path99);
9359
9359
  const dir = resolve2(fullPath, "..");
9360
9360
  await mkdir(dir, { recursive: true });
9361
9361
  await writeFile(fullPath, content, "utf-8");
9362
9362
  }
9363
- validatePath(path98) {
9364
- const fullPath = isAbsolute(path98) ? resolve2(path98) : resolve2(this.projectRoot, path98);
9363
+ validatePath(path99) {
9364
+ const fullPath = isAbsolute(path99) ? resolve2(path99) : resolve2(this.projectRoot, path99);
9365
9365
  const root = resolve2(this.projectRoot);
9366
9366
  if (fullPath !== root && !fullPath.startsWith(root + sep)) {
9367
- throw new WorkspaceError(`Path "${path98}" is outside the workspace directory "${this.projectRoot}"`);
9367
+ throw new WorkspaceError(`Path "${path99}" is outside the workspace directory "${this.projectRoot}"`);
9368
9368
  }
9369
9369
  try {
9370
9370
  const real = realpathSync2(fullPath);
9371
9371
  const realRoot = realpathSync2(root);
9372
9372
  if (real !== realRoot && !real.startsWith(realRoot + sep)) {
9373
- throw new WorkspaceError(`Path "${path98}" is outside the workspace directory "${this.projectRoot}"`);
9373
+ throw new WorkspaceError(`Path "${path99}" is outside the workspace directory "${this.projectRoot}"`);
9374
9374
  }
9375
9375
  } catch (err) {
9376
9376
  if (err instanceof WorkspaceError)
@@ -9557,12 +9557,12 @@ var init_git_manager = __esm({
9557
9557
  const code = parts[0];
9558
9558
  const status = code[0];
9559
9559
  const isRenameOrCopy = status === "R" || status === "C";
9560
- const path98 = isRenameOrCopy ? parts[2] : parts[1];
9561
- if (!path98 || seen.has(path98))
9560
+ const path99 = isRenameOrCopy ? parts[2] : parts[1];
9561
+ if (!path99 || seen.has(path99))
9562
9562
  continue;
9563
- seen.add(path98);
9563
+ seen.add(path99);
9564
9564
  files.push({
9565
- path: path98,
9565
+ path: path99,
9566
9566
  status,
9567
9567
  from: isRenameOrCopy ? parts[1] : void 0
9568
9568
  });
@@ -9710,9 +9710,9 @@ var init_git_manager = __esm({
9710
9710
  * empty for an added file or the root commit) and `modified` is the version
9711
9711
  * at `commit` (empty for a deletion). The working-tree/staged path above is
9712
9712
  * left entirely untouched (commit === undefined preserves existing behavior). */
9713
- async getFileDiff(path98, staged, from, commit) {
9713
+ async getFileDiff(path99, staged, from, commit) {
9714
9714
  if (commit) {
9715
- const parentPath = from || path98;
9715
+ const parentPath = from || path99;
9716
9716
  let original2 = "";
9717
9717
  try {
9718
9718
  original2 = await this.git.show([`${commit}^:${parentPath}`]);
@@ -9721,13 +9721,13 @@ var init_git_manager = __esm({
9721
9721
  }
9722
9722
  let modified2 = "";
9723
9723
  try {
9724
- modified2 = await this.git.show([`${commit}:${path98}`]);
9724
+ modified2 = await this.git.show([`${commit}:${path99}`]);
9725
9725
  } catch {
9726
9726
  modified2 = "";
9727
9727
  }
9728
9728
  return { original: original2, modified: modified2 };
9729
9729
  }
9730
- const headPath = from || path98;
9730
+ const headPath = from || path99;
9731
9731
  let original = "";
9732
9732
  try {
9733
9733
  original = await this.git.show([`HEAD:${headPath}`]);
@@ -9737,13 +9737,13 @@ var init_git_manager = __esm({
9737
9737
  let modified = "";
9738
9738
  if (staged) {
9739
9739
  try {
9740
- modified = await this.git.show([`:${path98}`]);
9740
+ modified = await this.git.show([`:${path99}`]);
9741
9741
  } catch {
9742
9742
  modified = "";
9743
9743
  }
9744
9744
  } else {
9745
9745
  try {
9746
- modified = await this.workspace.readFile(path98);
9746
+ modified = await this.workspace.readFile(path99);
9747
9747
  } catch {
9748
9748
  modified = "";
9749
9749
  }
@@ -15847,7 +15847,7 @@ function createNodeHub(deps) {
15847
15847
  since: c.since
15848
15848
  }));
15849
15849
  const announce = () => {
15850
- broadcast({ type: "nodes:changed", online: online().map(({ accountId, root, shell, os: os12, since }) => ({ accountId, root, shell, os: os12, since })) });
15850
+ broadcast({ type: "nodes:changed", online: online().map(({ accountId, root, shell, os: os13, since }) => ({ accountId, root, shell, os: os13, since })) });
15851
15851
  };
15852
15852
  const settle = (conn, id, fn) => {
15853
15853
  const p = conn.pending.get(id);
@@ -16830,7 +16830,7 @@ async function initObservability(haloProcess = "server") {
16830
16830
  return true;
16831
16831
  }
16832
16832
  const { registerSdk: registerSdk2 } = await Promise.resolve().then(() => (init_otel_sdk(), otel_sdk_exports));
16833
- providers = await registerSdk2(process.env.OTEL_SERVICE_NAME, "2.2.4", haloProcess);
16833
+ providers = await registerSdk2(process.env.OTEL_SERVICE_NAME, "2.2.5", haloProcess);
16834
16834
  console.log(`[Observability] OTLP export \u2192 ${process.env.OTEL_EXPORTER_OTLP_ENDPOINT} (service.name=${process.env.OTEL_SERVICE_NAME}, halo.process=${haloProcess}, capture_content=${config.observability.captureContent})`);
16835
16835
  return true;
16836
16836
  }
@@ -22018,8 +22018,8 @@ function applyPathPick(value, ref, pick) {
22018
22018
  const before = value.slice(0, markerStart);
22019
22019
  const kind = ref.kind === "scope" ? "scope" : ref.kind === "image" ? "image" : pick.isImage ? "image" : "file";
22020
22020
  const needsQuote = pick.insertPath.includes(" ");
22021
- const path98 = pick.isDir ? needsQuote ? `"${pick.insertPath}/` : `${pick.insertPath}/` : needsQuote ? `"${pick.insertPath}" ` : `${pick.insertPath} `;
22022
- return `${before}@${kind} ${path98}`;
22021
+ const path99 = pick.isDir ? needsQuote ? `"${pick.insertPath}/` : `${pick.insertPath}/` : needsQuote ? `"${pick.insertPath}" ` : `${pick.insertPath} `;
22022
+ return `${before}@${kind} ${path99}`;
22023
22023
  }
22024
22024
  var init_path_suggest_engine = __esm({
22025
22025
  "src/tui/path-suggest-engine.ts"() {
@@ -26855,8 +26855,8 @@ function detectOrphans(tree, declared, kept) {
26855
26855
  if (!block || typeof block !== "object")
26856
26856
  continue;
26857
26857
  for (const k of Object.keys(block)) {
26858
- const path98 = `${namespaceId}.${kindWord}.${k}`;
26859
- if (!declaredMap.has(path98)) {
26858
+ const path99 = `${namespaceId}.${kindWord}.${k}`;
26859
+ if (!declaredMap.has(path99)) {
26860
26860
  out.push({ namespaceId, kind: kindWord === "params" ? "param" : "secret", key: k });
26861
26861
  }
26862
26862
  }
@@ -28460,17 +28460,17 @@ function passwordStrengthError(pw) {
28460
28460
  }
28461
28461
  function authMiddleware() {
28462
28462
  return async (c, next) => {
28463
- const path98 = c.req.path;
28464
- if (PUBLIC_PATHS.some((p) => path98 === p || path98.startsWith(p + "?"))) {
28463
+ const path99 = c.req.path;
28464
+ if (PUBLIC_PATHS.some((p) => path99 === p || path99.startsWith(p + "?"))) {
28465
28465
  return next();
28466
28466
  }
28467
- if (EXTENSION_ASSET_PATH.test(path98)) {
28467
+ if (EXTENSION_ASSET_PATH.test(path99)) {
28468
28468
  return next();
28469
28469
  }
28470
28470
  const token = getCookie(c, COOKIE_NAME);
28471
28471
  const payload = validateToken(token);
28472
28472
  if (!payload) {
28473
- if (!path98.startsWith("/api/")) {
28473
+ if (!path99.startsWith("/api/")) {
28474
28474
  return next();
28475
28475
  }
28476
28476
  return c.json({ error: "Unauthorized" }, 401);
@@ -28524,14 +28524,14 @@ function createWebChannel(deps) {
28524
28524
  return findActiveSessionId(sm, accountId, prefix, activeOverrides, "full") ?? void 0;
28525
28525
  }
28526
28526
  function resolveWorkspace(account, override, scaffold = true) {
28527
- let path98 = account.workspacePath;
28527
+ let path99 = account.workspacePath;
28528
28528
  if (override && override !== account.workspacePath) {
28529
28529
  if (account.accessLevel !== "full") {
28530
28530
  return { ok: false, error: "workspace override requires a full-access token" };
28531
28531
  }
28532
- path98 = override;
28532
+ path99 = override;
28533
28533
  }
28534
- const resolved = scaffold ? resolveAccountWorkspace({ ...account, workspacePath: path98 }) : fs64.existsSync(path98) ? path98 : null;
28534
+ const resolved = scaffold ? resolveAccountWorkspace({ ...account, workspacePath: path99 }) : fs64.existsSync(path99) ? path99 : null;
28535
28535
  if (!resolved)
28536
28536
  return { ok: false, error: "workspace not found" };
28537
28537
  return { ok: true, path: resolved };
@@ -32756,7 +32756,7 @@ function buildCard(workspace, interfaceUrl, caps) {
32756
32756
  return {
32757
32757
  name: raw.name,
32758
32758
  description: raw.description,
32759
- version: typeof raw.version === "string" ? raw.version : "2.2.4",
32759
+ version: typeof raw.version === "string" ? raw.version : "2.2.5",
32760
32760
  supportedInterfaces: [{ url: interfaceUrl, protocolBinding: "JSONRPC", protocolVersion: A2A_VERSION }],
32761
32761
  capabilities: { streaming: caps.streaming, pushNotifications: true, extendedAgentCard: false },
32762
32762
  ...caps.tokenAuth === false ? {} : {
@@ -35780,11 +35780,15 @@ function haloBaseVersion(haloVersion) {
35780
35780
  return semver.valid(stripped) === stripped ? stripped : null;
35781
35781
  }
35782
35782
  function defaultHubBase(hubRepo) {
35783
+ const gh = githubHubRepo(hubRepo);
35784
+ return gh ? `https://raw.githubusercontent.com/${gh.owner}/${gh.repo}/main/extensions` : null;
35785
+ }
35786
+ function githubHubRepo(hubRepo) {
35783
35787
  let h = hubRepo.trim();
35784
35788
  if (h === "" || h.startsWith("{{"))
35785
35789
  h = DEFAULT_HUB_REPO;
35786
35790
  const m = /^(?:https:\/\/github\.com\/)?([A-Za-z0-9][A-Za-z0-9_.-]*)\/([A-Za-z0-9_.-]+?)(?:\.git)?\/?$/.exec(h);
35787
- return m ? `https://raw.githubusercontent.com/${m[1]}/${m[2]}/main/extensions` : null;
35791
+ return m ? { owner: m[1], repo: m[2] } : null;
35788
35792
  }
35789
35793
  function updateJsonUrl(id, source, hubBase2) {
35790
35794
  if (source)
@@ -35924,7 +35928,7 @@ function createCoreChecker(opts) {
35924
35928
  }
35925
35929
  function getCoreStatus(force) {
35926
35930
  checker ??= createCoreChecker({
35927
- haloVersion: "2.2.4",
35931
+ haloVersion: "2.2.5",
35928
35932
  fetchLatest: fetchNpmLatest,
35929
35933
  onChange: (status) => broadcast({ type: "updates:changed", scope: "core", status })
35930
35934
  });
@@ -36092,7 +36096,7 @@ function hubBase() {
36092
36096
  }
36093
36097
  function serverChecker() {
36094
36098
  checker2 ??= createExtensionsChecker({
36095
- haloVersion: "2.2.4",
36099
+ haloVersion: "2.2.5",
36096
36100
  installed: () => {
36097
36101
  const s = getSnapshot();
36098
36102
  return [...s.extensions, ...s.disabled];
@@ -36427,6 +36431,97 @@ var init_extensions = __esm({
36427
36431
  }
36428
36432
  });
36429
36433
 
36434
+ // ../server/dist/models/hub-update.js
36435
+ import fs80 from "node:fs";
36436
+ import os11 from "node:os";
36437
+ import path86 from "node:path";
36438
+ import JSZip3 from "jszip";
36439
+ function pickModelsRelease(releases) {
36440
+ if (!Array.isArray(releases))
36441
+ return null;
36442
+ for (const r of releases) {
36443
+ if (typeof r?.tag_name !== "string" || !/^models-v\d/.test(r.tag_name) || r.draft || r.prerelease)
36444
+ continue;
36445
+ const assets = Array.isArray(r.assets) ? r.assets : [];
36446
+ const zip = assets.find((a) => typeof a?.name === "string" && a.name.endsWith(".zip") && typeof a.browser_download_url === "string");
36447
+ if (zip)
36448
+ return { tag: r.tag_name, url: zip.browser_download_url };
36449
+ }
36450
+ return null;
36451
+ }
36452
+ async function unpackYamls(zipBuf, dest) {
36453
+ let zip;
36454
+ try {
36455
+ zip = await JSZip3.loadAsync(zipBuf);
36456
+ } catch (err) {
36457
+ throw new ModelsHubError(`release asset is not a zip: ${err instanceof Error ? err.message : String(err)}`);
36458
+ }
36459
+ const seen = /* @__PURE__ */ new Set();
36460
+ for (const entry of Object.values(zip.files)) {
36461
+ if (entry.dir)
36462
+ continue;
36463
+ const name = path86.posix.basename(entry.name.replace(/\\/g, "/"));
36464
+ if (!name.endsWith(".yaml") || name.startsWith("."))
36465
+ continue;
36466
+ if (seen.has(name))
36467
+ throw new ModelsHubError(`zip holds ${name} twice`);
36468
+ seen.add(name);
36469
+ fs80.writeFileSync(path86.join(dest, name), await entry.async("nodebuffer"));
36470
+ }
36471
+ }
36472
+ async function updateModelsFromHub(hubRepo, opts = {}) {
36473
+ const gh = githubHubRepo(hubRepo);
36474
+ if (!gh)
36475
+ throw new ModelsHubError(`not a GitHub hub: ${hubRepo}`);
36476
+ const hub = `${gh.owner}/${gh.repo}`;
36477
+ const api = `https://api.github.com/repos/${hub}/releases?per_page=100`;
36478
+ const res = await httpsGet(api, { maxBytes: RELEASES_MAX_BYTES, timeoutMs: RELEASES_TIMEOUT_MS, headers: { accept: "application/vnd.github+json" } });
36479
+ if (res.status !== 200)
36480
+ throw new ModelsHubError(`GitHub release API answered HTTP ${res.status} for ${hub} \u2014 rate-limited, private or wrong repo?`);
36481
+ let releases;
36482
+ try {
36483
+ releases = JSON.parse(res.body.toString("utf-8"));
36484
+ } catch {
36485
+ throw new ModelsHubError(`GitHub release API sent invalid JSON for ${hub}`);
36486
+ }
36487
+ const picked = pickModelsRelease(releases);
36488
+ if (!picked)
36489
+ throw new ModelsHubError(`no models-v* release with a .zip asset in ${hub}`);
36490
+ const zip = await httpsGet(picked.url, { maxBytes: ZIP_MAX_BYTES, timeoutMs: ZIP_TIMEOUT_MS, idleTimeoutMs: ZIP_IDLE_TIMEOUT_MS });
36491
+ if (zip.status !== 200)
36492
+ throw new ModelsHubError(`download of ${picked.tag} failed: HTTP ${zip.status}`);
36493
+ const tmp = fs80.mkdtempSync(path86.join(os11.tmpdir(), "halo-models-"));
36494
+ try {
36495
+ await unpackYamls(zip.body, tmp);
36496
+ let plan;
36497
+ try {
36498
+ plan = planModelsInstall(tmp, opts.dirs);
36499
+ } catch (err) {
36500
+ throw new ModelsHubError(`${picked.tag}: ${err instanceof Error ? err.message.replace(tmp, "the release zip") : String(err)}`);
36501
+ }
36502
+ const written = plan.needsConfirm && !opts.confirm ? null : applyModelsInstall(plan);
36503
+ return { hub, release: picked.tag, plan, written, summary: written ? summaryLine(plan, written) : null };
36504
+ } finally {
36505
+ fs80.rmSync(tmp, { recursive: true, force: true });
36506
+ }
36507
+ }
36508
+ var ModelsHubError, RELEASES_MAX_BYTES, ZIP_MAX_BYTES, RELEASES_TIMEOUT_MS, ZIP_TIMEOUT_MS, ZIP_IDLE_TIMEOUT_MS;
36509
+ var init_hub_update = __esm({
36510
+ "../server/dist/models/hub-update.js"() {
36511
+ "use strict";
36512
+ init_https_get();
36513
+ init_update_json();
36514
+ init_install();
36515
+ ModelsHubError = class extends Error {
36516
+ };
36517
+ RELEASES_MAX_BYTES = 2 * 1024 * 1024;
36518
+ ZIP_MAX_BYTES = 10 * 1024 * 1024;
36519
+ RELEASES_TIMEOUT_MS = 15e3;
36520
+ ZIP_TIMEOUT_MS = 6e4;
36521
+ ZIP_IDLE_TIMEOUT_MS = 2e4;
36522
+ }
36523
+ });
36524
+
36430
36525
  // ../server/dist/routes/updates.js
36431
36526
  import { Hono as Hono22 } from "hono";
36432
36527
  function statusOf(scope, force) {
@@ -36447,20 +36542,55 @@ function createUpdateRoutes() {
36447
36542
  const status = statusOf(body?.scope, true);
36448
36543
  return status ? c.json(status) : c.json({ error: SCOPE_ERROR }, 400);
36449
36544
  });
36545
+ app2.post("/models/update", async (c) => {
36546
+ const body = await c.req.json().catch(() => null);
36547
+ const hubRepo = getServerParam("extension", "hub_repo");
36548
+ if (!githubHubRepo(hubRepo)) {
36549
+ return c.json({ error: `Sync latest models supports GitHub hubs only (extension hub_repo is ${hubRepo}) \u2014 use /extension models in a chat, which also handles Gitea / Forgejo / GitLab` }, 400);
36550
+ }
36551
+ if (syncingModels)
36552
+ return c.json({ error: "A model sync is already running" }, 409);
36553
+ syncingModels = true;
36554
+ try {
36555
+ const r = await updateModelsFromHub(hubRepo, { confirm: body?.confirm === true });
36556
+ if (r.written)
36557
+ console.log(`[Models] synced ${r.hub} ${r.release}: ${r.summary}`);
36558
+ return c.json({
36559
+ hub: r.hub,
36560
+ release: r.release,
36561
+ needsConfirm: r.written === null,
36562
+ written: r.written ?? [],
36563
+ summary: r.summary,
36564
+ // `raw` (the yaml text) stays server-side.
36565
+ entries: r.plan.entries.map(({ raw: _raw, ...e }) => e)
36566
+ });
36567
+ } catch (err) {
36568
+ const msg = err instanceof Error ? err.message : String(err);
36569
+ console.log(`[Models] sync from ${hubRepo || "the default hub"} failed: ${msg}`);
36570
+ return c.json({ error: msg }, err instanceof ModelsHubError || err instanceof HttpsGetError ? 502 : 500);
36571
+ } finally {
36572
+ syncingModels = false;
36573
+ }
36574
+ });
36450
36575
  return app2;
36451
36576
  }
36452
- var SCOPE_ERROR;
36577
+ var SCOPE_ERROR, syncingModels;
36453
36578
  var init_updates = __esm({
36454
36579
  "../server/dist/routes/updates.js"() {
36455
36580
  "use strict";
36581
+ init_config();
36456
36582
  init_core_check();
36457
36583
  init_extension_check();
36584
+ init_update_json();
36585
+ init_https_get();
36586
+ init_hub_update();
36458
36587
  SCOPE_ERROR = 'scope must be "core" or "extensions"';
36588
+ syncingModels = false;
36459
36589
  }
36460
36590
  });
36461
36591
 
36462
36592
  // ../server/dist/models/watcher.js
36463
- import fs80 from "node:fs";
36593
+ import fs81 from "node:fs";
36464
36594
  function snapshot2() {
36465
36595
  const { effective } = loadProviders();
36466
36596
  return {
@@ -36488,7 +36618,7 @@ function reloadAndBroadcast() {
36488
36618
  }
36489
36619
  function openWatcher2(root) {
36490
36620
  try {
36491
- watcher2 = fs80.watch(root, { persistent: false, recursive: false }, () => scheduleFlush2());
36621
+ watcher2 = fs81.watch(root, { persistent: false, recursive: false }, () => scheduleFlush2());
36492
36622
  watcher2.on("error", (err) => {
36493
36623
  console.warn(`[Models] watch error on ${root}: ${err.message} \u2014 retrying in 1s`);
36494
36624
  closeWatcher2();
@@ -36514,7 +36644,7 @@ function start2() {
36514
36644
  return;
36515
36645
  const root = globalHubModelsDir();
36516
36646
  try {
36517
- fs80.mkdirSync(root, { recursive: true });
36647
+ fs81.mkdirSync(root, { recursive: true });
36518
36648
  } catch (err) {
36519
36649
  console.warn(`[Models] cannot create ${root}: ${err instanceof Error ? err.message : String(err)}`);
36520
36650
  }
@@ -36549,8 +36679,8 @@ var init_watcher2 = __esm({
36549
36679
  });
36550
36680
 
36551
36681
  // ../server/dist/evolution/notify.js
36552
- import fs81 from "node:fs";
36553
- import path86 from "node:path";
36682
+ import fs82 from "node:fs";
36683
+ import path87 from "node:path";
36554
36684
  import { and as and18, eq as eq22, isNull as isNull7 } from "drizzle-orm";
36555
36685
  function setEvoSessionRegistry(r) {
36556
36686
  _registry4 = r;
@@ -36569,7 +36699,7 @@ function formatAutoAppliedNotice(input) {
36569
36699
  }
36570
36700
  function readJson(file) {
36571
36701
  try {
36572
- return JSON.parse(fs81.readFileSync(file, "utf-8"));
36702
+ return JSON.parse(fs82.readFileSync(file, "utf-8"));
36573
36703
  } catch {
36574
36704
  return null;
36575
36705
  }
@@ -36583,10 +36713,10 @@ function notifyAutoApplied(db4) {
36583
36713
  try {
36584
36714
  const runId = JSON.parse(a.sourceRunIds)[0];
36585
36715
  const run = runId ? db4.select().from(evolutionRuns).where(eq22(evolutionRuns.id, runId)).get() : void 0;
36586
- if (run && fs81.existsSync(path86.join(a.workspacePath, ".halo"))) {
36716
+ if (run && fs82.existsSync(path87.join(a.workspacePath, ".halo"))) {
36587
36717
  const sm = registry2.getOrCreate(a.workspacePath);
36588
36718
  if (sm.getSessionById(run.sourceSession)) {
36589
- const verdict2 = readJson(path86.join(wsEvoRunDir(a.workspacePath, run.id), AUTO_APPLY_FILE));
36719
+ const verdict2 = readJson(path87.join(wsEvoRunDir(a.workspacePath, run.id), AUTO_APPLY_FILE));
36590
36720
  sm.notifySystem(run.sourceSession, formatAutoAppliedNotice({
36591
36721
  files: readPublishedFiles(a.workspacePath, a.id) ?? [],
36592
36722
  avg: verdict2?.score?.avg ?? null,
@@ -36872,14 +37002,14 @@ var init_ticker = __esm({
36872
37002
  });
36873
37003
 
36874
37004
  // ../server/dist/evolution/spawn.js
36875
- import fs82 from "node:fs";
36876
- import path87 from "node:path";
37005
+ import fs83 from "node:fs";
37006
+ import path88 from "node:path";
36877
37007
  import { spawn as spawn5 } from "node:child_process";
36878
37008
  import { fileURLToPath as fileURLToPath2 } from "node:url";
36879
37009
  function spawnEvoWrapper(wrapperPath, mode, id) {
36880
- fs82.mkdirSync(evoLogsDir(), { recursive: true });
37010
+ fs83.mkdirSync(evoLogsDir(), { recursive: true });
36881
37011
  const logPath = mode === "run" ? evoWrapperLogFile(id) : evoApplyLogFile(id);
36882
- const logFd = fs82.openSync(logPath, "a");
37012
+ const logFd = fs83.openSync(logPath, "a");
36883
37013
  let child;
36884
37014
  try {
36885
37015
  child = spawn5(process.execPath, [wrapperPath, `--mode=${mode}`, `--id=${id}`], {
@@ -36892,7 +37022,7 @@ function spawnEvoWrapper(wrapperPath, mode, id) {
36892
37022
  windowsHide: true
36893
37023
  });
36894
37024
  } finally {
36895
- fs82.closeSync(logFd);
37025
+ fs83.closeSync(logFd);
36896
37026
  }
36897
37027
  child.once("exit", (code, signal) => {
36898
37028
  if (code === 0)
@@ -36909,8 +37039,8 @@ var init_spawn = __esm({
36909
37039
  "use strict";
36910
37040
  init_child_env();
36911
37041
  init_paths();
36912
- __dirname2 = path87.dirname(fileURLToPath2(import.meta.url));
36913
- WRAPPER_PATH = path87.resolve(__dirname2, "evo-wrapper.js");
37042
+ __dirname2 = path88.dirname(fileURLToPath2(import.meta.url));
37043
+ WRAPPER_PATH = path88.resolve(__dirname2, "evo-wrapper.js");
36914
37044
  realEvoSpawner = (mode, id) => {
36915
37045
  spawnEvoWrapper(WRAPPER_PATH, mode, id);
36916
37046
  };
@@ -37730,12 +37860,12 @@ var init_handler3 = __esm({
37730
37860
  });
37731
37861
 
37732
37862
  // ../server/dist/routes/channel-accounts.js
37733
- import fs83 from "node:fs";
37863
+ import fs84 from "node:fs";
37734
37864
  function accountListFields(a) {
37735
37865
  return {
37736
37866
  accountId: a.accountId,
37737
37867
  workspacePath: a.workspacePath,
37738
- workspaceMissing: !fs83.existsSync(a.workspacePath),
37868
+ workspaceMissing: !fs84.existsSync(a.workspacePath),
37739
37869
  label: a.label,
37740
37870
  enabled: a.enabled,
37741
37871
  accessLevel: a.accessLevel,
@@ -38377,8 +38507,8 @@ var init_cdn = __esm({
38377
38507
  });
38378
38508
 
38379
38509
  // ../server/dist/channels/wechat/send-media.js
38380
- import fs84 from "node:fs/promises";
38381
- import path88 from "node:path";
38510
+ import fs85 from "node:fs/promises";
38511
+ import path89 from "node:path";
38382
38512
  function inferKind(filePath) {
38383
38513
  const cls = classifyMedia(filePath);
38384
38514
  if (cls === "image")
@@ -38390,7 +38520,7 @@ function inferKind(filePath) {
38390
38520
  async function sendMediaFile(params) {
38391
38521
  const { baseUrl, token, toUserId, contextToken, contextTokenAt, filePath } = params;
38392
38522
  const kind = params.kind ?? inferKind(filePath);
38393
- const plaintext = await fs84.readFile(filePath);
38523
+ const plaintext = await fs85.readFile(filePath);
38394
38524
  const prep = prepareUpload(plaintext);
38395
38525
  console.log(`[WeChat] sendMediaFile: path=${filePath} kind=${kind} rawsize=${prep.rawsize} filesize=${prep.filesize}`);
38396
38526
  const mediaType = kind === "image" ? UploadMediaType.IMAGE : kind === "video" ? UploadMediaType.VIDEO : UploadMediaType.FILE;
@@ -38428,7 +38558,7 @@ async function sendMediaFile(params) {
38428
38558
  aesKeyBase64,
38429
38559
  fileSizeCiphertext: prep.filesize,
38430
38560
  fileSize: prep.rawsize,
38431
- fileName: path88.basename(filePath)
38561
+ fileName: path89.basename(filePath)
38432
38562
  });
38433
38563
  const clientId = `halo-media-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
38434
38564
  const body = {
@@ -38591,8 +38721,8 @@ var init_login = __esm({
38591
38721
  });
38592
38722
 
38593
38723
  // ../server/dist/channels/wechat/handler.js
38594
- import fs85 from "node:fs";
38595
- import path89 from "node:path";
38724
+ import fs86 from "node:fs";
38725
+ import path90 from "node:path";
38596
38726
  import QRCode from "qrcode";
38597
38727
  function wxRoute(fromUserId, contextToken, contextTokenAt) {
38598
38728
  return (prev) => {
@@ -39013,7 +39143,7 @@ async function handleSlashCommand(args) {
39013
39143
  await reply(login.message);
39014
39144
  return true;
39015
39145
  }
39016
- const tmpPath = path89.join(tempDir(), `halo-qr-${login.sessionKey}.png`);
39146
+ const tmpPath = path90.join(tempDir(), `halo-qr-${login.sessionKey}.png`);
39017
39147
  await QRCode.toFile(tmpPath, login.qrcodeUrl, { width: 256, margin: 2 });
39018
39148
  await sendMediaFile({
39019
39149
  baseUrl: account.baseUrl,
@@ -39022,7 +39152,7 @@ async function handleSlashCommand(args) {
39022
39152
  contextToken,
39023
39153
  filePath: tmpPath
39024
39154
  });
39025
- await fs85.promises.unlink(tmpPath).catch(() => {
39155
+ await fs86.promises.unlink(tmpPath).catch(() => {
39026
39156
  });
39027
39157
  await reply(t("wechat.qr_sent", lang, { level, path: account.workspacePath }));
39028
39158
  waitLogin({ sessionKey: login.sessionKey }).then(async (result2) => {
@@ -39102,8 +39232,8 @@ var init_handler4 = __esm({
39102
39232
 
39103
39233
  // ../server/dist/routes/wechat.js
39104
39234
  import { Hono as Hono24 } from "hono";
39105
- import path90 from "node:path";
39106
- import fs86 from "node:fs";
39235
+ import path91 from "node:path";
39236
+ import fs87 from "node:fs";
39107
39237
  function createWechatRoutes(deps) {
39108
39238
  const { db: db4, channel } = deps;
39109
39239
  const app2 = new Hono24();
@@ -39112,7 +39242,7 @@ function createWechatRoutes(deps) {
39112
39242
  return {
39113
39243
  ...stripSecrets(acc),
39114
39244
  workspacePath: acc.workspacePath,
39115
- workspaceMissing: !fs86.existsSync(acc.workspacePath)
39245
+ workspaceMissing: !fs87.existsSync(acc.workspacePath)
39116
39246
  };
39117
39247
  });
39118
39248
  return c.json({ accounts });
@@ -39128,7 +39258,7 @@ function createWechatRoutes(deps) {
39128
39258
  return c.json({ error: "sessionKey required" }, 400);
39129
39259
  if (!body.workspacePath)
39130
39260
  return c.json({ error: "workspacePath required" }, 400);
39131
- if (!path90.isAbsolute(body.workspacePath))
39261
+ if (!path91.isAbsolute(body.workspacePath))
39132
39262
  return c.json({ error: "workspacePath must be absolute" }, 400);
39133
39263
  const levelError = accessLevelError(body.accessLevel, CHAT_ACCESS_LEVELS);
39134
39264
  if (levelError)
@@ -39341,7 +39471,7 @@ var init_descriptor2 = __esm({
39341
39471
  import { Hono as Hono25 } from "hono";
39342
39472
  import { streamSSE as streamSSE3 } from "hono/streaming";
39343
39473
  import crypto15 from "node:crypto";
39344
- import fs87 from "node:fs";
39474
+ import fs88 from "node:fs";
39345
39475
  function streamWithKeepalive(c, chunks) {
39346
39476
  return streamSSE3(c, async (stream) => {
39347
39477
  const timer2 = setInterval(() => {
@@ -39537,30 +39667,30 @@ function createWebRoutes(deps) {
39537
39667
  const filePath = c.req.query("path");
39538
39668
  if (!filePath)
39539
39669
  return c.json({ error: "path required" }, 400);
39540
- const path98 = await import("node:path");
39541
- const resolved = path98.default.resolve(account.workspacePath, filePath);
39542
- const root = path98.default.resolve(account.workspacePath);
39543
- if (resolved !== root && !resolved.startsWith(root + path98.default.sep)) {
39670
+ const path99 = await import("node:path");
39671
+ const resolved = path99.default.resolve(account.workspacePath, filePath);
39672
+ const root = path99.default.resolve(account.workspacePath);
39673
+ if (resolved !== root && !resolved.startsWith(root + path99.default.sep)) {
39544
39674
  return c.json({ error: "path traversal not allowed" }, 403);
39545
39675
  }
39546
39676
  let real;
39547
39677
  let realRoot;
39548
39678
  try {
39549
- real = fs87.realpathSync(resolved);
39550
- realRoot = fs87.realpathSync(root);
39679
+ real = fs88.realpathSync(resolved);
39680
+ realRoot = fs88.realpathSync(root);
39551
39681
  } catch {
39552
39682
  return c.json({ error: "file not found" }, 404);
39553
39683
  }
39554
- if (real !== realRoot && !real.startsWith(realRoot + path98.default.sep)) {
39684
+ if (real !== realRoot && !real.startsWith(realRoot + path99.default.sep)) {
39555
39685
  return c.json({ error: "path traversal not allowed" }, 403);
39556
39686
  }
39557
39687
  if (isHiddenWorkspacePath(real, realRoot)) {
39558
39688
  return c.json({ error: "path is not accessible" }, 403);
39559
39689
  }
39560
- const stat = fs87.statSync(real);
39690
+ const stat = fs88.statSync(real);
39561
39691
  if (stat.isDirectory())
39562
39692
  return c.json({ error: "cannot serve directory" }, 400);
39563
- const ext = path98.default.extname(real).toLowerCase();
39693
+ const ext = path99.default.extname(real).toLowerCase();
39564
39694
  const nonImageMimes = {
39565
39695
  ".mp4": "video/mp4",
39566
39696
  ".webm": "video/webm",
@@ -39568,8 +39698,8 @@ function createWebRoutes(deps) {
39568
39698
  ".txt": "text/plain"
39569
39699
  };
39570
39700
  const contentType = imageMimeFromExt(ext) || nonImageMimes[ext] || "application/octet-stream";
39571
- const fileName = path98.default.basename(resolved);
39572
- const data = fs87.readFileSync(real);
39701
+ const fileName = path99.default.basename(resolved);
39702
+ const data = fs88.readFileSync(real);
39573
39703
  c.header("content-type", contentType);
39574
39704
  c.header("content-disposition", `inline; filename="${fileName}"`);
39575
39705
  return c.body(data);
@@ -39791,10 +39921,10 @@ async function authTest(botToken) {
39791
39921
  return slackPost("auth.test", botToken, {});
39792
39922
  }
39793
39923
  async function uploadFile(args) {
39794
- const fs92 = await import("node:fs");
39795
- const path98 = await import("node:path");
39796
- const filename = args.filename ?? path98.basename(args.filePath);
39797
- const stat = fs92.statSync(args.filePath);
39924
+ const fs93 = await import("node:fs");
39925
+ const path99 = await import("node:path");
39926
+ const filename = args.filename ?? path99.basename(args.filePath);
39927
+ const stat = fs93.statSync(args.filePath);
39798
39928
  if (!stat.isFile())
39799
39929
  throw new Error(`[slack:uploadFile] not a regular file: ${args.filePath}`);
39800
39930
  const length = stat.size;
@@ -39812,7 +39942,7 @@ async function uploadFile(args) {
39812
39942
  if (step1Parsed.ok === false || !step1Parsed.upload_url || !step1Parsed.file_id) {
39813
39943
  throw new Error(`[slack:files.getUploadURLExternal] ${step1Parsed.error ?? "unknown"}`);
39814
39944
  }
39815
- const buf = fs92.readFileSync(args.filePath);
39945
+ const buf = fs93.readFileSync(args.filePath);
39816
39946
  const step2 = await fetch(step1Parsed.upload_url, {
39817
39947
  method: "POST",
39818
39948
  body: buf
@@ -39957,7 +40087,7 @@ var init_api2 = __esm({
39957
40087
  });
39958
40088
 
39959
40089
  // ../server/dist/channels/slack/handler.js
39960
- import path91 from "node:path";
40090
+ import path92 from "node:path";
39961
40091
  import { WebSocket as WebSocket3 } from "ws";
39962
40092
  function slashToBang(text6, commandNames) {
39963
40093
  if (commandNames.length === 0)
@@ -40088,7 +40218,7 @@ function startSlackChannel(deps) {
40088
40218
  const route = bridge.getRoute(sessionId);
40089
40219
  if (!account || !route)
40090
40220
  return;
40091
- const resolved = path91.resolve(filePath);
40221
+ const resolved = path92.resolve(filePath);
40092
40222
  await sendMediaOrReport({
40093
40223
  filePath,
40094
40224
  account,
@@ -40732,10 +40862,10 @@ async function replyMessage(args) {
40732
40862
  return { message_id: parsed.data?.message_id ?? "" };
40733
40863
  }
40734
40864
  async function uploadImage(args) {
40735
- const fs92 = await import("node:fs");
40736
- const path98 = await import("node:path");
40737
- const buf = fs92.readFileSync(args.filePath);
40738
- const filename = path98.basename(args.filePath);
40865
+ const fs93 = await import("node:fs");
40866
+ const path99 = await import("node:path");
40867
+ const buf = fs93.readFileSync(args.filePath);
40868
+ const filename = path99.basename(args.filePath);
40739
40869
  const send2 = async (token) => {
40740
40870
  const form = new FormData();
40741
40871
  form.append("image_type", "message");
@@ -40751,10 +40881,10 @@ async function uploadImage(args) {
40751
40881
  return { imageKey: parsed.data.image_key };
40752
40882
  }
40753
40883
  async function uploadFile2(args) {
40754
- const fs92 = await import("node:fs");
40755
- const path98 = await import("node:path");
40756
- const buf = fs92.readFileSync(args.filePath);
40757
- const filename = args.filename ?? path98.basename(args.filePath);
40884
+ const fs93 = await import("node:fs");
40885
+ const path99 = await import("node:path");
40886
+ const buf = fs93.readFileSync(args.filePath);
40887
+ const filename = args.filename ?? path99.basename(args.filePath);
40758
40888
  const send2 = async (token) => {
40759
40889
  const form = new FormData();
40760
40890
  form.append("file_type", args.fileType);
@@ -40821,7 +40951,7 @@ var init_api3 = __esm({
40821
40951
  });
40822
40952
 
40823
40953
  // ../server/dist/channels/feishu/handler.js
40824
- import path92 from "node:path";
40954
+ import path93 from "node:path";
40825
40955
  import * as Lark from "@larksuiteoapi/node-sdk";
40826
40956
  function buildSessionPrefixForThread2(chatId, rootId) {
40827
40957
  return sessionPrefix("feishu", `${chatId}:${rootId}`);
@@ -41024,7 +41154,7 @@ function startFeishuChannel(deps) {
41024
41154
  const route = bridge.getRoute(sessionId);
41025
41155
  if (!account || !route)
41026
41156
  return;
41027
- const resolved = path92.resolve(filePath);
41157
+ const resolved = path93.resolve(filePath);
41028
41158
  await sendMediaOrReport({
41029
41159
  filePath,
41030
41160
  account,
@@ -41191,7 +41321,7 @@ async function replyToInbound(args) {
41191
41321
  async function sendFeishuMedia(args) {
41192
41322
  const { account, inboundMessageId, isP2P, chatId, filePath } = args;
41193
41323
  const cls = classifyMedia(filePath);
41194
- const ext = path92.extname(filePath).toLowerCase();
41324
+ const ext = path93.extname(filePath).toLowerCase();
41195
41325
  if (cls === "image") {
41196
41326
  const { imageKey } = await uploadImage({ appId: account.appId, appSecret: account.appSecret, filePath });
41197
41327
  await replyToInboundRaw({
@@ -41586,8 +41716,8 @@ var init_event_adapter5 = __esm({
41586
41716
  });
41587
41717
 
41588
41718
  // ../server/dist/channels/wecom/handler.js
41589
- import path93 from "node:path";
41590
- import fs88 from "node:fs/promises";
41719
+ import path94 from "node:path";
41720
+ import fs89 from "node:fs/promises";
41591
41721
  import { WSClient as WSClient2, generateReqId } from "@wecom/aibot-node-sdk";
41592
41722
  function pickConversation(body) {
41593
41723
  const userid = body.from?.userid ?? "unknown";
@@ -41710,13 +41840,13 @@ async function replyText(wsClient, route, text6) {
41710
41840
  }
41711
41841
  async function sendWecomMedia(args) {
41712
41842
  const { wsClient, route, filePath } = args;
41713
- const ext = path93.extname(filePath).toLowerCase();
41843
+ const ext = path94.extname(filePath).toLowerCase();
41714
41844
  const cls = classifyMedia(filePath);
41715
41845
  const type = cls === "image" && [".png", ".jpg", ".jpeg", ".gif"].includes(ext) ? "image" : cls === "video" && ext === ".mp4" ? "video" : "file";
41716
- const buf = await fs88.readFile(filePath);
41846
+ const buf = await fs89.readFile(filePath);
41717
41847
  if (buf.length > MAX_WECOM_DOWNLOAD_BYTES)
41718
41848
  throw new Error("file exceeds 20MB");
41719
- const { media_id: mediaId } = await wsClient.uploadMedia(buf, { type, filename: path93.basename(filePath) });
41849
+ const { media_id: mediaId } = await wsClient.uploadMedia(buf, { type, filename: path94.basename(filePath) });
41720
41850
  if (route.reqId)
41721
41851
  await wsClient.replyMedia({ headers: { req_id: route.reqId } }, type, mediaId);
41722
41852
  else
@@ -41761,7 +41891,7 @@ function startWecomChannel(deps) {
41761
41891
  const wsClient = states.get(accountId)?.wsClient;
41762
41892
  if (!account || !route || !wsClient)
41763
41893
  return;
41764
- const resolved = path93.resolve(filePath);
41894
+ const resolved = path94.resolve(filePath);
41765
41895
  await sendMediaOrReport({
41766
41896
  filePath,
41767
41897
  account,
@@ -42249,17 +42379,17 @@ import { cors } from "hono/cors";
42249
42379
  import { serve } from "@hono/node-server";
42250
42380
  import { serveStatic } from "@hono/node-server/serve-static";
42251
42381
  import { WebSocketServer as WebSocketServer5 } from "ws";
42252
- import path94 from "node:path";
42253
- import fs89 from "node:fs";
42382
+ import path95 from "node:path";
42383
+ import fs90 from "node:fs";
42254
42384
  import { spawnSync as spawnSync4 } from "node:child_process";
42255
42385
  import { homedir as homedir26 } from "node:os";
42256
42386
  import { fileURLToPath as fileURLToPath3 } from "node:url";
42257
42387
  function findProjectRoot() {
42258
42388
  let dir = process.cwd();
42259
42389
  for (let i = 0; i < 32; i++) {
42260
- if (fs89.existsSync(path94.join(dir, "pnpm-workspace.yaml")))
42390
+ if (fs90.existsSync(path95.join(dir, "pnpm-workspace.yaml")))
42261
42391
  return dir;
42262
- const parent = path94.dirname(dir);
42392
+ const parent = path95.dirname(dir);
42263
42393
  if (parent === dir)
42264
42394
  break;
42265
42395
  dir = parent;
@@ -42269,15 +42399,15 @@ function findProjectRoot() {
42269
42399
  return process.cwd();
42270
42400
  }
42271
42401
  function acquireSingleInstanceLock(lockFile) {
42272
- fs89.mkdirSync(path94.dirname(lockFile), { recursive: true });
42273
- const fd = fs89.openSync(lockFile, fs89.constants.O_RDWR | fs89.constants.O_CREAT, 420);
42402
+ fs90.mkdirSync(path95.dirname(lockFile), { recursive: true });
42403
+ const fd = fs90.openSync(lockFile, fs90.constants.O_RDWR | fs90.constants.O_CREAT, 420);
42274
42404
  const result = spawnSync4("flock", ["-n", "3"], {
42275
42405
  stdio: ["ignore", "ignore", "ignore", fd]
42276
42406
  });
42277
42407
  if (result.error) {
42278
42408
  const content = readLockPid(fd);
42279
42409
  if (content > 0 && isProcessAlive(content)) {
42280
- fs89.closeSync(fd);
42410
+ fs90.closeSync(fd);
42281
42411
  console.error(`[Server] another halo server is already running (pid ${content}). kill it first.`);
42282
42412
  process.exit(1);
42283
42413
  }
@@ -42286,19 +42416,19 @@ function acquireSingleInstanceLock(lockFile) {
42286
42416
  if (content > 0 && !isProcessAlive(content)) {
42287
42417
  console.warn(`[Server] removing stale server.lock (pid ${content} not running)`);
42288
42418
  } else {
42289
- fs89.closeSync(fd);
42419
+ fs90.closeSync(fd);
42290
42420
  console.error(`[Server] another halo server is already running${content > 0 ? ` (pid ${content})` : ""}. kill it first.`);
42291
42421
  process.exit(1);
42292
42422
  }
42293
42423
  }
42294
- fs89.ftruncateSync(fd);
42295
- fs89.writeSync(fd, String(process.pid));
42296
- fs89.fsyncSync(fd);
42424
+ fs90.ftruncateSync(fd);
42425
+ fs90.writeSync(fd, String(process.pid));
42426
+ fs90.fsyncSync(fd);
42297
42427
  }
42298
42428
  function readLockPid(fd) {
42299
42429
  try {
42300
42430
  const buf = Buffer.alloc(32);
42301
- const n = fs89.readSync(fd, buf, 0, 32, 0);
42431
+ const n = fs90.readSync(fd, buf, 0, 32, 0);
42302
42432
  return parseInt(buf.subarray(0, n).toString("utf-8").trim(), 10) || 0;
42303
42433
  } catch {
42304
42434
  return 0;
@@ -42326,7 +42456,7 @@ function isProcessAlive(pid) {
42326
42456
  }
42327
42457
  }
42328
42458
  function readGitSha() {
42329
- if (!fs89.existsSync(path94.join(PROJECT_ROOT, "pnpm-workspace.yaml")) || !fs89.existsSync(path94.join(PROJECT_ROOT, ".git")))
42459
+ if (!fs90.existsSync(path95.join(PROJECT_ROOT, "pnpm-workspace.yaml")) || !fs90.existsSync(path95.join(PROJECT_ROOT, ".git")))
42330
42460
  return null;
42331
42461
  try {
42332
42462
  const rev = spawnSync4("git", ["rev-parse", "--short", "HEAD"], { cwd: PROJECT_ROOT, encoding: "utf-8" });
@@ -42347,14 +42477,14 @@ function applySandboxPaths() {
42347
42477
  }
42348
42478
  function resolveFrontendDir() {
42349
42479
  if (process.env.HALO_FRONTEND_DIR)
42350
- return path94.resolve(process.env.HALO_FRONTEND_DIR);
42351
- const bundled = path94.resolve(__dirname3, "..", "admin-out");
42352
- if (fs89.existsSync(path94.join(bundled, "index.html")))
42480
+ return path95.resolve(process.env.HALO_FRONTEND_DIR);
42481
+ const bundled = path95.resolve(__dirname3, "..", "admin-out");
42482
+ if (fs90.existsSync(path95.join(bundled, "index.html")))
42353
42483
  return bundled;
42354
- const sibling = path94.resolve(__dirname3, "..", "..", "admin", "out");
42355
- if (fs89.existsSync(path94.join(sibling, "index.html")))
42484
+ const sibling = path95.resolve(__dirname3, "..", "..", "admin", "out");
42485
+ if (fs90.existsSync(path95.join(sibling, "index.html")))
42356
42486
  return sibling;
42357
- return path94.resolve(PROJECT_ROOT, "packages", "admin", "out");
42487
+ return path95.resolve(PROJECT_ROOT, "packages", "admin", "out");
42358
42488
  }
42359
42489
  async function gracefulShutdown(signal) {
42360
42490
  beginShutdown();
@@ -42461,13 +42591,13 @@ var init_dist2 = __esm({
42461
42591
  init_sandbox();
42462
42592
  init_init();
42463
42593
  init_git_ssh();
42464
- __dirname3 = path94.dirname(fileURLToPath3(import.meta.url));
42594
+ __dirname3 = path95.dirname(fileURLToPath3(import.meta.url));
42465
42595
  PORT = config.server.port;
42466
- HALO_VERSION = "2.2.4";
42596
+ HALO_VERSION = "2.2.5";
42467
42597
  PROJECT_ROOT = findProjectRoot();
42468
- HALO_HOME4 = path94.join(homedir26(), ".halo");
42598
+ HALO_HOME4 = path95.join(homedir26(), ".halo");
42469
42599
  GIT_SHA = readGitSha();
42470
- if (!fs89.existsSync(path94.join(HALO_HOME4, "global", ".template-version"))) {
42600
+ if (!fs90.existsSync(path95.join(HALO_HOME4, "global", ".template-version"))) {
42471
42601
  process.stderr.write("\x1B[31m[Server] ~/.halo/global/ not initialized. Run `halo setup` first.\x1B[0m\n");
42472
42602
  process.exit(1);
42473
42603
  }
@@ -42478,7 +42608,7 @@ var init_dist2 = __esm({
42478
42608
  process.exit(1);
42479
42609
  }
42480
42610
  if (!AGENTCORE)
42481
- acquireSingleInstanceLock(path94.join(HALO_HOME4, "global", "server.lock"));
42611
+ acquireSingleInstanceLock(path95.join(HALO_HOME4, "global", "server.lock"));
42482
42612
  commandRegistry.assertDispatchCommands(DISPATCH_COMMANDS);
42483
42613
  await initObservability();
42484
42614
  initLogger();
@@ -42549,14 +42679,14 @@ var init_dist2 = __esm({
42549
42679
  app.route("/api", createJupyterRoutes(jupyter));
42550
42680
  }
42551
42681
  start2();
42552
- channelDb = createChannelDb(path94.join(HALO_HOME4, "secrets"));
42682
+ channelDb = createChannelDb(path95.join(HALO_HOME4, "secrets"));
42553
42683
  setChannelDb(channelDb);
42554
42684
  nodeHub = AGENTCORE ? null : createNodeHub({ db: channelDb });
42555
42685
  setNodeHub(nodeHub);
42556
- setEvoDb(createEvoDb(path94.join(HALO_HOME4, "global")));
42557
- setCronDb(createCronDb(path94.join(HALO_HOME4, "global")));
42686
+ setEvoDb(createEvoDb(path95.join(HALO_HOME4, "global")));
42687
+ setCronDb(createCronDb(path95.join(HALO_HOME4, "global")));
42558
42688
  if (!AGENTCORE)
42559
- setRunsDb(createRunsDb(path94.join(HALO_HOME4, "global")));
42689
+ setRunsDb(createRunsDb(path95.join(HALO_HOME4, "global")));
42560
42690
  setEvoSpawner(realEvoSpawner);
42561
42691
  if (!AGENTCORE) {
42562
42692
  startEvoTicker();
@@ -42572,7 +42702,7 @@ var init_dist2 = __esm({
42572
42702
  setEvoSessionRegistry(registry);
42573
42703
  if (OWNS_RUNTIMES && !AGENTCORE) {
42574
42704
  for (const ws of listRunningWorkspaces()) {
42575
- if (!fs89.existsSync(path94.join(ws, ".halo")))
42705
+ if (!fs90.existsSync(path95.join(ws, ".halo")))
42576
42706
  continue;
42577
42707
  if (!claimWorkspaceRuntime(ws))
42578
42708
  continue;
@@ -42600,7 +42730,7 @@ var init_dist2 = __esm({
42600
42730
  startCronDaemon();
42601
42731
  }
42602
42732
  if (!AGENTCORE) {
42603
- setA2ADb(createA2ADb(path94.join(HALO_HOME4, "global")));
42733
+ setA2ADb(createA2ADb(path95.join(HALO_HOME4, "global")));
42604
42734
  setA2AOutboundRegistry(registry);
42605
42735
  app.route("/a2a", createA2ARoutes({ registry, ownsRuntimes: OWNS_RUNTIMES }));
42606
42736
  app.route("/", createA2APushRoutes());
@@ -42617,7 +42747,7 @@ var init_dist2 = __esm({
42617
42747
  FRONTEND_DIR = resolveFrontendDir();
42618
42748
  if (!AGENTCORE) {
42619
42749
  app.use("/*", serveStatic({
42620
- root: path94.relative(process.cwd(), FRONTEND_DIR),
42750
+ root: path95.relative(process.cwd(), FRONTEND_DIR),
42621
42751
  // Next's `/_next/static/` files are content-hashed (under a buildId dir),
42622
42752
  // so they can be cached forever. Only on a found file — the SPA fallback
42623
42753
  // below must stay uncached, or a missing chunk caches index.html as js.
@@ -42631,9 +42761,9 @@ var init_dist2 = __esm({
42631
42761
  app.get("/*", (c) => {
42632
42762
  if (c.req.path.startsWith("/_next/static/"))
42633
42763
  return c.notFound();
42634
- const indexPath = path94.join(FRONTEND_DIR, "index.html");
42764
+ const indexPath = path95.join(FRONTEND_DIR, "index.html");
42635
42765
  try {
42636
- const html = fs89.readFileSync(indexPath, "utf-8");
42766
+ const html = fs90.readFileSync(indexPath, "utf-8");
42637
42767
  return c.html(html);
42638
42768
  } catch {
42639
42769
  return c.text("Frontend not built. Run: cd packages/admin && npx next build", 503);
@@ -42724,10 +42854,10 @@ __export(agentcore_front_exports, {
42724
42854
  workerEnv: () => workerEnv
42725
42855
  });
42726
42856
  import http3 from "node:http";
42727
- import fs90 from "node:fs";
42857
+ import fs91 from "node:fs";
42728
42858
  import fsp2 from "node:fs/promises";
42729
- import os11 from "node:os";
42730
- import path95 from "node:path";
42859
+ import os12 from "node:os";
42860
+ import path96 from "node:path";
42731
42861
  import crypto16 from "node:crypto";
42732
42862
  import { pipeline as pipeline2 } from "node:stream";
42733
42863
  import { execFile as execFile2, spawn as spawn6 } from "node:child_process";
@@ -42750,44 +42880,44 @@ function mountLayers(dir, mountinfo) {
42750
42880
  }).length;
42751
42881
  }
42752
42882
  function skipTemplateEntry(rel) {
42753
- const name = path95.basename(rel);
42754
- return rel === path95.join(".halo", "sessions") || /\.db(-wal|-shm|-journal)?$/.test(name) || name === "runtime.lock" || name.startsWith("agentcore.lease");
42883
+ const name = path96.basename(rel);
42884
+ return rel === path96.join(".halo", "sessions") || /\.db(-wal|-shm|-journal)?$/.test(name) || name === "runtime.lock" || name.startsWith("agentcore.lease");
42755
42885
  }
42756
42886
  function chownTree(dir, owner, sid) {
42757
42887
  try {
42758
- fs90.lchownSync(dir, owner.uid, owner.gid);
42759
- for (const rel of fs90.readdirSync(dir, { recursive: true }))
42760
- fs90.lchownSync(path95.join(dir, rel), owner.uid, owner.gid);
42888
+ fs91.lchownSync(dir, owner.uid, owner.gid);
42889
+ for (const rel of fs91.readdirSync(dir, { recursive: true }))
42890
+ fs91.lchownSync(path96.join(dir, rel), owner.uid, owner.gid);
42761
42891
  } catch (err) {
42762
42892
  console.warn(`[AgentCore] front: chown ${sid} to ${owner.uid}:${owner.gid} failed (${err.message}) \u2014 serving it as is`);
42763
42893
  }
42764
42894
  }
42765
42895
  function ensureSessionDir(base, sid, owner) {
42766
- const dir = path95.join(base, sid);
42767
- if (fs90.existsSync(dir))
42896
+ const dir = path96.join(base, sid);
42897
+ if (fs91.existsSync(dir))
42768
42898
  return false;
42769
- const tmp = path95.join(base, `.tmp-${crypto16.randomBytes(8).toString("hex")}`);
42770
- fs90.mkdirSync(tmp, { mode: 448 });
42899
+ const tmp = path96.join(base, `.tmp-${crypto16.randomBytes(8).toString("hex")}`);
42900
+ fs91.mkdirSync(tmp, { mode: 448 });
42771
42901
  try {
42772
- const template = path95.join(base, TEMPLATE_DIR);
42773
- if (fs90.statSync(template, { throwIfNoEntry: false })?.isDirectory()) {
42774
- fs90.cpSync(template, tmp, { recursive: true, verbatimSymlinks: true, filter: (src) => !skipTemplateEntry(path95.relative(template, src)) });
42902
+ const template = path96.join(base, TEMPLATE_DIR);
42903
+ if (fs91.statSync(template, { throwIfNoEntry: false })?.isDirectory()) {
42904
+ fs91.cpSync(template, tmp, { recursive: true, verbatimSymlinks: true, filter: (src) => !skipTemplateEntry(path96.relative(template, src)) });
42775
42905
  }
42776
42906
  if (owner)
42777
42907
  chownTree(tmp, owner, sid);
42778
- if (fs90.readdirSync(tmp).length === 0) {
42779
- fs90.rmdirSync(tmp);
42780
- fs90.mkdirSync(dir, { mode: 448 });
42908
+ if (fs91.readdirSync(tmp).length === 0) {
42909
+ fs91.rmdirSync(tmp);
42910
+ fs91.mkdirSync(dir, { mode: 448 });
42781
42911
  if (owner)
42782
42912
  chownTree(dir, owner, sid);
42783
42913
  return true;
42784
42914
  }
42785
- fs90.renameSync(tmp, dir);
42915
+ fs91.renameSync(tmp, dir);
42786
42916
  return true;
42787
42917
  } catch (err) {
42788
- fs90.rmSync(tmp, { recursive: true, force: true });
42918
+ fs91.rmSync(tmp, { recursive: true, force: true });
42789
42919
  const code = err.code;
42790
- if ((code === "EEXIST" || code === "ENOTEMPTY") && fs90.existsSync(dir))
42920
+ if ((code === "EEXIST" || code === "ENOTEMPTY") && fs91.existsSync(dir))
42791
42921
  return false;
42792
42922
  throw err;
42793
42923
  }
@@ -42831,7 +42961,7 @@ async function runViewSetup(base, sessionDir, deps = SYSTEM_SETUP) {
42831
42961
  const left = mountLayers(base, deps.mountinfo());
42832
42962
  if (left > 0)
42833
42963
  throw new Error(`view setup: ${base} still has ${left} mount(s) after ${MAX_UMOUNTS} \xD7 umount -l`);
42834
- if (fs90.existsSync(sessionDir))
42964
+ if (fs91.existsSync(sessionDir))
42835
42965
  throw new Error(`view setup: ${base} is still visible after umount -l`);
42836
42966
  }
42837
42967
  function workerEnv(src, front) {
@@ -42846,19 +42976,19 @@ function workerEnv(src, front) {
42846
42976
  return env;
42847
42977
  }
42848
42978
  async function copyMediaFile(p, root, dest, max = MAX_MEDIA_BYTES) {
42849
- if (!path95.isAbsolute(p))
42979
+ if (!path96.isAbsolute(p))
42850
42980
  return "not an absolute path";
42851
42981
  let pfd;
42852
42982
  try {
42853
- pfd = fs90.openSync(p, O_PATH);
42983
+ pfd = fs91.openSync(p, O_PATH);
42854
42984
  } catch (err) {
42855
42985
  return `cannot open (${err.code})`;
42856
42986
  }
42857
42987
  try {
42858
- const link = fs90.readlinkSync(`/proc/self/fd/${pfd}`);
42988
+ const link = fs91.readlinkSync(`/proc/self/fd/${pfd}`);
42859
42989
  if (!link.startsWith(`${root}/`))
42860
42990
  return `not under ${root}/`;
42861
- const st = fs90.fstatSync(pfd);
42991
+ const st = fs91.fstatSync(pfd);
42862
42992
  if (!st.isFile())
42863
42993
  return "not a regular file";
42864
42994
  if (st.size > max)
@@ -42885,7 +43015,7 @@ async function copyMediaFile(p, root, dest, max = MAX_MEDIA_BYTES) {
42885
43015
  await src.close();
42886
43016
  }
42887
43017
  } finally {
42888
- fs90.closeSync(pfd);
43018
+ fs91.closeSync(pfd);
42889
43019
  }
42890
43020
  }
42891
43021
  async function copyMediaLines(text6, root, dir, sid) {
@@ -42897,16 +43027,16 @@ async function copyMediaLines(text6, root, dir, sid) {
42897
43027
  out.push(line);
42898
43028
  continue;
42899
43029
  }
42900
- const sub = path95.join(dir, String(n++));
42901
- fs90.mkdirSync(sub);
42902
- const name = path95.basename(m[1]).replace(/[\x00-\x1f\x7f]/g, "_").replace(/^\.+/, "") || "file";
42903
- const dest = path95.join(sub, name);
43030
+ const sub = path96.join(dir, String(n++));
43031
+ fs91.mkdirSync(sub);
43032
+ const name = path96.basename(m[1]).replace(/[\x00-\x1f\x7f]/g, "_").replace(/^\.+/, "") || "file";
43033
+ const dest = path96.join(sub, name);
42904
43034
  const why = await copyMediaFile(m[1], root, dest).catch((err) => err.message);
42905
43035
  if (why === null) {
42906
43036
  out.push(`MEDIA:${dest}`);
42907
43037
  continue;
42908
43038
  }
42909
- fs90.rmSync(sub, { recursive: true, force: true });
43039
+ fs91.rmSync(sub, { recursive: true, force: true });
42910
43040
  console.warn(`[AgentCore] notify ${sid}: MEDIA dropped (${why}): ${JSON.stringify(m[1].slice(0, 300))}`);
42911
43041
  }
42912
43042
  return out.join("\n");
@@ -42950,7 +43080,7 @@ function readBody(req, max) {
42950
43080
  });
42951
43081
  }
42952
43082
  async function startAgentCoreFront(o) {
42953
- const base = fs90.realpathSync(o.base);
43083
+ const base = fs91.realpathSync(o.base);
42954
43084
  const workerPort = o.workerPort ?? WORKER_PORT;
42955
43085
  const token = crypto16.randomBytes(32).toString("hex");
42956
43086
  const isMounted = o.isMounted ?? ((b) => mountLayers(b, readMountinfo()) > 0);
@@ -43012,11 +43142,11 @@ async function startAgentCoreFront(o) {
43012
43142
  preparing++;
43013
43143
  let dir = "";
43014
43144
  const cleanup = () => {
43015
- fs90.rmSync(dir, { recursive: true, force: true });
43145
+ fs91.rmSync(dir, { recursive: true, force: true });
43016
43146
  settle();
43017
43147
  };
43018
43148
  try {
43019
- dir = fs90.mkdtempSync(path95.join(os11.tmpdir(), "halo-notify-"));
43149
+ dir = fs91.mkdtempSync(path96.join(os12.tmpdir(), "halo-notify-"));
43020
43150
  const text6 = await copyMediaLines(b.text, viewRoot, dir, b.session);
43021
43151
  runNotify(cmd, text6, { HALO_SESSION_ID: b.session, HALO_RUN_STATUS: b.status, HALO_WORKSPACE: dir }, dir, cleanup);
43022
43152
  } catch (err) {
@@ -43031,7 +43161,7 @@ async function startAgentCoreFront(o) {
43031
43161
  const activate = async (sid) => {
43032
43162
  if (!isMounted(base))
43033
43163
  throw Object.assign(new Error(`${base} is not a mount point (the EFS not mounted yet, or HALO_WORKSPACE is not its mount path) \u2014 refusing to serve the image's empty dir`), { status: 503 });
43034
- const sessionDir = path95.join(base, sid);
43164
+ const sessionDir = path96.join(base, sid);
43035
43165
  if (ensureSessionDir(base, sid, { uid: WORKER_UID, gid: WORKER_GID }))
43036
43166
  console.log(`[AgentCore] front: created ${sessionDir}`);
43037
43167
  try {
@@ -43186,7 +43316,7 @@ async function runAgentCoreFront(o) {
43186
43316
  throw new Error("HALO_AGENTCORE_SESSION_DIRS=1 needs root (bind mount, umount); the worker drops to an unprivileged uid itself");
43187
43317
  if (o.port === WORKER_PORT)
43188
43318
  throw new Error(`port ${WORKER_PORT} is the worker's loopback port \u2014 pick another HALO_PORT`);
43189
- const base = path95.resolve(o.base);
43319
+ const base = path96.resolve(o.base);
43190
43320
  const overlaps = (a, b) => a === b || a.startsWith(b === "/" ? "/" : `${b}/`);
43191
43321
  if (overlaps(WORKER_ROOT, base) || overlaps(base, WORKER_ROOT))
43192
43322
  throw new Error(`HALO_WORKSPACE (${base}) must not overlap ${WORKER_ROOT}`);
@@ -43233,7 +43363,7 @@ var init_agentcore_front = __esm({
43233
43363
  MAX_MEDIA_BYTES = 20 * 1024 * 1024;
43234
43364
  O_PATH = 2097152;
43235
43365
  execFileP = promisify3(execFile2);
43236
- readMountinfo = () => fs90.readFileSync("/proc/self/mountinfo", "utf8");
43366
+ readMountinfo = () => fs91.readFileSync("/proc/self/mountinfo", "utf8");
43237
43367
  SYSTEM_SETUP = {
43238
43368
  mountinfo: readMountinfo,
43239
43369
  exec: (argv) => execFileP(argv[0], argv.slice(1), { timeout: SETUP_TIMEOUT_MS })
@@ -43413,8 +43543,8 @@ var init_halo_client = __esm({
43413
43543
  }
43414
43544
  return await res.json();
43415
43545
  }
43416
- sessionUrl(path98, workspace, sessionId) {
43417
- const url = new URL(`${this.opts.baseUrl}${path98}`);
43546
+ sessionUrl(path99, workspace, sessionId) {
43547
+ const url = new URL(`${this.opts.baseUrl}${path99}`);
43418
43548
  url.searchParams.set("workspace", workspace);
43419
43549
  url.searchParams.set("sessionId", sessionId);
43420
43550
  return url;
@@ -43562,7 +43692,7 @@ var init_version = __esm({
43562
43692
  });
43563
43693
 
43564
43694
  // ../acp-adapter/dist/adapter.js
43565
- import path96 from "node:path";
43695
+ import path97 from "node:path";
43566
43696
  function composePrompt(blocks) {
43567
43697
  const segments = [];
43568
43698
  let run = "";
@@ -43755,7 +43885,7 @@ var init_adapter = __esm({
43755
43885
  if (cursor !== void 0 && !/^\d+$/.test(cursor))
43756
43886
  throw newError(`invalid cursor: ${cursor}`, -32602);
43757
43887
  const page = await this.client.listSessions(this.config.workspace, cursor === void 0 ? void 0 : Number(cursor));
43758
- if (p.cwd !== void 0 && path96.resolve(p.cwd) !== path96.resolve(page.workspace))
43888
+ if (p.cwd !== void 0 && path97.resolve(p.cwd) !== path97.resolve(page.workspace))
43759
43889
  return { sessions: [] };
43760
43890
  return {
43761
43891
  sessions: page.sessions.map((s) => ({
@@ -44369,8 +44499,8 @@ process.emitWarning = (warning, ...args) => {
44369
44499
 
44370
44500
  // src/index.ts
44371
44501
  init_server_supervisor();
44372
- import path97 from "node:path";
44373
- import fs91 from "node:fs";
44502
+ import path98 from "node:path";
44503
+ import fs92 from "node:fs";
44374
44504
  import { homedir as homedir27, userInfo } from "node:os";
44375
44505
  import { parseArgs as parseArgs2 } from "node:util";
44376
44506
 
@@ -44661,7 +44791,7 @@ function installUserUnit(opts, run = runCommand) {
44661
44791
  }
44662
44792
 
44663
44793
  // src/index.ts
44664
- var VERSION = "2.2.4";
44794
+ var VERSION = "2.2.5";
44665
44795
  var HELP_TOP = `Usage: halo <command> [options]
44666
44796
 
44667
44797
  Commands:
@@ -45028,8 +45158,8 @@ async function cmdSetup(argv = []) {
45028
45158
  const { buildBindProviderPlan: buildBindProviderPlan2, envKeyPlaceholders: envKeyPlaceholders2, KEEP_CURRENT: KEEP_CURRENT2, AWS_CHAIN_PROVIDER: AWS_CHAIN_PROVIDER2 } = await Promise.resolve().then(() => (init_setup_bind_provider(), setup_bind_provider_exports));
45029
45159
  const { promptText: promptText2, promptPassword: promptPassword2, promptSelect: promptSelect2, promptMultiSelect: promptMultiSelect2 } = await Promise.resolve().then(() => (init_setup_prompts(), setup_prompts_exports));
45030
45160
  const nonInteractive = argv.includes("--non-interactive") || argv.includes("-y");
45031
- const haloHome2 = path97.join(homedir27(), ".halo");
45032
- const globalDir2 = path97.join(haloHome2, "global");
45161
+ const haloHome2 = path98.join(homedir27(), ".halo");
45162
+ const globalDir2 = path98.join(haloHome2, "global");
45033
45163
  ensureHaloHome2(haloHome2);
45034
45164
  process.stderr.write(`[setup] ${haloHome2}/ ready
45035
45165
  `);
@@ -45382,7 +45512,7 @@ async function cmdUpgrade() {
45382
45512
  `);
45383
45513
  process.exit(1);
45384
45514
  }
45385
- const broken = verifyNativeModules2(path97.join(rootDir, PKG));
45515
+ const broken = verifyNativeModules2(path98.join(rootDir, PKG));
45386
45516
  if (broken.length > 0) {
45387
45517
  process.stderr.write(
45388
45518
  `
@@ -45413,7 +45543,7 @@ halo: upgrade failed (npm exited ${install.status}). ${hint}
45413
45543
  async function cmdAgents(flags) {
45414
45544
  const { initRuntime: initRuntime2, listAgents: listAgents2 } = await Promise.resolve().then(() => (init_harness(), harness_exports));
45415
45545
  await initRuntime2();
45416
- const workspace = path97.resolve(flags.workspace ?? process.cwd());
45546
+ const workspace = path98.resolve(flags.workspace ?? process.cwd());
45417
45547
  const agents = await listAgents2(workspace);
45418
45548
  if (agents.length === 0) {
45419
45549
  process.stderr.write("No agents found.\n");
@@ -45436,12 +45566,12 @@ ${HELP_SESSIONS}`);
45436
45566
  process.exitCode = 1;
45437
45567
  return;
45438
45568
  }
45439
- await cmdSessionsMigrate(path97.resolve(flags.workspace ?? process.cwd()));
45569
+ await cmdSessionsMigrate(path98.resolve(flags.workspace ?? process.cwd()));
45440
45570
  return;
45441
45571
  }
45442
45572
  const { initRuntime: initRuntime2, listSessions: listSessions2 } = await Promise.resolve().then(() => (init_harness(), harness_exports));
45443
45573
  await initRuntime2();
45444
- const workspace = path97.resolve(flags.workspace ?? process.cwd());
45574
+ const workspace = path98.resolve(flags.workspace ?? process.cwd());
45445
45575
  const sessions = listSessions2(workspace);
45446
45576
  if (sessions.length === 0) {
45447
45577
  process.stderr.write("No sessions found.\n");
@@ -45455,7 +45585,7 @@ ${HELP_SESSIONS}`);
45455
45585
  }
45456
45586
  }
45457
45587
  async function cmdSessionsMigrate(workspace) {
45458
- if (!fs91.existsSync(path97.join(workspace, ".halo"))) {
45588
+ if (!fs92.existsSync(path98.join(workspace, ".halo"))) {
45459
45589
  process.stderr.write(`Not a Halo workspace (no .halo/): ${workspace}
45460
45590
  `);
45461
45591
  process.exitCode = 1;
@@ -45487,7 +45617,7 @@ async function cmdModels(argv) {
45487
45617
  process.exitCode = 1;
45488
45618
  return;
45489
45619
  }
45490
- const plan = mod.planModelsInstall(path97.resolve(dir));
45620
+ const plan = mod.planModelsInstall(path98.resolve(dir));
45491
45621
  for (const line of mod.formatPlan(plan)) process.stdout.write(`${line}
45492
45622
  `);
45493
45623
  if (plan.needsConfirm && !values.yes) {
@@ -45596,11 +45726,11 @@ ${stdinContent}` : stdinContent;
45596
45726
  harness.destroy();
45597
45727
  }
45598
45728
  }
45599
- var SERVER_LOCK_PATH = path97.join(homedir27(), ".halo", "global", "server.lock");
45600
- var SERVER_LOG_PATH = path97.join(homedir27(), ".halo", "logs", "server.log");
45729
+ var SERVER_LOCK_PATH = path98.join(homedir27(), ".halo", "global", "server.lock");
45730
+ var SERVER_LOG_PATH = path98.join(homedir27(), ".halo", "logs", "server.log");
45601
45731
  function readServerPid() {
45602
45732
  try {
45603
- const txt = fs91.readFileSync(SERVER_LOCK_PATH, "utf-8").trim();
45733
+ const txt = fs92.readFileSync(SERVER_LOCK_PATH, "utf-8").trim();
45604
45734
  const n = parseInt(txt, 10);
45605
45735
  return Number.isFinite(n) && n > 0 ? n : null;
45606
45736
  } catch {
@@ -45707,8 +45837,8 @@ async function cmdServerStart(argv, restart) {
45707
45837
  }
45708
45838
  if (plan.note) writeDim(plan.note);
45709
45839
  const { spawn: spawn7 } = await import("node:child_process");
45710
- fs91.mkdirSync(path97.dirname(SERVER_LOG_PATH), { recursive: true });
45711
- const out = fs91.openSync(SERVER_LOG_PATH, "a");
45840
+ fs92.mkdirSync(path98.dirname(SERVER_LOG_PATH), { recursive: true });
45841
+ const out = fs92.openSync(SERVER_LOG_PATH, "a");
45712
45842
  const child = spawn7(process.argv[0], [process.argv[1], "server", "start"], {
45713
45843
  detached: true,
45714
45844
  stdio: ["ignore", out, out],
@@ -45789,8 +45919,8 @@ ${HELP_AGENTCORE}`);
45789
45919
  process.exitCode = 1;
45790
45920
  return;
45791
45921
  }
45792
- const workspace = path97.resolve(raw);
45793
- if (!fs91.statSync(workspace, { throwIfNoEntry: false })?.isDirectory()) {
45922
+ const workspace = path98.resolve(raw);
45923
+ if (!fs92.statSync(workspace, { throwIfNoEntry: false })?.isDirectory()) {
45794
45924
  process.stderr.write(`Workspace is not a directory: ${workspace}
45795
45925
  `);
45796
45926
  process.exitCode = 1;
@@ -45901,7 +46031,7 @@ async function cmdServerLogs(argv) {
45901
46031
  lines: { type: "string", short: "n" }
45902
46032
  }
45903
46033
  });
45904
- if (!fs91.existsSync(SERVER_LOG_PATH)) {
46034
+ if (!fs92.existsSync(SERVER_LOG_PATH)) {
45905
46035
  process.stderr.write(`No log file at ${SERVER_LOG_PATH}
45906
46036
  `);
45907
46037
  return;
@@ -45919,7 +46049,7 @@ function exitMissingSetup() {
45919
46049
  process.exit(1);
45920
46050
  }
45921
46051
  function isHaloHomeReady() {
45922
- return fs91.existsSync(path97.join(homedir27(), ".halo", "global", ".template-version"));
46052
+ return fs92.existsSync(path98.join(homedir27(), ".halo", "global", ".template-version"));
45923
46053
  }
45924
46054
  async function main2() {
45925
46055
  const argv = process.argv.slice(2);