@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/admin-out/404.html +1 -1
- package/admin-out/_next/static/chunks/1989-a9d3b40139c1e9a7.js +1 -0
- package/admin-out/_next/static/chunks/4320-0fb65ed376b666a8.js +1 -0
- package/admin-out/_next/static/chunks/app/{page-c9d174a5432b0007.js → page-7c5bdfc234c8ac16.js} +1 -1
- package/admin-out/_next/static/css/7eb37d975d4027da.css +1 -0
- package/admin-out/index.html +1 -1
- package/admin-out/index.txt +5 -5
- package/bundled-docs/design/architecture.md +1 -1
- package/bundled-docs/design/canvas-extensions.md +2 -0
- package/bundled-docs/design/storage.md +4 -2
- package/bundled-docs/design/ws.md +1 -1
- package/bundled-docs/dev/add-model-provider.md +18 -0
- package/bundled-docs/dev/api.md +6 -0
- package/bundled-docs/dev/env.md +1 -1
- package/bundled-docs/guide/agents.md +2 -2
- package/bundled-docs/guide/cli.md +1 -1
- package/bundled-docs/guide/skills.md +1 -1
- package/bundled-docs/requirements/settings.md +24 -1
- package/dist/index.js +327 -197
- package/package.json +1 -1
- package/templates/models/aws-bedrock-claude-invoke.yaml +62 -1
- package/admin-out/_next/static/chunks/1607-bf227fc5e4db45b7.js +0 -1
- package/admin-out/_next/static/chunks/1989-9d30cdb1a86e4beb.js +0 -1
- package/admin-out/_next/static/css/87d4fc049f865389.css +0 -1
- /package/admin-out/_next/static/{vf5W8US5y8B2f1E6zJJw3 → 1969BAiACyey4NBiI4j44}/_buildManifest.js +0 -0
- /package/admin-out/_next/static/{vf5W8US5y8B2f1E6zJJw3 → 1969BAiACyey4NBiI4j44}/_ssgManifest.js +0 -0
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 =
|
|
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(
|
|
9354
|
-
const fullPath = this.validatePath(
|
|
9353
|
+
async readFile(path99) {
|
|
9354
|
+
const fullPath = this.validatePath(path99);
|
|
9355
9355
|
return readFile(fullPath, "utf-8");
|
|
9356
9356
|
}
|
|
9357
|
-
async writeFile(
|
|
9358
|
-
const fullPath = this.validatePath(
|
|
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(
|
|
9364
|
-
const fullPath = isAbsolute(
|
|
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 "${
|
|
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 "${
|
|
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
|
|
9561
|
-
if (!
|
|
9560
|
+
const path99 = isRenameOrCopy ? parts[2] : parts[1];
|
|
9561
|
+
if (!path99 || seen.has(path99))
|
|
9562
9562
|
continue;
|
|
9563
|
-
seen.add(
|
|
9563
|
+
seen.add(path99);
|
|
9564
9564
|
files.push({
|
|
9565
|
-
path:
|
|
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(
|
|
9713
|
+
async getFileDiff(path99, staged, from, commit) {
|
|
9714
9714
|
if (commit) {
|
|
9715
|
-
const parentPath = from ||
|
|
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}:${
|
|
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 ||
|
|
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([`:${
|
|
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(
|
|
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:
|
|
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.
|
|
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
|
|
22022
|
-
return `${before}@${kind} ${
|
|
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
|
|
26859
|
-
if (!declaredMap.has(
|
|
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
|
|
28464
|
-
if (PUBLIC_PATHS.some((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(
|
|
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 (!
|
|
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
|
|
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
|
-
|
|
28532
|
+
path99 = override;
|
|
28533
28533
|
}
|
|
28534
|
-
const resolved = scaffold ? resolveAccountWorkspace({ ...account, workspacePath:
|
|
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.
|
|
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 ?
|
|
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.
|
|
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.
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
36553
|
-
import
|
|
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(
|
|
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 &&
|
|
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(
|
|
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
|
|
36876
|
-
import
|
|
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
|
-
|
|
37010
|
+
fs83.mkdirSync(evoLogsDir(), { recursive: true });
|
|
36881
37011
|
const logPath = mode === "run" ? evoWrapperLogFile(id) : evoApplyLogFile(id);
|
|
36882
|
-
const logFd =
|
|
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
|
-
|
|
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 =
|
|
36913
|
-
WRAPPER_PATH =
|
|
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
|
|
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: !
|
|
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
|
|
38381
|
-
import
|
|
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
|
|
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:
|
|
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
|
|
38595
|
-
import
|
|
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 =
|
|
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
|
|
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
|
|
39106
|
-
import
|
|
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: !
|
|
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 (!
|
|
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
|
|
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
|
|
39541
|
-
const resolved =
|
|
39542
|
-
const root =
|
|
39543
|
-
if (resolved !== root && !resolved.startsWith(root +
|
|
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 =
|
|
39550
|
-
realRoot =
|
|
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 +
|
|
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 =
|
|
39690
|
+
const stat = fs88.statSync(real);
|
|
39561
39691
|
if (stat.isDirectory())
|
|
39562
39692
|
return c.json({ error: "cannot serve directory" }, 400);
|
|
39563
|
-
const ext =
|
|
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 =
|
|
39572
|
-
const data =
|
|
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
|
|
39795
|
-
const
|
|
39796
|
-
const filename = args.filename ??
|
|
39797
|
-
const stat =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
40736
|
-
const
|
|
40737
|
-
const buf =
|
|
40738
|
-
const filename =
|
|
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
|
|
40755
|
-
const
|
|
40756
|
-
const buf =
|
|
40757
|
-
const filename = args.filename ??
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
41590
|
-
import
|
|
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 =
|
|
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
|
|
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:
|
|
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 =
|
|
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
|
|
42253
|
-
import
|
|
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 (
|
|
42390
|
+
if (fs90.existsSync(path95.join(dir, "pnpm-workspace.yaml")))
|
|
42261
42391
|
return dir;
|
|
42262
|
-
const parent =
|
|
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
|
-
|
|
42273
|
-
const fd =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
42295
|
-
|
|
42296
|
-
|
|
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 =
|
|
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 (!
|
|
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
|
|
42351
|
-
const bundled =
|
|
42352
|
-
if (
|
|
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 =
|
|
42355
|
-
if (
|
|
42484
|
+
const sibling = path95.resolve(__dirname3, "..", "..", "admin", "out");
|
|
42485
|
+
if (fs90.existsSync(path95.join(sibling, "index.html")))
|
|
42356
42486
|
return sibling;
|
|
42357
|
-
return
|
|
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 =
|
|
42594
|
+
__dirname3 = path95.dirname(fileURLToPath3(import.meta.url));
|
|
42465
42595
|
PORT = config.server.port;
|
|
42466
|
-
HALO_VERSION = "2.2.
|
|
42596
|
+
HALO_VERSION = "2.2.5";
|
|
42467
42597
|
PROJECT_ROOT = findProjectRoot();
|
|
42468
|
-
HALO_HOME4 =
|
|
42598
|
+
HALO_HOME4 = path95.join(homedir26(), ".halo");
|
|
42469
42599
|
GIT_SHA = readGitSha();
|
|
42470
|
-
if (!
|
|
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(
|
|
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(
|
|
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(
|
|
42557
|
-
setCronDb(createCronDb(
|
|
42686
|
+
setEvoDb(createEvoDb(path95.join(HALO_HOME4, "global")));
|
|
42687
|
+
setCronDb(createCronDb(path95.join(HALO_HOME4, "global")));
|
|
42558
42688
|
if (!AGENTCORE)
|
|
42559
|
-
setRunsDb(createRunsDb(
|
|
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 (!
|
|
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(
|
|
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:
|
|
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 =
|
|
42764
|
+
const indexPath = path95.join(FRONTEND_DIR, "index.html");
|
|
42635
42765
|
try {
|
|
42636
|
-
const html =
|
|
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
|
|
42857
|
+
import fs91 from "node:fs";
|
|
42728
42858
|
import fsp2 from "node:fs/promises";
|
|
42729
|
-
import
|
|
42730
|
-
import
|
|
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 =
|
|
42754
|
-
return rel ===
|
|
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
|
-
|
|
42759
|
-
for (const rel of
|
|
42760
|
-
|
|
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 =
|
|
42767
|
-
if (
|
|
42896
|
+
const dir = path96.join(base, sid);
|
|
42897
|
+
if (fs91.existsSync(dir))
|
|
42768
42898
|
return false;
|
|
42769
|
-
const tmp =
|
|
42770
|
-
|
|
42899
|
+
const tmp = path96.join(base, `.tmp-${crypto16.randomBytes(8).toString("hex")}`);
|
|
42900
|
+
fs91.mkdirSync(tmp, { mode: 448 });
|
|
42771
42901
|
try {
|
|
42772
|
-
const template =
|
|
42773
|
-
if (
|
|
42774
|
-
|
|
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 (
|
|
42779
|
-
|
|
42780
|
-
|
|
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
|
-
|
|
42915
|
+
fs91.renameSync(tmp, dir);
|
|
42786
42916
|
return true;
|
|
42787
42917
|
} catch (err) {
|
|
42788
|
-
|
|
42918
|
+
fs91.rmSync(tmp, { recursive: true, force: true });
|
|
42789
42919
|
const code = err.code;
|
|
42790
|
-
if ((code === "EEXIST" || code === "ENOTEMPTY") &&
|
|
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 (
|
|
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 (!
|
|
42979
|
+
if (!path96.isAbsolute(p))
|
|
42850
42980
|
return "not an absolute path";
|
|
42851
42981
|
let pfd;
|
|
42852
42982
|
try {
|
|
42853
|
-
pfd =
|
|
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 =
|
|
42988
|
+
const link = fs91.readlinkSync(`/proc/self/fd/${pfd}`);
|
|
42859
42989
|
if (!link.startsWith(`${root}/`))
|
|
42860
42990
|
return `not under ${root}/`;
|
|
42861
|
-
const st =
|
|
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
|
-
|
|
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 =
|
|
42901
|
-
|
|
42902
|
-
const name =
|
|
42903
|
-
const dest =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
43145
|
+
fs91.rmSync(dir, { recursive: true, force: true });
|
|
43016
43146
|
settle();
|
|
43017
43147
|
};
|
|
43018
43148
|
try {
|
|
43019
|
-
dir =
|
|
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 =
|
|
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 =
|
|
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 = () =>
|
|
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(
|
|
43417
|
-
const url = new URL(`${this.opts.baseUrl}${
|
|
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
|
|
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 &&
|
|
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
|
|
44373
|
-
import
|
|
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.
|
|
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 =
|
|
45032
|
-
const globalDir2 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 (!
|
|
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(
|
|
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 =
|
|
45600
|
-
var SERVER_LOG_PATH =
|
|
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 =
|
|
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
|
-
|
|
45711
|
-
const out =
|
|
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 =
|
|
45793
|
-
if (!
|
|
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 (!
|
|
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
|
|
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);
|