agentradar-cli 0.3.4 → 0.3.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/dist/secrets.js CHANGED
@@ -17,7 +17,8 @@ import { join } from "node:path";
17
17
  import { awpRequest, envValue } from "./tool-run.js";
18
18
  export const SECRETS_FILE = join(".agentradar", "secrets.enc");
19
19
  export const SECRETS_USAGE = "Usage: agentradar secrets pull|renew|env <runner-id> | agentradar secrets exec <runner-id> -- <command> [args...]"
20
- + " | agentradar secrets upload <runner-id> --env-file <path> | --from-env <NAME,...> | --prompt <NAME> [--only <NAME,...>] [--replace --approval-details '<json>'] [--token <token>]";
20
+ + " | agentradar secrets upload <runner-id> --env-file <path> | --from-env <NAME,...> | --prompt <NAME> [--only <NAME,...>] [--replace --approval-details '<json>'] [--token <token>]"
21
+ + " | agentradar secrets rotate <runner-id> --env-file <path> | --from-env <NAME,...> | --prompt <NAME> [--only <NAME,...>] [--token <token>]";
21
22
  /** The names the supervisor reserves for itself (supervise-agent.sh); a role secret never overrides one. */
22
23
  const RESERVED = /^(HOME|PATH|USER|LOGNAME|SHELL|TERM|COLORTERM|LANG|LC_[A-Z]+|TMPDIR|NODE_OPTIONS|CLAUDE_[A-Z_]+|CODEX_HOME|AR_[A-Z_]+|ANTHROPIC_API_KEY|AWP_[A-Z_]+|TMUX_SESSION|AGENT_PID_PATTERN|DISABLE_AUTOUPDATER)$/;
23
24
  /** The runner's own origin and key: its env file, else a hosted agent's run env (as tool-run.ts awpRequest). */
@@ -161,8 +162,9 @@ async function promptHidden(name) {
161
162
  /**
162
163
  * Vadym 11074: `agentradar secrets upload`. Values come from this machine (a .env file, the environment, a hidden prompt)
163
164
  * and never from the command line. Mints a slot with the `upload_secret` tool unless given its token, seals, posts once.
165
+ * SECRETS-PERMS (Vadym 11295): `agentradar secrets rotate` is the same with `rotate_secret`, for existing company secrets.
164
166
  */
165
- export async function secretsUpload(runnerId, flags, deps = {}) {
167
+ export async function secretsUpload(runnerId, flags, deps = {}, tool = "upload_secret") {
166
168
  const opts = new Map();
167
169
  for (let i = 0; i < flags.length; i++) {
168
170
  const flag = flags[i];
@@ -200,8 +202,8 @@ export async function secretsUpload(runnerId, flags, deps = {}) {
200
202
  let token = opts.get("token");
201
203
  if (!token) {
202
204
  const approvalDetails = opts.has("approval-details") ? JSON.parse(opts.get("approval-details")) : undefined;
203
- const said = await awpRequest(runnerId, "tools/call", { name: "upload_secret",
204
- arguments: { names: Object.keys(values), replace: opts.has("replace") || undefined, approvalDetails } }, deps);
205
+ const said = await awpRequest(runnerId, "tools/call", { name: tool, arguments: tool === "rotate_secret" ? { names: Object.keys(values) }
206
+ : { names: Object.keys(values), replace: opts.has("replace") || undefined, approvalDetails } }, deps);
205
207
  const minted = JSON.parse(said?.result?.content?.[0]?.text ?? "{}");
206
208
  if (!minted.ok || !minted.token)
207
209
  throw new Error(minted.error ?? "AgentRadar did not open an upload.");
@@ -237,6 +239,8 @@ export async function secretsOverCli(args, deps = {}) {
237
239
  return await secretsExec(runnerId, command, deps);
238
240
  if (verb === "upload" && runnerId)
239
241
  return await secretsUpload(runnerId, args.slice(2), deps);
242
+ if (verb === "rotate" && runnerId)
243
+ return await secretsUpload(runnerId, args.slice(2), deps, "rotate_secret");
240
244
  }
241
245
  catch (error) {
242
246
  (deps.logError ?? console.error)(error instanceof Error ? error.message : String(error));
@@ -89,6 +89,6 @@ else
89
89
  echo "LOADED: agentradar-agent@${AGENT_NAME} (could not enable linger; run 'loginctl enable-linger ${USER:-$(id -un)}' for boot-survival)"
90
90
  fi
91
91
  else
92
- echo "To load: install -m 644 '${UNIT}' ~/.config/systemd/user/ && systemctl --user daemon-reload && systemctl --user enable --now agentradar-agent@${AGENT_NAME} (+ loginctl enable-linger ${USER})"
92
+ echo "To load: install -m 644 '${UNIT}' ~/.config/systemd/user/ && systemctl --user daemon-reload && systemctl --user enable --now agentradar-agent@${AGENT_NAME} (+ loginctl enable-linger ${USER:-$(id -un)})"
93
93
  fi
94
94
  fi
@@ -400,6 +400,14 @@ ensure_agent() {
400
400
  # would run as a separate, UNISOLATED command in the supervisor's own shell. `bash -n` passes on
401
401
  # that — it is semantic, not syntactic — and a colour gate cannot see it either, because a pane that
402
402
  # never starts has nothing to colour. Caught by disc counting the args tmux actually received.
403
+ #
404
+ # The tmux CLIENT runs under `env -i` too. When this new-session starts the user's tmux server (first
405
+ # tmux after a reboot), the client's environment becomes the server's GLOBAL environment, inherited by
406
+ # every session anyone creates on that server later. Unscrubbed, the daemon's CLAUDE_CONFIG_DIR /
407
+ # CLAUDE_SETTINGS / plugin cache leaked into an unrelated always-on Claude session on the same Mac
408
+ # (2026-10-07): it read this agent's config dir, lost its trust state and transcript, and crash-looped.
409
+ env -i HOME="${HOME}" PATH="${PATH}" USER="${USER:-}" LANG="${LANG:-en_US.UTF-8}" \
410
+ LC_CTYPE="${AR_AGENT_LC_CTYPE:-en_US.UTF-8}" TMUX_TMPDIR="${TMUX_TMPDIR:-}" \
403
411
  "${TMUX_BIN}" new-session -d -s "${TMUX_SESSION}" -c "${AR_BASE}" \
404
412
  env -i \
405
413
  HOME="${HOME}" PATH="${PATH}" USER="${USER:-}" LOGNAME="${LOGNAME:-}" SHELL="${SHELL:-/bin/sh}" \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentradar-cli",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },