agentinbox-cli 0.1.0-nightly.29 → 0.1.0-nightly.30
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/{admin-CdP8RD4S.js → admin-8MQLrhsj.js} +4 -4
- package/dist/{admin-CdP8RD4S.js.map → admin-8MQLrhsj.js.map} +1 -1
- package/dist/cli.js +7 -7
- package/dist/{commands-Bl8pAaAn.js → commands-DxKT4tGy.js} +19 -19
- package/dist/{commands-Bl8pAaAn.js.map → commands-DxKT4tGy.js.map} +1 -1
- package/dist/{connect-BJBxb2jX.js → connect-CfxNALy5.js} +8 -8
- package/dist/{connect-BJBxb2jX.js.map → connect-CfxNALy5.js.map} +1 -1
- package/dist/{filter-DGVz6-P1.js → filter-Dl9GOkNe.js} +2 -2
- package/dist/{filter-DGVz6-P1.js.map → filter-Dl9GOkNe.js.map} +1 -1
- package/dist/instance-CkiEOmWa.js +2 -0
- package/dist/{instance-CsZuXUhl.js → instance-b-zilpyH.js} +2 -2
- package/dist/{instance-CsZuXUhl.js.map → instance-b-zilpyH.js.map} +1 -1
- package/dist/listen-BOHWwm_N.js +2 -0
- package/dist/{listen-D0folWg2.js → listen-cDUHSBkN.js} +6 -6
- package/dist/{listen-D0folWg2.js.map → listen-cDUHSBkN.js.map} +1 -1
- package/dist/{mcpheader-CXBiKYQn.js → mcpheader-CiJWpThH.js} +1 -1
- package/dist/{mcpheader-n5y3qdtI.js → mcpheader-Du6e5MGj.js} +2 -2
- package/dist/{mcpheader-n5y3qdtI.js.map → mcpheader-Du6e5MGj.js.map} +1 -1
- package/dist/mcpsetup-B9EH5659.js +2 -0
- package/dist/{mcpsetup-eJ8EAZYP.js → mcpsetup-CHQ9_Rbb.js} +4 -4
- package/dist/{mcpsetup-eJ8EAZYP.js.map → mcpsetup-CHQ9_Rbb.js.map} +1 -1
- package/dist/profile-K2QIOwX4.js +2 -0
- package/dist/{profile-CmTHXUK_.js → profile-uRinkfdm.js} +3 -3
- package/dist/{profile-CmTHXUK_.js.map → profile-uRinkfdm.js.map} +1 -1
- package/dist/{recipes-BvYwpZ6X.js → recipes-BQpXA6p1.js} +3 -3
- package/dist/{recipes-BvYwpZ6X.js.map → recipes-BQpXA6p1.js.map} +1 -1
- package/dist/recipes-QSyMVBiz.js +2 -0
- package/dist/{server-DQ9qc8Zp.js → server-CHIVVc1E.js} +123 -10
- package/dist/server-CHIVVc1E.js.map +1 -0
- package/dist/{service-DDH9FRVz.js → service-Bk4bGONc.js} +1 -1
- package/dist/{service-BRALQRRU.js → service-ChvWjnOR.js} +3 -3
- package/dist/{service-BRALQRRU.js.map → service-ChvWjnOR.js.map} +1 -1
- package/dist/{service-Cngp7vUP.js → service-D2IUVTXR.js} +1 -1
- package/dist/{service-CqBDLrpH.js → service-DXiBV61B.js} +4 -4
- package/dist/{service-CqBDLrpH.js.map → service-DXiBV61B.js.map} +1 -1
- package/dist/{types-3eEsBFVj.js → types-wY3IqC2D.js} +9 -2
- package/dist/types-wY3IqC2D.js.map +1 -0
- package/dist/web/assets/_agentId-BqzTDcZD.js +1 -0
- package/dist/web/assets/{_app-CVmQ7MLK.js → _app-C7fPyDq2.js} +1 -1
- package/dist/web/assets/{_app-DLq2Lyjd.js → _app-DgwuYgnY.js} +1 -1
- package/dist/web/assets/_webhookId-CgpQo4vc.js +1 -0
- package/dist/web/assets/{account-status-CrAJkcOr.js → account-status-DJ0qWvWa.js} +1 -1
- package/dist/web/assets/accounts-CbOWoMdP.js +1 -0
- package/dist/web/assets/{accounts-list-NsSsRdI3.js → accounts-list-DZevJmCK.js} +1 -1
- package/dist/web/assets/{agent-create-form-EJhevl9f.js → agent-create-form-BvCIE72U.js} +1 -1
- package/dist/web/assets/{agent-status-D6clBgxU.js → agent-status-BbmZYAXl.js} +1 -1
- package/dist/web/assets/{agents-4QzOCl4w.js → agents-CceZM3x2.js} +1 -1
- package/dist/web/assets/{approvals-DBLMEFhN.js → approvals-CAx6vOgX.js} +1 -1
- package/dist/web/assets/{attention-D3o1Ow1t.js → attention-CNzVKIFK.js} +1 -1
- package/dist/web/assets/{audit-7UCxqEM4.js → audit-B7aEP3m0.js} +1 -1
- package/dist/web/assets/{audit-bits-D4IdZgw6.js → audit-bits-BDWvLS1q.js} +1 -1
- package/dist/web/assets/{chips-input-IcqJzoRs.js → chips-input-CqlJWxP5.js} +1 -1
- package/dist/web/assets/{choice-cards-CuOTWDQV.js → choice-cards-BleSo0tf.js} +1 -1
- package/dist/web/assets/{command-DT-VjAH8.js → command-AXQYlyUG.js} +1 -1
- package/dist/web/assets/{common-Dgsni-y4.js → common-CYHl5rtl.js} +1 -1
- package/dist/web/assets/{connect-agent-guide-Lt6nyne7.js → connect-agent-guide-Dls13EN1.js} +1 -1
- package/dist/web/assets/connect-host-CJIdv0FX.js +6 -0
- package/dist/web/assets/{data-table-3VHub4f6.js → data-table-azFvp6rv.js} +1 -1
- package/dist/web/assets/{events-DWnG6W2j.js → events-DIFNutrL.js} +1 -1
- package/dist/web/assets/get-started-eioZ7d2-.js +1 -0
- package/dist/web/assets/index-D9cLH_cC.css +2 -0
- package/dist/web/assets/{index-BA6X8wDV.js → index-Db_9jgoe.js} +4 -4
- package/dist/web/assets/label-multi-select-BZsswbkd.js +1 -0
- package/dist/web/assets/{login-CdrOptU_.js → login-CADN0nRx.js} +1 -1
- package/dist/web/assets/{mutations-DhkIbcTW.js → mutations-v-10xhba.js} +1 -1
- package/dist/web/assets/{pairing-CzpZgY2W.js → pairing-B5noxLZT.js} +1 -1
- package/dist/web/assets/public-url-C5JBh_4V.js +1 -0
- package/dist/web/assets/select-COKkOCUQ.js +1 -0
- package/dist/web/assets/settings-BtMBK51Q.js +1 -0
- package/dist/web/assets/{setup-C5bXEPsc.js → setup-Bp-PaJW5.js} +1 -1
- package/dist/web/assets/{sheet-BLEj-8Ij.js → sheet-Dgp4Yt1H.js} +1 -1
- package/dist/web/assets/step-url-CQX7MVh1.js +1 -0
- package/dist/web/assets/{test-email-button-Cs3KWFJH.js → test-email-button-CzFAj2qJ.js} +1 -1
- package/dist/web/assets/{toggle-group-BGI6LcDX.js → toggle-group-Cf-1Z6pn.js} +1 -1
- package/dist/web/assets/use-delivery-speed-CKR1fpiI.js +1 -0
- package/dist/web/assets/{webhook-bits-Vs3yiIGs.js → webhook-bits-C1Czotz-.js} +1 -1
- package/dist/web/assets/{webhook-sheet-D9iyl9E_.js → webhook-sheet-BJmnyFT9.js} +1 -1
- package/dist/web/assets/webhooks-CrCs3Tr1.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/instance-DSOmQ7A5.js +0 -2
- package/dist/listen-BzpzZkb0.js +0 -2
- package/dist/mcpsetup-DJGd0z9y.js +0 -2
- package/dist/profile-CQ45PZKl.js +0 -2
- package/dist/recipes-BRsfXw8y.js +0 -2
- package/dist/server-DQ9qc8Zp.js.map +0 -1
- package/dist/types-3eEsBFVj.js.map +0 -1
- package/dist/web/assets/_agentId-zfONOtgk.js +0 -1
- package/dist/web/assets/_webhookId-CI1r9Wmt.js +0 -1
- package/dist/web/assets/accounts-C1DTVCe5.js +0 -1
- package/dist/web/assets/connect-host-DqBCdhnl.js +0 -6
- package/dist/web/assets/get-started-DxpwH7Q3.js +0 -1
- package/dist/web/assets/index-1Jgj6-wm.css +0 -2
- package/dist/web/assets/label-multi-select-BYOoYv8m.js +0 -1
- package/dist/web/assets/select-DiLqxcwi.js +0 -1
- package/dist/web/assets/settings-DJ4VtfU8.js +0 -1
- package/dist/web/assets/step-url-B3Rau4_j.js +0 -1
- package/dist/web/assets/webhooks-BBdfpukq.js +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { S as ApiError, a as pidAlive, b as Dispatcher, c as writeDead, d as forwardSecret, f as resolveListen, g as checkTransport, h as TransportError, l as DEFAULT_LISTEN_TYPES, m as forwardEvent, o as readDead, s as readStatus, w as getSelf, x as describeGrants, y as runCommand } from "./listen-
|
|
2
|
+
import { S as ApiError, a as pidAlive, b as Dispatcher, c as writeDead, d as forwardSecret, f as resolveListen, g as checkTransport, h as TransportError, l as DEFAULT_LISTEN_TYPES, m as forwardEvent, o as readDead, s as readStatus, w as getSelf, x as describeGrants, y as runCommand } from "./listen-cDUHSBkN.js";
|
|
3
3
|
import { i as safeText, r as formatDuration } from "./ui-B8Sd4Y7Y.js";
|
|
4
|
-
import { d as NPX, i as saveProfile, n as loadProfile, s as ensurePrivateDir } from "./profile-
|
|
4
|
+
import { d as NPX, i as saveProfile, n as loadProfile, s as ensurePrivateDir } from "./profile-uRinkfdm.js";
|
|
5
5
|
import { c as profilePath, i as deadPath, o as logPath, p as validProfileName } from "./paths-DckASYtc.js";
|
|
6
|
-
import { d as unitName, n as isServiceInstalled, r as launchdLabel } from "./service-
|
|
6
|
+
import { d as unitName, n as isServiceInstalled, r as launchdLabel } from "./service-DXiBV61B.js";
|
|
7
7
|
import pc from "picocolors";
|
|
8
8
|
//#region server/listen/admin.ts
|
|
9
9
|
const out = (s = "") => process.stdout.write(`${s}\n`);
|
|
@@ -197,4 +197,4 @@ async function replayDead(flags, opts = {}) {
|
|
|
197
197
|
//#endregion
|
|
198
198
|
export { clearDead, printDead, printSecret, printStatus, replayDead };
|
|
199
199
|
|
|
200
|
-
//# sourceMappingURL=admin-
|
|
200
|
+
//# sourceMappingURL=admin-8MQLrhsj.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-CdP8RD4S.js","names":[],"sources":["../server/listen/admin.ts"],"sourcesContent":["import pc from \"picocolors\";\nimport { ApiError, getSelf } from \"./api.ts\";\nimport { describeGrants } from \"./grants.ts\";\nimport { Dispatcher, type Job, type Target } from \"./dispatcher.ts\";\nimport { runCommand } from \"./exec.ts\";\nimport { ensurePrivateDir } from \"./fsutil.ts\";\nimport { forwardEvent } from \"./forward.ts\";\nimport { type ListenFlags, resolveListen } from \"./options.ts\";\nimport { DEFAULT_PROFILE, deadPath, logPath, profilePath, validProfileName } from \"./paths.ts\";\nimport { loadProfile, saveProfile } from \"./profile.ts\";\nimport { DEFAULT_LISTEN_TYPES, forwardSecret } from \"./options.ts\";\nimport { isServiceInstalled, launchdLabel, unitName } from \"./service.ts\";\nimport { type DeadEntry, pidAlive, readDead, readStatus, writeDead } from \"./state.ts\";\nimport { checkTransport, TransportError } from \"./transport.ts\";\nimport { formatDuration, safeText } from \"./ui.ts\";\nimport { NPX } from \"./version.ts\";\n\nconst out = (s = \"\") => process.stdout.write(`${s}\\n`);\nconst flagFor = (profile: string) => (profile === DEFAULT_PROFILE ? \"\" : ` --profile ${profile}`);\nconst ago = (iso: string | null | undefined) => (iso ? `${formatDuration(Date.now() - Date.parse(iso))} ago` : \"never\");\n\n// ───────────── listen secret ─────────────\n\n/** Prints the forward-mode signing secret (generating and saving it on first use). */\nexport function printSecret(profileName: string, opts: { rotate?: boolean }): void {\n const name = validProfileName(profileName);\n const profile = loadProfile(name);\n let { secret, created } = forwardSecret(profile);\n if (opts.rotate) {\n secret = forwardSecret({ ...profile, forward: undefined, forwardSecret: undefined }).secret;\n created = true;\n }\n if (created) {\n if (profile.forward) profile.forward = { ...profile.forward, secret };\n else profile.forwardSecret = secret;\n saveProfile(name, profile);\n process.stderr.write(pc.gray(`${opts.rotate ? \"Rotated\" : \"Generated\"} the forward signing secret for profile \"${name}\"${opts.rotate ? \"; restart the listener\" : \"\"}.\\n`));\n }\n // The secret alone on stdout, so `export AGENTINBOX_WEBHOOK_SECRET=$(agentinbox listen secret)` works.\n out(secret);\n}\n\n// ───────────── listen status ─────────────\n\nexport async function printStatus(profileName: string): Promise<void> {\n const name = validProfileName(profileName);\n const profile = loadProfile(name);\n const st = readStatus(name);\n const alive = st ? pidAlive(st.pid) && !st.stoppedAt : false;\n const dead = readDead(name);\n\n out(`${pc.bold(\"Profile\")} ${name} ${pc.gray(profilePath(name))}`);\n out(`${pc.bold(\"Agent\")} ${safeText(profile.agentName)} ${pc.gray(`(${profile.agentId})`)}`);\n out(`${pc.bold(\"Daemon\")} ${profile.url}`);\n out(`${pc.bold(\"Consumer\")} ${st?.consumer ?? profile.consumer}`);\n // What the last run used (flags included), else what the profile has saved.\n const exec = st && st.exec !== undefined ? st.exec : profile.exec;\n const forward = st && st.forward !== undefined ? st.forward : profile.forward?.url;\n const targets = [exec ? `exec ${safeText(exec, 120)}` : null, forward ? `forward ${forward}` : null].filter(Boolean);\n out(`${pc.bold(\"Runs\")} ${targets.length ? targets.join(\" · \") : pc.gray(\"nothing saved (pass --exec/--forward with --save)\")}`);\n out(\n `${pc.bold(\"Events\")} ${\n profile.types?.length\n ? profile.types.join(\", \")\n : `${DEFAULT_LISTEN_TYPES.join(\", \")} ${pc.gray(\"(default types; add --types all --save for every event)\")}`\n }`,\n );\n\n let svc = \"not installed\";\n if (process.platform === \"linux\" || process.platform === \"darwin\") {\n if (isServiceInstalled(name)) svc = `installed (${process.platform === \"linux\" ? unitName(name) : launchdLabel(name)}; details: ${NPX} listen service status${flagFor(name)})`;\n }\n out(`${pc.bold(\"Service\")} ${svc}`);\n\n try {\n // Never send the key over a connection `listen` itself would refuse.\n await checkTransport(profile.url, { insecure: profile.insecure });\n const self = await getSelf(profile.url, profile.apiKey, 5000);\n out(`${pc.bold(\"Key\")} ${pc.green(\"valid\")}`);\n // The access the console actually granted, in plain words (what the agent should report to its human).\n const lines = describeGrants(self.grants);\n out(`${pc.bold(\"Access\")} ${self.grants.length ? lines[0] : pc.yellow(lines[0]!)}`);\n for (const l of lines.slice(1)) out(` ${l}`);\n } catch (err) {\n const revoked = err instanceof ApiError && (err.status === 401 || err.status === 403);\n const why = err instanceof ApiError && err.status === 0 ? (err.cause as string) : err instanceof Error ? err.message.split(\"\\n\")[0] : String(err);\n if (err instanceof TransportError) out(`${pc.bold(\"Key\")} ${pc.red(`not checked: ${why}`)}`);\n else out(`${pc.bold(\"Key\")} ${revoked ? pc.red(`rejected: ${(err as Error).message}`) : pc.yellow(`not checked (${why})`)}`);\n }\n\n if (!st) {\n out(`${pc.bold(\"Listener\")} ${pc.gray(\"has not run yet\")}`);\n } else {\n const state = !alive\n ? pc.gray(`not running${st.stoppedAt ? ` (stopped ${ago(st.stoppedAt)}${st.exitReason ? `: ${safeText(st.exitReason, 160)}` : \"\"})` : \" (exited unexpectedly)\"}`)\n : st.connected\n ? pc.green(`running (pid ${st.pid}), connected ${ago(st.connectedSince)}`)\n : pc.yellow(`running (pid ${st.pid}), disconnected${st.lastDisconnect ? ` ${ago(st.lastDisconnect.at)}: ${safeText(st.lastDisconnect.reason, 160)}` : \"\"}`);\n out(`${pc.bold(\"Listener\")} ${state}`);\n out(`${pc.bold(\"Cursor\")} acked #${st.ackedSeq} · received #${st.receivedSeq}${alive && st.running ? ` · ${st.running} in progress` : \"\"} · last event ${ago(st.lastEventAt)}`);\n if (st.recent.length) {\n out(pc.bold(\"Recent\"));\n for (const r of st.recent.slice(0, 8)) {\n const icon = r.outcome === \"succeeded\" ? pc.green(\"✓\") : r.outcome === \"dead\" ? pc.red(\"✖\") : r.outcome === \"retrying\" ? pc.yellow(\"↻\") : pc.gray(\"·\");\n out(` ${icon} #${r.seq} ${r.type} ${pc.gray(`${ago(r.at)}${r.attempts > 1 ? `, ${r.attempts} attempts` : \"\"}${r.error && r.outcome !== \"succeeded\" ? `, ${safeText(r.error, 100)}` : \"\"}`)}`);\n }\n }\n }\n out(`${pc.bold(\"Dead\")} ${dead.length ? pc.red(`${dead.length} event${dead.length > 1 ? \"s\" : \"\"}`) + pc.gray(` (inspect: ${NPX} listen dead${flagFor(name)})`) : \"0\"}`);\n out(`${pc.bold(\"Log\")} ${logPath(name)}`);\n}\n\n// ───────────── listen dead ─────────────\n\nexport function printDead(profileName: string, opts: { json?: boolean }): void {\n const name = validProfileName(profileName);\n const entries = readDead(name);\n if (opts.json) {\n for (const e of entries) out(JSON.stringify(e));\n return;\n }\n if (!entries.length) {\n out(`No dead events for profile \"${name}\".`);\n return;\n }\n for (const e of entries) {\n const m = e.payload.data.message;\n out(`${pc.red(\"✖\")} #${e.seq} ${e.type} ${pc.gray(e.id)} ${pc.gray(`died ${ago(e.deadAt)} after ${e.attempts} attempts`)}`);\n if (m) out(` from ${safeText(m.from?.email ?? \"?\", 80)} \"${safeText(m.subject, 80)}\"`);\n out(pc.gray(` ${safeText(e.error, 300)}`));\n }\n out();\n out(pc.gray(`${entries.length} dead event${entries.length > 1 ? \"s\" : \"\"} in ${deadPath(name)}.`));\n out(pc.gray(`Replay with: ${NPX} listen dead --replay${flagFor(name)} (one: --id <evt_…>; drop all: --clear)`));\n out(pc.gray(`Replay uses the profile's saved --exec/--forward; if you ran them as flags only, pass them again, e.g. --replay --exec '<command>'.`));\n}\n\nexport function clearDead(profileName: string, id?: string): void {\n const name = validProfileName(profileName);\n const entries = readDead(name);\n const keep = id ? entries.filter((e) => e.id !== id) : [];\n writeDead(name, keep);\n out(`Removed ${entries.length - keep.length} dead event${entries.length - keep.length === 1 ? \"\" : \"s\"}.`);\n}\n\n/**\n * Runs dead events again through the profile's targets (or the ones passed as flags). Successes are\n * removed from dead.jsonl; failures stay. Returns how many still failed.\n */\nexport async function replayDead(flags: ListenFlags & { id?: string }, opts: { retryDelayMs?: (n: number) => number } = {}): Promise<number> {\n const name = validProfileName(flags.profile ?? DEFAULT_PROFILE);\n const profile = loadProfile(name);\n const { config } = resolveListen(name, profile, { ...flags, save: false });\n const all = readDead(name);\n const chosen = all.filter((e) => !flags.id || e.id === flags.id);\n if (!chosen.length) {\n out(flags.id ? `No dead event with id ${flags.id}.` : `No dead events for profile \"${name}\".`);\n return 0;\n }\n const available: Target[] = [];\n if (config.exec) available.push(\"exec\");\n if (config.forward) available.push(\"forward\");\n if (!available.length) throw new Error(`Nothing to replay to: pass --exec '<command>' and/or --forward <url> (or save them in the profile with \\`${NPX} listen --save …\\`).`);\n if (config.exec && process.platform === \"win32\") throw new Error(\"--exec isn't supported on Windows; replay with --forward instead.\");\n\n const timeoutMs = config.timeoutSeconds * 1000;\n if (config.cwdIsDefault) ensurePrivateDir(config.cwd);\n const failed = new Map<string, DeadEntry>();\n const bySeq = new Map(chosen.map((e) => [e.seq, e]));\n const dispatcher = new Dispatcher({\n targets: available,\n concurrency: config.concurrency,\n maxAttempts: config.maxAttempts,\n retryDelayMs: opts.retryDelayMs,\n run: async (job: Job, signal) => {\n const errors: string[] = [];\n if (job.remaining.has(\"exec\") && config.exec) {\n const r = await runCommand(config.exec, job.payload, { timeoutMs, signal, cwd: config.cwd });\n if (r.ok) job.remaining.delete(\"exec\");\n else errors.push(`command: ${r.error}`);\n }\n if (job.remaining.has(\"forward\") && config.forward) {\n const r = await forwardEvent(config.forward.url, config.forward.secret, job.payload, { timeoutMs: Math.min(timeoutMs, 30_000), signal });\n if (r.ok) job.remaining.delete(\"forward\");\n else errors.push(`forward: ${r.error}`);\n }\n return errors;\n },\n onAdvance: () => {},\n onDead: (job) => {\n const e = bySeq.get(job.seq)!;\n failed.set(e.id, { ...e, deadAt: new Date().toISOString(), attempts: e.attempts + job.attempts, error: job.lastError ?? \"failed\" });\n out(`${pc.red(\"✖\")} #${job.seq} still failing: ${safeText(job.lastError ?? \"failed\", 200)}`);\n },\n onFinished: (job) => {\n if (job.outcome === \"succeeded\") out(`${pc.green(\"✓\")} #${job.seq} ${job.payload.type} replayed`);\n },\n });\n out(`Replaying ${chosen.length} dead event${chosen.length > 1 ? \"s\" : \"\"} (up to ${config.maxAttempts} attempts each)…`);\n // Only the targets that never succeeded (a forward that went through isn't POSTed again).\n for (const e of [...chosen].sort((a, b) => a.seq - b.seq)) {\n const targets = e.targets?.length ? e.targets.filter((t) => available.includes(t)) : available;\n if (!targets.length) {\n out(`${pc.yellow(\"!\")} #${e.seq} needs ${e.targets.join(\" and \")}, which isn't configured now; pass --${e.targets[0]} to replay it.`);\n failed.set(e.id, e);\n continue;\n }\n dispatcher.push(e.payload, { targets });\n }\n await dispatcher.idle();\n\n const replayed = new Set(chosen.map((e) => e.id));\n // Re-read so entries added by a running listener meanwhile are kept.\n const current = readDead(name);\n writeDead(name, [...current.filter((e) => !replayed.has(e.id)), ...failed.values()]);\n out(`${chosen.length - failed.size} replayed, ${failed.size} still dead.`);\n return failed.size;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"admin-8MQLrhsj.js","names":[],"sources":["../server/listen/admin.ts"],"sourcesContent":["import pc from \"picocolors\";\nimport { ApiError, getSelf } from \"./api.ts\";\nimport { describeGrants } from \"./grants.ts\";\nimport { Dispatcher, type Job, type Target } from \"./dispatcher.ts\";\nimport { runCommand } from \"./exec.ts\";\nimport { ensurePrivateDir } from \"./fsutil.ts\";\nimport { forwardEvent } from \"./forward.ts\";\nimport { type ListenFlags, resolveListen } from \"./options.ts\";\nimport { DEFAULT_PROFILE, deadPath, logPath, profilePath, validProfileName } from \"./paths.ts\";\nimport { loadProfile, saveProfile } from \"./profile.ts\";\nimport { DEFAULT_LISTEN_TYPES, forwardSecret } from \"./options.ts\";\nimport { isServiceInstalled, launchdLabel, unitName } from \"./service.ts\";\nimport { type DeadEntry, pidAlive, readDead, readStatus, writeDead } from \"./state.ts\";\nimport { checkTransport, TransportError } from \"./transport.ts\";\nimport { formatDuration, safeText } from \"./ui.ts\";\nimport { NPX } from \"./version.ts\";\n\nconst out = (s = \"\") => process.stdout.write(`${s}\\n`);\nconst flagFor = (profile: string) => (profile === DEFAULT_PROFILE ? \"\" : ` --profile ${profile}`);\nconst ago = (iso: string | null | undefined) => (iso ? `${formatDuration(Date.now() - Date.parse(iso))} ago` : \"never\");\n\n// ───────────── listen secret ─────────────\n\n/** Prints the forward-mode signing secret (generating and saving it on first use). */\nexport function printSecret(profileName: string, opts: { rotate?: boolean }): void {\n const name = validProfileName(profileName);\n const profile = loadProfile(name);\n let { secret, created } = forwardSecret(profile);\n if (opts.rotate) {\n secret = forwardSecret({ ...profile, forward: undefined, forwardSecret: undefined }).secret;\n created = true;\n }\n if (created) {\n if (profile.forward) profile.forward = { ...profile.forward, secret };\n else profile.forwardSecret = secret;\n saveProfile(name, profile);\n process.stderr.write(pc.gray(`${opts.rotate ? \"Rotated\" : \"Generated\"} the forward signing secret for profile \"${name}\"${opts.rotate ? \"; restart the listener\" : \"\"}.\\n`));\n }\n // The secret alone on stdout, so `export AGENTINBOX_WEBHOOK_SECRET=$(agentinbox listen secret)` works.\n out(secret);\n}\n\n// ───────────── listen status ─────────────\n\nexport async function printStatus(profileName: string): Promise<void> {\n const name = validProfileName(profileName);\n const profile = loadProfile(name);\n const st = readStatus(name);\n const alive = st ? pidAlive(st.pid) && !st.stoppedAt : false;\n const dead = readDead(name);\n\n out(`${pc.bold(\"Profile\")} ${name} ${pc.gray(profilePath(name))}`);\n out(`${pc.bold(\"Agent\")} ${safeText(profile.agentName)} ${pc.gray(`(${profile.agentId})`)}`);\n out(`${pc.bold(\"Daemon\")} ${profile.url}`);\n out(`${pc.bold(\"Consumer\")} ${st?.consumer ?? profile.consumer}`);\n // What the last run used (flags included), else what the profile has saved.\n const exec = st && st.exec !== undefined ? st.exec : profile.exec;\n const forward = st && st.forward !== undefined ? st.forward : profile.forward?.url;\n const targets = [exec ? `exec ${safeText(exec, 120)}` : null, forward ? `forward ${forward}` : null].filter(Boolean);\n out(`${pc.bold(\"Runs\")} ${targets.length ? targets.join(\" · \") : pc.gray(\"nothing saved (pass --exec/--forward with --save)\")}`);\n out(\n `${pc.bold(\"Events\")} ${\n profile.types?.length\n ? profile.types.join(\", \")\n : `${DEFAULT_LISTEN_TYPES.join(\", \")} ${pc.gray(\"(default types; add --types all --save for every event)\")}`\n }`,\n );\n\n let svc = \"not installed\";\n if (process.platform === \"linux\" || process.platform === \"darwin\") {\n if (isServiceInstalled(name)) svc = `installed (${process.platform === \"linux\" ? unitName(name) : launchdLabel(name)}; details: ${NPX} listen service status${flagFor(name)})`;\n }\n out(`${pc.bold(\"Service\")} ${svc}`);\n\n try {\n // Never send the key over a connection `listen` itself would refuse.\n await checkTransport(profile.url, { insecure: profile.insecure });\n const self = await getSelf(profile.url, profile.apiKey, 5000);\n out(`${pc.bold(\"Key\")} ${pc.green(\"valid\")}`);\n // The access the console actually granted, in plain words (what the agent should report to its human).\n const lines = describeGrants(self.grants);\n out(`${pc.bold(\"Access\")} ${self.grants.length ? lines[0] : pc.yellow(lines[0]!)}`);\n for (const l of lines.slice(1)) out(` ${l}`);\n } catch (err) {\n const revoked = err instanceof ApiError && (err.status === 401 || err.status === 403);\n const why = err instanceof ApiError && err.status === 0 ? (err.cause as string) : err instanceof Error ? err.message.split(\"\\n\")[0] : String(err);\n if (err instanceof TransportError) out(`${pc.bold(\"Key\")} ${pc.red(`not checked: ${why}`)}`);\n else out(`${pc.bold(\"Key\")} ${revoked ? pc.red(`rejected: ${(err as Error).message}`) : pc.yellow(`not checked (${why})`)}`);\n }\n\n if (!st) {\n out(`${pc.bold(\"Listener\")} ${pc.gray(\"has not run yet\")}`);\n } else {\n const state = !alive\n ? pc.gray(`not running${st.stoppedAt ? ` (stopped ${ago(st.stoppedAt)}${st.exitReason ? `: ${safeText(st.exitReason, 160)}` : \"\"})` : \" (exited unexpectedly)\"}`)\n : st.connected\n ? pc.green(`running (pid ${st.pid}), connected ${ago(st.connectedSince)}`)\n : pc.yellow(`running (pid ${st.pid}), disconnected${st.lastDisconnect ? ` ${ago(st.lastDisconnect.at)}: ${safeText(st.lastDisconnect.reason, 160)}` : \"\"}`);\n out(`${pc.bold(\"Listener\")} ${state}`);\n out(`${pc.bold(\"Cursor\")} acked #${st.ackedSeq} · received #${st.receivedSeq}${alive && st.running ? ` · ${st.running} in progress` : \"\"} · last event ${ago(st.lastEventAt)}`);\n if (st.recent.length) {\n out(pc.bold(\"Recent\"));\n for (const r of st.recent.slice(0, 8)) {\n const icon = r.outcome === \"succeeded\" ? pc.green(\"✓\") : r.outcome === \"dead\" ? pc.red(\"✖\") : r.outcome === \"retrying\" ? pc.yellow(\"↻\") : pc.gray(\"·\");\n out(` ${icon} #${r.seq} ${r.type} ${pc.gray(`${ago(r.at)}${r.attempts > 1 ? `, ${r.attempts} attempts` : \"\"}${r.error && r.outcome !== \"succeeded\" ? `, ${safeText(r.error, 100)}` : \"\"}`)}`);\n }\n }\n }\n out(`${pc.bold(\"Dead\")} ${dead.length ? pc.red(`${dead.length} event${dead.length > 1 ? \"s\" : \"\"}`) + pc.gray(` (inspect: ${NPX} listen dead${flagFor(name)})`) : \"0\"}`);\n out(`${pc.bold(\"Log\")} ${logPath(name)}`);\n}\n\n// ───────────── listen dead ─────────────\n\nexport function printDead(profileName: string, opts: { json?: boolean }): void {\n const name = validProfileName(profileName);\n const entries = readDead(name);\n if (opts.json) {\n for (const e of entries) out(JSON.stringify(e));\n return;\n }\n if (!entries.length) {\n out(`No dead events for profile \"${name}\".`);\n return;\n }\n for (const e of entries) {\n const m = e.payload.data.message;\n out(`${pc.red(\"✖\")} #${e.seq} ${e.type} ${pc.gray(e.id)} ${pc.gray(`died ${ago(e.deadAt)} after ${e.attempts} attempts`)}`);\n if (m) out(` from ${safeText(m.from?.email ?? \"?\", 80)} \"${safeText(m.subject, 80)}\"`);\n out(pc.gray(` ${safeText(e.error, 300)}`));\n }\n out();\n out(pc.gray(`${entries.length} dead event${entries.length > 1 ? \"s\" : \"\"} in ${deadPath(name)}.`));\n out(pc.gray(`Replay with: ${NPX} listen dead --replay${flagFor(name)} (one: --id <evt_…>; drop all: --clear)`));\n out(pc.gray(`Replay uses the profile's saved --exec/--forward; if you ran them as flags only, pass them again, e.g. --replay --exec '<command>'.`));\n}\n\nexport function clearDead(profileName: string, id?: string): void {\n const name = validProfileName(profileName);\n const entries = readDead(name);\n const keep = id ? entries.filter((e) => e.id !== id) : [];\n writeDead(name, keep);\n out(`Removed ${entries.length - keep.length} dead event${entries.length - keep.length === 1 ? \"\" : \"s\"}.`);\n}\n\n/**\n * Runs dead events again through the profile's targets (or the ones passed as flags). Successes are\n * removed from dead.jsonl; failures stay. Returns how many still failed.\n */\nexport async function replayDead(flags: ListenFlags & { id?: string }, opts: { retryDelayMs?: (n: number) => number } = {}): Promise<number> {\n const name = validProfileName(flags.profile ?? DEFAULT_PROFILE);\n const profile = loadProfile(name);\n const { config } = resolveListen(name, profile, { ...flags, save: false });\n const all = readDead(name);\n const chosen = all.filter((e) => !flags.id || e.id === flags.id);\n if (!chosen.length) {\n out(flags.id ? `No dead event with id ${flags.id}.` : `No dead events for profile \"${name}\".`);\n return 0;\n }\n const available: Target[] = [];\n if (config.exec) available.push(\"exec\");\n if (config.forward) available.push(\"forward\");\n if (!available.length) throw new Error(`Nothing to replay to: pass --exec '<command>' and/or --forward <url> (or save them in the profile with \\`${NPX} listen --save …\\`).`);\n if (config.exec && process.platform === \"win32\") throw new Error(\"--exec isn't supported on Windows; replay with --forward instead.\");\n\n const timeoutMs = config.timeoutSeconds * 1000;\n if (config.cwdIsDefault) ensurePrivateDir(config.cwd);\n const failed = new Map<string, DeadEntry>();\n const bySeq = new Map(chosen.map((e) => [e.seq, e]));\n const dispatcher = new Dispatcher({\n targets: available,\n concurrency: config.concurrency,\n maxAttempts: config.maxAttempts,\n retryDelayMs: opts.retryDelayMs,\n run: async (job: Job, signal) => {\n const errors: string[] = [];\n if (job.remaining.has(\"exec\") && config.exec) {\n const r = await runCommand(config.exec, job.payload, { timeoutMs, signal, cwd: config.cwd });\n if (r.ok) job.remaining.delete(\"exec\");\n else errors.push(`command: ${r.error}`);\n }\n if (job.remaining.has(\"forward\") && config.forward) {\n const r = await forwardEvent(config.forward.url, config.forward.secret, job.payload, { timeoutMs: Math.min(timeoutMs, 30_000), signal });\n if (r.ok) job.remaining.delete(\"forward\");\n else errors.push(`forward: ${r.error}`);\n }\n return errors;\n },\n onAdvance: () => {},\n onDead: (job) => {\n const e = bySeq.get(job.seq)!;\n failed.set(e.id, { ...e, deadAt: new Date().toISOString(), attempts: e.attempts + job.attempts, error: job.lastError ?? \"failed\" });\n out(`${pc.red(\"✖\")} #${job.seq} still failing: ${safeText(job.lastError ?? \"failed\", 200)}`);\n },\n onFinished: (job) => {\n if (job.outcome === \"succeeded\") out(`${pc.green(\"✓\")} #${job.seq} ${job.payload.type} replayed`);\n },\n });\n out(`Replaying ${chosen.length} dead event${chosen.length > 1 ? \"s\" : \"\"} (up to ${config.maxAttempts} attempts each)…`);\n // Only the targets that never succeeded (a forward that went through isn't POSTed again).\n for (const e of [...chosen].sort((a, b) => a.seq - b.seq)) {\n const targets = e.targets?.length ? e.targets.filter((t) => available.includes(t)) : available;\n if (!targets.length) {\n out(`${pc.yellow(\"!\")} #${e.seq} needs ${e.targets.join(\" and \")}, which isn't configured now; pass --${e.targets[0]} to replay it.`);\n failed.set(e.id, e);\n continue;\n }\n dispatcher.push(e.payload, { targets });\n }\n await dispatcher.idle();\n\n const replayed = new Set(chosen.map((e) => e.id));\n // Re-read so entries added by a running listener meanwhile are kept.\n const current = readDead(name);\n writeDead(name, [...current.filter((e) => !replayed.has(e.id)), ...failed.values()]);\n out(`${chosen.length - failed.size} replayed, ${failed.size} still dead.`);\n return failed.size;\n}\n"],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -76,7 +76,7 @@ const SERVER_GROUP = "Run agentinbox:";
|
|
|
76
76
|
const AGENT_GROUP = "On an agent's machine:";
|
|
77
77
|
withServerOptions(program.command("start", { isDefault: true }).description("run agentinbox in this terminal and print the setup link (the default command)").summary("run it in this terminal (the default command)").helpGroup(SERVER_GROUP)).option("--no-open", "don't open a browser on first run").option("--dev", "development: API only, the console runs on Vite (:5173)").allowExcessArguments().action(async (o, cmd) => {
|
|
78
78
|
if (cmd.args.length) throw new Error(unknownCommand(cmd.args[0]));
|
|
79
|
-
const { runForeground } = await import("./server-
|
|
79
|
+
const { runForeground } = await import("./server-CHIVVc1E.js");
|
|
80
80
|
await runForeground({
|
|
81
81
|
...configInput(o),
|
|
82
82
|
dev: !!o.dev,
|
|
@@ -87,15 +87,15 @@ withServerOptions(program.command("start", { isDefault: true }).description("run
|
|
|
87
87
|
const service = program.command("service").description("run agentinbox in the background as a systemd / launchd service, started at boot").summary("run it in the background (systemd / launchd)").helpGroup(SERVER_GROUP);
|
|
88
88
|
withServerOptions(service.command("install").description("install and start the service; re-run it to change the port or update")).action(async (o) => {
|
|
89
89
|
const { loadConfig } = await import("./config-DS2ClYL5.js");
|
|
90
|
-
const { installService } = await import("./service-
|
|
90
|
+
const { installService } = await import("./service-Bk4bGONc.js");
|
|
91
91
|
await installService(loadConfig(configInput(o), version));
|
|
92
92
|
});
|
|
93
93
|
service.command("uninstall").description("stop and remove the service (keeps your data)").option("-d, --data <dir>", "data directory, if the installed service doesn't say (default ~/.agentinbox, env AGENTINBOX_DATA)").action(async (o) => {
|
|
94
|
-
const { uninstallService } = await import("./service-
|
|
94
|
+
const { uninstallService } = await import("./service-Bk4bGONc.js");
|
|
95
95
|
uninstallService({ dataDir: resolve(o.data ?? process.env.AGENTINBOX_DATA ?? join(homedir(), ".agentinbox")) });
|
|
96
96
|
});
|
|
97
97
|
service.command("status").description("show service status").action(async () => {
|
|
98
|
-
const { serviceStatus } = await import("./service-
|
|
98
|
+
const { serviceStatus } = await import("./service-Bk4bGONc.js");
|
|
99
99
|
serviceStatus();
|
|
100
100
|
});
|
|
101
101
|
const skill = program.command("skill").description("the agentinbox agent skill (SKILL.md): teaches an agent how to use agentinbox's tools").summary("install the agent skill (SKILL.md)").helpGroup(AGENT_GROUP);
|
|
@@ -122,7 +122,7 @@ program.command("reset-password").description("forgot the console password? Remo
|
|
|
122
122
|
const { SettingsStore } = await import("./settings-CqouaxRg.js");
|
|
123
123
|
const { AuditLog } = await import("./audit-BVpTUgLt.js");
|
|
124
124
|
const { currentSetupToken, isClaimed, resetAdminPassword } = await import("./auth-D_FWbtRd.js");
|
|
125
|
-
const { runningInstance } = await import("./instance-
|
|
125
|
+
const { runningInstance } = await import("./instance-CkiEOmWa.js");
|
|
126
126
|
const { consoleUrls } = await import("./urls-Dp8pBGMU.js");
|
|
127
127
|
const running = runningInstance(dataDir);
|
|
128
128
|
const config = loadConfig({
|
|
@@ -151,7 +151,7 @@ program.command("reset-password").description("forgot the console password? Remo
|
|
|
151
151
|
db.close();
|
|
152
152
|
}
|
|
153
153
|
});
|
|
154
|
-
const { registerListenCommands } = await import("./commands-
|
|
154
|
+
const { registerListenCommands } = await import("./commands-DxKT4tGy.js");
|
|
155
155
|
registerListenCommands(program);
|
|
156
156
|
const AGENT_SUMMARIES = {
|
|
157
157
|
connect: "pair an agent; you approve it in the console",
|
|
@@ -171,7 +171,7 @@ program.commandsGroup(SERVER_GROUP).helpCommand("help [command]", "show help for
|
|
|
171
171
|
async function serverUrl(flag) {
|
|
172
172
|
let raw = flag ?? process.env.AGENTINBOX_URL;
|
|
173
173
|
if (!raw) {
|
|
174
|
-
const { runningInstance } = await import("./instance-
|
|
174
|
+
const { runningInstance } = await import("./instance-CkiEOmWa.js");
|
|
175
175
|
const running = runningInstance(resolve(process.env.AGENTINBOX_DATA || join(homedir(), ".agentinbox")));
|
|
176
176
|
const host = running && ![
|
|
177
177
|
"0.0.0.0",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as EVENT_TYPES } from "./types-
|
|
3
|
-
import { d as NPX } from "./profile-
|
|
2
|
+
import { n as EVENT_TYPES } from "./types-wY3IqC2D.js";
|
|
3
|
+
import { d as NPX } from "./profile-uRinkfdm.js";
|
|
4
4
|
import { t as DEFAULT_PROFILE } from "./paths-DckASYtc.js";
|
|
5
|
-
import { a as recipesHelp, t as TOOLS } from "./recipes-
|
|
5
|
+
import { a as recipesHelp, t as TOOLS } from "./recipes-BQpXA6p1.js";
|
|
6
6
|
import { InvalidArgumentError } from "commander";
|
|
7
7
|
//#region server/listen/commands.ts
|
|
8
8
|
/** `agentinbox connect`, `agentinbox setup-mcp` and `agentinbox listen …`, all lazily loaded. */
|
|
@@ -48,19 +48,19 @@ Exit codes: 0 approved, 2 denied, 3 expired, 4 already consumed, 130 cancelled,
|
|
|
48
48
|
|
|
49
49
|
Example:
|
|
50
50
|
${NPX} connect https://mail.example.com --tool claude-code --setup-mcp`).action(async (url, flags) => {
|
|
51
|
-
const { runConnect } = await import("./connect-
|
|
51
|
+
const { runConnect } = await import("./connect-CfxNALy5.js");
|
|
52
52
|
process.exit(await runConnect(url, flags, { handleSignals: true }));
|
|
53
53
|
});
|
|
54
54
|
profileOption(program.command("setup-mcp").description("register the agentinbox MCP server in your agent's tool, without showing the key")).option("--tool <tool>", `${TOOLS.filter((t) => t !== "other").join(", ")} (default: the tool given to connect)`).option("--dry-run", "print the exact commands and file changes, and change nothing").addHelpText("after", mcpSetupHelp()).action(async (flags) => {
|
|
55
|
-
const { parseTool, printMcpResult } = await import("./connect-
|
|
56
|
-
const { loadProfile } = await import("./profile-
|
|
57
|
-
const { setupMcp, mcpTarget } = await import("./mcpsetup-
|
|
55
|
+
const { parseTool, printMcpResult } = await import("./connect-CfxNALy5.js");
|
|
56
|
+
const { loadProfile } = await import("./profile-K2QIOwX4.js");
|
|
57
|
+
const { setupMcp, mcpTarget } = await import("./mcpsetup-B9EH5659.js");
|
|
58
58
|
const { profilePath } = await import("./paths-BMavi0Uq.js");
|
|
59
59
|
const name = flags.profile ?? "default";
|
|
60
60
|
const profile = loadProfile(name);
|
|
61
61
|
const tool = flags.tool ? parseTool(flags.tool) : profile.tool ?? "other";
|
|
62
62
|
if (tool === "other") throw new Error(`Which tool? Pass --tool ${TOOLS.filter((t) => t !== "other").join("|")}.`);
|
|
63
|
-
const { claudeMcpConfigPath, writeClaudeMcpConfig } = await import("./mcpheader-
|
|
63
|
+
const { claudeMcpConfigPath, writeClaudeMcpConfig } = await import("./mcpheader-CiJWpThH.js");
|
|
64
64
|
const r = setupMcp(tool, mcpTarget(name, profile), profilePath(name), { dryRun: flags.dryRun });
|
|
65
65
|
if (flags.dryRun) r.changes = [...r.changes ?? [], `refresh ${claudeMcpConfigPath(name)} (keyless MCP config the Claude Code listen recipe loads)`];
|
|
66
66
|
else writeClaudeMcpConfig(name, `${profile.url}/mcp`);
|
|
@@ -68,17 +68,17 @@ Example:
|
|
|
68
68
|
if (!r.ok) process.exitCode = 1;
|
|
69
69
|
});
|
|
70
70
|
profileOption(program.command("mcp-header").description("print the agent's Authorization header as JSON for an MCP client's header helper (refuses to print to a terminal)")).action(async (flags) => {
|
|
71
|
-
const { printMcpHeader } = await import("./mcpheader-
|
|
71
|
+
const { printMcpHeader } = await import("./mcpheader-CiJWpThH.js");
|
|
72
72
|
process.exitCode = printMcpHeader(flags.profile ?? "default");
|
|
73
73
|
});
|
|
74
74
|
const listen = listenFlags(program.command("listen").description("wake a local agent on new mail: hold an outbound stream to the daemon and run a command or POST to localhost per event")).option("--dry-run", "print matching events without running anything (uses a throwaway <consumer>-dry-run cursor)").option("--from-start", "a NEW consumer starts at the oldest stored event (no effect once it exists: use --backfill)").option("--backfill", "run the mail from before this listener started through --exec/--forward once, oldest first, then exit; safe while the listener runs (own cursor)").option("--until <seq>", "with --backfill: replay up to this event number instead of where the listener started", int("--until")).option("--print-recipe <tool>", `print the ready-made --exec command for ${TOOLS.join(", ")} (with this machine's paths) and exit`).addHelpText("after", recipesHelp()).action(async (flags) => {
|
|
75
75
|
if (flags.printRecipe !== void 0) {
|
|
76
|
-
const { parseTool } = await import("./connect-
|
|
77
|
-
const { recipe } = await import("./recipes-
|
|
76
|
+
const { parseTool } = await import("./connect-CfxNALy5.js");
|
|
77
|
+
const { recipe } = await import("./recipes-QSyMVBiz.js");
|
|
78
78
|
process.stdout.write(`${recipe(parseTool(flags.printRecipe), flags.profile ?? "default").exec}\n`);
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
|
-
const { runListener } = await import("./listen-
|
|
81
|
+
const { runListener } = await import("./listen-BOHWwm_N.js");
|
|
82
82
|
process.exit(await runListener({
|
|
83
83
|
flags,
|
|
84
84
|
handleSignals: true
|
|
@@ -86,17 +86,17 @@ Example:
|
|
|
86
86
|
});
|
|
87
87
|
profileOption(listen.command("status").description("show the listener's connection, cursor, recent events and dead letters")).action(async (_o, cmd) => {
|
|
88
88
|
const flags = all(cmd);
|
|
89
|
-
const { printStatus } = await import("./admin-
|
|
89
|
+
const { printStatus } = await import("./admin-8MQLrhsj.js");
|
|
90
90
|
await printStatus(flags.profile ?? "default");
|
|
91
91
|
});
|
|
92
92
|
profileOption(listen.command("secret").description("print the forward-mode signing secret (whsec_…) for your local receiver")).option("--rotate", "generate a new secret (restart the listener afterwards)").action(async (_o, cmd) => {
|
|
93
93
|
const flags = all(cmd);
|
|
94
|
-
const { printSecret } = await import("./admin-
|
|
94
|
+
const { printSecret } = await import("./admin-8MQLrhsj.js");
|
|
95
95
|
printSecret(flags.profile ?? "default", flags);
|
|
96
96
|
});
|
|
97
97
|
listenFlags(listen.command("dead").description("list events that failed every attempt; --replay runs them again")).option("--replay", "run dead events again (successes are removed)").option("--id <eventId>", "only this event (with --replay or --clear)").option("--clear", "delete dead events without running them").option("--json", "print raw JSON lines").action(async (_o, cmd) => {
|
|
98
98
|
const flags = all(cmd);
|
|
99
|
-
const admin = await import("./admin-
|
|
99
|
+
const admin = await import("./admin-8MQLrhsj.js");
|
|
100
100
|
const profile = flags.profile ?? "default";
|
|
101
101
|
if (flags.clear) admin.clearDead(profile, flags.id);
|
|
102
102
|
else if (flags.replay) {
|
|
@@ -106,21 +106,21 @@ Example:
|
|
|
106
106
|
const service = listen.command("service").description("run the listener in the background (systemd user service / launchd agent, one per profile)");
|
|
107
107
|
listenFlags(service.command("install").description("install and start the listener service; flags are saved to the profile. Re-run to update")).action(async (_o, cmd) => {
|
|
108
108
|
const flags = all(cmd);
|
|
109
|
-
const { installListenService } = await import("./service-
|
|
109
|
+
const { installListenService } = await import("./service-D2IUVTXR.js");
|
|
110
110
|
await installListenService(flags);
|
|
111
111
|
});
|
|
112
112
|
profileOption(service.command("uninstall").description("stop and remove the listener service (keeps the profile)")).action(async (_o, cmd) => {
|
|
113
113
|
const flags = all(cmd);
|
|
114
|
-
const { uninstallListenService } = await import("./service-
|
|
114
|
+
const { uninstallListenService } = await import("./service-D2IUVTXR.js");
|
|
115
115
|
uninstallListenService(flags.profile ?? "default");
|
|
116
116
|
});
|
|
117
117
|
profileOption(service.command("status").description("show the service manager's status for the listener")).action(async (_o, cmd) => {
|
|
118
118
|
const flags = all(cmd);
|
|
119
|
-
const { listenServiceStatus } = await import("./service-
|
|
119
|
+
const { listenServiceStatus } = await import("./service-D2IUVTXR.js");
|
|
120
120
|
listenServiceStatus(flags.profile ?? "default");
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
123
|
//#endregion
|
|
124
124
|
export { registerListenCommands };
|
|
125
125
|
|
|
126
|
-
//# sourceMappingURL=commands-
|
|
126
|
+
//# sourceMappingURL=commands-DxKT4tGy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands-Bl8pAaAn.js","names":[],"sources":["../server/listen/commands.ts"],"sourcesContent":["import { type Command, InvalidArgumentError } from \"commander\";\nimport { EVENT_TYPES } from \"../../shared/types.ts\";\nimport type { ConnectFlags } from \"./connect.ts\";\nimport type { ListenFlags } from \"./options.ts\";\nimport { DEFAULT_PROFILE } from \"./paths.ts\";\nimport { recipesHelp, TOOLS } from \"./recipes.ts\";\nimport { NPX } from \"./version.ts\";\n\n/** `agentinbox connect`, `agentinbox setup-mcp` and `agentinbox listen …`, all lazily loaded. */\n\n/**\n * Options of a `listen` subcommand plus any its ancestors parsed: `listen` declares the same flags\n * (--profile, --exec…), and commander lets the parent claim them wherever they appear.\n */\nconst all = <T>(cmd: Command): T => cmd.optsWithGlobals() as T;\n\nconst collect = (value: string, previous: string[] | undefined) => [...(previous ?? []), value];\n\nconst int = (name: string) => (value: string) => {\n if (!/^\\d+$/.test(value)) throw new InvalidArgumentError(`${name} must be a whole number.`);\n return Number(value);\n};\n\nconst profileOption = (cmd: Command) => cmd.option(\"--profile <name>\", `profile to use (default \"${DEFAULT_PROFILE}\")`);\n\nfunction listenFlags(cmd: Command): Command {\n return profileOption(cmd)\n .option(\"--exec <command>\", \"run this command for each event (via /bin/sh; the event arrives on stdin as JSON, never in the command)\")\n .option(\"--forward <url>\", \"POST each event to this localhost URL, signed per Standard Webhooks\")\n .option(\"--types <list>\", `comma-separated event types, or \"all\" (default: message.received, new mail only; also ${EVENT_TYPES.filter((t) => t !== \"message.received\").join(\", \")})`)\n .option(\"--from <glob>\", 'only senders matching this glob, e.g. \"*@stripe.com\" (repeatable)', collect)\n .option(\"--to <glob>\", \"only when a to/cc address matches (repeatable)\", collect)\n .option(\"--label <id>\", \"only messages with this Gmail label id, e.g. INBOX or Label_123 (repeatable)\", collect)\n .option(\"--subject <regex>\", \"only subjects matching this case-insensitive regular expression\")\n .option(\"--include-body\", \"include the cleaned message body in each event\")\n .option(\"--no-include-body\", \"don't include bodies (overrides a saved setting)\")\n .option(\"--concurrency <n>\", \"events handled at once (default 2)\", int(\"--concurrency\"))\n .option(\"--timeout <seconds>\", \"per-event time limit; the whole process group is killed after it (default 300)\", int(\"--timeout\"))\n .option(\"--max-attempts <n>\", \"attempts before an event goes to dead letters (default 5)\", int(\"--max-attempts\"))\n .option(\"--consumer <name>\", \"server-side cursor name (default <hostname>-<profile>)\")\n .option(\"--cwd <dir>\", \"directory --exec commands run in (default: a private dir in the state dir; must be yours and not group/world-writable)\")\n .option(\"--insecure\", \"allow plain http to a non-loopback, non-Tailscale daemon (loud warning)\")\n .option(\"--save\", \"save these settings to the profile\");\n}\n\n/** `setup-mcp --help`: exactly what it changes, per tool. */\nfunction mcpSetupHelp(): string {\n return `\nWhat it changes (the server is named \"agentinbox\", or \"agentinbox-<profile>\" for --profile):\n claude-code runs \\`claude mcp remove agentinbox --scope user\\` then\n \\`claude mcp add-json --scope user agentinbox '{\"type\":\"http\",\"url\":\"<daemon>/mcp\",\"headersHelper\":\"…\"}'\\`.\n The header helper (~/.config/agentinbox/bin/mcp-header.mjs) reads the key from your profile, so\n the key is in neither the command line nor ~/.claude.json. Backs up ~/.claude.json first\n ($CLAUDE_CONFIG_DIR/.claude.json if set).\n codex adds or replaces [mcp_servers.agentinbox] in ~/.codex/config.toml ($CODEX_HOME), with the key in\n http_headers; the file becomes 0600.\n cursor adds or replaces mcpServers.agentinbox in ~/.cursor/mcp.json, with the key in headers; 0600.\n hermes adds or replaces mcp_servers.agentinbox in ~/.hermes/config.yaml ($HERMES_HOME) and puts the key in\n ~/.hermes/.env as AGENTINBOX_API_KEY; both 0600.\nEvery file is backed up first as <file>.agentinbox-backup-<timestamp> (0600; backups of files holding the key hold it\ntoo). It also refreshes ~/.config/agentinbox/mcp/<profile>.claude.json (no key), which the listen recipe uses.\n\nCheck it afterwards: claude mcp list · codex mcp list · agent mcp list (Cursor) · hermes mcp test agentinbox\n\nExample:\n ${NPX} setup-mcp --tool claude-code --dry-run`;\n}\n\nexport function registerListenCommands(program: Command): void {\n program\n .command(\"connect\")\n .description(\"pair this machine's agent with an agentinbox daemon (approve the code in the console)\")\n .argument(\"<daemon-url>\", \"the agentinbox daemon, e.g. https://mail.example.com or http://100.101.102.103:8425\")\n .option(\"--name <name>\", 'how the agent appears in the console (default \"<Tool> on <hostname>\")')\n .option(\"--tool <tool>\", `the agent's tool: ${TOOLS.join(\", \")}; tailors the next steps`)\n .option(\"--account <email>\", \"mailbox to request access to (repeatable; the approver decides)\", collect)\n .option(\"--capabilities <list>\", \"capabilities to request, e.g. read,draft (the approver decides)\")\n .option(\"--reason <text>\", \"why the agent needs access (shown to the approver)\")\n .option(\"--setup-mcp\", \"also register the MCP server in the chosen tool (the key is never shown; `setup-mcp --help` lists exactly what changes)\")\n .option(\"--profile <name>\", `profile to save the key in (default \"${DEFAULT_PROFILE}\")`)\n .option(\"--consumer <name>\", \"listener cursor name (default <hostname>-<profile>)\")\n .option(\"--log <file>\", \"also write the output to this file (created 0600; for running connect in the background)\")\n .option(\"--insecure\", \"allow plain http to a non-loopback, non-Tailscale daemon (loud warning)\")\n .option(\"--force\", \"re-pair an existing profile (keeps its listener settings)\")\n .addHelpText(\n \"after\",\n `\nExit codes: 0 approved, 2 denied, 3 expired, 4 already consumed, 130 cancelled, 1 error.\n\nExample:\n ${NPX} connect https://mail.example.com --tool claude-code --setup-mcp`,\n )\n .action(async (url: string, flags: ConnectFlags) => {\n const { runConnect } = await import(\"./connect.ts\");\n process.exit(await runConnect(url, flags, { handleSignals: true }));\n });\n\n profileOption(program.command(\"setup-mcp\").description(\"register the agentinbox MCP server in your agent's tool, without showing the key\"))\n .option(\"--tool <tool>\", `${TOOLS.filter((t) => t !== \"other\").join(\", \")} (default: the tool given to connect)`)\n .option(\"--dry-run\", \"print the exact commands and file changes, and change nothing\")\n .addHelpText(\"after\", mcpSetupHelp())\n .action(async (flags: { tool?: string; profile?: string; dryRun?: boolean }) => {\n const { parseTool, printMcpResult } = await import(\"./connect.ts\");\n const { loadProfile } = await import(\"./profile.ts\");\n const { setupMcp, mcpTarget } = await import(\"./mcpsetup.ts\");\n const { profilePath } = await import(\"./paths.ts\");\n const name = flags.profile ?? DEFAULT_PROFILE;\n const profile = loadProfile(name);\n const tool = flags.tool ? parseTool(flags.tool) : (profile.tool ?? \"other\");\n if (tool === \"other\") throw new Error(`Which tool? Pass --tool ${TOOLS.filter((t) => t !== \"other\").join(\"|\")}.`);\n const { claudeMcpConfigPath, writeClaudeMcpConfig } = await import(\"./mcpheader.ts\");\n const r = setupMcp(tool, mcpTarget(name, profile), profilePath(name), { dryRun: flags.dryRun });\n if (flags.dryRun) r.changes = [...(r.changes ?? []), `refresh ${claudeMcpConfigPath(name)} (keyless MCP config the Claude Code listen recipe loads)`];\n else writeClaudeMcpConfig(name, `${profile.url}/mcp`);\n printMcpResult(r);\n if (!r.ok) process.exitCode = 1;\n });\n\n profileOption(\n program.command(\"mcp-header\").description(\"print the agent's Authorization header as JSON for an MCP client's header helper (refuses to print to a terminal)\"),\n ).action(async (flags: { profile?: string }) => {\n const { printMcpHeader } = await import(\"./mcpheader.ts\");\n process.exitCode = printMcpHeader(flags.profile ?? DEFAULT_PROFILE);\n });\n\n const listen = listenFlags(\n program\n .command(\"listen\")\n .description(\"wake a local agent on new mail: hold an outbound stream to the daemon and run a command or POST to localhost per event\"),\n )\n .option(\"--dry-run\", \"print matching events without running anything (uses a throwaway <consumer>-dry-run cursor)\")\n .option(\"--from-start\", \"a NEW consumer starts at the oldest stored event (no effect once it exists: use --backfill)\")\n .option(\"--backfill\", \"run the mail from before this listener started through --exec/--forward once, oldest first, then exit; safe while the listener runs (own cursor)\")\n .option(\"--until <seq>\", \"with --backfill: replay up to this event number instead of where the listener started\", int(\"--until\"))\n .option(\"--print-recipe <tool>\", `print the ready-made --exec command for ${TOOLS.join(\", \")} (with this machine's paths) and exit`)\n .addHelpText(\"after\", recipesHelp())\n .action(async (flags: ListenFlags & { printRecipe?: string }) => {\n if (flags.printRecipe !== undefined) {\n const { parseTool } = await import(\"./connect.ts\");\n const { recipe } = await import(\"./recipes.ts\");\n process.stdout.write(`${recipe(parseTool(flags.printRecipe), flags.profile ?? DEFAULT_PROFILE).exec}\\n`);\n return;\n }\n const { runListener } = await import(\"./listen.ts\");\n process.exit(await runListener({ flags, handleSignals: true }));\n });\n\n profileOption(listen.command(\"status\").description(\"show the listener's connection, cursor, recent events and dead letters\")).action(async (_o: unknown, cmd: Command) => {\n const flags = all<{ profile?: string }>(cmd);\n const { printStatus } = await import(\"./admin.ts\");\n await printStatus(flags.profile ?? DEFAULT_PROFILE);\n });\n\n profileOption(listen.command(\"secret\").description(\"print the forward-mode signing secret (whsec_…) for your local receiver\"))\n .option(\"--rotate\", \"generate a new secret (restart the listener afterwards)\")\n .action(async (_o: unknown, cmd: Command) => {\n const flags = all<{ profile?: string; rotate?: boolean }>(cmd);\n const { printSecret } = await import(\"./admin.ts\");\n printSecret(flags.profile ?? DEFAULT_PROFILE, flags);\n });\n\n listenFlags(listen.command(\"dead\").description(\"list events that failed every attempt; --replay runs them again\"))\n .option(\"--replay\", \"run dead events again (successes are removed)\")\n .option(\"--id <eventId>\", \"only this event (with --replay or --clear)\")\n .option(\"--clear\", \"delete dead events without running them\")\n .option(\"--json\", \"print raw JSON lines\")\n .action(async (_o: unknown, cmd: Command) => {\n const flags = all<ListenFlags & { replay?: boolean; id?: string; clear?: boolean; json?: boolean }>(cmd);\n const admin = await import(\"./admin.ts\");\n const profile = flags.profile ?? DEFAULT_PROFILE;\n if (flags.clear) admin.clearDead(profile, flags.id);\n else if (flags.replay) {\n if ((await admin.replayDead(flags)) > 0) process.exitCode = 1;\n } else admin.printDead(profile, flags);\n });\n\n const service = listen.command(\"service\").description(\"run the listener in the background (systemd user service / launchd agent, one per profile)\");\n listenFlags(service.command(\"install\").description(\"install and start the listener service; flags are saved to the profile. Re-run to update\")).action(\n async (_o: unknown, cmd: Command) => {\n const flags = all<ListenFlags>(cmd);\n const { installListenService } = await import(\"./service.ts\");\n await installListenService(flags);\n },\n );\n profileOption(service.command(\"uninstall\").description(\"stop and remove the listener service (keeps the profile)\")).action(async (_o: unknown, cmd: Command) => {\n const flags = all<{ profile?: string }>(cmd);\n const { uninstallListenService } = await import(\"./service.ts\");\n uninstallListenService(flags.profile ?? DEFAULT_PROFILE);\n });\n profileOption(service.command(\"status\").description(\"show the service manager's status for the listener\")).action(async (_o: unknown, cmd: Command) => {\n const flags = all<{ profile?: string }>(cmd);\n const { listenServiceStatus } = await import(\"./service.ts\");\n listenServiceStatus(flags.profile ?? DEFAULT_PROFILE);\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"commands-DxKT4tGy.js","names":[],"sources":["../server/listen/commands.ts"],"sourcesContent":["import { type Command, InvalidArgumentError } from \"commander\";\nimport { EVENT_TYPES } from \"../../shared/types.ts\";\nimport type { ConnectFlags } from \"./connect.ts\";\nimport type { ListenFlags } from \"./options.ts\";\nimport { DEFAULT_PROFILE } from \"./paths.ts\";\nimport { recipesHelp, TOOLS } from \"./recipes.ts\";\nimport { NPX } from \"./version.ts\";\n\n/** `agentinbox connect`, `agentinbox setup-mcp` and `agentinbox listen …`, all lazily loaded. */\n\n/**\n * Options of a `listen` subcommand plus any its ancestors parsed: `listen` declares the same flags\n * (--profile, --exec…), and commander lets the parent claim them wherever they appear.\n */\nconst all = <T>(cmd: Command): T => cmd.optsWithGlobals() as T;\n\nconst collect = (value: string, previous: string[] | undefined) => [...(previous ?? []), value];\n\nconst int = (name: string) => (value: string) => {\n if (!/^\\d+$/.test(value)) throw new InvalidArgumentError(`${name} must be a whole number.`);\n return Number(value);\n};\n\nconst profileOption = (cmd: Command) => cmd.option(\"--profile <name>\", `profile to use (default \"${DEFAULT_PROFILE}\")`);\n\nfunction listenFlags(cmd: Command): Command {\n return profileOption(cmd)\n .option(\"--exec <command>\", \"run this command for each event (via /bin/sh; the event arrives on stdin as JSON, never in the command)\")\n .option(\"--forward <url>\", \"POST each event to this localhost URL, signed per Standard Webhooks\")\n .option(\"--types <list>\", `comma-separated event types, or \"all\" (default: message.received, new mail only; also ${EVENT_TYPES.filter((t) => t !== \"message.received\").join(\", \")})`)\n .option(\"--from <glob>\", 'only senders matching this glob, e.g. \"*@stripe.com\" (repeatable)', collect)\n .option(\"--to <glob>\", \"only when a to/cc address matches (repeatable)\", collect)\n .option(\"--label <id>\", \"only messages with this Gmail label id, e.g. INBOX or Label_123 (repeatable)\", collect)\n .option(\"--subject <regex>\", \"only subjects matching this case-insensitive regular expression\")\n .option(\"--include-body\", \"include the cleaned message body in each event\")\n .option(\"--no-include-body\", \"don't include bodies (overrides a saved setting)\")\n .option(\"--concurrency <n>\", \"events handled at once (default 2)\", int(\"--concurrency\"))\n .option(\"--timeout <seconds>\", \"per-event time limit; the whole process group is killed after it (default 300)\", int(\"--timeout\"))\n .option(\"--max-attempts <n>\", \"attempts before an event goes to dead letters (default 5)\", int(\"--max-attempts\"))\n .option(\"--consumer <name>\", \"server-side cursor name (default <hostname>-<profile>)\")\n .option(\"--cwd <dir>\", \"directory --exec commands run in (default: a private dir in the state dir; must be yours and not group/world-writable)\")\n .option(\"--insecure\", \"allow plain http to a non-loopback, non-Tailscale daemon (loud warning)\")\n .option(\"--save\", \"save these settings to the profile\");\n}\n\n/** `setup-mcp --help`: exactly what it changes, per tool. */\nfunction mcpSetupHelp(): string {\n return `\nWhat it changes (the server is named \"agentinbox\", or \"agentinbox-<profile>\" for --profile):\n claude-code runs \\`claude mcp remove agentinbox --scope user\\` then\n \\`claude mcp add-json --scope user agentinbox '{\"type\":\"http\",\"url\":\"<daemon>/mcp\",\"headersHelper\":\"…\"}'\\`.\n The header helper (~/.config/agentinbox/bin/mcp-header.mjs) reads the key from your profile, so\n the key is in neither the command line nor ~/.claude.json. Backs up ~/.claude.json first\n ($CLAUDE_CONFIG_DIR/.claude.json if set).\n codex adds or replaces [mcp_servers.agentinbox] in ~/.codex/config.toml ($CODEX_HOME), with the key in\n http_headers; the file becomes 0600.\n cursor adds or replaces mcpServers.agentinbox in ~/.cursor/mcp.json, with the key in headers; 0600.\n hermes adds or replaces mcp_servers.agentinbox in ~/.hermes/config.yaml ($HERMES_HOME) and puts the key in\n ~/.hermes/.env as AGENTINBOX_API_KEY; both 0600.\nEvery file is backed up first as <file>.agentinbox-backup-<timestamp> (0600; backups of files holding the key hold it\ntoo). It also refreshes ~/.config/agentinbox/mcp/<profile>.claude.json (no key), which the listen recipe uses.\n\nCheck it afterwards: claude mcp list · codex mcp list · agent mcp list (Cursor) · hermes mcp test agentinbox\n\nExample:\n ${NPX} setup-mcp --tool claude-code --dry-run`;\n}\n\nexport function registerListenCommands(program: Command): void {\n program\n .command(\"connect\")\n .description(\"pair this machine's agent with an agentinbox daemon (approve the code in the console)\")\n .argument(\"<daemon-url>\", \"the agentinbox daemon, e.g. https://mail.example.com or http://100.101.102.103:8425\")\n .option(\"--name <name>\", 'how the agent appears in the console (default \"<Tool> on <hostname>\")')\n .option(\"--tool <tool>\", `the agent's tool: ${TOOLS.join(\", \")}; tailors the next steps`)\n .option(\"--account <email>\", \"mailbox to request access to (repeatable; the approver decides)\", collect)\n .option(\"--capabilities <list>\", \"capabilities to request, e.g. read,draft (the approver decides)\")\n .option(\"--reason <text>\", \"why the agent needs access (shown to the approver)\")\n .option(\"--setup-mcp\", \"also register the MCP server in the chosen tool (the key is never shown; `setup-mcp --help` lists exactly what changes)\")\n .option(\"--profile <name>\", `profile to save the key in (default \"${DEFAULT_PROFILE}\")`)\n .option(\"--consumer <name>\", \"listener cursor name (default <hostname>-<profile>)\")\n .option(\"--log <file>\", \"also write the output to this file (created 0600; for running connect in the background)\")\n .option(\"--insecure\", \"allow plain http to a non-loopback, non-Tailscale daemon (loud warning)\")\n .option(\"--force\", \"re-pair an existing profile (keeps its listener settings)\")\n .addHelpText(\n \"after\",\n `\nExit codes: 0 approved, 2 denied, 3 expired, 4 already consumed, 130 cancelled, 1 error.\n\nExample:\n ${NPX} connect https://mail.example.com --tool claude-code --setup-mcp`,\n )\n .action(async (url: string, flags: ConnectFlags) => {\n const { runConnect } = await import(\"./connect.ts\");\n process.exit(await runConnect(url, flags, { handleSignals: true }));\n });\n\n profileOption(program.command(\"setup-mcp\").description(\"register the agentinbox MCP server in your agent's tool, without showing the key\"))\n .option(\"--tool <tool>\", `${TOOLS.filter((t) => t !== \"other\").join(\", \")} (default: the tool given to connect)`)\n .option(\"--dry-run\", \"print the exact commands and file changes, and change nothing\")\n .addHelpText(\"after\", mcpSetupHelp())\n .action(async (flags: { tool?: string; profile?: string; dryRun?: boolean }) => {\n const { parseTool, printMcpResult } = await import(\"./connect.ts\");\n const { loadProfile } = await import(\"./profile.ts\");\n const { setupMcp, mcpTarget } = await import(\"./mcpsetup.ts\");\n const { profilePath } = await import(\"./paths.ts\");\n const name = flags.profile ?? DEFAULT_PROFILE;\n const profile = loadProfile(name);\n const tool = flags.tool ? parseTool(flags.tool) : (profile.tool ?? \"other\");\n if (tool === \"other\") throw new Error(`Which tool? Pass --tool ${TOOLS.filter((t) => t !== \"other\").join(\"|\")}.`);\n const { claudeMcpConfigPath, writeClaudeMcpConfig } = await import(\"./mcpheader.ts\");\n const r = setupMcp(tool, mcpTarget(name, profile), profilePath(name), { dryRun: flags.dryRun });\n if (flags.dryRun) r.changes = [...(r.changes ?? []), `refresh ${claudeMcpConfigPath(name)} (keyless MCP config the Claude Code listen recipe loads)`];\n else writeClaudeMcpConfig(name, `${profile.url}/mcp`);\n printMcpResult(r);\n if (!r.ok) process.exitCode = 1;\n });\n\n profileOption(\n program.command(\"mcp-header\").description(\"print the agent's Authorization header as JSON for an MCP client's header helper (refuses to print to a terminal)\"),\n ).action(async (flags: { profile?: string }) => {\n const { printMcpHeader } = await import(\"./mcpheader.ts\");\n process.exitCode = printMcpHeader(flags.profile ?? DEFAULT_PROFILE);\n });\n\n const listen = listenFlags(\n program\n .command(\"listen\")\n .description(\"wake a local agent on new mail: hold an outbound stream to the daemon and run a command or POST to localhost per event\"),\n )\n .option(\"--dry-run\", \"print matching events without running anything (uses a throwaway <consumer>-dry-run cursor)\")\n .option(\"--from-start\", \"a NEW consumer starts at the oldest stored event (no effect once it exists: use --backfill)\")\n .option(\"--backfill\", \"run the mail from before this listener started through --exec/--forward once, oldest first, then exit; safe while the listener runs (own cursor)\")\n .option(\"--until <seq>\", \"with --backfill: replay up to this event number instead of where the listener started\", int(\"--until\"))\n .option(\"--print-recipe <tool>\", `print the ready-made --exec command for ${TOOLS.join(\", \")} (with this machine's paths) and exit`)\n .addHelpText(\"after\", recipesHelp())\n .action(async (flags: ListenFlags & { printRecipe?: string }) => {\n if (flags.printRecipe !== undefined) {\n const { parseTool } = await import(\"./connect.ts\");\n const { recipe } = await import(\"./recipes.ts\");\n process.stdout.write(`${recipe(parseTool(flags.printRecipe), flags.profile ?? DEFAULT_PROFILE).exec}\\n`);\n return;\n }\n const { runListener } = await import(\"./listen.ts\");\n process.exit(await runListener({ flags, handleSignals: true }));\n });\n\n profileOption(listen.command(\"status\").description(\"show the listener's connection, cursor, recent events and dead letters\")).action(async (_o: unknown, cmd: Command) => {\n const flags = all<{ profile?: string }>(cmd);\n const { printStatus } = await import(\"./admin.ts\");\n await printStatus(flags.profile ?? DEFAULT_PROFILE);\n });\n\n profileOption(listen.command(\"secret\").description(\"print the forward-mode signing secret (whsec_…) for your local receiver\"))\n .option(\"--rotate\", \"generate a new secret (restart the listener afterwards)\")\n .action(async (_o: unknown, cmd: Command) => {\n const flags = all<{ profile?: string; rotate?: boolean }>(cmd);\n const { printSecret } = await import(\"./admin.ts\");\n printSecret(flags.profile ?? DEFAULT_PROFILE, flags);\n });\n\n listenFlags(listen.command(\"dead\").description(\"list events that failed every attempt; --replay runs them again\"))\n .option(\"--replay\", \"run dead events again (successes are removed)\")\n .option(\"--id <eventId>\", \"only this event (with --replay or --clear)\")\n .option(\"--clear\", \"delete dead events without running them\")\n .option(\"--json\", \"print raw JSON lines\")\n .action(async (_o: unknown, cmd: Command) => {\n const flags = all<ListenFlags & { replay?: boolean; id?: string; clear?: boolean; json?: boolean }>(cmd);\n const admin = await import(\"./admin.ts\");\n const profile = flags.profile ?? DEFAULT_PROFILE;\n if (flags.clear) admin.clearDead(profile, flags.id);\n else if (flags.replay) {\n if ((await admin.replayDead(flags)) > 0) process.exitCode = 1;\n } else admin.printDead(profile, flags);\n });\n\n const service = listen.command(\"service\").description(\"run the listener in the background (systemd user service / launchd agent, one per profile)\");\n listenFlags(service.command(\"install\").description(\"install and start the listener service; flags are saved to the profile. Re-run to update\")).action(\n async (_o: unknown, cmd: Command) => {\n const flags = all<ListenFlags>(cmd);\n const { installListenService } = await import(\"./service.ts\");\n await installListenService(flags);\n },\n );\n profileOption(service.command(\"uninstall\").description(\"stop and remove the listener service (keeps the profile)\")).action(async (_o: unknown, cmd: Command) => {\n const flags = all<{ profile?: string }>(cmd);\n const { uninstallListenService } = await import(\"./service.ts\");\n uninstallListenService(flags.profile ?? DEFAULT_PROFILE);\n });\n profileOption(service.command(\"status\").description(\"show the service manager's status for the listener\")).action(async (_o: unknown, cmd: Command) => {\n const flags = all<{ profile?: string }>(cmd);\n const { listenServiceStatus } = await import(\"./service.ts\");\n listenServiceStatus(flags.profile ?? DEFAULT_PROFILE);\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as CAPABILITIES } from "./types-
|
|
3
|
-
import { C as clientInfo, E as startPairing, S as ApiError, T as pollPairing, _ as insecureBanner, g as checkTransport, p as validConsumer, u as defaultConsumer, v as normalizeDaemonUrl, w as getSelf, x as describeGrants } from "./listen-
|
|
2
|
+
import { t as CAPABILITIES } from "./types-wY3IqC2D.js";
|
|
3
|
+
import { C as clientInfo, E as startPairing, S as ApiError, T as pollPairing, _ as insecureBanner, g as checkTransport, p as validConsumer, u as defaultConsumer, v as normalizeDaemonUrl, w as getSelf, x as describeGrants } from "./listen-cDUHSBkN.js";
|
|
4
4
|
import { i as safeText, n as box, r as formatDuration, t as StatusLine } from "./ui-B8Sd4Y7Y.js";
|
|
5
|
-
import { d as NPX, i as saveProfile, n as loadProfile, r as profileExists, t as listProfiles } from "./profile-
|
|
5
|
+
import { d as NPX, i as saveProfile, n as loadProfile, r as profileExists, t as listProfiles } from "./profile-uRinkfdm.js";
|
|
6
6
|
import { c as profilePath, p as validProfileName } from "./paths-DckASYtc.js";
|
|
7
|
-
import { c as writeClaudeMcpConfig } from "./mcpheader-
|
|
8
|
-
import { i as recipe, n as TOOL_LABELS, o as shellQuote, t as TOOLS } from "./recipes-
|
|
9
|
-
import { n as isServiceInstalled } from "./service-
|
|
10
|
-
import { l as setupMcp, s as mcpTarget } from "./mcpsetup-
|
|
7
|
+
import { c as writeClaudeMcpConfig } from "./mcpheader-Du6e5MGj.js";
|
|
8
|
+
import { i as recipe, n as TOOL_LABELS, o as shellQuote, t as TOOLS } from "./recipes-BQpXA6p1.js";
|
|
9
|
+
import { n as isServiceInstalled } from "./service-DXiBV61B.js";
|
|
10
|
+
import { l as setupMcp, s as mcpTarget } from "./mcpsetup-CHQ9_Rbb.js";
|
|
11
11
|
import { closeSync, constants, fchmodSync, lstatSync, openSync, writeSync } from "node:fs";
|
|
12
12
|
import { hostname } from "node:os";
|
|
13
13
|
import pc from "picocolors";
|
|
@@ -332,4 +332,4 @@ function printNextSteps(profileName, profile, tool, mcp) {
|
|
|
332
332
|
//#endregion
|
|
333
333
|
export { parseTool, printMcpResult, runConnect };
|
|
334
334
|
|
|
335
|
-
//# sourceMappingURL=connect-
|
|
335
|
+
//# sourceMappingURL=connect-CfxNALy5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect-BJBxb2jX.js","names":[],"sources":["../server/listen/connect.ts"],"sourcesContent":["import { closeSync, constants, fchmodSync, lstatSync, openSync, writeSync } from \"node:fs\";\nimport { hostname } from \"node:os\";\nimport pc from \"picocolors\";\nimport type { AgentTool, PairingPoll, PairingStart, PairingStartInput } from \"../../shared/agent-api.ts\";\nimport { CAPABILITIES, type Capability } from \"../../shared/types.ts\";\nimport { ApiError, clientInfo, getSelf, pollPairing, startPairing } from \"./api.ts\";\nimport { describeGrants } from \"./grants.ts\";\nimport { writeClaudeMcpConfig } from \"./mcpheader.ts\";\nimport { isServiceInstalled } from \"./service.ts\";\nimport { setupMcp, mcpTarget, type McpSetupResult } from \"./mcpsetup.ts\";\nimport { defaultConsumer, validConsumer } from \"./options.ts\";\nimport { DEFAULT_PROFILE, profilePath, validProfileName } from \"./paths.ts\";\nimport { listProfiles, loadProfile, type Profile, profileExists, saveProfile } from \"./profile.ts\";\nimport { recipe, shellQuote, TOOL_LABELS, TOOLS } from \"./recipes.ts\";\nimport { checkTransport, insecureBanner, normalizeDaemonUrl } from \"./transport.ts\";\nimport { box, formatDuration, safeText, StatusLine } from \"./ui.ts\";\nimport { NPX } from \"./version.ts\";\n\nexport interface ConnectFlags {\n name?: string;\n tool?: string;\n account?: string[];\n capabilities?: string;\n reason?: string;\n profile?: string;\n consumer?: string;\n insecure?: boolean;\n force?: boolean;\n setupMcp?: boolean;\n /** Also write the output (plain text) to this file: created 0600, never through a symlink or someone else's file. */\n log?: string;\n}\n\n/** Exit codes, so scripts (and agents setting themselves up) can tell outcomes apart. */\nexport const CONNECT_EXIT = { approved: 0, error: 1, denied: 2, expired: 3, consumed: 4, cancelled: 130 } as const;\n\nexport interface ConnectOptions {\n /** Tests: poll faster than the server's interval. */\n pollIntervalMs?: number;\n signal?: AbortSignal;\n handleSignals?: boolean;\n}\n\nexport function parseTool(value: string | undefined): AgentTool {\n if (value === undefined) return \"other\";\n const v = value.trim().toLowerCase().replace(/^claude$/, \"claude-code\");\n if (!(TOOLS as readonly string[]).includes(v)) throw new Error(`Unknown --tool \"${value}\". Choose one of: ${TOOLS.join(\", \")}.`);\n return v as AgentTool;\n}\n\nexport function parseCapabilities(value: string | undefined): Capability[] | undefined {\n if (value === undefined) return undefined;\n const list = value\n .split(\",\")\n .map((s) => s.trim().toLowerCase())\n .filter(Boolean);\n const bad = list.filter((c) => !(CAPABILITIES as readonly string[]).includes(c));\n if (bad.length) throw new Error(`Unknown capabilit${bad.length > 1 ? \"ies\" : \"y\"} ${bad.join(\", \")}. Choose from: ${CAPABILITIES.join(\", \")}.`);\n return [...new Set(list)] as Capability[];\n}\n\nconst shortHost = () => hostname().replace(/\\.(local|lan|home)$/i, \"\");\n\nconst sleep = (ms: number, signal?: AbortSignal) =>\n new Promise<void>((resolve) => {\n const t = setTimeout(resolve, ms);\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(t);\n resolve();\n },\n { once: true },\n );\n });\n\n// eslint-disable-next-line no-control-regex\nconst stripAnsi = (s: string) => s.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n/** --log target (fd), written in parallel with the console. */\nlet logFd: number | null = null;\nconst toLog = (s: string) => {\n if (logFd !== null) writeSync(logFd, stripAnsi(s) + \"\\n\");\n};\nconst out = (s = \"\") => {\n process.stdout.write(`${s}\\n`);\n toLog(s);\n};\nconst err = (s = \"\") => {\n process.stderr.write(`${s}\\n`);\n toLog(s);\n};\n\n/**\n * Opens --log safely: a new file is created 0600 with O_EXCL; an existing one (e.g. from `mktemp`) is\n * only reused if it is a regular file owned by us, opened without following symlinks. This is what\n * keeps another local user from pre-creating the log and reading the pairing as it happens.\n */\nexport function openConnectLog(path: string): number {\n try {\n return openSync(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code !== \"EEXIST\") throw e;\n }\n const st = lstatSync(path);\n const uid = process.getuid?.();\n if (!st.isFile() || (uid !== undefined && st.uid !== uid)) throw new Error(`Refusing --log ${path}: it exists and is not a regular file owned by you.`);\n const fd = openSync(path, constants.O_WRONLY | constants.O_TRUNC | constants.O_NOFOLLOW);\n fchmodSync(fd, 0o600);\n return fd;\n}\n\nexport async function runConnect(rawUrl: string, flags: ConnectFlags, opts: ConnectOptions = {}): Promise<number> {\n if (flags.log) logFd = openConnectLog(flags.log);\n try {\n return await connect(rawUrl, flags, opts);\n } finally {\n if (logFd !== null) closeSync(logFd);\n logFd = null;\n }\n}\n\nasync function connect(rawUrl: string, flags: ConnectFlags, opts: ConnectOptions): Promise<number> {\n const url = normalizeDaemonUrl(rawUrl);\n const verdict = await checkTransport(url, { insecure: flags.insecure });\n if (verdict.warning) err(insecureBanner(verdict.warning));\n\n const profileName = validProfileName(flags.profile ?? DEFAULT_PROFILE);\n let replacing: Profile | null = null;\n if (profileExists(profileName) && flags.force) {\n try {\n replacing = loadProfile(profileName);\n } catch {\n // Unreadable: it's being replaced anyway.\n }\n }\n if (profileExists(profileName) && !flags.force) {\n let who = \"\";\n try {\n const p = loadProfile(profileName);\n who = ` (agent \"${safeText(p.agentName)}\" on ${p.url})`;\n } catch {\n // Unreadable: still don't overwrite silently.\n }\n const others = listProfiles();\n throw new Error(\n `Profile \"${profileName}\" already exists${who}.\\n` +\n ` Pair a second agent with --profile <name>${others.length > 1 ? ` (existing: ${others.join(\", \")})` : \"\"}, or replace this one with --force.`,\n );\n }\n const tool = parseTool(flags.tool);\n const capabilities = parseCapabilities(flags.capabilities);\n // --force keeps the listener's consumer, so the server-side cursor carries on (no replay, no gap).\n const consumer = validConsumer(flags.consumer ?? replacing?.consumer ?? defaultConsumer(profileName));\n const name = (flags.name?.trim() || `${tool === \"other\" ? \"Agent\" : TOOL_LABELS[tool]} on ${shortHost()}`).slice(0, 80);\n\n const input: PairingStartInput = {\n name,\n requested: {\n ...(flags.account?.length ? { accounts: flags.account } : {}),\n ...(capabilities ? { capabilities } : {}),\n ...(flags.reason ? { reason: flags.reason } : {}),\n },\n client: { ...clientInfo(), tool },\n };\n\n let start: PairingStart;\n try {\n start = await startPairing(url, input);\n } catch (e) {\n if (e instanceof ApiError && e.status === 404) {\n throw new Error(`${url} doesn't support pairing (no /agent/v1/pairings). Is this an agentinbox daemon, and is it up to date?`);\n }\n if (e instanceof ApiError) throw new Error(`${e.message}${e.hint ? `\\n ${e.hint}` : \"\"}`);\n throw e;\n }\n\n const links = approveLinks(url, start);\n out();\n out(\n box([\n pc.bold(\"Approve this agent in the agentinbox console\"),\n \"\",\n `Code: ${pc.bold(pc.yellow(safeText(start.userCode, 40)))}`,\n `Open: ${pc.cyan(safeText(links.primary, 300))}`,\n ...(links.publicUrl\n ? [` or: ${pc.cyan(safeText(links.publicUrl, 300))}`, pc.gray(` (first: the address this CLI used; second: the console's public URL setting)`)]\n : []),\n `Agent: ${safeText(name)}`,\n \"\",\n pc.gray(\"Only approve if the console shows this exact code.\"),\n ]),\n );\n out();\n\n // Ctrl-C: stop cleanly. Nothing was approved; the request just expires.\n const ac = new AbortController();\n const onAbort = () => ac.abort();\n opts.signal?.addEventListener(\"abort\", onAbort, { once: true });\n const onSigint = () => ac.abort();\n if (opts.handleSignals) process.on(\"SIGINT\", onSigint);\n\n const started = Date.now();\n const expiresAt = Date.parse(start.expiresAt) || started + 10 * 60_000;\n let interval = Math.max(1, start.interval || 5) * 1000;\n let note = \"\";\n const status = new StatusLine(process.stderr);\n status.start(\n () =>\n `Waiting for approval · ${formatDuration(Date.now() - started)} elapsed · code expires in ${formatDuration(expiresAt - Date.now())}${note ? pc.yellow(` · ${note}`) : \"\"}`,\n );\n\n let result: PairingPoll | null = null;\n try {\n while (!ac.signal.aborted) {\n await sleep(opts.pollIntervalMs ?? interval, ac.signal);\n if (ac.signal.aborted) break;\n try {\n const r = await pollPairing(url, start.deviceCode);\n note = \"\";\n if (r.status === \"pending\") continue;\n if (r.status === \"slow_down\") {\n // The server asks for more room between polls.\n interval = Math.max(interval + 1000, (r.interval || 0) * 1000);\n continue;\n }\n result = r;\n break;\n } catch (e) {\n if (e instanceof ApiError && e.status === 429) {\n interval += 5000;\n note = \"rate limited, slowing down\";\n continue;\n }\n if (e instanceof ApiError && e.status >= 400 && e.status < 500 && e.status !== 408) {\n throw new Error(`${e.message}${e.hint ? `\\n ${e.hint}` : \"\"}`);\n }\n // Network trouble or a 5xx: keep trying until the code expires.\n note = \"can't reach the daemon, retrying\";\n if (Date.now() > expiresAt + 30_000) {\n result = { status: \"expired\" };\n break;\n }\n }\n }\n } finally {\n status.stop();\n if (opts.handleSignals) process.off(\"SIGINT\", onSigint);\n opts.signal?.removeEventListener(\"abort\", onAbort);\n }\n\n if (!result) {\n err(pc.yellow(\"Cancelled. Nothing was approved; the code expires on its own.\"));\n return CONNECT_EXIT.cancelled;\n }\n\n switch (result.status) {\n case \"denied\":\n err(pc.red(`✖ The request was denied in the console${result.note ? `: ${safeText(result.note, 300)}` : \".\"}`));\n return CONNECT_EXIT.denied;\n case \"expired\":\n err(pc.red(\"✖ The code expired before it was approved.\"));\n err(` Run the same command again for a fresh code, and approve it within ${formatDuration(Date.parse(start.expiresAt) - started)}.`);\n return CONNECT_EXIT.expired;\n case \"consumed\":\n err(pc.red(\"✖ This pairing was already completed and its key handed out once (perhaps by an earlier run of this command).\"));\n err(` For safety the key is never delivered twice. Start over with \\`${NPX} connect\\`, or rotate the agent's key in the console.`);\n return CONNECT_EXIT.consumed;\n case \"approved\":\n break;\n default:\n throw new Error(`Unexpected pairing status ${JSON.stringify((result as { status: unknown }).status)}`);\n }\n\n // --force keeps everything about the listener (targets, filters, limits, forward secret, cwd); only\n // the pairing (daemon, key, agent) is replaced.\n const kept: Partial<Profile> = replacing\n ? {\n types: replacing.types,\n filter: replacing.filter,\n includeBody: replacing.includeBody,\n exec: replacing.exec,\n forward: replacing.forward,\n forwardSecret: replacing.forwardSecret,\n concurrency: replacing.concurrency,\n timeoutSeconds: replacing.timeoutSeconds,\n maxAttempts: replacing.maxAttempts,\n cwd: replacing.cwd,\n }\n : {};\n const profile: Profile = {\n ...kept,\n url,\n apiKey: result.apiKey,\n agentId: result.agent.id,\n agentName: result.agent.name,\n consumer,\n ...(verdict.kind === \"insecure\" ? { insecure: true } : {}),\n tool,\n // Derived from the URL the user chose and transport-checked; the daemon's advertised URLs come\n // from its publicUrl setting and are never trusted with the key.\n mcpUrl: `${url}/mcp`,\n skillUrl: `${url}/skill.md`,\n createdAt: new Date().toISOString(),\n };\n const path = saveProfile(profileName, profile);\n writeClaudeMcpConfig(profileName, profile.mcpUrl!);\n if (typeof result.mcpUrl === \"string\" && result.mcpUrl !== profile.mcpUrl) {\n err(\n pc.yellow(\n `! The daemon advertises its MCP endpoint as ${safeText(result.mcpUrl, 200)} (its \"public URL\" setting); using ${profile.mcpUrl}, the address you connected to. Set the public URL in the console if agents should use another address.`,\n ),\n );\n }\n\n out(`${pc.green(\"✔\")} Approved. Agent ${pc.bold(safeText(result.agent.name))} ${pc.gray(`(${result.agent.id})`)} is connected.`);\n out(` Key saved to ${pc.cyan(path)} ${pc.gray(\"(mode 0600; never displayed. Rotate it in the console if it leaks.)\")}`);\n if (replacing && (replacing.exec || replacing.forward)) {\n out(` Kept this profile's listener settings. Restart the listener to use the new key${isServiceInstalled(profileName) ? `: ${NPX} listen service install${profileName === DEFAULT_PROFILE ? \"\" : ` --profile ${profileName}`}` : \".\"}`);\n }\n if (replacing && replacing.agentId !== profile.agentId) {\n err(\n pc.yellow(\n `! Replaced profile \"${profileName}\" (agent \"${safeText(replacing.agentName)}\", ${replacing.agentId}). Its key still works until you rotate it or delete that agent in the console; config backups made by setup-mcp (*.agentinbox-backup-*) may contain it.`,\n ),\n );\n }\n\n await printGrants(url, profile.apiKey, profileName);\n\n let mcp: McpSetupResult | null = null;\n if (flags.setupMcp) {\n mcp = setupMcp(tool, mcpTarget(profileName, profile), path);\n printMcpResult(mcp);\n }\n printNextSteps(profileName, profile, tool, mcp);\n return CONNECT_EXIT.approved;\n}\n\n/**\n * The approve link. The daemon builds it from its public URL setting (default http://localhost:<port>),\n * which may not be the address this CLI reached it at (127.0.0.1, a LAN IP, an SSH tunnel's port): then\n * the link on the address we used comes first, and the public-URL one is shown as well.\n */\nexport function approveLinks(url: string, start: Pick<PairingStart, \"verificationUrl\" | \"userCode\">): { primary: string; publicUrl: string | null } {\n let advertised: URL;\n try {\n advertised = new URL(start.verificationUrl);\n } catch {\n return { primary: start.verificationUrl, publicUrl: null };\n }\n const ours = new URL(url);\n if (advertised.origin === ours.origin) return { primary: start.verificationUrl, publicUrl: null };\n // Same page on our address: keep a path prefix we connected through (reverse proxy), else swap the origin.\n const rest = `${advertised.search}${advertised.hash}`;\n const primary = advertised.pathname.endsWith(\"/approvals\") ? `${url}/approvals${rest}` : `${ours.origin}${advertised.pathname}${rest}`;\n return { primary, publicUrl: start.verificationUrl };\n}\n\n/** What the approver actually granted, in plain words (the console's choice decides, not the request). */\nasync function printGrants(url: string, key: string, profileName: string): Promise<void> {\n const p = profileName === DEFAULT_PROFILE ? \"\" : ` --profile ${profileName}`;\n try {\n const self = await getSelf(url, key, 8000);\n out(` ${pc.bold(\"Access granted\")} ${pc.gray(\"(chosen by whoever approved it; change it in the console under Agents):\")}`);\n for (const line of describeGrants(self.grants)) out(` ${self.grants.length ? line : pc.yellow(line)}`);\n } catch (e) {\n err(pc.yellow(`! Couldn't read this agent's access yet (${e instanceof Error ? e.message.split(\"\\n\")[0] : String(e)}). Check it with: ${NPX} listen status${p}`));\n }\n}\n\nexport function printMcpResult(r: McpSetupResult): void {\n if (r.ok) out(`${r.dryRun ? pc.cyan(\"○\") : pc.green(\"✔\")} ${r.message}`);\n else err(`${pc.yellow(\"!\")} ${r.message}`);\n if (r.ok && r.changes?.length) {\n // Indented lines are file contents; the rest are steps.\n for (const l of r.changes) out(l.startsWith(\" \") ? pc.gray(` ${l}`) : ` - ${l}`);\n }\n if (r.backup) out(pc.gray(` Backup: ${r.backup}`));\n if (!r.ok && r.manual?.length) {\n out(\" Do it by hand:\");\n for (const l of r.manual) out(` ${l}`);\n }\n if (r.ok && r.verify?.length) out(` ${r.dryRun ? \"Afterwards, check it with\" : \"Check it with\"}: ${r.verify.map((v) => pc.cyan(v)).join(\"; \")}`);\n}\n\nfunction skillCommand(tool: AgentTool, url: string): string {\n switch (tool) {\n case \"claude-code\":\n return `${NPX} skill install --target claude --url ${url}`;\n case \"codex\":\n return `${NPX} skill install --target codex --url ${url}`;\n case \"hermes\":\n return `${NPX} skill install --target ~/.hermes/skills/email --url ${url}`;\n case \"cursor\":\n return `${NPX} skill install --target agents --url ${url}`;\n default:\n return `${NPX} skill print --url ${url} > SKILL.md`;\n }\n}\n\nexport function printNextSteps(profileName: string, profile: Profile, tool: AgentTool, mcp: McpSetupResult | null): void {\n const p = profileName === DEFAULT_PROFILE ? \"\" : ` --profile ${profileName}`;\n const label = tool === \"other\" ? \"your agent\" : TOOL_LABELS[tool];\n const r = recipe(tool, profileName);\n const execArg = shellQuote(r.exec);\n out();\n out(pc.bold(\"Next steps\"));\n let n = 1;\n if (mcp?.ok) {\n out(` ${n++}. ${label} has the agentinbox MCP tools ${pc.gray(`(restart it if it's running)`)}.`);\n } else if (tool === \"other\") {\n out(` ${n++}. Point your agent's MCP client at ${pc.cyan(profile.mcpUrl ?? `${profile.url}/mcp`)} with header Authorization: Bearer <key>`);\n out(pc.gray(` The key is the \"apiKey\" field in ${profilePath(profileName)}.`));\n } else {\n out(` ${n++}. Give ${label} the agentinbox MCP tools without ever seeing the key:`);\n out(` ${pc.cyan(`${NPX} setup-mcp --tool ${tool}${p}`)} ${pc.gray(\"(add --dry-run to see exactly what it changes first)\")}`);\n }\n out(` ${n++}. Install the agentinbox skill so ${label} knows the rules:`);\n out(` ${pc.cyan(skillCommand(tool, profile.url))}`);\n out(` ${n++}. Wake ${label} when mail arrives. First try it in the foreground (Ctrl-C stops it; --save keeps the command in the profile):`);\n out(` ${pc.cyan(`${NPX} listen${p} --save --exec ${execArg}`)}`);\n out(pc.gray(` Only new mail wakes it (message.received), not mail you send. Change it with --types, e.g. --types thread.reply_received (only replies to threads you sent) or --types all.`));\n out(pc.gray(` What the woken agent can use: ${r.confinement}.`));\n for (const note of r.notes) out(pc.gray(` ${note}`));\n out(` ${n++}. Check that it works: in the console's setup, the \"Check that it works\" step sends a test email.`);\n out(` Watch it arrive in the foreground listener as ${pc.cyan(\"→ #… message.received\")} followed by one ${pc.green(\"✓\")} line once ${label} handled it.`);\n out(` ${n++}. Then keep it running in the background (systemd / launchd, starts at login; stop the foreground one first):`);\n out(` ${pc.cyan(`${NPX} listen service install${p}`)}`);\n out(` ${pc.cyan(`${NPX} listen status${p}`)} ${pc.gray(\"(connection, cursor, recent events and the access granted)\")}`);\n out();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"connect-CfxNALy5.js","names":[],"sources":["../server/listen/connect.ts"],"sourcesContent":["import { closeSync, constants, fchmodSync, lstatSync, openSync, writeSync } from \"node:fs\";\nimport { hostname } from \"node:os\";\nimport pc from \"picocolors\";\nimport type { AgentTool, PairingPoll, PairingStart, PairingStartInput } from \"../../shared/agent-api.ts\";\nimport { CAPABILITIES, type Capability } from \"../../shared/types.ts\";\nimport { ApiError, clientInfo, getSelf, pollPairing, startPairing } from \"./api.ts\";\nimport { describeGrants } from \"./grants.ts\";\nimport { writeClaudeMcpConfig } from \"./mcpheader.ts\";\nimport { isServiceInstalled } from \"./service.ts\";\nimport { setupMcp, mcpTarget, type McpSetupResult } from \"./mcpsetup.ts\";\nimport { defaultConsumer, validConsumer } from \"./options.ts\";\nimport { DEFAULT_PROFILE, profilePath, validProfileName } from \"./paths.ts\";\nimport { listProfiles, loadProfile, type Profile, profileExists, saveProfile } from \"./profile.ts\";\nimport { recipe, shellQuote, TOOL_LABELS, TOOLS } from \"./recipes.ts\";\nimport { checkTransport, insecureBanner, normalizeDaemonUrl } from \"./transport.ts\";\nimport { box, formatDuration, safeText, StatusLine } from \"./ui.ts\";\nimport { NPX } from \"./version.ts\";\n\nexport interface ConnectFlags {\n name?: string;\n tool?: string;\n account?: string[];\n capabilities?: string;\n reason?: string;\n profile?: string;\n consumer?: string;\n insecure?: boolean;\n force?: boolean;\n setupMcp?: boolean;\n /** Also write the output (plain text) to this file: created 0600, never through a symlink or someone else's file. */\n log?: string;\n}\n\n/** Exit codes, so scripts (and agents setting themselves up) can tell outcomes apart. */\nexport const CONNECT_EXIT = { approved: 0, error: 1, denied: 2, expired: 3, consumed: 4, cancelled: 130 } as const;\n\nexport interface ConnectOptions {\n /** Tests: poll faster than the server's interval. */\n pollIntervalMs?: number;\n signal?: AbortSignal;\n handleSignals?: boolean;\n}\n\nexport function parseTool(value: string | undefined): AgentTool {\n if (value === undefined) return \"other\";\n const v = value.trim().toLowerCase().replace(/^claude$/, \"claude-code\");\n if (!(TOOLS as readonly string[]).includes(v)) throw new Error(`Unknown --tool \"${value}\". Choose one of: ${TOOLS.join(\", \")}.`);\n return v as AgentTool;\n}\n\nexport function parseCapabilities(value: string | undefined): Capability[] | undefined {\n if (value === undefined) return undefined;\n const list = value\n .split(\",\")\n .map((s) => s.trim().toLowerCase())\n .filter(Boolean);\n const bad = list.filter((c) => !(CAPABILITIES as readonly string[]).includes(c));\n if (bad.length) throw new Error(`Unknown capabilit${bad.length > 1 ? \"ies\" : \"y\"} ${bad.join(\", \")}. Choose from: ${CAPABILITIES.join(\", \")}.`);\n return [...new Set(list)] as Capability[];\n}\n\nconst shortHost = () => hostname().replace(/\\.(local|lan|home)$/i, \"\");\n\nconst sleep = (ms: number, signal?: AbortSignal) =>\n new Promise<void>((resolve) => {\n const t = setTimeout(resolve, ms);\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(t);\n resolve();\n },\n { once: true },\n );\n });\n\n// eslint-disable-next-line no-control-regex\nconst stripAnsi = (s: string) => s.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n/** --log target (fd), written in parallel with the console. */\nlet logFd: number | null = null;\nconst toLog = (s: string) => {\n if (logFd !== null) writeSync(logFd, stripAnsi(s) + \"\\n\");\n};\nconst out = (s = \"\") => {\n process.stdout.write(`${s}\\n`);\n toLog(s);\n};\nconst err = (s = \"\") => {\n process.stderr.write(`${s}\\n`);\n toLog(s);\n};\n\n/**\n * Opens --log safely: a new file is created 0600 with O_EXCL; an existing one (e.g. from `mktemp`) is\n * only reused if it is a regular file owned by us, opened without following symlinks. This is what\n * keeps another local user from pre-creating the log and reading the pairing as it happens.\n */\nexport function openConnectLog(path: string): number {\n try {\n return openSync(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code !== \"EEXIST\") throw e;\n }\n const st = lstatSync(path);\n const uid = process.getuid?.();\n if (!st.isFile() || (uid !== undefined && st.uid !== uid)) throw new Error(`Refusing --log ${path}: it exists and is not a regular file owned by you.`);\n const fd = openSync(path, constants.O_WRONLY | constants.O_TRUNC | constants.O_NOFOLLOW);\n fchmodSync(fd, 0o600);\n return fd;\n}\n\nexport async function runConnect(rawUrl: string, flags: ConnectFlags, opts: ConnectOptions = {}): Promise<number> {\n if (flags.log) logFd = openConnectLog(flags.log);\n try {\n return await connect(rawUrl, flags, opts);\n } finally {\n if (logFd !== null) closeSync(logFd);\n logFd = null;\n }\n}\n\nasync function connect(rawUrl: string, flags: ConnectFlags, opts: ConnectOptions): Promise<number> {\n const url = normalizeDaemonUrl(rawUrl);\n const verdict = await checkTransport(url, { insecure: flags.insecure });\n if (verdict.warning) err(insecureBanner(verdict.warning));\n\n const profileName = validProfileName(flags.profile ?? DEFAULT_PROFILE);\n let replacing: Profile | null = null;\n if (profileExists(profileName) && flags.force) {\n try {\n replacing = loadProfile(profileName);\n } catch {\n // Unreadable: it's being replaced anyway.\n }\n }\n if (profileExists(profileName) && !flags.force) {\n let who = \"\";\n try {\n const p = loadProfile(profileName);\n who = ` (agent \"${safeText(p.agentName)}\" on ${p.url})`;\n } catch {\n // Unreadable: still don't overwrite silently.\n }\n const others = listProfiles();\n throw new Error(\n `Profile \"${profileName}\" already exists${who}.\\n` +\n ` Pair a second agent with --profile <name>${others.length > 1 ? ` (existing: ${others.join(\", \")})` : \"\"}, or replace this one with --force.`,\n );\n }\n const tool = parseTool(flags.tool);\n const capabilities = parseCapabilities(flags.capabilities);\n // --force keeps the listener's consumer, so the server-side cursor carries on (no replay, no gap).\n const consumer = validConsumer(flags.consumer ?? replacing?.consumer ?? defaultConsumer(profileName));\n const name = (flags.name?.trim() || `${tool === \"other\" ? \"Agent\" : TOOL_LABELS[tool]} on ${shortHost()}`).slice(0, 80);\n\n const input: PairingStartInput = {\n name,\n requested: {\n ...(flags.account?.length ? { accounts: flags.account } : {}),\n ...(capabilities ? { capabilities } : {}),\n ...(flags.reason ? { reason: flags.reason } : {}),\n },\n client: { ...clientInfo(), tool },\n };\n\n let start: PairingStart;\n try {\n start = await startPairing(url, input);\n } catch (e) {\n if (e instanceof ApiError && e.status === 404) {\n throw new Error(`${url} doesn't support pairing (no /agent/v1/pairings). Is this an agentinbox daemon, and is it up to date?`);\n }\n if (e instanceof ApiError) throw new Error(`${e.message}${e.hint ? `\\n ${e.hint}` : \"\"}`);\n throw e;\n }\n\n const links = approveLinks(url, start);\n out();\n out(\n box([\n pc.bold(\"Approve this agent in the agentinbox console\"),\n \"\",\n `Code: ${pc.bold(pc.yellow(safeText(start.userCode, 40)))}`,\n `Open: ${pc.cyan(safeText(links.primary, 300))}`,\n ...(links.publicUrl\n ? [` or: ${pc.cyan(safeText(links.publicUrl, 300))}`, pc.gray(` (first: the address this CLI used; second: the console's public URL setting)`)]\n : []),\n `Agent: ${safeText(name)}`,\n \"\",\n pc.gray(\"Only approve if the console shows this exact code.\"),\n ]),\n );\n out();\n\n // Ctrl-C: stop cleanly. Nothing was approved; the request just expires.\n const ac = new AbortController();\n const onAbort = () => ac.abort();\n opts.signal?.addEventListener(\"abort\", onAbort, { once: true });\n const onSigint = () => ac.abort();\n if (opts.handleSignals) process.on(\"SIGINT\", onSigint);\n\n const started = Date.now();\n const expiresAt = Date.parse(start.expiresAt) || started + 10 * 60_000;\n let interval = Math.max(1, start.interval || 5) * 1000;\n let note = \"\";\n const status = new StatusLine(process.stderr);\n status.start(\n () =>\n `Waiting for approval · ${formatDuration(Date.now() - started)} elapsed · code expires in ${formatDuration(expiresAt - Date.now())}${note ? pc.yellow(` · ${note}`) : \"\"}`,\n );\n\n let result: PairingPoll | null = null;\n try {\n while (!ac.signal.aborted) {\n await sleep(opts.pollIntervalMs ?? interval, ac.signal);\n if (ac.signal.aborted) break;\n try {\n const r = await pollPairing(url, start.deviceCode);\n note = \"\";\n if (r.status === \"pending\") continue;\n if (r.status === \"slow_down\") {\n // The server asks for more room between polls.\n interval = Math.max(interval + 1000, (r.interval || 0) * 1000);\n continue;\n }\n result = r;\n break;\n } catch (e) {\n if (e instanceof ApiError && e.status === 429) {\n interval += 5000;\n note = \"rate limited, slowing down\";\n continue;\n }\n if (e instanceof ApiError && e.status >= 400 && e.status < 500 && e.status !== 408) {\n throw new Error(`${e.message}${e.hint ? `\\n ${e.hint}` : \"\"}`);\n }\n // Network trouble or a 5xx: keep trying until the code expires.\n note = \"can't reach the daemon, retrying\";\n if (Date.now() > expiresAt + 30_000) {\n result = { status: \"expired\" };\n break;\n }\n }\n }\n } finally {\n status.stop();\n if (opts.handleSignals) process.off(\"SIGINT\", onSigint);\n opts.signal?.removeEventListener(\"abort\", onAbort);\n }\n\n if (!result) {\n err(pc.yellow(\"Cancelled. Nothing was approved; the code expires on its own.\"));\n return CONNECT_EXIT.cancelled;\n }\n\n switch (result.status) {\n case \"denied\":\n err(pc.red(`✖ The request was denied in the console${result.note ? `: ${safeText(result.note, 300)}` : \".\"}`));\n return CONNECT_EXIT.denied;\n case \"expired\":\n err(pc.red(\"✖ The code expired before it was approved.\"));\n err(` Run the same command again for a fresh code, and approve it within ${formatDuration(Date.parse(start.expiresAt) - started)}.`);\n return CONNECT_EXIT.expired;\n case \"consumed\":\n err(pc.red(\"✖ This pairing was already completed and its key handed out once (perhaps by an earlier run of this command).\"));\n err(` For safety the key is never delivered twice. Start over with \\`${NPX} connect\\`, or rotate the agent's key in the console.`);\n return CONNECT_EXIT.consumed;\n case \"approved\":\n break;\n default:\n throw new Error(`Unexpected pairing status ${JSON.stringify((result as { status: unknown }).status)}`);\n }\n\n // --force keeps everything about the listener (targets, filters, limits, forward secret, cwd); only\n // the pairing (daemon, key, agent) is replaced.\n const kept: Partial<Profile> = replacing\n ? {\n types: replacing.types,\n filter: replacing.filter,\n includeBody: replacing.includeBody,\n exec: replacing.exec,\n forward: replacing.forward,\n forwardSecret: replacing.forwardSecret,\n concurrency: replacing.concurrency,\n timeoutSeconds: replacing.timeoutSeconds,\n maxAttempts: replacing.maxAttempts,\n cwd: replacing.cwd,\n }\n : {};\n const profile: Profile = {\n ...kept,\n url,\n apiKey: result.apiKey,\n agentId: result.agent.id,\n agentName: result.agent.name,\n consumer,\n ...(verdict.kind === \"insecure\" ? { insecure: true } : {}),\n tool,\n // Derived from the URL the user chose and transport-checked; the daemon's advertised URLs come\n // from its publicUrl setting and are never trusted with the key.\n mcpUrl: `${url}/mcp`,\n skillUrl: `${url}/skill.md`,\n createdAt: new Date().toISOString(),\n };\n const path = saveProfile(profileName, profile);\n writeClaudeMcpConfig(profileName, profile.mcpUrl!);\n if (typeof result.mcpUrl === \"string\" && result.mcpUrl !== profile.mcpUrl) {\n err(\n pc.yellow(\n `! The daemon advertises its MCP endpoint as ${safeText(result.mcpUrl, 200)} (its \"public URL\" setting); using ${profile.mcpUrl}, the address you connected to. Set the public URL in the console if agents should use another address.`,\n ),\n );\n }\n\n out(`${pc.green(\"✔\")} Approved. Agent ${pc.bold(safeText(result.agent.name))} ${pc.gray(`(${result.agent.id})`)} is connected.`);\n out(` Key saved to ${pc.cyan(path)} ${pc.gray(\"(mode 0600; never displayed. Rotate it in the console if it leaks.)\")}`);\n if (replacing && (replacing.exec || replacing.forward)) {\n out(` Kept this profile's listener settings. Restart the listener to use the new key${isServiceInstalled(profileName) ? `: ${NPX} listen service install${profileName === DEFAULT_PROFILE ? \"\" : ` --profile ${profileName}`}` : \".\"}`);\n }\n if (replacing && replacing.agentId !== profile.agentId) {\n err(\n pc.yellow(\n `! Replaced profile \"${profileName}\" (agent \"${safeText(replacing.agentName)}\", ${replacing.agentId}). Its key still works until you rotate it or delete that agent in the console; config backups made by setup-mcp (*.agentinbox-backup-*) may contain it.`,\n ),\n );\n }\n\n await printGrants(url, profile.apiKey, profileName);\n\n let mcp: McpSetupResult | null = null;\n if (flags.setupMcp) {\n mcp = setupMcp(tool, mcpTarget(profileName, profile), path);\n printMcpResult(mcp);\n }\n printNextSteps(profileName, profile, tool, mcp);\n return CONNECT_EXIT.approved;\n}\n\n/**\n * The approve link. The daemon builds it from its public URL setting (default http://localhost:<port>),\n * which may not be the address this CLI reached it at (127.0.0.1, a LAN IP, an SSH tunnel's port): then\n * the link on the address we used comes first, and the public-URL one is shown as well.\n */\nexport function approveLinks(url: string, start: Pick<PairingStart, \"verificationUrl\" | \"userCode\">): { primary: string; publicUrl: string | null } {\n let advertised: URL;\n try {\n advertised = new URL(start.verificationUrl);\n } catch {\n return { primary: start.verificationUrl, publicUrl: null };\n }\n const ours = new URL(url);\n if (advertised.origin === ours.origin) return { primary: start.verificationUrl, publicUrl: null };\n // Same page on our address: keep a path prefix we connected through (reverse proxy), else swap the origin.\n const rest = `${advertised.search}${advertised.hash}`;\n const primary = advertised.pathname.endsWith(\"/approvals\") ? `${url}/approvals${rest}` : `${ours.origin}${advertised.pathname}${rest}`;\n return { primary, publicUrl: start.verificationUrl };\n}\n\n/** What the approver actually granted, in plain words (the console's choice decides, not the request). */\nasync function printGrants(url: string, key: string, profileName: string): Promise<void> {\n const p = profileName === DEFAULT_PROFILE ? \"\" : ` --profile ${profileName}`;\n try {\n const self = await getSelf(url, key, 8000);\n out(` ${pc.bold(\"Access granted\")} ${pc.gray(\"(chosen by whoever approved it; change it in the console under Agents):\")}`);\n for (const line of describeGrants(self.grants)) out(` ${self.grants.length ? line : pc.yellow(line)}`);\n } catch (e) {\n err(pc.yellow(`! Couldn't read this agent's access yet (${e instanceof Error ? e.message.split(\"\\n\")[0] : String(e)}). Check it with: ${NPX} listen status${p}`));\n }\n}\n\nexport function printMcpResult(r: McpSetupResult): void {\n if (r.ok) out(`${r.dryRun ? pc.cyan(\"○\") : pc.green(\"✔\")} ${r.message}`);\n else err(`${pc.yellow(\"!\")} ${r.message}`);\n if (r.ok && r.changes?.length) {\n // Indented lines are file contents; the rest are steps.\n for (const l of r.changes) out(l.startsWith(\" \") ? pc.gray(` ${l}`) : ` - ${l}`);\n }\n if (r.backup) out(pc.gray(` Backup: ${r.backup}`));\n if (!r.ok && r.manual?.length) {\n out(\" Do it by hand:\");\n for (const l of r.manual) out(` ${l}`);\n }\n if (r.ok && r.verify?.length) out(` ${r.dryRun ? \"Afterwards, check it with\" : \"Check it with\"}: ${r.verify.map((v) => pc.cyan(v)).join(\"; \")}`);\n}\n\nfunction skillCommand(tool: AgentTool, url: string): string {\n switch (tool) {\n case \"claude-code\":\n return `${NPX} skill install --target claude --url ${url}`;\n case \"codex\":\n return `${NPX} skill install --target codex --url ${url}`;\n case \"hermes\":\n return `${NPX} skill install --target ~/.hermes/skills/email --url ${url}`;\n case \"cursor\":\n return `${NPX} skill install --target agents --url ${url}`;\n default:\n return `${NPX} skill print --url ${url} > SKILL.md`;\n }\n}\n\nexport function printNextSteps(profileName: string, profile: Profile, tool: AgentTool, mcp: McpSetupResult | null): void {\n const p = profileName === DEFAULT_PROFILE ? \"\" : ` --profile ${profileName}`;\n const label = tool === \"other\" ? \"your agent\" : TOOL_LABELS[tool];\n const r = recipe(tool, profileName);\n const execArg = shellQuote(r.exec);\n out();\n out(pc.bold(\"Next steps\"));\n let n = 1;\n if (mcp?.ok) {\n out(` ${n++}. ${label} has the agentinbox MCP tools ${pc.gray(`(restart it if it's running)`)}.`);\n } else if (tool === \"other\") {\n out(` ${n++}. Point your agent's MCP client at ${pc.cyan(profile.mcpUrl ?? `${profile.url}/mcp`)} with header Authorization: Bearer <key>`);\n out(pc.gray(` The key is the \"apiKey\" field in ${profilePath(profileName)}.`));\n } else {\n out(` ${n++}. Give ${label} the agentinbox MCP tools without ever seeing the key:`);\n out(` ${pc.cyan(`${NPX} setup-mcp --tool ${tool}${p}`)} ${pc.gray(\"(add --dry-run to see exactly what it changes first)\")}`);\n }\n out(` ${n++}. Install the agentinbox skill so ${label} knows the rules:`);\n out(` ${pc.cyan(skillCommand(tool, profile.url))}`);\n out(` ${n++}. Wake ${label} when mail arrives. First try it in the foreground (Ctrl-C stops it; --save keeps the command in the profile):`);\n out(` ${pc.cyan(`${NPX} listen${p} --save --exec ${execArg}`)}`);\n out(pc.gray(` Only new mail wakes it (message.received), not mail you send. Change it with --types, e.g. --types thread.reply_received (only replies to threads you sent) or --types all.`));\n out(pc.gray(` What the woken agent can use: ${r.confinement}.`));\n for (const note of r.notes) out(pc.gray(` ${note}`));\n out(` ${n++}. Check that it works: in the console's setup, the \"Check that it works\" step sends a test email.`);\n out(` Watch it arrive in the foreground listener as ${pc.cyan(\"→ #… message.received\")} followed by one ${pc.green(\"✓\")} line once ${label} handled it.`);\n out(` ${n++}. Then keep it running in the background (systemd / launchd, starts at login; stop the foreground one first):`);\n out(` ${pc.cyan(`${NPX} listen service install${p}`)}`);\n out(` ${pc.cyan(`${NPX} listen status${p}`)} ${pc.gray(\"(connection, cursor, recent events and the access granted)\")}`);\n out();\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as EVENT_TYPES } from "./types-
|
|
2
|
+
import { n as EVENT_TYPES } from "./types-wY3IqC2D.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { RE2JS } from "re2js";
|
|
5
5
|
//#region server/util/glob.ts
|
|
@@ -137,4 +137,4 @@ function matchesFilter(f, ev) {
|
|
|
137
137
|
//#endregion
|
|
138
138
|
export { webhookPatchSchema as a, matchesGlob as c, webhookInputSchema as i, normalizeFilter as n, subjectPatternError as o, webhookFilterSchema as r, matchesAnyGlob as s, matchesFilter as t };
|
|
139
139
|
|
|
140
|
-
//# sourceMappingURL=filter-
|
|
140
|
+
//# sourceMappingURL=filter-Dl9GOkNe.js.map
|