@meetquinn/animactl 0.1.2 → 0.1.3

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 (289) hide show
  1. package/README.md +11 -6
  2. package/dist/server/{runtime/activity-payload.d.ts → activities/format.d.ts} +4 -1
  3. package/dist/server/activities/format.d.ts.map +1 -0
  4. package/dist/server/{runtime/activity-payload.js → activities/format.js} +16 -1
  5. package/dist/server/agents/agent-skills.d.ts +7 -3
  6. package/dist/server/agents/agent-skills.d.ts.map +1 -1
  7. package/dist/server/agents/agent-skills.js +243 -38
  8. package/dist/server/agents/agent-slack.service.d.ts +15 -0
  9. package/dist/server/agents/agent-slack.service.d.ts.map +1 -1
  10. package/dist/server/agents/agent-slack.service.js +43 -6
  11. package/dist/server/agents/default-skills.d.ts +9 -0
  12. package/dist/server/agents/default-skills.d.ts.map +1 -0
  13. package/dist/server/agents/default-skills.js +52 -0
  14. package/dist/server/cli/runtime-cli.d.ts +7 -1
  15. package/dist/server/cli/runtime-cli.d.ts.map +1 -1
  16. package/dist/server/cli/runtime-cli.js +107 -3
  17. package/dist/server/cli/services-cli.d.ts.map +1 -1
  18. package/dist/server/cli/services-cli.js +39 -0
  19. package/dist/server/inbox/slack-subscriber.d.ts +2 -0
  20. package/dist/server/inbox/slack-subscriber.d.ts.map +1 -1
  21. package/dist/server/inbox/slack-subscriber.js +28 -2
  22. package/dist/server/inbox/slack-subscription.service.d.ts.map +1 -1
  23. package/dist/server/inbox/slack-subscription.service.js +13 -1
  24. package/dist/server/inbox/wake-queue.service.d.ts +3 -1
  25. package/dist/server/inbox/wake-queue.service.d.ts.map +1 -1
  26. package/dist/server/inbox/wake-queue.service.js +5 -3
  27. package/dist/server/provider-usage/http.d.ts +1 -0
  28. package/dist/server/provider-usage/http.d.ts.map +1 -1
  29. package/dist/server/provider-usage/http.js +23 -1
  30. package/dist/server/provider-usage/provider-usage.service.d.ts +1 -4
  31. package/dist/server/provider-usage/provider-usage.service.d.ts.map +1 -1
  32. package/dist/server/provider-usage/provider-usage.service.js +1 -18
  33. package/dist/server/provider-usage/providers/claude.d.ts +1 -1
  34. package/dist/server/provider-usage/providers/claude.d.ts.map +1 -1
  35. package/dist/server/provider-usage/providers/claude.js +1 -1
  36. package/dist/server/provider-usage/providers/codex.d.ts +1 -1
  37. package/dist/server/provider-usage/providers/codex.d.ts.map +1 -1
  38. package/dist/server/provider-usage/providers/codex.js +1 -1
  39. package/dist/server/provider-usage/providers/kimi.d.ts +1 -1
  40. package/dist/server/provider-usage/providers/kimi.d.ts.map +1 -1
  41. package/dist/server/provider-usage/providers/kimi.js +4 -4
  42. package/dist/server/provider-usage/result.d.ts +5 -0
  43. package/dist/server/provider-usage/result.d.ts.map +1 -0
  44. package/dist/server/provider-usage/result.js +18 -0
  45. package/dist/server/providers/active-runtime.d.ts +1 -1
  46. package/dist/server/providers/active-runtime.d.ts.map +1 -1
  47. package/dist/server/providers/claude-events.d.ts +1 -1
  48. package/dist/server/providers/claude-events.d.ts.map +1 -1
  49. package/dist/server/providers/claude-events.js +2 -2
  50. package/dist/server/providers/claude.d.ts +1 -1
  51. package/dist/server/providers/claude.d.ts.map +1 -1
  52. package/dist/server/providers/claude.js +2 -2
  53. package/dist/server/providers/codex-app-server.d.ts +1 -1
  54. package/dist/server/providers/codex-app-server.d.ts.map +1 -1
  55. package/dist/server/providers/codex-app-server.js +1 -1
  56. package/dist/server/providers/codex-events.js +1 -1
  57. package/dist/server/providers/codex.d.ts +1 -1
  58. package/dist/server/providers/codex.d.ts.map +1 -1
  59. package/dist/server/providers/codex.js +2 -2
  60. package/dist/server/{runtime/provider-contract.d.ts → providers/contract.d.ts} +1 -1
  61. package/dist/server/providers/contract.d.ts.map +1 -0
  62. package/dist/server/providers/factory.d.ts +1 -1
  63. package/dist/server/providers/factory.d.ts.map +1 -1
  64. package/dist/server/providers/kimi-events.d.ts +1 -1
  65. package/dist/server/providers/kimi-events.d.ts.map +1 -1
  66. package/dist/server/providers/kimi-events.js +1 -1
  67. package/dist/server/providers/kimi.d.ts +1 -1
  68. package/dist/server/providers/kimi.d.ts.map +1 -1
  69. package/dist/server/providers/kimi.js +3 -2
  70. package/dist/server/providers/reasoning-events.js +1 -1
  71. package/dist/server/runtime/active-run-control.d.ts +19 -0
  72. package/dist/server/runtime/active-run-control.d.ts.map +1 -0
  73. package/dist/server/runtime/active-run-control.js +89 -0
  74. package/dist/server/runtime/activity.js +1 -1
  75. package/dist/server/runtime/agent-runner.d.ts +1 -1
  76. package/dist/server/runtime/agent-runner.d.ts.map +1 -1
  77. package/dist/server/runtime/delivery-prompt.d.ts +6 -0
  78. package/dist/server/runtime/delivery-prompt.d.ts.map +1 -1
  79. package/dist/server/runtime/delivery-prompt.js +53 -34
  80. package/dist/server/runtime/followup-appender.d.ts +20 -0
  81. package/dist/server/runtime/followup-appender.d.ts.map +1 -0
  82. package/dist/server/runtime/followup-appender.js +128 -0
  83. package/dist/server/runtime/host.d.ts +2 -0
  84. package/dist/server/runtime/host.d.ts.map +1 -1
  85. package/dist/server/runtime/host.js +8 -0
  86. package/dist/server/runtime/provider-runner.d.ts +16 -0
  87. package/dist/server/runtime/provider-runner.d.ts.map +1 -0
  88. package/dist/server/runtime/provider-runner.js +86 -0
  89. package/dist/server/runtime/runtime-bridge.d.ts +1 -1
  90. package/dist/server/runtime/runtime-bridge.d.ts.map +1 -1
  91. package/dist/server/runtime/runtime-session.service.d.ts +1 -1
  92. package/dist/server/runtime/runtime-session.service.d.ts.map +1 -1
  93. package/dist/server/runtime/runtime-session.service.js +1 -1
  94. package/dist/server/runtime/runtime-worker.d.ts +2 -10
  95. package/dist/server/runtime/runtime-worker.d.ts.map +1 -1
  96. package/dist/server/runtime/runtime-worker.js +60 -286
  97. package/dist/server/runtime-management/managed-runtime.d.ts.map +1 -0
  98. package/dist/server/runtime-management/runtime-release.d.ts.map +1 -0
  99. package/dist/server/{runtime → runtime-management}/runtime-upgrade.d.ts +1 -0
  100. package/dist/server/runtime-management/runtime-upgrade.d.ts.map +1 -0
  101. package/dist/server/{runtime → runtime-management}/runtime-upgrade.js +14 -0
  102. package/dist/server/services/system.service.d.ts +41 -0
  103. package/dist/server/services/system.service.d.ts.map +1 -0
  104. package/dist/server/services/system.service.js +154 -0
  105. package/dist/server/settings/settings.service.d.ts +2 -1
  106. package/dist/server/settings/settings.service.d.ts.map +1 -1
  107. package/dist/server/settings/settings.service.js +9 -1
  108. package/dist/server/slack/shortcuts.d.ts +0 -3
  109. package/dist/server/slack/shortcuts.d.ts.map +1 -1
  110. package/dist/server/slack/shortcuts.js +0 -3
  111. package/dist/server/slack-interactions/shortcut-ids.d.ts +4 -0
  112. package/dist/server/slack-interactions/shortcut-ids.d.ts.map +1 -0
  113. package/dist/server/slack-interactions/shortcut-ids.js +3 -0
  114. package/dist/server/slack-interactions/shortcut-views.d.ts +65 -0
  115. package/dist/server/slack-interactions/shortcut-views.d.ts.map +1 -0
  116. package/dist/server/slack-interactions/shortcut-views.js +211 -0
  117. package/dist/server/{slack → slack-interactions}/shortcut.service.d.ts +2 -47
  118. package/dist/server/slack-interactions/shortcut.service.d.ts.map +1 -0
  119. package/dist/server/slack-interactions/shortcut.service.js +227 -0
  120. package/dist/server/storage/jsonl-log.d.ts +9 -0
  121. package/dist/server/storage/jsonl-log.d.ts.map +1 -1
  122. package/dist/server/storage/jsonl-log.js +36 -1
  123. package/dist/server/storage/schema/server.store.d.ts +5 -0
  124. package/dist/server/storage/schema/server.store.d.ts.map +1 -1
  125. package/dist/server/storage/schema/server.store.js +2 -1
  126. package/dist/server/storage/schema/wake-queue.store.d.ts +15 -1
  127. package/dist/server/storage/schema/wake-queue.store.d.ts.map +1 -1
  128. package/dist/server/storage/schema/wake-queue.store.js +5 -3
  129. package/dist/server/tests/agent-config.test.d.ts +2 -0
  130. package/dist/server/tests/agent-config.test.d.ts.map +1 -0
  131. package/dist/server/tests/agent-config.test.js +229 -0
  132. package/dist/server/tests/agent-runtime.test.d.ts +2 -0
  133. package/dist/server/tests/agent-runtime.test.d.ts.map +1 -0
  134. package/dist/server/tests/agent-runtime.test.js +1110 -0
  135. package/dist/server/tests/agent-seed-memory.test.d.ts +2 -0
  136. package/dist/server/tests/agent-seed-memory.test.d.ts.map +1 -0
  137. package/dist/server/tests/agent-seed-memory.test.js +16 -0
  138. package/dist/server/tests/agent-skills.test.d.ts +2 -0
  139. package/dist/server/tests/agent-skills.test.d.ts.map +1 -0
  140. package/dist/server/tests/agent-skills.test.js +140 -0
  141. package/dist/server/tests/anima-home.d.ts +2 -0
  142. package/dist/server/tests/anima-home.d.ts.map +1 -0
  143. package/dist/server/tests/anima-home.js +4 -0
  144. package/dist/server/tests/cli-file.test.d.ts +2 -0
  145. package/dist/server/tests/cli-file.test.d.ts.map +1 -0
  146. package/dist/server/tests/cli-file.test.js +596 -0
  147. package/dist/server/tests/cli-message.test.d.ts +2 -0
  148. package/dist/server/tests/cli-message.test.d.ts.map +1 -0
  149. package/dist/server/tests/cli-message.test.js +1196 -0
  150. package/dist/server/tests/client-error-routes.test.d.ts +2 -0
  151. package/dist/server/tests/client-error-routes.test.d.ts.map +1 -0
  152. package/dist/server/tests/client-error-routes.test.js +163 -0
  153. package/dist/server/tests/config.test.d.ts +2 -0
  154. package/dist/server/tests/config.test.d.ts.map +1 -0
  155. package/dist/server/tests/config.test.js +497 -0
  156. package/dist/server/tests/default-skills.test.d.ts +2 -0
  157. package/dist/server/tests/default-skills.test.d.ts.map +1 -0
  158. package/dist/server/tests/default-skills.test.js +57 -0
  159. package/dist/server/tests/helpers/inbox.d.ts +10 -0
  160. package/dist/server/tests/helpers/inbox.d.ts.map +1 -0
  161. package/dist/server/tests/helpers/inbox.js +21 -0
  162. package/dist/server/tests/helpers/slack.d.ts +11 -0
  163. package/dist/server/tests/helpers/slack.d.ts.map +1 -0
  164. package/dist/server/tests/helpers/slack.js +17 -0
  165. package/dist/server/tests/helpers/state.d.ts +19 -0
  166. package/dist/server/tests/helpers/state.d.ts.map +1 -0
  167. package/dist/server/tests/helpers/state.js +69 -0
  168. package/dist/server/tests/inbox-slack-events.test.d.ts +2 -0
  169. package/dist/server/tests/inbox-slack-events.test.d.ts.map +1 -0
  170. package/dist/server/tests/inbox-slack-events.test.js +271 -0
  171. package/dist/server/tests/inbox.test.d.ts +2 -0
  172. package/dist/server/tests/inbox.test.d.ts.map +1 -0
  173. package/dist/server/tests/inbox.test.js +144 -0
  174. package/dist/server/tests/interactive-ask.test.d.ts +2 -0
  175. package/dist/server/tests/interactive-ask.test.d.ts.map +1 -0
  176. package/dist/server/tests/interactive-ask.test.js +387 -0
  177. package/dist/server/tests/kb.test.d.ts +2 -0
  178. package/dist/server/tests/kb.test.d.ts.map +1 -0
  179. package/dist/server/tests/kb.test.js +371 -0
  180. package/dist/server/tests/message.service.test.d.ts +2 -0
  181. package/dist/server/tests/message.service.test.d.ts.map +1 -0
  182. package/dist/server/tests/message.service.test.js +151 -0
  183. package/dist/server/tests/messages.test.d.ts +2 -0
  184. package/dist/server/tests/messages.test.d.ts.map +1 -0
  185. package/dist/server/tests/messages.test.js +12 -0
  186. package/dist/server/tests/prompt-attachments.test.d.ts +2 -0
  187. package/dist/server/tests/prompt-attachments.test.d.ts.map +1 -0
  188. package/dist/server/tests/prompt-attachments.test.js +274 -0
  189. package/dist/server/tests/provider-usage.test.d.ts +2 -0
  190. package/dist/server/tests/provider-usage.test.d.ts.map +1 -0
  191. package/dist/server/tests/provider-usage.test.js +97 -0
  192. package/dist/server/tests/reminders.test.d.ts +2 -0
  193. package/dist/server/tests/reminders.test.d.ts.map +1 -0
  194. package/dist/server/tests/reminders.test.js +383 -0
  195. package/dist/server/tests/runtime-cli.test.d.ts +2 -0
  196. package/dist/server/tests/runtime-cli.test.d.ts.map +1 -0
  197. package/dist/server/tests/runtime-cli.test.js +21 -0
  198. package/dist/server/tests/runtime-upgrade.test.d.ts +2 -0
  199. package/dist/server/tests/runtime-upgrade.test.d.ts.map +1 -0
  200. package/dist/server/tests/runtime-upgrade.test.js +307 -0
  201. package/dist/server/tests/runtime-worker.test.d.ts +2 -0
  202. package/dist/server/tests/runtime-worker.test.d.ts.map +1 -0
  203. package/dist/server/tests/runtime-worker.test.js +1021 -0
  204. package/dist/server/tests/runtime.test.d.ts +2 -0
  205. package/dist/server/tests/runtime.test.d.ts.map +1 -0
  206. package/dist/server/tests/runtime.test.js +354 -0
  207. package/dist/server/tests/services.test.d.ts +2 -0
  208. package/dist/server/tests/services.test.d.ts.map +1 -0
  209. package/dist/server/tests/services.test.js +636 -0
  210. package/dist/server/tests/slack-files.test.d.ts +2 -0
  211. package/dist/server/tests/slack-files.test.d.ts.map +1 -0
  212. package/dist/server/tests/slack-files.test.js +118 -0
  213. package/dist/server/tests/slack-shortcuts.test.d.ts +2 -0
  214. package/dist/server/tests/slack-shortcuts.test.d.ts.map +1 -0
  215. package/dist/server/tests/slack-shortcuts.test.js +310 -0
  216. package/dist/server/tests/slack.test.d.ts +2 -0
  217. package/dist/server/tests/slack.test.d.ts.map +1 -0
  218. package/dist/server/tests/slack.test.js +213 -0
  219. package/dist/server/tests/state-cache.test.d.ts +2 -0
  220. package/dist/server/tests/state-cache.test.d.ts.map +1 -0
  221. package/dist/server/tests/state-cache.test.js +184 -0
  222. package/dist/server/tests/subscriptions.test.d.ts +2 -0
  223. package/dist/server/tests/subscriptions.test.d.ts.map +1 -0
  224. package/dist/server/tests/subscriptions.test.js +292 -0
  225. package/dist/server/tests/system-service.test.d.ts +2 -0
  226. package/dist/server/tests/system-service.test.d.ts.map +1 -0
  227. package/dist/server/tests/system-service.test.js +20 -0
  228. package/dist/server/tests/url-routes.test.d.ts +2 -0
  229. package/dist/server/tests/url-routes.test.d.ts.map +1 -0
  230. package/dist/server/tests/url-routes.test.js +217 -0
  231. package/dist/server/tests/web-api.test.d.ts +2 -0
  232. package/dist/server/tests/web-api.test.d.ts.map +1 -0
  233. package/dist/server/tests/web-api.test.js +1759 -0
  234. package/dist/server/web/app.d.ts.map +1 -1
  235. package/dist/server/web/app.js +2 -0
  236. package/dist/server/web/client-error-routes.d.ts +3 -0
  237. package/dist/server/web/client-error-routes.d.ts.map +1 -0
  238. package/dist/server/web/client-error-routes.js +101 -0
  239. package/dist/server/web/system-routes.d.ts.map +1 -1
  240. package/dist/server/web/system-routes.js +21 -131
  241. package/dist/shared/agent-config.d.ts +8 -18
  242. package/dist/shared/agent-config.d.ts.map +1 -1
  243. package/dist/shared/agent-config.js +3 -4
  244. package/dist/shared/inbox.d.ts +27 -0
  245. package/dist/shared/inbox.d.ts.map +1 -1
  246. package/dist/shared/inbox.js +1 -0
  247. package/dist/shared/server-info.d.ts +6 -5
  248. package/dist/shared/server-info.d.ts.map +1 -1
  249. package/dist/shared/server-info.js +3 -1
  250. package/dist/shared/server-settings.d.ts +6 -0
  251. package/dist/shared/server-settings.d.ts.map +1 -1
  252. package/dist/shared/server-settings.js +1 -0
  253. package/dist/shared/skills.d.ts +24 -3
  254. package/dist/shared/skills.d.ts.map +1 -1
  255. package/dist/web/assets/activity-DHjip8tY.js +7 -0
  256. package/dist/web/assets/clipboard-D2NSC52v.js +1 -0
  257. package/dist/web/assets/{external-link-Dt0qTpmV.js → external-link-Bhr1WdRS.js} +1 -1
  258. package/dist/web/assets/{file-text-Dd9ys6py.js → file-text-CYMA_SMA.js} +1 -1
  259. package/dist/web/assets/{index-CzAQnbuO.js → index-CVpew409.js} +5 -5
  260. package/dist/web/assets/index-mh0uJTkY.css +2 -0
  261. package/dist/web/assets/kb-DDVpYkT9.js +35 -0
  262. package/dist/web/assets/profile-CBy6GNzp.js +1 -0
  263. package/dist/web/assets/reminders-Bbwb9QNT.js +1 -0
  264. package/dist/web/favicon.svg +1 -1
  265. package/dist/web/index.html +2 -2
  266. package/package.json +1 -1
  267. package/templates/runtime-standing-prompt.md +16 -2
  268. package/templates/skills/find-skills/SKILL.md +133 -0
  269. package/dist/server/runtime/activity-payload.d.ts.map +0 -1
  270. package/dist/server/runtime/activity-text.d.ts +0 -4
  271. package/dist/server/runtime/activity-text.d.ts.map +0 -1
  272. package/dist/server/runtime/activity-text.js +0 -16
  273. package/dist/server/runtime/managed-runtime.d.ts.map +0 -1
  274. package/dist/server/runtime/provider-contract.d.ts.map +0 -1
  275. package/dist/server/runtime/runtime-release.d.ts.map +0 -1
  276. package/dist/server/runtime/runtime-upgrade.d.ts.map +0 -1
  277. package/dist/server/slack/shortcut.service.d.ts.map +0 -1
  278. package/dist/server/slack/shortcut.service.js +0 -493
  279. package/dist/web/assets/activity-BP0C81IV.js +0 -7
  280. package/dist/web/assets/globe-DmDZSgDP.js +0 -1
  281. package/dist/web/assets/index-DKecrvN0.css +0 -2
  282. package/dist/web/assets/kb-3wFeP2Jt.js +0 -32
  283. package/dist/web/assets/profile-D7wPZXW_.js +0 -1
  284. package/dist/web/assets/reminders-DOhroVwo.js +0 -1
  285. /package/dist/server/{runtime/provider-contract.js → providers/contract.js} +0 -0
  286. /package/dist/server/{runtime → runtime-management}/managed-runtime.d.ts +0 -0
  287. /package/dist/server/{runtime → runtime-management}/managed-runtime.js +0 -0
  288. /package/dist/server/{runtime → runtime-management}/runtime-release.d.ts +0 -0
  289. /package/dist/server/{runtime → runtime-management}/runtime-release.js +0 -0
