@turmind/halo 2.0.4 → 2.0.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
@@ -15857,7 +15857,7 @@ async function initObservability(haloProcess = "server") {
15857
15857
  return true;
15858
15858
  }
15859
15859
  const { registerSdk: registerSdk2 } = await Promise.resolve().then(() => (init_otel_sdk(), otel_sdk_exports));
15860
- providers = await registerSdk2(process.env.OTEL_SERVICE_NAME, "2.0.4", haloProcess);
15860
+ providers = await registerSdk2(process.env.OTEL_SERVICE_NAME, "2.0.5", haloProcess);
15861
15861
  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})`);
15862
15862
  return true;
15863
15863
  }
@@ -31001,7 +31001,7 @@ function buildCard(workspace, interfaceUrl, caps) {
31001
31001
  return {
31002
31002
  name: raw.name,
31003
31003
  description: raw.description,
31004
- version: typeof raw.version === "string" ? raw.version : "2.0.4",
31004
+ version: typeof raw.version === "string" ? raw.version : "2.0.5",
31005
31005
  supportedInterfaces: [{ url: interfaceUrl, protocolBinding: "JSONRPC", protocolVersion: A2A_VERSION }],
31006
31006
  capabilities: { streaming: caps.streaming, pushNotifications: true, extendedAgentCard: false },
31007
31007
  ...caps.tokenAuth === false ? {} : {
@@ -33760,7 +33760,7 @@ function createCoreChecker(opts) {
33760
33760
  }
33761
33761
  function getCoreStatus(force) {
33762
33762
  checker ??= createCoreChecker({
33763
- haloVersion: "2.0.4",
33763
+ haloVersion: "2.0.5",
33764
33764
  fetchLatest: fetchNpmLatest,
33765
33765
  onChange: (status) => broadcast({ type: "updates:changed", scope: "core", status })
33766
33766
  });
@@ -33928,7 +33928,7 @@ function hubBase() {
33928
33928
  }
33929
33929
  function serverChecker() {
33930
33930
  checker2 ??= createExtensionsChecker({
33931
- haloVersion: "2.0.4",
33931
+ haloVersion: "2.0.5",
33932
33932
  installed: () => {
33933
33933
  const s = getSnapshot();
33934
33934
  return [...s.extensions, ...s.disabled];
@@ -34627,29 +34627,48 @@ var init_ticker = __esm({
34627
34627
  });
34628
34628
 
34629
34629
  // ../server/dist/evolution/spawn.js
34630
+ import fs75 from "node:fs";
34630
34631
  import path83 from "node:path";
34631
34632
  import { spawn as spawn5 } from "node:child_process";
34632
34633
  import { fileURLToPath as fileURLToPath2 } from "node:url";
34634
+ function spawnEvoWrapper(wrapperPath, mode, id) {
34635
+ fs75.mkdirSync(evoLogsDir(), { recursive: true });
34636
+ const logPath = mode === "run" ? evoWrapperLogFile(id) : evoApplyLogFile(id);
34637
+ const logFd = fs75.openSync(logPath, "a");
34638
+ let child;
34639
+ try {
34640
+ child = spawn5(process.execPath, [wrapperPath, `--mode=${mode}`, `--id=${id}`], {
34641
+ detached: true,
34642
+ stdio: ["ignore", "ignore", logFd],
34643
+ env: cleanChildEnv(),
34644
+ // Without this, a detached console process on Windows gets a freshly
34645
+ // allocated console window (a black box pops up for every evo/score/apply
34646
+ // run). cron doesn't hit this — it spawns the cli inline, not via a
34647
+ // detached wrapper. No-op on macOS/Linux.
34648
+ windowsHide: true
34649
+ });
34650
+ } finally {
34651
+ fs75.closeSync(logFd);
34652
+ }
34653
+ child.once("exit", (code, signal) => {
34654
+ if (code === 0)
34655
+ return;
34656
+ console.error(`[EvoSpawn] ${mode} wrapper pid=${child.pid} id=${id} exited code=${code} signal=${signal} \u2014 see ${logPath}`);
34657
+ });
34658
+ child.unref();
34659
+ console.log(`[EvoSpawn] launched ${mode} wrapper pid=${child.pid} id=${id}`);
34660
+ return child;
34661
+ }
34633
34662
  var __dirname2, WRAPPER_PATH, realEvoSpawner;
34634
34663
  var init_spawn = __esm({
34635
34664
  "../server/dist/evolution/spawn.js"() {
34636
34665
  "use strict";
34637
34666
  init_child_env();
34667
+ init_paths();
34638
34668
  __dirname2 = path83.dirname(fileURLToPath2(import.meta.url));
34639
34669
  WRAPPER_PATH = path83.resolve(__dirname2, "evo-wrapper.js");
34640
34670
  realEvoSpawner = (mode, id) => {
34641
- const child = spawn5(process.execPath, [WRAPPER_PATH, `--mode=${mode}`, `--id=${id}`], {
34642
- detached: true,
34643
- stdio: "ignore",
34644
- env: cleanChildEnv(),
34645
- // Without this, a detached console process on Windows gets a freshly
34646
- // allocated console window (a black box pops up for every evo/score/apply
34647
- // run). cron doesn't hit this — it spawns the cli inline, not via a
34648
- // detached wrapper. No-op on macOS/Linux.
34649
- windowsHide: true
34650
- });
34651
- child.unref();
34652
- console.log(`[EvoSpawn] launched ${mode} wrapper pid=${child.pid} id=${id}`);
34671
+ spawnEvoWrapper(WRAPPER_PATH, mode, id);
34653
34672
  };
34654
34673
  }
34655
34674
  });
@@ -35467,12 +35486,12 @@ var init_handler3 = __esm({
35467
35486
  });
35468
35487
 
35469
35488
  // ../server/dist/routes/channel-accounts.js
35470
- import fs75 from "node:fs";
35489
+ import fs76 from "node:fs";
35471
35490
  function accountListFields(a) {
35472
35491
  return {
35473
35492
  accountId: a.accountId,
35474
35493
  workspacePath: a.workspacePath,
35475
- workspaceMissing: !fs75.existsSync(a.workspacePath),
35494
+ workspaceMissing: !fs76.existsSync(a.workspacePath),
35476
35495
  label: a.label,
35477
35496
  enabled: a.enabled,
35478
35497
  accessLevel: a.accessLevel,
@@ -36114,7 +36133,7 @@ var init_cdn = __esm({
36114
36133
  });
36115
36134
 
36116
36135
  // ../server/dist/channels/wechat/send-media.js
36117
- import fs76 from "node:fs/promises";
36136
+ import fs77 from "node:fs/promises";
36118
36137
  import path84 from "node:path";
36119
36138
  function inferKind(filePath) {
36120
36139
  const cls = classifyMedia(filePath);
@@ -36127,7 +36146,7 @@ function inferKind(filePath) {
36127
36146
  async function sendMediaFile(params) {
36128
36147
  const { baseUrl, token, toUserId, contextToken, contextTokenAt, filePath } = params;
36129
36148
  const kind = params.kind ?? inferKind(filePath);
36130
- const plaintext = await fs76.readFile(filePath);
36149
+ const plaintext = await fs77.readFile(filePath);
36131
36150
  const prep = prepareUpload(plaintext);
36132
36151
  console.log(`[WeChat] sendMediaFile: path=${filePath} kind=${kind} rawsize=${prep.rawsize} filesize=${prep.filesize}`);
36133
36152
  const mediaType = kind === "image" ? UploadMediaType.IMAGE : kind === "video" ? UploadMediaType.VIDEO : UploadMediaType.FILE;
@@ -36328,7 +36347,7 @@ var init_login = __esm({
36328
36347
  });
36329
36348
 
36330
36349
  // ../server/dist/channels/wechat/handler.js
36331
- import fs77 from "node:fs";
36350
+ import fs78 from "node:fs";
36332
36351
  import path85 from "node:path";
36333
36352
  import QRCode from "qrcode";
36334
36353
  function wxRoute(fromUserId, contextToken, contextTokenAt) {
@@ -36759,7 +36778,7 @@ async function handleSlashCommand(args) {
36759
36778
  contextToken,
36760
36779
  filePath: tmpPath
36761
36780
  });
36762
- await fs77.promises.unlink(tmpPath).catch(() => {
36781
+ await fs78.promises.unlink(tmpPath).catch(() => {
36763
36782
  });
36764
36783
  await reply(t("wechat.qr_sent", lang, { level, path: account.workspacePath }));
36765
36784
  waitLogin({ sessionKey: login.sessionKey }).then(async (result2) => {
@@ -36840,7 +36859,7 @@ var init_handler4 = __esm({
36840
36859
  // ../server/dist/routes/wechat.js
36841
36860
  import { Hono as Hono22 } from "hono";
36842
36861
  import path86 from "node:path";
36843
- import fs78 from "node:fs";
36862
+ import fs79 from "node:fs";
36844
36863
  function createWechatRoutes(deps) {
36845
36864
  const { db: db4, channel } = deps;
36846
36865
  const app2 = new Hono22();
@@ -36849,7 +36868,7 @@ function createWechatRoutes(deps) {
36849
36868
  return {
36850
36869
  ...stripSecrets(acc),
36851
36870
  workspacePath: acc.workspacePath,
36852
- workspaceMissing: !fs78.existsSync(acc.workspacePath)
36871
+ workspaceMissing: !fs79.existsSync(acc.workspacePath)
36853
36872
  };
36854
36873
  });
36855
36874
  return c.json({ accounts });
@@ -37078,7 +37097,7 @@ var init_descriptor2 = __esm({
37078
37097
  import { Hono as Hono23 } from "hono";
37079
37098
  import { streamSSE as streamSSE3 } from "hono/streaming";
37080
37099
  import crypto12 from "node:crypto";
37081
- import fs79 from "node:fs";
37100
+ import fs80 from "node:fs";
37082
37101
  function streamWithKeepalive(c, chunks) {
37083
37102
  return streamSSE3(c, async (stream) => {
37084
37103
  const timer2 = setInterval(() => {
@@ -37283,8 +37302,8 @@ function createWebRoutes(deps) {
37283
37302
  let real;
37284
37303
  let realRoot;
37285
37304
  try {
37286
- real = fs79.realpathSync(resolved);
37287
- realRoot = fs79.realpathSync(root);
37305
+ real = fs80.realpathSync(resolved);
37306
+ realRoot = fs80.realpathSync(root);
37288
37307
  } catch {
37289
37308
  return c.json({ error: "file not found" }, 404);
37290
37309
  }
@@ -37294,7 +37313,7 @@ function createWebRoutes(deps) {
37294
37313
  if (isHiddenWorkspacePath(real, realRoot)) {
37295
37314
  return c.json({ error: "path is not accessible" }, 403);
37296
37315
  }
37297
- const stat = fs79.statSync(real);
37316
+ const stat = fs80.statSync(real);
37298
37317
  if (stat.isDirectory())
37299
37318
  return c.json({ error: "cannot serve directory" }, 400);
37300
37319
  const ext = path94.default.extname(real).toLowerCase();
@@ -37306,7 +37325,7 @@ function createWebRoutes(deps) {
37306
37325
  };
37307
37326
  const contentType = imageMimeFromExt(ext) || nonImageMimes[ext] || "application/octet-stream";
37308
37327
  const fileName = path94.default.basename(resolved);
37309
- const data = fs79.readFileSync(real);
37328
+ const data = fs80.readFileSync(real);
37310
37329
  c.header("content-type", contentType);
37311
37330
  c.header("content-disposition", `inline; filename="${fileName}"`);
37312
37331
  return c.body(data);
@@ -37528,10 +37547,10 @@ async function authTest(botToken) {
37528
37547
  return slackPost("auth.test", botToken, {});
37529
37548
  }
37530
37549
  async function uploadFile(args) {
37531
- const fs84 = await import("node:fs");
37550
+ const fs85 = await import("node:fs");
37532
37551
  const path94 = await import("node:path");
37533
37552
  const filename = args.filename ?? path94.basename(args.filePath);
37534
- const stat = fs84.statSync(args.filePath);
37553
+ const stat = fs85.statSync(args.filePath);
37535
37554
  if (!stat.isFile())
37536
37555
  throw new Error(`[slack:uploadFile] not a regular file: ${args.filePath}`);
37537
37556
  const length = stat.size;
@@ -37549,7 +37568,7 @@ async function uploadFile(args) {
37549
37568
  if (step1Parsed.ok === false || !step1Parsed.upload_url || !step1Parsed.file_id) {
37550
37569
  throw new Error(`[slack:files.getUploadURLExternal] ${step1Parsed.error ?? "unknown"}`);
37551
37570
  }
37552
- const buf = fs84.readFileSync(args.filePath);
37571
+ const buf = fs85.readFileSync(args.filePath);
37553
37572
  const step2 = await fetch(step1Parsed.upload_url, {
37554
37573
  method: "POST",
37555
37574
  body: buf
@@ -38469,9 +38488,9 @@ async function replyMessage(args) {
38469
38488
  return { message_id: parsed.data?.message_id ?? "" };
38470
38489
  }
38471
38490
  async function uploadImage(args) {
38472
- const fs84 = await import("node:fs");
38491
+ const fs85 = await import("node:fs");
38473
38492
  const path94 = await import("node:path");
38474
- const buf = fs84.readFileSync(args.filePath);
38493
+ const buf = fs85.readFileSync(args.filePath);
38475
38494
  const filename = path94.basename(args.filePath);
38476
38495
  const send2 = async (token) => {
38477
38496
  const form = new FormData();
@@ -38488,9 +38507,9 @@ async function uploadImage(args) {
38488
38507
  return { imageKey: parsed.data.image_key };
38489
38508
  }
38490
38509
  async function uploadFile2(args) {
38491
- const fs84 = await import("node:fs");
38510
+ const fs85 = await import("node:fs");
38492
38511
  const path94 = await import("node:path");
38493
- const buf = fs84.readFileSync(args.filePath);
38512
+ const buf = fs85.readFileSync(args.filePath);
38494
38513
  const filename = args.filename ?? path94.basename(args.filePath);
38495
38514
  const send2 = async (token) => {
38496
38515
  const form = new FormData();
@@ -39324,7 +39343,7 @@ var init_event_adapter5 = __esm({
39324
39343
 
39325
39344
  // ../server/dist/channels/wecom/handler.js
39326
39345
  import path89 from "node:path";
39327
- import fs80 from "node:fs/promises";
39346
+ import fs81 from "node:fs/promises";
39328
39347
  import { WSClient as WSClient2, generateReqId } from "@wecom/aibot-node-sdk";
39329
39348
  function pickConversation(body) {
39330
39349
  const userid = body.from?.userid ?? "unknown";
@@ -39450,7 +39469,7 @@ async function sendWecomMedia(args) {
39450
39469
  const ext = path89.extname(filePath).toLowerCase();
39451
39470
  const cls = classifyMedia(filePath);
39452
39471
  const type = cls === "image" && [".png", ".jpg", ".jpeg", ".gif"].includes(ext) ? "image" : cls === "video" && ext === ".mp4" ? "video" : "file";
39453
- const buf = await fs80.readFile(filePath);
39472
+ const buf = await fs81.readFile(filePath);
39454
39473
  if (buf.length > MAX_WECOM_DOWNLOAD_BYTES)
39455
39474
  throw new Error("file exceeds 20MB");
39456
39475
  const { media_id: mediaId } = await wsClient.uploadMedia(buf, { type, filename: path89.basename(filePath) });
@@ -39987,14 +40006,14 @@ import { serve } from "@hono/node-server";
39987
40006
  import { serveStatic } from "@hono/node-server/serve-static";
39988
40007
  import { WebSocketServer as WebSocketServer4 } from "ws";
39989
40008
  import path90 from "node:path";
39990
- import fs81 from "node:fs";
40009
+ import fs82 from "node:fs";
39991
40010
  import { spawnSync as spawnSync4 } from "node:child_process";
39992
40011
  import { homedir as homedir25 } from "node:os";
39993
40012
  import { fileURLToPath as fileURLToPath3 } from "node:url";
39994
40013
  function findProjectRoot() {
39995
40014
  let dir = process.cwd();
39996
40015
  for (let i = 0; i < 32; i++) {
39997
- if (fs81.existsSync(path90.join(dir, "pnpm-workspace.yaml")))
40016
+ if (fs82.existsSync(path90.join(dir, "pnpm-workspace.yaml")))
39998
40017
  return dir;
39999
40018
  const parent = path90.dirname(dir);
40000
40019
  if (parent === dir)
@@ -40006,15 +40025,15 @@ function findProjectRoot() {
40006
40025
  return process.cwd();
40007
40026
  }
40008
40027
  function acquireSingleInstanceLock(lockFile) {
40009
- fs81.mkdirSync(path90.dirname(lockFile), { recursive: true });
40010
- const fd = fs81.openSync(lockFile, fs81.constants.O_RDWR | fs81.constants.O_CREAT, 420);
40028
+ fs82.mkdirSync(path90.dirname(lockFile), { recursive: true });
40029
+ const fd = fs82.openSync(lockFile, fs82.constants.O_RDWR | fs82.constants.O_CREAT, 420);
40011
40030
  const result = spawnSync4("flock", ["-n", "3"], {
40012
40031
  stdio: ["ignore", "ignore", "ignore", fd]
40013
40032
  });
40014
40033
  if (result.error) {
40015
40034
  const content = readLockPid(fd);
40016
40035
  if (content > 0 && isProcessAlive(content)) {
40017
- fs81.closeSync(fd);
40036
+ fs82.closeSync(fd);
40018
40037
  console.error(`[Server] another halo server is already running (pid ${content}). kill it first.`);
40019
40038
  process.exit(1);
40020
40039
  }
@@ -40023,19 +40042,19 @@ function acquireSingleInstanceLock(lockFile) {
40023
40042
  if (content > 0 && !isProcessAlive(content)) {
40024
40043
  console.warn(`[Server] removing stale server.lock (pid ${content} not running)`);
40025
40044
  } else {
40026
- fs81.closeSync(fd);
40045
+ fs82.closeSync(fd);
40027
40046
  console.error(`[Server] another halo server is already running${content > 0 ? ` (pid ${content})` : ""}. kill it first.`);
40028
40047
  process.exit(1);
40029
40048
  }
40030
40049
  }
40031
- fs81.ftruncateSync(fd);
40032
- fs81.writeSync(fd, String(process.pid));
40033
- fs81.fsyncSync(fd);
40050
+ fs82.ftruncateSync(fd);
40051
+ fs82.writeSync(fd, String(process.pid));
40052
+ fs82.fsyncSync(fd);
40034
40053
  }
40035
40054
  function readLockPid(fd) {
40036
40055
  try {
40037
40056
  const buf = Buffer.alloc(32);
40038
- const n = fs81.readSync(fd, buf, 0, 32, 0);
40057
+ const n = fs82.readSync(fd, buf, 0, 32, 0);
40039
40058
  return parseInt(buf.subarray(0, n).toString("utf-8").trim(), 10) || 0;
40040
40059
  } catch {
40041
40060
  return 0;
@@ -40063,7 +40082,7 @@ function isProcessAlive(pid) {
40063
40082
  }
40064
40083
  }
40065
40084
  function readGitSha() {
40066
- if (!fs81.existsSync(path90.join(PROJECT_ROOT, "pnpm-workspace.yaml")) || !fs81.existsSync(path90.join(PROJECT_ROOT, ".git")))
40085
+ if (!fs82.existsSync(path90.join(PROJECT_ROOT, "pnpm-workspace.yaml")) || !fs82.existsSync(path90.join(PROJECT_ROOT, ".git")))
40067
40086
  return null;
40068
40087
  try {
40069
40088
  const rev = spawnSync4("git", ["rev-parse", "--short", "HEAD"], { cwd: PROJECT_ROOT, encoding: "utf-8" });
@@ -40086,10 +40105,10 @@ function resolveFrontendDir() {
40086
40105
  if (process.env.HALO_FRONTEND_DIR)
40087
40106
  return path90.resolve(process.env.HALO_FRONTEND_DIR);
40088
40107
  const bundled = path90.resolve(__dirname3, "..", "admin-out");
40089
- if (fs81.existsSync(path90.join(bundled, "index.html")))
40108
+ if (fs82.existsSync(path90.join(bundled, "index.html")))
40090
40109
  return bundled;
40091
40110
  const sibling = path90.resolve(__dirname3, "..", "..", "admin", "out");
40092
- if (fs81.existsSync(path90.join(sibling, "index.html")))
40111
+ if (fs82.existsSync(path90.join(sibling, "index.html")))
40093
40112
  return sibling;
40094
40113
  return path90.resolve(PROJECT_ROOT, "packages", "admin", "out");
40095
40114
  }
@@ -40194,11 +40213,11 @@ var init_dist2 = __esm({
40194
40213
  init_git_ssh();
40195
40214
  __dirname3 = path90.dirname(fileURLToPath3(import.meta.url));
40196
40215
  PORT = config.server.port;
40197
- HALO_VERSION = "2.0.4";
40216
+ HALO_VERSION = "2.0.5";
40198
40217
  PROJECT_ROOT = findProjectRoot();
40199
40218
  HALO_HOME4 = path90.join(homedir25(), ".halo");
40200
40219
  GIT_SHA = readGitSha();
40201
- if (!fs81.existsSync(path90.join(HALO_HOME4, "global", ".template-version"))) {
40220
+ if (!fs82.existsSync(path90.join(HALO_HOME4, "global", ".template-version"))) {
40202
40221
  process.stderr.write("\x1B[31m[Server] ~/.halo/global/ not initialized. Run `halo setup` first.\x1B[0m\n");
40203
40222
  process.exit(1);
40204
40223
  }
@@ -40300,7 +40319,7 @@ var init_dist2 = __esm({
40300
40319
  setCronSessionRegistry(registry);
40301
40320
  if (OWNS_RUNTIMES && !AGENTCORE) {
40302
40321
  for (const ws of listRunningWorkspaces()) {
40303
- if (!fs81.existsSync(path90.join(ws, ".halo")))
40322
+ if (!fs82.existsSync(path90.join(ws, ".halo")))
40304
40323
  continue;
40305
40324
  if (!claimWorkspaceRuntime(ws))
40306
40325
  continue;
@@ -40346,7 +40365,7 @@ var init_dist2 = __esm({
40346
40365
  app.get("/*", (c) => {
40347
40366
  const indexPath = path90.join(FRONTEND_DIR, "index.html");
40348
40367
  try {
40349
- const html = fs81.readFileSync(indexPath, "utf-8");
40368
+ const html = fs82.readFileSync(indexPath, "utf-8");
40350
40369
  return c.html(html);
40351
40370
  } catch {
40352
40371
  return c.text("Frontend not built. Run: cd packages/admin && npx next build", 503);
@@ -40434,7 +40453,7 @@ __export(agentcore_front_exports, {
40434
40453
  workerEnv: () => workerEnv
40435
40454
  });
40436
40455
  import http3 from "node:http";
40437
- import fs82 from "node:fs";
40456
+ import fs83 from "node:fs";
40438
40457
  import fsp2 from "node:fs/promises";
40439
40458
  import os11 from "node:os";
40440
40459
  import path91 from "node:path";
@@ -40465,39 +40484,39 @@ function skipTemplateEntry(rel) {
40465
40484
  }
40466
40485
  function chownTree(dir, owner, sid) {
40467
40486
  try {
40468
- fs82.lchownSync(dir, owner.uid, owner.gid);
40469
- for (const rel of fs82.readdirSync(dir, { recursive: true }))
40470
- fs82.lchownSync(path91.join(dir, rel), owner.uid, owner.gid);
40487
+ fs83.lchownSync(dir, owner.uid, owner.gid);
40488
+ for (const rel of fs83.readdirSync(dir, { recursive: true }))
40489
+ fs83.lchownSync(path91.join(dir, rel), owner.uid, owner.gid);
40471
40490
  } catch (err) {
40472
40491
  console.warn(`[AgentCore] front: chown ${sid} to ${owner.uid}:${owner.gid} failed (${err.message}) \u2014 serving it as is`);
40473
40492
  }
40474
40493
  }
40475
40494
  function ensureSessionDir(base, sid, owner) {
40476
40495
  const dir = path91.join(base, sid);
40477
- if (fs82.existsSync(dir))
40496
+ if (fs83.existsSync(dir))
40478
40497
  return false;
40479
40498
  const tmp = path91.join(base, `.tmp-${crypto13.randomBytes(8).toString("hex")}`);
40480
- fs82.mkdirSync(tmp, { mode: 448 });
40499
+ fs83.mkdirSync(tmp, { mode: 448 });
40481
40500
  try {
40482
40501
  const template = path91.join(base, TEMPLATE_DIR);
40483
- if (fs82.statSync(template, { throwIfNoEntry: false })?.isDirectory()) {
40484
- fs82.cpSync(template, tmp, { recursive: true, verbatimSymlinks: true, filter: (src) => !skipTemplateEntry(path91.relative(template, src)) });
40502
+ if (fs83.statSync(template, { throwIfNoEntry: false })?.isDirectory()) {
40503
+ fs83.cpSync(template, tmp, { recursive: true, verbatimSymlinks: true, filter: (src) => !skipTemplateEntry(path91.relative(template, src)) });
40485
40504
  }
40486
40505
  if (owner)
40487
40506
  chownTree(tmp, owner, sid);
40488
- if (fs82.readdirSync(tmp).length === 0) {
40489
- fs82.rmdirSync(tmp);
40490
- fs82.mkdirSync(dir, { mode: 448 });
40507
+ if (fs83.readdirSync(tmp).length === 0) {
40508
+ fs83.rmdirSync(tmp);
40509
+ fs83.mkdirSync(dir, { mode: 448 });
40491
40510
  if (owner)
40492
40511
  chownTree(dir, owner, sid);
40493
40512
  return true;
40494
40513
  }
40495
- fs82.renameSync(tmp, dir);
40514
+ fs83.renameSync(tmp, dir);
40496
40515
  return true;
40497
40516
  } catch (err) {
40498
- fs82.rmSync(tmp, { recursive: true, force: true });
40517
+ fs83.rmSync(tmp, { recursive: true, force: true });
40499
40518
  const code = err.code;
40500
- if ((code === "EEXIST" || code === "ENOTEMPTY") && fs82.existsSync(dir))
40519
+ if ((code === "EEXIST" || code === "ENOTEMPTY") && fs83.existsSync(dir))
40501
40520
  return false;
40502
40521
  throw err;
40503
40522
  }
@@ -40541,7 +40560,7 @@ async function runViewSetup(base, sessionDir, deps = SYSTEM_SETUP) {
40541
40560
  const left = mountLayers(base, deps.mountinfo());
40542
40561
  if (left > 0)
40543
40562
  throw new Error(`view setup: ${base} still has ${left} mount(s) after ${MAX_UMOUNTS} \xD7 umount -l`);
40544
- if (fs82.existsSync(sessionDir))
40563
+ if (fs83.existsSync(sessionDir))
40545
40564
  throw new Error(`view setup: ${base} is still visible after umount -l`);
40546
40565
  }
40547
40566
  function workerEnv(src, front) {
@@ -40560,15 +40579,15 @@ async function copyMediaFile(p, root, dest, max = MAX_MEDIA_BYTES) {
40560
40579
  return "not an absolute path";
40561
40580
  let pfd;
40562
40581
  try {
40563
- pfd = fs82.openSync(p, O_PATH);
40582
+ pfd = fs83.openSync(p, O_PATH);
40564
40583
  } catch (err) {
40565
40584
  return `cannot open (${err.code})`;
40566
40585
  }
40567
40586
  try {
40568
- const link = fs82.readlinkSync(`/proc/self/fd/${pfd}`);
40587
+ const link = fs83.readlinkSync(`/proc/self/fd/${pfd}`);
40569
40588
  if (!link.startsWith(`${root}/`))
40570
40589
  return `not under ${root}/`;
40571
- const st = fs82.fstatSync(pfd);
40590
+ const st = fs83.fstatSync(pfd);
40572
40591
  if (!st.isFile())
40573
40592
  return "not a regular file";
40574
40593
  if (st.size > max)
@@ -40595,7 +40614,7 @@ async function copyMediaFile(p, root, dest, max = MAX_MEDIA_BYTES) {
40595
40614
  await src.close();
40596
40615
  }
40597
40616
  } finally {
40598
- fs82.closeSync(pfd);
40617
+ fs83.closeSync(pfd);
40599
40618
  }
40600
40619
  }
40601
40620
  async function copyMediaLines(text6, root, dir, sid) {
@@ -40608,7 +40627,7 @@ async function copyMediaLines(text6, root, dir, sid) {
40608
40627
  continue;
40609
40628
  }
40610
40629
  const sub = path91.join(dir, String(n++));
40611
- fs82.mkdirSync(sub);
40630
+ fs83.mkdirSync(sub);
40612
40631
  const name = path91.basename(m[1]).replace(/[\x00-\x1f\x7f]/g, "_").replace(/^\.+/, "") || "file";
40613
40632
  const dest = path91.join(sub, name);
40614
40633
  const why = await copyMediaFile(m[1], root, dest).catch((err) => err.message);
@@ -40616,7 +40635,7 @@ async function copyMediaLines(text6, root, dir, sid) {
40616
40635
  out.push(`MEDIA:${dest}`);
40617
40636
  continue;
40618
40637
  }
40619
- fs82.rmSync(sub, { recursive: true, force: true });
40638
+ fs83.rmSync(sub, { recursive: true, force: true });
40620
40639
  console.warn(`[AgentCore] notify ${sid}: MEDIA dropped (${why}): ${JSON.stringify(m[1].slice(0, 300))}`);
40621
40640
  }
40622
40641
  return out.join("\n");
@@ -40660,7 +40679,7 @@ function readBody(req, max) {
40660
40679
  });
40661
40680
  }
40662
40681
  async function startAgentCoreFront(o) {
40663
- const base = fs82.realpathSync(o.base);
40682
+ const base = fs83.realpathSync(o.base);
40664
40683
  const workerPort = o.workerPort ?? WORKER_PORT;
40665
40684
  const token = crypto13.randomBytes(32).toString("hex");
40666
40685
  const isMounted = o.isMounted ?? ((b) => mountLayers(b, readMountinfo()) > 0);
@@ -40722,11 +40741,11 @@ async function startAgentCoreFront(o) {
40722
40741
  preparing++;
40723
40742
  let dir = "";
40724
40743
  const cleanup = () => {
40725
- fs82.rmSync(dir, { recursive: true, force: true });
40744
+ fs83.rmSync(dir, { recursive: true, force: true });
40726
40745
  settle();
40727
40746
  };
40728
40747
  try {
40729
- dir = fs82.mkdtempSync(path91.join(os11.tmpdir(), "halo-notify-"));
40748
+ dir = fs83.mkdtempSync(path91.join(os11.tmpdir(), "halo-notify-"));
40730
40749
  const text6 = await copyMediaLines(b.text, viewRoot, dir, b.session);
40731
40750
  runNotify(cmd, text6, { HALO_SESSION_ID: b.session, HALO_RUN_STATUS: b.status, HALO_WORKSPACE: dir }, dir, cleanup);
40732
40751
  } catch (err) {
@@ -40943,7 +40962,7 @@ var init_agentcore_front = __esm({
40943
40962
  MAX_MEDIA_BYTES = 20 * 1024 * 1024;
40944
40963
  O_PATH = 2097152;
40945
40964
  execFileP = promisify3(execFile2);
40946
- readMountinfo = () => fs82.readFileSync("/proc/self/mountinfo", "utf8");
40965
+ readMountinfo = () => fs83.readFileSync("/proc/self/mountinfo", "utf8");
40947
40966
  SYSTEM_SETUP = {
40948
40967
  mountinfo: readMountinfo,
40949
40968
  exec: (argv) => execFileP(argv[0], argv.slice(1), { timeout: SETUP_TIMEOUT_MS })
@@ -42081,7 +42100,7 @@ process.emitWarning = (warning, ...args) => {
42081
42100
  // src/index.ts
42082
42101
  init_server_supervisor();
42083
42102
  import path93 from "node:path";
42084
- import fs83 from "node:fs";
42103
+ import fs84 from "node:fs";
42085
42104
  import { homedir as homedir26, userInfo } from "node:os";
42086
42105
  import { parseArgs as parseArgs2 } from "node:util";
42087
42106
 
@@ -42372,7 +42391,7 @@ function installUserUnit(opts, run = runCommand) {
42372
42391
  }
42373
42392
 
42374
42393
  // src/index.ts
42375
- var VERSION = "2.0.4";
42394
+ var VERSION = "2.0.5";
42376
42395
  var HELP_TOP = `Usage: halo <command> [options]
