aimeat 1.6.1 → 1.8.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 (296) hide show
  1. package/dist/bin/aimeat.js +0 -0
  2. package/dist/locales/en.json +257 -8
  3. package/dist/locales/fi.json +257 -8
  4. package/dist/public/css/views/agents-detail.css +713 -0
  5. package/dist/public/css/views/foundry.css +1 -0
  6. package/dist/public/css/views/marketplace.css +1 -0
  7. package/dist/public/css/views/profile.css +24 -2
  8. package/dist/public/js/services/admin.js +13 -0
  9. package/dist/public/js/services/agent-activity.js +20 -0
  10. package/dist/public/js/services/agent-capabilities.js +15 -0
  11. package/dist/public/js/services/agent-directives.js +28 -0
  12. package/dist/public/js/services/agent-messages.js +34 -0
  13. package/dist/public/js/services/agent-services.js +17 -0
  14. package/dist/public/js/services/agent-tasks.js +46 -0
  15. package/dist/public/js/services/generator-spec-validate.js +23 -0
  16. package/dist/public/js/services/memory.js +45 -3
  17. package/dist/public/js/services/sharing-groups.js +51 -0
  18. package/dist/public/spa.html +21 -2
  19. package/dist/public/views/admin/agent-tasks-tab.js +156 -0
  20. package/dist/public/views/admin/federation-tab.js +7 -7
  21. package/dist/public/views/admin/memory-tab.js +1 -0
  22. package/dist/public/views/admin/overview-tab.js +25 -0
  23. package/dist/public/views/admin/prompts-tab.js +9 -10
  24. package/dist/public/views/admin/sharing-groups-tab.js +86 -0
  25. package/dist/public/views/admin.js +4 -0
  26. package/dist/public/views/profile/access-tab.js +528 -5
  27. package/dist/public/views/profile/agents-activity-subtab.js +242 -0
  28. package/dist/public/views/profile/agents-capabilities-subtab.js +165 -0
  29. package/dist/public/views/profile/agents-directives-subtab.js +292 -0
  30. package/dist/public/views/profile/agents-messages-subtab.js +223 -0
  31. package/dist/public/views/profile/agents-services-subtab.js +111 -0
  32. package/dist/public/views/profile/agents-tab.js +100 -49
  33. package/dist/public/views/profile/agents-tasks-subtab.js +313 -0
  34. package/dist/public/views/profile/generator-detail.js +8 -1
  35. package/dist/public/views/profile/knowledge-tab.js +5 -5
  36. package/dist/public/views/profile/memory-tab.js +458 -29
  37. package/dist/public/views/profile/wallet-tab.js +14 -0
  38. package/dist/src/config.d.ts +5 -0
  39. package/dist/src/config.d.ts.map +1 -1
  40. package/dist/src/config.js +9 -2
  41. package/dist/src/config.js.map +1 -1
  42. package/dist/src/mcp/agent-capabilities.d.ts +18 -0
  43. package/dist/src/mcp/agent-capabilities.d.ts.map +1 -0
  44. package/dist/src/mcp/agent-capabilities.js +85 -0
  45. package/dist/src/mcp/agent-capabilities.js.map +1 -0
  46. package/dist/src/mcp/agent-messages.d.ts +15 -0
  47. package/dist/src/mcp/agent-messages.d.ts.map +1 -0
  48. package/dist/src/mcp/agent-messages.js +81 -0
  49. package/dist/src/mcp/agent-messages.js.map +1 -0
  50. package/dist/src/mcp/agent-tasks.d.ts +16 -0
  51. package/dist/src/mcp/agent-tasks.d.ts.map +1 -0
  52. package/dist/src/mcp/agent-tasks.js +350 -0
  53. package/dist/src/mcp/agent-tasks.js.map +1 -0
  54. package/dist/src/mcp/core.d.ts.map +1 -1
  55. package/dist/src/mcp/core.js +8 -4
  56. package/dist/src/mcp/core.js.map +1 -1
  57. package/dist/src/mcp/index.d.ts.map +1 -1
  58. package/dist/src/mcp/index.js +8 -0
  59. package/dist/src/mcp/index.js.map +1 -1
  60. package/dist/src/mcp/memory-extended.js +1 -1
  61. package/dist/src/mcp/memory-extended.js.map +1 -1
  62. package/dist/src/mcp/sharing-groups.d.ts +16 -0
  63. package/dist/src/mcp/sharing-groups.d.ts.map +1 -0
  64. package/dist/src/mcp/sharing-groups.js +240 -0
  65. package/dist/src/mcp/sharing-groups.js.map +1 -0
  66. package/dist/src/models/agent-capabilities-schemas.d.ts +23 -0
  67. package/dist/src/models/agent-capabilities-schemas.d.ts.map +1 -0
  68. package/dist/src/models/agent-capabilities-schemas.js +19 -0
  69. package/dist/src/models/agent-capabilities-schemas.js.map +1 -0
  70. package/dist/src/models/agent-directives-schemas.d.ts +44 -0
  71. package/dist/src/models/agent-directives-schemas.d.ts.map +1 -0
  72. package/dist/src/models/agent-directives-schemas.js +41 -0
  73. package/dist/src/models/agent-directives-schemas.js.map +1 -0
  74. package/dist/src/models/agent-message-schemas.d.ts +32 -0
  75. package/dist/src/models/agent-message-schemas.d.ts.map +1 -0
  76. package/dist/src/models/agent-message-schemas.js +25 -0
  77. package/dist/src/models/agent-message-schemas.js.map +1 -0
  78. package/dist/src/models/agent-task-schemas.d.ts +133 -0
  79. package/dist/src/models/agent-task-schemas.d.ts.map +1 -0
  80. package/dist/src/models/agent-task-schemas.js +84 -0
  81. package/dist/src/models/agent-task-schemas.js.map +1 -0
  82. package/dist/src/models/schemas.d.ts +5 -0
  83. package/dist/src/models/schemas.d.ts.map +1 -1
  84. package/dist/src/models/schemas.js +5 -3
  85. package/dist/src/models/schemas.js.map +1 -1
  86. package/dist/src/models/sharing-group-schemas.d.ts +52 -0
  87. package/dist/src/models/sharing-group-schemas.d.ts.map +1 -0
  88. package/dist/src/models/sharing-group-schemas.js +46 -0
  89. package/dist/src/models/sharing-group-schemas.js.map +1 -0
  90. package/dist/src/routes/admin-agent-tasks.d.ts +12 -0
  91. package/dist/src/routes/admin-agent-tasks.d.ts.map +1 -0
  92. package/dist/src/routes/admin-agent-tasks.js +62 -0
  93. package/dist/src/routes/admin-agent-tasks.js.map +1 -0
  94. package/dist/src/routes/admin-monitoring.d.ts +2 -1
  95. package/dist/src/routes/admin-monitoring.d.ts.map +1 -1
  96. package/dist/src/routes/admin-monitoring.js +80 -2
  97. package/dist/src/routes/admin-monitoring.js.map +1 -1
  98. package/dist/src/routes/admin-sharing-groups.d.ts +12 -0
  99. package/dist/src/routes/admin-sharing-groups.d.ts.map +1 -0
  100. package/dist/src/routes/admin-sharing-groups.js +37 -0
  101. package/dist/src/routes/admin-sharing-groups.js.map +1 -0
  102. package/dist/src/routes/admin.d.ts +1 -1
  103. package/dist/src/routes/admin.d.ts.map +1 -1
  104. package/dist/src/routes/admin.js +2 -2
  105. package/dist/src/routes/admin.js.map +1 -1
  106. package/dist/src/routes/agent-activity.d.ts +17 -0
  107. package/dist/src/routes/agent-activity.d.ts.map +1 -0
  108. package/dist/src/routes/agent-activity.js +130 -0
  109. package/dist/src/routes/agent-activity.js.map +1 -0
  110. package/dist/src/routes/agent-capabilities.d.ts +18 -0
  111. package/dist/src/routes/agent-capabilities.d.ts.map +1 -0
  112. package/dist/src/routes/agent-capabilities.js +115 -0
  113. package/dist/src/routes/agent-capabilities.js.map +1 -0
  114. package/dist/src/routes/agent-directives.d.ts +17 -0
  115. package/dist/src/routes/agent-directives.d.ts.map +1 -0
  116. package/dist/src/routes/agent-directives.js +206 -0
  117. package/dist/src/routes/agent-directives.js.map +1 -0
  118. package/dist/src/routes/agent-integration.d.ts +17 -0
  119. package/dist/src/routes/agent-integration.d.ts.map +1 -0
  120. package/dist/src/routes/agent-integration.js +169 -0
  121. package/dist/src/routes/agent-integration.js.map +1 -0
  122. package/dist/src/routes/agent-messages.d.ts +17 -0
  123. package/dist/src/routes/agent-messages.d.ts.map +1 -0
  124. package/dist/src/routes/agent-messages.js +168 -0
  125. package/dist/src/routes/agent-messages.js.map +1 -0
  126. package/dist/src/routes/agent-tasks.d.ts +25 -0
  127. package/dist/src/routes/agent-tasks.d.ts.map +1 -0
  128. package/dist/src/routes/agent-tasks.js +427 -0
  129. package/dist/src/routes/agent-tasks.js.map +1 -0
  130. package/dist/src/routes/capabilities.js +4 -4
  131. package/dist/src/routes/capabilities.js.map +1 -1
  132. package/dist/src/routes/cortex.d.ts.map +1 -1
  133. package/dist/src/routes/cortex.js +1 -2
  134. package/dist/src/routes/cortex.js.map +1 -1
  135. package/dist/src/routes/extensions.d.ts.map +1 -1
  136. package/dist/src/routes/extensions.js +1 -2
  137. package/dist/src/routes/extensions.js.map +1 -1
  138. package/dist/src/routes/federation-auth.d.ts.map +1 -1
  139. package/dist/src/routes/federation-auth.js +3 -1
  140. package/dist/src/routes/federation-auth.js.map +1 -1
  141. package/dist/src/routes/federation-peer.d.ts.map +1 -1
  142. package/dist/src/routes/federation-peer.js +11 -2
  143. package/dist/src/routes/federation-peer.js.map +1 -1
  144. package/dist/src/routes/federation-sync.d.ts +1 -0
  145. package/dist/src/routes/federation-sync.d.ts.map +1 -1
  146. package/dist/src/routes/federation-sync.js +29 -0
  147. package/dist/src/routes/federation-sync.js.map +1 -1
  148. package/dist/src/routes/generator.d.ts.map +1 -1
  149. package/dist/src/routes/generator.js +33 -5
  150. package/dist/src/routes/generator.js.map +1 -1
  151. package/dist/src/routes/knowledge.d.ts.map +1 -1
  152. package/dist/src/routes/knowledge.js +4 -3
  153. package/dist/src/routes/knowledge.js.map +1 -1
  154. package/dist/src/routes/memory.d.ts +9 -0
  155. package/dist/src/routes/memory.d.ts.map +1 -1
  156. package/dist/src/routes/memory.js +312 -13
  157. package/dist/src/routes/memory.js.map +1 -1
  158. package/dist/src/routes/permissions.js +1 -1
  159. package/dist/src/routes/permissions.js.map +1 -1
  160. package/dist/src/routes/prompts.d.ts +10 -0
  161. package/dist/src/routes/prompts.d.ts.map +1 -1
  162. package/dist/src/routes/prompts.js +97 -2
  163. package/dist/src/routes/prompts.js.map +1 -1
  164. package/dist/src/routes/sharing-groups.d.ts +20 -0
  165. package/dist/src/routes/sharing-groups.d.ts.map +1 -0
  166. package/dist/src/routes/sharing-groups.js +303 -0
  167. package/dist/src/routes/sharing-groups.js.map +1 -0
  168. package/dist/src/routes/stats.d.ts +1 -0
  169. package/dist/src/routes/stats.d.ts.map +1 -1
  170. package/dist/src/routes/stats.js +26 -1
  171. package/dist/src/routes/stats.js.map +1 -1
  172. package/dist/src/routes/storage-files.d.ts.map +1 -1
  173. package/dist/src/routes/storage-files.js +4 -1
  174. package/dist/src/routes/storage-files.js.map +1 -1
  175. package/dist/src/routes/wallet.d.ts.map +1 -1
  176. package/dist/src/routes/wallet.js +2 -0
  177. package/dist/src/routes/wallet.js.map +1 -1
  178. package/dist/src/routes/work.d.ts.map +1 -1
  179. package/dist/src/routes/work.js +3 -0
  180. package/dist/src/routes/work.js.map +1 -1
  181. package/dist/src/schemas/knowledge-package.js +1 -1
  182. package/dist/src/schemas/knowledge-package.js.map +1 -1
  183. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  184. package/dist/src/server-bootstrap/routes-loader.js +52 -1
  185. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  186. package/dist/src/services/activity-recorder.d.ts +16 -0
  187. package/dist/src/services/activity-recorder.d.ts.map +1 -0
  188. package/dist/src/services/activity-recorder.js +59 -0
  189. package/dist/src/services/activity-recorder.js.map +1 -0
  190. package/dist/src/services/config-schema.d.ts.map +1 -1
  191. package/dist/src/services/config-schema.js +5 -0
  192. package/dist/src/services/config-schema.js.map +1 -1
  193. package/dist/src/services/consent.d.ts +1 -1
  194. package/dist/src/services/consent.d.ts.map +1 -1
  195. package/dist/src/services/consent.js +28 -1
  196. package/dist/src/services/consent.js.map +1 -1
  197. package/dist/src/services/core-jobs.d.ts.map +1 -1
  198. package/dist/src/services/core-jobs.js +5 -0
  199. package/dist/src/services/core-jobs.js.map +1 -1
  200. package/dist/src/services/federation-helpers.d.ts +1 -0
  201. package/dist/src/services/federation-helpers.d.ts.map +1 -1
  202. package/dist/src/services/federation-helpers.js +1 -1
  203. package/dist/src/services/federation-helpers.js.map +1 -1
  204. package/dist/src/services/generator-autopilot.d.ts.map +1 -1
  205. package/dist/src/services/generator-autopilot.js +125 -26
  206. package/dist/src/services/generator-autopilot.js.map +1 -1
  207. package/dist/src/services/generator-prompts/index.d.ts +1 -1
  208. package/dist/src/services/generator-prompts/index.d.ts.map +1 -1
  209. package/dist/src/services/generator-prompts/index.js +1 -1
  210. package/dist/src/services/generator-prompts/index.js.map +1 -1
  211. package/dist/src/services/generator-prompts/spec-validate.d.ts +1 -0
  212. package/dist/src/services/generator-prompts/spec-validate.d.ts.map +1 -1
  213. package/dist/src/services/generator-prompts/spec-validate.js +20 -0
  214. package/dist/src/services/generator-prompts/spec-validate.js.map +1 -1
  215. package/dist/src/services/generator-prompts/validate.d.ts +7 -1
  216. package/dist/src/services/generator-prompts/validate.d.ts.map +1 -1
  217. package/dist/src/services/generator-prompts/validate.js +70 -0
  218. package/dist/src/services/generator-prompts/validate.js.map +1 -1
  219. package/dist/src/services/job-seeding.d.ts.map +1 -1
  220. package/dist/src/services/job-seeding.js +2 -0
  221. package/dist/src/services/job-seeding.js.map +1 -1
  222. package/dist/src/services/prompt-defaults.d.ts +1 -0
  223. package/dist/src/services/prompt-defaults.d.ts.map +1 -1
  224. package/dist/src/services/prompt-defaults.js +830 -8
  225. package/dist/src/services/prompt-defaults.js.map +1 -1
  226. package/dist/src/services/prompt-seeder.js +1 -1
  227. package/dist/src/services/prompt-seeder.js.map +1 -1
  228. package/dist/src/services/stats.d.ts +1 -0
  229. package/dist/src/services/stats.d.ts.map +1 -1
  230. package/dist/src/services/stats.js +2 -1
  231. package/dist/src/services/stats.js.map +1 -1
  232. package/dist/src/services/task-stall-detector.d.ts +10 -0
  233. package/dist/src/services/task-stall-detector.d.ts.map +1 -0
  234. package/dist/src/services/task-stall-detector.js +38 -0
  235. package/dist/src/services/task-stall-detector.js.map +1 -0
  236. package/dist/src/services/work-task-bridge.d.ts +10 -0
  237. package/dist/src/services/work-task-bridge.d.ts.map +1 -0
  238. package/dist/src/services/work-task-bridge.js +53 -0
  239. package/dist/src/services/work-task-bridge.js.map +1 -0
  240. package/dist/src/storage/interface.d.ts +172 -5
  241. package/dist/src/storage/interface.d.ts.map +1 -1
  242. package/dist/src/storage/providers/mongodb/index.d.ts +95 -2
  243. package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
  244. package/dist/src/storage/providers/mongodb/index.js +661 -7
  245. package/dist/src/storage/providers/mongodb/index.js.map +1 -1
  246. package/dist/src/storage/providers/sqlite/index.d.ts +73 -1
  247. package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
  248. package/dist/src/storage/providers/sqlite/index.js +136 -3
  249. package/dist/src/storage/providers/sqlite/index.js.map +1 -1
  250. package/dist/src/storage/providers/sqlite/repos/agent-activity.d.ts +14 -0
  251. package/dist/src/storage/providers/sqlite/repos/agent-activity.d.ts.map +1 -0
  252. package/dist/src/storage/providers/sqlite/repos/agent-activity.js +44 -0
  253. package/dist/src/storage/providers/sqlite/repos/agent-activity.js.map +1 -0
  254. package/dist/src/storage/providers/sqlite/repos/agent-directives.d.ts +14 -0
  255. package/dist/src/storage/providers/sqlite/repos/agent-directives.d.ts.map +1 -0
  256. package/dist/src/storage/providers/sqlite/repos/agent-directives.js +65 -0
  257. package/dist/src/storage/providers/sqlite/repos/agent-directives.js.map +1 -0
  258. package/dist/src/storage/providers/sqlite/repos/agent-message.d.ts +28 -0
  259. package/dist/src/storage/providers/sqlite/repos/agent-message.d.ts.map +1 -0
  260. package/dist/src/storage/providers/sqlite/repos/agent-message.js +93 -0
  261. package/dist/src/storage/providers/sqlite/repos/agent-message.js.map +1 -0
  262. package/dist/src/storage/providers/sqlite/repos/agent-task.d.ts +45 -0
  263. package/dist/src/storage/providers/sqlite/repos/agent-task.d.ts.map +1 -0
  264. package/dist/src/storage/providers/sqlite/repos/agent-task.js +155 -0
  265. package/dist/src/storage/providers/sqlite/repos/agent-task.js.map +1 -0
  266. package/dist/src/storage/providers/sqlite/repos/sharing-group.d.ts +16 -0
  267. package/dist/src/storage/providers/sqlite/repos/sharing-group.d.ts.map +1 -0
  268. package/dist/src/storage/providers/sqlite/repos/sharing-group.js +68 -0
  269. package/dist/src/storage/providers/sqlite/repos/sharing-group.js.map +1 -0
  270. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  271. package/dist/src/storage/providers/sqlite/schema.js +104 -0
  272. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  273. package/dist/src/storage/repositories/agent-activity.repository.d.ts +15 -0
  274. package/dist/src/storage/repositories/agent-activity.repository.d.ts.map +1 -0
  275. package/dist/src/storage/repositories/agent-activity.repository.js +8 -0
  276. package/dist/src/storage/repositories/agent-activity.repository.js.map +1 -0
  277. package/dist/src/storage/repositories/agent-directives.repository.d.ts +15 -0
  278. package/dist/src/storage/repositories/agent-directives.repository.d.ts.map +1 -0
  279. package/dist/src/storage/repositories/agent-directives.repository.js +8 -0
  280. package/dist/src/storage/repositories/agent-directives.repository.js.map +1 -0
  281. package/dist/src/storage/repositories/agent-message.repository.d.ts +29 -0
  282. package/dist/src/storage/repositories/agent-message.repository.d.ts.map +1 -0
  283. package/dist/src/storage/repositories/agent-message.repository.js +8 -0
  284. package/dist/src/storage/repositories/agent-message.repository.js.map +1 -0
  285. package/dist/src/storage/repositories/agent-task.repository.d.ts +46 -0
  286. package/dist/src/storage/repositories/agent-task.repository.d.ts.map +1 -0
  287. package/dist/src/storage/repositories/agent-task.repository.js +8 -0
  288. package/dist/src/storage/repositories/agent-task.repository.js.map +1 -0
  289. package/dist/src/storage/repositories/index.d.ts +5 -0
  290. package/dist/src/storage/repositories/index.d.ts.map +1 -1
  291. package/dist/src/storage/repositories/sharing-group.repository.d.ts +17 -0
  292. package/dist/src/storage/repositories/sharing-group.repository.d.ts.map +1 -0
  293. package/dist/src/storage/repositories/sharing-group.repository.js +8 -0
  294. package/dist/src/storage/repositories/sharing-group.repository.js.map +1 -0
  295. package/package.json +77 -97
  296. package/prisma/schema.prisma +104 -0