package/README.md CHANGED
@@ -3,11 +3,16 @@
3
3
  Operator CLI for installing and running Anima from npm.
4
4
 
5
5
  ```bash
6
- npx @meetquinn/animactl start
7
- npx @meetquinn/animactl@canary restart
8
- npx @meetquinn/animactl status
9
- npx @meetquinn/animactl stop
6
+ npx -y @meetquinn/animactl start
7
+ npx -y @meetquinn/animactl dashboard
8
+ npx -y @meetquinn/animactl restart
9
+ npx -y @meetquinn/animactl@canary restart
10
+ npx -y @meetquinn/animactl status
11
+ npx -y @meetquinn/animactl stop
10
12
  ```
11
13
 
12
- This package installs the `@meetquinn/animactl` runtime into `~/.anima/runtime/current` and runs
13
- services from that pinned runtime. Durable Anima data remains in `~/.anima`.
14
+ This package installs the selected `@meetquinn/animactl` runtime into
15
+ `~/.anima/runtime/current` and runs services from that pinned runtime. Durable Anima data remains
16
+ in `~/.anima`. `start` launches the dashboard automatically on a local desktop; use `dashboard` to
17
+ launch it again. Use `restart` for command-line upgrades; with no version suffix, `npx` selects the
18
+ `latest` npm dist-tag.
@@ -1,5 +1,8 @@
1
+ export declare function truncateForActivity(text: string): string;
2
+ export declare function runtimeErrorPayload(error: unknown): Record<string, unknown>;
1
3
  export declare function copyNumber(source: Record<string, unknown> | undefined, target: Record<string, unknown>, from: string, to: string): void;
