aimeat 1.27.1 → 1.28.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 (291) hide show
  1. package/dist/locales/en.json +67 -3
  2. package/dist/locales/fi.json +67 -3
  3. package/dist/public/components/NotificationBell.js +2 -4
  4. package/dist/public/css/views/agents-detail.css +11 -0
  5. package/dist/public/css/views/inbox.css +49 -1
  6. package/dist/public/css/views/profile.css +36 -0
  7. package/dist/public/js/presence-store.js +7 -1
  8. package/dist/public/js/services/agents.js +10 -3
  9. package/dist/public/js/services/living.js +1 -1
  10. package/dist/public/js/services/memory.js +23 -3
  11. package/dist/public/js/services/nodes.js +1 -1
  12. package/dist/public/js/services/notebook-plan.js +1 -1
  13. package/dist/public/js/services/notebook.js +25 -77
  14. package/dist/public/js/services/organisms.js +31 -0
  15. package/dist/public/js/services/tracked-responses.js +28 -4
  16. package/dist/public/lib/live-updates.js +231 -94
  17. package/dist/public/spa.html +4 -1
  18. package/dist/public/views/admin/agent-integration-tab.js +2 -5
  19. package/dist/public/views/admin/agent-tasks-tab.js +2 -5
  20. package/dist/public/views/admin/cortex-tab.js +2 -5
  21. package/dist/public/views/admin/federation-tab.js +3 -10
  22. package/dist/public/views/admin/memory-tab.js +2 -5
  23. package/dist/public/views/admin/messages-tab.js +2 -5
  24. package/dist/public/views/admin/packages-tab.js +2 -5
  25. package/dist/public/views/admin/sharing-groups-tab.js +2 -5
  26. package/dist/public/views/landing-node-totals.js +3 -3
  27. package/dist/public/views/profile/agents/agent-card.js +8 -5
  28. package/dist/public/views/profile/agents/tab-activity.js +2 -3
  29. package/dist/public/views/profile/agents/tab-agent-config.js +2 -3
  30. package/dist/public/views/profile/agents/tab-data-access.js +2 -3
  31. package/dist/public/views/profile/agents/tab-integration.js +2 -3
  32. package/dist/public/views/profile/agents/tab-messages.js +2 -6
  33. package/dist/public/views/profile/agents/tab-quality.js +2 -5
  34. package/dist/public/views/profile/agents/tab-schedules.js +2 -4
  35. package/dist/public/views/profile/agents-activity-subtab.js +2 -5
  36. package/dist/public/views/profile/agents-capabilities-subtab.js +2 -2
  37. package/dist/public/views/profile/agents-messages-subtab.js +2 -5
  38. package/dist/public/views/profile/agents-services-subtab.js +2 -3
  39. package/dist/public/views/profile/agents-tab.js +67 -88
  40. package/dist/public/views/profile/agents-tasks-subtab.js +3 -8
  41. package/dist/public/views/profile/boards-tab.js +2 -5
  42. package/dist/public/views/profile/chat-sessions-tab.js +2 -5
  43. package/dist/public/views/profile/ecosystem-tab.js +7 -12
  44. package/dist/public/views/profile/extensions-tab.js +2 -5
  45. package/dist/public/views/profile/federation-tab.js +2 -5
  46. package/dist/public/views/profile/inbox-tab.js +222 -153
  47. package/dist/public/views/profile/knowledge-tab.js +2 -5
  48. package/dist/public/views/profile/landing-page.js +10 -26
  49. package/dist/public/views/profile/memory-tab.js +2 -5
  50. package/dist/public/views/profile/notebook-card.js +27 -1
  51. package/dist/public/views/profile/organisms/activity-panel.js +3 -2
  52. package/dist/public/views/profile/organisms/home.js +52 -3
  53. package/dist/public/views/profile/organisms/members.js +2 -5
  54. package/dist/public/views/profile/organisms/mindmap.js +194 -0
  55. package/dist/public/views/profile/organisms/panels.js +3 -10
  56. package/dist/public/views/profile/organisms/participants-panel.js +3 -2
  57. package/dist/public/views/profile/organisms/readme-panel.js +97 -0
  58. package/dist/public/views/profile/organisms/sources-panel.js +2 -5
  59. package/dist/public/views/profile/organisms/timeline-panel.js +104 -0
  60. package/dist/public/views/profile/organisms/workspace-comments.js +2 -5
  61. package/dist/public/views/profile/organisms/workspace-list.js +8 -8
  62. package/dist/public/views/profile/organisms/workspace.js +41 -6
  63. package/dist/public/views/profile/organisms-tab.js +3 -6
  64. package/dist/public/views/profile/packages-tab.js +2 -5
  65. package/dist/public/views/profile/scheduler-tab.js +2 -4
  66. package/dist/public/views/profile/track-response-modal.js +211 -0
  67. package/dist/public/views/profile/workflows-tab.js +4 -13
  68. package/dist/public/views/profile.js +8 -9
  69. package/dist/scripts/consent-audit-prune.d.ts +21 -0
  70. package/dist/scripts/consent-audit-prune.d.ts.map +1 -0
  71. package/dist/scripts/consent-audit-prune.js +198 -0
  72. package/dist/scripts/consent-audit-prune.js.map +1 -0
  73. package/dist/scripts/telemetry-prune.d.ts +20 -0
  74. package/dist/scripts/telemetry-prune.d.ts.map +1 -0
  75. package/dist/scripts/telemetry-prune.js +195 -0
  76. package/dist/scripts/telemetry-prune.js.map +1 -0
  77. package/dist/src/auth/jwt.d.ts +1 -0
  78. package/dist/src/auth/jwt.d.ts.map +1 -1
  79. package/dist/src/auth/jwt.js +13 -0
  80. package/dist/src/auth/jwt.js.map +1 -1
  81. package/dist/src/cli/connect/mcp/local-server.d.ts.map +1 -1
  82. package/dist/src/cli/connect/mcp/local-server.js +109 -0
  83. package/dist/src/cli/connect/mcp/local-server.js.map +1 -1
  84. package/dist/src/cli/connect/tool-call.d.ts.map +1 -1
  85. package/dist/src/cli/connect/tool-call.js +9 -0
  86. package/dist/src/cli/connect/tool-call.js.map +1 -1
  87. package/dist/src/cli/connect/tunnel-client.d.ts +16 -0
  88. package/dist/src/cli/connect/tunnel-client.d.ts.map +1 -1
  89. package/dist/src/cli/connect/tunnel-client.js +42 -0
  90. package/dist/src/cli/connect/tunnel-client.js.map +1 -1
  91. package/dist/src/config.d.ts +1 -0
  92. package/dist/src/config.d.ts.map +1 -1
  93. package/dist/src/config.js +1 -0
  94. package/dist/src/config.js.map +1 -1
  95. package/dist/src/generated/api-types.d.ts +400 -21
  96. package/dist/src/generated/api-types.d.ts.map +1 -1
  97. package/dist/src/generated/prisma-postgres/edge.js +16 -3
  98. package/dist/src/generated/prisma-postgres/index-browser.js +13 -0
  99. package/dist/src/generated/prisma-postgres/index.d.ts +1550 -160
  100. package/dist/src/generated/prisma-postgres/index.js +16 -3
  101. package/dist/src/generated/prisma-postgres/package.json +1 -1
  102. package/dist/src/generated/prisma-postgres/schema.prisma +17 -0
  103. package/dist/src/generated/prisma-postgres/wasm.js +16 -3
  104. package/dist/src/index.js +4 -0
  105. package/dist/src/index.js.map +1 -1
  106. package/dist/src/mcp/agent-telemetry.d.ts +2 -0
  107. package/dist/src/mcp/agent-telemetry.d.ts.map +1 -1
  108. package/dist/src/mcp/agent-telemetry.js +8 -3
  109. package/dist/src/mcp/agent-telemetry.js.map +1 -1
  110. package/dist/src/mcp/annotations.d.ts.map +1 -1
  111. package/dist/src/mcp/annotations.js +1 -0
  112. package/dist/src/mcp/annotations.js.map +1 -1
  113. package/dist/src/mcp/catalog/definitions.d.ts.map +1 -1
  114. package/dist/src/mcp/catalog/definitions.js +15 -0
  115. package/dist/src/mcp/catalog/definitions.js.map +1 -1
  116. package/dist/src/mcp/organisms.d.ts +2 -0
  117. package/dist/src/mcp/organisms.d.ts.map +1 -1
  118. package/dist/src/mcp/organisms.js +43 -0
  119. package/dist/src/mcp/organisms.js.map +1 -1
  120. package/dist/src/mcp/workspaces.d.ts.map +1 -1
  121. package/dist/src/mcp/workspaces.js +4 -0
  122. package/dist/src/mcp/workspaces.js.map +1 -1
  123. package/dist/src/routes/agent-messages.js +2 -2
  124. package/dist/src/routes/agent-messages.js.map +1 -1
  125. package/dist/src/routes/agent-tasks.js +14 -14
  126. package/dist/src/routes/agent-tasks.js.map +1 -1
  127. package/dist/src/routes/agent-telemetry.d.ts +3 -0
  128. package/dist/src/routes/agent-telemetry.d.ts.map +1 -1
  129. package/dist/src/routes/agent-telemetry.js +11 -6
  130. package/dist/src/routes/agent-telemetry.js.map +1 -1
  131. package/dist/src/routes/agents.d.ts.map +1 -1
  132. package/dist/src/routes/agents.js +41 -3
  133. package/dist/src/routes/agents.js.map +1 -1
  134. package/dist/src/routes/boards.d.ts.map +1 -1
  135. package/dist/src/routes/boards.js +4 -2
  136. package/dist/src/routes/boards.js.map +1 -1
  137. package/dist/src/routes/consent.d.ts.map +1 -1
  138. package/dist/src/routes/consent.js +14 -1
  139. package/dist/src/routes/consent.js.map +1 -1
  140. package/dist/src/routes/matches.d.ts.map +1 -1
  141. package/dist/src/routes/matches.js +1 -3
  142. package/dist/src/routes/matches.js.map +1 -1
  143. package/dist/src/routes/memory.d.ts.map +1 -1
  144. package/dist/src/routes/memory.js +37 -1
  145. package/dist/src/routes/memory.js.map +1 -1
  146. package/dist/src/routes/messages.d.ts.map +1 -1
  147. package/dist/src/routes/messages.js +11 -9
  148. package/dist/src/routes/messages.js.map +1 -1
  149. package/dist/src/routes/organisms.d.ts +8 -0
  150. package/dist/src/routes/organisms.d.ts.map +1 -1
  151. package/dist/src/routes/organisms.js +120 -2
  152. package/dist/src/routes/organisms.js.map +1 -1
  153. package/dist/src/routes/owners.d.ts.map +1 -1
  154. package/dist/src/routes/owners.js +2 -0
  155. package/dist/src/routes/owners.js.map +1 -1
  156. package/dist/src/routes/personal.d.ts.map +1 -1
  157. package/dist/src/routes/personal.js +7 -0
  158. package/dist/src/routes/personal.js.map +1 -1
  159. package/dist/src/routes/sse.d.ts +3 -0
  160. package/dist/src/routes/sse.d.ts.map +1 -1
  161. package/dist/src/routes/sse.js +27 -15
  162. package/dist/src/routes/sse.js.map +1 -1
  163. package/dist/src/routes/storage-files.d.ts +2 -0
  164. package/dist/src/routes/storage-files.d.ts.map +1 -1
  165. package/dist/src/routes/storage-files.js +4 -7
  166. package/dist/src/routes/storage-files.js.map +1 -1
  167. package/dist/src/routes/tracked-responses.d.ts.map +1 -1
  168. package/dist/src/routes/tracked-responses.js +52 -0
  169. package/dist/src/routes/tracked-responses.js.map +1 -1
  170. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  171. package/dist/src/server-bootstrap/routes-loader.js +7 -0
  172. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  173. package/dist/src/services/access-guard.d.ts +4 -4
  174. package/dist/src/services/access-guard.d.ts.map +1 -1
  175. package/dist/src/services/access-guard.js +7 -8
  176. package/dist/src/services/access-guard.js.map +1 -1
  177. package/dist/src/services/activity-recorder.d.ts +2 -13
  178. package/dist/src/services/activity-recorder.d.ts.map +1 -1
  179. package/dist/src/services/activity-recorder.js +0 -42
  180. package/dist/src/services/activity-recorder.js.map +1 -1
  181. package/dist/src/services/connect-tunnel.d.ts +56 -3
  182. package/dist/src/services/connect-tunnel.d.ts.map +1 -1
  183. package/dist/src/services/connect-tunnel.js +216 -1
  184. package/dist/src/services/connect-tunnel.js.map +1 -1
  185. package/dist/src/services/consent-audit-buffer.d.ts +45 -0
  186. package/dist/src/services/consent-audit-buffer.d.ts.map +1 -0
  187. package/dist/src/services/consent-audit-buffer.js +85 -0
  188. package/dist/src/services/consent-audit-buffer.js.map +1 -0
  189. package/dist/src/services/consent.d.ts +9 -3
  190. package/dist/src/services/consent.d.ts.map +1 -1
  191. package/dist/src/services/consent.js +13 -5
  192. package/dist/src/services/consent.js.map +1 -1
  193. package/dist/src/services/core-jobs.d.ts.map +1 -1
  194. package/dist/src/services/core-jobs.js +15 -4
  195. package/dist/src/services/core-jobs.js.map +1 -1
  196. package/dist/src/services/event-bus.d.ts +15 -2
  197. package/dist/src/services/event-bus.d.ts.map +1 -1
  198. package/dist/src/services/event-bus.js +10 -4
  199. package/dist/src/services/event-bus.js.map +1 -1
  200. package/dist/src/services/job-seeding.d.ts.map +1 -1
  201. package/dist/src/services/job-seeding.js +2 -0
  202. package/dist/src/services/job-seeding.js.map +1 -1
  203. package/dist/src/services/message-delivery.d.ts +1 -1
  204. package/dist/src/services/message-delivery.d.ts.map +1 -1
  205. package/dist/src/services/message-delivery.js +10 -7
  206. package/dist/src/services/message-delivery.js.map +1 -1
  207. package/dist/src/services/message-send.d.ts.map +1 -1
  208. package/dist/src/services/message-send.js +24 -16
  209. package/dist/src/services/message-send.js.map +1 -1
  210. package/dist/src/services/onboarding-validator.d.ts.map +1 -1
  211. package/dist/src/services/onboarding-validator.js +13 -3
  212. package/dist/src/services/onboarding-validator.js.map +1 -1
  213. package/dist/src/services/organism-comments.d.ts +5 -1
  214. package/dist/src/services/organism-comments.d.ts.map +1 -1
  215. package/dist/src/services/organism-comments.js +7 -22
  216. package/dist/src/services/organism-comments.js.map +1 -1
  217. package/dist/src/services/organism-readme.d.ts +24 -0
  218. package/dist/src/services/organism-readme.d.ts.map +1 -0
  219. package/dist/src/services/organism-readme.js +37 -0
  220. package/dist/src/services/organism-readme.js.map +1 -0
  221. package/dist/src/services/readiness-scorer.d.ts.map +1 -1
  222. package/dist/src/services/readiness-scorer.js +11 -6
  223. package/dist/src/services/readiness-scorer.js.map +1 -1
  224. package/dist/src/services/scheduler.d.ts.map +1 -1
  225. package/dist/src/services/scheduler.js +9 -3
  226. package/dist/src/services/scheduler.js.map +1 -1
  227. package/dist/src/services/structure-graph.d.ts +65 -0
  228. package/dist/src/services/structure-graph.d.ts.map +1 -0
  229. package/dist/src/services/structure-graph.js +53 -0
  230. package/dist/src/services/structure-graph.js.map +1 -0
  231. package/dist/src/services/structure-overview.d.ts +6 -0
  232. package/dist/src/services/structure-overview.d.ts.map +1 -1
  233. package/dist/src/services/structure-overview.js +1 -1
  234. package/dist/src/services/structure-overview.js.map +1 -1
  235. package/dist/src/services/structure-snapshot.d.ts +47 -0
  236. package/dist/src/services/structure-snapshot.d.ts.map +1 -0
  237. package/dist/src/services/structure-snapshot.js +101 -0
  238. package/dist/src/services/structure-snapshot.js.map +1 -0
  239. package/dist/src/services/telemetry-buffer.d.ts +73 -0
  240. package/dist/src/services/telemetry-buffer.d.ts.map +1 -0
  241. package/dist/src/services/telemetry-buffer.js +185 -0
  242. package/dist/src/services/telemetry-buffer.js.map +1 -0
  243. package/dist/src/services/tracked-classify.d.ts +98 -0
  244. package/dist/src/services/tracked-classify.d.ts.map +1 -0
  245. package/dist/src/services/tracked-classify.js +182 -0
  246. package/dist/src/services/tracked-classify.js.map +1 -0
  247. package/dist/src/services/workspace-access.d.ts +36 -0
  248. package/dist/src/services/workspace-access.d.ts.map +1 -0
  249. package/dist/src/services/workspace-access.js +38 -0
  250. package/dist/src/services/workspace-access.js.map +1 -0
  251. package/dist/src/storage/interface.d.ts +4 -1
  252. package/dist/src/storage/interface.d.ts.map +1 -1
  253. package/dist/src/storage/interface.js.map +1 -1
  254. package/dist/src/storage/providers/mongodb/index.d.ts +25 -1
  255. package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
  256. package/dist/src/storage/providers/mongodb/index.js +127 -1
  257. package/dist/src/storage/providers/mongodb/index.js.map +1 -1
  258. package/dist/src/storage/providers/sqlite/index.d.ts +25 -1
  259. package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
  260. package/dist/src/storage/providers/sqlite/index.js +51 -4
  261. package/dist/src/storage/providers/sqlite/index.js.map +1 -1
  262. package/dist/src/storage/providers/sqlite/repos/agent-message.d.ts +4 -0
  263. package/dist/src/storage/providers/sqlite/repos/agent-message.d.ts.map +1 -1
  264. package/dist/src/storage/providers/sqlite/repos/agent-message.js +14 -0
  265. package/dist/src/storage/providers/sqlite/repos/agent-message.js.map +1 -1
  266. package/dist/src/storage/providers/sqlite/repos/agent-task.d.ts +9 -0
  267. package/dist/src/storage/providers/sqlite/repos/agent-task.d.ts.map +1 -1
  268. package/dist/src/storage/providers/sqlite/repos/agent-task.js +25 -0
  269. package/dist/src/storage/providers/sqlite/repos/agent-task.js.map +1 -1
  270. package/dist/src/storage/providers/sqlite/repos/memory.d.ts +22 -1
  271. package/dist/src/storage/providers/sqlite/repos/memory.d.ts.map +1 -1
  272. package/dist/src/storage/providers/sqlite/repos/memory.js +61 -3
  273. package/dist/src/storage/providers/sqlite/repos/memory.js.map +1 -1
  274. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  275. package/dist/src/storage/providers/sqlite/schema.js +21 -0
  276. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  277. package/dist/src/storage/repositories/agent-message.repository.d.ts +10 -0
  278. package/dist/src/storage/repositories/agent-message.repository.d.ts.map +1 -1
  279. package/dist/src/storage/repositories/agent-task.repository.d.ts +15 -0
  280. package/dist/src/storage/repositories/agent-task.repository.d.ts.map +1 -1
  281. package/dist/src/storage/repositories/consent.repository.d.ts +2 -0
  282. package/dist/src/storage/repositories/consent.repository.d.ts.map +1 -1
  283. package/dist/src/storage/repositories/memory.repository.d.ts +31 -0
  284. package/dist/src/storage/repositories/memory.repository.d.ts.map +1 -1
  285. package/dist/src/utils/messaging.d.ts +5 -0
  286. package/dist/src/utils/messaging.d.ts.map +1 -1
  287. package/dist/src/utils/messaging.js +0 -0
  288. package/dist/src/utils/messaging.js.map +1 -1
  289. package/package.json +5 -1
  290. package/prisma/schema.postgres.prisma +17 -0
  291. package/prisma/schema.prisma +19 -0
