npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@agentdock/daemon

v0.0.10

Published

PC daemon + CLI for AgentDock — ACP abstraction, TransportHandler, process management

Downloads

1,302

Readme

@agentdock/daemon

PC 守护进程 + CLI — 在用户电脑上运行,管理 AI Agent 子进程并将事件上报到 server。

概述

daemon 是 AgentDock 的本地端,安装在开发者的 PC 上(npx agentdock),职责:

  • 进程管理:启动/停止 AI Agent 子进程(Claude Code 等)
  • ACP 抽象:统一接口适配不同 CLI(ACP / exec / SDK 路线)
  • 事件转换:将 Agent 原始输出(JSONL)映射为 wire 协议的 SessionEnvelope
  • 上报:通过 Socket.IO 将事件推送到 server
  • 控制服务器:本地 HTTP 端点,供其他进程查询/停止 daemon

在架构中的位置

wire → crypto → daemon

依赖 wire(协议定义)和 crypto(签名认证),独立运行在用户 PC 上。

模块结构

src/
├── cli.ts                # CLI 入口(agentdock start/stop/status)
├── cli-args.ts           # 命令行参数解析
├── acp.ts                # AgentBackend — 子进程管理(spawn/readline/stdin/signal)
├── transport.ts          # TransportHandler — 按 agent 类型配置超时/过滤器
├── claude-transport.ts   # Claude JSONL 解析器(content block → AgentMessage[])
├── copilot-transport.ts  # Copilot CLI / OpenCode ACP ndJSON 解析器(M9-1)
├── agentSpawn.ts         # AgentType → BackendOptions 分派器(M9-2,6 种 agent)
├── sessionMapper.ts      # SessionMapper — AgentMessage → SessionEnvelope 转换 + turn 边界
├── sessionBridge.ts      # AgentBackend → SessionMapper → ServerClient 桥接(M5-2)
├── serverClient.ts       # SDK 封装(machine-scoped 连接 + sendEnvelope + createSession)
├── interactionDetector.ts # 交互检测器(question / permission-request 提取)
├── rpcHandler.ts         # RPC 方法处理(approve/deny/answer/abort/stop)
├── secretManager.ts      # 密钥文件读写(master secret 持久化)
├── keyManager.ts         # DEK 生命周期管理(生成/封装/解封)
├── pairingClient.ts      # 配对客户端(Curve25519 keypair + NaCl Box + 轮询)
├── lock.ts               # PID 文件锁(O_EXCL 排他创建 + EPERM/ESRCH 区分)
├── state.ts              # 状态文件读写(pid/port/startTime/version/heartbeat)
├── paths.ts              # 标准路径(~/.agentdock/daemon.pid, daemon.state.json, daemon.log)
├── controlServer.ts      # 本地 HTTP 控制服务器(/health /sessions /stop)
├── daemonLoop.ts         # 主循环(心跳 + server 连接 + graceful shutdown)
└── index.ts              # Barrel exports

API 参考

CLI 命令

npx agentdock [--agent claude] [--port 9876]  # 启动 daemon
npx agentdock stop                             # 停止 daemon
npx agentdock status                           # 查看状态

AgentBackend (acp.ts)

import { createAgentBackend } from '@agentdock/daemon';
import type { AgentBackend, BackendOptions, AgentMessage } from '@agentdock/daemon';

const backend: AgentBackend = createAgentBackend({
  command: 'claude',
  args: ['--output-format', 'stream-json'],
  cwd: '/path/to/project',
  spawnFn: childProcess.spawn,
});

// 启动子进程
await backend.start();

// 监听消息
backend.onMessage((msg: AgentMessage) => {
  // { type: 'text' | 'tool-call' | 'service' | ..., content: ... }
});

// 发送输入
backend.sendMessage('user input');

// 取消当前操作
backend.cancel(); // SIGINT

// 清理
backend.dispose(); // SIGTERM + cleanup

Claude JSONL 解析器 (claude-transport.ts)

import { parseClaudeLine } from '@agentdock/daemon';

// 解析 Claude Code 的 JSONL 输出
// 处理多 content block(thinking + text + tool_use)
const messages: AgentMessage[] = parseClaudeLine(jsonLine);
// 返回数组而非单个(L13 教训:不丢弃后续 block)

SessionMapper (sessionMapper.ts)

import { createSessionMapper } from '@agentdock/daemon';

const mapper = createSessionMapper({ userId: 'user-123' });

// AgentMessage → SessionEnvelope
const envelopes = mapper.map(agentMessage);
// 自动管理 turn 边界(turn-start/turn-end)

文件锁 (lock.ts)

import { acquireLock, releaseLock, isLocked } from '@agentdock/daemon';

const result = acquireLock(); // O_EXCL 排他创建
// result: { acquired: true } | { acquired: false, pid: 12345 }

releaseLock(); // 先验证 PID 所有权再删除(L12 教训)

控制服务器 (controlServer.ts)

import { startControlServer } from '@agentdock/daemon';

const server = await startControlServer({ port: 9876 });
// GET /health → { status: 'ok', pid, uptime }
// GET /sessions → 活跃会话列表
// POST /stop → graceful shutdown

Daemon 主循环 (daemonLoop.ts)

import { createDaemonLoop } from '@agentdock/daemon';

const loop = createDaemonLoop({
  heartbeatInterval: 30000,
  onShutdown: async () => {
    /* cleanup */
  },
});

await loop.start();
// 心跳 + 信号处理(SIGINT/SIGTERM) + graceful shutdown

开发

# 运行测试(131 tests)
pnpm --filter @agentdock/daemon test

# 覆盖率(目标 80%+,实际 97.3%)
pnpm --filter @agentdock/daemon test:coverage

# 本地启动 daemon
pnpm --filter @agentdock/daemon dev

设计决策

  • PID 文件锁用 O_EXCL:排他创建防止 TOCTOU 竞态(L12 教训)
  • parseClaudeLine 返回数组:处理多 content block,不丢弃数据(L13 教训)
  • ACP 抽象层:统一接口,后续添加 Codex/Gemini Transport 只需实现新 handler
  • EPERM vs ESRCH 区分:判断进程是否存活时,EPERM = 存活但无权限,ESRCH = 不存在
  • 控制服务器用原生 http:轻量级,不引入 Fastify 依赖(daemon 应尽量小)