2
4
  export declare function copyString(source: Record<string, unknown> | undefined, target: Record<string, unknown>, from: string, to: string): void;
3
5
  export declare function copyBoolean(source: Record<string, unknown> | undefined, target: Record<string, unknown>, from: string, to: string): void;
4
6
  export declare function copyActivityPreview(source: Record<string, unknown> | undefined, target: Record<string, unknown>, from: string, to: string): void;
5
- //# sourceMappingURL=activity-payload.d.ts.map
7
+ export declare function isFirstClassAnimaCliCommand(command: string | undefined): boolean;
8
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../server/activities/format.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAI3E;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,IAAI,CAGN;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,IAAI,CAGN;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,IAAI,CAGN;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,IAAI,CAGN;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAOhF"}
@@ -1,4 +1,12 @@
1
- import { truncateForActivity } from './activity-text.js';
1
+ import { errorMessage } from '../ids.js';
2
+ export function truncateForActivity(text) {
3
+ return text.trim().slice(0, 4000);
4
+ }
5
+ export function runtimeErrorPayload(error) {
6
+ return {
7
+ error: truncateForActivity(errorMessage(error)),
8
+ };
9
+ }
2
10
  export function copyNumber(source, target, from, to) {
3
11
  const value = source?.[from];
4
12
  if (typeof value === 'number' && Number.isFinite(value))
@@ -19,3 +27,10 @@ export function copyActivityPreview(source, target, from, to) {
19
27
  if (typeof value === 'string' && value)
20
28
  target[to] = truncateForActivity(value);
21
29
  }
30
+ export function isFirstClassAnimaCliCommand(command) {
31
+ const trimmed = command?.trim();
32
+ if (!trimmed)
33
+ return false;
34
+ const withOptionalEnv = String.raw `(?:[A-Za-z_][A-Za-z0-9_]*=(?:"[^"]*"|'[^']*'|\S+)\s+)*`;
35
+ return new RegExp(String.raw `^${withOptionalEnv}anima\s+(?:ask|message\s+(?:read|send|update|react)|file\s+send|reminder\s+(?:schedule|cancel|snooze|list)|subscription\s+(?:list|mute))\b`).test(trimmed);
36
+ }
@@ -1,4 +1,8 @@
1
- import type { AgentConfig } from '../../shared/agent-config.js';
2
- import type { AgentSkills } from '../../shared/skills.js';
3
- export declare function scanAgentSkills(agent: AgentConfig): Promise<AgentSkills>;
1
+ import type { AgentConfig } from "../../shared/agent-config.js";
2
+ import type { AgentSkills } from "../../shared/skills.js";
3
+ interface SkillScanOptions {
4
+ homeDir?: string;
5
+ }
6
+ export declare function scanAgentSkills(agent: AgentConfig, options?: SkillScanOptions): Promise<AgentSkills>;
7
+ export {};
4
8
  //# sourceMappingURL=agent-skills.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-skills.d.ts","sourceRoot":"","sources":["../../../server/agents/agent-skills.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,wBAAwB,CAAC;AAMxE,wBAAsB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAS9E"}
1
+ {"version":3,"file":"agent-skills.d.ts","sourceRoot":"","sources":["../../../server/agents/agent-skills.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,wBAAwB,CAAC;AAKhC,UAAU,gBAAgB;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuBD,wBAAsB,eAAe,CACnC,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,WAAW,CAAC,CAetB"}
@@ -1,56 +1,253 @@
1
- import { readdir, readFile } from 'node:fs/promises';
2
- import { homedir } from 'node:os';
3
- import { join } from 'node:path';
4
- import { resolveAgentHomePath } from './agent-config-ops.js';
5
- const GLOBAL_AGENTS_SKILLS = join(homedir(), '.agents', 'skills');
6
- const GLOBAL_CODEX_SKILLS = join(homedir(), '.codex', 'skills');
7
- export async function scanAgentSkills(agent) {
8
- const isCodex = agent.provider.kind === 'codex-cli';
9
- const globalPath = isCodex ? GLOBAL_CODEX_SKILLS : GLOBAL_AGENTS_SKILLS;
10
- const localPath = join(resolveAgentHomePath(agent), '.claude', 'skills');
11
- const [global, local] = await Promise.all([
12
- scanSkillDir(globalPath, isCodex),
13
- scanSkillDir(localPath, false),
14
- ]);
15
- return { global, globalPath, local, localPath };
16
- }
17
- async function scanSkillDir(dir, excludeSystem) {
18
- let dirNames;
1
+ import { lstat, readdir, readFile, realpath } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { basename, join, resolve } from "node:path";
4
+ import { resolveAgentHomePath } from "./agent-config-ops.js";
5
+ const PLUGIN_CACHE_MAX_DEPTH = 8;
6
+ export async function scanAgentSkills(agent, options = {}) {
7
+ const roots = skillRoots(options.homeDir ?? homedir());
8
+ const agentHome = resolveAgentHomePath(agent);
9
+ const globalDefinitions = await globalSkillSources(agent, roots);
10
+ const localDefinitions = localSkillSources(agent, agentHome);
11
+ const globalSources = await scanSources(globalDefinitions);
12
+ const localSources = await scanSources(localDefinitions);
13
+ return {
14
+ global: flattenSources(globalSources),
15
+ globalPath: pathSummary(globalSources, globalDefinitions),
16
+ globalSources,
17
+ local: flattenSources(localSources),
18
+ localPath: pathSummary(localSources, localDefinitions),
19
+ localSources,
20
+ };
21
+ }
22
+ function skillRoots(homeDir) {
23
+ return {
24
+ agentsSkills: join(homeDir, ".agents", "skills"),
25
+ claudeInstalledPlugins: join(homeDir, ".claude", "plugins", "installed_plugins.json"),
26
+ claudePluginsCache: join(homeDir, ".claude", "plugins", "cache"),
27
+ claudeSkills: join(homeDir, ".claude", "skills"),
28
+ codexPluginsCache: join(homeDir, ".codex", "plugins", "cache"),
29
+ codexSkills: join(homeDir, ".codex", "skills"),
30
+ codexSystemSkills: join(homeDir, ".codex", "skills", ".system"),
31
+ };
32
+ }
33
+ async function globalSkillSources(agent, roots) {
34
+ if (agent.provider.kind === "codex-cli") {
35
+ return [
36
+ { kind: "common", label: "Common", path: roots.agentsSkills },
37
+ { kind: "provider", label: "Codex", path: roots.codexSkills },
38
+ { kind: "system", label: "Built-in", path: roots.codexSystemSkills },
39
+ {
40
+ kind: "bundled",
41
+ label: "Bundled",
42
+ path: roots.codexPluginsCache,
43
+ scanner: "nested",
44
+ },
45
+ ];
46
+ }
47
+ if (agent.provider.kind === "claude-code") {
48
+ return [
49
+ { kind: "common", label: "Common", path: roots.agentsSkills },
50
+ { kind: "provider", label: "Claude Code", path: roots.claudeSkills },
51
+ ...(await claudeUserPluginSources(roots)),
52
+ ];
53
+ }
54
+ return [{ kind: "common", label: "Common", path: roots.agentsSkills }];
55
+ }
56
+ function localSkillSources(agent, agentHome) {
57
+ const common = {
58
+ kind: "local",
59
+ label: "Agent",
60
+ path: join(agentHome, ".agents", "skills"),
61
+ };
62
+ if (agent.provider.kind === "codex-cli") {
63
+ return [
64
+ common,
65
+ {
66
+ kind: "local",
67
+ label: "Agent Codex",
68
+ path: join(agentHome, ".codex", "skills"),
69
+ },
70
+ ];
71
+ }
72
+ if (agent.provider.kind === "claude-code") {
73
+ return [
74
+ common,
75
+ {
76
+ kind: "local",
77
+ label: "Agent Claude Code",
78
+ path: join(agentHome, ".claude", "skills"),
79
+ },
80
+ ];
81
+ }
82
+ return [common];
83
+ }
84
+ async function claudeUserPluginSources(roots) {
85
+ const installed = await readJsonFile(roots.claudeInstalledPlugins);
86
+ if (!isRecord(installed) || !isRecord(installed["plugins"]))
87
+ return [];
88
+ const sources = [];
89
+ for (const [pluginId, installs] of Object.entries(installed["plugins"])) {
90
+ if (!Array.isArray(installs))
91
+ continue;
92
+ for (const install of installs) {
93
+ if (!isRecord(install))
94
+ continue;
95
+ if (install["scope"] !== "user")
96
+ continue;
97
+ const installPath = stringValue(install["installPath"]);
98
+ if (!installPath)
99
+ continue;
100
+ sources.push({
101
+ kind: "provider",
102
+ label: pluginLabel(pluginId, "Claude plugin"),
103
+ path: installPath,
104
+ scanner: "nested",
105
+ });
106
+ }
107
+ }
108
+ return sources;
109
+ }
110
+ function pluginLabel(pluginId, fallback) {
111
+ const [name] = pluginId.split("@");
112
+ return name ? name : fallback;
113
+ }
114
+ async function scanSources(definitions) {
115
+ const seenRealPaths = new Set();
116
+ const sources = [];
117
+ for (const definition of definitions) {
118
+ const results = definition.scanner === "nested"
119
+ ? await scanNestedSkillDirs(definition, seenRealPaths)
120
+ : await scanTopLevelSkillDir(definition, seenRealPaths);
121
+ sources.push({
122
+ kind: definition.kind,
123
+ label: definition.label,
124
+ path: definition.path,
125
+ skills: results.map(stripInternalFields),
126
+ });
127
+ }
128
+ return sources;
129
+ }
130
+ async function scanTopLevelSkillDir(definition, seenRealPaths) {
131
+ let entries;
19
132
  try {
20
- const entries = await readdir(dir, { withFileTypes: true });
21
- dirNames = entries
22
- .filter((entry) => {
23
- if (!entry.isDirectory())
24
- return false;
25
- if (excludeSystem && entry.name === '.system')
26
- return false;
27
- if (entry.name.startsWith('.'))
28
- return false;
29
- return true;
30
- })
31
- .map((entry) => entry.name)
32
- .sort();
133
+ entries = await readdir(definition.path, { withFileTypes: true });
33
134
  }
34
135
  catch {
35
136
  return [];
36
137
  }
37
- const results = await Promise.all(dirNames.map((dirName) => readSkill(dir, dirName)));
138
+ const dirNames = [];
139
+ for (const entry of entries) {
140
+ if (entry.name.startsWith("."))
141
+ continue;
142
+ if (entry.isDirectory()) {
143
+ dirNames.push(entry.name);
144
+ continue;
145
+ }
146
+ if (!entry.isSymbolicLink())
147
+ continue;
148
+ try {
149
+ const linkTarget = await lstat(join(definition.path, entry.name));
150
+ if (linkTarget.isSymbolicLink())
151
+ dirNames.push(entry.name);
152
+ }
153
+ catch {
154
+ // Ignore broken links.
155
+ }
156
+ }
157
+ const results = await Promise.all(dirNames
158
+ .sort()
159
+ .map((dirName) => readSkill(join(definition.path, dirName), dirName, definition, seenRealPaths)));
38
160
  return results.filter((skill) => skill !== null);
39
161
  }
40
- async function readSkill(base, dirName) {
162
+ async function scanNestedSkillDirs(definition, seenRealPaths) {
163
+ const dirs = await findSkillDirs(definition.path, definition.scanner === "nested" ? PLUGIN_CACHE_MAX_DEPTH : 3);
164
+ const results = await Promise.all(dirs.map((dir) => readSkill(dir, basename(dir), definition, seenRealPaths)));
165
+ return results
166
+ .filter((skill) => skill !== null)
167
+ .sort((left, right) => left.name.localeCompare(right.name));
168
+ }
169
+ async function findSkillDirs(root, maxDepth) {
170
+ const results = [];
171
+ async function walk(dir, depth) {
172
+ if (depth > maxDepth)
173
+ return;
174
+ let entries;
175
+ try {
176
+ entries = await readdir(dir, { withFileTypes: true });
177
+ }
178
+ catch {
179
+ return;
180
+ }
181
+ if (entries.some((entry) => entry.isFile() && entry.name === "SKILL.md")) {
182
+ results.push(dir);
183
+ return;
184
+ }
185
+ await Promise.all(entries.map(async (entry) => {
186
+ if (!entry.isDirectory())
187
+ return;
188
+ if (entry.name === "node_modules")
189
+ return;
190
+ await walk(join(dir, entry.name), depth + 1);
191
+ }));
192
+ }
193
+ await walk(root, 0);
194
+ return results;
195
+ }
196
+ async function readSkill(skillDir, dirName, source, seenRealPaths) {
41
197
  try {
42
- const content = await readFile(join(base, dirName, 'SKILL.md'), 'utf8');
198
+ const [content, resolvedPath] = await Promise.all([
199
+ readFile(join(skillDir, "SKILL.md"), "utf8"),
200
+ realpath(skillDir),
201
+ ]);
202
+ if (seenRealPaths.has(resolvedPath))
203
+ return null;
204
+ seenRealPaths.add(resolvedPath);
43
205
  const frontmatter = parseSkillFrontmatter(content);
44
206
  return {
45
207
  dirName,
46
208
  name: frontmatter.name ?? dirName,
47
- ...(frontmatter.description ? { description: frontmatter.description } : {}),
209
+ realPath: resolvedPath,
210
+ sourceKind: source.kind,
211
+ sourceLabel: source.label,
212
+ sourcePath: skillDir,
213
+ ...(frontmatter.description
214
+ ? { description: frontmatter.description }
215
+ : {}),
48
216
  };
49
217
  }
50
218
  catch {
51
219
  return null;
52
220
  }
53
221
  }
222
+ function stripInternalFields(skill) {
223
+ const { realPath: _realPath, ...summary } = skill;
224
+ return summary;
225
+ }
226
+ function flattenSources(sources) {
227
+ return sources.flatMap((source) => source.skills);
228
+ }
229
+ function pathSummary(sources, definitions) {
230
+ const pathsWithSkills = sources
231
+ .filter((source) => source.skills.length > 0)
232
+ .map((source) => source.path);
233
+ return (pathsWithSkills.length > 0
234
+ ? pathsWithSkills
235
+ : definitions.map((definition) => definition.path)).join(", ");
236
+ }
237
+ async function readJsonFile(path) {
238
+ try {
239
+ return JSON.parse(await readFile(path, "utf8"));
240
+ }
241
+ catch {
242
+ return undefined;
243
+ }
244
+ }
245
+ function isRecord(value) {
246
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
247
+ }
248
+ function stringValue(value) {
249
+ return typeof value === "string" && value.trim() ? resolve(value) : undefined;
250
+ }
54
251
  function parseSkillFrontmatter(content) {
55
252
  const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
56
253
  if (!match)
@@ -61,11 +258,19 @@ function parseSkillFrontmatter(content) {
61
258
  if (!keyValue)
62
259
  continue;
63
260
  const key = keyValue[1];
64
- const value = keyValue[2].trim();
65
- if (key === 'description' && value)
261
+ const value = normalizeFrontmatterValue(keyValue[2].trim());
262
+ if (key === "description" && value)
66
263
  result.description = value;
67
- if (key === 'name' && value)
264
+ if (key === "name" && value)
68
265
  result.name = value;
69
266
  }
70
267
  return result;
71
268
  }
269
+ function normalizeFrontmatterValue(value) {
270
+ if (value.length < 2)
271
+ return value;
272
+ const quote = value[0];
273
+ if ((quote !== '"' && quote !== "'") || value[value.length - 1] !== quote)
274
+ return value;
275
+ return value.slice(1, -1);
276
+ }
@@ -10,6 +10,21 @@ export declare class AgentSlackService {
10
10
  getManifestUpdateInfo(): Promise<AgentSlackManifestUpdateInfo>;
11
11
  upgradeManifestVersion(input: AgentSlackManifestUpgradeRequest): Promise<AgentConfig>;
12
12
  syncDisplayInfo(): Promise<AgentConfig>;
13
+ /**
14
+ * Refresh the bot's Slack display info (avatar, name, workspace icon) at most
15
+ * once per `ttlMs`, stamping `slack.botProfileSyncedAt`. When the last sync is
16
+ * still fresh this is a cheap no-op — it reads the local config only and makes
17
+ * NO Slack API calls. Best-effort: callers run it fire-and-forget off the
18
+ * message path and swallow errors. Pass an existing `client` to reuse the
19
+ * inbound request's WebClient instead of building a new one.
20
+ */
21
+ syncDisplayInfoIfStale(options: {
22
+ client?: WebClient;
23
+ ttlMs: number;
24
+ }): Promise<{
25
+ synced: boolean;
26
+ }>;
27
+ private persistDisplayInfo;
13
28
  getWebClient(): Promise<WebClient>;
14
29
  getAgentWebClient(): Promise<{
15
30
  agent: AgentConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-slack.service.d.ts","sourceRoot":"","sources":["../../../server/agents/agent-slack.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACxB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,gCAAgC,EACtC,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAoBlD,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,EAAE,YAAY;IAGjD,cAAc,CAClB,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,0BAA0B,CAAC;IAIhC,OAAO,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,WAAW,CAAC;IAwB9D,qBAAqB,IAAI,OAAO,CAAC,4BAA4B,CAAC;IAgB9D,sBAAsB,CAC1B,KAAK,EAAE,gCAAgC,GACtC,OAAO,CAAC,WAAW,CAAC;IAoCjB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC;IAcvC,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC;IAIlC,iBAAiB,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,CAAC;IAK7E,OAAO,CAAC,iBAAiB;IAInB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAK/C,SAAS,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAK1C,QAAQ,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC;IAkB3D,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;YAMxB,2BAA2B;CAqD1C;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAE5E"}
1
+ {"version":3,"file":"agent-slack.service.d.ts","sourceRoot":"","sources":["../../../server/agents/agent-slack.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACxB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,gCAAgC,EACtC,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAoBlD,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,EAAE,YAAY;IAGjD,cAAc,CAClB,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,0BAA0B,CAAC;IAIhC,OAAO,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,WAAW,CAAC;IAwB9D,qBAAqB,IAAI,OAAO,CAAC,4BAA4B,CAAC;IAgB9D,sBAAsB,CAC1B,KAAK,EAAE,gCAAgC,GACtC,OAAO,CAAC,WAAW,CAAC;IAoCjB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC;IAI7C;;;;;;;OAOG;IACG,sBAAsB,CAAC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;YAS5F,kBAAkB;IAuB1B,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC;IAIlC,iBAAiB,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,CAAC;IAK7E,OAAO,CAAC,iBAAiB;IAInB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAK/C,SAAS,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAK1C,QAAQ,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC;IAkB3D,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;YAMxB,2BAA2B;CAqD1C;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAE5E"}
@@ -87,15 +87,42 @@ export class AgentSlackService {
87
87
  });
88
88
  }
89
89
  async syncDisplayInfo() {
90
+ return this.persistDisplayInfo(await getSlackDisplayInfo(await this.getWebClient()));
91
+ }
92
+ /**
93
+ * Refresh the bot's Slack display info (avatar, name, workspace icon) at most
94
+ * once per `ttlMs`, stamping `slack.botProfileSyncedAt`. When the last sync is
95
+ * still fresh this is a cheap no-op — it reads the local config only and makes
96
+ * NO Slack API calls. Best-effort: callers run it fire-and-forget off the
97
+ * message path and swallow errors. Pass an existing `client` to reuse the
98
+ * inbound request's WebClient instead of building a new one.
99
+ */
100
+ async syncDisplayInfoIfStale(options) {
90
101
  const agent = await this.agentService.getConfig();
91
- const info = await getSlackDisplayInfo(await this.getWebClient());
92
- const appId = info.appId ?? appIdFromAppToken(agent.slack.appToken);
102
+ if (!agent.slack.botToken)
103
+ return { synced: false };
104
+ if (isWithinTtl(agent.slack.botProfileSyncedAt, options.ttlMs))
105
+ return { synced: false };
106
+ const client = options.client ?? this.webClientForAgent(agent);
107
+ await this.persistDisplayInfo(await getSlackDisplayInfo(client), nowIso());
108
+ return { synced: true };
109
+ }
110
+ async persistDisplayInfo(info, botProfileSyncedAt) {
111
+ // Re-read the latest config AFTER the (slow) Slack API calls, then merge in
112
+ // only the display fields. The automatic on-message refresh runs fire-and-
113
+ // forget, so an operator could edit config in the dashboard while a sync is
114
+ // in flight — saving a pre-call snapshot here would silently clobber that
115
+ // edit. Reading now closes the seconds-long network window; the residual
116
+ // sub-call window matches every other AgentService mutator.
117
+ const latest = await this.agentService.getConfig();
118
+ const appId = info.appId ?? appIdFromAppToken(latest.slack.appToken);
93
119
  return this.agentService.saveConfig({
94
- ...agent,
120
+ ...latest,
95
121
  slack: {
96
- ...agent.slack,
122
+ ...latest.slack,
97
123
  ...info,
98
124
  ...(appId ? { appId } : {}),
125
+ ...(botProfileSyncedAt ? { botProfileSyncedAt } : {}),
99
126
  },
100
127
  });
101
128
  }
@@ -151,7 +178,7 @@ export class AgentSlackService {
151
178
  throw new AgentConfigError(502, `Slack did not return a DM channel for ${owner.slackUserId}`);
152
179
  const mention = `<@${owner.slackUserId}>`;
153
180
  const ownerName = owner.displayName?.trim()
154
- || operatorHandleLabel(owner.handle)
181
+ || ownerHandleLabel(owner.handle)
155
182
  || mention;
156
183
  const now = nowIso();
157
184
  const textLines = [
@@ -184,13 +211,23 @@ export class AgentSlackService {
184
211
  export function agentSlackServiceForAgent(agentId) {
185
212
  return new AgentSlackService(new AgentService(agentId));
186
213
  }
214
+ // True when `iso` is a valid timestamp within `ttlMs` of now. Unset/unparseable
215
+ // timestamps and a non-positive ttl are treated as stale so a sync still runs.
216
+ function isWithinTtl(iso, ttlMs) {
217
+ if (!iso || ttlMs <= 0)
218
+ return false;
219
+ const then = Date.parse(iso);
220
+ if (Number.isNaN(then))
221
+ return false;
222
+ return Date.now() - then < ttlMs;
223
+ }
187
224
  function requireBotToken(agent) {
188
225
  const token = agent.slack.botToken;
189
226
  if (!token)
190
227
  throw new AgentConfigError(400, `Agent ${agent.id} has no bot token configured`);
191
228
  return token;
192
229
  }
193
- function operatorHandleLabel(handle) {
230
+ function ownerHandleLabel(handle) {
194
231
  const trimmed = handle?.trim();
195
232
  if (!trimmed)
196
233
  return undefined;
@@ -0,0 +1,9 @@
1
+ export interface EnsureDefaultSkillsOptions {
2
+ homeDir?: string;
3
+ }
4
+ export interface EnsureDefaultSkillsResult {
5
+ claudeLinkInstalled: boolean;
6
+ commonSkillInstalled: boolean;
7
+ }
8
+ export declare function ensureDefaultSkills(options?: EnsureDefaultSkillsOptions): Promise<EnsureDefaultSkillsResult>;
9
+ //# sourceMappingURL=default-skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-skills.d.ts","sourceRoot":"","sources":["../../../server/agents/default-skills.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,yBAAyB;IACxC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,yBAAyB,CAAC,CAMpC"}
@@ -0,0 +1,52 @@
1
+ import { lstat, mkdir, rm, stat, symlink, writeFile } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { dirname, join, relative } from 'node:path';
4
+ import { readBundledTemplate } from '../bundled-templates.js';
5
+ import { isMissingFile } from '../storage/json-file.js';
6
+ const FIND_SKILLS_DIR = 'find-skills';
7
+ const FIND_SKILLS_TEMPLATE = 'skills/find-skills/SKILL.md';
8
+ export async function ensureDefaultSkills(options = {}) {
9
+ const homeDir = options.homeDir ?? homedir();
10
+ const commonSkillDir = join(homeDir, '.agents', 'skills', FIND_SKILLS_DIR);
11
+ const commonSkillInstalled = await ensureFindSkills(commonSkillDir);
12
+ const claudeLinkInstalled = await ensureClaudeFindSkillsLink(homeDir, commonSkillDir);
13
+ return { claudeLinkInstalled, commonSkillInstalled };
14
+ }
15
+ async function ensureFindSkills(skillDir) {
16
+ const skillPath = join(skillDir, 'SKILL.md');
17
+ if (await pathExists(skillPath))
18
+ return false;
19
+ await mkdir(skillDir, { recursive: true });
20
+ await writeFile(skillPath, await readBundledTemplate(FIND_SKILLS_TEMPLATE), 'utf8');
21
+ return true;
22
+ }
23
+ async function ensureClaudeFindSkillsLink(homeDir, commonSkillDir) {
24
+ const claudeSkillPath = join(homeDir, '.claude', 'skills', FIND_SKILLS_DIR);
25
+ const existing = await lstat(claudeSkillPath).catch((error) => {
26
+ if (isMissingFile(error))
27
+ return undefined;
28
+ throw error;
29
+ });
30
+ if (existing) {
31
+ if (existing.isSymbolicLink() && !(await pathExists(claudeSkillPath))) {
32
+ await rm(claudeSkillPath, { force: true });
33
+ }
34
+ else {
35
+ return false;
36
+ }
37
+ }
38
+ await mkdir(dirname(claudeSkillPath), { recursive: true });
39
+ await symlink(relative(dirname(claudeSkillPath), commonSkillDir), claudeSkillPath, 'dir');
40
+ return true;
41
+ }
42
+ async function pathExists(path) {
43
+ try {
44
+ await stat(path);
45
+ return true;
46
+ }
47
+ catch (error) {
48
+ if (isMissingFile(error))
49
+ return false;
50
+ throw error;
51
+ }
52
+ }
@@ -1,5 +1,5 @@
1
1
  import type { Command } from 'commander';
2
- import { type RuntimeInstallOptions, type RuntimeStatus } from '../runtime/managed-runtime.js';
2
+ import { type RuntimeInstallOptions, type RuntimeStatus } from '../runtime-management/managed-runtime.js';
3
3
  import { type RuntimeUpgradeStatusResponse } from '../../shared/runtime-upgrade.js';
4
4
  interface RuntimeCliOptions {
5
5
  channel?: string;
@@ -10,6 +10,7 @@ interface RuntimeCliOptions {
10
10
  idleTimeoutMs?: number;
11
11
  logPath?: string;
12
12
  npm?: string;
13
+ browser?: boolean;
13
14
  only?: 'agent' | 'web';
14
15
  packageName?: string;
15
16
  previousStartedAt?: string;
@@ -29,5 +30,10 @@ export declare function runtimeInstallOptions(options: RuntimeCliOptions, defaul
29
30
  }): RuntimeInstallOptions;
30
31
  export declare function printRuntimeStatus(status: RuntimeStatus): void;
31
32
  export declare function printUpgradeStatus(status: RuntimeUpgradeStatusResponse): void;
33
+ export declare function dashboardUrl(host: string, port: number): string;
34
+ export declare function dashboardLaunchCommand(url: string, platform: NodeJS.Platform): {
35
+ command: string;
36
+ args: string[];
37
+ };
32
38
  export {};
33
39
  //# sourceMappingURL=runtime-cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-cli.d.ts","sourceRoot":"","sources":["../../../server/cli/runtime-cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,OAAO,EAOL,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EACnB,MAAM,+BAA+B,CAAC;AAMvC,OAAO,EAAuB,KAAK,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AAEzG,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAID,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAK7D;AAED,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAMtE;AA6HD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO,GAClE,qBAAqB,CAQvB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAc9D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,4BAA4B,GAAG,IAAI,CAgB7E"}
1
+ {"version":3,"file":"runtime-cli.d.ts","sourceRoot":"","sources":["../../../server/cli/runtime-cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,OAAO,EAOL,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EACnB,MAAM,0CAA0C,CAAC;AAMlD,OAAO,EAAuB,KAAK,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AAEzG,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAID,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAK7D;AAED,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAMtE;AAqID,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO,GAClE,qBAAqB,CAQvB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAc9D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,4BAA4B,GAAG,IAAI,CAgB7E;AAuGD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/D;AA4CD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAIlH"}