@turmind/halo 2.2.5 → 2.2.6
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/README.md +2 -1
- package/admin-out/404.html +1 -1
- package/admin-out/_next/static/chunks/1989-3ab059aa2c368f46.js +1 -0
- package/admin-out/_next/static/chunks/app/page-99eba94ecd0f8e81.js +1 -0
- package/admin-out/index.html +1 -1
- package/admin-out/index.txt +4 -4
- package/bundled-docs/design/agent.md +0 -1
- package/bundled-docs/design/cron.md +2 -2
- package/bundled-docs/design/feishu.md +10 -0
- package/bundled-docs/design/stt-local.md +1 -1
- package/bundled-docs/dev/api.md +1 -1
- package/bundled-docs/dev/deploy.md +26 -1
- package/bundled-docs/dev/desktop-packaging.md +3 -2
- package/bundled-docs/dev/env.md +0 -1
- package/bundled-docs/guide/cli.md +1 -1
- package/bundled-docs/requirements/explorer.md +10 -3
- package/dist/feishu-sdk.cjs +23128 -0
- package/dist/feishu-sdk.licenses.txt +1465 -0
- package/dist/index.js +97 -29
- package/package.json +1 -2
- package/admin-out/_next/static/chunks/1989-a9d3b40139c1e9a7.js +0 -1
- package/admin-out/_next/static/chunks/app/page-7c5bdfc234c8ac16.js +0 -1
- /package/admin-out/_next/static/{1969BAiACyey4NBiI4j44 → 6I6qmeIcucaJczGu5oP3C}/_buildManifest.js +0 -0
- /package/admin-out/_next/static/{1969BAiACyey4NBiI4j44 → 6I6qmeIcucaJczGu5oP3C}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -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.6", 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
|
}
|
|
@@ -23920,6 +23920,31 @@ async function planFolderZip(root, projectPath, opts) {
|
|
|
23920
23920
|
const [rootReal, wsReal] = await Promise.all([fs53.realpath(root), fs53.realpath(projectPath)]);
|
|
23921
23921
|
if (isBlockedPath(rootReal, wsReal))
|
|
23922
23922
|
throw new FolderZipError(403, "Path is not accessible");
|
|
23923
|
+
const planner = createPlanner(wsReal, opts);
|
|
23924
|
+
await planner.walk(rootReal, "");
|
|
23925
|
+
return planner.plan;
|
|
23926
|
+
}
|
|
23927
|
+
async function planSelectionZip(rels, projectPath, opts) {
|
|
23928
|
+
const selected = new Set(rels);
|
|
23929
|
+
const kept = [...selected].filter((rel) => rel === "" || !rel.split("/").some((_, i, segs) => selected.has(segs.slice(0, i).join("/")))).sort();
|
|
23930
|
+
let common = kept[0].split("/").slice(0, -1);
|
|
23931
|
+
for (const rel of kept) {
|
|
23932
|
+
const segs = rel.split("/").slice(0, -1);
|
|
23933
|
+
let i = 0;
|
|
23934
|
+
while (i < common.length && common[i] === segs[i])
|
|
23935
|
+
i++;
|
|
23936
|
+
common = common.slice(0, i);
|
|
23937
|
+
}
|
|
23938
|
+
const parent = common.join("/");
|
|
23939
|
+
const wsReal = await fs53.realpath(projectPath);
|
|
23940
|
+
const planner = createPlanner(wsReal, opts);
|
|
23941
|
+
for (const rel of kept) {
|
|
23942
|
+
const real = rel ? path60.join(await fs53.realpath(path60.join(wsReal, path60.dirname(rel))), path60.basename(rel)) : wsReal;
|
|
23943
|
+
await planner.addSelected(real, parent ? rel.slice(parent.length + 1) : rel);
|
|
23944
|
+
}
|
|
23945
|
+
return { plan: planner.plan, parent };
|
|
23946
|
+
}
|
|
23947
|
+
function createPlanner(wsReal, opts) {
|
|
23923
23948
|
const { includeIgnored, limits, signal } = opts;
|
|
23924
23949
|
const deadline = Date.now() + limits.maxWalkMs;
|
|
23925
23950
|
const plan = { items: [], files: 0, bytes: 0, excluded: new ExcludedLog() };
|
|
@@ -24012,8 +24037,31 @@ async function planFolderZip(root, projectPath, opts) {
|
|
|
24012
24037
|
}
|
|
24013
24038
|
return nonEmpty2;
|
|
24014
24039
|
}
|
|
24015
|
-
|
|
24016
|
-
|
|
24040
|
+
async function addSelected(real, rel) {
|
|
24041
|
+
signal?.throwIfAborted();
|
|
24042
|
+
if (Date.now() > deadline)
|
|
24043
|
+
throw walkTimeout();
|
|
24044
|
+
const name = path60.basename(real);
|
|
24045
|
+
const st = await fs53.lstat(real);
|
|
24046
|
+
if (rel.split("/").some((seg, i) => isZipUnsafeName(seg, i === 0))) {
|
|
24047
|
+
excluded.add("unreadable", `${rel}${st.isDirectory() ? "/" : ""} (name not valid in a zip)`);
|
|
24048
|
+
} else if (st.isSymbolicLink()) {
|
|
24049
|
+
await addSymlink(real, rel, name);
|
|
24050
|
+
} else if (st.isDirectory()) {
|
|
24051
|
+
if (isBlockedPath(real, wsReal))
|
|
24052
|
+
excluded.add("blocked", `${rel}/`);
|
|
24053
|
+
else if (!await walk(real, rel) && rel)
|
|
24054
|
+
plan.items.push({ rel, mtimeMs: st.mtimeMs });
|
|
24055
|
+
} else if (st.isFile()) {
|
|
24056
|
+
if (isEnvName(name) || isBlockedPath(real, wsReal))
|
|
24057
|
+
excluded.add("blocked", rel);
|
|
24058
|
+
else
|
|
24059
|
+
addFile(rel, real, st);
|
|
24060
|
+
} else {
|
|
24061
|
+
excluded.add("unreadable", `${rel} (not a regular file)`);
|
|
24062
|
+
}
|
|
24063
|
+
}
|
|
24064
|
+
return { plan, walk, addSelected };
|
|
24017
24065
|
}
|
|
24018
24066
|
function planSummary(plan) {
|
|
24019
24067
|
return { files: plan.files, bytes: plan.bytes, excluded: { ...plan.excluded.counts }, ignoredNames: { ...plan.excluded.ignoredNames } };
|
|
@@ -24747,26 +24795,44 @@ function createFileRoutes(opts = {}) {
|
|
|
24747
24795
|
}
|
|
24748
24796
|
});
|
|
24749
24797
|
app2.get("/files/download-folder", async (c) => {
|
|
24750
|
-
const
|
|
24798
|
+
const relPaths = c.req.queries("path") ?? [];
|
|
24799
|
+
const relPath = relPaths[0] ?? "";
|
|
24751
24800
|
const projectId = c.req.query("projectId");
|
|
24752
24801
|
if (!projectId)
|
|
24753
24802
|
return c.json({ error: "projectId is required" }, 400);
|
|
24754
24803
|
const signal = c.req.raw.signal;
|
|
24804
|
+
const planOpts = { includeIgnored: c.req.query("include") === "excluded", limits: folderZipLimits, signal };
|
|
24755
24805
|
try {
|
|
24756
|
-
|
|
24757
|
-
|
|
24758
|
-
|
|
24759
|
-
|
|
24760
|
-
|
|
24761
|
-
|
|
24762
|
-
|
|
24763
|
-
|
|
24764
|
-
|
|
24765
|
-
|
|
24766
|
-
|
|
24806
|
+
let plan;
|
|
24807
|
+
let folderName;
|
|
24808
|
+
if (relPaths.length > 1) {
|
|
24809
|
+
let projectPath = "";
|
|
24810
|
+
const rels = [];
|
|
24811
|
+
for (const p of relPaths) {
|
|
24812
|
+
const resolved = await resolveProjectFile(projectId, p);
|
|
24813
|
+
if ("error" in resolved)
|
|
24814
|
+
return c.json({ error: resolved.error }, resolved.status);
|
|
24815
|
+
projectPath = resolved.projectPath;
|
|
24816
|
+
const rel = path61.relative(projectPath, resolved.absolutePath);
|
|
24817
|
+
if (rel === ".." || rel.startsWith(`..${path61.sep}`) || path61.isAbsolute(rel))
|
|
24818
|
+
return c.json({ error: "Path traversal not allowed" }, 403);
|
|
24819
|
+
rels.push(rel.split(path61.sep).join("/"));
|
|
24820
|
+
}
|
|
24821
|
+
const selection = await planSelectionZip(rels, projectPath, planOpts);
|
|
24822
|
+
plan = selection.plan;
|
|
24823
|
+
folderName = `${path61.basename(path61.resolve(projectPath, selection.parent)) || "workspace"}-selection`;
|
|
24824
|
+
} else {
|
|
24825
|
+
const resolved = await resolveProjectFile(projectId, relPath);
|
|
24826
|
+
if ("error" in resolved)
|
|
24827
|
+
return c.json({ error: resolved.error }, resolved.status);
|
|
24828
|
+
const { projectPath, absolutePath } = resolved;
|
|
24829
|
+
if (!(await fs54.stat(absolutePath)).isDirectory())
|
|
24830
|
+
return c.json({ error: "Not a directory" }, 400);
|
|
24831
|
+
plan = await planFolderZip(absolutePath, projectPath, planOpts);
|
|
24832
|
+
folderName = path61.basename(absolutePath) || "workspace";
|
|
24833
|
+
}
|
|
24767
24834
|
if (c.req.query("estimate") === "1")
|
|
24768
24835
|
return c.json(planSummary(plan));
|
|
24769
|
-
const folderName = path61.basename(absolutePath) || "workspace";
|
|
24770
24836
|
const fileName = `${folderName}.zip`;
|
|
24771
24837
|
const asciiName = fileName.replace(/[^\x20-\x7e]|["\\]/g, "_");
|
|
24772
24838
|
const encodedName = encodeURIComponent(fileName).replace(/['()*]/g, (ch) => `%${ch.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
@@ -32756,7 +32822,7 @@ function buildCard(workspace, interfaceUrl, caps) {
|
|
|
32756
32822
|
return {
|
|
32757
32823
|
name: raw.name,
|
|
32758
32824
|
description: raw.description,
|
|
32759
|
-
version: typeof raw.version === "string" ? raw.version : "2.2.
|
|
32825
|
+
version: typeof raw.version === "string" ? raw.version : "2.2.6",
|
|
32760
32826
|
supportedInterfaces: [{ url: interfaceUrl, protocolBinding: "JSONRPC", protocolVersion: A2A_VERSION }],
|
|
32761
32827
|
capabilities: { streaming: caps.streaming, pushNotifications: true, extendedAgentCard: false },
|
|
32762
32828
|
...caps.tokenAuth === false ? {} : {
|
|
@@ -34238,7 +34304,7 @@ async function finishRun(runId, db4, session) {
|
|
|
34238
34304
|
if (session.turnError) {
|
|
34239
34305
|
status = "failed";
|
|
34240
34306
|
failureReason = session.turnError.slice(0, 500);
|
|
34241
|
-
} else if (!
|
|
34307
|
+
} else if (!answer) {
|
|
34242
34308
|
status = "failed";
|
|
34243
34309
|
failureReason = "run produced no output (nothing to dispatch)";
|
|
34244
34310
|
}
|
|
@@ -34250,7 +34316,7 @@ async function finishRun(runId, db4, session) {
|
|
|
34250
34316
|
const targets = job ? parseTargets(job.targets) : [];
|
|
34251
34317
|
let dispatchResults = [];
|
|
34252
34318
|
if (job && status === "succeeded" && targets.length > 0) {
|
|
34253
|
-
dispatchResults = await dispatchToTargets(
|
|
34319
|
+
dispatchResults = await dispatchToTargets(answer, targets, row.workspacePath ?? job.workspacePath);
|
|
34254
34320
|
if (dispatchResults.length > 0 && dispatchResults.every((r) => !r.ok)) {
|
|
34255
34321
|
status = "failed";
|
|
34256
34322
|
failureReason = `all ${dispatchResults.length} target(s) failed: ${dispatchResults.map((r) => `${r.channelType}:${r.error ?? "?"}`).join("; ")}`;
|
|
@@ -35928,7 +35994,7 @@ function createCoreChecker(opts) {
|
|
|
35928
35994
|
}
|
|
35929
35995
|
function getCoreStatus(force) {
|
|
35930
35996
|
checker ??= createCoreChecker({
|
|
35931
|
-
haloVersion: "2.2.
|
|
35997
|
+
haloVersion: "2.2.6",
|
|
35932
35998
|
fetchLatest: fetchNpmLatest,
|
|
35933
35999
|
onChange: (status) => broadcast({ type: "updates:changed", scope: "core", status })
|
|
35934
36000
|
});
|
|
@@ -36096,7 +36162,7 @@ function hubBase() {
|
|
|
36096
36162
|
}
|
|
36097
36163
|
function serverChecker() {
|
|
36098
36164
|
checker2 ??= createExtensionsChecker({
|
|
36099
|
-
haloVersion: "2.2.
|
|
36165
|
+
haloVersion: "2.2.6",
|
|
36100
36166
|
installed: () => {
|
|
36101
36167
|
const s = getSnapshot();
|
|
36102
36168
|
return [...s.extensions, ...s.disabled];
|
|
@@ -40952,7 +41018,6 @@ var init_api3 = __esm({
|
|
|
40952
41018
|
|
|
40953
41019
|
// ../server/dist/channels/feishu/handler.js
|
|
40954
41020
|
import path93 from "node:path";
|
|
40955
|
-
import * as Lark from "@larksuiteoapi/node-sdk";
|
|
40956
41021
|
function buildSessionPrefixForThread2(chatId, rootId) {
|
|
40957
41022
|
return sessionPrefix("feishu", `${chatId}:${rootId}`);
|
|
40958
41023
|
}
|
|
@@ -41199,13 +41264,16 @@ function startFeishuChannel(deps) {
|
|
|
41199
41264
|
const state = ensureState(accountId);
|
|
41200
41265
|
if (state.stopped || state.wsClient)
|
|
41201
41266
|
return;
|
|
41202
|
-
const
|
|
41267
|
+
const { WSClient: WSClient2, EventDispatcher, LoggerLevel } = await import("./feishu-sdk.cjs");
|
|
41268
|
+
if (state.stopped || state.wsClient)
|
|
41269
|
+
return;
|
|
41270
|
+
const wsClient = new WSClient2({
|
|
41203
41271
|
appId: account.appId,
|
|
41204
41272
|
appSecret: account.appSecret,
|
|
41205
|
-
loggerLevel:
|
|
41273
|
+
loggerLevel: LoggerLevel.warn
|
|
41206
41274
|
});
|
|
41207
41275
|
state.wsClient = wsClient;
|
|
41208
|
-
const dispatcher = new
|
|
41276
|
+
const dispatcher = new EventDispatcher({});
|
|
41209
41277
|
dispatcher.register({
|
|
41210
41278
|
"im.message.receive_v1": async (data) => {
|
|
41211
41279
|
dispatchEvent(accountId, data);
|
|
@@ -41718,7 +41786,7 @@ var init_event_adapter5 = __esm({
|
|
|
41718
41786
|
// ../server/dist/channels/wecom/handler.js
|
|
41719
41787
|
import path94 from "node:path";
|
|
41720
41788
|
import fs89 from "node:fs/promises";
|
|
41721
|
-
import { WSClient
|
|
41789
|
+
import { WSClient, generateReqId } from "@wecom/aibot-node-sdk";
|
|
41722
41790
|
function pickConversation(body) {
|
|
41723
41791
|
const userid = body.from?.userid ?? "unknown";
|
|
41724
41792
|
if (body.chattype === "group" && body.chatid) {
|
|
@@ -41950,7 +42018,7 @@ function startWecomChannel(deps) {
|
|
|
41950
42018
|
const state = ensureState(accountId);
|
|
41951
42019
|
if (state.stopped || state.wsClient)
|
|
41952
42020
|
return;
|
|
41953
|
-
const wsClient = new
|
|
42021
|
+
const wsClient = new WSClient({
|
|
41954
42022
|
botId: account.botId,
|
|
41955
42023
|
secret: account.secret,
|
|
41956
42024
|
maxReconnectAttempts: -1,
|
|
@@ -42593,7 +42661,7 @@ var init_dist2 = __esm({
|
|
|
42593
42661
|
init_git_ssh();
|
|
42594
42662
|
__dirname3 = path95.dirname(fileURLToPath3(import.meta.url));
|
|
42595
42663
|
PORT = config.server.port;
|
|
42596
|
-
HALO_VERSION = "2.2.
|
|
42664
|
+
HALO_VERSION = "2.2.6";
|
|
42597
42665
|
PROJECT_ROOT = findProjectRoot();
|
|
42598
42666
|
HALO_HOME4 = path95.join(homedir26(), ".halo");
|
|
42599
42667
|
GIT_SHA = readGitSha();
|
|
@@ -44791,7 +44859,7 @@ function installUserUnit(opts, run = runCommand) {
|
|
|
44791
44859
|
}
|
|
44792
44860
|
|
|
44793
44861
|
// src/index.ts
|
|
44794
|
-
var VERSION = "2.2.
|
|
44862
|
+
var VERSION = "2.2.6";
|
|
44795
44863
|
var HELP_TOP = `Usage: halo <command> [options]
|
|
44796
44864
|
|
|
44797
44865
|
Commands:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@turmind/halo",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.6",
|
|
4
4
|
"description": "Halo — multi-agent collaborative workspace. CLI + TUI + HTTP/WS server in one package.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
"@aws-sdk/client-transcribe-streaming": "^3.1142.0",
|
|
23
23
|
"@aws-sdk/credential-provider-node": "^3.972.30",
|
|
24
24
|
"@hono/node-server": "^1.19.17",
|
|
25
|
-
"@larksuiteoapi/node-sdk": "^1.65.0",
|
|
26
25
|
"@opentelemetry/api": "^1.9.1",
|
|
27
26
|
"@opentelemetry/api-logs": "^0.222.0",
|
|
28
27
|
"@opentelemetry/exporter-logs-otlp-proto": "^0.222.0",
|