@@ -97,14 +97,34 @@
97
97
  .pf .wallet-balance-copy:hover{background:rgba(232,86,74,.25)}
98
98
  .pf .mem-item{display:flex;justify-content:space-between;align-items:center;padding:.5rem 0;border-bottom:1px solid rgba(232,86,74,.08);font-size:.85rem;cursor:pointer;gap:.5rem}
99
99
  .pf .mem-item:hover{background:rgba(232,86,74,.05)}
100
- .pf .mem-key{font-family:monospace;color:var(--accent,#E8564A);font-weight:500;flex:1}
100
+ .pf .mem-key{font-family:monospace;color:var(--accent,#E8564A);font-weight:500;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
101
+ .pf .mem-time{font-size:.7rem;color:var(--text-dim,#6B7280);white-space:nowrap;flex-shrink:0}
102
+ .pf .mem-sort-bar{display:flex;align-items:center;gap:.35rem}
103
+ .pf .mem-sort-select{font-size:.75rem;padding:2px 6px;min-width:auto;width:auto}
101
104
  .pf .mem-vis{font-size:.7rem}
102
105
  .pf .shield-icon{font-size:.85rem;cursor:pointer;opacity:.6;transition:opacity .2s}
103
106
  .pf .shield-icon:hover{opacity:1}
104
107
  .pf .key-rules-box{background:#F9FAFB;border:1px solid rgba(139,92,246,.3);border-radius:8px;padding:.75rem;margin-top:.75rem;margin-bottom:.5rem}
105
108
  .pf .mem-detail{background:rgba(0,0,0,.04);border:1px solid rgba(232,86,74,.1);border-radius:8px;padding:1rem;margin-top:.5rem;font-size:.85rem}
106
109
  .pf .mem-detail pre{white-space:pre-wrap;word-break:break-all;font-family:monospace;color:var(--text,#1A1A2E);font-size:.8rem}
107
- .pf .mem-detail .mem-actions{display:flex;gap:.5rem;margin-top:.75rem}
110
+ .pf .mem-detail .mem-actions{display:flex;gap:.5rem;margin-top:.75rem;flex-wrap:wrap}
111
+ .pf .mem-browse-panel{background:var(--surface,#F9FAFB);border:1px solid var(--border,#E5E7EB);border-radius:var(--radius,12px);padding:1rem;margin-bottom:1rem}
112
+ .pf .mem-browse-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:.75rem}
113
+ .pf .mem-browse-list{display:flex;flex-direction:column;gap:.5rem}
114
+ .pf .mem-browse-item{display:flex;align-items:center;gap:.75rem;padding:.5rem .75rem;background:var(--card,#FFFFFF);border:1px solid var(--border,#E5E7EB);border-radius:8px;min-width:0}
115
+ .pf .mem-browse-item:hover{border-color:var(--accent,#E8564A)}
116
+ .pf .mem-browse-key{font-family:monospace;color:var(--accent,#E8564A);font-weight:500;flex:1;font-size:.85rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
117
+ .pf .mem-browse-meta{display:flex;align-items:center;gap:.5rem;flex-shrink:0;max-width:40%;overflow:hidden}
118
+ .pf .mem-browse-tags{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:200px}
119
+ .pf .mem-browse-buttons{display:flex;gap:.5rem;flex-wrap:wrap}
120
+ .pf .mem-discover-search{display:flex;gap:.35rem;align-items:center}
121
+ .pf .mem-discover-item{border:1px solid var(--border,#E5E7EB);border-radius:8px;overflow:hidden;background:var(--card,#FFFFFF)}
122
+ .pf .mem-discover-item:hover{border-color:var(--accent,#E8564A)}
123
+ .pf .mem-discover-row{display:flex;align-items:center;gap:.75rem;padding:.5rem .75rem;cursor:pointer;min-width:0}
124
+ .pf .mem-discover-info{flex:1;min-width:0;overflow:hidden}
125
+ .pf .mem-discover-owner{font-size:.7rem;color:var(--text-dim,#6B7280);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
126
+ .pf .mem-discover-preview{padding:.5rem .75rem;border-top:1px solid var(--border,#E5E7EB);background:var(--bg-dim,#F3F4F6)}
127
+ .pf .mem-discover-preview pre{white-space:pre-wrap;word-break:break-all;font-family:monospace;font-size:.75rem;color:var(--text,#1A1A2E);max-height:300px;overflow-y:auto;margin:0}
108
128
  .pf .peer-card{display:flex;justify-content:space-between;align-items:center}
109
129
  .pf .peer-status{display:flex;align-items:center;gap:.4rem}
110
130
  .pf .peer-dot{width:8px;height:8px;border-radius:50%}
@@ -823,6 +843,7 @@
823
843
  .pf .vis-pill:hover { opacity: 0.8; }
824
844
  .pf .vis-public { background: rgba(74, 222, 128, .15); color: #4ade80; }
825
845
  .pf .vis-owner { background: rgba(96, 165, 250, .15); color: #60a5fa; }
846
+ .pf .vis-group { background: rgba(16, 185, 129, .15); color: var(--success, #10b981); }
826
847
  .pf .vis-private { background: rgba(192, 132, 252, .15); color: #c084fc; }
827
848
  .pf .vis-protected { background: rgba(96, 165, 250, .15); color: #60a5fa; }
828
849
 
@@ -1664,6 +1685,7 @@
1664
1685
  .pf .pf-view-item-vis { font-size: .62rem; font-weight: 500; padding: 1px 6px; border-radius: 4px; }
1665
1686
  .pf .pf-view-item-vis.pf-vis-private { background: var(--accent-soft, #FFF0EE); color: var(--accent, #E8564A); }
1666
1687
  .pf .pf-view-item-vis.pf-vis-public { background: rgba(34,197,94,.1); color: var(--success, #22c55e); }
1688
+ .pf .pf-view-item-vis.pf-vis-group { background: rgba(16,185,129,.1); color: var(--success, #10b981); }
1667
1689
  .pf .pf-view-item-vis.pf-vis-shared { background: #EEF0FF; color: #6366F1; }
1668
1690
 
1669
1691
  /* Agent status dots in panels */
@@ -249,3 +249,16 @@ export const resetAllSystemPrompts = () => apiPost('/v1/admin/prompts/reset-
249
249
  export const resetPromptGroup = (group) => apiPost(`/v1/admin/prompts/reset-group/${encodeURIComponent(group)}`);
250
250
  export const getPromptVersions = (id) => apiGet(`/v1/admin/prompts/${encodeURIComponent(id)}/versions`);
251
251
  export const restorePromptVersion = (id, v) => apiPost(`/v1/admin/prompts/${encodeURIComponent(id)}/versions/${v}/restore`);
252
+
253
+ // ── Agent Tasks (admin) ──
254
+ export const getAdminAgentTasks = (params = {}) => {
255
+ const q = new URLSearchParams();
256
+ if (params.status) q.set('status', params.status);
257
+ if (params.agent) q.set('agent', params.agent);
258
+ if (params.page) q.set('page', String(params.page));
259
+ if (params.per_page) q.set('per_page', String(params.per_page));
260
+ return apiGet('/v1/admin/agent-tasks?' + q.toString());
261
+ };
262
+
263
+ // ── Sharing Groups (admin) ──
264
+ export const getAdminSharingGroups = () => apiGet('/v1/admin/sharing-groups');
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @file agent-activity.js
3
+ * @description Frontend API service for agent activity stats and history.
4
+ * Provides access to activity statistics (tasks completed, tokens used,
5
+ * success rate), daily activity history, and event log entries.
6
+ * @structure
7
+ * - getActivity() -- fetch activity stats and daily history
8
+ * - getActivityLog() -- fetch paginated event log
9
+ * @version-history
10
+ * v1.0.0 -- 2026-05-22 -- Initial creation for Agent Dashboard Phase 2
11
+ */
12
+ import { apiGet } from '/js/api.js';
13
+
14
+ export async function getActivity(agentName, days = 30, granularity = 'daily') {
15
+ return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/activity?days=${days}&granularity=${granularity}`);
16
+ }
17
+
18
+ export async function getActivityLog(agentName, page = 1, perPage = 20) {
19
+ return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/activity/log?page=${page}&per_page=${perPage}`);
20
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @file agent-capabilities.js
3
+ * @description Frontend API service for agent capability reporting and retrieval
4
+ * @version-history
5
+ * v1.0.0 -- 2026-05-22 -- Initial creation for Agent Dashboard Phase 2
6
+ */
7
+ import { apiGet, apiPut } from '/js/api.js';
8
+
9
+ export async function getCapabilities(agentName) {
10
+ return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/capabilities`);
11
+ }
12
+
13
+ export async function updateCapabilities(agentName, data) {
14
+ return apiPut(`/v1/agents/${encodeURIComponent(agentName)}/capabilities`, data);
15
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @file agent-directives.js
3
+ * @description Frontend API service for agent directives operations.
4
+ * Provides get/upsert/delete for per-agent directives and owner-level defaults.
5
+ * @version-history
6
+ * v1.0.0 -- 2026-05-21 -- Initial creation for Agent Dashboard Phase 1
7
+ */
8
+ import { apiGet, apiPut, apiDelete } from '/js/api.js';
9
+
10
+ export async function getDirectives(agentName) {
11
+ return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/directives`);
12
+ }
13
+
14
+ export async function upsertDirectives(agentName, data) {
15
+ return apiPut(`/v1/agents/${encodeURIComponent(agentName)}/directives`, data);
16
+ }
17
+
18
+ export async function deleteDirectives(agentName) {
19
+ return apiDelete(`/v1/agents/${encodeURIComponent(agentName)}/directives`);
20
+ }
21
+
22
+ export async function getOwnerDefaults() {
23
+ return apiGet('/v1/owner/agent-defaults');
24
+ }
25
+
26
+ export async function upsertOwnerDefaults(data) {
27
+ return apiPut('/v1/owner/agent-defaults', data);
28
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @file agent-messages.js
3
+ * @description Frontend API service for agent messages.
4
+ * Provides send, list, thread listing, and status update operations.
5
+ * @version-history
6
+ * v1.0.0 -- 2026-05-22 -- Initial creation for Agent Dashboard Phase 3
7
+ */
8
+ import { apiGet, apiPost, apiPatch } from '/js/api.js';
9
+
10
+ export async function sendMessage(agentName, content, threadId) {
11
+ return apiPost(`/v1/agents/${encodeURIComponent(agentName)}/messages`, {
12
+ content,
13
+ direction: 'inbound',
14
+ ...(threadId && { thread_id: threadId }),
15
+ });
16
+ }
17
+
18
+ export async function listMessages(agentName, opts = {}) {
19
+ const params = new URLSearchParams();
20
+ if (opts.page) params.set('page', String(opts.page));
21
+ if (opts.perPage) params.set('per_page', String(opts.perPage));
22
+ if (opts.direction) params.set('direction', opts.direction);
23
+ if (opts.threadId) params.set('thread_id', opts.threadId);
24
+ const qs = params.toString();
25
+ return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/messages${qs ? '?' + qs : ''}`);
26
+ }
27
+
28
+ export async function listThreads(agentName) {
29
+ return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/messages/threads`);
30
+ }
31
+
32
+ export async function updateMessageStatus(agentName, messageId, status) {
33
+ return apiPatch(`/v1/agents/${encodeURIComponent(agentName)}/messages/${messageId}`, { status });
34
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @file agent-services.js
3
+ * @description Frontend API service for agent published services (actions).
4
+ * Fetches actions from the work exchange and filters by agent name.
5
+ * @version-history
6
+ * v1.0.0 -- 2026-05-22 -- Initial creation for Agent Dashboard Phase 3
7
+ */
8
+ import { apiGet } from '/js/api.js';
9
+
10
+ export async function getAgentServices(agentName) {
11
+ const res = await apiGet('/v1/actions');
12
+ if (!res.ok) return { ok: false, actions: [] };
13
+ const actions = (res.data?.actions || []).filter(a =>
14
+ a.provider_gaii?.includes(`${agentName}#`) || a.provider_gaii?.includes(agentName)
15
+ );
16
+ return { ok: true, actions };
17
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @file agent-tasks.js
3
+ * @description Frontend API service for agent task operations.
4
+ * Provides CRUD, lifecycle (start/complete/fail), and event log access
5
+ * for the agent task queue system.
6
+ * @version-history
7
+ * v1.0.0 -- 2026-05-21 -- Initial creation for Agent Dashboard Phase 1
8
+ */
9
+ import { apiGet, apiPost, apiDelete } from '/js/api.js';
10
+
11
+ export async function listTasks(agentName, opts = {}) {
12
+ const params = new URLSearchParams();
13
+ if (opts.status) params.set('status', opts.status);
14
+ if (opts.page) params.set('page', String(opts.page));
15
+ if (opts.per_page) params.set('per_page', String(opts.per_page));
16
+ const qs = params.toString();
17
+ return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/tasks${qs ? '?' + qs : ''}`);
18
+ }
19
+
20
+ export async function getTask(agentName, taskId) {
21
+ return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/tasks/${encodeURIComponent(taskId)}`);
22
+ }
23
+
24
+ export async function createTask(agentName, data) {
25
+ return apiPost(`/v1/agents/${encodeURIComponent(agentName)}/tasks`, data);
26
+ }
27
+
28
+ export async function startTask(agentName, taskId) {
29
+ return apiPost(`/v1/agents/${encodeURIComponent(agentName)}/tasks/${encodeURIComponent(taskId)}/start`);
30
+ }
31
+
32
+ export async function completeTask(agentName, taskId, data = {}) {
33
+ return apiPost(`/v1/agents/${encodeURIComponent(agentName)}/tasks/${encodeURIComponent(taskId)}/complete`, data);
34
+ }
35
+
36
+ export async function failTask(agentName, taskId, reason) {
37
+ return apiPost(`/v1/agents/${encodeURIComponent(agentName)}/tasks/${encodeURIComponent(taskId)}/fail`, { reason });
38
+ }
39
+
40
+ export async function deleteTask(agentName, taskId) {
41
+ return apiDelete(`/v1/agents/${encodeURIComponent(agentName)}/tasks/${encodeURIComponent(taskId)}`);
42
+ }
43
+
44
+ export async function listEvents(agentName, taskId) {
45
+ return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/tasks/${encodeURIComponent(taskId)}/events`);
46
+ }
@@ -8,6 +8,7 @@
8
8
  * - validateDataApiSpec: structural validation of data API spec JSON
9
9
  * - validateComponentSpec: structural validation of component spec JSON
10
10
  * - validateAppDomainSpec: structural validation of app-domain spec JSON
11
+ * - validateAppSpec: structural validation of app (HTML page) spec JSON
11
12
  * - validateSpecAgainstProbe: compare spec declarations against probe results
12
13
  * @usage
13
14
  * import { validateExtensionSpec, validateSpecAgainstProbe } from '/js/services/generator-spec-validate.js';
@@ -122,6 +123,28 @@ export function validateAppDomainSpec(spec) {
122
123
  return { valid: errors.length === 0, errors };
123
124
  }
124
125
 
126
+ /**
127
+ * Validate that an app (HTML page) spec has required structure.
128
+ * @param {object} spec - Parsed app spec JSON
129
+ * @returns {{ valid: boolean, errors: string[] }}
130
+ */
131
+ export function validateAppSpec(spec) {
132
+ const errors = [];
133
+ if (!spec) return { valid: false, errors: ['Spec is null or undefined'] };
134
+
135
+ if (!spec.name) errors.push('Missing spec.name');
136
+ if (spec.name && !/^[a-z0-9]+(-[a-z0-9]+)*$/.test(spec.name)) {
137
+ errors.push(`spec.name "${spec.name}" must be ASCII kebab-case`);
138
+ }
139
+ if (!spec.title) errors.push('Missing spec.title');
140
+ if (!spec.appDomainLib) errors.push('Missing spec.appDomainLib — must reference the app-domain cortex libName');
141
+ if (!Array.isArray(spec.cortexDependencies) || spec.cortexDependencies.length === 0) {
142
+ errors.push('Missing or empty spec.cortexDependencies — must list all cortex registeredAs names');
143
+ }
144
+
145
+ return { valid: errors.length === 0, errors };
146
+ }
147
+
125
148
  /**
126
149
  * Compare extension spec against actual probe results.
127
150
  * SPEC IS KING: if probe response doesn't match spec, the CODE is wrong.
@@ -22,9 +22,10 @@ export async function searchMemory(query, agentGaii) {
22
22
  }
23
23
 
24
24
  /** Create a new memory entry. */
25
- export async function createMemory(key, value, visibility, tags) {
25
+ export async function createMemory(key, value, visibility, tags, groupId) {
26
26
  const body = { key, value, visibility: visibility || 'private' };
27
27
  if (tags) body.tags = Array.isArray(tags) ? tags : tags.split(',').map(t => t.trim()).filter(Boolean);
28
+ if (visibility === 'group' && groupId) body.group_id = groupId;
28
29
  return api('/v1/memory', {
29
30
  method: 'POST',
30
31
  body: JSON.stringify(body),
@@ -48,10 +49,12 @@ export async function updateMemoryFull(key, fields) {
48
49
  }
49
50
 
50
51
  /** Update visibility on a memory entry. */
51
- export async function updateMemoryVisibility(key, visibility, version) {
52
+ export async function updateMemoryVisibility(key, visibility, version, groupId) {
53
+ const body = { visibility, version };
54
+ if (visibility === 'group' && groupId) body.group_id = groupId;
52
55
  return api(`/v1/memory/${encodeURIComponent(key)}`, {
53
56
  method: 'PUT',
54
- body: JSON.stringify({ visibility, version }),
57
+ body: JSON.stringify(body),
55
58
  });
56
59
  }
57
60
 
@@ -120,3 +123,42 @@ export async function pullFromHome(key) {
120
123
  export async function pushToHome(key) {
121
124
  return apiPost('/v1/memory/push-home', { key });
122
125
  }
126
+
127
+ /** List memory entries on the home node (federated sessions). */
128
+ export async function listHomeMemories() {
129
+ const resp = await apiPost('/v1/memory/list-home', {});
130
+ return resp?.data?.entries || [];
131
+ }
132
+
133
+ /** List memory entries on a remote peer node (home sessions). */
134
+ export async function listRemoteMemories(peerNodeId) {
135
+ const resp = await apiPost('/v1/memory/list-remote', { peer_node_id: peerNodeId });
136
+ return resp?.data?.entries || [];
137
+ }
138
+
139
+ /** Pull a memory entry from a remote peer node (home sessions). */
140
+ export async function pullFromRemote(peerNodeId, key) {
141
+ return apiPost('/v1/memory/pull-remote', { peer_node_id: peerNodeId, key });
142
+ }
143
+
144
+ /** Discover public memory entries from other users on this node. */
145
+ export async function discoverPublicMemories(opts = {}) {
146
+ const params = new URLSearchParams();
147
+ if (opts.prefix) params.set('prefix', opts.prefix);
148
+ if (opts.owner) params.set('owner', opts.owner);
149
+ if (opts.q) params.set('q', opts.q);
150
+ if (opts.limit) params.set('limit', String(opts.limit));
151
+ if (opts.offset) params.set('offset', String(opts.offset));
152
+ const qs = params.toString();
153
+ const data = await apiGet('/v1/memory/discover' + (qs ? '?' + qs : ''));
154
+ return data?.data || { items: [], total: 0 };
155
+ }
156
+
157
+ /** Copy a public memory entry from another user to your own memory. */
158
+ export async function copyPublicMemory(sourceGaii, key, visibility) {
159
+ return apiPost('/v1/memory/copy', {
160
+ source_gaii: sourceGaii,
161
+ key,
162
+ visibility: visibility || 'private',
163
+ });
164
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @file sharing-groups.js
3
+ * @description Frontend API service for sharing group operations.
4
+ * Provides list/get/create/update/delete for groups and add/update/remove for members.
5
+ * @structure
6
+ * - listGroups() -- GET /v1/groups
7
+ * - getGroup(id) -- GET /v1/groups/:id
8
+ * - createGroup() -- POST /v1/groups
9
+ * - updateGroup() -- PATCH /v1/groups/:id
10
+ * - deleteGroup() -- DELETE /v1/groups/:id
11
+ * - addMember() -- POST /v1/groups/:id/members
12
+ * - updateMember() -- PATCH /v1/groups/:id/members/:identifier
13
+ * - removeMember() -- DELETE /v1/groups/:id/members/:identifier
14
+ * @usage
15
+ * import { listGroups, createGroup } from '/js/services/sharing-groups.js';
16
+ * @version-history
17
+ * v1.0.0 -- 2026-05-21 -- Initial creation for Agent Dashboard Phase 1
18
+ */
19
+ import { apiGet, apiPost, apiPatch, apiDelete } from '/js/api.js';
20
+
21
+ export async function listGroups() {
22
+ return apiGet('/v1/groups');
23
+ }
24
+
25
+ export async function getGroup(groupId) {
26
+ return apiGet(`/v1/groups/${encodeURIComponent(groupId)}`);
27
+ }
28
+
29
+ export async function createGroup(data) {
30
+ return apiPost('/v1/groups', data);
31
+ }
32
+
33
+ export async function updateGroup(groupId, data) {
34
+ return apiPatch(`/v1/groups/${encodeURIComponent(groupId)}`, data);
35
+ }
36
+
37
+ export async function deleteGroup(groupId) {
38
+ return apiDelete(`/v1/groups/${encodeURIComponent(groupId)}`);
39
+ }
40
+
41
+ export async function addMember(groupId, data) {
42
+ return apiPost(`/v1/groups/${encodeURIComponent(groupId)}/members`, data);
43
+ }
44
+
45
+ export async function updateMember(groupId, identifier, data) {
46
+ return apiPatch(`/v1/groups/${encodeURIComponent(groupId)}/members/${encodeURIComponent(identifier)}`, data);
47
+ }
48
+
49
+ export async function removeMember(groupId, identifier) {
50
+ return apiDelete(`/v1/groups/${encodeURIComponent(groupId)}/members/${encodeURIComponent(identifier)}`);
51
+ }
@@ -64,6 +64,7 @@
64
64
  <link rel="stylesheet" href="/css/components/tags.css">
65
65
  <link rel="stylesheet" href="/css/views/help.css">
66
66
  <link rel="stylesheet" href="/css/views/capabilities.css">
67
+ <link rel="stylesheet" href="/css/views/agents-detail.css">
67
68
  <link rel="stylesheet" href="/css/views/admin.css">
68
69
  <script type="importmap">
69
70
  {
@@ -140,7 +141,20 @@
140
141
  "/components/useViewCSS.js": "/components/useViewCSS.js",
141
142
  "/lib/live-updates.js": "/lib/live-updates.js",
142
143
  "/lib/minidenticons.min.js": "/lib/minidenticons.min.js",
143
- "/lib/yaml.mjs": "/lib/yaml.mjs"
144
+ "/lib/yaml.mjs": "/lib/yaml.mjs",
145
+ "/views/profile/agents-tasks-subtab.js": "/views/profile/agents-tasks-subtab.js",
146
+ "/views/profile/agents-directives-subtab.js": "/views/profile/agents-directives-subtab.js",
147
+ "/js/services/agent-tasks.js": "/js/services/agent-tasks.js",
148
+ "/js/services/agent-directives.js": "/js/services/agent-directives.js",
149
+ "/js/services/agent-capabilities.js": "/js/services/agent-capabilities.js",
150
+ "/views/profile/agents-capabilities-subtab.js": "/views/profile/agents-capabilities-subtab.js",
151
+ "/js/services/sharing-groups.js": "/js/services/sharing-groups.js",
152
+ "/js/services/agent-activity.js": "/js/services/agent-activity.js",
153
+ "/views/profile/agents-activity-subtab.js": "/views/profile/agents-activity-subtab.js",
154
+ "/views/profile/agents-services-subtab.js": "/views/profile/agents-services-subtab.js",
155
+ "/views/profile/agents-messages-subtab.js": "/views/profile/agents-messages-subtab.js",
156
+ "/js/services/agent-services.js": "/js/services/agent-services.js",
157
+ "/js/services/agent-messages.js": "/js/services/agent-messages.js"
144
158
  }
145
159
  }
146
160
  </script>
@@ -377,9 +391,14 @@
377
391
  <a href="/v1/help" onClick=${(e) => handleNav(e, '/v1/help')} class="${currentPath === '/v1/help' ? 'active' : ''}">${t('nav.help')}</a>
378
392
  ${session && html`
379
393
  <a href="/app-catalog.html" target="_blank" class="${currentPath === '/app-catalog.html' ? 'active' : ''}">${t('nav.apps') || 'Apps'}</a>
380
- <a href="/v1/profile" class="profile-link visible" onClick=${(e) => handleNav(e, '/v1/profile')}>
394
+ <a href="/v1/profile" class="profile-link visible ${currentPath === '/v1/profile' ? 'active' : ''}" onClick=${(e) => handleNav(e, '/v1/profile')}>
381
395
  ${t('nav.profile')}
382
396
  </a>
397
+ ${session.roles && session.roles.includes('operator') && html`
398
+ <a href="/v1/admin" class="${currentPath === '/v1/admin' ? 'active' : ''}" onClick=${(e) => handleNav(e, '/v1/admin')}>
399
+ ${t('nav.admin')}
400
+ </a>
401
+ `}
383
402
  `}
384
403
  <div class="topnav-center">
385
404
  <button class="lang-btn ${locale === 'en' ? 'active' : ''}" onClick=${() => handleLangSwitch('en')}>EN</button>
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @file agent-tasks-tab.js
3
+ * @description Admin dashboard tab for browsing all agent tasks across all owners.
4
+ * Provides status filtering, pagination, and TODO progress display.
5
+ * @version-history
6
+ * v1.0.0 -- 2026-05-21 -- Initial creation for Agent Dashboard Phase 1
7
+ */
8
+ import { h } from 'preact';
9
+ import { useState, useEffect, useCallback } from 'preact/hooks';
10
+ import htm from 'htm';
11
+ const html = htm.bind(h);
12
+ import { t } from '/js/i18n.js';
13
+ import { escHtml } from '/js/utils.js';
14
+ import { num, dt, Empty, Badge } from './shared.js';
15
+ import { apiGet } from '/js/api.js';
16
+
17
+ const PAGE_SIZE = 20;
18
+
19
+ const STATUSES = ['', 'draft', 'queued', 'active', 'stalled', 'done', 'failed'];
20
+
21
+ export default function AgentTasksTab({ data, reload, session }) {
22
+ const [tasks, setTasks] = useState([]);
23
+ const [total, setTotal] = useState(0);
24
+ const [page, setPage] = useState(1);
25
+ const [loading, setLoading] = useState(false);
26
+ const [statusFilter, setStatusFilter] = useState('');
27
+
28
+ const loadTasks = useCallback(async (p = 1) => {
29
+ setLoading(true);
30
+ try {
31
+ const params = new URLSearchParams();
32
+ params.set('page', String(p));
33
+ params.set('per_page', String(PAGE_SIZE));
34
+ if (statusFilter) params.set('status', statusFilter);
35
+ const r = await apiGet('/v1/admin/agent-tasks?' + params.toString());
36
+ if (r.data) {
37
+ setTasks(r.data.tasks || []);
38
+ setTotal(r.data.total || 0);
39
+ setPage(p);
40
+ }
41
+ } catch (e) {
42
+ console.warn('Failed to load agent tasks:', e.message);
43
+ }
44
+ setLoading(false);
45
+ }, [statusFilter]);
46
+
47
+ useEffect(() => { loadTasks(1); }, [loadTasks]);
48
+
49
+ // Listen for live updates
50
+ useEffect(() => {
51
+ const handler = () => { loadTasks(page); };
52
+ window.addEventListener('aimeat-live-update', handler);
53
+ return () => window.removeEventListener('aimeat-live-update', handler);
54
+ }, [loadTasks, page]);
55
+
56
+ function handleFilterChange(e) {
57
+ setStatusFilter(e.target.value);
58
+ }
59
+
60
+ function statusColor(status) {
61
+ switch (status) {
62
+ case 'active': return 'var(--accent, #06b6d4)';
63
+ case 'done': return '#22c55e';
64
+ case 'failed': return '#ef4444';
65
+ case 'stalled': return '#eab308';
66
+ case 'queued': return '#a855f7';
67
+ case 'draft': return 'var(--text-dim)';
68
+ default: return 'var(--text-dim)';
69
+ }
70
+ }
71
+
72
+ const totalPages = Math.ceil(total / PAGE_SIZE);
73
+
74
+ return html`
75
+ <div>
76
+ <!-- Filter bar -->
77
+ <div class="adm-mem-filters">
78
+ <select class="adm-input" value=${statusFilter} onChange=${handleFilterChange}>
79
+ <option value="">${t('dashboard.agentTasksStatus')} (${t('dashboard.all') || 'All'})</option>
80
+ ${STATUSES.filter(s => s).map(s => html`
81
+ <option value=${s}>${s}</option>
82
+ `)}
83
+ </select>
84
+ <button class="adm-btn" onClick=${() => loadTasks(1)} disabled=${loading}>
85
+ ${loading ? t('dashboard.loading') : t('dashboard.refresh')}
86
+ </button>
87
+ </div>
88
+
89
+ <!-- Stats summary -->
90
+ <div class="adm-mem-stats">
91
+ <div class="adm-mem-stat">
92
+ <span class="adm-mem-stat-value">${num(total)}</span>
93
+ <span class="adm-mem-stat-label">${t('dashboard.agentTasksTotal')}</span>
94
+ </div>
95
+ </div>
96
+
97
+ <!-- Table -->
98
+ ${tasks.length === 0 && !loading && html`<${Empty} text=${t('dashboard.agentTasksEmpty')} />`}
99
+
100
+ ${tasks.length > 0 && html`
101
+ <div class="adm-card">
102
+ <div class="scrollable">
103
+ <table>
104
+ <thead><tr>
105
+ <th>${t('dashboard.agentTasksAgent')}</th>
106
+ <th>${t('dashboard.agentTasksTitle')}</th>
107
+ <th>${t('dashboard.agentTasksStatus')}</th>
108
+ <th>${t('dashboard.agentTasksTodoProgress')}</th>
109
+ <th>${t('dashboard.agentTasksCreated')}</th>
110
+ <th>${t('dashboard.agentTasksLastEvent')}</th>
111
+ </tr></thead>
112
+ <tbody>
113
+ ${tasks.map(task => html`
114
+ <tr>
115
+ <td class="mono" style="font-size:.8rem">${escHtml(task.agent_gaii)}</td>
116
+ <td>${escHtml(task.title)}</td>
117
+ <td>
118
+ <span class="tag" style="color:${statusColor(task.status)};border-color:${statusColor(task.status)}">
119
+ ${task.status}
120
+ </span>
121
+ </td>
122
+ <td>
123
+ ${task.todo_progress.total > 0
124
+ ? html`${task.todo_progress.done}/${task.todo_progress.total}`
125
+ : html`<span style="color:var(--text-dim)">--</span>`
126
+ }
127
+ </td>
128
+ <td style="color:var(--text-dim)">${dt(task.created_at)}</td>
129
+ <td style="color:var(--text-dim)">${dt(task.last_event_at)}</td>
130
+ </tr>
131
+ `)}
132
+ </tbody>
133
+ </table>
134
+ </div>
135
+
136
+ <!-- Pagination -->
137
+ ${totalPages > 1 && html`
138
+ <div class="adm-mem-pagination">
139
+ <button class="adm-btn-sm"
140
+ disabled=${page <= 1}
141
+ onClick=${() => loadTasks(page - 1)}>
142
+ ← ${t('dashboard.prev') || 'Prev'}
143
+ </button>
144
+ <span class="adm-mem-page-info">${page} / ${totalPages}</span>
145
+ <button class="adm-btn-sm"
146
+ disabled=${page >= totalPages}
147
+ onClick=${() => loadTasks(page + 1)}>
148
+ ${t('dashboard.next') || 'Next'} →
149
+ </button>
150
+ </div>
151
+ `}
152
+ </div>
153
+ `}
154
+ </div>
155
+ `;
156
+ }
@@ -38,10 +38,10 @@ export default function FederationTab({ data, reload }) {
38
38
 
39
39
  useEffect(() => {
40
40
  getConfig().then(res => {
41
- if (res.ok && res.data?.config) {
42
- const c = res.data.config;
43
- setAuthPolicy(c.federation?.auth_policy ?? c.federationAuthPolicy ?? 'disabled');
44
- const scopes = c.federation?.default_scopes ?? c.federationDefaultScopes ?? 'memory:read,catalogue:read';
41
+ if (res.ok && res.data?.schema) {
42
+ const s = res.data.schema;
43
+ setAuthPolicy(s['federation.auth_policy']?.value ?? 'disabled');
44
+ const scopes = s['federation.default_scopes']?.value ?? 'memory:read,catalogue:read';
45
45
  setDefaultScopes(typeof scopes === 'string' ? scopes.split(',').filter(Boolean) : (scopes || []));
46
46
  }
47
47
  setAuthPolicyLoading(false);
@@ -50,8 +50,8 @@ export default function FederationTab({ data, reload }) {
50
50
 
51
51
  const doSaveAuthPolicy = async (policy, scopes) => {
52
52
  const changes = [
53
- { key: 'federation.auth_policy', value: policy },
54
- { key: 'federation.default_scopes', value: Array.isArray(scopes) ? scopes.join(',') : scopes },
53
+ { path: 'federation.auth_policy', value: policy },
54
+ { path: 'federation.default_scopes', value: Array.isArray(scopes) ? scopes.join(',') : scopes },
55
55
  ];
56
56
  const res = await saveConfig(changes);
57
57
  if (res.ok) { setActionSuccess(t('dashboard.fedPolicyUpdated')); setTimeout(() => setActionSuccess(null), 3000); }
@@ -385,7 +385,7 @@ export default function FederationTab({ data, reload }) {
385
385
  ${(p.status === 'active' || p.status === 'degraded') && html`
386
386
  <button class="adm-btn-sm" onClick=${() => doRemove(p.node_id)}>${t('dashboard.fedDepeer')}</button>
387
387
  `}
388
- ${p.status === 'active' && html`
388
+ ${(p.status === 'active' || p.status === 'degraded' || p.status === 'offline' || p.status === 'depeering') && html`
389
389
  <button class="adm-btn-sm adm-text-error" onClick=${() => doEmergencyRemove(p.node_id)}>\u26A0 ${t('dashboard.fedEmergencyDepeer')}</button>
390
390
  `}
391
391
  </td>
@@ -141,6 +141,7 @@ export default function MemoryTab({ data, reload, session }) {
141
141
  <option value="">${t('dashboard.memoryVisibility')} (${t('dashboard.all') || 'All'})</option>
142
142
  <option value="private">private</option>
143
143
  <option value="owner">owner</option>
144
+ <option value="group">group</option>
144
145
  <option value="public">public</option>
145
146
  </select>
146
147
  <button type="submit" class="adm-btn" disabled=${loading}>