@nanhara/hara 0.122.3 → 0.122.4
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/CHANGELOG.md +98 -0
- package/README.md +15 -2
- package/dist/agent/limits.js +51 -0
- package/dist/agent/loop.js +367 -112
- package/dist/agent/repeat-guard.js +49 -12
- package/dist/checkpoints.js +9 -0
- package/dist/cli.js +2 -1
- package/dist/config.js +10 -2
- package/dist/context/agents-md.js +21 -2
- package/dist/context/mentions.js +84 -1
- package/dist/context/workspace-scope.js +49 -0
- package/dist/cron/deliver.js +61 -38
- package/dist/cron/runner.js +423 -65
- package/dist/cron/schedule.js +23 -7
- package/dist/cron/store.js +709 -43
- package/dist/fs-walk.js +279 -7
- package/dist/fs-write.js +9 -0
- package/dist/gateway/feishu.js +351 -64
- package/dist/gateway/flows-pending.js +28 -14
- package/dist/gateway/flows.js +306 -31
- package/dist/gateway/outbound-files.js +20 -6
- package/dist/gateway/runtime-state.js +1485 -0
- package/dist/gateway/serve.js +550 -242
- package/dist/gateway/telegram.js +279 -29
- package/dist/gateway/tts.js +182 -38
- package/dist/hooks.js +22 -22
- package/dist/index.js +466 -158
- package/dist/memory/store.js +8 -5
- package/dist/org/planner.js +11 -6
- package/dist/process-identity.js +52 -0
- package/dist/providers/bounded-turn.js +42 -0
- package/dist/recall.js +69 -1
- package/dist/runtime.js +24 -0
- package/dist/sandbox.js +54 -4
- package/dist/search/embed.js +13 -2
- package/dist/search/hybrid.js +6 -3
- package/dist/search/semindex.js +87 -5
- package/dist/security/guardian.js +3 -15
- package/dist/security/permissions.js +11 -0
- package/dist/serve/server.js +70 -42
- package/dist/serve/sessions.js +4 -3
- package/dist/tools/agent.js +1 -1
- package/dist/tools/ask_user.js +5 -1
- package/dist/tools/builtin.js +5 -2
- package/dist/tools/codebase.js +67 -18
- package/dist/tools/computer.js +149 -68
- package/dist/tools/cron.js +72 -18
- package/dist/tools/edit.js +3 -2
- package/dist/tools/external_agent.js +66 -12
- package/dist/tools/memory.js +25 -7
- package/dist/tools/patch.js +11 -2
- package/dist/tools/registry.js +16 -1
- package/dist/tools/search.js +68 -9
- package/dist/tools/send.js +1 -1
- package/dist/tools/skill.js +1 -1
- package/dist/tools/web.js +43 -13
- package/dist/tui/App.js +93 -25
- package/dist/vision.js +5 -6
- package/package.json +2 -2
- package/runtime-bootstrap.cjs +22 -0
package/dist/hooks.js
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
// PreToolUse runs BEFORE a tool: non-zero, timeout, signal, or launch failure BLOCKS the call.
|
|
3
3
|
// PostToolUse runs AFTER: observe-only (format, log, notify). Configured in config.json `hooks` + contributed
|
|
4
4
|
// by plugins. The command receives {tool, payload} as JSON on stdin + HARA_TOOL_NAME in the env.
|
|
5
|
-
import { spawnSync } from "node:child_process";
|
|
6
5
|
import { resolve } from "node:path";
|
|
7
6
|
import { loadConfig } from "./config.js";
|
|
8
7
|
import { pluginHooks } from "./plugins/plugins.js";
|
|
9
|
-
import { redactToolSubprocessOutput
|
|
10
|
-
import {
|
|
8
|
+
import { redactToolSubprocessOutput } from "./security/subprocess-env.js";
|
|
9
|
+
import { runShell } from "./sandbox.js";
|
|
11
10
|
const cache = new Map();
|
|
12
11
|
export function resetHooksCache() {
|
|
13
12
|
cache.clear();
|
|
@@ -42,41 +41,42 @@ export function hasHooks(cwd = process.cwd()) {
|
|
|
42
41
|
return !!(h.PreToolUse?.length || h.PostToolUse?.length);
|
|
43
42
|
}
|
|
44
43
|
/** Run hooks for an event matching `toolName`. Any abnormal PreToolUse termination fails closed;
|
|
45
|
-
* PostToolUse remains observe-only.
|
|
46
|
-
|
|
44
|
+
* PostToolUse remains observe-only. Every child owns a cancellable process group; no hook may hold the
|
|
45
|
+
* event loop past the parent run deadline, and an aborted batch never starts its next command. */
|
|
46
|
+
export async function runHooks(event, toolName, payload, cwd, timeoutMs = 30_000, signal) {
|
|
47
47
|
for (const h of merged(cwd)[event] ?? []) {
|
|
48
|
+
if (signal?.aborted) {
|
|
49
|
+
return event === "PreToolUse"
|
|
50
|
+
? { block: true, message: "⛔ blocked because the agent run was cancelled before the PreToolUse hook completed" }
|
|
51
|
+
: { block: false, message: "" };
|
|
52
|
+
}
|
|
48
53
|
if (!matches(h.matcher, toolName))
|
|
49
54
|
continue;
|
|
50
|
-
let r;
|
|
51
55
|
try {
|
|
52
56
|
// Hooks are user/plugin-configured external code. Route them through the same command preflight and
|
|
53
57
|
// macOS protected-read mask as Bash, even though hooks remain observe-only after a tool has run.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
cwd,
|
|
57
|
-
input: JSON.stringify({ tool: toolName, payload }),
|
|
58
|
-
encoding: "utf8",
|
|
58
|
+
await runShell(h.command, cwd, "off", {
|
|
59
|
+
signal,
|
|
59
60
|
timeout: timeoutMs,
|
|
60
|
-
|
|
61
|
+
maxBuffer: 256 * 1024,
|
|
62
|
+
input: JSON.stringify({ tool: toolName, payload }),
|
|
63
|
+
env: { HARA_TOOL_NAME: toolName },
|
|
61
64
|
});
|
|
62
65
|
}
|
|
63
66
|
catch (error) {
|
|
64
67
|
if (event === "PreToolUse") {
|
|
65
|
-
const
|
|
66
|
-
|
|
68
|
+
const failure = error;
|
|
69
|
+
const output = redactToolSubprocessOutput(`${failure.stdout ?? ""}${failure.stderr ?? ""}`.trim());
|
|
70
|
+
const detail = redactToolSubprocessOutput(failure.message || String(error));
|
|
71
|
+
return {
|
|
72
|
+
block: true,
|
|
73
|
+
message: `⛔ blocked by a PreToolUse hook${output ? `: ${output}` : detail ? ` (${detail})` : ""}`,
|
|
74
|
+
};
|
|
67
75
|
}
|
|
68
76
|
// PostToolUse is best-effort: a policy-blocked or broken observer must never rewrite the result of a
|
|
69
77
|
// tool that already completed. In particular, do not retry it through an unsandboxed fallback shell.
|
|
70
78
|
continue;
|
|
71
79
|
}
|
|
72
|
-
// A hook is allowed to ignore stdin. On Linux, a command that exits successfully before Node finishes
|
|
73
|
-
// writing `input` can report EPIPE in r.error *alongside status=0*. The wait status is authoritative in
|
|
74
|
-
// that case; true launch/write failures still have status=null, while timeouts/signals remain blocked.
|
|
75
|
-
if (event === "PreToolUse" && (r.status !== 0 || !!r.signal)) {
|
|
76
|
-
const output = redactToolSubprocessOutput((String(r.stdout ?? "") + String(r.stderr ?? "")).trim());
|
|
77
|
-
const failure = redactToolSubprocessOutput(r.error?.message || (r.signal ? `terminated by ${r.signal}` : `exit ${r.status ?? "unknown"}`));
|
|
78
|
-
return { block: true, message: `⛔ blocked by a PreToolUse hook${output ? `: ${output}` : ` (${failure})`}` };
|
|
79
|
-
}
|
|
80
80
|
}
|
|
81
81
|
return { block: false, message: "" };
|
|
82
82
|
}
|