@@ -59,8 +59,39 @@
59
59
  "inbox.trackCreated": "Tracked response created.",
60
60
  "inbox.trackFailed": "Could not create the tracked response.",
61
61
  "inbox.trackPickTarget": "Pick an organism and workspace first.",
62
- "inbox.trackReady": "Reply ready",
62
+ "inbox.trackReady": "Reply ready — approve or reject",
63
63
  "inbox.trackUseSuggested": "Use suggested reply",
64
+ "inbox.trackApprove": "Approve & edit",
65
+ "inbox.trackReject": "Reject",
66
+ "inbox.trackOpenRecord": "Open record",
67
+ "inbox.trackNoRecord": "No linked record to open.",
68
+ "inbox.trackAlready": "This message already has a tracked response.",
69
+ "inbox.trackCancelled": "Tracked response cancelled.",
70
+ "inbox.trackStateWatching": "Watching",
71
+ "inbox.trackStateAwaiting": "Reply ready",
72
+ "inbox.trackStateReplied": "Replied",
73
+ "inbox.trackStateError": "Error — will retry",
74
+ "inbox.trackedTitle": "Tracked responses",
75
+ "inbox.trackedEmpty": "No tracked responses yet. Use 🔗 on a message to track one.",
76
+ "inbox.trackedTo": "to",
77
+ "inbox.trackedWatching": "watching",
78
+ "inbox.trackedOpen": "Open",
79
+ "inbox.trackedOpenConvo": "Open conversation",
80
+ "inbox.trackedCancel": "Cancel",
81
+ "inbox.trackedAllDone": "All tracked responses are completed.",
82
+ "inbox.trackedDoneCount": "{n} completed",
83
+ "inbox.trackHintAi": "Your AI chose where this belongs. Review, pick the record type, and a reply policy.",
84
+ "inbox.trackAiThinking": "AI is choosing where this belongs…",
85
+ "inbox.trackNeedsAi": "Tracking a response needs your own AI (OpenRouter or Ollama) to decide where the message belongs. Configure it to use this feature.",
86
+ "inbox.trackConfigureAi": "Configure AI",
87
+ "inbox.trackContent": "Content",
88
+ "inbox.trackNoTypes": "This workspace has no record types",
89
+ "inbox.trackCreatedGated": "Tracked response created — the record was sent for approval.",
90
+ "inbox.trackFillNote": "On create, your AI fills the record's fields to match this type's schema and sets the completion condition automatically.",
91
+ "inbox.trackPark": "Put in notebook for later",
92
+ "inbox.trackParked": "Saved to the notebook for later processing.",
93
+ "inbox.trackParkedBadge": "Owes a reply to {peer}",
94
+ "inbox.trackParkedDesc": "Parked from a message. Process it when ready — a reply will be tracked back to the sender.",
64
95
  "inbox.status.queued": "queued",
