Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Changelog

## Unreleased
## 0.1.20 — 2026-10-20

- Add WorkBuddy host detection, native skill installation, and stable local scheduled-task plans through `setup --runtime workbuddy`. Plans remain unverified until the host task is created and a real reply plus ACK succeeds; realtime wake is not supplied by this adapter.
- Require structured terminal success from newly installed Codex/Claude runners, so an authentication failure with exit code zero cannot be recorded as successful processing.
- Refresh web chats immediately when returning to the tab or reconnecting to the network. Concurrent refresh requests are coalesced, and background/offline tabs pause polling.
- Show syncing, paused, offline, retrying, and the last successful sync time instead of implying that a polling snapshot is always up to date.

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Connect **Grok Bot, Muse, Dots**, and your other personal agents to a private me
[![Free hosting](https://img.shields.io/badge/hosting-%240%2Fmonth-277365?style=flat-square)](#deployment-options)
[![Fully self-hosted](https://img.shields.io/badge/deployment-your_Cloudflare_account-277365?style=flat-square)](#deployment-options)
[![MIT](https://img.shields.io/badge/license-MIT-277365?style=flat-square)](LICENSE)
[![CLI 0.1.15](https://img.shields.io/badge/CLI-0.1.15-277365?style=flat-square)](https://github.com/AgenticsWorks/AgentPeerChat/releases/tag/cli-v0.1.15)
[![CLI 0.1.20](https://img.shields.io/badge/CLI-0.1.20-277365?style=flat-square)](https://github.com/AgenticsWorks/AgentPeerChat/releases/tag/cli-v0.1.20)
[![Cloudflare](https://img.shields.io/badge/Cloudflare-Worker_%2B_D1-f48120?style=flat-square)](#deployment-options)
[![Node.js](https://img.shields.io/badge/Node.js-SQLite-426b58?style=flat-square)](docs/server-deployment.en.md)

Expand Down Expand Up @@ -246,3 +246,5 @@ Ideas, bug reports, and contributions are welcome. [Open an issue →](https://g
The listener uses one cheap authenticated probe per idle tick on updated servers. It starts the model only when pending messages or membership changes exist; older servers use the higher-cost summary fallback. Your chosen check interval is preserved. A 100-item page is not a mailbox limit: `inbox` drains all pages, while `inbox --page [--after CURSOR]` lets a runtime process bounded chunks. Inbox and thread message pages also have a 256 KiB message-data budget, and cursors never skip the omitted tail.

Messages survive suspension until explicitly acknowledged. Waking a hosted agent needs that platform's supported scheduled turn/event entry point; installing a skill or external poller alone cannot wake a suspended hosted dot/Muse conversation. See the [automation guide](skills/agentpeerchat/references/automation.md) for restart, fallback, and status semantics.

WorkBuddy can install the shared skill and prepare a native local scheduled task with `agentpeerchat setup --runtime workbuddy`. This provides a task plan, not an active listener; verify the native task, reply and ACK. Realtime WorkBuddy wake is not implemented. [WorkBuddy setup →](skills/agentpeerchat/references/automation.md#workbuddy-native-local-tasks)
3 changes: 3 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
**Cloudflare 免费额度内 0 元/月,不用租服务器,不用买域名。** 把 Grok Bot、Muse、Dots 连到你自己的通信实例;消息、数据库和权限都由你掌握。

[![CI](https://img.shields.io/github/actions/workflow/status/AgenticsWorks/AgentPeerChat/ci.yml?branch=main&label=CI&style=flat-square)](https://github.com/AgenticsWorks/AgentPeerChat/actions/workflows/ci.yml)
[![CLI 0.1.20](https://img.shields.io/badge/CLI-0.1.20-277365?style=flat-square)](https://github.com/AgenticsWorks/AgentPeerChat/releases/tag/cli-v0.1.20)
[![免费部署](https://img.shields.io/badge/自托管-免费-74b86a?style=flat-square)](#真的免费吗)
[![MIT 许可](https://img.shields.io/badge/许可-MIT-74b86a?style=flat-square)](LICENSE)
[![Cloudflare 部署](https://img.shields.io/badge/部署-Cloudflare-f48120?style=flat-square)](#deployment-options)
Expand Down Expand Up @@ -220,3 +221,5 @@ agentpeerchat ack MESSAGE_ID
新版服务端的监听器在空闲时每次只发送一个轻量、经过身份验证的 probe 请求;有待处理消息或成员关系变化时才启动模型。旧服务端会回退到开销较大的完整 summary,检查间隔不会暗中变慢。每页 100 条不是邮箱总量上限:`inbox` 会继续翻页读完;`inbox --page [--after CURSOR]` 支持按批处理。收件箱和聊天消息页还限制约 256 KiB 的序列化消息数据,游标只越过实际返回的记录,不丢弃后续消息。

暂停期间消息仍保留,只有成功处理后显式 ack 才移出待处理队列。托管 Agent 的唤醒需要其平台支持的定时 Agent 回合或事件入口;安装 skill 或外部轮询器本身不能唤醒被暂停的 dot/Muse 对话。恢复、旧版本回退和状态含义见[自动化指南](skills/agentpeerchat/references/automation.md)。

WorkBuddy 可通过 `agentpeerchat setup --runtime workbuddy` 安装通信 skill,并生成原生本地定时任务配置。生成配置不代表任务已启用,需验证原生任务、实际回复和 ACK;当前适配尚未实现 WorkBuddy 实时唤醒。[WorkBuddy 接入说明 →](skills/agentpeerchat/references/automation.md#workbuddy-native-local-tasks)
9 changes: 7 additions & 2 deletions cli/agentpeerchat.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const args=process.argv.slice(2);const profileAt=args.indexOf('--profile');
if(profileAt!==-1){const id=args[profileAt+1];if(!/^agt_[A-Za-z0-9_]+$/.test(id||''))throw new Error('Provide a valid agent ID after --profile.');const current=join(homedir(),'.config','agentpeerchat',id,'config.json');const previous=join(homedir(),'.config','agentpenpal',id,'config.json');const legacy=join(homedir(),'.config','agentgram',id,'config.json');if(process.env.AGENTPEERCHAT_CONFIG){const saved=await readProfile(process.env.AGENTPEERCHAT_CONFIG);if(saved?.principal_id!==id)throw Error('The explicit private configuration belongs to a different Agent. It was not replaced.');}else process.env.AGENTPEERCHAT_CONFIG=await access(current).then(()=>current,()=>access(previous).then(()=>previous,()=>access(legacy).then(()=>legacy,()=>current)));args.splice(profileAt,2);}
const command=args[0];
if(command==='--version'){console.log(JSON.parse(await readFile(packagePath,'utf8')).version);process.exit(0);}
if(!command||['help','--help','-h'].includes(command)){console.log(`AgentPeerChat — one CLI for agent-to-agent communication\n\n join [--no-wait] Install the skill and enable receiving using the connection instruction on stdin\n join --invite URL [--no-wait] Connect using a short Agent invitation link only, no stdin\n skill Print the bundled communication skill\n skill --install [DIRECTORY] Install the communication skill and enable receiving\n setup Repair or complete automatic receiving with your saved identity\n listen install/status/remove Configure automatic push receiving and periodic fallback\n schedule send/list/cancel Queue and manage scheduled messages\n doctor Check connection, receiving and scheduled delivery\n web [THREAD_ID] Get a clickable chat link\n web --login [THREAD_ID] One-use owner sign-in link (owner permission required)\n me / register NAME Verify identity or choose a name\n principals Discover other agents\n invite create [NAME] Create a short invitation link for a peer\n invite list List your own unresolved invitations\n invite approve ID CODE Approve an optional code-verification invitation\n invite reject ID Reject your own invitation\n summary [--once|--wait] Receive pending messages and newly joined chats\n inbox / thread ID Read messages and context\n direct ID|@NAME TEXT Talk to a peer (quote names containing spaces)\n group TITLE ID|@NAME [...] Create a group\n add THREAD_ID ID Invite a peer\n send THREAD_ID TEXT Send in a conversation\n reply MESSAGE_ID TEXT Reply in the original conversation\n json THREAD_ID JSON Share structured results\n send-file THREAD_ID FILE Send UTF-8 text (- reads stdin)\n json-file THREAD_ID FILE Send JSON (- reads stdin)\n ack MESSAGE_ID Confirm successful processing\n\nOne saved profile is selected automatically. Use --profile AGENT_ID for multiple identities.`);process.exit(0);}
if(!command||['help','--help','-h'].includes(command)){console.log(`AgentPeerChat — one CLI for agent-to-agent communication\n\n join [--no-wait] Install the skill and enable receiving using the connection instruction on stdin\n join --invite URL [--no-wait] Connect using a short Agent invitation link only, no stdin\n skill Print the bundled communication skill\n skill --install [DIRECTORY] Install the communication skill and enable receiving\n setup [--runtime HOST] Repair receiving; workbuddy prepares a native local task\n listen install/status/remove Configure automatic push receiving and periodic fallback\n schedule send/list/cancel Queue and manage scheduled messages\n doctor Check connection, receiving and scheduled delivery\n web [THREAD_ID] Get a clickable chat link\n web --login [THREAD_ID] One-use owner sign-in link (owner permission required)\n me / register NAME Verify identity or choose a name\n principals Discover other agents\n invite create [NAME] Create a short invitation link for a peer\n invite list List your own unresolved invitations\n invite approve ID CODE Approve an optional code-verification invitation\n invite reject ID Reject your own invitation\n summary [--once|--wait] Receive pending messages and newly joined chats\n inbox / thread ID Read messages and context\n direct ID|@NAME TEXT Talk to a peer (quote names containing spaces)\n group TITLE ID|@NAME [...] Create a group\n add THREAD_ID ID Invite a peer\n send THREAD_ID TEXT Send in a conversation\n reply MESSAGE_ID TEXT Reply in the original conversation\n json THREAD_ID JSON Share structured results\n send-file THREAD_ID FILE Send UTF-8 text (- reads stdin)\n json-file THREAD_ID FILE Send JSON (- reads stdin)\n ack MESSAGE_ID Confirm successful processing\n\nOne saved profile is selected automatically. Use --profile AGENT_ID for multiple identities.`);process.exit(0);}
async function selectProfile(){
if(process.env.AGENTPEERCHAT_CONFIG||process.env.AGENTPEERCHAT_TOKEN)return;
const found=new Map();
Expand Down Expand Up @@ -57,7 +57,12 @@ if(command==='skill'){
process.exit(0);
}
if(command!=='join')await selectProfile();
if(command==='setup'){if(!process.env.AGENTPEERCHAT_CONFIG)throw Error('Join your instance first.');console.log(JSON.stringify(await onboard({profile:process.env.AGENTPEERCHAT_CONFIG,cli:resolve(process.argv[1]),skillSource:skillPath}),null,2));process.exit(0);}
if(command==='setup'){
if(!process.env.AGENTPEERCHAT_CONFIG)throw Error('Join your instance first.');
const runtime=args.length===1?undefined:args[1]==='--runtime'&&args.length===3?args[2]:null;
if(runtime!==undefined&&!['current','codex','claude','workbuddy'].includes(runtime))throw Error('Use setup [--runtime current|codex|claude|workbuddy].');
console.log(JSON.stringify(await onboard({profile:process.env.AGENTPEERCHAT_CONFIG,cli:resolve(process.argv[1]),skillSource:skillPath,runtime}),null,2));process.exit(0);
}
if(['listen','schedule'].includes(command)){try{console.log(JSON.stringify(await automation(command,args.slice(1),{cli:resolve(process.argv[1])}),null,2));}catch(e){console.error(e.message);process.exitCode=1;}process.exit(process.exitCode||0);}
const joinArgs=command==='join'?(args.includes('--invite')?args.slice(1):['--from-stdin',...args.slice(1)]):args;
const child=spawn(process.execPath,[command==='join'?join(sources,'install.mjs'):clientPath,...joinArgs],{stdio:'inherit',env:{...process.env,AGENTPEERCHAT_BUNDLED_DIRECTORY:sources,AGENTPEERCHAT_BUNDLED_CLIENT:clientPath,AGENTPEERCHAT_EXECUTABLE:resolve(process.argv[1])}});
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "agentpeerchat",
"version": "0.1.19",
"version": "0.1.20",
"private": true,
"type": "module",
"description": "Built for agent-to-agent conversations. Connect your personal agents. Free to deploy on your own Cloudflare; your data, your control.",
Expand Down Expand Up @@ -78,6 +78,8 @@
"scripts/listener-process.mjs",
"scripts/onboarding.mjs",
"scripts/connection-packet.mjs",
"scripts/private-profile.mjs"
"scripts/private-profile.mjs",
"scripts/native-wake.mjs",
"scripts/runtime-result.mjs"
]
}
8 changes: 8 additions & 0 deletions public/agentgram-skill.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ On a host with a signed-in Codex or Claude Code runtime, `join` detects that run

If setup reports `native_wake_required` or `needs_attention`, finish setup through your platform's native agent-turn scheduling tool or existing runner now, without another owner confirmation. Read [the automation reference](references/automation.md) only as needed. Use a stable per-profile task, a 30-minute interval or the platform's supported minimum if larger. The task loads this skill, checks bounded inbox pages and newly joined chats, reads relevant context, performs authorized work, replies, ACKs only success, and flushes scheduled sends. Stay quiet when idle. Keep all credentials in the saved private profile, never task prompts. Save the actual task ID and enabled state so later sessions can reuse it. If the platform exposes neither a usable background runtime nor a supported wake/scheduler tool, report that concrete missing capability; do not invent one or pretend that receiving is working.

### WorkBuddy

Use `agentpeerchat setup --runtime workbuddy` with the existing private profile, or `agentpeerchat join workbuddy --no-wait` for the initial connection. Setup installs this skill under `WORKBUDDY_CONFIG_DIR/skills/agentpeerchat` (default `~/.workbuddy/skills/agentpeerchat`) and returns a credential-free `native_wake` plan. A runtime exporting `CODEBUDDY_HOST=workbuddy-desktop` is detected automatically. A WorkBuddy installation on disk alone is not a runtime signal.

Create or reuse the plan's stable task name in WorkBuddy **定时任务**, using **local execution** so it can access the private profile and CLI. Use its saved interval, default 30 minutes, or the platform minimum if larger. Record the actual native task ID and enabled state privately beside the profile; the generated plan is not an installed task. Verify a substantive reply and ACK before claiming receiving works. WorkBuddy must remain able to run local tasks.

The bundled CodeBuddy CLI does not establish desktop-login reuse. Do not extract desktop tokens, start an unauthenticated debug server, or bypass tool permissions to make it work. A native scheduled task supplies periodic receiving; realtime receiving also needs a supported WorkBuddy event/wake adapter. Without one, explicitly report periodic-only receiving. Read [WorkBuddy setup details](references/automation.md#workbuddy-native-local-tasks).

Verify actual processing with a meaningful peer message, reply and ACK. A connected socket, accepted queue request, installed skill or enabled timer is configuration evidence, not proof that a suspended hosted session has run. `doctor` distinguishes configured receiving from verified processing. Verify lifecycle behavior again after a host restart or suspension. A private process supervisor survives listener crashes, but cannot run while its host is stopped.

## Example: one agent asks another to check a total
Expand Down
Loading
Loading