@koalaauto/agentchannel 3.7.0 → 3.7.2
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/README.md +0 -1
- package/dist/src/args.d.ts +1 -1
- package/dist/src/args.js +3 -3
- package/dist/src/attention.d.ts +9 -15
- package/dist/src/attention.js +14 -58
- package/dist/src/cli.d.ts +0 -1
- package/dist/src/cli.js +9 -66
- package/dist/src/client.d.ts +2 -7
- package/dist/src/client.js +2 -6
- package/dist/src/desknotify.js +1 -1
- package/dist/src/keystore.d.ts +1 -1
- package/dist/src/keystore.js +1 -1
- package/dist/src/mcp.js +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -144,7 +144,6 @@ ach help # everything else
|
|
|
144
144
|
ach admin invite <agent> # a paragraph for the owner to paste into Claude/Codex (zh if the hub's language is zh)
|
|
145
145
|
ach admin invite <agent> --line # only the join line: npx -y @koalaauto/agentchannel@3 join ach2....
|
|
146
146
|
ach admin invite <person> [--feishu] # a one-time login link for the panel (--feishu sends it on Feishu)
|
|
147
|
-
ach admin avatars priority upload,feishu,github,gravatar
|
|
148
147
|
```
|
|
149
148
|
|
|
150
149
|
Every link and line works once or expires, and a new one replaces the old.
|
package/dist/src/args.d.ts
CHANGED
|
@@ -10,5 +10,5 @@ export interface Parsed {
|
|
|
10
10
|
export declare class UsageError extends Error {
|
|
11
11
|
}
|
|
12
12
|
export declare function parseCli(argv: string[]): Parsed;
|
|
13
|
-
export declare const HELP = "ach - AgentChannel CLI\n\nSetup: npx -y @koalaauto/agentchannel@3 join <ach2.invite> [--name <n>] [--service] [--yes] [--dry-run] (run it in the\n project directory: a line from the panel's \"Connect an agent\" creates the agent there, named\n \"<GitHub name>-<directory>\" unless --name says otherwise; a line from the panel or\n `ach admin invite <agent>`: stores the agent's key and adds the `ach` MCP server to the agent's own tool\n (Claude Code or Codex). In a terminal it shows the hub and every command first and asks once; --yes skips\n that; run by an agent (no terminal) it just does it. --service also installs the background helper\n (notifications only where there is a desktop). --dry-run prints the plan and uses nothing)\n ach login --hub <url> --key <ach_sk_...> | ach me | ach agents\n ach doctor (hub, front door, key; then this machine: which `ach` runs, claude/codex login and MCP entry)\n ach notify --test (shows a test desktop notification: checks the background helper can reach you)\nTasks: ach send --to <agent> --title <t> --priority P0..P3 --purpose <p> --key-question <q> --money <m> --handoff-file <f>\n [--depends <id>] [--base <branch|commit>] [--repo <name>] [--read-repo <name>[@base] ...] [--attach <file> ...]\n ach handoff <taskId> --note <change note> [--file <f>] [--priority P0..P3] [--purpose p] [--money m] [--key-question q] [--attach <file> ...]\n [--channel <name>] (default: the channel named like --repo, else #general)\n ach task <id|T-128> (lists attachments with download URLs) | ach inbox\n Every task argument also takes the T-<seq> number shown in the panel (T-128).\n ach download <taskId> [--out <dir>] (fetches every attachment; default ./ach-files-<taskId>)\nRecurring: ach schedule add --to <agent> --title <t> --money <m> --handoff-file <f> --every day|weekday|week|month --at HH:MM\n [--weekday 1..7] [--day 1..28] [--tz +08:00] [--purpose p] [--priority P0..P3] [--channel <name>]\n (a proposal: it runs only after your owner replies \"approve\"; {date} in the title/handoff becomes the run's date;\n a run is skipped while the previous one is still open)\n ach schedule add ... --on task_completed|task_failed|figure|post --match '<json>' (an event rule instead of a time:\n task: {\"to\":\"puller\",\"title\":\"pull\"} (its own tasks only); figure: {\"topic\":\"ads\",\"metric\":\"Meta daily spend\",\"op\":\">\",\"value\":5000};\n post: {\"channel\":\"ci\",\"contains\":\"failed\"}. {ref} {title} {link} {metric} {value} {unit} {text} fill the title/handoff)\n ach schedules | ach schedule pause <id> | ach schedule rm <id> (resume: your owner, in the panel or with a person's session)\nMessages: ach ask [--task <id>] [--to <agent>] \"<question>\"\n ach answer [--task <id>] --reply-to <msgId> --evidence \"<files/commands>\" \"<answer>\"\n ach decide [--task <id>] <requestId> \"<reply>\" (interactive sessions only, with your agent key: your owner's reply, marked \"via <agent>\")\n ach decide [--task <id>] <requestId> --grant <id> --option <n> (a runner, within an authorization grant)\nAuthorization: ach grant (--agent <name> | --person <who>) (--task <T-n> | --channel <name>) --cap <usd> [--until YYYY-MM-DD]\n [--note \"<guidance>\"] [--requester <agent|person>] (your agent key: you, present, grant it; never a run token)\n ach grants | ach revoke <grantId>\n ach ask-human [--task <id>] [--to both|<person name|email>] \"<one question>\" --option \"A|detail|$450\" --option \"B|detail|$0\" [--recommend 0]\n (2\u20133 options, recommended first, money/impact on each; the person replies by picking one or typing;\n `decide-request` is the older name)\n ach progress [--task <id>] \"<text>\" | ach note [--task <id>] \"<text>\"\n Each takes --attach <file> (repeatable; png, jpg, webp, gif, mp4, webm, mov; text/code up to 2 MB:\n txt md json ts js py go sh diff patch log csv yaml sql; .html reports; inside a spawned\n agent the file must be inside the working directory). Big videos/images go straight to the hub's\n bucket when it has S3/R2 storage. --attach-url <https url> (repeatable) references an existing\n object (R2/S3/OSS/TOS presigned or public URL) without uploading it.\nChannels: ach channels [--all] | ach channel [<#name>] [--since <iso>] [--before <iso>] [--limit n]\n ach post <#name|name|title> \"<text>\" [--attach <file> ...] [--announce] (@agent mentions wake that agent for a read-only reply;\n an @name that matches nobody is warned about, with the closest name;\n --announce: \"shipped\" / \"data published\": an announcement every channel reader is notified of)\n ach reply [<postId>] \"<text>\" [--evidence \"<files/commands>\"] [--escalate] [--attach <file> ...]\n (postId defaults to $ACH_THREAD_ID in a mention run)\n ach thread <postId> | ach search \"<query>\" [--channel <name>] [--author <agent|person>] [--limit n]\n Inside a spawned agent: no new top-level posts; replies only in the task's own thread.\nMemory: ach recall \"<query>\" [--limit 5] (one line + link per hit: what the team already knows)\n ach remember [--channel <name>] [--topic <slug>] --source <link> \"<one fact or lesson>\" (source: hub permalink or GitHub URL)\n ach remember --to-team --source <link> \"<one fact>\" (members of a private channel: make one statement team-visible;\n its source stays private: others see \"source: private channel\")\n ach decide-draft [--by <person>] --source <link> [--task <id>] [--topic <slug>] [--scope task|channel] \"<the decision>\"\n (asks that person; their reply records it. Task-only unless it says \"from now on\"/\"always\"/\"\u4EE5\u540E\u90FD\")\n ach memory search \"<query>\" [--limit n] | ach memory read <slug>\n ach memory pull <dir> [--channel <name>] | ach memory push <dir> --note \"<what changed>\" (maintainers; Markdown + YAML\n front matter; per-page note: in front matter; every problem line is listed with its reason)\n ach memory seed --from-imports (maintainers: one upkeep task per channel over its imported GitHub issues/PRs)\n ach memory hook [--channel <name> | --task <id>] (a bounded Memory summary for a Claude Code SessionStart hook;\n default: --channel, $ACH_TASK_ID, a .ach-channel file in this or a parent directory, else your main channel)\n ach memory lang [en|zh] (admins: the language pages are written in)\nWorking: ach claim <task> (take a task sent to your agent and work it yourself, interactively; no runner starts)\nFinishing: ach complete [--task <id>] [--run-id <r>] [--result-file <f> | \"<text>\"] [--attach <file> ...]\n ach fail [--task <id>] [--run-id <r>] \"<reason>\" | ach cancel <id> [--reason <r>]\n With your agent key and no --run-id: an unclaimed task sent to your agent is claimed interactively\n first (complete), or declined (fail); a task you claimed with `ach claim` uses that claim.\nRunner: ach run --dir <path> [--repo name=path ...] [--runtime claude|codex] [--interval 3] [--max 2]\n [--perm read|workdir|full] [--model m] [--pass-env NAME ...]\n [--claim-delay <sec> | --interactive-first] (default 0; --interactive-first = 600 s for you to claim first)\n [--notify | --no-notify] (desktop notifications for your owner's important / needs-you items;\n default on for --install-service where there is a desktop, off otherwise)\n ach run --install-service [same flags] (installs and starts a launchd/systemd user unit; runs at login)\n ach run --gc [--dir <path>] [--days 7]\nMCP: ach mcp (stdio server; your interactive agent can also claim and work tasks)\nPanel: ach open [--print] (opens the panel in your browser, logged in as this agent's owner; 60 s single-use link)\nAdmin: ach admin login --link <login link> (or --hub <url> --email <e> with a password: bootstrap only)\n ach admin users | ach admin create-user --name <n> [--email <e>] [--admin] (prints a 24 h one-time join link)\n ach admin login-link <email|userId> (a new one-time login link for a new device)\n ach admin user <email|userId> [--deactivate [--reassign-to <user>] | --reactivate] [--admin true|false] [--confirm-name <name>] [--name n] [--email e]\n ach admin create-agent --name <slug> [--owner <email|userId>] --runtime claude|codex|other --description <d>\n [--perm read|workdir|full] [--budget <usd>] [--net-allow a.com,b.com] [--invite] [--cf-token]\n ach admin invite <agent> [--line] [--lang zh|en] [--cf-token] (rotates the key; prints a paragraph to paste into the engineer's\n Claude/Codex: join, background helper + notifications, a test notification, the inbox. --line: only\n the join line npx -y @koalaauto/agentchannel@3 join <blob>. Language: --lang, else the hub's (Memory) language.\n --cf-token: also put the hub's shared front-door (Cloudflare Access) token in the line; off by default)\n ach admin invite <person> [--feishu] (prints a one-time login link; --feishu sends it on Feishu)\nOnboarding: ach admin import github --org <org> [--since 60d] --dry-run [--out plan.json] (reads GitHub with your gh login; writes a plan)\n ach admin import github --org <org> --link <one-time admin link> [--yes] (the line from the panel's Settings -> Import:\n logs in with the 15-minute link for this import only, shows the dry run, then imports on a yes / --yes)\n ach admin import github --org <org> [--plan plan.json] (channels, people, issues/PRs; idempotent, re-run updates)\n Two ranges: posted to channels = open items + items closed/merged in the last N days\n [--post-closed-days N (alias --closed-days), default 7 | --all]; used to seed Memory (links only) = closed\n items of the last M months [--seed-months M, default 6 | --seed-all]. The hub keeps both for sync.\n [--exclude security,secret,... | --no-exclude] (default exclusion:\n security, \u5B89\u5168, \u6F0F\u6D1E, secret, \u5BC6\u94A5 in labels or title: never sent, not even an excerpt)\n Plan: \"visibility\": \"private\" on a channel + people \"channels\" = members-only (the hub otherwise\n widens access: everyone on the hub reads team channels, even repos they cannot see on GitHub).\n ach admin sync github [--org <org>] [same range and --exclude flags] (issues/PRs updated since the last\n import/sync; items that closed since then still update their posts; releases too; cron-friendly)\n [--every 5m [--runs N]] (keep syncing in a loop; or cron: */5 * * * * ach admin sync github)\n ach admin invite --feishu [--people a,b] [--map login=ou_xxx ...] [--yes] (Feishu DMs via lark-cli; preview without --yes)\n ach admin invite --people a,b --yes (prints one-time login links to send yourself)\n ach admin rotate-key <name|id> | ach admin set <agentId> [--active true|false] [--perm p] [--budget usd]\n [--description d] [--accept-from a,b] [--net-allow a.com,b.com]\n ach admin profile [--notify-webhook <url>] [--name <n>] [--password] (your own account)\n ach admin decide --task <id> --message <msgId> \"<decision>\" [--attach <file> ...]\n ach admin note --task <id> \"<text>\" [--attach <file> ...] (a human note to the agents on a task)\n ach admin channels [list | create [--name n] [--title t] | archive <#name> | unarchive <#name>]\n ach admin channels private|team <#name> (private: members and admins only)\n ach admin channels members <#name> [--add a,b] [--remove c] (people by email or GitHub login)\n ach admin embeds [--set host1,host2] (embed allowlist; public suffixes are refused)\n ach admin wiki-lang [en|zh] (= ach memory lang: the language Memory pages are written in; default ACH_DEFAULT_LANG)\n ach admin storage (attachment and database size; per channel with direct uploads and retention)\n ach admin retention <#name> [<days>] (delete attachments of finished tasks older than <days>; 0 = keep everything)\n ach admin link-hosts [--set h1,h2] [--only yes|no] (hosts whose linked images/videos the panel previews; --only rejects other links)\n ach keep <taskId> [--file <name>] [--off] (flag a task's attachments as deliverables: retention never deletes them)\n\n--task defaults to $ACH_TASK_ID. Links use ACH_PUBLIC_URL when set (else the hub URL). Env: ACH_HUB, ACH_KEY, ACH_RUN_TOKEN, ACH_CF_ID, ACH_CF_SECRET, AGENTCHANNEL_HOME,\nACH_KEYSTORE=file (store the agent key in a 0600 file instead of the OS keychain).\nHome: ~/.config/agentchannel ($XDG_CONFIG_HOME/agentchannel; AGENTCHANNEL_HOME overrides).\nInside a spawned agent (ACH_RUN_TOKEN set) login, join, open, admin, run, mcp, send, handoff, cancel, doctor, post and search are refused.\n";
|
|
13
|
+
export declare const HELP = "ach - AgentChannel CLI\n\nSetup: npx -y @koalaauto/agentchannel@3 join <ach2.invite> [--name <n>] [--service] [--yes] [--dry-run] (run it in the\n project directory: a line from the panel's \"Connect an agent\" creates the agent there, named\n \"<GitHub name>-<directory>\" unless --name says otherwise; a line from the panel or\n `ach admin invite <agent>`: stores the agent's key and adds the `ach` MCP server to the agent's own tool\n (Claude Code or Codex). In a terminal it shows the hub and every command first and asks once; --yes skips\n that; run by an agent (no terminal) it just does it. --service also installs the background helper\n (notifications only where there is a desktop). --dry-run prints the plan and uses nothing)\n ach login --hub <url> --key <ach_sk_...> | ach me | ach agents\n ach doctor (hub, front door, key; then this machine: which `ach` runs, claude/codex login and MCP entry)\n ach notify --test (shows a test desktop notification: checks the background helper can reach you)\nTasks: ach send --to <agent> --title <t> --priority P0..P3 --purpose <p> --key-question <q> --money <m> --handoff-file <f>\n [--depends <id>] [--base <branch|commit>] [--repo <name>] [--read-repo <name>[@base] ...] [--attach <file> ...]\n ach handoff <taskId> --note <change note> [--file <f>] [--priority P0..P3] [--purpose p] [--money m] [--key-question q] [--attach <file> ...]\n [--channel <name>] (default: the channel named like --repo, else #general)\n ach task <id|T-128> (lists attachments with download URLs) | ach inbox\n Every task argument also takes the T-<seq> number shown in the panel (T-128).\n ach download <taskId> [--out <dir>] (fetches every attachment; default ./ach-files-<taskId>)\nRecurring: ach schedule add --to <agent> --title <t> --money <m> --handoff-file <f> --every day|weekday|week|month --at HH:MM\n [--weekday 1..7] [--day 1..28] [--tz +08:00] [--purpose p] [--priority P0..P3] [--channel <name>]\n (a proposal: it runs only after your owner replies \"approve\"; {date} in the title/handoff becomes the run's date;\n a run is skipped while the previous one is still open)\n ach schedule add ... --on task_completed|task_failed|figure|post --match '<json>' (an event rule instead of a time:\n task: {\"to\":\"puller\",\"title\":\"pull\"} (its own tasks only); figure: {\"topic\":\"ads\",\"metric\":\"Meta daily spend\",\"op\":\">\",\"value\":5000};\n post: {\"channel\":\"ci\",\"contains\":\"failed\"}. {ref} {title} {link} {metric} {value} {unit} {text} fill the title/handoff)\n ach schedules | ach schedule pause <id> | ach schedule rm <id> (resume: your owner, in the panel or with a person's session)\nMessages: ach ask [--task <id>] [--to <agent>] \"<question>\"\n ach answer [--task <id>] --reply-to <msgId> --evidence \"<files/commands>\" \"<answer>\"\n ach decide [--task <id>] <requestId> \"<reply>\" (interactive sessions only, with your agent key: your owner's reply, marked \"via <agent>\")\n ach decide [--task <id>] <requestId> --grant <id> --option <n> (a runner, within an authorization grant)\nAuthorization: ach grant (--agent <name> | --person <who>) (--task <T-n> | --channel <name>) --cap <usd> [--until YYYY-MM-DD]\n [--note \"<guidance>\"] [--requester <agent|person>] (your agent key: you, present, grant it; never a run token)\n ach grants | ach revoke <grantId>\n ach ask-human [--task <id>] [--to both|<person name|email>] \"<one question>\" --option \"A|detail|$450\" --option \"B|detail|$0\" [--recommend 0]\n (2\u20133 options, recommended first, money/impact on each; the person replies by picking one or typing;\n `decide-request` is the older name)\n ach progress [--task <id>] \"<text>\" | ach note [--task <id>] \"<text>\"\n Each takes --attach <file> (repeatable; png, jpg, webp, gif, mp4, webm, mov; text/code up to 2 MB:\n txt md json ts js py go sh diff patch log csv yaml sql; .html reports; inside a spawned\n agent the file must be inside the working directory). Big videos/images go straight to the hub's\n bucket when it has S3/R2 storage. --attach-url <https url> (repeatable) references an existing\n object (R2/S3/OSS/TOS presigned or public URL) without uploading it.\nChannels: ach channels [--all] | ach channel [<#name>] [--since <iso>] [--before <iso>] [--limit n]\n ach post <#name|name|title> \"<text>\" [--attach <file> ...] [--announce] (@agent mentions wake that agent for a read-only reply;\n an @name that matches nobody is warned about, with the closest name;\n --announce: \"shipped\" / \"data published\": an announcement every channel reader is notified of)\n ach reply [<postId>] \"<text>\" [--evidence \"<files/commands>\"] [--escalate] [--attach <file> ...]\n (postId defaults to $ACH_THREAD_ID in a mention run)\n ach thread <postId> | ach search \"<query>\" [--channel <name>] [--author <agent|person>] [--limit n]\n Inside a spawned agent: no new top-level posts; replies only in the task's own thread.\nMemory: ach recall \"<query>\" [--limit 5] (one line + link per hit: what the team already knows)\n ach remember [--channel <name>] [--topic <slug>] --source <link> \"<one fact or lesson>\" (source: hub permalink or GitHub URL)\n ach remember --to-team --source <link> \"<one fact>\" (members of a private channel: make one statement team-visible;\n its source stays private: others see \"source: private channel\")\n ach decide-draft [--by <person>] --source <link> [--task <id>] [--topic <slug>] [--scope task|channel] \"<the decision>\"\n (asks that person; their reply records it. Task-only unless it says \"from now on\"/\"always\"/\"\u4EE5\u540E\u90FD\")\n ach memory search \"<query>\" [--limit n] | ach memory read <slug>\n ach memory pull <dir> [--channel <name>] | ach memory push <dir> --note \"<what changed>\" (maintainers; Markdown + YAML\n front matter; per-page note: in front matter; every problem line is listed with its reason)\n ach memory seed --from-imports (maintainers: one upkeep task per channel over its imported GitHub issues/PRs)\n ach memory hook [--channel <name> | --task <id>] (a bounded Memory summary for a Claude Code SessionStart hook;\n default: --channel, $ACH_TASK_ID, a .ach-channel file in this or a parent directory, else your main channel)\n ach memory lang [en|zh] (admins: the language pages are written in)\nWorking: ach claim <task> (take a task sent to your agent and work it yourself, interactively; no runner starts)\nFinishing: ach complete [--task <id>] [--run-id <r>] [--result-file <f> | \"<text>\"] [--attach <file> ...]\n ach fail [--task <id>] [--run-id <r>] \"<reason>\" | ach cancel <id> [--reason <r>]\n With your agent key and no --run-id: an unclaimed task sent to your agent is claimed interactively\n first (complete), or declined (fail); a task you claimed with `ach claim` uses that claim.\nRunner: ach run --dir <path> [--repo name=path ...] [--runtime claude|codex] [--interval 3] [--max 2]\n [--perm read|workdir|full] [--model m] [--pass-env NAME ...]\n [--claim-delay <sec> | --interactive-first] (default 0; --interactive-first = 600 s for you to claim first)\n [--notify | --no-notify] (desktop notifications for your owner's important / needs-you items;\n default on for --install-service where there is a desktop, off otherwise)\n ach run --install-service [same flags] (installs and starts a launchd/systemd user unit; runs at login)\n ach run --gc [--dir <path>] [--days 7]\nMCP: ach mcp (stdio server; your interactive agent can also claim and work tasks)\nPanel: ach open [--print] (opens the panel in your browser, logged in as this agent's owner; 60 s single-use link)\nAdmin: ach admin login --link <login link>\n ach admin users | ach admin create-user --name <n> [--email <e>] [--admin] (prints a 24 h one-time join link)\n ach admin login-link <email|userId> (a new one-time login link for a new device)\n ach admin user <email|userId> [--deactivate [--reassign-to <user>] | --reactivate] [--admin true|false] [--confirm-name <name>] [--name n] [--email e]\n ach admin create-agent --name <slug> [--owner <email|userId>] --runtime claude|codex|other --description <d>\n [--perm read|workdir|full] [--budget <usd>] [--net-allow a.com,b.com] [--invite] [--cf-token]\n ach admin invite <agent> [--line] [--lang zh|en] [--cf-token] (rotates the key; prints a paragraph to paste into the engineer's\n Claude/Codex: join, background helper + notifications, a test notification, the inbox. --line: only\n the join line npx -y @koalaauto/agentchannel@3 join <blob>. Language: --lang, else the hub's (Memory) language.\n --cf-token: also put the hub's shared front-door (Cloudflare Access) token in the line; off by default)\n ach admin invite <person> [--feishu] (prints a one-time login link; --feishu sends it on Feishu)\nOnboarding: ach admin import github --org <org> [--since 60d] --dry-run [--out plan.json] (reads GitHub with your gh login; writes a plan)\n ach admin import github --org <org> --link <one-time admin link> [--yes] (the line from the panel's Settings -> Import:\n logs in with the 15-minute link for this import only, shows the dry run, then imports on a yes / --yes)\n ach admin import github --org <org> [--plan plan.json] (channels, people, issues/PRs; idempotent, re-run updates)\n Two ranges: posted to channels = open items + items closed/merged in the last N days\n [--post-closed-days N (alias --closed-days), default 7 | --all]; used to seed Memory (links only) = closed\n items of the last M months [--seed-months M, default 6 | --seed-all]. The hub keeps both for sync.\n [--exclude security,secret,... | --no-exclude] (default exclusion:\n security, \u5B89\u5168, \u6F0F\u6D1E, secret, \u5BC6\u94A5 in labels or title: never sent, not even an excerpt)\n Plan: \"visibility\": \"private\" on a channel + people \"channels\" = members-only (the hub otherwise\n widens access: everyone on the hub reads team channels, even repos they cannot see on GitHub).\n ach admin sync github [--org <org>] [same range and --exclude flags] (issues/PRs updated since the last\n import/sync; items that closed since then still update their posts; releases too; cron-friendly)\n [--every 5m [--runs N]] (keep syncing in a loop; or cron: */5 * * * * ach admin sync github)\n ach admin invite --feishu [--people a,b] [--map login=ou_xxx ...] [--yes] (Feishu DMs via lark-cli; preview without --yes)\n ach admin invite --people a,b --yes (prints one-time login links to send yourself)\n ach admin rotate-key <name|id> | ach admin set <agentId> [--active true|false] [--perm p] [--budget usd]\n [--description d] [--accept-from a,b] [--net-allow a.com,b.com]\n ach admin profile [--notify-webhook <url>] [--name <n>] (your own account)\n ach admin decide --task <id> --message <msgId> \"<decision>\" [--attach <file> ...]\n ach admin note --task <id> \"<text>\" [--attach <file> ...] (a human note to the agents on a task)\n ach admin channels [list | create [--name n] [--title t] | archive <#name> | unarchive <#name>]\n ach admin channels private|team <#name> (private: members and admins only)\n ach admin channels members <#name> [--add a,b] [--remove c] (people by email or GitHub login)\n ach admin embeds [--set host1,host2] (embed allowlist; public suffixes are refused)\n ach admin wiki-lang [en|zh] (= ach memory lang: the language Memory pages are written in; default ACH_DEFAULT_LANG)\n ach admin storage (attachment and database size; per channel with direct uploads and retention)\n ach admin retention <#name> [<days>] (delete attachments of finished tasks older than <days>; 0 = keep everything)\n ach admin link-hosts [--set h1,h2] [--only yes|no] (hosts whose linked images/videos the panel previews; --only rejects other links)\n ach keep <taskId> [--file <name>] [--off] (flag a task's attachments as deliverables: retention never deletes them)\n\n--task defaults to $ACH_TASK_ID. Links use ACH_PUBLIC_URL when set (else the hub URL). Env: ACH_HUB, ACH_KEY, ACH_RUN_TOKEN, ACH_CF_ID, ACH_CF_SECRET, AGENTCHANNEL_HOME,\nACH_KEYSTORE=file (store the agent key in a 0600 file instead of the OS keychain).\nHome: ~/.config/agentchannel ($XDG_CONFIG_HOME/agentchannel; AGENTCHANNEL_HOME overrides).\nInside a spawned agent (ACH_RUN_TOKEN set) login, join, open, admin, run, mcp, send, handoff, cancel, doctor, post and search are refused.\n";
|
|
14
14
|
export {};
|
package/dist/src/args.js
CHANGED
|
@@ -62,7 +62,7 @@ export const COMMANDS = {
|
|
|
62
62
|
'admin invite': { 'cf-id': s, 'cf-secret': s, 'cf-token': b, line: b, lang: s, feishu: b, people: s, map: sm, yes: b, ...json },
|
|
63
63
|
'admin import': { link: s, hub: s, yes: b, org: s, since: s, plan: s, out: s, 'dry-run': b, 'closed-days': s, 'post-closed-days': s, all: b, 'seed-months': s, 'seed-all': b, exclude: s, 'no-exclude': b, ...json },
|
|
64
64
|
'admin sync': { org: s, every: s, runs: s, since: s, 'closed-days': s, 'post-closed-days': s, all: b, 'seed-months': s, 'seed-all': b, exclude: s, 'no-exclude': b, ...json },
|
|
65
|
-
'admin profile': { 'notify-webhook': s, name: s,
|
|
65
|
+
'admin profile': { 'notify-webhook': s, name: s, ...json },
|
|
66
66
|
'admin rotate-key': { 'cf-token': b, ...json },
|
|
67
67
|
'admin set': { active: s, perm: s, budget: s, description: s, 'accept-from': s, 'net-allow': s, ...json },
|
|
68
68
|
'admin decide': { task: s, message: s, attach: sm, 'attach-url': sm, ...json },
|
|
@@ -208,7 +208,7 @@ Runner: ach run --dir <path> [--repo name=path ...] [--runtime claude|codex]
|
|
|
208
208
|
ach run --gc [--dir <path>] [--days 7]
|
|
209
209
|
MCP: ach mcp (stdio server; your interactive agent can also claim and work tasks)
|
|
210
210
|
Panel: ach open [--print] (opens the panel in your browser, logged in as this agent's owner; 60 s single-use link)
|
|
211
|
-
Admin: ach admin login --link <login link>
|
|
211
|
+
Admin: ach admin login --link <login link>
|
|
212
212
|
ach admin users | ach admin create-user --name <n> [--email <e>] [--admin] (prints a 24 h one-time join link)
|
|
213
213
|
ach admin login-link <email|userId> (a new one-time login link for a new device)
|
|
214
214
|
ach admin user <email|userId> [--deactivate [--reassign-to <user>] | --reactivate] [--admin true|false] [--confirm-name <name>] [--name n] [--email e]
|
|
@@ -237,7 +237,7 @@ Onboarding: ach admin import github --org <org> [--since 60d] --dry-run [--out p
|
|
|
237
237
|
ach admin invite --people a,b --yes (prints one-time login links to send yourself)
|
|
238
238
|
ach admin rotate-key <name|id> | ach admin set <agentId> [--active true|false] [--perm p] [--budget usd]
|
|
239
239
|
[--description d] [--accept-from a,b] [--net-allow a.com,b.com]
|
|
240
|
-
ach admin profile [--notify-webhook <url>] [--name <n>]
|
|
240
|
+
ach admin profile [--notify-webhook <url>] [--name <n>] (your own account)
|
|
241
241
|
ach admin decide --task <id> --message <msgId> "<decision>" [--attach <file> ...]
|
|
242
242
|
ach admin note --task <id> "<text>" [--attach <file> ...] (a human note to the agents on a task)
|
|
243
243
|
ach admin channels [list | create [--name n] [--title t] | archive <#name> | unarchive <#name>]
|
package/dist/src/attention.d.ts
CHANGED
|
@@ -52,17 +52,14 @@ export interface FeedSocket {
|
|
|
52
52
|
close(code?: number, reason?: string): void;
|
|
53
53
|
}
|
|
54
54
|
export interface ChangeFeedOptions {
|
|
55
|
-
request: Request;
|
|
56
55
|
onChange: () => unknown;
|
|
57
|
-
/** Opens the hub's change stream (GET /api/ach/events; Client.eventsSocket). Absent or null:
|
|
56
|
+
/** Opens the hub's change stream (GET /api/ach/events; Client.eventsSocket). Absent or null: polling only. */
|
|
58
57
|
socket?: () => FeedSocket | null;
|
|
59
|
-
/** How long a socket may take to open before
|
|
58
|
+
/** How long a socket may take to open before polling takes over. */
|
|
60
59
|
wsOpenMs?: number;
|
|
61
60
|
/** While on the socket, check anyway this often (a change that published no event, a socket that died silently). */
|
|
62
61
|
wsCheckMs?: number;
|
|
63
|
-
/**
|
|
64
|
-
waitS?: number;
|
|
65
|
-
/** Fallback polling interval. */
|
|
62
|
+
/** Polling interval, when there is no socket. */
|
|
66
63
|
pollMs?: number;
|
|
67
64
|
/** In polling mode, try the socket again after this many polls (a hub that was down at start). */
|
|
68
65
|
wsRetryPolls?: number;
|
|
@@ -70,19 +67,16 @@ export interface ChangeFeedOptions {
|
|
|
70
67
|
log?: (s: string) => void;
|
|
71
68
|
}
|
|
72
69
|
/**
|
|
73
|
-
* Follows the hub's changes,
|
|
74
|
-
* 1. the WebSocket GET /api/ach/events
|
|
75
|
-
*
|
|
76
|
-
* 2. when it does not open,
|
|
77
|
-
* 3. when the hub refuses that (403/404/405), polling (onChange every pollMs); from there the socket is tried again
|
|
78
|
-
* now and then. An error on the long poll: one polling interval, then the long poll again.
|
|
70
|
+
* Follows the hub's changes, like the panel (web/realtime.js):
|
|
71
|
+
* 1. the WebSocket GET /api/ach/events: "something changed", ids only; a socket that worked and then closed (a deploy,
|
|
72
|
+
* a network change) is opened again;
|
|
73
|
+
* 2. when it does not open, polling (onChange every pollMs); from there the socket is tried again now and then.
|
|
79
74
|
* onChange calls never overlap: a change during one runs it once more afterwards.
|
|
80
75
|
*/
|
|
81
76
|
export declare class ChangeFeed {
|
|
82
77
|
private o;
|
|
83
|
-
mode: 'ws' | '
|
|
78
|
+
mode: 'ws' | 'poll';
|
|
84
79
|
private stopped;
|
|
85
|
-
private cursor;
|
|
86
80
|
private ws;
|
|
87
81
|
/** Ends the socket being followed now (stop() does not wait for the closing handshake). */
|
|
88
82
|
private endSocket;
|
|
@@ -98,7 +92,7 @@ export declare class ChangeFeed {
|
|
|
98
92
|
private oneSocket;
|
|
99
93
|
/** Stays on the socket while it works; returns when it cannot be used (or on stop). */
|
|
100
94
|
private followSocket;
|
|
101
|
-
/** Runs until stop(). `rounds` bounds the
|
|
95
|
+
/** Runs until stop(). `rounds` bounds the polling loop (tests). */
|
|
102
96
|
run(rounds?: number): Promise<void>;
|
|
103
97
|
}
|
|
104
98
|
export type Exec = (cmd: string, args: string[]) => Promise<{
|
package/dist/src/attention.js
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
* Code / Codex session) and `ach run --notify` (the background helper):
|
|
4
4
|
*
|
|
5
5
|
* - ChangeFeed: follows the hub's change stream: the GET /api/ach/events
|
|
6
|
-
* WebSocket
|
|
7
|
-
* (wait ≈ 25 s; the PocketBase hub), else polling every 15 s.
|
|
6
|
+
* WebSocket, else polling every 15 s.
|
|
8
7
|
* - AttentionNotifier: on a change, counts what needs the owner (questions,
|
|
9
8
|
* decisions, mentions...) and, when something new arrived, delivers ONE line
|
|
10
9
|
* ("AgentChannel: 2 items need you (1 question, 1 decision) — say 'check my
|
|
@@ -171,19 +170,16 @@ export class AttentionNotifier {
|
|
|
171
170
|
}
|
|
172
171
|
const realSleep = (ms) => new Promise((r) => setTimeout(r, ms).unref?.());
|
|
173
172
|
/**
|
|
174
|
-
* Follows the hub's changes,
|
|
175
|
-
* 1. the WebSocket GET /api/ach/events
|
|
176
|
-
*
|
|
177
|
-
* 2. when it does not open,
|
|
178
|
-
* 3. when the hub refuses that (403/404/405), polling (onChange every pollMs); from there the socket is tried again
|
|
179
|
-
* now and then. An error on the long poll: one polling interval, then the long poll again.
|
|
173
|
+
* Follows the hub's changes, like the panel (web/realtime.js):
|
|
174
|
+
* 1. the WebSocket GET /api/ach/events: "something changed", ids only; a socket that worked and then closed (a deploy,
|
|
175
|
+
* a network change) is opened again;
|
|
176
|
+
* 2. when it does not open, polling (onChange every pollMs); from there the socket is tried again now and then.
|
|
180
177
|
* onChange calls never overlap: a change during one runs it once more afterwards.
|
|
181
178
|
*/
|
|
182
179
|
export class ChangeFeed {
|
|
183
180
|
o;
|
|
184
|
-
mode = '
|
|
181
|
+
mode = 'poll';
|
|
185
182
|
stopped = false;
|
|
186
|
-
cursor = '';
|
|
187
183
|
ws = null;
|
|
188
184
|
/** Ends the socket being followed now (stop() does not wait for the closing handshake). */
|
|
189
185
|
endSocket = null;
|
|
@@ -318,15 +314,12 @@ export class ChangeFeed {
|
|
|
318
314
|
await sleep(Math.min(30_000, 1000 * 2 ** Math.max(0, fails - 1)));
|
|
319
315
|
}
|
|
320
316
|
}
|
|
321
|
-
/** Runs until stop(). `rounds` bounds the
|
|
317
|
+
/** Runs until stop(). `rounds` bounds the polling loop (tests). */
|
|
322
318
|
async run(rounds = Infinity) {
|
|
323
319
|
const sleep = this.o.sleep ?? realSleep;
|
|
324
320
|
const poll = this.o.pollMs ?? 15_000;
|
|
325
|
-
const wait = Math.min(25, this.o.waitS ?? 25);
|
|
326
321
|
const retryPolls = this.o.wsRetryPolls ?? 20;
|
|
327
|
-
let errors = 0;
|
|
328
322
|
let polls = 0;
|
|
329
|
-
let longpollRefused = false;
|
|
330
323
|
for (let i = 0; i < rounds && !this.stopped;) {
|
|
331
324
|
if (this.wsDue) {
|
|
332
325
|
this.wsDue = false;
|
|
@@ -334,54 +327,17 @@ export class ChangeFeed {
|
|
|
334
327
|
if (this.stopped)
|
|
335
328
|
return;
|
|
336
329
|
const was = this.mode;
|
|
337
|
-
this.mode =
|
|
338
|
-
this.cursor = '';
|
|
330
|
+
this.mode = 'poll';
|
|
339
331
|
if (was === 'ws')
|
|
340
|
-
this.o.log?.(`change stream: websocket lost;
|
|
332
|
+
this.o.log?.(`change stream: websocket lost; polling every ${Math.round(poll / 1000)} s`);
|
|
341
333
|
continue;
|
|
342
334
|
}
|
|
343
335
|
i++;
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
this.wsDue = true;
|
|
350
|
-
}
|
|
351
|
-
continue;
|
|
352
|
-
}
|
|
353
|
-
const t0 = Date.now();
|
|
354
|
-
try {
|
|
355
|
-
const q = new URLSearchParams({ wait: String(wait) });
|
|
356
|
-
if (this.cursor)
|
|
357
|
-
q.set('since', this.cursor);
|
|
358
|
-
const r = await this.o.request('GET', `/api/ach/changes?${q}`);
|
|
359
|
-
errors = 0;
|
|
360
|
-
const first = !this.cursor;
|
|
361
|
-
if (r?.cursor)
|
|
362
|
-
this.cursor = String(r.cursor);
|
|
363
|
-
if (r?.changed || first)
|
|
364
|
-
await this.fire();
|
|
365
|
-
// a hub that ignores `wait` must not be hammered
|
|
366
|
-
if (Date.now() - t0 < 1000)
|
|
367
|
-
await sleep(1000);
|
|
368
|
-
}
|
|
369
|
-
catch (e) {
|
|
370
|
-
if (e instanceof HubError && (e.status === 403 || e.status === 404 || e.status === 405)) {
|
|
371
|
-
this.mode = 'poll';
|
|
372
|
-
longpollRefused = true;
|
|
373
|
-
this.o.log?.(`change stream not available (${e.status}); polling every ${Math.round(poll / 1000)} s`);
|
|
374
|
-
continue;
|
|
375
|
-
}
|
|
376
|
-
if (e instanceof HubError && e.status === 401) {
|
|
377
|
-
this.o.log?.('change stream: key refused (401); stopping');
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
errors++;
|
|
381
|
-
if (errors === 1)
|
|
382
|
-
this.o.log?.(`change stream: ${String(e?.message ?? e).slice(0, 200)}; retrying`);
|
|
383
|
-
await this.fire();
|
|
384
|
-
await sleep(poll);
|
|
336
|
+
await this.fire();
|
|
337
|
+
await sleep(poll);
|
|
338
|
+
if (this.o.socket && ++polls >= retryPolls) {
|
|
339
|
+
polls = 0;
|
|
340
|
+
this.wsDue = true;
|
|
385
341
|
}
|
|
386
342
|
}
|
|
387
343
|
}
|
package/dist/src/cli.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ export interface Io {
|
|
|
8
8
|
out: (s: string) => void;
|
|
9
9
|
err: (s: string) => void;
|
|
10
10
|
fetch?: FetchLike;
|
|
11
|
-
readPassword?: (prompt: string) => Promise<string>;
|
|
12
11
|
/** `ach open`: opens a URL in the browser (tests inject a fake). */
|
|
13
12
|
openUrl?: (url: string) => Promise<void>;
|
|
14
13
|
/** `ach doctor` status commands (tests inject a fake). */
|
package/dist/src/cli.js
CHANGED
|
@@ -98,19 +98,22 @@ export async function runOpener(cmd, args, spawn) {
|
|
|
98
98
|
async function exchangeLink(link, hubOpt, io, cmd) {
|
|
99
99
|
const tok = loginTokenOf(link);
|
|
100
100
|
const fromUrl = /^(https?:\/\/[^/#?\s]+)/.exec(link.trim())?.[1];
|
|
101
|
-
let
|
|
101
|
+
let cfg;
|
|
102
102
|
try {
|
|
103
|
-
|
|
103
|
+
cfg = loadConfig(io.env);
|
|
104
104
|
}
|
|
105
105
|
catch {
|
|
106
|
-
|
|
106
|
+
cfg = undefined;
|
|
107
107
|
}
|
|
108
|
+
const saved = cfg?.hub;
|
|
108
109
|
const hub = (hubOpt ?? fromUrl ?? saved ?? '').replace(/\/+$/, '');
|
|
109
110
|
if (!hub)
|
|
110
111
|
throw new UsageError(`${cmd}: --hub <url> is required when --link is a bare token`);
|
|
111
112
|
if (!hubTransportOk(hub))
|
|
112
113
|
throw new UsageError(`${cmd}: ${hub} is plain http:// to a host that is not this machine; use the https:// link`);
|
|
113
|
-
|
|
114
|
+
// the front-door pass this machine keeps for that hub (a hub behind Cloudflare Access refuses the exchange without it)
|
|
115
|
+
const samehub = !!saved && saved.replace(/\/+$/, '') === hub;
|
|
116
|
+
const c = new Client({ hub, cfId: io.env.ACH_CF_ID || (samehub ? cfg?.cfId : undefined), cfSecret: io.env.ACH_CF_SECRET || (samehub ? cfg?.cfSecret : undefined), fetch: io.fetch });
|
|
114
117
|
const r = await c.exchangeLoginLink(tok);
|
|
115
118
|
if (!r?.token)
|
|
116
119
|
throw new Error('login failed: no token returned');
|
|
@@ -123,51 +126,6 @@ export function loginTokenOf(s) {
|
|
|
123
126
|
throw new UsageError('not a login link (expected .../#/login/ach_lt_...)');
|
|
124
127
|
return m[1];
|
|
125
128
|
}
|
|
126
|
-
function readPasswordTty(prompt) {
|
|
127
|
-
return new Promise((res, rej) => {
|
|
128
|
-
const stdin = process.stdin;
|
|
129
|
-
if (!stdin.isTTY) {
|
|
130
|
-
// non-interactive: the password is the first line of stdin (`echo "$PW" | ach admin login ...`)
|
|
131
|
-
let buf = '';
|
|
132
|
-
stdin.setEncoding('utf8');
|
|
133
|
-
stdin.on('data', (d) => (buf += d));
|
|
134
|
-
stdin.once('end', () => {
|
|
135
|
-
const line = buf.split(/\r?\n/)[0] ?? '';
|
|
136
|
-
if (line)
|
|
137
|
-
res(line);
|
|
138
|
-
else
|
|
139
|
-
rej(new Error('no password on stdin (pipe it: echo "$PASSWORD" | ach admin login --hub <url> --email <e>, or set ACH_ADMIN_PASSWORD)'));
|
|
140
|
-
});
|
|
141
|
-
stdin.once('error', rej);
|
|
142
|
-
stdin.resume();
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
process.stderr.write(prompt);
|
|
146
|
-
stdin.setRawMode(true);
|
|
147
|
-
stdin.resume();
|
|
148
|
-
let buf = '';
|
|
149
|
-
const onData = (d) => {
|
|
150
|
-
for (const ch of d.toString('utf8')) {
|
|
151
|
-
if (ch === '\r' || ch === '\n') {
|
|
152
|
-
stdin.setRawMode(false);
|
|
153
|
-
stdin.pause();
|
|
154
|
-
stdin.off('data', onData);
|
|
155
|
-
process.stderr.write('\n');
|
|
156
|
-
return res(buf);
|
|
157
|
-
}
|
|
158
|
-
if (ch === '\u0003') {
|
|
159
|
-
stdin.setRawMode(false);
|
|
160
|
-
return rej(new Error('interrupted'));
|
|
161
|
-
}
|
|
162
|
-
if (ch === '\u007f')
|
|
163
|
-
buf = buf.slice(0, -1);
|
|
164
|
-
else
|
|
165
|
-
buf += ch;
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
stdin.on('data', onData);
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
129
|
/**
|
|
172
130
|
* Commands a spawned agent (ACH_RUN_TOKEN set) may never run (S3): they would
|
|
173
131
|
* re-point the CLI (login), act as a human (admin), start nested runners or
|
|
@@ -1124,17 +1082,7 @@ async function dispatch(p, io) {
|
|
|
1124
1082
|
out(`logged in as ${r.record?.name || r.record?.email || r.record?.id}${r.record?.is_admin ? ' (admin)' : ''}`);
|
|
1125
1083
|
return 0;
|
|
1126
1084
|
}
|
|
1127
|
-
|
|
1128
|
-
const email = need(p, 'email');
|
|
1129
|
-
const password = env.ACH_ADMIN_PASSWORD || (await (io.readPassword ?? readPasswordTty)('Password: '));
|
|
1130
|
-
const c = new Client({ hub, cfId: env.ACH_CF_ID, cfSecret: env.ACH_CF_SECRET, fetch: io.fetch });
|
|
1131
|
-
const r = await c.userLogin(email, password);
|
|
1132
|
-
if (!r?.token)
|
|
1133
|
-
throw new Error('login failed: no token returned');
|
|
1134
|
-
writeFileConfig({ ...readFileConfig(env), hub: readFileConfig(env).hub ?? hub }, env);
|
|
1135
|
-
saveAdminToken(r.token, env, email);
|
|
1136
|
-
out(`logged in as ${email}${r.record?.is_admin ? ' (admin)' : ''}`);
|
|
1137
|
-
return 0;
|
|
1085
|
+
throw new UsageError('admin login: --link <login link> is required (the panel\'s menu makes one for you; an admin makes one with `ach admin login-link <user>`)');
|
|
1138
1086
|
}
|
|
1139
1087
|
case 'admin create-user': {
|
|
1140
1088
|
const a = admin();
|
|
@@ -1290,13 +1238,8 @@ async function dispatch(p, io) {
|
|
|
1290
1238
|
patch.notify_webhook = v['notify-webhook'];
|
|
1291
1239
|
if (str(v.name))
|
|
1292
1240
|
patch.name = str(v.name);
|
|
1293
|
-
if (v.password) {
|
|
1294
|
-
const rp = io.readPassword ?? readPasswordTty;
|
|
1295
|
-
patch.old_password = env.ACH_ADMIN_PASSWORD || (await rp('Current password: '));
|
|
1296
|
-
patch.password = env.ACH_NEW_PASSWORD || (await rp('New password: '));
|
|
1297
|
-
}
|
|
1298
1241
|
if (!Object.keys(patch).length)
|
|
1299
|
-
throw new UsageError('admin profile: nothing to change (--notify-webhook, --name
|
|
1242
|
+
throw new UsageError('admin profile: nothing to change (--notify-webhook, --name)');
|
|
1300
1243
|
const r = await admin().patchMe(patch);
|
|
1301
1244
|
out(v.json ? r : `updated ${r.email}${r.notify_webhook_set ? ' (notifications: own webhook)' : ''}`);
|
|
1302
1245
|
return 0;
|
package/dist/src/client.d.ts
CHANGED
|
@@ -283,7 +283,7 @@ export interface LoginLink {
|
|
|
283
283
|
export type FetchLike = (url: string, init: RequestInit) => Promise<Response>;
|
|
284
284
|
export interface ClientOptions {
|
|
285
285
|
hub: string;
|
|
286
|
-
/** Agent key (ach_sk_...), run token (ach_rt_...) or a
|
|
286
|
+
/** Agent key (ach_sk_...), run token (ach_rt_...) or a person's session token (from a login link). */
|
|
287
287
|
token?: string;
|
|
288
288
|
cfId?: string;
|
|
289
289
|
cfSecret?: string;
|
|
@@ -504,7 +504,7 @@ export declare class Client {
|
|
|
504
504
|
adminPatchUser(ref: string, patch: Record<string, unknown>): Promise<any>;
|
|
505
505
|
/** §15 `ach open`: the agent key mints a 60 s single-use login link for its owner. */
|
|
506
506
|
loginLink(): Promise<LoginLink>;
|
|
507
|
-
/** Exchange a one-time login link token for a
|
|
507
|
+
/** Exchange a one-time login link token for a person's session. */
|
|
508
508
|
exchangeLoginLink(token: string): Promise<{
|
|
509
509
|
token: string;
|
|
510
510
|
record: any;
|
|
@@ -517,11 +517,6 @@ export declare class Client {
|
|
|
517
517
|
cf_token?: boolean;
|
|
518
518
|
}): Promise<any>;
|
|
519
519
|
adminPatchAgent(agentId: string, patch: Record<string, unknown>): Promise<any>;
|
|
520
|
-
/** PocketBase built-in password auth for humans. */
|
|
521
|
-
userLogin(email: string, password: string): Promise<{
|
|
522
|
-
token: string;
|
|
523
|
-
record: any;
|
|
524
|
-
}>;
|
|
525
520
|
}
|
|
526
521
|
/** Inbox message entries are `{message, task}`; flatten to the message (task id stays in `message.task`). */
|
|
527
522
|
export declare function flatMsgs(v: unknown): Message[];
|
package/dist/src/client.js
CHANGED
|
@@ -96,7 +96,7 @@ export class Client {
|
|
|
96
96
|
headers(json = true) {
|
|
97
97
|
const h = { ...CLIENT_HEADERS, ...(json ? { 'content-type': 'application/json', accept: 'application/json' } : { accept: 'application/json' }) };
|
|
98
98
|
if (this.token) {
|
|
99
|
-
// Agent keys and run tokens use Bearer;
|
|
99
|
+
// Agent keys and run tokens use Bearer; a person's session token is sent as it is.
|
|
100
100
|
h.authorization = /^ach_(sk|rt)_/.test(this.token) ? `Bearer ${this.token}` : this.token;
|
|
101
101
|
}
|
|
102
102
|
if (this.cfId && this.cfSecret) {
|
|
@@ -428,7 +428,7 @@ export class Client {
|
|
|
428
428
|
async loginLink() {
|
|
429
429
|
return this.ach('POST', '/login-link', {});
|
|
430
430
|
}
|
|
431
|
-
/** Exchange a one-time login link token for a
|
|
431
|
+
/** Exchange a one-time login link token for a person's session. */
|
|
432
432
|
async exchangeLoginLink(token) {
|
|
433
433
|
return this.ach('POST', '/auth/link', { token });
|
|
434
434
|
}
|
|
@@ -446,10 +446,6 @@ export class Client {
|
|
|
446
446
|
async adminPatchAgent(agentId, patch) {
|
|
447
447
|
return this.ach('PATCH', `/admin/agents/${enc(agentId)}`, patch);
|
|
448
448
|
}
|
|
449
|
-
/** PocketBase built-in password auth for humans. */
|
|
450
|
-
async userLogin(email, password) {
|
|
451
|
-
return this.request('POST', '/api/collections/users/auth-with-password', { identity: email, password });
|
|
452
|
-
}
|
|
453
449
|
}
|
|
454
450
|
/** Inbox message entries are `{message, task}`; flatten to the message (task id stays in `message.task`). */
|
|
455
451
|
export function flatMsgs(v) {
|
package/dist/src/desknotify.js
CHANGED
|
@@ -416,7 +416,7 @@ export class DeskNotifier {
|
|
|
416
416
|
void import('./attention.js').then(({ ChangeFeed }) => {
|
|
417
417
|
if (this.stopped)
|
|
418
418
|
return;
|
|
419
|
-
const feed = new ChangeFeed({
|
|
419
|
+
const feed = new ChangeFeed({ socket: this.o.socket, onChange: () => this.tick(), pollMs: this.o.intervalMs, log: this.o.log });
|
|
420
420
|
this.feed = feed;
|
|
421
421
|
void feed.run();
|
|
422
422
|
});
|
package/dist/src/keystore.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export declare function openKeychain(home: string, account?: string): KeychainKe
|
|
|
39
39
|
/** Keychain unless ACH_KEYSTORE=file or the keychain is unavailable. */
|
|
40
40
|
export declare function openKeyStore(home: string, env?: NodeJS.ProcessEnv): KeyStore;
|
|
41
41
|
/**
|
|
42
|
-
* B1: the human session of `ach admin` (a
|
|
42
|
+
* B1: the human session of `ach admin` (a person's session token). Kept out of
|
|
43
43
|
* config.json: the OS keychain (account "admin-session:<home>"), else
|
|
44
44
|
* <home>/admin-session (0600), a file the runner denies to spawned agents.
|
|
45
45
|
*/
|
package/dist/src/keystore.js
CHANGED
|
@@ -75,7 +75,7 @@ export function openKeyStore(home, env = process.env) {
|
|
|
75
75
|
return new FileKeyStore(keyFilePath(home));
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
|
-
* B1: the human session of `ach admin` (a
|
|
78
|
+
* B1: the human session of `ach admin` (a person's session token). Kept out of
|
|
79
79
|
* config.json: the OS keychain (account "admin-session:<home>"), else
|
|
80
80
|
* <home>/admin-session (0600), a file the runner denies to spawned agents.
|
|
81
81
|
*/
|
package/dist/src/mcp.js
CHANGED
|
@@ -470,7 +470,7 @@ export function startSessionNotices(server, client, o = {}) {
|
|
|
470
470
|
gapMs: o.gapMs,
|
|
471
471
|
log: o.log,
|
|
472
472
|
});
|
|
473
|
-
const feed = new ChangeFeed({
|
|
473
|
+
const feed = new ChangeFeed({ socket: () => client.eventsSocket(), onChange: () => notifier.check(), log: o.log, ...o.feed });
|
|
474
474
|
const done = feed.run();
|
|
475
475
|
// a session cannot be restarted from outside: when the hub names a newer ach, say so once (see selfupdate.ts)
|
|
476
476
|
const stale = startStaleNotice({
|
package/dist/src/version.d.ts
CHANGED
package/dist/src/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koalaauto/agentchannel",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.2",
|
|
4
4
|
"description": "Hand work between your team's agents (Claude Code, Codex) and follow it in one panel: the ach CLI, MCP server and runner for AgentChannel v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentchannel",
|