65
96
  "inbox.status.sent": "sent",
66
97
  "inbox.status.delivered": "delivered",
@@ -413,6 +444,7 @@
413
444
  "somethingWentWrong": "Something went wrong",
414
445
  "retry": "Retry",
415
446
  "save": "Save",
447
+ "saving": "Saving…",
416
448
  "close": "Close",
417
449
  "loading": "Loading...",
418
450
  "search": "Search...",
@@ -6259,6 +6291,38 @@
6259
6291
  "submitReview": "Submit Review"
6260
6292
  }
6261
6293
  },
6294
+ "readme": {
6295
+ "editTitle": "Edit README",
6296
+ "edit": "Edit README",
6297
+ "write": "Write",
6298
+ "preview": "Preview",
6299
+ "generateAi": "Generate with AI",
6300
+ "copied": "Copied!",
6301
+ "pasteBack": "Prompt copied — run it in your AI chat, then paste the Markdown result here.",
6302
+ "placeholder": "# Title\n\nDescribe what this is about. Mermaid diagrams are allowed.",
6303
+ "emptyHint": "No description yet. Add a README so people (and agents) know what this is about.",
6304
+ "saved": "README saved"
6305
+ },
6306
+ "mindmap": {
6307
+ "titleOrg": "Organism map",
6308
+ "titleWs": "Workspace map",
6309
+ "level": "Level",
6310
+ "levelWs": "Workspaces",
6311
+ "levelSpaces": "+ Spaces",
6312
+ "levelCounts": "+ Counts",
6313
+ "showUsers": "Users",
6314
+ "showActivity": "Activity",
6315
+ "heatmap": "Heatmap",
6316
+ "clickHint": "Click a node to open it."
6317
+ },
6318
+ "timeline": {
6319
+ "title": "Development timeline",
6320
+ "empty": "No structural history yet.",
6321
+ "now": "now",
6322
+ "snapshot": "Snapshot",
6323
+ "pick": "Pick a point to see the structure then.",
6324
+ "changed": "structure changed"
6325
+ },
6262
6326
  "organisms": {
6263
6327
  "title": "Organisms",
6264
6328
  "backToList": "All organisms",
@@ -6515,8 +6579,8 @@
6515
6579
  "moreActions": "More actions",
6516
6580
  "policyLabel": "Join policy",
6517
6581
  "tabWorkspaces": "Workspaces",
6518
- "structureOverviewOrg": "Organism structure overview",
6519
- "structureOverviewWs": "Workspace structure overview",
6582
+ "structureOverviewOrg": "Organism structure — table of contents",
6583
+ "structureOverviewWs": "Workspace structure — table of contents",
6520
6584
  "structEmpty": "No structure to show yet.",
6521
6585
  "tabMembers": "Members",
6522
6586
  "tabAgents": "Agents",
@@ -59,8 +59,39 @@
59
59
  "inbox.trackCreated": "Seurattu vastaus luotu.",
60
60
  "inbox.trackFailed": "Seuratun vastauksen luonti epäonnistui.",
61
61
  "inbox.trackPickTarget": "Valitse ensin organismi ja työtila.",
62
- "inbox.trackReady": "Vastaus valmis",
62
+ "inbox.trackReady": "Vastaus valmis — hyväksy tai hylkää",
63
63
  "inbox.trackUseSuggested": "Käytä ehdotettua vastausta",
64
+ "inbox.trackApprove": "Hyväksy ja muokkaa",
65
+ "inbox.trackReject": "Hylkää",
66
+ "inbox.trackOpenRecord": "Avaa tietue",
67
+ "inbox.trackNoRecord": "Ei linkitettyä tietuetta avattavaksi.",
68
+ "inbox.trackAlready": "Tällä viestillä on jo seurattu vastaus.",
69
+ "inbox.trackCancelled": "Seurattu vastaus peruutettu.",
70
+ "inbox.trackStateWatching": "Seurataan",
71
+ "inbox.trackStateAwaiting": "Vastaus valmis",
72
+ "inbox.trackStateReplied": "Vastattu",
73
+ "inbox.trackStateError": "Virhe — yritetään uudelleen",
74
+ "inbox.trackedTitle": "Seuratut vastaukset",
75
+ "inbox.trackedEmpty": "Ei seurattuja vastauksia vielä. Paina 🔗 viestin kohdalla aloittaaksesi.",
76
+ "inbox.trackedTo": "vastaanottaja",
77
+ "inbox.trackedWatching": "seurataan",
78
+ "inbox.trackedOpen": "Avaa",
79
+ "inbox.trackedOpenConvo": "Avaa keskustelu",
80
+ "inbox.trackedCancel": "Peruuta",
81
+ "inbox.trackedAllDone": "Kaikki seuratut vastaukset on hoidettu.",
82
+ "inbox.trackedDoneCount": "{n} hoidettu",
83
+ "inbox.trackHintAi": "Tekoälysi valitsi minne tämä kuuluu. Tarkista, valitse tietuetyyppi ja vastaustapa.",
84
+ "inbox.trackAiThinking": "Tekoäly valitsee minne tämä kuuluu…",
85
+ "inbox.trackNeedsAi": "Vastauksen seuraaminen vaatii oman tekoälysi (OpenRouter tai Ollama) päättämään minne viesti kuuluu. Ota se käyttöön käyttääksesi tätä toimintoa.",
86
+ "inbox.trackConfigureAi": "Määritä tekoäly",
87
+ "inbox.trackContent": "Sisältö",
88
+ "inbox.trackNoTypes": "Tällä työtilalla ei ole tietuetyyppejä",
89
+ "inbox.trackCreatedGated": "Seurattu vastaus luotu — tietue lähetettiin hyväksyttäväksi.",
90
+ "inbox.trackFillNote": "Luotaessa tekoälysi täyttää tietueen kentät tämän tyypin scheman mukaan ja asettaa valmis-ehdon automaattisesti.",
91
+ "inbox.trackPark": "Laita muistikirjaan myöhempää käsittelyä varten",
92
+ "inbox.trackParked": "Tallennettu muistikirjaan myöhempää käsittelyä varten.",
93
+ "inbox.trackParkedBadge": "Velkaa vastauksen: {peer}",
94
+ "inbox.trackParkedDesc": "Parkkeerattu viestistä. Käsittele kun ehdit — vastaus seurataan takaisin lähettäjälle.",
64
95
  "inbox.status.queued": "jonossa",
65
96
  "inbox.status.sent": "lähetetty",
66
97
  "inbox.status.delivered": "toimitettu",
@@ -413,6 +444,7 @@
413
444
  "somethingWentWrong": "Jokin meni pieleen",
414
445
  "retry": "Yritä uudelleen",
415
446
  "save": "Tallenna",
447
+ "saving": "Tallennetaan…",
416
448
  "close": "Sulje",
417
449
  "loading": "Ladataan...",
418
450
  "search": "Haku...",
@@ -6259,6 +6291,38 @@
6259
6291
  "submitReview": "Lähetä arviointi"
6260
6292
  }
