hilos-agent 0.11.9 → 0.11.10
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/bin/hilos-agent.mjs +2 -1
- package/package.json +1 -1
- package/src/cli.mjs +24 -0
- package/src/handler.mjs +17 -1
package/bin/hilos-agent.mjs
CHANGED
|
@@ -30,6 +30,7 @@ import { hookMain, hooksMain } from "../src/hook.mjs";
|
|
|
30
30
|
import { runWebMcpCommand } from "../src/webmcp-bridge.mjs";
|
|
31
31
|
import { detectVendor, fastChatCmd, webCapability } from "../src/progress-emitter.mjs";
|
|
32
32
|
import { commandArgv } from "../src/argv.mjs";
|
|
33
|
+
import { runWithTerminalSignals } from "../src/cli.mjs";
|
|
33
34
|
|
|
34
35
|
// 1251 — the plugin writes `hook --claude --personal`, so the client flags name
|
|
35
36
|
// the vendor for `hook` the same way they choose a target for `hooks install`.
|
|
@@ -318,7 +319,7 @@ async function main() {
|
|
|
318
319
|
delete cliFlags.joinStdin;
|
|
319
320
|
delete cliFlags.help;
|
|
320
321
|
const cfg = resolveConfig({ flags: cliFlags, join: joinPayload });
|
|
321
|
-
await run(cfg);
|
|
322
|
+
await runWithTerminalSignals((signal) => run(cfg, { signal }));
|
|
322
323
|
}
|
|
323
324
|
|
|
324
325
|
main().catch((e) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hilos-agent",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.10",
|
|
4
4
|
"description": "Run your own coding agent (Claude Code, Codex, Cursor, OpenCode, Hermes, or any command) as a teammate in a hilos room. The checkout and credentials stay local; changes go to your configured Git remote as a PR for human review, and bounded progress and reports go to hilos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/cli.mjs
CHANGED
|
@@ -7,6 +7,30 @@
|
|
|
7
7
|
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Let the daemon finish its existing abort/cleanup path before exiting.
|
|
12
|
+
* @param {(signal: AbortSignal) => Promise<any>} task
|
|
13
|
+
* @param {import("node:events").EventEmitter & { exitCode?: number | string }} signalSource
|
|
14
|
+
*/
|
|
15
|
+
export async function runWithTerminalSignals(task, signalSource = process) {
|
|
16
|
+
const controller = new AbortController();
|
|
17
|
+
const interrupt = () => stop("SIGINT", 130);
|
|
18
|
+
const terminate = () => stop("SIGTERM", 143);
|
|
19
|
+
const stop = (name, code) => {
|
|
20
|
+
if (controller.signal.aborted) return;
|
|
21
|
+
signalSource.exitCode = code;
|
|
22
|
+
controller.abort(new Error(`Daemon received ${name}`));
|
|
23
|
+
};
|
|
24
|
+
signalSource.once("SIGINT", interrupt);
|
|
25
|
+
signalSource.once("SIGTERM", terminate);
|
|
26
|
+
try {
|
|
27
|
+
return await task(controller.signal);
|
|
28
|
+
} finally {
|
|
29
|
+
signalSource.removeListener("SIGINT", interrupt);
|
|
30
|
+
signalSource.removeListener("SIGTERM", terminate);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
10
34
|
// ── Environment isolation ────────────────────────────────────────────────────
|
|
11
35
|
// The coding/chat CLI we spawn (`claude -p`, `codex`, …) is a model with tool
|
|
12
36
|
// use: it can run `env`/`printenv` and echo whatever it sees into the channel.
|
package/src/handler.mjs
CHANGED
|
@@ -4975,6 +4975,11 @@ export async function handleTask({ message, channelId, tool, me, caps = {}, iter
|
|
|
4975
4975
|
body,
|
|
4976
4976
|
});
|
|
4977
4977
|
await updateChannelMarker(compactRunMarker("cancelled", branch));
|
|
4978
|
+
// 1270 — a process interruption has no server-side Stop action to settle
|
|
4979
|
+
// the row. Iterate claims keep their fenced recovery path in run().
|
|
4980
|
+
if (runId && caps.runs && !iterateClaimId) {
|
|
4981
|
+
await tool("update_run", { runId, status: "failed", reason: "daemon-stopped" }).catch(() => {});
|
|
4982
|
+
}
|
|
4978
4983
|
// Every repo-lane cancel funnels through here, so one settle covers them
|
|
4979
4984
|
// all: a stopped run still spent tokens (0787).
|
|
4980
4985
|
await settleRunUsage();
|
|
@@ -5254,8 +5259,19 @@ export async function handleTask({ message, channelId, tool, me, caps = {}, iter
|
|
|
5254
5259
|
compactRunMarker(staged.failed ? "run-failed" : "no-changes", branch),
|
|
5255
5260
|
);
|
|
5256
5261
|
await settleRunUsage(); // "no changes" is not "no spend" (0787)
|
|
5257
|
-
// 1182 —
|
|
5262
|
+
// 1182 — retry direction receipts before terminal settlement drops any
|
|
5263
|
+
// still-unacknowledged input. No turn is left in this pass.
|
|
5258
5264
|
if (directions) await directions.close();
|
|
5265
|
+
// A terminal progress card is presentation; it does not settle this row.
|
|
5266
|
+
// Keep an existing PR at its review gate when feedback produces no diff.
|
|
5267
|
+
if (runId && caps.runs && !iterateClaimId) {
|
|
5268
|
+
await tool("update_run", {
|
|
5269
|
+
runId,
|
|
5270
|
+
status: continuingPrUrl ? "awaiting_review" : staged.failed ? "failed" : "succeeded",
|
|
5271
|
+
...(continuingPrUrl ? { prUrl: continuingPrUrl } : {}),
|
|
5272
|
+
...(!continuingPrUrl ? { reason: staged.failed ? "coding-tool-failed" : "no-changes" } : {}),
|
|
5273
|
+
});
|
|
5274
|
+
}
|
|
5259
5275
|
return { status: staged.failed ? "run-failed" : "no-changes" };
|
|
5260
5276
|
};
|
|
5261
5277
|
if (staged.empty) return await finishEmptyTree({ afterDirection: afterCoding.advanced });
|