@turmind/halo 2.0.3 → 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/admin-out/404.html +1 -1
- package/admin-out/_next/static/chunks/app/_not-found/{page-484fd244e4bc7b70.js → page-4271518f2746cf73.js} +1 -1
- package/admin-out/_next/static/chunks/app/layout-ea161287d934ba96.js +1 -0
- package/admin-out/_next/static/chunks/app/{page-faee6fbd17dc7b80.js → page-cb05cd98d8f9042a.js} +1 -1
- package/admin-out/_next/static/chunks/{main-app-42f48cb3fd4811f4.js → main-app-340a5b58ed229c4d.js} +1 -1
- package/admin-out/_next/static/chunks/{webpack-b7907e0d16faa4ca.js → webpack-74f577c1b094f942.js} +1 -1
- package/admin-out/index.html +1 -1
- package/admin-out/index.txt +4 -4
- package/bundled-docs/design/canvas-extensions.md +2 -2
- package/bundled-docs/design/evolution.md +2 -2
- package/bundled-docs/dev/api.md +1 -1
- package/bundled-docs/dev/deploy.md +1 -1
- package/dist/evo-wrapper.js +2810 -0
- package/dist/index.js +151 -97
- package/package.json +1 -1
- package/admin-out/_next/static/chunks/app/layout-3e437a977abd0081.js +0 -1
- /package/admin-out/_next/static/{P7yMYf16Q3-XqGtzCJNnw → F7kFetjUGIXr5T6aTQAtP}/_buildManifest.js +0 -0
- /package/admin-out/_next/static/{P7yMYf16Q3-XqGtzCJNnw → F7kFetjUGIXr5T6aTQAtP}/_ssgManifest.js +0 -0
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.
|
|
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
|
}
|
|
@@ -28141,6 +28141,37 @@ function classifyTranscribeError(err) {
|
|
|
28141
28141
|
return "bad-request";
|
|
28142
28142
|
return "io";
|
|
28143
28143
|
}
|
|
28144
|
+
function splitBySpeaker(text6, start3, end, items) {
|
|
28145
|
+
const counts = /* @__PURE__ */ new Map();
|
|
28146
|
+
for (const i of items)
|
|
28147
|
+
if (i.Type === "pronunciation" && i.Speaker !== void 0)
|
|
28148
|
+
counts.set(i.Speaker, (counts.get(i.Speaker) ?? 0) + 1);
|
|
28149
|
+
if (counts.size === 0)
|
|
28150
|
+
return [{ text: text6, start: start3, end }];
|
|
28151
|
+
if (counts.size === 1)
|
|
28152
|
+
return [{ text: text6, start: start3, end, speaker: [...counts.keys()][0] }];
|
|
28153
|
+
const runs = [];
|
|
28154
|
+
let cursor = 0;
|
|
28155
|
+
for (const item of items) {
|
|
28156
|
+
const content = item.Content ?? "";
|
|
28157
|
+
const at = text6.indexOf(content, cursor);
|
|
28158
|
+
if (at < 0) {
|
|
28159
|
+
let top = "";
|
|
28160
|
+
for (const [s, n] of counts)
|
|
28161
|
+
if (n > (counts.get(top) ?? 0))
|
|
28162
|
+
top = s;
|
|
28163
|
+
return [{ text: text6, start: start3, end, speaker: top }];
|
|
28164
|
+
}
|
|
28165
|
+
cursor = at + content.length;
|
|
28166
|
+
const run = runs.at(-1);
|
|
28167
|
+
if (item.Type === "pronunciation" && item.Speaker !== void 0 && item.Speaker !== run?.speaker) {
|
|
28168
|
+
runs.push({ at: run ? at : 0, speaker: item.Speaker, start: (run ? item : items[0]).StartTime ?? start3, end: item.EndTime ?? end });
|
|
28169
|
+
} else if (run) {
|
|
28170
|
+
run.end = item.EndTime ?? run.end;
|
|
28171
|
+
}
|
|
28172
|
+
}
|
|
28173
|
+
return runs.map((r, k) => ({ text: text6.slice(r.at, runs[k + 1]?.at ?? text6.length).trim(), start: r.start, end: r.end, speaker: r.speaker })).filter((s) => s.text);
|
|
28174
|
+
}
|
|
28144
28175
|
function extParam(extId, key, fallback) {
|
|
28145
28176
|
const declared = getExtension(extId)?.settings?.params?.find((f) => f.key === key)?.default;
|
|
28146
28177
|
return getServerParam(`ext-${extId}`, key) || declared || fallback;
|
|
@@ -28275,20 +28306,24 @@ function createTranscribeProxy(deps = {}) {
|
|
|
28275
28306
|
...languageOpts,
|
|
28276
28307
|
MediaEncoding: "pcm",
|
|
28277
28308
|
MediaSampleRateHertz: 16e3,
|
|
28309
|
+
ShowSpeakerLabel: true,
|
|
28278
28310
|
AudioStream: audio()
|
|
28279
28311
|
}), { abortSignal: abort.signal });
|
|
28280
28312
|
for await (const ev of res.TranscriptResultStream ?? []) {
|
|
28281
28313
|
for (const r of ev.TranscriptEvent?.Transcript?.Results ?? []) {
|
|
28282
|
-
const
|
|
28314
|
+
const alt = r.Alternatives?.[0];
|
|
28315
|
+
const text6 = alt?.Transcript ?? "";
|
|
28283
28316
|
if (!text6)
|
|
28284
28317
|
continue;
|
|
28285
|
-
|
|
28286
|
-
|
|
28287
|
-
|
|
28288
|
-
|
|
28289
|
-
text: text6,
|
|
28290
|
-
|
|
28291
|
-
}
|
|
28318
|
+
const start3 = r.StartTime ?? 0;
|
|
28319
|
+
const end = r.EndTime ?? 0;
|
|
28320
|
+
const lang2 = r.LanguageCode ?? ("code" in langSpec ? langSpec.code : "");
|
|
28321
|
+
if (r.IsPartial) {
|
|
28322
|
+
send2({ type: "partial", start: start3, end, text: text6, lang: lang2 });
|
|
28323
|
+
continue;
|
|
28324
|
+
}
|
|
28325
|
+
for (const s of splitBySpeaker(text6, start3, end, alt?.Items ?? []))
|
|
28326
|
+
send2({ type: "final", ...s, lang: lang2 });
|
|
28292
28327
|
}
|
|
28293
28328
|
}
|
|
28294
28329
|
if (!closed)
|
|
@@ -30966,7 +31001,7 @@ function buildCard(workspace, interfaceUrl, caps) {
|
|
|
30966
31001
|
return {
|
|
30967
31002
|
name: raw.name,
|
|
30968
31003
|
description: raw.description,
|
|
30969
|
-
version: typeof raw.version === "string" ? raw.version : "2.0.
|
|
31004
|
+
version: typeof raw.version === "string" ? raw.version : "2.0.5",
|
|
30970
31005
|
supportedInterfaces: [{ url: interfaceUrl, protocolBinding: "JSONRPC", protocolVersion: A2A_VERSION }],
|
|
30971
31006
|
capabilities: { streaming: caps.streaming, pushNotifications: true, extendedAgentCard: false },
|
|
30972
31007
|
...caps.tokenAuth === false ? {} : {
|
|
@@ -33725,7 +33760,7 @@ function createCoreChecker(opts) {
|
|
|
33725
33760
|
}
|
|
33726
33761
|
function getCoreStatus(force) {
|
|
33727
33762
|
checker ??= createCoreChecker({
|
|
33728
|
-
haloVersion: "2.0.
|
|
33763
|
+
haloVersion: "2.0.5",
|
|
33729
33764
|
fetchLatest: fetchNpmLatest,
|
|
33730
33765
|
onChange: (status) => broadcast({ type: "updates:changed", scope: "core", status })
|
|
33731
33766
|
});
|
|
@@ -33893,7 +33928,7 @@ function hubBase() {
|
|
|
33893
33928
|
}
|
|
33894
33929
|
function serverChecker() {
|
|
33895
33930
|
checker2 ??= createExtensionsChecker({
|
|
33896
|
-
haloVersion: "2.0.
|
|
33931
|
+
haloVersion: "2.0.5",
|
|
33897
33932
|
installed: () => {
|
|
33898
33933
|
const s = getSnapshot();
|
|
33899
33934
|
return [...s.extensions, ...s.disabled];
|
|
@@ -34592,29 +34627,48 @@ var init_ticker = __esm({
|
|
|
34592
34627
|
});
|
|
34593
34628
|
|
|
34594
34629
|
// ../server/dist/evolution/spawn.js
|
|
34630
|
+
import fs75 from "node:fs";
|
|
34595
34631
|
import path83 from "node:path";
|
|
34596
34632
|
import { spawn as spawn5 } from "node:child_process";
|
|
34597
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
|
+
}
|
|
34598
34662
|
var __dirname2, WRAPPER_PATH, realEvoSpawner;
|
|
34599
34663
|
var init_spawn = __esm({
|
|
34600
34664
|
"../server/dist/evolution/spawn.js"() {
|
|
34601
34665
|
"use strict";
|
|
34602
34666
|
init_child_env();
|
|
34667
|
+
init_paths();
|
|
34603
34668
|
__dirname2 = path83.dirname(fileURLToPath2(import.meta.url));
|
|
34604
34669
|
WRAPPER_PATH = path83.resolve(__dirname2, "evo-wrapper.js");
|
|
34605
34670
|
realEvoSpawner = (mode, id) => {
|
|
34606
|
-
|
|
34607
|
-
detached: true,
|
|
34608
|
-
stdio: "ignore",
|
|
34609
|
-
env: cleanChildEnv(),
|
|
34610
|
-
// Without this, a detached console process on Windows gets a freshly
|
|
34611
|
-
// allocated console window (a black box pops up for every evo/score/apply
|
|
34612
|
-
// run). cron doesn't hit this — it spawns the cli inline, not via a
|
|
34613
|
-
// detached wrapper. No-op on macOS/Linux.
|
|
34614
|
-
windowsHide: true
|
|
34615
|
-
});
|
|
34616
|
-
child.unref();
|
|
34617
|
-
console.log(`[EvoSpawn] launched ${mode} wrapper pid=${child.pid} id=${id}`);
|
|
34671
|
+
spawnEvoWrapper(WRAPPER_PATH, mode, id);
|
|
34618
34672
|
};
|
|
34619
34673
|
}
|
|
34620
34674
|
});
|
|
@@ -35432,12 +35486,12 @@ var init_handler3 = __esm({
|
|
|
35432
35486
|
});
|
|
35433
35487
|
|
|
35434
35488
|
// ../server/dist/routes/channel-accounts.js
|
|
35435
|
-
import
|
|
35489
|
+
import fs76 from "node:fs";
|
|
35436
35490
|
function accountListFields(a) {
|
|
35437
35491
|
return {
|
|
35438
35492
|
accountId: a.accountId,
|
|
35439
35493
|
workspacePath: a.workspacePath,
|
|
35440
|
-
workspaceMissing: !
|
|
35494
|
+
workspaceMissing: !fs76.existsSync(a.workspacePath),
|
|
35441
35495
|
label: a.label,
|
|
35442
35496
|
enabled: a.enabled,
|
|
35443
35497
|
accessLevel: a.accessLevel,
|
|
@@ -36079,7 +36133,7 @@ var init_cdn = __esm({
|
|
|
36079
36133
|
});
|
|
36080
36134
|
|
|
36081
36135
|
// ../server/dist/channels/wechat/send-media.js
|
|
36082
|
-
import
|
|
36136
|
+
import fs77 from "node:fs/promises";
|
|
36083
36137
|
import path84 from "node:path";
|
|
36084
36138
|
function inferKind(filePath) {
|
|
36085
36139
|
const cls = classifyMedia(filePath);
|
|
@@ -36092,7 +36146,7 @@ function inferKind(filePath) {
|
|
|
36092
36146
|
async function sendMediaFile(params) {
|
|
36093
36147
|
const { baseUrl, token, toUserId, contextToken, contextTokenAt, filePath } = params;
|
|
36094
36148
|
const kind = params.kind ?? inferKind(filePath);
|
|
36095
|
-
const plaintext = await
|
|
36149
|
+
const plaintext = await fs77.readFile(filePath);
|
|
36096
36150
|
const prep = prepareUpload(plaintext);
|
|
36097
36151
|
console.log(`[WeChat] sendMediaFile: path=${filePath} kind=${kind} rawsize=${prep.rawsize} filesize=${prep.filesize}`);
|
|
36098
36152
|
const mediaType = kind === "image" ? UploadMediaType.IMAGE : kind === "video" ? UploadMediaType.VIDEO : UploadMediaType.FILE;
|
|
@@ -36293,7 +36347,7 @@ var init_login = __esm({
|
|
|
36293
36347
|
});
|
|
36294
36348
|
|
|
36295
36349
|
// ../server/dist/channels/wechat/handler.js
|
|
36296
|
-
import
|
|
36350
|
+
import fs78 from "node:fs";
|
|
36297
36351
|
import path85 from "node:path";
|
|
36298
36352
|
import QRCode from "qrcode";
|
|
36299
36353
|
function wxRoute(fromUserId, contextToken, contextTokenAt) {
|
|
@@ -36724,7 +36778,7 @@ async function handleSlashCommand(args) {
|
|
|
36724
36778
|
contextToken,
|
|
36725
36779
|
filePath: tmpPath
|
|
36726
36780
|
});
|
|
36727
|
-
await
|
|
36781
|
+
await fs78.promises.unlink(tmpPath).catch(() => {
|
|
36728
36782
|
});
|
|
36729
36783
|
await reply(t("wechat.qr_sent", lang, { level, path: account.workspacePath }));
|
|
36730
36784
|
waitLogin({ sessionKey: login.sessionKey }).then(async (result2) => {
|
|
@@ -36805,7 +36859,7 @@ var init_handler4 = __esm({
|
|
|
36805
36859
|
// ../server/dist/routes/wechat.js
|
|
36806
36860
|
import { Hono as Hono22 } from "hono";
|
|
36807
36861
|
import path86 from "node:path";
|
|
36808
|
-
import
|
|
36862
|
+
import fs79 from "node:fs";
|
|
36809
36863
|
function createWechatRoutes(deps) {
|
|
36810
36864
|
const { db: db4, channel } = deps;
|
|
36811
36865
|
const app2 = new Hono22();
|
|
@@ -36814,7 +36868,7 @@ function createWechatRoutes(deps) {
|
|
|
36814
36868
|
return {
|
|
36815
36869
|
...stripSecrets(acc),
|
|
36816
36870
|
workspacePath: acc.workspacePath,
|
|
36817
|
-
workspaceMissing: !
|
|
36871
|
+
workspaceMissing: !fs79.existsSync(acc.workspacePath)
|
|
36818
36872
|
};
|
|
36819
36873
|
});
|
|
36820
36874
|
return c.json({ accounts });
|
|
@@ -37043,7 +37097,7 @@ var init_descriptor2 = __esm({
|
|
|
37043
37097
|
import { Hono as Hono23 } from "hono";
|
|
37044
37098
|
import { streamSSE as streamSSE3 } from "hono/streaming";
|
|
37045
37099
|
import crypto12 from "node:crypto";
|
|
37046
|
-
import
|
|
37100
|
+
import fs80 from "node:fs";
|
|
37047
37101
|
function streamWithKeepalive(c, chunks) {
|
|
37048
37102
|
return streamSSE3(c, async (stream) => {
|
|
37049
37103
|
const timer2 = setInterval(() => {
|
|
@@ -37248,8 +37302,8 @@ function createWebRoutes(deps) {
|
|
|
37248
37302
|
let real;
|
|
37249
37303
|
let realRoot;
|
|
37250
37304
|
try {
|
|
37251
|
-
real =
|
|
37252
|
-
realRoot =
|
|
37305
|
+
real = fs80.realpathSync(resolved);
|
|
37306
|
+
realRoot = fs80.realpathSync(root);
|
|
37253
37307
|
} catch {
|
|
37254
37308
|
return c.json({ error: "file not found" }, 404);
|
|
37255
37309
|
}
|
|
@@ -37259,7 +37313,7 @@ function createWebRoutes(deps) {
|
|
|
37259
37313
|
if (isHiddenWorkspacePath(real, realRoot)) {
|
|
37260
37314
|
return c.json({ error: "path is not accessible" }, 403);
|
|
37261
37315
|
}
|
|
37262
|
-
const stat =
|
|
37316
|
+
const stat = fs80.statSync(real);
|
|
37263
37317
|
if (stat.isDirectory())
|
|
37264
37318
|
return c.json({ error: "cannot serve directory" }, 400);
|
|
37265
37319
|
const ext = path94.default.extname(real).toLowerCase();
|
|
@@ -37271,7 +37325,7 @@ function createWebRoutes(deps) {
|
|
|
37271
37325
|
};
|
|
37272
37326
|
const contentType = imageMimeFromExt(ext) || nonImageMimes[ext] || "application/octet-stream";
|
|
37273
37327
|
const fileName = path94.default.basename(resolved);
|
|
37274
|
-
const data =
|
|
37328
|
+
const data = fs80.readFileSync(real);
|
|
37275
37329
|
c.header("content-type", contentType);
|
|
37276
37330
|
c.header("content-disposition", `inline; filename="${fileName}"`);
|
|
37277
37331
|
return c.body(data);
|
|
@@ -37493,10 +37547,10 @@ async function authTest(botToken) {
|
|
|
37493
37547
|
return slackPost("auth.test", botToken, {});
|
|
37494
37548
|
}
|
|
37495
37549
|
async function uploadFile(args) {
|
|
37496
|
-
const
|
|
37550
|
+
const fs85 = await import("node:fs");
|
|
37497
37551
|
const path94 = await import("node:path");
|
|
37498
37552
|
const filename = args.filename ?? path94.basename(args.filePath);
|
|
37499
|
-
const stat =
|
|
37553
|
+
const stat = fs85.statSync(args.filePath);
|
|
37500
37554
|
if (!stat.isFile())
|
|
37501
37555
|
throw new Error(`[slack:uploadFile] not a regular file: ${args.filePath}`);
|
|
37502
37556
|
const length = stat.size;
|
|
@@ -37514,7 +37568,7 @@ async function uploadFile(args) {
|
|
|
37514
37568
|
if (step1Parsed.ok === false || !step1Parsed.upload_url || !step1Parsed.file_id) {
|
|
37515
37569
|
throw new Error(`[slack:files.getUploadURLExternal] ${step1Parsed.error ?? "unknown"}`);
|
|
37516
37570
|
}
|
|
37517
|
-
const buf =
|
|
37571
|
+
const buf = fs85.readFileSync(args.filePath);
|
|
37518
37572
|
const step2 = await fetch(step1Parsed.upload_url, {
|
|
37519
37573
|
method: "POST",
|
|
37520
37574
|
body: buf
|
|
@@ -38434,9 +38488,9 @@ async function replyMessage(args) {
|
|
|
38434
38488
|
return { message_id: parsed.data?.message_id ?? "" };
|
|
38435
38489
|
}
|
|
38436
38490
|
async function uploadImage(args) {
|
|
38437
|
-
const
|
|
38491
|
+
const fs85 = await import("node:fs");
|
|
38438
38492
|
const path94 = await import("node:path");
|
|
38439
|
-
const buf =
|
|
38493
|
+
const buf = fs85.readFileSync(args.filePath);
|
|
38440
38494
|
const filename = path94.basename(args.filePath);
|
|
38441
38495
|
const send2 = async (token) => {
|
|
38442
38496
|
const form = new FormData();
|
|
@@ -38453,9 +38507,9 @@ async function uploadImage(args) {
|
|
|
38453
38507
|
return { imageKey: parsed.data.image_key };
|
|
38454
38508
|
}
|
|
38455
38509
|
async function uploadFile2(args) {
|
|
38456
|
-
const
|
|
38510
|
+
const fs85 = await import("node:fs");
|
|
38457
38511
|
const path94 = await import("node:path");
|
|
38458
|
-
const buf =
|
|
38512
|
+
const buf = fs85.readFileSync(args.filePath);
|
|
38459
38513
|
const filename = args.filename ?? path94.basename(args.filePath);
|
|
38460
38514
|
const send2 = async (token) => {
|
|
38461
38515
|
const form = new FormData();
|
|
@@ -39289,7 +39343,7 @@ var init_event_adapter5 = __esm({
|
|
|
39289
39343
|
|
|
39290
39344
|
// ../server/dist/channels/wecom/handler.js
|
|
39291
39345
|
import path89 from "node:path";
|
|
39292
|
-
import
|
|
39346
|
+
import fs81 from "node:fs/promises";
|
|
39293
39347
|
import { WSClient as WSClient2, generateReqId } from "@wecom/aibot-node-sdk";
|
|
39294
39348
|
function pickConversation(body) {
|
|
39295
39349
|
const userid = body.from?.userid ?? "unknown";
|
|
@@ -39415,7 +39469,7 @@ async function sendWecomMedia(args) {
|
|
|
39415
39469
|
const ext = path89.extname(filePath).toLowerCase();
|
|
39416
39470
|
const cls = classifyMedia(filePath);
|
|
39417
39471
|
const type = cls === "image" && [".png", ".jpg", ".jpeg", ".gif"].includes(ext) ? "image" : cls === "video" && ext === ".mp4" ? "video" : "file";
|
|
39418
|
-
const buf = await
|
|
39472
|
+
const buf = await fs81.readFile(filePath);
|
|
39419
39473
|
if (buf.length > MAX_WECOM_DOWNLOAD_BYTES)
|
|
39420
39474
|
throw new Error("file exceeds 20MB");
|
|
39421
39475
|
const { media_id: mediaId } = await wsClient.uploadMedia(buf, { type, filename: path89.basename(filePath) });
|
|
@@ -39952,14 +40006,14 @@ import { serve } from "@hono/node-server";
|
|
|
39952
40006
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
39953
40007
|
import { WebSocketServer as WebSocketServer4 } from "ws";
|
|
39954
40008
|
import path90 from "node:path";
|
|
39955
|
-
import
|
|
40009
|
+
import fs82 from "node:fs";
|
|
39956
40010
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
39957
40011
|
import { homedir as homedir25 } from "node:os";
|
|
39958
40012
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
39959
40013
|
function findProjectRoot() {
|
|
39960
40014
|
let dir = process.cwd();
|
|
39961
40015
|
for (let i = 0; i < 32; i++) {
|
|
39962
|
-
if (
|
|
40016
|
+
if (fs82.existsSync(path90.join(dir, "pnpm-workspace.yaml")))
|
|
39963
40017
|
return dir;
|
|
39964
40018
|
const parent = path90.dirname(dir);
|
|
39965
40019
|
if (parent === dir)
|
|
@@ -39971,15 +40025,15 @@ function findProjectRoot() {
|
|
|
39971
40025
|
return process.cwd();
|
|
39972
40026
|
}
|
|
39973
40027
|
function acquireSingleInstanceLock(lockFile) {
|
|
39974
|
-
|
|
39975
|
-
const fd =
|
|
40028
|
+
fs82.mkdirSync(path90.dirname(lockFile), { recursive: true });
|
|
40029
|
+
const fd = fs82.openSync(lockFile, fs82.constants.O_RDWR | fs82.constants.O_CREAT, 420);
|
|
39976
40030
|
const result = spawnSync4("flock", ["-n", "3"], {
|
|
39977
40031
|
stdio: ["ignore", "ignore", "ignore", fd]
|
|
39978
40032
|
});
|
|
39979
40033
|
if (result.error) {
|
|
39980
40034
|
const content = readLockPid(fd);
|
|
39981
40035
|
if (content > 0 && isProcessAlive(content)) {
|
|
39982
|
-
|
|
40036
|
+
fs82.closeSync(fd);
|
|
39983
40037
|
console.error(`[Server] another halo server is already running (pid ${content}). kill it first.`);
|
|
39984
40038
|
process.exit(1);
|
|
39985
40039
|
}
|
|
@@ -39988,19 +40042,19 @@ function acquireSingleInstanceLock(lockFile) {
|
|
|
39988
40042
|
if (content > 0 && !isProcessAlive(content)) {
|
|
39989
40043
|
console.warn(`[Server] removing stale server.lock (pid ${content} not running)`);
|
|
39990
40044
|
} else {
|
|
39991
|
-
|
|
40045
|
+
fs82.closeSync(fd);
|
|
39992
40046
|
console.error(`[Server] another halo server is already running${content > 0 ? ` (pid ${content})` : ""}. kill it first.`);
|
|
39993
40047
|
process.exit(1);
|
|
39994
40048
|
}
|
|
39995
40049
|
}
|
|
39996
|
-
|
|
39997
|
-
|
|
39998
|
-
|
|
40050
|
+
fs82.ftruncateSync(fd);
|
|
40051
|
+
fs82.writeSync(fd, String(process.pid));
|
|
40052
|
+
fs82.fsyncSync(fd);
|
|
39999
40053
|
}
|
|
40000
40054
|
function readLockPid(fd) {
|
|
40001
40055
|
try {
|
|
40002
40056
|
const buf = Buffer.alloc(32);
|
|
40003
|
-
const n =
|
|
40057
|
+
const n = fs82.readSync(fd, buf, 0, 32, 0);
|
|
40004
40058
|
return parseInt(buf.subarray(0, n).toString("utf-8").trim(), 10) || 0;
|
|
40005
40059
|
} catch {
|
|
40006
40060
|
return 0;
|
|
@@ -40028,7 +40082,7 @@ function isProcessAlive(pid) {
|
|
|
40028
40082
|
}
|
|
40029
40083
|
}
|
|
40030
40084
|
function readGitSha() {
|
|
40031
|
-
if (!
|
|
40085
|
+
if (!fs82.existsSync(path90.join(PROJECT_ROOT, "pnpm-workspace.yaml")) || !fs82.existsSync(path90.join(PROJECT_ROOT, ".git")))
|
|
40032
40086
|
return null;
|
|
40033
40087
|
try {
|
|
40034
40088
|
const rev = spawnSync4("git", ["rev-parse", "--short", "HEAD"], { cwd: PROJECT_ROOT, encoding: "utf-8" });
|
|
@@ -40051,10 +40105,10 @@ function resolveFrontendDir() {
|
|
|
40051
40105
|
if (process.env.HALO_FRONTEND_DIR)
|
|
40052
40106
|
return path90.resolve(process.env.HALO_FRONTEND_DIR);
|
|
40053
40107
|
const bundled = path90.resolve(__dirname3, "..", "admin-out");
|
|
40054
|
-
if (
|
|
40108
|
+
if (fs82.existsSync(path90.join(bundled, "index.html")))
|
|
40055
40109
|
return bundled;
|
|
40056
40110
|
const sibling = path90.resolve(__dirname3, "..", "..", "admin", "out");
|
|
40057
|
-
if (
|
|
40111
|
+
if (fs82.existsSync(path90.join(sibling, "index.html")))
|
|
40058
40112
|
return sibling;
|
|
40059
40113
|
return path90.resolve(PROJECT_ROOT, "packages", "admin", "out");
|
|
40060
40114
|
}
|
|
@@ -40159,11 +40213,11 @@ var init_dist2 = __esm({
|
|
|
40159
40213
|
init_git_ssh();
|
|
40160
40214
|
__dirname3 = path90.dirname(fileURLToPath3(import.meta.url));
|
|
40161
40215
|
PORT = config.server.port;
|
|
40162
|
-
HALO_VERSION = "2.0.
|
|
40216
|
+
HALO_VERSION = "2.0.5";
|
|
40163
40217
|
PROJECT_ROOT = findProjectRoot();
|
|
40164
40218
|
HALO_HOME4 = path90.join(homedir25(), ".halo");
|
|
40165
40219
|
GIT_SHA = readGitSha();
|
|
40166
|
-
if (!
|
|
40220
|
+
if (!fs82.existsSync(path90.join(HALO_HOME4, "global", ".template-version"))) {
|
|
40167
40221
|
process.stderr.write("\x1B[31m[Server] ~/.halo/global/ not initialized. Run `halo setup` first.\x1B[0m\n");
|
|
40168
40222
|
process.exit(1);
|
|
40169
40223
|
}
|
|
@@ -40265,7 +40319,7 @@ var init_dist2 = __esm({
|
|
|
40265
40319
|
setCronSessionRegistry(registry);
|
|
40266
40320
|
if (OWNS_RUNTIMES && !AGENTCORE) {
|
|
40267
40321
|
for (const ws of listRunningWorkspaces()) {
|
|
40268
|
-
if (!
|
|
40322
|
+
if (!fs82.existsSync(path90.join(ws, ".halo")))
|
|
40269
40323
|
continue;
|
|
40270
40324
|
if (!claimWorkspaceRuntime(ws))
|
|
40271
40325
|
continue;
|
|
@@ -40311,7 +40365,7 @@ var init_dist2 = __esm({
|
|
|
40311
40365
|
app.get("/*", (c) => {
|
|
40312
40366
|
const indexPath = path90.join(FRONTEND_DIR, "index.html");
|
|
40313
40367
|
try {
|
|
40314
|
-
const html =
|
|
40368
|
+
const html = fs82.readFileSync(indexPath, "utf-8");
|
|
40315
40369
|
return c.html(html);
|
|
40316
40370
|
} catch {
|
|
40317
40371
|
return c.text("Frontend not built. Run: cd packages/admin && npx next build", 503);
|
|
@@ -40399,7 +40453,7 @@ __export(agentcore_front_exports, {
|
|
|
40399
40453
|
workerEnv: () => workerEnv
|
|
40400
40454
|
});
|
|
40401
40455
|
import http3 from "node:http";
|
|
40402
|
-
import
|
|
40456
|
+
import fs83 from "node:fs";
|
|
40403
40457
|
import fsp2 from "node:fs/promises";
|
|
40404
40458
|
import os11 from "node:os";
|
|
40405
40459
|
import path91 from "node:path";
|
|
@@ -40430,39 +40484,39 @@ function skipTemplateEntry(rel) {
|
|
|
40430
40484
|
}
|
|
40431
40485
|
function chownTree(dir, owner, sid) {
|
|
40432
40486
|
try {
|
|
40433
|
-
|
|
40434
|
-
for (const rel of
|
|
40435
|
-
|
|
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);
|
|
40436
40490
|
} catch (err) {
|
|
40437
40491
|
console.warn(`[AgentCore] front: chown ${sid} to ${owner.uid}:${owner.gid} failed (${err.message}) \u2014 serving it as is`);
|
|
40438
40492
|
}
|
|
40439
40493
|
}
|
|
40440
40494
|
function ensureSessionDir(base, sid, owner) {
|
|
40441
40495
|
const dir = path91.join(base, sid);
|
|
40442
|
-
if (
|
|
40496
|
+
if (fs83.existsSync(dir))
|
|
40443
40497
|
return false;
|
|
40444
40498
|
const tmp = path91.join(base, `.tmp-${crypto13.randomBytes(8).toString("hex")}`);
|
|
40445
|
-
|
|
40499
|
+
fs83.mkdirSync(tmp, { mode: 448 });
|
|
40446
40500
|
try {
|
|
40447
40501
|
const template = path91.join(base, TEMPLATE_DIR);
|
|
40448
|
-
if (
|
|
40449
|
-
|
|
40502
|
+
if (fs83.statSync(template, { throwIfNoEntry: false })?.isDirectory()) {
|
|
40503
|
+
fs83.cpSync(template, tmp, { recursive: true, verbatimSymlinks: true, filter: (src) => !skipTemplateEntry(path91.relative(template, src)) });
|
|
40450
40504
|
}
|
|
40451
40505
|
if (owner)
|
|
40452
40506
|
chownTree(tmp, owner, sid);
|
|
40453
|
-
if (
|
|
40454
|
-
|
|
40455
|
-
|
|
40507
|
+
if (fs83.readdirSync(tmp).length === 0) {
|
|
40508
|
+
fs83.rmdirSync(tmp);
|
|
40509
|
+
fs83.mkdirSync(dir, { mode: 448 });
|
|
40456
40510
|
if (owner)
|
|
40457
40511
|
chownTree(dir, owner, sid);
|
|
40458
40512
|
return true;
|
|
40459
40513
|
}
|
|
40460
|
-
|
|
40514
|
+
fs83.renameSync(tmp, dir);
|
|
40461
40515
|
return true;
|
|
40462
40516
|
} catch (err) {
|
|
40463
|
-
|
|
40517
|
+
fs83.rmSync(tmp, { recursive: true, force: true });
|
|
40464
40518
|
const code = err.code;
|
|
40465
|
-
if ((code === "EEXIST" || code === "ENOTEMPTY") &&
|
|
40519
|
+
if ((code === "EEXIST" || code === "ENOTEMPTY") && fs83.existsSync(dir))
|
|
40466
40520
|
return false;
|
|
40467
40521
|
throw err;
|
|
40468
40522
|
}
|
|
@@ -40506,7 +40560,7 @@ async function runViewSetup(base, sessionDir, deps = SYSTEM_SETUP) {
|
|
|
40506
40560
|
const left = mountLayers(base, deps.mountinfo());
|
|
40507
40561
|
if (left > 0)
|
|
40508
40562
|
throw new Error(`view setup: ${base} still has ${left} mount(s) after ${MAX_UMOUNTS} \xD7 umount -l`);
|
|
40509
|
-
if (
|
|
40563
|
+
if (fs83.existsSync(sessionDir))
|
|
40510
40564
|
throw new Error(`view setup: ${base} is still visible after umount -l`);
|
|
40511
40565
|
}
|
|
40512
40566
|
function workerEnv(src, front) {
|
|
@@ -40525,15 +40579,15 @@ async function copyMediaFile(p, root, dest, max = MAX_MEDIA_BYTES) {
|
|
|
40525
40579
|
return "not an absolute path";
|
|
40526
40580
|
let pfd;
|
|
40527
40581
|
try {
|
|
40528
|
-
pfd =
|
|
40582
|
+
pfd = fs83.openSync(p, O_PATH);
|
|
40529
40583
|
} catch (err) {
|
|
40530
40584
|
return `cannot open (${err.code})`;
|
|
40531
40585
|
}
|
|
40532
40586
|
try {
|
|
40533
|
-
const link =
|
|
40587
|
+
const link = fs83.readlinkSync(`/proc/self/fd/${pfd}`);
|
|
40534
40588
|
if (!link.startsWith(`${root}/`))
|
|
40535
40589
|
return `not under ${root}/`;
|
|
40536
|
-
const st =
|
|
40590
|
+
const st = fs83.fstatSync(pfd);
|
|
40537
40591
|
if (!st.isFile())
|
|
40538
40592
|
return "not a regular file";
|
|
40539
40593
|
if (st.size > max)
|
|
@@ -40560,7 +40614,7 @@ async function copyMediaFile(p, root, dest, max = MAX_MEDIA_BYTES) {
|
|
|
40560
40614
|
await src.close();
|
|
40561
40615
|
}
|
|
40562
40616
|
} finally {
|
|
40563
|
-
|
|
40617
|
+
fs83.closeSync(pfd);
|
|
40564
40618
|
}
|
|
40565
40619
|
}
|
|
40566
40620
|
async function copyMediaLines(text6, root, dir, sid) {
|
|
@@ -40573,7 +40627,7 @@ async function copyMediaLines(text6, root, dir, sid) {
|
|
|
40573
40627
|
continue;
|
|
40574
40628
|
}
|
|
40575
40629
|
const sub = path91.join(dir, String(n++));
|
|
40576
|
-
|
|
40630
|
+
fs83.mkdirSync(sub);
|
|
40577
40631
|
const name = path91.basename(m[1]).replace(/[\x00-\x1f\x7f]/g, "_").replace(/^\.+/, "") || "file";
|
|
40578
40632
|
const dest = path91.join(sub, name);
|
|
40579
40633
|
const why = await copyMediaFile(m[1], root, dest).catch((err) => err.message);
|
|
@@ -40581,7 +40635,7 @@ async function copyMediaLines(text6, root, dir, sid) {
|
|
|
40581
40635
|
out.push(`MEDIA:${dest}`);
|
|
40582
40636
|
continue;
|
|
40583
40637
|
}
|
|
40584
|
-
|
|
40638
|
+
fs83.rmSync(sub, { recursive: true, force: true });
|
|
40585
40639
|
console.warn(`[AgentCore] notify ${sid}: MEDIA dropped (${why}): ${JSON.stringify(m[1].slice(0, 300))}`);
|
|
40586
40640
|
}
|
|
40587
40641
|
return out.join("\n");
|
|
@@ -40625,7 +40679,7 @@ function readBody(req, max) {
|
|
|
40625
40679
|
});
|
|
40626
40680
|
}
|
|
40627
40681
|
async function startAgentCoreFront(o) {
|
|
40628
|
-
const base =
|
|
40682
|
+
const base = fs83.realpathSync(o.base);
|
|
40629
40683
|
const workerPort = o.workerPort ?? WORKER_PORT;
|
|
40630
40684
|
const token = crypto13.randomBytes(32).toString("hex");
|
|
40631
40685
|
const isMounted = o.isMounted ?? ((b) => mountLayers(b, readMountinfo()) > 0);
|
|
@@ -40687,11 +40741,11 @@ async function startAgentCoreFront(o) {
|
|
|
40687
40741
|
preparing++;
|
|
40688
40742
|
let dir = "";
|
|
40689
40743
|
const cleanup = () => {
|
|
40690
|
-
|
|
40744
|
+
fs83.rmSync(dir, { recursive: true, force: true });
|
|
40691
40745
|
settle();
|
|
40692
40746
|
};
|
|
40693
40747
|
try {
|
|
40694
|
-
dir =
|
|
40748
|
+
dir = fs83.mkdtempSync(path91.join(os11.tmpdir(), "halo-notify-"));
|
|
40695
40749
|
const text6 = await copyMediaLines(b.text, viewRoot, dir, b.session);
|
|
40696
40750
|
runNotify(cmd, text6, { HALO_SESSION_ID: b.session, HALO_RUN_STATUS: b.status, HALO_WORKSPACE: dir }, dir, cleanup);
|
|
40697
40751
|
} catch (err) {
|
|
@@ -40908,7 +40962,7 @@ var init_agentcore_front = __esm({
|
|
|
40908
40962
|
MAX_MEDIA_BYTES = 20 * 1024 * 1024;
|
|
40909
40963
|
O_PATH = 2097152;
|
|
40910
40964
|
execFileP = promisify3(execFile2);
|
|
40911
|
-
readMountinfo = () =>
|
|
40965
|
+
readMountinfo = () => fs83.readFileSync("/proc/self/mountinfo", "utf8");
|
|
40912
40966
|
SYSTEM_SETUP = {
|
|
40913
40967
|
mountinfo: readMountinfo,
|
|
40914
40968
|
exec: (argv) => execFileP(argv[0], argv.slice(1), { timeout: SETUP_TIMEOUT_MS })
|
|
@@ -42046,7 +42100,7 @@ process.emitWarning = (warning, ...args) => {
|
|
|
42046
42100
|
// src/index.ts
|
|
42047
42101
|
init_server_supervisor();
|
|
42048
42102
|
import path93 from "node:path";
|
|
42049
|
-
import
|
|
42103
|
+
import fs84 from "node:fs";
|
|
42050
42104
|
import { homedir as homedir26, userInfo } from "node:os";
|
|
42051
42105
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
42052
42106
|
|
|
@@ -42337,7 +42391,7 @@ function installUserUnit(opts, run = runCommand) {
|
|
|
42337
42391
|
}
|
|
42338
42392
|
|
|
42339
42393
|
// src/index.ts
|
|
42340
|
-
var VERSION = "2.0.
|
|
42394
|
+
var VERSION = "2.0.5";
|
|
42341
42395
|
var HELP_TOP = `Usage: halo <command> [options]
|
|
42342
42396
|
|
|
42343
42397
|
Commands:
|
|
@@ -43131,7 +43185,7 @@ ${HELP_SESSIONS}`);
|
|
|
43131
43185
|
}
|
|
43132
43186
|
}
|
|
43133
43187
|
async function cmdSessionsMigrate(workspace) {
|
|
43134
|
-
if (!
|
|
43188
|
+
if (!fs84.existsSync(path93.join(workspace, ".halo"))) {
|
|
43135
43189
|
process.stderr.write(`Not a Halo workspace (no .halo/): ${workspace}
|
|
43136
43190
|
`);
|
|
43137
43191
|
process.exitCode = 1;
|
|
@@ -43276,7 +43330,7 @@ var SERVER_LOCK_PATH = path93.join(homedir26(), ".halo", "global", "server.lock"
|
|
|
43276
43330
|
var SERVER_LOG_PATH = path93.join(homedir26(), ".halo", "logs", "server.log");
|
|
43277
43331
|
function readServerPid() {
|
|
43278
43332
|
try {
|
|
43279
|
-
const txt =
|
|
43333
|
+
const txt = fs84.readFileSync(SERVER_LOCK_PATH, "utf-8").trim();
|
|
43280
43334
|
const n = parseInt(txt, 10);
|
|
43281
43335
|
return Number.isFinite(n) && n > 0 ? n : null;
|
|
43282
43336
|
} catch {
|
|
@@ -43383,8 +43437,8 @@ async function cmdServerStart(argv, restart) {
|
|
|
43383
43437
|
}
|
|
43384
43438
|
if (plan.note) writeDim(plan.note);
|
|
43385
43439
|
const { spawn: spawn7 } = await import("node:child_process");
|
|
43386
|
-
|
|
43387
|
-
const out =
|
|
43440
|
+
fs84.mkdirSync(path93.dirname(SERVER_LOG_PATH), { recursive: true });
|
|
43441
|
+
const out = fs84.openSync(SERVER_LOG_PATH, "a");
|
|
43388
43442
|
const child = spawn7(process.argv[0], [process.argv[1], "server", "start"], {
|
|
43389
43443
|
detached: true,
|
|
43390
43444
|
stdio: ["ignore", out, out],
|
|
@@ -43466,7 +43520,7 @@ ${HELP_AGENTCORE}`);
|
|
|
43466
43520
|
return;
|
|
43467
43521
|
}
|
|
43468
43522
|
const workspace = path93.resolve(raw);
|
|
43469
|
-
if (!
|
|
43523
|
+
if (!fs84.statSync(workspace, { throwIfNoEntry: false })?.isDirectory()) {
|
|
43470
43524
|
process.stderr.write(`Workspace is not a directory: ${workspace}
|
|
43471
43525
|
`);
|
|
43472
43526
|
process.exitCode = 1;
|
|
@@ -43577,7 +43631,7 @@ async function cmdServerLogs(argv) {
|
|
|
43577
43631
|
lines: { type: "string", short: "n" }
|
|
43578
43632
|
}
|
|
43579
43633
|
});
|
|
43580
|
-
if (!
|
|
43634
|
+
if (!fs84.existsSync(SERVER_LOG_PATH)) {
|
|
43581
43635
|
process.stderr.write(`No log file at ${SERVER_LOG_PATH}
|
|
43582
43636
|
`);
|
|
43583
43637
|
return;
|
|
@@ -43595,7 +43649,7 @@ function exitMissingSetup() {
|
|
|
43595
43649
|
process.exit(1);
|
|
43596
43650
|
}
|
|
43597
43651
|
function isHaloHomeReady() {
|
|
43598
|
-
return
|
|
43652
|
+
return fs84.existsSync(path93.join(homedir26(), ".halo", "global", ".template-version"));
|
|
43599
43653
|
}
|
|
43600
43654
|
async function main2() {
|
|
43601
43655
|
const argv = process.argv.slice(2);
|