6261
6293
  },
6294
+ "readme": {
6295
+ "editTitle": "Muokkaa README:ta",
6296
+ "edit": "Muokkaa README:ta",
6297
+ "write": "Kirjoita",
6298
+ "preview": "Esikatselu",
6299
+ "generateAi": "Luo tekoälyllä",
6300
+ "copied": "Kopioitu!",
6301
+ "pasteBack": "Prompti kopioitu — aja se AI-chatissa ja liitä Markdown-tulos tähän.",
6302
+ "placeholder": "# Otsikko\n\nKuvaa mistä tässä on kyse. Mermaid-kaaviot ovat sallittuja.",
6303
+ "emptyHint": "Ei vielä kuvausta. Lisää README, jotta ihmiset (ja agentit) tietävät mistä on kyse.",
6304
+ "saved": "README tallennettu"
6305
+ },
6306
+ "mindmap": {
6307
+ "titleOrg": "Organismin kartta",
6308
+ "titleWs": "Työtilan kartta",
6309
+ "level": "Taso",
6310
+ "levelWs": "Työtilat",
6311
+ "levelSpaces": "+ Spacet",
6312
+ "levelCounts": "+ Määrät",
6313
+ "showUsers": "Käyttäjät",
6314
+ "showActivity": "Aktiviteetti",
6315
+ "heatmap": "Lämpökartta",
6316
+ "clickHint": "Klikkaa solmua avataksesi sen."
6317
+ },
6318
+ "timeline": {
6319
+ "title": "Kehityksen aikajana",
6320
+ "empty": "Ei vielä rakennehistoriaa.",
6321
+ "now": "nyt",
6322
+ "snapshot": "Tilannekuva",
6323
+ "pick": "Valitse kohta nähdäksesi rakenteen silloin.",
6324
+ "changed": "rakenne muuttui"
6325
+ },
6262
6326
  "organisms": {
6263
6327
  "title": "Organismit",
6264
6328
  "backToList": "Kaikki organismit",
@@ -6515,8 +6579,8 @@
6515
6579
  "moreActions": "Lisätoiminnot",
6516
6580
  "policyLabel": "Liittymiskäytäntö",
6517
6581
  "tabWorkspaces": "Työtilat",
6518
- "structureOverviewOrg": "Organismin rakenteen yleiskuva",
6519
- "structureOverviewWs": "Työtilan rakenteen yleiskuva",
6582
+ "structureOverviewOrg": "Organismin rakenne sisällysluettelona",
6583
+ "structureOverviewWs": "Työtilan rakenne sisällysluettelona",
6520
6584
  "structEmpty": "Ei vielä rakennetta näytettäväksi.",
6521
6585
  "tabMembers": "Jäsenet",
6522
6586
  "tabAgents": "Agentit",
@@ -13,6 +13,7 @@
13
13
  import { h } from 'preact';
14
14
  import { useState, useEffect, useRef, useCallback } from 'preact/hooks';
15
15
  import htm from 'htm';
16
+ import { onLiveUpdate } from '/lib/live-updates.js';
16
17
  const html = htm.bind(h);
17
18
 
18
19
  const jwt = () => { try { return window.AIMEAT?.auth?.getSession?.()?.jwt || ''; } catch { return ''; } };
@@ -49,10 +50,7 @@ export function NotificationBell({ t, onNavigate }) {
49
50
 
50
51
  useEffect(() => {
51
52
  load();
52
- const onUpd = () => load();
53
- window.addEventListener('aimeat-live-update', onUpd);
54
- const iv = setInterval(load, 45000);
55
- return () => { window.removeEventListener('aimeat-live-update', onUpd); clearInterval(iv); };
53
+ return onLiveUpdate(['agent-messages', 'agent-tasks', 'notifications', 'workspace-access'], () => load());
56
54
  }, [load]);
57
55
 
58
56
  // Close the dropdown on an outside click.
@@ -4,6 +4,8 @@
4
4
  * Uses agd- prefix to avoid collisions with other profile styles.
5
5
  * All colors use CSS variables from theme.css.
6
6
  * @version-history
7
+ * v1.11.0 -- 2026-06-21 -- Add has-unseen DOT badge modifier (.pf-agd-*-badge--dot): a small
8
+ * round indicator replacing the old numeric change-count badge.
7
9
  * v1.10.0 -- 2026-06-03 -- Add fleet "running now" panel styles (.pf-agd-active,
8
10
  * -head, -empty, -list, -row, -dot, -agent, -title, -time) for the cross-agent
9
11
  * active-tasks list between the board and the agent list. All colors tokenized
@@ -2000,6 +2002,15 @@
2000
2002
  color: var(--danger-fg, #DC2626);
2001
2003
  border-color: var(--danger-border, #FECACA);
2002
2004
  }
2005
+ /* Has-unseen DOT (no count): a small round indicator replacing the old number badge. */
2006
+ .pf .pf-agd-change-badge--dot,
2007
+ .pf .pf-agd-tab-badge--dot {
2008
+ min-width: 8px;
2009
+ width: 8px;
2010
+ height: 8px;
2011
+ padding: 0;
2012
+ border-radius: 50%;
2013
+ }
2003
2014
 
2004
2015
  /* ── Board legend (filter pills), capability summary, inline misc (2026-06-10 round) ── */
2005
2016
  .pf .pf-agd-board-legend { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
@@ -308,9 +308,57 @@
308
308
  }
309
309
  .inbox-track-banner-txt { flex: 1; }
310
310
 
311
+ /* A "reply ready" suggested-reply shown as a dashed draft bubble with approve/reject. */
312
+ .inbox-bubble--draft {
313
+ border: 1px dashed var(--accent-border) !important;
314
+ background: var(--accent-subtle) !important;
315
+ }
316
+ .inbox-draft-label { font-size: 11px; font-weight: 600; color: var(--accent); margin-bottom: 4px; }
317
+ .inbox-draft-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; margin-top: 8px; }
318
+
311
319
  .inbox-track-form { display: flex; flex-direction: column; gap: 10px; }
312
320
  .inbox-track-hint { color: var(--text-dim); font-size: 13px; margin: 0; }
313
321
  .inbox-form-row { display: flex; flex-direction: column; gap: 4px; }
314
322
  .inbox-form-label { font-size: 12px; color: var(--text-dim); }
315
323
  .inbox-form-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
316
- .inbox-track-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; }
324
+ .inbox-track-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; align-items: center; }
325
+ .inbox-track-classify { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 32px 16px; text-align: center; }
326
+ .inbox-track-classify-step { font-weight: 600; }
327
+ .inbox-track-classify-sub { font-size: 13px; color: var(--text-dim); }
328
+ .inbox-track-content { resize: vertical; font-family: inherit; }
329
+
330
+ /* Spinner shown on the create button while a tracked response is being created. */
331
+ .inbox-spinner {
332
+ display: inline-block; width: 12px; height: 12px; vertical-align: -1px;
333
+ border: 2px solid var(--border); border-top-color: var(--accent);
334
+ border-radius: var(--radius-full); animation: inbox-spin 0.7s linear infinite;
335
+ }
336
+ @keyframes inbox-spin { to { transform: rotate(360deg); } }
337
+
338
+ /* Per-message "is tracked" badge + the tracked-responses dashboard. */
339
+ .inbox-head-actions { display: flex; align-items: center; gap: 8px; }
340
+ .btn-outline--active { border-color: var(--accent); color: var(--accent); }
341
+ .inbox-track-badge {
342
+ display: inline-flex; align-items: center; gap: 3px;
343
+ font-size: 11px; padding: 1px 7px; border-radius: var(--radius-full);
344
+ border: 1px solid var(--border); color: var(--text-dim); white-space: nowrap;
345
+ }
346
+ .inbox-track-badge--watch { border-color: var(--accent-border); color: var(--accent); }
347
+ .inbox-track-badge--ready { border-color: var(--accent-border); color: var(--accent); background: var(--accent-subtle); }
348
+ .inbox-track-badge--done { border-color: var(--border); color: var(--text-dim); }
349
+ .inbox-track-badge--err { border-color: var(--danger); color: var(--danger); }
350
+
351
+ .inbox-tracked-list { display: flex; flex-direction: column; gap: 8px; padding: 12px; overflow-y: auto; }
352
+ .inbox-tracked-row {
353
+ display: flex; align-items: center; justify-content: space-between; gap: 12px;
354
+ padding: 10px 12px; border: 1px solid var(--card-border); border-radius: var(--radius-sm);
355
+ background: var(--card-bg);
356
+ }
357
+ .inbox-tracked-main { min-width: 0; flex: 1; }
358
+ .inbox-tracked-line1 { display: flex; align-items: center; gap: 8px; }
359
+ .inbox-tracked-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
360
+ .inbox-tracked-sub { font-size: 12px; color: var(--text-dim); margin-top: 3px; }
361
+ .inbox-tracked-sub code { font-size: 11px; background: var(--card-bg-alt); padding: 1px 5px; border-radius: var(--radius-xs); }
362
+ .inbox-tracked-err { color: var(--danger); }
363
+ .inbox-tracked-actions { display: flex; gap: 6px; flex-shrink: 0; }
364
+ .inbox-tracked-done { color: var(--text-dim); font-size: 12px; padding: 8px 6px 2px; border-top: 1px solid var(--border); margin-top: 4px; }
@@ -2543,6 +2543,42 @@
2543
2543
  .pj-struct-body .md-body strong { font-weight: 600; }