42377
42396
 
42378
42397
  Commands:
@@ -43166,7 +43185,7 @@ ${HELP_SESSIONS}`);
43166
43185
  }
43167
43186
  }
43168
43187
  async function cmdSessionsMigrate(workspace) {
43169
- if (!fs83.existsSync(path93.join(workspace, ".halo"))) {
43188
+ if (!fs84.existsSync(path93.join(workspace, ".halo"))) {
43170
43189
  process.stderr.write(`Not a Halo workspace (no .halo/): ${workspace}
43171
43190
  `);
43172
43191
  process.exitCode = 1;
@@ -43311,7 +43330,7 @@ var SERVER_LOCK_PATH = path93.join(homedir26(), ".halo", "global", "server.lock"
43311
43330
  var SERVER_LOG_PATH = path93.join(homedir26(), ".halo", "logs", "server.log");
43312
43331
  function readServerPid() {
43313
43332
  try {
43314
- const txt = fs83.readFileSync(SERVER_LOCK_PATH, "utf-8").trim();
43333
+ const txt = fs84.readFileSync(SERVER_LOCK_PATH, "utf-8").trim();
43315
43334
  const n = parseInt(txt, 10);
43316
43335
  return Number.isFinite(n) && n > 0 ? n : null;
43317
43336
  } catch {
@@ -43418,8 +43437,8 @@ async function cmdServerStart(argv, restart) {
43418
43437
  }
43419
43438
  if (plan.note) writeDim(plan.note);
43420
43439
  const { spawn: spawn7 } = await import("node:child_process");
43421
- fs83.mkdirSync(path93.dirname(SERVER_LOG_PATH), { recursive: true });
43422
- const out = fs83.openSync(SERVER_LOG_PATH, "a");
43440
+ fs84.mkdirSync(path93.dirname(SERVER_LOG_PATH), { recursive: true });
43441
+ const out = fs84.openSync(SERVER_LOG_PATH, "a");
43423
43442
  const child = spawn7(process.argv[0], [process.argv[1], "server", "start"], {
43424
43443
  detached: true,
43425
43444
  stdio: ["ignore", out, out],
@@ -43501,7 +43520,7 @@ ${HELP_AGENTCORE}`);
43501
43520
  return;
