@iniesta8888/agent-live 0.3.0

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.
Files changed (182) hide show
  1. package/CODE_OF_CONDUCT.md +7 -0
  2. package/CONTRIBUTING.md +56 -0
  3. package/LICENSE +21 -0
  4. package/README.md +92 -0
  5. package/SECURITY.md +13 -0
  6. package/dist/adapter-sdk/index.d.ts +45 -0
  7. package/dist/adapter-sdk/index.d.ts.map +1 -0
  8. package/dist/adapter-sdk/index.js +106 -0
  9. package/dist/adapter-sdk/index.js.map +1 -0
  10. package/dist/content/compiler.d.ts +31 -0
  11. package/dist/content/compiler.d.ts.map +1 -0
  12. package/dist/content/compiler.js +218 -0
  13. package/dist/content/compiler.js.map +1 -0
  14. package/dist/content/graph-validator.d.ts +56 -0
  15. package/dist/content/graph-validator.d.ts.map +1 -0
  16. package/dist/content/graph-validator.js +226 -0
  17. package/dist/content/graph-validator.js.map +1 -0
  18. package/dist/content/library.d.ts +4 -0
  19. package/dist/content/library.d.ts.map +1 -0
  20. package/dist/content/library.js +45 -0
  21. package/dist/content/library.js.map +1 -0
  22. package/dist/content/registry.d.ts +34 -0
  23. package/dist/content/registry.d.ts.map +1 -0
  24. package/dist/content/registry.js +130 -0
  25. package/dist/content/registry.js.map +1 -0
  26. package/dist/content/runtime-content.d.ts +63 -0
  27. package/dist/content/runtime-content.d.ts.map +1 -0
  28. package/dist/content/runtime-content.js +78 -0
  29. package/dist/content/runtime-content.js.map +1 -0
  30. package/dist/content/schema.d.ts +142 -0
  31. package/dist/content/schema.d.ts.map +1 -0
  32. package/dist/content/schema.js +280 -0
  33. package/dist/content/schema.js.map +1 -0
  34. package/dist/content/validator.d.ts +35 -0
  35. package/dist/content/validator.d.ts.map +1 -0
  36. package/dist/content/validator.js +205 -0
  37. package/dist/content/validator.js.map +1 -0
  38. package/dist/core/agents.d.ts +56 -0
  39. package/dist/core/agents.d.ts.map +1 -0
  40. package/dist/core/agents.js +148 -0
  41. package/dist/core/agents.js.map +1 -0
  42. package/dist/core/limits.d.ts +15 -0
  43. package/dist/core/limits.d.ts.map +1 -0
  44. package/dist/core/limits.js +16 -0
  45. package/dist/core/limits.js.map +1 -0
  46. package/dist/core/mapping.d.ts +17 -0
  47. package/dist/core/mapping.d.ts.map +1 -0
  48. package/dist/core/mapping.js +94 -0
  49. package/dist/core/mapping.js.map +1 -0
  50. package/dist/core/protocol.d.ts +105 -0
  51. package/dist/core/protocol.d.ts.map +1 -0
  52. package/dist/core/protocol.js +6 -0
  53. package/dist/core/protocol.js.map +1 -0
  54. package/dist/core/state.d.ts +49 -0
  55. package/dist/core/state.d.ts.map +1 -0
  56. package/dist/core/state.js +216 -0
  57. package/dist/core/state.js.map +1 -0
  58. package/dist/creator/commands.d.ts +19 -0
  59. package/dist/creator/commands.d.ts.map +1 -0
  60. package/dist/creator/commands.js +44 -0
  61. package/dist/creator/commands.js.map +1 -0
  62. package/dist/creator/mode.d.ts +10 -0
  63. package/dist/creator/mode.d.ts.map +1 -0
  64. package/dist/creator/mode.js +23 -0
  65. package/dist/creator/mode.js.map +1 -0
  66. package/dist/creator/service.d.ts +199 -0
  67. package/dist/creator/service.d.ts.map +1 -0
  68. package/dist/creator/service.js +159 -0
  69. package/dist/creator/service.js.map +1 -0
  70. package/dist/index.d.ts +14 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +10 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/runtime/agent-live-runtime.d.ts +17 -0
  75. package/dist/runtime/agent-live-runtime.d.ts.map +1 -0
  76. package/dist/runtime/agent-live-runtime.js +50 -0
  77. package/dist/runtime/agent-live-runtime.js.map +1 -0
  78. package/dist/runtime/content-service.d.ts +75 -0
  79. package/dist/runtime/content-service.d.ts.map +1 -0
  80. package/dist/runtime/content-service.js +60 -0
  81. package/dist/runtime/content-service.js.map +1 -0
  82. package/dist/runtime/resource-guard.d.ts +17 -0
  83. package/dist/runtime/resource-guard.d.ts.map +1 -0
  84. package/dist/runtime/resource-guard.js +54 -0
  85. package/dist/runtime/resource-guard.js.map +1 -0
  86. package/dist/runtime/server.d.ts +39 -0
  87. package/dist/runtime/server.d.ts.map +1 -0
  88. package/dist/runtime/server.js +286 -0
  89. package/dist/runtime/server.js.map +1 -0
  90. package/dist/web/app.d.ts +1 -0
  91. package/dist/web/app.js +1317 -0
  92. package/dist/web/index.html +45 -0
  93. package/dist/web/office.js +350 -0
  94. package/dist/web/sprites.js +185 -0
  95. package/dist/web/style.css +288 -0
  96. package/dist/web/v2/bootstrap.js +276 -0
  97. package/dist/web/v2/content/README.md +17 -0
  98. package/dist/web/v2/content/agent-skins/studio-team.json +33 -0
  99. package/dist/web/v2/content/agent-skins/tiny-developers.json +33 -0
  100. package/dist/web/v2/content/atmospheres/default.json +13 -0
  101. package/dist/web/v2/content/atmospheres/rainy-night.json +37 -0
  102. package/dist/web/v2/content/catalog.json +14 -0
  103. package/dist/web/v2/content/component-library/activity-implementations.json +873 -0
  104. package/dist/web/v2/content/component-library/activity-recipes.json +25 -0
  105. package/dist/web/v2/content/component-library/agent-profile-templates.json +18 -0
  106. package/dist/web/v2/content/component-library/catalog.json +38 -0
  107. package/dist/web/v2/content/component-library/npc-templates.json +42 -0
  108. package/dist/web/v2/content/component-library/props.json +41 -0
  109. package/dist/web/v2/content/environments/local-office.json +31 -0
  110. package/dist/web/v2/content/environments/rainy-night.json +28 -0
  111. package/dist/web/v2/content/environments/static-office.json +27 -0
  112. package/dist/web/v2/content/layouts/boardroom-office.json +122 -0
  113. package/dist/web/v2/content/layouts/demo-office.json +88 -0
  114. package/dist/web/v2/content/layouts/lively-office.json +96 -0
  115. package/dist/web/v2/content/layouts/old-school-office.json +154 -0
  116. package/dist/web/v2/content/layouts/tech-open-office.json +132 -0
  117. package/dist/web/v2/content/life-activities/boardroom-routines.json +67 -0
  118. package/dist/web/v2/content/life-activities/none.json +10 -0
  119. package/dist/web/v2/content/life-activities/office-basics.json +39 -0
  120. package/dist/web/v2/content/life-activities/old-school-routines.json +74 -0
  121. package/dist/web/v2/content/life-activities/tech-office-routines.json +148 -0
  122. package/dist/web/v2/content/npcs/boardroom-staff.json +54 -0
  123. package/dist/web/v2/content/npcs/none.json +10 -0
  124. package/dist/web/v2/content/npcs/office-staff.json +25 -0
  125. package/dist/web/v2/content/npcs/old-school-staff.json +39 -0
  126. package/dist/web/v2/content/npcs/tech-office-staff.json +40 -0
  127. package/dist/web/v2/content/official-offices/boardroom-office.json +25 -0
  128. package/dist/web/v2/content/official-offices/old-school-office.json +25 -0
  129. package/dist/web/v2/content/official-offices/tech-open-office.json +25 -0
  130. package/dist/web/v2/content/presets/boardroom-office.json +21 -0
  131. package/dist/web/v2/content/presets/cozy-studio.json +19 -0
  132. package/dist/web/v2/content/presets/demo-office.json +19 -0
  133. package/dist/web/v2/content/presets/lively-office.json +19 -0
  134. package/dist/web/v2/content/presets/night-shift.json +19 -0
  135. package/dist/web/v2/content/presets/old-school-office.json +20 -0
  136. package/dist/web/v2/content/presets/refined-demo.json +20 -0
  137. package/dist/web/v2/content/presets/tech-open-office.json +21 -0
  138. package/dist/web/v2/content/props/default-office.json +23 -0
  139. package/dist/web/v2/content/props/extended-office.json +39 -0
  140. package/dist/web/v2/content/props/tech-office.json +28 -0
  141. package/dist/web/v2/content/styles/pixel-classic.json +160 -0
  142. package/dist/web/v2/content/styles/warm-studio.json +150 -0
  143. package/dist/web/v2/environment-runtime.d.ts +1 -0
  144. package/dist/web/v2/environment-runtime.js +138 -0
  145. package/dist/web/v2/graph-validator.d.ts +55 -0
  146. package/dist/web/v2/graph-validator.js +225 -0
  147. package/dist/web/v2/i18n.js +54 -0
  148. package/dist/web/v2/locales/en.json +209 -0
  149. package/dist/web/v2/locales/zh-CN.json +52 -0
  150. package/dist/web/v2/office-engine.d.ts +1 -0
  151. package/dist/web/v2/office-engine.js +145 -0
  152. package/dist/web/v2/office-renderer.d.ts +1 -0
  153. package/dist/web/v2/office-renderer.js +843 -0
  154. package/dist/web/v2/parity.html +10 -0
  155. package/dist/web/v2/parity.js +82 -0
  156. package/dist/web/v2/sprite-renderer.d.ts +1 -0
  157. package/dist/web/v2/sprite-renderer.js +242 -0
  158. package/dist/web/v2/static-content.js +48 -0
  159. package/dist/web/v2/style.css +140 -0
  160. package/dist/web/v2.html +68 -0
  161. package/docs/ADAPTER-DEVELOPMENT.md +328 -0
  162. package/docs/ADAPTER-SDK.md +109 -0
  163. package/docs/ARCHITECTURE.md +223 -0
  164. package/docs/COMPONENT-LIBRARY.md +212 -0
  165. package/docs/CUSTOMIZATION.md +163 -0
  166. package/docs/DEVELOPER.md +186 -0
  167. package/docs/DSH-ADAPTER-DESIGN.md +173 -0
  168. package/docs/OFFICE-THEMES.md +516 -0
  169. package/docs/PRESET-CONFIG.md +460 -0
  170. package/docs/RELEASE-CHECK.md +23 -0
  171. package/docs/TECHNICAL.md +515 -0
  172. package/docs/USING-CODEX.md +24 -0
  173. package/docs/USING-DSH.md +44 -0
  174. package/docs/USING-PI.md +50 -0
  175. package/docs/VISION.md +146 -0
  176. package/examples/adapter/local-office.mjs +52 -0
  177. package/package.json +89 -0
  178. package/skills/agent-live-adapter-builder/SKILL.md +30 -0
  179. package/skills/agent-live-adapter-builder/agents/openai.yaml +4 -0
  180. package/skills/agent-live-adapter-builder/references/investigation.md +9 -0
  181. package/skills/agent-live-adapter-builder/references/review.md +7 -0
  182. package/skills/agent-live-adapter-builder/scripts/create-adapter.mjs +26 -0
