agentradar-cli 0.3.21 → 0.3.22

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Paperclip AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -30,7 +30,7 @@ Your primary objective is to reach your quotas and drive the company forward in
30
30
 
31
31
  ## Talking to humans
32
32
 
33
- Write to humans so a 13-year-old would understand: a few short plain lines, then one next step, not a list of ideas. No ids, paths, tool names, task codes or internal terms unless asked (say "your team", "company memory"; name a plan with its monthly price). Say money in dollars, never cents; give every link with what it opens. Answer only what was asked, and say it once. Talk to the event's `sender` as "you", never by name or as "the owner"; no persona from another chat carries over. Keep to what a human told you all chat, say so before a step they may not expect (a web search, sending, hiring), and never offer to contact anyone unless asked. Never talk about how messages reach you. Do the obvious thing for "undo that"; if unclear, offer short choices. Check your tools before saying what is scheduled or done, never from memory.
33
+ Write to humans so a 13-year-old would understand: a few short lines, then one next step, not a list of ideas. No ids, paths, tool names, task codes or internal terms unless asked (say "your team", "company memory"; name a plan with its monthly price). Say "human" for a human. Say money in dollars, never cents; give every link with what it opens. Answer only what was asked, and say it once. Talk to the event's `sender` as "you", never by name or as "the owner"; no persona from another chat carries over. Keep to what a human told you all chat, say so before a step they may not expect (a web search, sending, hiring), and never offer to contact anyone unless asked. Never talk about how messages reach you. Do the obvious thing for "undo that"; if unclear, offer short choices. Check your tools before saying what is scheduled or done, never from memory.
34
34
 
35
35
  ## Work loop
36
36
 