2544
2544
  .pj-struct-body .md-body em { color: var(--muted); font-style: normal; }
2545
2545
 
2546
+ /* ── README panel (free-form description, Osa A) ── */
2547
+ .pj-readme { margin: 0.4rem 0 0.9rem; padding: 0.85rem 1rem; background: var(--card); border: 1px solid var(--border); border-radius: 10px; }
2548
+ .pj-readme-empty { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; justify-content: space-between; }
2549
+ .pj-readme-bar { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.5rem; }
2550
+ .pj-readme-actions { display: inline-flex; gap: 0.4rem; flex-wrap: wrap; }
2551
+ .pj-readme-body .md-body { font-size: 0.9rem; color: var(--text); line-height: 1.55; }
2552
+ .pj-readme-body .md-body > :first-child { margin-top: 0; }
2553
+ .pj-readme-textarea { width: 100%; font-family: var(--font-mono, monospace); font-size: 0.82rem; line-height: 1.5; resize: vertical; }
2554
+
2555
+ /* ── Interactive mindmap (Osa C) — reuses .of-mapwrap--clickable cursor/hover from offers.css ── */
2556
+ .pj-mindmap { margin: 0.4rem 0 0.9rem; }
2557
+ .pj-mindmap-body { margin-top: 0.4rem; padding: 0.75rem 0.9rem; background: var(--card); border: 1px solid var(--border); border-radius: 10px; }
2558
+ .pj-mindmap-opts { display: flex; flex-wrap: wrap; align-items: center; gap: 0.9rem; margin-bottom: 0.6rem; }
2559
+ .pj-mm-opt { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; color: var(--text-dim); }
2560
+ .pj-mm-opt select { width: auto; }
2561
+ .pj-mm-check { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.8rem; color: var(--text-dim); cursor: pointer; }
2562
+ .pj-mindmap-canvas { overflow: auto; max-height: 36rem; }
2563
+ .pj-mindmap-canvas .node { cursor: pointer; }
2564
+ .pj-mindmap-canvas .node:hover { opacity: 0.82; }
2565
+ .pj-mindmap-hint { margin-top: 0.4rem; }
2566
+
2567
+ /* ── Structure timeline / development (Osa D) ── */
2568
+ .pj-timeline { margin: 0.4rem 0 0.9rem; }
2569
+ .pj-timeline-body { margin-top: 0.4rem; padding: 0.75rem 0.9rem; background: var(--card); border: 1px solid var(--border); border-radius: 10px; }
2570
+ .pj-timeline-grid { display: grid; grid-template-columns: minmax(14rem, 22rem) 1fr; gap: 1rem; align-items: start; }
2571
+ .pj-timeline-list { list-style: none; margin: 0; padding: 0; max-height: 30rem; overflow: auto; }
2572
+ .pj-timeline-item { margin: 0; }
2573
+ .pj-timeline-entry { display: flex; flex-direction: column; gap: 0.1rem; width: 100%; text-align: left; background: none; border: none; border-left: 2px solid var(--border); padding: 0.4rem 0.6rem; cursor: pointer; color: var(--text); }
2574
+ .pj-timeline-entry:hover { background: var(--bg-dim); }
2575
+ .pj-timeline-item.is-active .pj-timeline-entry { border-left-color: var(--accent); background: var(--bg-dim); }
2576
+ .pj-timeline-date { font-size: 0.75rem; color: var(--muted); }
2577
+ .pj-timeline-event { font-size: 0.84rem; }
2578
+ .pj-timeline-counts { font-size: 0.72rem; }
2579
+ .pj-timeline-map { overflow: auto; max-height: 30rem; }
2580
+ @media (max-width: 720px) { .pj-timeline-grid { grid-template-columns: 1fr; } }
2581
+
2546
2582
  /* ── Workspace renew (phase 2): header actions, review banner, add-space tab ── */
