@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
@@ -0,0 +1,217 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { AGENT_TABS, DEFAULT_TAB, buildPath, buildKbPath, buildKbRawPath, parseLocation, parseKbPath, reconcileLocation, } from '../../shared/url-routes.js';
4
+ // ---------------------------------------------------------------------------
5
+ // parseLocation
6
+ // ---------------------------------------------------------------------------
7
+ test('parseLocation: bare `/` yields nulls', () => {
8
+ assert.deepEqual(parseLocation('/'), { agentId: null, tab: null });
9
+ assert.deepEqual(parseLocation(''), { agentId: null, tab: null });
10
+ });
11
+ test('parseLocation: `/agents/<id>` yields agentId with null tab (bootstrap canonicalizes)', () => {
12
+ assert.deepEqual(parseLocation('/agents/nora'), { agentId: 'nora', tab: null });
13
+ });
14
+ test('parseLocation: `/agents/<id>/<tab>` parses each known tab', () => {
15
+ for (const tab of AGENT_TABS) {
16
+ assert.deepEqual(parseLocation(`/agents/iris/${tab}`), { agentId: 'iris', tab });
17
+ }
18
+ });
19
+ test('parseLocation: unknown tab keeps agentId, returns tab=null so reconcile fills DEFAULT_TAB', () => {
20
+ assert.deepEqual(parseLocation('/agents/nora/garbage'), { agentId: 'nora', tab: null });
21
+ });
22
+ test('parseLocation: non-agents prefix or extra segments → reset to nulls', () => {
23
+ assert.deepEqual(parseLocation('/settings'), { agentId: null, tab: null });
24
+ assert.deepEqual(parseLocation('/agents'), { agentId: null, tab: null });
25
+ assert.deepEqual(parseLocation('/agents/nora/activity/extra'), { agentId: null, tab: null });
26
+ });
27
+ // ---------------------------------------------------------------------------
28
+ // buildPath (round-trip)
29
+ // ---------------------------------------------------------------------------
30
+ test('buildPath: null agentId → `/`', () => {
31
+ assert.equal(buildPath({ agentId: null, tab: null }), '/');
32
+ assert.equal(buildPath({ agentId: null, tab: 'activity' }), '/');
33
+ });
34
+ test('buildPath: agentId + tab round-trips through parseLocation', () => {
35
+ for (const tab of AGENT_TABS) {
36
+ const path = buildPath({ agentId: 'milo', tab });
37
+ assert.equal(path, `/agents/milo/${tab}`);
38
+ assert.deepEqual(parseLocation(path), { agentId: 'milo', tab });
39
+ }
40
+ });
41
+ test('buildPath: agentId with no tab emits the canonical-pending form', () => {
42
+ assert.equal(buildPath({ agentId: 'milo', tab: null }), '/agents/milo');
43
+ });
44
+ // ---------------------------------------------------------------------------
45
+ // reconcileLocation — covers iris's 7 routing cases
46
+ // ---------------------------------------------------------------------------
47
+ // All agents in SNAPSHOT are connected (slack.connected = true) — the normal case.
48
+ // Tokens are always redacted to "" on the wire; slack.connected is the durable signal.
49
+ const CONNECTED = { connected: true };
50
+ const SNAPSHOT = {
51
+ agents: [
52
+ { id: 'anima', slack: CONNECTED },
53
+ { id: 'iris', slack: CONNECTED },
54
+ { id: 'milo', slack: CONNECTED },
55
+ { id: 'nora', slack: CONNECTED },
56
+ ],
57
+ agentStatuses: [
58
+ { agentId: 'anima', queueDepth: 0 },
59
+ { agentId: 'iris', queueDepth: 0 },
60
+ { agentId: 'milo', currentItemId: 'turn_active', queueDepth: 0 },
61
+ { agentId: 'nora', queueDepth: 0 },
62
+ ],
63
+ selectedAgentId: 'iris',
64
+ };
65
+ test('reconcileLocation: bare `/` picks the currently-running agent and fills DEFAULT_TAB', () => {
66
+ assert.deepEqual(reconcileLocation(SNAPSHOT, { agentId: null, tab: null }), { agentId: 'milo', tab: DEFAULT_TAB });
67
+ });
68
+ test('reconcileLocation: bare `/` falls back to selectedAgentId when nobody is running', () => {
69
+ const idle = {
70
+ ...SNAPSHOT,
71
+ agentStatuses: SNAPSHOT.agentStatuses.map((s) => ({ agentId: s.agentId, queueDepth: 0 })),
72
+ };
73
+ assert.deepEqual(reconcileLocation(idle, { agentId: null, tab: null }), { agentId: 'iris', tab: DEFAULT_TAB });
74
+ });
75
+ test('reconcileLocation: bare `/` falls back to first agent when no selection hint exists', () => {
76
+ const minimal = {
77
+ agents: [{ id: 'anima', slack: CONNECTED }, { id: 'nora', slack: CONNECTED }],
78
+ agentStatuses: [],
79
+ };
80
+ assert.deepEqual(reconcileLocation(minimal, { agentId: null, tab: null }), { agentId: 'anima', tab: DEFAULT_TAB });
81
+ });
82
+ test('reconcileLocation: `/agents/<id>` (no tab) canonicalizes to DEFAULT_TAB', () => {
83
+ assert.deepEqual(reconcileLocation(SNAPSHOT, { agentId: 'nora', tab: null }), { agentId: 'nora', tab: DEFAULT_TAB });
84
+ });
85
+ test('reconcileLocation: each `/agents/<id>/<tab>` triple is left alone (no-op)', () => {
86
+ for (const tab of AGENT_TABS) {
87
+ assert.equal(reconcileLocation(SNAPSHOT, { agentId: 'nora', tab }), null, `tab ${tab} should be a no-op`);
88
+ }
89
+ });
90
+ test('reconcileLocation: unknown agentId is left alone for the view-level not-found state', () => {
91
+ assert.equal(reconcileLocation(SNAPSHOT, { agentId: 'ghost', tab: 'profile' }), null);
92
+ });
93
+ test('reconcileLocation: parseLocation already maps unknown tab → null, then reconcile fills DEFAULT_TAB', () => {
94
+ // End-to-end: pathname → parseLocation → reconcile → final URL state.
95
+ const parsed = parseLocation('/agents/nora/garbage');
96
+ assert.deepEqual(parsed, { agentId: 'nora', tab: null });
97
+ assert.deepEqual(reconcileLocation(SNAPSHOT, parsed), { agentId: 'nora', tab: DEFAULT_TAB });
98
+ });
99
+ test('reconcileLocation: returns null when there are no agents at all (nothing to pick)', () => {
100
+ const empty = { agents: [], agentStatuses: [] };
101
+ assert.equal(reconcileLocation(empty, { agentId: null, tab: null }), null);
102
+ });
103
+ // ---------------------------------------------------------------------------
104
+ // Not-connected agents: activity redirects to profile (no kbName).
105
+ // ---------------------------------------------------------------------------
106
+ const NC_SNAPSHOT = {
107
+ agents: [
108
+ { id: 'anima', slack: CONNECTED },
109
+ { id: 'new-agent' }, // no slack object → slack.connected !== true → not-connected
110
+ ],
111
+ agentStatuses: [
112
+ { agentId: 'anima', queueDepth: 0 },
113
+ { agentId: 'new-agent', queueDepth: 0 },
114
+ ],
115
+ selectedAgentId: 'anima',
116
+ };
117
+ test('reconcileLocation: not-connected + null tab → profile', () => {
118
+ assert.deepEqual(reconcileLocation(NC_SNAPSHOT, { agentId: 'new-agent', tab: null }), { agentId: 'new-agent', tab: 'profile' });
119
+ });
120
+ test('reconcileLocation: not-connected + activity tab → no-op (explicit nav respected)', () => {
121
+ // Sidebar navigates to /agents/:id (no tab), so this branch is only reached
122
+ // via an explicit in-page tab click — which should not be overridden.
123
+ assert.equal(reconcileLocation(NC_SNAPSHOT, { agentId: 'new-agent', tab: 'activity' }), null);
124
+ });
125
+ test('reconcileLocation: not-connected + profile tab → no-op', () => {
126
+ assert.equal(reconcileLocation(NC_SNAPSHOT, { agentId: 'new-agent', tab: 'profile' }), null);
127
+ });
128
+ test('reconcileLocation: not-connected + reminders tab → no-op (explicit nav respected)', () => {
129
+ assert.equal(reconcileLocation(NC_SNAPSHOT, { agentId: 'new-agent', tab: 'reminders' }), null);
130
+ });
131
+ test('reconcileLocation: auto-pick of not-connected agent → profile tab', () => {
132
+ // When auto-selecting and the picked agent has no kbName.
133
+ const ncOnly = {
134
+ agents: [{ id: 'new-agent' }],
135
+ agentStatuses: [{ agentId: 'new-agent', queueDepth: 0 }],
136
+ };
137
+ assert.deepEqual(reconcileLocation(ncOnly, { agentId: null, tab: null }), { agentId: 'new-agent', tab: 'profile' });
138
+ });
139
+ test('reconcileLocation: connected agent activity is left alone (no-op)', () => {
140
+ assert.equal(reconcileLocation(NC_SNAPSHOT, { agentId: 'anima', tab: 'activity' }), null);
141
+ });
142
+ // ---------------------------------------------------------------------------
143
+ // Kb surface: parse / build / raw-url
144
+ // ---------------------------------------------------------------------------
145
+ test('parseKbPath: non-kb paths return null (fall back to agent routing)', () => {
146
+ assert.equal(parseKbPath('/'), null);
147
+ assert.equal(parseKbPath('/agents/nora/activity'), null);
148
+ assert.equal(parseKbPath('/settings'), null);
149
+ });
150
+ test('parseKbPath: bare /kb selects no kb', () => {
151
+ assert.deepEqual(parseKbPath('/kb'), { id: null, filePath: null });
152
+ });
153
+ test('parseKbPath: /kb/<id> opens a kb with no file', () => {
154
+ assert.deepEqual(parseKbPath('/kb/team'), { id: 'team', filePath: null });
155
+ });
156
+ test('parseKbPath: /kb/<id>/<file> parses a nested repo-relative path', () => {
157
+ assert.deepEqual(parseKbPath('/kb/team/prds/team-kb-web-view.md'), {
158
+ id: 'team',
159
+ filePath: 'prds/team-kb-web-view.md',
160
+ });
161
+ });
162
+ test('parseKbPath: percent-encoded segments are decoded', () => {
163
+ assert.deepEqual(parseKbPath('/kb/content-team/notes/a%20b.md'), {
164
+ id: 'content-team',
165
+ filePath: 'notes/a b.md',
166
+ });
167
+ });
168
+ test('parseKbPath: the raw backend route is not a browse target', () => {
169
+ assert.equal(parseKbPath('/kb/raw/team/docs/report.html'), null);
170
+ });
171
+ test('buildKbPath: round-trips through parseKbPath', () => {
172
+ const cases = [
173
+ { id: null, filePath: null, expected: '/kb' },
174
+ { id: 'team', filePath: null, expected: '/kb/team' },
175
+ { id: 'team', filePath: 'prds/x.md', expected: '/kb/team/prds/x.md' },
176
+ ];
177
+ for (const { id, filePath, expected } of cases) {
178
+ const path = buildKbPath({ id, filePath });
179
+ assert.equal(path, expected);
180
+ assert.deepEqual(parseKbPath(path), { id, filePath });
181
+ }
182
+ });
183
+ test('buildKbPath: encodes spaces per segment, keeping slashes literal', () => {
184
+ assert.equal(buildKbPath({ id: 'content-team', filePath: 'notes/a b.md' }), '/kb/content-team/notes/a%20b.md');
185
+ });
186
+ test('buildKbRawPath: emits the backend raw route with per-segment encoding', () => {
187
+ assert.equal(buildKbRawPath('team', 'docs/report.html'), '/kb/raw/team/docs/report.html');
188
+ assert.equal(buildKbRawPath('content-team', 'a b/c.css'), '/kb/raw/content-team/a%20b/c.css');
189
+ });
190
+ // ---------------------------------------------------------------------------
191
+ // Integration: simulate the user-facing scenarios iris listed as a regression
192
+ // table (parseLocation → reconcile → buildPath round-trip).
193
+ // ---------------------------------------------------------------------------
194
+ test('routing table: every input path lands on the canonical pathname iris specified', () => {
195
+ const cases = [
196
+ { input: '/', expected: '/agents/milo/activity', note: 'bare root → most-recently-active' },
197
+ { input: '/agents/nora', expected: '/agents/nora/activity', note: 'no tab → DEFAULT_TAB' },
198
+ { input: '/agents/nora/activity', expected: '/agents/nora/activity', note: 'activity stays' },
199
+ { input: '/agents/nora/profile', expected: '/agents/nora/profile', note: 'profile stays' },
200
+ { input: '/agents/nora/reminders', expected: '/agents/nora/reminders', note: 'reminders stays' },
201
+ { input: '/agents/ghost/profile', expected: '/agents/ghost/profile', note: 'unknown id → view-level not-found' },
202
+ { input: '/agents/nora/garbage', expected: '/agents/nora/activity', note: 'unknown tab → DEFAULT_TAB' },
203
+ ];
204
+ for (const { input, expected, note } of cases) {
205
+ let parsed = parseLocation(input);
206
+ // Run reconcile up to twice so redirects can settle when a URL canonicalizes
207
+ // through an intermediate state.
208
+ for (let i = 0; i < 2; i++) {
209
+ const target = reconcileLocation(SNAPSHOT, parsed);
210
+ if (!target)
211
+ break;
212
+ parsed = target;
213
+ }
214
+ const finalPath = buildPath(parsed);
215
+ assert.equal(finalPath, expected, `${input} → ${expected} (${note})`);
216
+ }
217
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=web-api.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-api.test.d.ts","sourceRoot":"","sources":["../../../server/tests/web-api.test.ts"],"names":[],"mappings":""}