43502
43521
  }
43503
43522
  const workspace = path93.resolve(raw);
43504
- if (!fs83.statSync(workspace, { throwIfNoEntry: false })?.isDirectory()) {
43523
+ if (!fs84.statSync(workspace, { throwIfNoEntry: false })?.isDirectory()) {
43505
43524
  process.stderr.write(`Workspace is not a directory: ${workspace}
43506
43525
  `);
43507
43526
  process.exitCode = 1;
@@ -43612,7 +43631,7 @@ async function cmdServerLogs(argv) {
43612
43631
  lines: { type: "string", short: "n" }
43613
43632
  }
43614
43633
  });
43615
- if (!fs83.existsSync(SERVER_LOG_PATH)) {
43634
+ if (!fs84.existsSync(SERVER_LOG_PATH)) {
43616
43635
  process.stderr.write(`No log file at ${SERVER_LOG_PATH}
43617
43636
  `);
43618
43637
  return;
@@ -43630,7 +43649,7 @@ function exitMissingSetup() {
43630
43649
  process.exit(1);
43631
43650
  }
43632
43651
  function isHaloHomeReady() {
43633
- return fs83.existsSync(path93.join(homedir26(), ".halo", "global", ".template-version"));
43652
+ return fs84.existsSync(path93.join(homedir26(), ".halo", "global", ".template-version"));
43634
43653
  }
43635
43654
  async function main2() {
43636
43655
  const argv = process.argv.slice(2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turmind/halo",
3
- "version": "2.0.4",
3
+ "version": "2.0.5",
4
4
  "description": "Halo — multi-agent collaborative workspace. CLI + TUI + HTTP/WS server in one package.",
5
5
  "type": "module",
6
6
  "license": "MIT",