2547
2583
  .pj-ws-head-actions { margin-left: auto; display: flex; gap: 0.4rem; align-items: center; }
2548
2584
  .pj-ws-banner { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; border: 1px solid var(--border); border-left: 3px solid var(--warn, var(--accent)); border-radius: 10px; background: var(--card); padding: 0.55rem 0.75rem; margin: 0.6rem 0 0.2rem; }
@@ -70,7 +70,13 @@ export function refreshAll() {
70
70
  function bindLive() {
71
71
  if (liveBound) return;
72
72
  liveBound = true;
73
- window.addEventListener('aimeat-live-update', refreshAll);
73
+ // Refresh presence only when the 'presence' domain actually changed (or on a legacy
74
+ // "everything changed" payload), not on every unrelated live update.
75
+ window.addEventListener('aimeat-live-update', (e) => {
76
+ const d = /** @type {CustomEvent} */ (e).detail?.domains;
77
+ if (d && !d.has('presence')) return;
78
+ refreshAll();
79
+ });
74
80
  }
75
81
 
76
82
  /**
@@ -4,9 +4,16 @@
4
4
  */
5
5
  import { apiGet, apiPost, apiDelete, api } from '/js/api.js';
6
6
 
7
- /** List agents owned by the given owner. Returns array. */
8
- export async function listAgents(owner) {
9
- const data = await apiGet('/v1/agents');
7
+ /**
8
+ * List agents owned by the given owner. Returns array.
9
+ * @param {string} [owner] filter to this owner
10
+ * @param {{ include?: string }} [opts] `include:'stats'` attaches a per-agent `stats` projection
11
+ * (task/message counts + latest timestamps + active_tasks + onboarding) in ONE request,
12
+ * replacing the old N+1 per-agent fan-out.
13
+ */
14
+ export async function listAgents(owner, opts = {}) {
15
+ const qs = opts.include ? `?include=${encodeURIComponent(opts.include)}` : '';
16
+ const data = await apiGet(`/v1/agents${qs}`);
10
17
  const list = data?.data?.agents || data?.data || [];
11
18
  return owner ? list.filter(a => a.owner === owner) : list;
12
19
  }
@@ -334,7 +334,7 @@ function awaitTask(agentName, taskId, onStatus) {
334
334
  if (st === 'failed' || st === 'stalled') { settled = true; cleanup(); reject(new Error('agent ' + st)); return; }
335
335
  if (Date.now() > deadline) { settled = true; cleanup(); reject(new Error('TIMEOUT')); }
336
336
  }
337
- const onLive = () => check();
337
+ const onLive = (e) => { const d = e.detail?.domains; if (d && !d.has('agent-tasks')) return; check(); };
338
338
  const timer = setInterval(check, 5000);
339
339
  window.addEventListener('aimeat-live-update', onLive);
340
340
  check();
@@ -3,6 +3,8 @@
3
3
  * @description AIMEAT Memory Service — key-value memory CRUD, search, file management.
4
4
  * @version-history
5
5
  * v1.1.0 — 2026-06-10 — Add getMemory(key) single-entry read (GET /v1/memory/:key).
6
+ * v1.2.0 — 2026-06-21 — getMemory(key, { soft }) — optional ?soft=1 read returning 200/null
7
+ * for keys that may not exist yet (kills browser-console 404 noise).
6
8
  */
7
9
  import { api, apiGet, apiPost, apiDelete } from '/js/api.js';
8
10
 
@@ -14,9 +16,21 @@ export async function listMemories(agentGaii) {
14
16
  return Array.isArray(list) ? list : [];
15
17
  }
16
18
 
17
- /** Read a single memory entry. Returns the envelope ({ data: { key, value, version, ... } }); throws/404s if missing. */
18
- export async function getMemory(key) {
19
- return apiGet(`/v1/memory/${encodeURIComponent(key)}`);
19
+ /** Cheap count of owner-scope memory entries (no values transferred). For stat displays. */
20
+ export async function countMemories() {
21
+ const data = await apiGet('/v1/memory?count=true');
22
+ return data?.data?.count ?? 0;
23
+ }
24
+
25
+ /**
26
+ * Read a single memory entry. Returns the envelope ({ data: { key, value, version, ... } }).
27
+ * By default throws/404s if missing. Pass { soft: true } for optional keys (UI prefs, config)
28
+ * that may legitimately not exist yet: the server returns a 200 with { value: null, exists: false }
29
+ * instead of a 404, avoiding browser-console 404 noise.
30
+ */
31
+ export async function getMemory(key, opts) {
32
+ const q = opts && opts.soft ? '?soft=1' : '';
33
+ return apiGet(`/v1/memory/${encodeURIComponent(key)}${q}`);
20
34
  }
21
35
 
22
36
  /** Search memory by query string. Returns array. Optional agentGaii. */
@@ -111,6 +125,12 @@ export async function listFiles() {
111
125
  return Array.isArray(list) ? list : [];
112
126
  }
113
127
 
128
+ /** Cheap count of files (no metadata transferred). For stat displays. */
129
+ export async function countFiles() {
130
+ const data = await apiGet('/v1/memory/files?count=true');
131
+ return data?.data?.count ?? 0;
132
+ }
133
+
114
134
  /** Upload a file (base64). */
115
135
  export async function uploadFile(key, base64Content, mimeType, visibility, tags) {
116
136
  const body = {
@@ -20,7 +20,7 @@ async function isPersonalEnabled() {
20
20
  export async function listNodes() {
21
21
  try {
22
22
  if (!(await isPersonalEnabled())) return [];
23
- const data = await apiGet('/v1/personal/status');
23
+ const data = await apiGet('/v1/personal/status?soft=1');
24
24
  return data?.data?.node_id ? [data.data] : [];
25
25
  } catch { return []; }
26
26
  }
@@ -74,7 +74,7 @@ function awaitTask(agentName, taskId, opts = {}) {
74
74
  if (status === 'failed' || status === 'stalled') { settled = true; cleanup(); reject(new Error('Agent task ' + status)); return; }
75
75
  if (Date.now() > deadline) { settled = true; cleanup(); reject(new Error('TIMEOUT')); }
76
76
  }
77
- const onLive = () => check();
77
+ const onLive = (e) => { const d = e.detail?.domains; if (d && !d.has('agent-tasks')) return; check(); };
78
78
  const timer = setInterval(check, 5000);
79
79
  window.addEventListener('aimeat-live-update', onLive);
80
80
  check();
@@ -15,8 +15,9 @@
15
15
  * @version-history
16
16
  * v1.0.0 — 2026-06-19 — Initial: classify + materialize-document orchestration (slice B).
17
17
  * v1.1.0 — 2026-06-21 — Phase 3: distribute (split → many homes) + notebook.settings trust toggles.
18
- * v1.2.0 — 2026-06-21 — Add materializeRecord (records-space sibling) + patchRecord for the Tracked
19
- * Response flow (inbox message actionable workspace record, source preserved).
18
+ * v1.2.0 — 2026-06-21 — (reverted) materializeRecord/patchRecord removed the Tracked Response flow
19
+ * now writes records through the proper workspace draft→publish path (services/organisms.js), not a
20
+ * raw memory write, so records land in the right namespace/owner and show up with activity.
20
21
  */
21
22
  import { api, apiPost } from '/js/api.js';
22
23
  import { createMemory, getMemory, deleteMemory } from '/js/services/memory.js';
@@ -56,6 +57,28 @@ export async function distributeNote(text) {
56
57
  return resp?.data || null;
57
58
  }
58
59
 
60
+ /**
61
+ * Park an inbox message into the notebook for later processing, preserving the link back to the
62
+ * original message and the "owes a reply" intent (so when the note is later turned into a tracked
63
+ * response, the binding re-attaches to the source message). Stored as a normal notebook inbox entry.
64
+ * @param {object} msg The inbox message ({ id, body, conversationId, direction, senderGhii, recipientGhii }).
65
+ * @param {{ title?: string, content?: string, mode?: 'auto'|'approve' }} [opts]
66
+ */
67
+ export async function parkMessageToNotebook(msg, opts = {}) {
68
+ const key = 'notebook.inbox.' + Date.now();
69
+ const peerGhii = msg?.direction === 'outbound' ? (msg?.recipientGhii || '') : (msg?.senderGhii || '');
70
+ const value = {
71
+ text: (opts.content && opts.content.trim()) || msg?.body || '',
72
+ title: opts.title || '',
73
+ capturedAt: new Date().toISOString(),
74
+ source: { kind: 'message', messageId: msg?.id, conversationId: msg?.conversationId, peerGhii, originNodeId: (peerGhii.split('@')[1] || '') },
75
+ trackedResponseIntent: { owes: true, mode: opts.mode || 'approve' },
76
+ };
77
+ const resp = await createMemory(key, value, 'private');
78
+ if (resp?.ok === false) throw new Error(resp.error?.message || 'Could not park to notebook');
79
+ return { key };
80
+ }
81
+
59
82
  /** The per-owner notebook trust toggles ({ autoDetectIntent, autoRunPlan, autoDistribute }). */
60
83
  export async function getNotebookSettings() {
61
84
  try { const r = await getMemory('notebook.settings'); return (r?.data?.value) || {}; }
@@ -151,81 +174,6 @@ export async function materializeDocument(plan) {
151
174
  return { organismId, workspaceId, space, docId };
152
175
  }
153
176
 
154
- /** A records-space objectType (mode:'records') for a memory-backed workspace — the sibling of the
155
- * document space, used by materializeRecord (e.g. a `bug` space). */
156
- function recordSpaceObjectType(namespace, name) {
157
- return { name: name || namespace, namespace, mode: 'records', backing: 'memory', writeRole: 'member', cardinality: 'many', versioned: true };
158
- }
159
-
160
- /**
161
- * Materialize a note into a workspace RECORD (mode:'records'), the actionable sibling of
162
- * materializeDocument. Unlike documents it does NOT delete any source — the Tracked Response that
163
- * binds this record needs the originating inbox message to persist. Returns the record's `.latest`
164
- * memory key so a Tracked Response can watch it.
165
- * @param {object} plan
166
- * @param {string|null} plan.organismId Existing organism id, or null to create one.
167
- * @param {string} [plan.organismName] Name for a new organism.
168
- * @param {string|null} plan.workspaceId Existing workspace id, or null to create one.
169
- * @param {string} [plan.workspaceName] Name for a new workspace.
170
- * @param {string} plan.space Records-space namespace (e.g. 'bug').
171
- * @param {string} [plan.spaceName] Display name for a newly-created space.
172
- * @param {object} plan.record The record value (e.g. { title, markdown, status, severity }).
173
- * @param {string} [plan.recordId]
174
- * @returns {Promise<{organismId:string, workspaceId:string, space:string, recordId:string, key:string}>}
175
- */
176
- export async function materializeRecord(plan) {
177
- let { organismId, workspaceId } = plan;
178
- const namespace = plan.space || 'note';
179
-
180
- // 1. Organism — create if needed.
181
- if (!organismId) {
182
- const resp = await createOrganism({
183
- name: (plan.organismName || 'Notebook').trim(),
184
- description: 'Created from the notebook',
185
- type: 'project', join_policy: 'approval_required', visibility: 'private',
186
- });
187
- if (resp?.ok === false) throw new Error(resp.error?.message || 'Could not create organism');
188
- organismId = resp?.data?.organism?.id;
189
- if (!organismId) throw new Error('Organism creation returned no id');
190
- }
191
-
192
- // 2. Workspace — create if needed (registry + manifest with the records space).
193
- if (!workspaceId) {
194
- workspaceId = rid('ws-');
195
- const manifest = { manifestVersion: '1.0', id: organismId, name: plan.workspaceName || 'Notebook', kind: 'project', status: 'active', objectTypes: [recordSpaceObjectType(namespace, plan.spaceName)] };
196
- await saveManifest(organismId, workspaceId, manifest);
197
- await apiPost('/v1/memory', { key: `${wsRoot(organismId, workspaceId)}.meta.readme`, value: `# ${manifest.name}\n\nCreated from the notebook.`, visibility: 'private' });
198
- const existing = await listWorkspaces(organismId);
199
- await saveWorkspaceRegistry(organismId, [...existing, { id: workspaceId, name: manifest.name, createdAt: new Date().toISOString() }]);
200
- } else {
201
- // Ensure the records space exists on the chosen workspace (additive — never replace the manifest).
202
- const manifest = await readManifest(organismId, workspaceId);
203
- if (manifest && !(manifest.objectTypes || []).some(ot => ot.namespace === namespace)) {
204
- const updated = { ...manifest, objectTypes: [...(manifest.objectTypes || []), recordSpaceObjectType(namespace, plan.spaceName)] };
205
- await saveManifest(organismId, workspaceId, updated).catch(() => {});
206
- }
207
- }
208
-
209
- // 3. Write the record at its .latest key (the key a Tracked Response watches).
210
- const recordId = plan.recordId || rid('rec-');
211
- const key = `${wsRoot(organismId, workspaceId)}.${namespace}.${recordId}.latest`;
212
- const value = { id: recordId, ...(plan.record || {}) };
213
- const resp = await createMemory(key, value, 'private');
214
- if (resp?.ok === false) throw new Error(resp.error?.message || 'Could not write record');
215
-
216
- return { organismId, workspaceId, space: namespace, recordId, key };
217
- }
218
-
219
- /** Best-effort merge a patch onto an existing memory record value (e.g. stamp a trackedResponse
220
- * back-ref onto a freshly-materialized record). Reads current value, shallow-merges, rewrites. */
221
- export async function patchRecord(key, patch) {
222
- try {
223
- const r = await getMemory(key);
224
- const cur = (r?.data?.value && typeof r.data.value === 'object') ? r.data.value : {};
225
- await createMemory(key, { ...cur, ...patch }, 'private');
226
- } catch { /* best-effort back-ref */ }
227
- }
228
-
229
177
  /**
230
178
  * Materialize each chunk of a distribute plan into its own home. Chunks with a resolved home go there;
231
179
  * chunks the model proposed a NEW name for create that org/workspace; chunks with neither are grouped
@@ -518,6 +518,37 @@ export async function getWorkspaceOverview(orgId, wsId) {
518
518
  } catch { return ''; }
519
519
  }
520
520
 
521
+ /** Deterministic GRAPH of the whole organism (workspaces → spaces + counts/last-activity, members,
522
+ * agents) — the data behind the interactive mindmap. Returns null on failure. */
523
+ export async function getOrganismGraph(orgId) {
524
+ try {
525
+ const r = await apiGet(`/v1/organisms/${encodeURIComponent(orgId)}/graph`);
526
+ return r?.data?.graph || null;
527
+ } catch { return null; }
528
+ }
529
+
530
+ /** Deterministic GRAPH of ONE workspace (root = workspace, with its spaces). Returns null on failure. */
531
+ export async function getWorkspaceGraph(orgId, wsId) {
532
+ try {
533
+ const r = await apiGet(`/v1/organisms/${encodeURIComponent(orgId)}/workspace/graph?ws=${encodeURIComponent(wsId)}`);
534
+ return r?.data?.graph || null;
535
+ } catch { return null; }
536
+ }
537
+
538
+ /** Organism STRUCTURE TIMELINE: { current, history } — the trackable structure fingerprint's current
539
+ * value + archived prior versions (newest first). Returns { current: null, history: [] } on failure. */
540
+ export async function getStructureHistory(orgId) {
541
+ try {
542
+ const r = await apiGet(`/v1/organisms/${encodeURIComponent(orgId)}/structure/history`);
543
+ return r?.data || { current: null, history: [] };
544
+ } catch { return { current: null, history: [] }; }
545
+ }
546
+
547
+ /** Save a workspace's free-form README (markdown). Creator/admin only (enforced server-side). */
548
+ export async function saveWorkspaceReadme(orgId, wsId, readme) {
549
+ return apiPut(`/v1/organisms/${encodeURIComponent(orgId)}/workspace?ws=${encodeURIComponent(wsId)}`, { ws: wsId, readme });
550
+ }
551
+
521
552
  /** Overwrite a workspace's manifest (e.g. edited name/summary/policy from Settings). */
522
553
  export async function saveManifest(orgId, wsId, manifest) {
523
554
  return apiPost('/v1/memory', { key: `${wsRoot(orgId, wsId)}.meta.manifest`, value: manifest, visibility: 'private' });