package/dist/channel.js CHANGED
@@ -122,6 +122,7 @@ export async function startChannel(runnerId, deps = {}) {
122
122
  // Vadym 10342: an unconfirmed channel is reported to AgentRadar (runnerState channel_unconfirmed), so the owner sees
123
123
  // the agent is not receiving messages; "ready" again once the session does run `inbox next`.
124
124
  let unconfirmed = null;
125
+ let reportedAt = 0;
125
126
  let warning;
126
127
  let skillSync;
127
128
  let teammateNotices;
@@ -203,13 +204,17 @@ export async function startChannel(runnerId, deps = {}) {
203
204
  if (unconfirmed === "pending") {
204
205
  await next({ runnerState: "channel_unconfirmed" });
205
206
  unconfirmed = "reported";
207
+ reportedAt = Date.now();
206
208
  }
207
209
  if (unconfirmed === "reported" && polled())
208
210
  unconfirmed = null;
209
211
  // While reported, no runnerState: the stored state stands, and the poll still drains for wake signals.
210
212
  // Receipt only: a preview still needs read_message before any reply (server gate). A "starting" poll cannot ack.
211
213
  const ack = guarded && unacked.length && calledSince(lastSent) ? unacked : null;
212
- const response = await next({ ...(unconfirmed ? {} : { runnerState: guarded ? "ready" : "starting" }), ...(ack ? { ackEventIds: ack } : {}) });
214
+ // While reported, a short hold: the session's first `inbox next` clears the flag within seconds, not after the 200 s empty-queue hold.
215
+ // After 10 min still unconfirmed, back to the full hold (the session is likely never confirming; ~450 polls/h otherwise).
216
+ const fast = unconfirmed && Date.now() - reportedAt < (deps.unconfirmedFastMs ?? 600_000);
217
+ const response = await next({ ...(unconfirmed ? (fast ? { waitMs: 5_000 } : {}) : { runnerState: guarded ? "ready" : "starting" }), ...(ack ? { ackEventIds: ack } : {}) });
213
218
  if (response.error || response.result?.isError)
214
219
  throw new Error("AgentRadar refused `agentradar run $AR_CLI_RUNNER_ID inbox next`; check the runner key and its poll permission");
215
220
  const content = response.result?.content;
package/dist/runner.js CHANGED
@@ -450,8 +450,22 @@ export async function startVendorRunner(runnerId, home = homedir(), deps = {}) {
450
450
  return false;
451
451
  };
452
452
  const shared = spawnChild("bash", [supervisor, envPath]);
453
- shared.once("error", (error) => { stop(); reject(error); });
453
+ // RUNNER-KILL-LEAVES-FEEDER: a `kill` reaches only this process, so pass it on to the supervisors, whose EXIT
454
+ // trap stops their feeders. Otherwise they outlive the runner and a restarted one delivers every event twice.
455
+ // SIGINT too: `kill -INT <pid>` reaches only the runner (Ctrl-C reaches the whole group anyway). SIGHUP (the
456
+ // vendor closes the terminal) only when a terminal runs it: a listener would undo a nohup start's ignored SIGHUP.
457
+ // The runner exits once the shared supervisor has; a second signal kills it at once.
458
+ const signals = deps.signals ?? process;
459
+ const names = (deps.hangup ?? process.stdout.isTTY === true)
460
+ ? ["SIGTERM", "SIGINT", "SIGHUP"] : ["SIGTERM", "SIGINT"];
461
+ const unlisten = () => { for (const name of names)
462
+ signals.off(name, forward); };
463
+ const forward = () => { unlisten(); stop(); shared.kill("SIGTERM"); };
464
+ for (const name of names)
465
+ signals.once(name, forward);
466
+ shared.once("error", (error) => { unlisten(); stop(); reject(error); });
454
467
  shared.once("exit", (code, signal) => {
468
+ unlisten();
455
469
  stop();
456
470
  if (!updating)
457
471
  return resolvePromise(code ?? (signal ? 1 : 0));
package/dist/tool-run.js CHANGED
@@ -247,7 +247,7 @@ const serviceTools = (runnerId, tools) => {
247
247
  /** Top-level `--help` headings (main 10-15: ~6 sections so 37 groups scan). */
248
248
  const SECTIONS = {
249
249
  Work: ["inbox", "threads", "tasks", "projects", "outcomes", "escalations", "interventions", "incidents", "briefs", "feedback", "me", "team", "browser", "files"],
250
- Channels: ["channels", "contacts", "webhooks", "integrations", "join-links", "onboarding"],
250
+ Channels: ["channels", "contacts", "webhooks", "integrations", "join-links", "onboarding", "telegram"],
251
251
  Access: ["permissions", "approvals", "secrets", "roles", "org-chart", "org"],
252
252
  Data: ["vaults", "memory", "skills", "metrics", "model", "hosting", "subscriptions", "selftest"],
253
253
  Money: ["spend", "wallet", "usage", "marketplace", "placement", "karma"],
@@ -790,7 +790,9 @@ export function paneInputReady(text, harness = AR_AGENT_HARNESS, readyPattern =
790
790
  * at 50, where the ❯ prompt and the bypass footer still show; the spinner line "✽ Sautéing… (24s · ↓ 105 tokens)"
791
791
  * shows at every width and turns into "✻ Worked for 13s" when the turn ends.
792
792
  */
793
- export const paneBusy = (text) => /\besc to (?:interrupt|cancel)\b/i.test(text ?? "")
793
+ // Hermes (hermes-agent 0.19.0) swaps its idle "❯" composer for "⚕ ❯ msg=interrupt · /queue · … Ctrl+C cancel" mid-turn,
794
+ // and text typed there interrupts the running turn, so the next event of a batch must wait for it.
795
+ export const paneBusy = (text) => /\besc to (?:interrupt|cancel)\b|\bmsg=interrupt\b/i.test(text ?? "")
794
796
  || /^\s*[^\w\s]\s+\S+…\s*\(\s*(?:\d+h\s*)?(?:\d+m\s*)?\d+s\b/m.test(text ?? "");
795
797
 
796
798
  /**
File without changes
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentradar-cli",
3
- "version": "0.3.21",
3
+ "version": "0.3.22",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },
@@ -34,16 +34,15 @@
34
34
  "publishConfig": {
35
35
  "access": "public"
36
36
  },
37
+ "devDependencies": {
38
+ "@types/node": "^22.20.5",
39
+ "typescript": "^5.7.3",
40
+ "vitest": "^4.1.8"
41
+ },
37
42
  "scripts": {
38
43
  "build": "tsc && mkdir -p dist/agentradar-vendor dist/vendor-runner/supervisor && cp ../../skills/agentradar-vendor/SKILL.md dist/agentradar-vendor/SKILL.md && cp ../../templates/vendor-runner/feeder.mjs ../../templates/vendor-runner/pane-live.sh ../../templates/vendor-runner/session-frame.mjs ../../templates/vendor-runner/skill-zip.mjs ../../templates/vendor-runner/terminal-bridge.mjs dist/vendor-runner/ && cp ../../templates/vendor-runner/supervisor/supervise-agent.sh ../../templates/vendor-runner/supervisor/install-agent.sh ../../templates/vendor-runner/supervisor/com.agentradar.agent.plist.template ../../templates/vendor-runner/supervisor/agentradar-agent@.service.template dist/vendor-runner/supervisor/ && rm -rf dist/agent-guard && cp -R ../../templates/agent-guard dist/agent-guard && rm dist/agent-guard/scripts/*.test.mjs && chmod +x dist/index.js dist/vendor-runner/pane-live.sh dist/vendor-runner/supervisor/supervise-agent.sh dist/vendor-runner/supervisor/install-agent.sh",
39
44
  "clean": "rm -rf dist",
40
- "prepack": "pnpm run build",
41
45
  "typecheck": "tsc --noEmit",
42
46
  "test": "vitest run"
43
- },
44
- "devDependencies": {
45
- "@types/node": "^22.20.5",
46
- "typescript": "^5.7.3",
47
- "vitest": "^4.1.8"
48
47
  }
49
- }
48
+ }