@@ -0,0 +1,515 @@
1
+ # Agent Live 技术文档
2
+
3
+ > 版本 0.3.0(开发中)· 最后校准 2026-09-13 · Node 22+
4
+
5
+ > 本文主要记录最初的 Pi / Local Runtime / Browser 实现细节。跨宿主职责与最新公共合同以 [ARCHITECTURE.md](ARCHITECTURE.md)、[ADAPTER-SDK.md](ADAPTER-SDK.md) 和各宿主 Adapter 设计为准。
6
+
7
+ ## 1. 架构总览
8
+
9
+ 当前公共架构、依赖方向和 Adapter Contract 以 [ARCHITECTURE.md](ARCHITECTURE.md) 为准。本文件继续记录协议、Pi 映射和渲染实现细节。
10
+
11
+ ```text
12
+ Pi / Codex → Adapter → Core → Runtime → Browser Renderer
13
+ ↕ optional host controls
14
+ ```
15
+
16
+ 关键点:
17
+
18
+ - Pi 的服务跑在 Pi 进程内;Codex 使用随页面生命周期运行的轻量客户端。两者都没有守护进程。
19
+ - 画面事件通过 SSE 单向传输;Codex 的 Prompt、模型、停止和授权通过本地 HTTP 控制接口回传。
20
+ - 前后端共享 `protocol.ts` 定义的事件词汇,但前端是纯 JS(无构建步骤),靠约定而非类型检查保持一致。
21
+ - 原版和 V2 共用 `app.js` 的事件状态机;V2 的地图、角色、导航和视觉 token 由内容配置与两个原生 renderer 提供,不加载原版 `office.js` / `sprites.js`。
22
+
23
+ ## 2. 运行环境与依赖
24
+
25
+ | 项 | 要求 | 说明 |
26
+ | --- | --- | --- |
27
+ | Node | ≥ 22 | 直接跑 `.ts` 靠原生 type stripping,不引入 tsx/jiti |
28
+ | npm 依赖 | **零** | 只用 `node:http` / `node:fs` / `node:path` / `node:url` / `node:child_process` |
29
+ | 前端依赖 | **零** | 原版用全局脚本;V2 用浏览器原生 ES modules;均无打包 |
30
+ | pi | 0.84.x | 依赖其扩展 API 与事件名 |
31
+
32
+ 零依赖是硬约束:扩展在 pi 的运行环境里加载,引入 npm 包会带来解析和版本问题。
33
+
34
+ 代价:不能使用不可擦除的 TypeScript 语法(如 parameter properties、enum),只能用类型注解形式。
35
+
36
+ ## 3. 目录结构
37
+
38
+ ```
39
+ agent-live/
40
+ ├── index.ts # Pi 兼容入口,re-export 官方 Pi Adapter
41
+ ├── package.json # type: module;pi.extensions 声明入口
42
+ ├── README.md
43
+ ├── docs/ # 产品、愿景、内容模型、平台能力与技术文档
44
+ ├── plugins/agent-live/scripts/
45
+ │ ├── preview.ts # 脱离 pi 单独起服务,用于调视觉
46
+ │ ├── validate-content.ts # 校验 V2 内容合同
47
+ │ └── validate-environment.ts # 校验时间、天气与 NPC 班次
48
+ ├── plugins/agent-live/src/
49
+ │ ├── core/ # 标准协议、状态与工具语义
50
+ │ ├── runtime/ # 共享本地服务和生命周期
51
+ │ └── adapters/ # Adapter Contract、Pi 与 Codex 实现
52
+ └── plugins/agent-live/web/
53
+ ├── index.html # 原版入口(冻结回归基线)
54
+ ├── style.css # 原版深色像素风 UI
55
+ ├── sprites.js # 原版程序化角色与粒子
56
+ ├── office.js # 原版地图、家具、导航数据
57
+ ├── app.js # 两入口共用的 SSE、演出编排与动画循环
58
+ ├── v2.html # 配置化入口
59
+ └── v2/
60
+ ├── bootstrap.js # 内容加载、校验、token 应用与启动
61
+ ├── environment-runtime.js # 时间、天气、照明与 NPC 班次
62
+ ├── office-renderer.js # Layout / Props / Style 原生 renderer
63
+ ├── sprite-renderer.js # Agent Skin / Style 原生 renderer
64
+ ├── parity.html/.js # 原版与 V2 的逐像素回归
65
+ └── content/ # 八类内容、三套正式 Preset 与内部回归内容
66
+ ```
67
+
68
+ ## 4. 生命周期
69
+
70
+ | 阶段 | 触发 | 行为 |
71
+ | --- | --- | --- |
72
+ | 启动 | `session_start` 或首次 `/agent-live` | `boot()` 建 `OfficeState`、主管上班、起 HTTP 服务、状态栏显示地址 |
73
+ | 运行 | 各类 pi 事件 | 翻译成 `OfficeEvent` 广播给所有连接的浏览器 |
74
+ | 关闭 | `session_shutdown` | 关服务、断开所有 SSE 客户端、`dispose()` 清空状态 |
75
+
76
+ `boot()` 幂等(`if (state) return`),所以 `/agent-live` 命令在 `session_start` 之前被调用也安全。
77
+
78
+ 启动失败时:有 UI 就 `ctx.ui.notify(..., "error")`,无 UI(如 `pi -p` 打印模式)落到 `console.error`,避免静默失败。
79
+
80
+ ## 5. 事件协议
81
+
82
+ 定义在 `plugins/agent-live/src/core/protocol.ts`,被两侧共享。
83
+
84
+ ### 5.1 事件表
85
+
86
+ | 事件 | 载荷 | 前端表现 |
87
+ | --- | --- | --- |
88
+ | `snapshot` | `agents[] / log[] / session` | 全量重建(清空 actors、粒子、日志 DOM) |
89
+ | `session` | `session` | 更新顶栏模型、轮次、忙碌标记 |
90
+ | `agent_join` | `agent` | 新建小人;非主管从门口进场并喊"我来了" |
91
+ | `agent_leave` | `id, ok` | 浮对勾/叉号,走回门口后销毁 |
92
+ | `agent_state` | `id, state, detail` | 状态灯换色,员工卡刷新 |
93
+ | `task` | `id, task` | 主管的任务写进底部任务条 |
94
+ | `thought` | `id, text` | 蓝色思考气泡(取末尾 52 字) |
95
+ | `say` | `id, text` | 灰色汇报气泡(取开头 90 字) |
96
+ | `action` | `id, action, label, toolCallId` | 走向对应工位,工位点亮,黄色动作气泡 |
97
+ | `action_end` | `id, toolCallId, ok` | 工位熄灭,回工位;失败浮叉号 |
98
+ | `delegate` | `from, to, task` | 入会面队列,播双人交接 |
99
+ | `usage` | `id, tokens, cost` | 员工卡与顶栏成本刷新 |
100
+ | `log` | `item` | 追加一条动态 |
101
+
102
+ ### 5.2 核心类型
103
+
104
+ ```ts
105
+ type AgentState = "idle" | "thinking" | "working" | "waiting" | "talking" | "done" | "error";
106
+ type OfficeAction = "type" | "archive" | "server" | "whiteboard" | "phone" | "delegate" | "coffee";
107
+
108
+ interface AgentView {
109
+ id: string; name: string; role: string;
110
+ parent?: string; // 有父即子 agent,前端据此决定进场方式
111
+ state: AgentState; detail?: string; action?: OfficeAction;
112
+ task?: string; thought?: string; model?: string;
113
+ tokens: number; cost: number; toolCalls: number;
114
+ joinedAt: number; seat?: number;
115
+ }
116
+ ```
117
+
118
+ `seat` 由服务端分配,前端不自行计算,保证多客户端看到同一布局。
119
+
120
+ ## 6. pi 事件 → 办公室事件
121
+
122
+ `packages/pi/src/adapter.ts` 的翻译规则:
123
+
124
+ | pi 事件 | 处理 |
125
+ | --- | --- |
126
+ | `session_start` | `boot()` |
127
+ | `session_shutdown` | 关服务并清空状态 |
128
+ | `model_select` / `thinking_level_select` | 更新 session 信息 |
129
+ | `before_agent_start` | 写入任务(`event.prompt` 压缩空白后截 300 字),状态转 thinking |
130
+ | `message_start` | **重置流式游标**,状态转 thinking |
131
+ | `message_update` | 提取 thinking 与 text 的增量(见 6.1),推思考、切换 thinking/talking |
132
+ | `message_end` | 强制 flush 思考缓冲、发 say、累加 usage |
133
+ | `turn_start` / `turn_end` | 更新 busy 与轮次(`turnIndex + 1`) |
134
+ | `tool_execution_start` | 起动作;若是委派工具则拉子 agent 进场 |
135
+ | `tool_execution_update` | 同步子 agent 进度 |
136
+ | `tool_execution_end` | 结束动作;子 agent 按各自 `exitCode` 定成败,未定论的用工具整体结果兜底,延迟 2.6s 离场 |
137
+ | `agent_end` / `agent_settled` | flush 思考,转 idle,busy 置 false |
138
+
139
+ ### 6.1 流式增量提取
140
+
141
+ pi 的 `message_update` 携带的是**累积的完整 message**,不是增量。所以维护两个游标:
142
+
143
+ ```ts
144
+ const thinking = joinBlocks(message.content, "thinking");
145
+ if (thinking.length > thinkingCursor) {
146
+ state.pushThought(MAIN, thinking.slice(thinkingCursor));
147
+ thinkingCursor = thinking.length;
148
+ }
149
+ ```
150
+
151
+ `message_start` 时归零。`joinBlocks` 从 `content` 数组里筛出指定类型的块并拼接,兼容 `content` 是纯字符串的情况。
152
+
153
+ ### 6.2 思考节流
154
+
155
+ 推理 token 到得很快,逐字广播会让气泡永远只显示一两个字。`state.ts` 的策略:
156
+
157
+ - 缓冲 180ms(`THOUGHT_FLUSH_MS`)后批量刷新。
158
+ - 非强制刷新时,**不足 12 字(`MIN_THOUGHT_CHARS`)的片段继续留在缓冲里**,避免开头冒出一个字的气泡。
159
+ - `message_end` / `agent_end` / `agent_settled` 强制刷新,保证尾巴不丢。
160
+ - 定时器 `unref()`,不阻止进程退出。
161
+
162
+ 实测(真实模型一次会话)刷新出的块长度为 126 字、78 字,符合预期。
163
+
164
+ ## 7. 工具 → 工位映射
165
+
166
+ `plugins/agent-live/src/core/mapping.ts`。按工具名正则匹配,**不硬编码具体工具**,所以自定义工具也能自动归位:
167
+
168
+ | 正则 | 工位 |
169
+ | --- | --- |
170
+ | `^(read\|ls\|glob\|grep\|find\|rg\|search_files\|list)` | `archive` 档案柜 |
171
+ | `^(write\|edit\|multi_edit\|apply_patch\|create\|notebook)` | `type` 自己工位 |
172
+ | `^(bash\|shell\|exec\|run\|terminal)` | `server` 服务器机架 |
173
+ | `^(todo\|plan\|task_list\|note)` | `whiteboard` 白板 |
174
+ | `(browser\|web\|fetch\|http\|curl\|search)` | `phone` 电话桌 |
175
+ | `^(ask_user\|question\|confirm)` | `phone` 电话桌 |
176
+ | `^(subagent\|task\|dispatch_agent\|spawn_agent\|agent)$` | `delegate` 会议桌 |
177
+ | 兜底 | `type` |
178
+
179
+ `labelForTool()` 另生成中文标签,会从参数里挑最有信息量的字段并做路径缩写(`…/core/session-manager.ts`):
180
+
181
+ | 工具 | 标签样例 |
182
+ | --- | --- |
183
+ | read | `查阅 …/core/session-manager.ts` |
184
+ | bash | `执行 npm test -- session` |
185
+ | grep | `检索 /getSession/` |
186
+ | ask_user | `请示 要不要加 TTL?` |
187
+
188
+ ## 8. 委派解析
189
+
190
+ `describeDelegation()` 把 subagent 工具接受的三种参数形态归一成一个扁平列表:
191
+
192
+ | 形态 | 参数 | 结果 |
193
+ | --- | --- | --- |
194
+ | 单个 | `{ agent, task }`(或 `prompt`/`description`/`subagent_type`) | 1 条,slot 0 |
195
+ | 并行 | `{ tasks: [{agent, task}, …] }` | N 条,slot 为下标 |
196
+ | 链式 | `{ chain: [{agent, task}, …] }` | N 条,slot 为下标 |
197
+
198
+ 子 agent 的 id 为 `` `${toolCallId}:${slot}` ``,保证并行/链式各路互不冲突,且工具结束时能精确回收。
199
+
200
+ `syncDelegationProgress()` 读取 `details.results[]`(或 `details.tasks[]`),逐条处理:
201
+
202
+ 1. 有 `usage` 就累加 token 与成本。
203
+ 2. 看 `exitCode`。**`-1` 表示这一路还在跑**(subagent 扩展的约定);已出数值则按 `exitCode !== 0` 或 `stopReason` 为 `error`/`aborted` 判成败,设成 done/error 后**跳过后续镜像**——否则每次进度回传都会把已交付的人重新拽去工位。
204
+ 3. 还在跑的,取最后一条 assistant 消息镜像状态:含 `toolCall` → 起对应动作;含 thinking → 转 thinking 并推思考;含 text → 转 talking。
205
+
206
+ 工具整体结束时(`tool_execution_end`)只给**尚未定论**的子 agent 兜底,不覆盖上面的单条结论。并行三路里一路失败,那一路才能独立显示为失败。
207
+
208
+ ## 9. 服务端
209
+
210
+ `plugins/agent-live/src/runtime/server.ts`,约 170 行。
211
+
212
+ ### 9.1 路由
213
+
214
+ | 路径 | 行为 |
215
+ | --- | --- |
216
+ | `/events` | SSE。先写 `: connected`,**立刻推一份 snapshot**,再订阅增量;25s 心跳 `: ping`;`req.close` 时清理订阅与心跳 |
217
+ | `/api/state` | 返回当前 snapshot 的 JSON,用于脚本化检查 |
218
+ | 其他 | 静态文件,根路径映射到 `index.html` |
219
+
220
+ 响应头带 `x-accel-buffering: no` 与 `cache-control: no-cache, no-transform`,避免代理缓冲导致事件延迟。
221
+
222
+ ### 9.2 端口探测
223
+
224
+ 从 `AGENT_LIVE_PI_PORT`(默认 7788)开始,遇 `EADDRINUSE` 递增,最多尝试 12 次(7788–7800)。这样多个 pi 会话可以并存,各占一个端口,互不干扰。
225
+
226
+ ### 9.3 静态文件与安全
227
+
228
+ - `WEB_ROOT = path.resolve(moduleDir(), "..", "web")`。`moduleDir()` 优先用 `import.meta.url`,失败回退 `__dirname` / `cwd`。
229
+ - **软链接接入时仍然正确**:根 `index.ts` 只做 re-export,`import.meta.url` 解析到真实的 `plugins/agent-live/src/`,`../web` 因此指向真实项目目录。
230
+ - 解析后校验 `filePath.startsWith(WEB_ROOT)`,否则 403,防目录穿越。
231
+ - MIME 白名单,未知扩展名回落 `application/octet-stream`。
232
+ - **只绑 `127.0.0.1`**。事件流、完整状态和宿主控制状态使用本地访问令牌,并拒绝非本机 `Host` / `Origin`;仍不得暴露到局域网或公网。
233
+
234
+ ### 9.4 广播容错
235
+
236
+ `OfficeState.emit()` 对每个监听器单独 try/catch。一个死掉的浏览器连接不能中断 agent 主循环——这是整个设计里唯一的强约束。
237
+
238
+ ## 10. 状态机
239
+
240
+ `plugins/agent-live/src/core/state.ts`,`OfficeState` 类。
241
+
242
+ | 常量 | 值 | 作用 |
243
+ | --- | --- | --- |
244
+ | `MAX_LOG` | 200 | 内存里保留的日志条数 |
245
+ | `THOUGHT_FLUSH_MS` | 180 | 思考批量刷新间隔 |
246
+ | `MIN_THOUGHT_CHARS` | 12 | 非强制刷新的最小片段长度 |
247
+ | `SCENE_LIMITS.seats` | 8 | 可坐工位总数 |
248
+ | `SCENE_LIMITS.agents` | 16 | 同一办公室中的真实 Agent 上限 |
249
+
250
+ - `snapshot()` 只带**最后 60 条**日志,新连接的客户端不至于一次性灌进 200 条。
251
+ - 座位用 `Set<number>` 管理,`claimSeat()` 取第一个空位,`leave()` 归还。座位已满时返回 `-1`,Agent 不带 `seat` 字段,由 Engine 使用站立位置;人数和工位数量不再强绑定。
252
+ - `addLog()` 的第四个参数 `broadcast` 控制是否额外发 `log` 事件。thought / say / tool 三类传 `false`,因为它们已有各自的专门事件,前端收到后自己写进动态栏(见 §11.7);join / leave / delegate 传 `true`,由服务端直接广播。两类日志都会进 `snapshot` 的历史记录。
253
+
254
+ ## 11. 前端渲染
255
+
256
+ `plugins/agent-live/web/app.js`。
257
+
258
+ ### 11.1 分辨率与缩放
259
+
260
+ 逻辑分辨率固定 384×216(16:9)。320×200 装不下 8 个工位加家具,所以放大到 384×216。
261
+
262
+ ```js
263
+ dpr = min(devicePixelRatio, 2);
264
+ scale = max(1, floor(min(canvasW / 384, canvasH / 216))); // 必须是整数
265
+ offX = floor((canvasW - 384 * scale) / 2); // 偏移也取整
266
+ ```
267
+
268
+ 整数缩放 + 整数偏移 = 每个逻辑像素恰好落在整数个设备像素上,边缘不糊。
269
+
270
+ ### 11.2 双层变换
271
+
272
+ ```js
273
+ ctx.setTransform(scale, 0, 0, scale, offX, offY); // 第一层:场景、小人、粒子
274
+ Office.drawRoom(...); Sprites.drawCharacter(...); Sprites.drawParticle(...);
275
+ ctx.setTransform(1, 0, 0, 1, 0, 0); // 第二层:名牌、气泡
276
+ drawLabel(...); drawBubble(...);
277
+ ```
278
+
279
+ 文字如果跟着场景一起放大会变成马赛克,所以在未缩放的坐标系里绘制,字号按 `scale` 比例算并夹最小值(名牌 `max(10*dpr, scale*3)`,气泡 `max(11*dpr, scale*3.2)`)。
280
+
281
+ ### 11.3 主循环
282
+
283
+ `requestAnimationFrame`,`dt` 上限 0.05s(切走标签页再回来不会瞬移)。顺序:`update(dt, now)` → `render(now)`。
284
+
285
+ 小人按 `y` 坐标排序后绘制,实现前后遮挡关系。
286
+
287
+ ### 11.4 移动
288
+
289
+ 曼哈顿移动:每帧只沿一个轴走,速度 `SPEED = 44` 逻辑 px/s。到达路点则弹出下一个;路径走完时套用 `dest` 的朝向与走道编号,姿势切回 `restPose()`。
290
+
291
+ `restPose()` 由动作决定:档案柜/机架/白板 → `reach`,电话 → `talk`,会面中 → `talk`,工作中且无动作或打字 → `type`,其余 → `sit`/`stand`。
292
+
293
+ ### 11.5 气泡
294
+
295
+ 逐字显示(46 字/秒),最多 3 行,自动换行按字符宽度测量。气泡框会被夹在画布内(`x` 钳制到 `[4dpr, canvasW - boxW - 4dpr]`),尖角随之偏移但仍指向小人。
296
+
297
+ ### 11.6 粒子
298
+
299
+ | 类型 | 用途 |
300
+ | --- | --- |
301
+ | `key` | 打字 |
302
+ | `paper` | 翻档案 / 交接纸条 |
303
+ | `spark` | 跑命令 |
304
+ | `check` | 成功 |
305
+ | `cross` | 失败 |
306
+ | `bang` | 接到任务 |
307
+
308
+ 工作中每 0.26s 发一个(服务器机架 0.18s,更密)。带 `target` 的粒子做插值飞行(用于纸条从 A 飞到 B),其余按速度直线运动并淡出。
309
+
310
+ ### 11.7 动态栏
311
+
312
+ 服务端只为 join / leave / delegate 广播 `log` 事件(§10)。thought / say / action 到达时由 `feed(agentId, kind, text)` 自行写入,用的是**事件全文**;气泡只显示裁剪后的片段(思考取末尾 52 字、汇报取开头 90 字)。分开处理是有意的:瞥一眼看气泡,回头查细节看动态栏。
313
+
314
+ `logLine()` 负责建 DOM 并把节点数压在 220 以内,`snapshot` 里的历史日志走同一个函数。
315
+
316
+ ## 12. 地图与寻路
317
+
318
+ 原版实现在 `plugins/agent-live/web/office.js`;V2 的同一组导航数据来自 `plugins/agent-live/web/v2/content/layouts/demo-office.json`,由 `plugins/agent-live/web/v2/office-renderer.js` 暴露给 Runtime。二者都使用 8px 网格和整数像素绘制。
319
+
320
+ 导航靠固定走道而非通用寻路算法:
321
+
322
+ ```
323
+ LANES = [46, 100, 162] // 三条横向走道
324
+ VCONN = [76, 140, 204, 276] // 四条纵向通道
325
+ ```
326
+
327
+ `path(from, target)` 生成轴对齐路点:
328
+
329
+ 1. 从当前位置垂直走上自己所在的走道
330
+ 2. 若目标在别的走道,选一条**总距离最短**的纵向通道横穿过去
331
+ 3. 沿目标走道横向移动到目标 x
332
+ 4. 垂直进入目标锚点
333
+
334
+ 每个锚点带 `{x, y, dir, lane}`,`lane` 是它属于哪条走道。因为所有家具都摆在走道之间的空隙里,这个路由天然不会穿过桌子——不需要碰撞检测,也不需要 A*。
335
+
336
+ `SEATS` 为两排各 4 个工位(cx = 44/108/172/236,第一排挂 lane 1,第二排挂 lane 2)。`TARGETS` 定义 archive / server / whiteboard / phone / coffee / meetA / meetB / entry,其中 `meetA(108,190,朝右)` 与 `meetB(244,190,朝左)` 正好面对面。
337
+
338
+ `stationKey(action, seat)` 返回高亮用的工位 id:`type`/`delegate`/空 → `desk{seat}`,其余 → 动作名本身。
339
+
340
+ ## 13. 会面编排
341
+
342
+ 委派事件先进 `meetQueue`,同一时刻只有一场 `meeting`。状态机:
343
+
344
+ ```
345
+ delegate 事件 → 入队
346
+ ↓ (无进行中的会面)
347
+ phase = "walk" 双方 goTo(meetA / meetB),主管冒"派活:…"
348
+ ↓ (双方 path 清空,或超时 5s)
349
+ phase = "hand" 纸条飞行 + 感叹号 + 子 agent 复述 + 双音提示
350
+ ↓ (1.5s)
351
+ endMeeting() 清 inMeeting,各自 retarget()
352
+ ```
353
+
354
+ `inMeeting` 标志在会面期间抑制 `retarget()`,防止其他事件把人从会议桌上拽走。超时兜底保证任何寻路异常都不会让队列永久卡死。
355
+
356
+ ## 14. 演示模式
357
+
358
+ `runDemo()` 在 `plugins/agent-live/web/app.js` 内,通过 `apply()` 灌入伪造事件,与真实 SSE 走完全相同的渲染路径。
359
+
360
+ **演示脚本不额外发 `log` 事件**,只在委派处发一条(因为服务端确实会为委派单独广播日志),其余动态条目全由 §11.7 的 `feed()` 产生。这条约束必须保持:早期演示脚本给每条思考 / 汇报 / 工具都手工补了一条 `log`,正好掩盖住了前端漏写日志的缺口,代价是演示成了唯一“好使”的模式。
361
+
362
+ `?demo=1` 自动播放,否则 `connect()` 建立 SSE。演示只播一遍,不循环。
363
+
364
+ 后端曾有一份对称的 `runDemo()`,已删除:两份脚本会各自漂移,留前端这份就够,`/agent-live demo` 只负责用 `?demo=1` 打开浏览器。
365
+
366
+ ## 15. 安装与部署
367
+
368
+ Pi 用户安装独立的 `@iniesta8888/agent-live-pi-adapter` npm 包。其入口是
369
+ `packages/pi/dist/adapter.js`,构建时只打包 Pi Adapter 与所需公共
370
+ Runtime,并携带独立 Viewer;不会把 Codex 或 DSH 实现带给 Pi 用户。
371
+
372
+ ## 16. 配置项
373
+
374
+ | 环境变量 | 默认 | 作用 |
375
+ | --- | --- | --- |
376
+ | `AGENT_LIVE_PI_PORT` | 7788 | 起始端口,冲突时向后探测 12 次 |
377
+ | `AGENT_LIVE_AUTO_OPEN` | 未设置 | 设为 `1` 则会话启动时自动打开浏览器 |
378
+
379
+ ## 17. 验证记录
380
+
381
+ 以下均为实跑结果,非推断。
382
+
383
+ | 检查项 | 方法 | 结果 |
384
+ | --- | --- | --- |
385
+ | 扩展可加载 | `pi --list-models` | 退出码 0,无报错 |
386
+ | 服务在真实会话中启动 | `pi -p` 后轮询 `/api/state` | 第 8 次轮询(约 3.2s)拿到 snapshot,主管带真实模型名与任务 |
387
+ | 真实事件流完整 | 会话期间 `curl -N /events` | `agent_state`×14、`session`×6、`usage`×3、`thought`×3、`say`×2、`action`×2、`action_end`×2、`snapshot`×1 |
388
+ | 工具映射正确 | 同上 | `bash ls -la` → `action:server`/"执行 ls -la";`read package.json` → `action:archive`/"查阅 package.json" |
389
+ | 思考分块合理 | 同上 | 刷新块长 126 字、78 字,无单字气泡 |
390
+ | 前端无运行时错误 | 浏览器 QA(console/page error/network) | 全部通过 |
391
+ | 演示全流程 | 播放中与播放后读取 DOM | 中段 3 人各就各位、状态正确;结束时子 agent 已离场,成本汇总 46.2k tok / $0.1840 |
392
+ | 动态栏(演示) | 播完读取 `#log` 文本 | 16 条、无重复;思考 / 工具 / 汇报 / 派活 四类齐全 |
393
+ | 动态栏(真实会话) | 会话期间浏览器读取 `#log` | 依次出现“阿派 上班了”、四条思考全文、“查阅 package.json”、“执行 ls -la web”、汇报全文 |
394
+ | V2 内容合同 | `npm run validate:content` | 内置 Preset 与八类内容全部通过 |
395
+ | 公共运行环境 | `npm run validate:environment` | 时间覆盖、天气覆盖、18:00 下班与跨夜班次全部通过 |
396
+ | V2 像素一致性 | `/v2/parity.html` | 房间 5 组、角色 3 组、粒子 7 组,共 15 个用例均为 0 channel differences |
397
+ | V2 完整演示 | 播放 `/v2.html?demo=1` 并检查 DOM / console | 完成至 46.2k tok / $0.1840,子 agent 正常离场,无 console error |
398
+ | V2 真实连接 | 非 demo 入口连接 SSE | 成功建立连接并接收会话状态 |
399
+
400
+ ## 18. 已知缺陷
401
+
402
+ ### 18.1 工位不做竞争处理(P2)
403
+
404
+ 两个 agent 同时去档案柜会站在同一个锚点上重叠。需要给每个工位加候补站位或排队。
405
+
406
+ ### 18.2 无座位 Agent 的表现较弱(P3)
407
+
408
+ Agent 与座位容量已经解耦:最多显示 16 个 Agent,前 8 个获得固定座位,其余 Agent 不再挤占最后一个座位。无座位 Agent 仍能参与工作动作和协作,但空闲时缺少明确的等待区视觉,这是后续内容优化项。
409
+
410
+ ### 18.3 成本可能显示为 0(上游字段缺失)
411
+
412
+ 实测部分模型 / 中继下 token 数正常累加,但成本停在 `$0.0000`——`message.usage.cost.total` 没给值。不是渲染问题,无法在本项目内解决。
413
+
414
+ ### 18.4 长思考在日志里会被切成多条
415
+
416
+ 180ms 批量刷新的自然结果:一段长推理在动态栏里可能表现为相邻的两三条。气泡观感正常,日志略显割裂。要连贯得在日志侧按 agent 合并相邻的 thought。
417
+
418
+ ### 18.5 工具参数缺失时标签不完整
419
+
420
+ 参数里没有 `path` 类字段时,`labelForTool()` 会产出光秃的“查阅”。实测在并行工具调用参数串台时见到过两条。要严谨就在拼不出提示时回落到工具名。
421
+
422
+ ## 19. 扩展指南
423
+
424
+ 新功能只扩展 V2;`plugins/agent-live/web/office.js` 和 `plugins/agent-live/web/sprites.js` 保持冻结。
425
+
426
+ **加一个角色外观**:在 `plugins/agent-live/web/v2/content/agent-skins/tiny-developers.json` 增加角色名、上衣与滚边配色。若它还是宿主传来的新职位名,再在 `plugins/agent-live/src/core/agents.ts` 的角色映射中增加中文名。名字匹配走小写。
427
+
428
+ **加一个已有类别的 Prop**:先在 Props registry 声明类型、尺寸、能力与 renderer,再在 Layout 的 `propInstances` 中放置实例。功能锚点必须位于可达通道上。
429
+
430
+ **加一种全新的 Prop 表现或能力**:除内容声明外,还要在 `plugins/agent-live/web/v2/office-renderer.js` 增加绘制逻辑;若它承载新的真实工作事件,再同步扩展 `plugins/agent-live/src/core/protocol.ts`、`plugins/agent-live/src/core/mapping.ts` 与 `plugins/agent-live/web/app.js` 的动作和特效分支。纯生活设施不应伪装成 Work Event。
431
+
432
+ **加一个 Layout**:创建新的 Layout JSON,保持 `single-office-v1`、384×216、8 个座位、连通导航,并为六种必需 Work Semantic 提供落点。随后新增或更新一个 Preset 引用它。座位默认使用 `workstation`,也可通过 `seats[].renderer` 选择内置的 `cubicle-workstation`、`executive-seat` 或 `boardroom-seat`。
433
+
434
+ **加一套 Style**:新建 Style JSON,完整覆盖 CSS、Canvas 与 Character tokens;布局坐标和事件语义不得放进 Style。
435
+
436
+ **接新的委派工具**:若参数结构不是现有三种形态,扩展 `describeDelegation()`;若进度回传结构不同,扩展 `syncDelegationProgress()` 的 results 提取逻辑。
437
+
438
+ **换成精灵图**:`plugins/agent-live/web/v2/sprite-renderer.js` 的 `drawCharacter(c, actor, t)` 是角色绘制入口,保持 Runtime 需要的返回接口不变即可整体替换为贴图绘制。
439
+
440
+ ## 20. 性能与资源
441
+
442
+ | 项 | 表现 |
443
+ | --- | --- |
444
+ | 服务端内存 | 上限约 200 条日志、4000 条内存回放事件和 16 个 Agent 对象 |
445
+ | 广播开销 | 每事件对每客户端一次 `JSON.stringify` + 一次 write |
446
+ | 前端绘制 | 每帧约 200–300 次 `fillRect`,60fps 无压力 |
447
+ | 日志 DOM | 上限 220 节点,超出从头部移除 |
448
+ | 员工卡 | 整体重建(人数少,开销可忽略) |
449
+ | 心跳 | 25s 一次,防代理断连 |
450
+
451
+ 主要的 CPU 成本是 `drawRoom()` 每帧重绘全部家具。目前分辨率下无所谓;真要优化就把静态层缓存到离屏 canvas,只重绘会闪烁的部分。
452
+
453
+ ## 21. 配置化 V2 入口
454
+
455
+ 原版 `/?demo=1` 保持冻结,用作视觉与行为回归基线。新版 `/v2.html?demo=1` 的启动链路为:
456
+
457
+ ```text
458
+ v2.html
459
+ └─ v2/bootstrap.js
460
+ ├─ 解析 URL 指定的 Preset(默认 builtin/tech-open-office)
461
+ ├─ 并行加载 Style / Layout / Agent Skin / Props / NPC / Life / Atmosphere / Environment
462
+ ├─ 校验 single-office-v1、内容引用、时间天气和 NPC 班次
463
+ ├─ environment-runtime.js → window.OfficeEnvironment
464
+ ├─ 应用 UI tokens 与 Atmosphere 覆盖
465
+ ├─ office-renderer.js → window.Office
466
+ ├─ sprite-renderer.js → window.Sprites
467
+ └─ 动态加载固定的 app.js Office Runtime
468
+ ```
469
+
470
+ V2 的办公室和角色绘制已经完全由自己的 renderer 与内容配置生成,不加载经典 `office.js` / `sprites.js`。两条入口只共用固定的 `app.js` Office Runtime,使事件协议、移动、气泡、交接和侧栏行为保持一致。五套 Layout 共用这条 Runtime;布局差异不会改变宿主事件协议。
471
+
472
+ Environment 也是本地模块:核心不主动请求天气服务。宿主可通过 URL 参数或 `window.OfficeEnvironment.update()` 注入已经标准化的天气/时间,renderer 只读取快照。这使联网、定位和密钥权限停留在 Connector 一侧,内容和画面层仍保持零网络依赖。
473
+
474
+ 新增目录:
475
+
476
+ ```text
477
+ plugins/agent-live/web/v2.html
478
+ plugins/agent-live/web/v2/
479
+ bootstrap.js
480
+ environment-runtime.js
481
+ office-renderer.js
482
+ sprite-renderer.js
483
+ style.css
484
+ parity.html
485
+ parity.js
486
+ content/
487
+ presets/demo-office.json
488
+ presets/old-school-office.json
489
+ presets/boardroom-office.json
490
+ styles/pixel-classic.json
491
+ layouts/demo-office.json
492
+ layouts/old-school-office.json
493
+ layouts/boardroom-office.json
494
+ agent-skins/tiny-developers.json
495
+ props/default-office.json
496
+ props/extended-office.json
497
+ npcs/none.json
498
+ npcs/old-school-staff.json
499
+ npcs/boardroom-staff.json
500
+ life-activities/none.json
501
+ life-activities/old-school-routines.json
502
+ life-activities/boardroom-routines.json
503
+ atmospheres/default.json
504
+ environments/local-office.json
505
+ environments/static-office.json
506
+ environments/rainy-night.json
507
+ ```
508
+
509
+ 内容合同检查使用:
510
+
511
+ ```bash
512
+ npm run validate:content
513
+ ```
514
+
515
+ 校验失败时 V2 不启动 Runtime,并在连接状态和动态栏中显示具体错误;已加载的原版入口不受影响。视觉回归使用 `/v2/parity.html`,当前覆盖 5 组房间状态、3 组角色状态和 7 组粒子状态。
@@ -0,0 +1,24 @@
1
+ # 在 Codex 中使用 Agent Live
2
+
3
+ > 以下是 Agent Live Marketplace 公开后的普通用户流程。
4
+
5
+ ## 安装和启动
6
+
7
+ ```bash
8
+ codex plugin marketplace add ssssnail/agent-live --ref main
9
+ codex plugin add agent-live@agent-live-marketplace
10
+ ```
11
+
12
+ 在 Codex 中调用 Agent Live Skill。它会返回并打开一个本地办公室地址;任务需要在该页面的输入框中发起。
13
+
14
+ ## 自定义
15
+
16
+ Codex 当前采用单轮显式自定义:调用 Skill 时把修改要求写在同一句中,例如:
17
+
18
+ ```text
19
+ /agent-live custom:将 Boss 改名为负责人,办公室名称改成创意工作间,并去掉 slogan。
20
+ ```
21
+
22
+ 修改成功后会立即保存并启用,不需要预览或确认。Custom Office 只保存在本机,不会改动官方 Preset。
23
+
24
+ Codex 当前没有持续 Creator Mode;下一次修改时再次调用 Agent Live Skill 并描述要求即可。关闭办公室网页后,本次本地服务会自动退出。
@@ -0,0 +1,44 @@
1
+ # 在 DeepSeek Harness 中使用 Agent Live
2
+
3
+ > 以下是 DSH Adapter 发布到包仓库后的普通用户流程。
4
+
5
+ ## 安装和启动
6
+
7
+ ```bash
8
+ dsh plugin --profile web add @iniesta8888/agent-live-dsh-adapter
9
+ dsh plugin --profile web install
10
+ dsh web
11
+ ```
12
+
13
+ 打开一个 DSH 会话,顶部会出现 `Agent Live` View。切换到该 View 即可观看;对话、停止和审批仍在 DSH 原界面完成。
14
+
15
+ ## 选择办公室
16
+
17
+ 在 DSH 命令输入框中执行:
18
+
19
+ ```text
20
+ /agent-live list presets
21
+ /agent-live preset tech
22
+ ```
23
+
24
+ 还可以选择 `meetingroom` 或 `oldschool`。
25
+
26
+ ## 自定义
27
+
28
+ ```text
29
+ /agent-live custom
30
+ ```
31
+
32
+ 进入 Creator Mode 后直接描述修改,例如:
33
+
34
+ ```text
35
+ 将 Agent 改名为主程序,Boss 改名为负责人,再增加两名同事,办公室名称改成协作空间。
36
+ ```
37
+
38
+ 完成后执行:
39
+
40
+ ```text
41
+ /agent-live exit
42
+ ```
43
+
44
+ 修改会立即保存到本机并启用,不需要预览或确认,也不会改动官方 Preset。
@@ -0,0 +1,50 @@
1
+ # 在 Pi 中使用 Agent Live
2
+
3
+ > 以下是 Agent Live 仓库公开并完成发布后的普通用户流程。
4
+
5
+ ## 安装和启动
6
+
7
+ 发布到 npm 后,推荐一条命令安装:
8
+
9
+ ```bash
10
+ pi install npm:@iniesta8888/agent-live-pi-adapter
11
+ ```
12
+
13
+ 重启 Pi,然后输入:
14
+
15
+ ```text
16
+ /agent-live
17
+ ```
18
+
19
+ 浏览器会打开本地像素办公室。此后继续在 Pi 中工作即可。
20
+
21
+ ## 选择办公室
22
+
23
+ ```text
24
+ /agent-live list presets
25
+ /agent-live preset tech
26
+ ```
27
+
28
+ 还可以选择 `meetingroom` 或 `oldschool`。
29
+
30
+ ## 自定义
31
+
32
+ 先进入 Creator Mode:
33
+
34
+ ```text
35
+ /agent-live custom
36
+ ```
37
+
38
+ 然后直接描述修改,例如:
39
+
40
+ ```text
41
+ 把 Agent 改名为主程序,办公室名称改成像素工作室,再增加两名同事。
42
+ ```
43
+
44
+ 完成后退出:
45
+
46
+ ```text
47
+ /agent-live exit
48
+ ```
49
+
50
+ 修改会保存为本机 Custom Office,不会改动官方 Preset。关闭本地服务可使用 `/agent-live close`。