aimeat 1.5.0 → 1.7.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 (385) hide show
  1. package/dist/.env.example +15 -0
  2. package/dist/bin/aimeat.js +0 -0
  3. package/dist/locales/en.json +291 -8
  4. package/dist/locales/fi.json +291 -8
  5. package/dist/public/css/views/admin.css +97 -0
  6. package/dist/public/css/views/agents-detail.css +563 -0
  7. package/dist/public/css/views/foundry.css +1 -0
  8. package/dist/public/css/views/marketplace.css +1 -0
  9. package/dist/public/css/views/profile.css +2 -0
  10. package/dist/public/js/services/admin.js +20 -1
  11. package/dist/public/js/services/agent-activity.js +20 -0
  12. package/dist/public/js/services/agent-capabilities.js +15 -0
  13. package/dist/public/js/services/agent-directives.js +28 -0
  14. package/dist/public/js/services/agent-messages.js +34 -0
  15. package/dist/public/js/services/agent-services.js +17 -0
  16. package/dist/public/js/services/agent-tasks.js +46 -0
  17. package/dist/public/js/services/memory.js +6 -3
  18. package/dist/public/js/services/sharing-groups.js +51 -0
  19. package/dist/public/spa.html +21 -2
  20. package/dist/public/views/admin/agent-tasks-tab.js +156 -0
  21. package/dist/public/views/admin/federation-tab.js +60 -0
  22. package/dist/public/views/admin/memory-tab.js +1 -0
  23. package/dist/public/views/admin/overview-tab.js +25 -0
  24. package/dist/public/views/admin/sharing-groups-tab.js +86 -0
  25. package/dist/public/views/admin/stats-tab.js +480 -187
  26. package/dist/public/views/admin.js +4 -0
  27. package/dist/public/views/profile/access-tab.js +511 -5
  28. package/dist/public/views/profile/agents-activity-subtab.js +242 -0
  29. package/dist/public/views/profile/agents-capabilities-subtab.js +165 -0
  30. package/dist/public/views/profile/agents-directives-subtab.js +292 -0
  31. package/dist/public/views/profile/agents-messages-subtab.js +222 -0
  32. package/dist/public/views/profile/agents-services-subtab.js +111 -0
  33. package/dist/public/views/profile/agents-tab.js +94 -47
  34. package/dist/public/views/profile/agents-tasks-subtab.js +254 -0
  35. package/dist/public/views/profile/knowledge-tab.js +5 -5
  36. package/dist/public/views/profile/memory-tab.js +90 -25
  37. package/dist/src/auth/node-keys.d.ts.map +1 -1
  38. package/dist/src/auth/node-keys.js +3 -0
  39. package/dist/src/auth/node-keys.js.map +1 -1
  40. package/dist/src/config.d.ts +18 -0
  41. package/dist/src/config.d.ts.map +1 -1
  42. package/dist/src/config.js +23 -2
  43. package/dist/src/config.js.map +1 -1
  44. package/dist/src/index.js +41 -2
  45. package/dist/src/index.js.map +1 -1
  46. package/dist/src/mcp/agent-capabilities.d.ts +18 -0
  47. package/dist/src/mcp/agent-capabilities.d.ts.map +1 -0
  48. package/dist/src/mcp/agent-capabilities.js +85 -0
  49. package/dist/src/mcp/agent-capabilities.js.map +1 -0
  50. package/dist/src/mcp/agent-messages.d.ts +15 -0
  51. package/dist/src/mcp/agent-messages.d.ts.map +1 -0
  52. package/dist/src/mcp/agent-messages.js +81 -0
  53. package/dist/src/mcp/agent-messages.js.map +1 -0
  54. package/dist/src/mcp/agent-tasks.d.ts +16 -0
  55. package/dist/src/mcp/agent-tasks.d.ts.map +1 -0
  56. package/dist/src/mcp/agent-tasks.js +350 -0
  57. package/dist/src/mcp/agent-tasks.js.map +1 -0
  58. package/dist/src/mcp/core.d.ts.map +1 -1
  59. package/dist/src/mcp/core.js +8 -4
  60. package/dist/src/mcp/core.js.map +1 -1
  61. package/dist/src/mcp/extensions.js +1 -1
  62. package/dist/src/mcp/extensions.js.map +1 -1
  63. package/dist/src/mcp/index.d.ts.map +1 -1
  64. package/dist/src/mcp/index.js +8 -0
  65. package/dist/src/mcp/index.js.map +1 -1
  66. package/dist/src/mcp/memory-extended.js +1 -1
  67. package/dist/src/mcp/memory-extended.js.map +1 -1
  68. package/dist/src/mcp/sharing-groups.d.ts +16 -0
  69. package/dist/src/mcp/sharing-groups.d.ts.map +1 -0
  70. package/dist/src/mcp/sharing-groups.js +240 -0
  71. package/dist/src/mcp/sharing-groups.js.map +1 -0
  72. package/dist/src/middleware/rate-limit.d.ts.map +1 -1
  73. package/dist/src/middleware/rate-limit.js +4 -1
  74. package/dist/src/middleware/rate-limit.js.map +1 -1
  75. package/dist/src/models/agent-capabilities-schemas.d.ts +20 -0
  76. package/dist/src/models/agent-capabilities-schemas.d.ts.map +1 -0
  77. package/dist/src/models/agent-capabilities-schemas.js +16 -0
  78. package/dist/src/models/agent-capabilities-schemas.js.map +1 -0
  79. package/dist/src/models/agent-directives-schemas.d.ts +44 -0
  80. package/dist/src/models/agent-directives-schemas.d.ts.map +1 -0
  81. package/dist/src/models/agent-directives-schemas.js +41 -0
  82. package/dist/src/models/agent-directives-schemas.js.map +1 -0
  83. package/dist/src/models/agent-message-schemas.d.ts +32 -0
  84. package/dist/src/models/agent-message-schemas.d.ts.map +1 -0
  85. package/dist/src/models/agent-message-schemas.js +25 -0
  86. package/dist/src/models/agent-message-schemas.js.map +1 -0
  87. package/dist/src/models/agent-task-schemas.d.ts +133 -0
  88. package/dist/src/models/agent-task-schemas.d.ts.map +1 -0
  89. package/dist/src/models/agent-task-schemas.js +84 -0
  90. package/dist/src/models/agent-task-schemas.js.map +1 -0
  91. package/dist/src/models/schemas.d.ts +50 -0
  92. package/dist/src/models/schemas.d.ts.map +1 -1
  93. package/dist/src/models/schemas.js +42 -4
  94. package/dist/src/models/schemas.js.map +1 -1
  95. package/dist/src/models/sharing-group-schemas.d.ts +52 -0
  96. package/dist/src/models/sharing-group-schemas.d.ts.map +1 -0
  97. package/dist/src/models/sharing-group-schemas.js +46 -0
  98. package/dist/src/models/sharing-group-schemas.js.map +1 -0
  99. package/dist/src/routes/actions.d.ts.map +1 -1
  100. package/dist/src/routes/actions.js +1 -0
  101. package/dist/src/routes/actions.js.map +1 -1
  102. package/dist/src/routes/admin-agent-tasks.d.ts +12 -0
  103. package/dist/src/routes/admin-agent-tasks.d.ts.map +1 -0
  104. package/dist/src/routes/admin-agent-tasks.js +62 -0
  105. package/dist/src/routes/admin-agent-tasks.js.map +1 -0
  106. package/dist/src/routes/admin-monitoring.d.ts +2 -1
  107. package/dist/src/routes/admin-monitoring.d.ts.map +1 -1
  108. package/dist/src/routes/admin-monitoring.js +82 -2
  109. package/dist/src/routes/admin-monitoring.js.map +1 -1
  110. package/dist/src/routes/admin-sharing-groups.d.ts +12 -0
  111. package/dist/src/routes/admin-sharing-groups.d.ts.map +1 -0
  112. package/dist/src/routes/admin-sharing-groups.js +37 -0
  113. package/dist/src/routes/admin-sharing-groups.js.map +1 -0
  114. package/dist/src/routes/admin.d.ts +1 -1
  115. package/dist/src/routes/admin.d.ts.map +1 -1
  116. package/dist/src/routes/admin.js +35 -17
  117. package/dist/src/routes/admin.js.map +1 -1
  118. package/dist/src/routes/agent-activity.d.ts +17 -0
  119. package/dist/src/routes/agent-activity.d.ts.map +1 -0
  120. package/dist/src/routes/agent-activity.js +130 -0
  121. package/dist/src/routes/agent-activity.js.map +1 -0
  122. package/dist/src/routes/agent-capabilities.d.ts +17 -0
  123. package/dist/src/routes/agent-capabilities.d.ts.map +1 -0
  124. package/dist/src/routes/agent-capabilities.js +106 -0
  125. package/dist/src/routes/agent-capabilities.js.map +1 -0
  126. package/dist/src/routes/agent-directives.d.ts +17 -0
  127. package/dist/src/routes/agent-directives.d.ts.map +1 -0
  128. package/dist/src/routes/agent-directives.js +206 -0
  129. package/dist/src/routes/agent-directives.js.map +1 -0
  130. package/dist/src/routes/agent-integration.d.ts +17 -0
  131. package/dist/src/routes/agent-integration.d.ts.map +1 -0
  132. package/dist/src/routes/agent-integration.js +169 -0
  133. package/dist/src/routes/agent-integration.js.map +1 -0
  134. package/dist/src/routes/agent-messages.d.ts +17 -0
  135. package/dist/src/routes/agent-messages.d.ts.map +1 -0
  136. package/dist/src/routes/agent-messages.js +168 -0
  137. package/dist/src/routes/agent-messages.js.map +1 -0
  138. package/dist/src/routes/agent-tasks.d.ts +24 -0
  139. package/dist/src/routes/agent-tasks.d.ts.map +1 -0
  140. package/dist/src/routes/agent-tasks.js +425 -0
  141. package/dist/src/routes/agent-tasks.js.map +1 -0
  142. package/dist/src/routes/agents.js +2 -2
  143. package/dist/src/routes/agents.js.map +1 -1
  144. package/dist/src/routes/apps.d.ts.map +1 -1
  145. package/dist/src/routes/apps.js +5 -1
  146. package/dist/src/routes/apps.js.map +1 -1
  147. package/dist/src/routes/auth.d.ts.map +1 -1
  148. package/dist/src/routes/auth.js +19 -1
  149. package/dist/src/routes/auth.js.map +1 -1
  150. package/dist/src/routes/boards.js +2 -2
  151. package/dist/src/routes/boards.js.map +1 -1
  152. package/dist/src/routes/capabilities.js +4 -4
  153. package/dist/src/routes/capabilities.js.map +1 -1
  154. package/dist/src/routes/consent.d.ts.map +1 -1
  155. package/dist/src/routes/consent.js +2 -1
  156. package/dist/src/routes/consent.js.map +1 -1
  157. package/dist/src/routes/cortex.d.ts.map +1 -1
  158. package/dist/src/routes/cortex.js +1 -2
  159. package/dist/src/routes/cortex.js.map +1 -1
  160. package/dist/src/routes/disputes.js +4 -4
  161. package/dist/src/routes/disputes.js.map +1 -1
  162. package/dist/src/routes/extensions.d.ts.map +1 -1
  163. package/dist/src/routes/extensions.js +73 -23
  164. package/dist/src/routes/extensions.js.map +1 -1
  165. package/dist/src/routes/federation-auth.d.ts.map +1 -1
  166. package/dist/src/routes/federation-auth.js +2 -62
  167. package/dist/src/routes/federation-auth.js.map +1 -1
  168. package/dist/src/routes/federation-peer.d.ts.map +1 -1
  169. package/dist/src/routes/federation-peer.js +13 -1
  170. package/dist/src/routes/federation-peer.js.map +1 -1
  171. package/dist/src/routes/flags.d.ts.map +1 -1
  172. package/dist/src/routes/flags.js +2 -1
  173. package/dist/src/routes/flags.js.map +1 -1
  174. package/dist/src/routes/foundry.d.ts.map +1 -1
  175. package/dist/src/routes/foundry.js +2 -2
  176. package/dist/src/routes/foundry.js.map +1 -1
  177. package/dist/src/routes/generator.d.ts.map +1 -1
  178. package/dist/src/routes/generator.js +35 -7
  179. package/dist/src/routes/generator.js.map +1 -1
  180. package/dist/src/routes/ghii.d.ts.map +1 -1
  181. package/dist/src/routes/ghii.js +67 -31
  182. package/dist/src/routes/ghii.js.map +1 -1
  183. package/dist/src/routes/knowledge.d.ts.map +1 -1
  184. package/dist/src/routes/knowledge.js +4 -3
  185. package/dist/src/routes/knowledge.js.map +1 -1
  186. package/dist/src/routes/memory.d.ts.map +1 -1
  187. package/dist/src/routes/memory.js +10 -4
  188. package/dist/src/routes/memory.js.map +1 -1
  189. package/dist/src/routes/owners.d.ts.map +1 -1
  190. package/dist/src/routes/owners.js +104 -8
  191. package/dist/src/routes/owners.js.map +1 -1
  192. package/dist/src/routes/packages.js +1 -1
  193. package/dist/src/routes/packages.js.map +1 -1
  194. package/dist/src/routes/permissions.js +1 -1
  195. package/dist/src/routes/permissions.js.map +1 -1
  196. package/dist/src/routes/prompts.d.ts +9 -0
  197. package/dist/src/routes/prompts.d.ts.map +1 -1
  198. package/dist/src/routes/prompts.js +57 -1
  199. package/dist/src/routes/prompts.js.map +1 -1
  200. package/dist/src/routes/sharing-groups.d.ts +20 -0
  201. package/dist/src/routes/sharing-groups.d.ts.map +1 -0
  202. package/dist/src/routes/sharing-groups.js +297 -0
  203. package/dist/src/routes/sharing-groups.js.map +1 -0
  204. package/dist/src/routes/stats.d.ts +14 -0
  205. package/dist/src/routes/stats.d.ts.map +1 -1
  206. package/dist/src/routes/stats.js +79 -4
  207. package/dist/src/routes/stats.js.map +1 -1
  208. package/dist/src/routes/storage-files.d.ts.map +1 -1
  209. package/dist/src/routes/storage-files.js +8 -1
  210. package/dist/src/routes/storage-files.js.map +1 -1
  211. package/dist/src/routes/upload.js +2 -2
  212. package/dist/src/routes/upload.js.map +1 -1
  213. package/dist/src/routes/wallet.d.ts.map +1 -1
  214. package/dist/src/routes/wallet.js +2 -1
  215. package/dist/src/routes/wallet.js.map +1 -1
  216. package/dist/src/routes/work.d.ts.map +1 -1
  217. package/dist/src/routes/work.js +5 -1
  218. package/dist/src/routes/work.js.map +1 -1
  219. package/dist/src/schemas/knowledge-package.js +1 -1
  220. package/dist/src/schemas/knowledge-package.js.map +1 -1
  221. package/dist/src/server-bootstrap/routes-loader.d.ts +1 -1
  222. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  223. package/dist/src/server-bootstrap/routes-loader.js +24 -4
  224. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  225. package/dist/src/server-bootstrap/service-init.d.ts.map +1 -1
  226. package/dist/src/server-bootstrap/service-init.js +2 -0
  227. package/dist/src/server-bootstrap/service-init.js.map +1 -1
  228. package/dist/src/server-bootstrap/static-files.d.ts.map +1 -1
  229. package/dist/src/server-bootstrap/static-files.js +10 -7
  230. package/dist/src/server-bootstrap/static-files.js.map +1 -1
  231. package/dist/src/server.d.ts.map +1 -1
  232. package/dist/src/server.js +4 -2
  233. package/dist/src/server.js.map +1 -1
  234. package/dist/src/services/activity-recorder.d.ts +16 -0
  235. package/dist/src/services/activity-recorder.d.ts.map +1 -0
  236. package/dist/src/services/activity-recorder.js +59 -0
  237. package/dist/src/services/activity-recorder.js.map +1 -0
  238. package/dist/src/services/capability-invoke.d.ts.map +1 -1
  239. package/dist/src/services/capability-invoke.js +5 -18
  240. package/dist/src/services/capability-invoke.js.map +1 -1
  241. package/dist/src/services/config-schema.d.ts.map +1 -1
  242. package/dist/src/services/config-schema.js +18 -0
  243. package/dist/src/services/config-schema.js.map +1 -1
  244. package/dist/src/services/consent.d.ts +1 -1
  245. package/dist/src/services/consent.d.ts.map +1 -1
  246. package/dist/src/services/consent.js +29 -11
  247. package/dist/src/services/consent.js.map +1 -1
  248. package/dist/src/services/core-jobs.d.ts.map +1 -1
  249. package/dist/src/services/core-jobs.js +5 -0
  250. package/dist/src/services/core-jobs.js.map +1 -1
  251. package/dist/src/services/directory.d.ts.map +1 -1
  252. package/dist/src/services/directory.js +10 -4
  253. package/dist/src/services/directory.js.map +1 -1
  254. package/dist/src/services/email.d.ts +17 -4
  255. package/dist/src/services/email.d.ts.map +1 -1
  256. package/dist/src/services/email.js +30 -12
  257. package/dist/src/services/email.js.map +1 -1
  258. package/dist/src/services/extension-runtime.d.ts.map +1 -1
  259. package/dist/src/services/extension-runtime.js +5 -0
  260. package/dist/src/services/extension-runtime.js.map +1 -1
  261. package/dist/src/services/federation.d.ts +2 -0
  262. package/dist/src/services/federation.d.ts.map +1 -1
  263. package/dist/src/services/federation.js.map +1 -1
  264. package/dist/src/services/job-seeding.d.ts.map +1 -1
  265. package/dist/src/services/job-seeding.js +2 -0
  266. package/dist/src/services/job-seeding.js.map +1 -1
  267. package/dist/src/services/mailbox-notification.d.ts +17 -0
  268. package/dist/src/services/mailbox-notification.d.ts.map +1 -1
  269. package/dist/src/services/mailbox-notification.js +25 -0
  270. package/dist/src/services/mailbox-notification.js.map +1 -1
  271. package/dist/src/services/morsel.d.ts.map +1 -1
  272. package/dist/src/services/morsel.js +10 -9
  273. package/dist/src/services/morsel.js.map +1 -1
  274. package/dist/src/services/password.d.ts +1 -6
  275. package/dist/src/services/password.d.ts.map +1 -1
  276. package/dist/src/services/password.js +19 -10
  277. package/dist/src/services/password.js.map +1 -1
  278. package/dist/src/services/push.d.ts +16 -0
  279. package/dist/src/services/push.d.ts.map +1 -1
  280. package/dist/src/services/push.js +20 -0
  281. package/dist/src/services/push.js.map +1 -1
  282. package/dist/src/services/quota.d.ts.map +1 -1
  283. package/dist/src/services/quota.js +2 -1
  284. package/dist/src/services/quota.js.map +1 -1
  285. package/dist/src/services/scheduler.d.ts.map +1 -1
  286. package/dist/src/services/scheduler.js +17 -1
  287. package/dist/src/services/scheduler.js.map +1 -1
  288. package/dist/src/services/stats.d.ts +43 -2
  289. package/dist/src/services/stats.d.ts.map +1 -1
  290. package/dist/src/services/stats.js +177 -1
  291. package/dist/src/services/stats.js.map +1 -1
  292. package/dist/src/services/task-stall-detector.d.ts +10 -0
  293. package/dist/src/services/task-stall-detector.d.ts.map +1 -0
  294. package/dist/src/services/task-stall-detector.js +38 -0
  295. package/dist/src/services/task-stall-detector.js.map +1 -0
  296. package/dist/src/services/totp.js +2 -2
  297. package/dist/src/services/work-task-bridge.d.ts +10 -0
  298. package/dist/src/services/work-task-bridge.d.ts.map +1 -0
  299. package/dist/src/services/work-task-bridge.js +53 -0
  300. package/dist/src/services/work-task-bridge.js.map +1 -0
  301. package/dist/src/storage/interface.d.ts +175 -5
  302. package/dist/src/storage/interface.d.ts.map +1 -1
  303. package/dist/src/storage/providers/mongodb/index.d.ts +105 -2
  304. package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
  305. package/dist/src/storage/providers/mongodb/index.js +738 -8
  306. package/dist/src/storage/providers/mongodb/index.js.map +1 -1
  307. package/dist/src/storage/providers/sqlite/index.d.ts +83 -1
  308. package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
  309. package/dist/src/storage/providers/sqlite/index.js +204 -5
  310. package/dist/src/storage/providers/sqlite/index.js.map +1 -1
  311. package/dist/src/storage/providers/sqlite/repos/agent-activity.d.ts +14 -0
  312. package/dist/src/storage/providers/sqlite/repos/agent-activity.d.ts.map +1 -0
  313. package/dist/src/storage/providers/sqlite/repos/agent-activity.js +44 -0
  314. package/dist/src/storage/providers/sqlite/repos/agent-activity.js.map +1 -0
  315. package/dist/src/storage/providers/sqlite/repos/agent-directives.d.ts +14 -0
  316. package/dist/src/storage/providers/sqlite/repos/agent-directives.d.ts.map +1 -0
  317. package/dist/src/storage/providers/sqlite/repos/agent-directives.js +65 -0
  318. package/dist/src/storage/providers/sqlite/repos/agent-directives.js.map +1 -0
  319. package/dist/src/storage/providers/sqlite/repos/agent-message.d.ts +28 -0
  320. package/dist/src/storage/providers/sqlite/repos/agent-message.d.ts.map +1 -0
  321. package/dist/src/storage/providers/sqlite/repos/agent-message.js +93 -0
  322. package/dist/src/storage/providers/sqlite/repos/agent-message.js.map +1 -0
  323. package/dist/src/storage/providers/sqlite/repos/agent-task.d.ts +45 -0
  324. package/dist/src/storage/providers/sqlite/repos/agent-task.d.ts.map +1 -0
  325. package/dist/src/storage/providers/sqlite/repos/agent-task.js +155 -0
  326. package/dist/src/storage/providers/sqlite/repos/agent-task.js.map +1 -0
  327. package/dist/src/storage/providers/sqlite/repos/consent.d.ts +1 -0
  328. package/dist/src/storage/providers/sqlite/repos/consent.d.ts.map +1 -1
  329. package/dist/src/storage/providers/sqlite/repos/consent.js +4 -0
  330. package/dist/src/storage/providers/sqlite/repos/consent.js.map +1 -1
  331. package/dist/src/storage/providers/sqlite/repos/sharing-group.d.ts +16 -0
  332. package/dist/src/storage/providers/sqlite/repos/sharing-group.d.ts.map +1 -0
  333. package/dist/src/storage/providers/sqlite/repos/sharing-group.js +68 -0
  334. package/dist/src/storage/providers/sqlite/repos/sharing-group.js.map +1 -0
  335. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  336. package/dist/src/storage/providers/sqlite/schema.js +121 -0
  337. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  338. package/dist/src/storage/repositories/agent-activity.repository.d.ts +15 -0
  339. package/dist/src/storage/repositories/agent-activity.repository.d.ts.map +1 -0
  340. package/dist/src/storage/repositories/agent-activity.repository.js +8 -0
  341. package/dist/src/storage/repositories/agent-activity.repository.js.map +1 -0
  342. package/dist/src/storage/repositories/agent-directives.repository.d.ts +15 -0
  343. package/dist/src/storage/repositories/agent-directives.repository.d.ts.map +1 -0
  344. package/dist/src/storage/repositories/agent-directives.repository.js +8 -0
  345. package/dist/src/storage/repositories/agent-directives.repository.js.map +1 -0
  346. package/dist/src/storage/repositories/agent-message.repository.d.ts +29 -0
  347. package/dist/src/storage/repositories/agent-message.repository.d.ts.map +1 -0
  348. package/dist/src/storage/repositories/agent-message.repository.js +8 -0
  349. package/dist/src/storage/repositories/agent-message.repository.js.map +1 -0
  350. package/dist/src/storage/repositories/agent-task.repository.d.ts +46 -0
  351. package/dist/src/storage/repositories/agent-task.repository.d.ts.map +1 -0
  352. package/dist/src/storage/repositories/agent-task.repository.js +8 -0
  353. package/dist/src/storage/repositories/agent-task.repository.js.map +1 -0
  354. package/dist/src/storage/repositories/consent.repository.d.ts +1 -0
  355. package/dist/src/storage/repositories/consent.repository.d.ts.map +1 -1
  356. package/dist/src/storage/repositories/device-auth.repository.d.ts +1 -0
  357. package/dist/src/storage/repositories/device-auth.repository.d.ts.map +1 -1
  358. package/dist/src/storage/repositories/extension-instance.repository.d.ts +1 -0
  359. package/dist/src/storage/repositories/extension-instance.repository.d.ts.map +1 -1
  360. package/dist/src/storage/repositories/index.d.ts +6 -0
  361. package/dist/src/storage/repositories/index.d.ts.map +1 -1
  362. package/dist/src/storage/repositories/knowledge.repository.d.ts +2 -0
  363. package/dist/src/storage/repositories/knowledge.repository.d.ts.map +1 -1
  364. package/dist/src/storage/repositories/moderation.repository.d.ts +1 -0
  365. package/dist/src/storage/repositories/moderation.repository.d.ts.map +1 -1
  366. package/dist/src/storage/repositories/sharing-group.repository.d.ts +17 -0
  367. package/dist/src/storage/repositories/sharing-group.repository.d.ts.map +1 -0
  368. package/dist/src/storage/repositories/sharing-group.repository.js +8 -0
  369. package/dist/src/storage/repositories/sharing-group.repository.js.map +1 -0
  370. package/dist/src/storage/repositories/stats.repository.d.ts +12 -0
  371. package/dist/src/storage/repositories/stats.repository.d.ts.map +1 -0
  372. package/dist/src/storage/repositories/stats.repository.js +7 -0
  373. package/dist/src/storage/repositories/stats.repository.js.map +1 -0
  374. package/dist/src/storage/storage-factory.js +1 -0
  375. package/dist/src/storage/storage-factory.js.map +1 -1
  376. package/dist/src/utils/password-validation.d.ts +8 -0
  377. package/dist/src/utils/password-validation.d.ts.map +1 -0
  378. package/dist/src/utils/password-validation.js +25 -0
  379. package/dist/src/utils/password-validation.js.map +1 -0
  380. package/dist/src/utils/service-summary.d.ts +6 -1
  381. package/dist/src/utils/service-summary.d.ts.map +1 -1
  382. package/dist/src/utils/service-summary.js +6 -1
  383. package/dist/src/utils/service-summary.js.map +1 -1
  384. package/package.json +97 -77
  385. package/prisma/schema.prisma +128 -10
@@ -48,6 +48,8 @@ import PackagesAdminTab from './admin/packages-tab.js';
48
48
  import MemoryAdminTab from './admin/memory-tab.js';
49
49
  import GeneratorDebugTab from './admin/generator-debug-tab.js';
50
50
  import CapabilitiesAdminTab from './admin/capabilities-tab.js';
51
+ import AgentTasksAdminTab from './admin/agent-tasks-tab.js';
52
+ import SharingGroupsAdminTab from './admin/sharing-groups-tab.js';
51
53
 
52
54
  // ── Sidebar nav structure ──
53
55
  const NAV_GROUPS = [
@@ -74,6 +76,8 @@ const NAV_GROUPS = [
74
76
  { id: 'realtime', icon: '\u{1F4E1}', key: 'dashboard.realtime', component: RealtimeTab, count: 'rooms' },
75
77
  { id: 'work', icon: '\u{1F4E6}', key: 'dashboard.work', component: WorkTab, count: 'work' },
76
78
  { id: 'memory-admin', icon: '\u{1F5C4}', key: 'dashboard.memoryAdmin', component: MemoryAdminTab },
79
+ { id: 'agent-tasks', icon: '\u{1F4CB}', key: 'dashboard.agentTasksTab', component: AgentTasksAdminTab },
80
+ { id: 'sharing-groups', icon: '\u{1F465}', key: 'dashboard.sharingGroupsTab', component: SharingGroupsAdminTab },
77
81
  { id: 'capabilities', icon: '⚡', key: 'capabilities.adminTitle', component: CapabilitiesAdminTab },
78
82
  ]},
79
83
  { key: 'dashboard.navInfrastructure', items: [
@@ -1,20 +1,522 @@
1
1
  /**
2
2
  * @file access-tab.js
3
3
  * @description Profile tab displaying session info, public key, owner key,
4
- * MCP endpoint details, and federation access management for the current user.
4
+ * MCP endpoint details, federation access management, sharing groups,
5
+ * and owner-level agent defaults.
6
+ * @structure
7
+ * - AccessTab (default export) -- main tab component
8
+ * - SharingGroupsSection -- CRUD for sharing groups with expandable member lists
9
+ * - AgentDefaultsSection -- owner-level default rules and token budget for agents
5
10
  * @version-history
6
- * v1.0.0 — 2026-03-16 — Initial access tab
7
- * v1.1.0 — 2026-03-17 — Replace inline styles with CSS classes
8
- * v1.2.0 — 2026-05-21 — Add Federation Access section for auth consent management
11
+ * v1.0.0 -- 2026-03-16 -- Initial access tab
12
+ * v1.1.0 -- 2026-03-17 -- Replace inline styles with CSS classes
13
+ * v1.2.0 -- 2026-05-21 -- Add Federation Access section for auth consent management
14
+ * v1.3.0 -- 2026-05-21 -- Add Sharing Groups and Agent Defaults sections
9
15
  */
10
16
  import { h } from 'preact';
11
- import { useState, useEffect } from 'preact/hooks';
17
+ import { useState, useEffect, useCallback, useRef } from 'preact/hooks';
12
18
  import htm from 'htm';
13
19
  const html = htm.bind(h);
14
20
  import { t } from '/js/i18n.js';
15
21
  import { escHtml, copyToClipboard } from '/js/utils.js';
16
22
  import { getNodeUrl } from '/js/services/auth.js';
17
23
  import { apiGet, apiPost, apiDelete } from '/js/api.js';
24
+ import { useConfirm } from '/components/Modal.js';
25
+ import * as groupsApi from '/js/services/sharing-groups.js';
26
+ import { getOwnerDefaults, upsertOwnerDefaults } from '/js/services/agent-directives.js';
27
+
28
+ /* ═══════════════════════════════════════════════════════════════════
29
+ Sharing Groups Section
30
+ ═══════════════════════════════════════════════════════════════════ */
31
+
32
+ function SharingGroupsSection({ showToast }) {
33
+ const { confirm, ConfirmUI } = useConfirm();
34
+ const [groups, setGroups] = useState(null);
35
+ const [expandedId, setExpandedId] = useState(null);
36
+ const [showCreate, setShowCreate] = useState(false);
37
+ const [creating, setCreating] = useState(false);
38
+
39
+ // Create form
40
+ const [formName, setFormName] = useState('');
41
+ const [formDesc, setFormDesc] = useState('');
42
+
43
+ // Add-member form (per-group)
44
+ const [addingTo, setAddingTo] = useState(null);
45
+ const [memberIdent, setMemberIdent] = useState('');
46
+ const [memberType, setMemberType] = useState('ghii');
47
+ const [memberRead, setMemberRead] = useState(true);
48
+ const [memberWrite, setMemberWrite] = useState(false);
49
+
50
+ // Edit group (inline)
51
+ const [editingId, setEditingId] = useState(null);
52
+ const [editName, setEditName] = useState('');
53
+ const [editDesc, setEditDesc] = useState('');
54
+ const [saving, setSaving] = useState(false);
55
+
56
+ const loadGroups = useCallback(async () => {
57
+ try {
58
+ const resp = await groupsApi.listGroups();
59
+ setGroups(resp?.data?.groups || []);
60
+ } catch {
61
+ setGroups([]);
62
+ }
63
+ }, []);
64
+
65
+ useEffect(() => { loadGroups(); }, [loadGroups]);
66
+
67
+ // Live update listener
68
+ const liveRef = useRef(loadGroups);
69
+ liveRef.current = loadGroups;
70
+ useEffect(() => {
71
+ const handler = () => liveRef.current();
72
+ window.addEventListener('aimeat-live-update', handler);
73
+ return () => window.removeEventListener('aimeat-live-update', handler);
74
+ }, []);
75
+
76
+ const handleCreate = useCallback(async () => {
77
+ if (!formName.trim()) {
78
+ showToast(t('profile.access.sgNameRequired') || 'Group name is required');
79
+ return;
80
+ }
81
+ setCreating(true);
82
+ try {
83
+ await groupsApi.createGroup({
84
+ name: formName.trim(),
85
+ description: formDesc.trim() || undefined,
86
+ members: [],
87
+ default_permissions: { read: true, write: false },
88
+ });
89
+ showToast(t('profile.access.sgCreated') || 'Sharing group created');
90
+ setShowCreate(false);
91
+ setFormName('');
92
+ setFormDesc('');
93
+ loadGroups();
94
+ } catch (e) {
95
+ showToast(e.message || (t('profile.access.sgCreateError') || 'Failed to create group'));
96
+ } finally {
97
+ setCreating(false);
98
+ }
99
+ }, [formName, formDesc, showToast, loadGroups]);
100
+
101
+ const handleDelete = useCallback((id, name) => {
102
+ confirm(
103
+ (t('profile.access.sgConfirmDelete') || 'Delete group "{name}"? This cannot be undone.').replace('{name}', name),
104
+ async () => {
105
+ try {
106
+ await groupsApi.deleteGroup(id);
107
+ showToast(t('profile.access.sgDeleted') || 'Sharing group deleted');
108
+ if (expandedId === id) setExpandedId(null);
109
+ loadGroups();
110
+ } catch (e) {
111
+ showToast(e.message || (t('profile.access.sgDeleteError') || 'Failed to delete group'));
112
+ }
113
+ },
114
+ { danger: true },
115
+ );
116
+ }, [confirm, showToast, loadGroups, expandedId]);
117
+
118
+ const startEdit = useCallback((group) => {
119
+ setEditingId(group.id);
120
+ setEditName(group.name);
121
+ setEditDesc(group.description || '');
122
+ }, []);
123
+
124
+ const handleUpdate = useCallback(async (id) => {
125
+ if (!editName.trim()) {
126
+ showToast(t('profile.access.sgNameRequired') || 'Group name is required');
127
+ return;
128
+ }
129
+ setSaving(true);
130
+ try {
131
+ await groupsApi.updateGroup(id, {
132
+ name: editName.trim(),
133
+ description: editDesc.trim() || undefined,
134
+ });
135
+ showToast(t('profile.access.sgUpdated') || 'Group updated');
136
+ setEditingId(null);
137
+ loadGroups();
138
+ } catch (e) {
139
+ showToast(e.message || (t('profile.access.sgUpdateError') || 'Failed to update group'));
140
+ } finally {
141
+ setSaving(false);
142
+ }
143
+ }, [editName, editDesc, showToast, loadGroups]);
144
+
145
+ const handleAddMember = useCallback(async (groupId) => {
146
+ if (!memberIdent.trim()) {
147
+ showToast(t('profile.access.sgMemberRequired') || 'Identifier is required');
148
+ return;
149
+ }
150
+ try {
151
+ await groupsApi.addMember(groupId, {
152
+ identifier: memberIdent.trim(),
153
+ identifier_type: memberType,
154
+ permissions: { read: memberRead, write: memberWrite },
155
+ });
156
+ showToast(t('profile.access.sgMemberAdded') || 'Member added');
157
+ setMemberIdent('');
158
+ setAddingTo(null);
159
+ loadGroups();
160
+ } catch (e) {
161
+ showToast(e.message || (t('profile.access.sgMemberAddError') || 'Failed to add member'));
162
+ }
163
+ }, [memberIdent, memberType, memberRead, memberWrite, showToast, loadGroups]);
164
+
165
+ const handleRemoveMember = useCallback((groupId, identifier) => {
166
+ confirm(
167
+ (t('profile.access.sgConfirmRemoveMember') || 'Remove "{name}" from this group?').replace('{name}', identifier),
168
+ async () => {
169
+ try {
170
+ await groupsApi.removeMember(groupId, identifier);
171
+ showToast(t('profile.access.sgMemberRemoved') || 'Member removed');
172
+ loadGroups();
173
+ } catch (e) {
174
+ showToast(e.message || (t('profile.access.sgMemberRemoveError') || 'Failed to remove member'));
175
+ }
176
+ },
177
+ { danger: true },
178
+ );
179
+ }, [confirm, showToast, loadGroups]);
180
+
181
+ const renderMemberRow = (groupId, member) => html`
182
+ <div class="mem-item" key=${member.identifier}>
183
+ <span class="mem-key">${escHtml(member.identifier)}</span>
184
+ <span class="badge ${member.identifierType === 'gaii' ? 'badge-info' : 'badge-muted'}">${member.identifierType}</span>
185
+ <span class="badge ${member.permissions?.read ? 'badge-success' : 'badge-muted'}">
186
+ ${t('profile.access.sgRead') || 'read'}
187
+ </span>
188
+ <span class="badge ${member.permissions?.write ? 'badge-success' : 'badge-muted'}">
189
+ ${t('profile.access.sgWrite') || 'write'}
190
+ </span>
191
+ <button class="btn-ghost btn-danger btn-sm" onClick=${(e) => { e.stopPropagation(); handleRemoveMember(groupId, member.identifier); }}>
192
+ ${t('profile.access.sgRemove') || 'Remove'}
193
+ </button>
194
+ </div>
195
+ `;
196
+
197
+ const renderGroupCard = (group) => {
198
+ const isExpanded = expandedId === group.id;
199
+ const isEditing = editingId === group.id;
200
+ const memberCount = (group.members || []).length;
201
+
202
+ return html`
203
+ <div class="card ${isExpanded ? 'card-expanded' : ''}" key=${group.id}>
204
+ <div class="card-header card-clickable" onClick=${() => setExpandedId(isExpanded ? null : group.id)}>
205
+ <span class="expand-icon">${isExpanded ? '▼' : '▶'}</span>
206
+ <div class="card-title">${escHtml(group.name)}</div>
207
+ <span class="badge badge-muted">${memberCount} ${t('profile.access.sgMembers') || 'members'}</span>
208
+ </div>
209
+ ${group.description && html`
210
+ <div class="card-subtitle">${escHtml(group.description)}</div>
211
+ `}
212
+
213
+ ${isExpanded && !isEditing && html`
214
+ <div class="card-detail">
215
+ <div class="detail-grid">
216
+ <div class="detail-item">
217
+ <span class="detail-label">${t('profile.access.sgDefaultPerms') || 'Default permissions'}</span>
218
+ <span class="detail-value">
219
+ ${group.defaultPermissions?.read ? (t('profile.access.sgRead') || 'read') : ''} ${group.defaultPermissions?.write ? (t('profile.access.sgWrite') || 'write') : ''}
220
+ </span>
221
+ </div>
222
+ ${group.createdAt && html`
223
+ <div class="detail-item">
224
+ <span class="detail-label">${t('profile.access.sgCreatedAt') || 'Created'}</span>
225
+ <span class="detail-value">${new Date(group.createdAt).toLocaleDateString()}</span>
226
+ </div>
227
+ `}
228
+ </div>
229
+
230
+ <h4 class="card-h3 mt-section">${t('profile.access.sgMemberList') || 'Members'}</h4>
231
+ ${memberCount === 0
232
+ ? html`<div class="empty">${t('profile.access.sgNoMembers') || 'No members yet'}</div>`
233
+ : (group.members || []).map(m => renderMemberRow(group.id, m))
234
+ }
235
+
236
+ ${addingTo === group.id ? html`
237
+ <div class="create-form">
238
+ <div class="form-row">
239
+ <label>${t('profile.access.sgMemberIdentifier') || 'Identifier (GHII or GAII)'}</label>
240
+ <input type="text" class="input-field input-sm"
241
+ placeholder=${'alice@node-id'}
242
+ value=${memberIdent} onInput=${e => setMemberIdent(e.target.value)}
243
+ onKeyDown=${e => e.key === 'Enter' && handleAddMember(group.id)} />
244
+ </div>
245
+ <div class="form-row">
246
+ <label>${t('profile.access.sgMemberType') || 'Type'}</label>
247
+ <select class="input-field input-sm" value=${memberType} onChange=${e => setMemberType(e.target.value)}>
248
+ <option value="ghii">GHII</option>
249
+ <option value="gaii">GAII</option>
250
+ </select>
251
+ </div>
252
+ <div class="flex-row-wrap">
253
+ <label class="flex-row">
254
+ <input type="checkbox" checked=${memberRead} onChange=${() => setMemberRead(!memberRead)} />
255
+ ${t('profile.access.sgRead') || 'Read'}
256
+ </label>
257
+ <label class="flex-row">
258
+ <input type="checkbox" checked=${memberWrite} onChange=${() => setMemberWrite(!memberWrite)} />
259
+ ${t('profile.access.sgWrite') || 'Write'}
260
+ </label>
261
+ </div>
262
+ <div class="form-actions">
263
+ <button class="btn-primary btn-sm" onClick=${() => handleAddMember(group.id)}>
264
+ ${t('profile.access.sgAddMember') || 'Add'}
265
+ </button>
266
+ <button class="btn-ghost btn-sm" onClick=${() => setAddingTo(null)}>
267
+ ${t('profile.access.sgCancel') || 'Cancel'}
268
+ </button>
269
+ </div>
270
+ </div>
271
+ ` : html`
272
+ <div class="card-actions">
273
+ <button class="btn-outline btn-sm" onClick=${(e) => { e.stopPropagation(); setAddingTo(group.id); setMemberIdent(''); setMemberType('ghii'); setMemberRead(true); setMemberWrite(false); }}>
274
+ ${t('profile.access.sgAddMember') || 'Add Member'}
275
+ </button>
276
+ <button class="btn-outline btn-sm" onClick=${(e) => { e.stopPropagation(); startEdit(group); }}>
277
+ ${t('profile.access.sgEdit') || 'Edit'}
278
+ </button>
279
+ <button class="btn-danger-solid btn-sm" onClick=${(e) => { e.stopPropagation(); handleDelete(group.id, group.name); }}>
280
+ ${t('profile.access.sgDelete') || 'Delete'}
281
+ </button>
282
+ </div>
283
+ `}
284
+ </div>
285
+ `}
286
+
287
+ ${isExpanded && isEditing && html`
288
+ <div class="card-detail" onClick=${(e) => e.stopPropagation()}>
289
+ <div class="flex-col">
290
+ <div class="form-row">
291
+ <label>${t('profile.access.sgGroupName') || 'Group name'}</label>
292
+ <input type="text" class="input-field input-sm"
293
+ value=${editName} onInput=${e => setEditName(e.target.value)} />
294
+ </div>
295
+ <div class="form-row">
296
+ <label>${t('profile.access.sgDescription') || 'Description'}</label>
297
+ <textarea class="input-field input-sm" rows="2"
298
+ value=${editDesc} onInput=${e => setEditDesc(e.target.value)} />
299
+ </div>
300
+ <div class="form-actions">
301
+ <button class="btn-primary btn-sm" onClick=${() => handleUpdate(group.id)} disabled=${saving}>
302
+ ${saving ? '...' : (t('profile.access.sgSave') || 'Save')}
303
+ </button>
304
+ <button class="btn-ghost btn-sm" onClick=${() => setEditingId(null)}>
305
+ ${t('profile.access.sgCancel') || 'Cancel'}
306
+ </button>
307
+ </div>
308
+ </div>
309
+ </div>
310
+ `}
311
+ </div>
312
+ `;
313
+ };
314
+
315
+ return html`
316
+ <h3 class="card-h3 mt-section">\u{1F465} ${t('profile.access.sgTitle') || 'Sharing Groups'}</h3>
317
+ <div class="section-desc">${t('profile.access.sgDesc') || 'Define groups of identities to share memory entries with. Assign a sharing group to memory keys to control who can read or write.'}</div>
318
+
319
+ ${groups === null
320
+ ? html`<div class="empty">${t('profile.access.sgLoading') || 'Loading...'}</div>`
321
+ : groups.length === 0
322
+ ? html`<div class="empty">${t('profile.access.sgEmpty') || 'No sharing groups yet.'}</div>`
323
+ : groups.map(renderGroupCard)
324
+ }
325
+
326
+ ${!showCreate ? html`
327
+ <div class="mb-1">
328
+ <button class="btn-primary" onClick=${() => setShowCreate(true)}>
329
+ ${t('profile.access.sgCreate') || 'New Group'}
330
+ </button>
331
+ </div>
332
+ ` : html`
333
+ <div class="create-form">
334
+ <h4 class="card-h3 mb-half">${t('profile.access.sgCreateTitle') || 'Create Sharing Group'}</h4>
335
+ <div class="flex-col">
336
+ <div class="form-row">
337
+ <label>${t('profile.access.sgGroupName') || 'Group name'}</label>
338
+ <input type="text" class="input-field input-sm"
339
+ placeholder=${t('profile.access.sgNamePlaceholder') || 'e.g. Team Alpha'}
340
+ value=${formName} onInput=${e => setFormName(e.target.value)}
341
+ onKeyDown=${e => e.key === 'Enter' && handleCreate()} />
342
+ </div>
343
+ <div class="form-row">
344
+ <label>${t('profile.access.sgDescription') || 'Description (optional)'}</label>
345
+ <textarea class="input-field input-sm" rows="2"
346
+ placeholder=${t('profile.access.sgDescPlaceholder') || 'What is this group for?'}
347
+ value=${formDesc} onInput=${e => setFormDesc(e.target.value)} />
348
+ </div>
349
+ <div class="form-actions">
350
+ <button class="btn-primary btn-sm" onClick=${handleCreate} disabled=${creating}>
351
+ ${creating ? '...' : (t('profile.access.sgCreateBtn') || 'Create')}
352
+ </button>
353
+ <button class="btn-ghost btn-sm" onClick=${() => setShowCreate(false)}>
354
+ ${t('profile.access.sgCancel') || 'Cancel'}
355
+ </button>
356
+ </div>
357
+ </div>
358
+ </div>
359
+ `}
360
+ <${ConfirmUI} />
361
+ `;
362
+ }
363
+
364
+ /* ═══════════════════════════════════════════════════════════════════
365
+ Agent Defaults Section
366
+ ═══════════════════════════════════════════════════════════════════ */
367
+
368
+ function AgentDefaultsSection({ showToast }) {
369
+ const [defaults, setDefaults] = useState(null);
370
+ const [editing, setEditing] = useState(false);
371
+ const [saving, setSaving] = useState(false);
372
+
373
+ // Edit state
374
+ const [editRules, setEditRules] = useState([]);
375
+ const [editBudget, setEditBudget] = useState('');
376
+ const [newRule, setNewRule] = useState('');
377
+
378
+ const loadDefaults = useCallback(async () => {
379
+ try {
380
+ const resp = await getOwnerDefaults();
381
+ setDefaults(resp?.data?.defaults || null);
382
+ } catch {
383
+ setDefaults(null);
384
+ }
385
+ }, []);
386
+
387
+ useEffect(() => { loadDefaults(); }, [loadDefaults]);
388
+
389
+ // Live update listener
390
+ const liveRef = useRef(loadDefaults);
391
+ liveRef.current = loadDefaults;
392
+ useEffect(() => {
393
+ const handler = () => liveRef.current();
394
+ window.addEventListener('aimeat-live-update', handler);
395
+ return () => window.removeEventListener('aimeat-live-update', handler);
396
+ }, []);
397
+
398
+ const startEdit = useCallback(() => {
399
+ const rules = defaults?.rules || [];
400
+ const budget = defaults?.default_token_budget;
401
+ setEditRules([...rules]);
402
+ setEditBudget(budget != null ? String(budget) : '');
403
+ setNewRule('');
404
+ setEditing(true);
405
+ }, [defaults]);
406
+
407
+ const handleSave = useCallback(async () => {
408
+ setSaving(true);
409
+ try {
410
+ const budgetVal = editBudget.trim() ? parseInt(editBudget, 10) : undefined;
411
+ if (editBudget.trim() && (isNaN(budgetVal) || budgetVal < 0)) {
412
+ showToast(t('profile.access.adInvalidBudget') || 'Token budget must be a non-negative number');
413
+ setSaving(false);
414
+ return;
415
+ }
416
+ await upsertOwnerDefaults({
417
+ rules: editRules,
418
+ default_token_budget: budgetVal,
419
+ default_memory_areas: defaults?.default_memory_areas || [],
420
+ });
421
+ showToast(t('profile.access.adSaved') || 'Agent defaults saved');
422
+ setEditing(false);
423
+ loadDefaults();
424
+ } catch (e) {
425
+ showToast(e.message || (t('profile.access.adSaveError') || 'Failed to save defaults'));
426
+ } finally {
427
+ setSaving(false);
428
+ }
429
+ }, [editRules, editBudget, defaults, showToast, loadDefaults]);
430
+
431
+ const addRule = useCallback(() => {
432
+ if (!newRule.trim()) return;
433
+ setEditRules(prev => [...prev, newRule.trim()]);
434
+ setNewRule('');
435
+ }, [newRule]);
436
+
437
+ const removeRule = useCallback((idx) => {
438
+ setEditRules(prev => prev.filter((_, i) => i !== idx));
439
+ }, []);
440
+
441
+ const rules = defaults?.rules || [];
442
+ const budget = defaults?.default_token_budget;
443
+
444
+ return html`
445
+ <h3 class="card-h3 mt-section">\u{1F916} ${t('profile.access.adTitle') || 'Agent Defaults'}</h3>
446
+ <div class="section-desc">${t('profile.access.adDesc') || 'Owner-level defaults that apply to all your agents unless overridden by per-agent directives.'}</div>
447
+
448
+ ${!editing ? html`
449
+ <div class="card">
450
+ <div class="flex-between mb-half">
451
+ <div class="card-title">${t('profile.access.adRules') || 'Default Rules'}</div>
452
+ <button class="btn-outline btn-sm" onClick=${startEdit}>
453
+ ${t('profile.access.adEdit') || 'Edit'}
454
+ </button>
455
+ </div>
456
+
457
+ ${rules.length === 0
458
+ ? html`<div class="empty">${t('profile.access.adNoRules') || 'No default rules set.'}</div>`
459
+ : rules.map((rule, i) => html`
460
+ <div class="mem-item" key=${i}>
461
+ <span class="mem-key">${escHtml(rule)}</span>
462
+ </div>
463
+ `)
464
+ }
465
+
466
+ <div class="mem-item">
467
+ <span class="mem-key">${t('profile.access.adTokenBudget') || 'Token Budget'}</span>
468
+ <span>${budget != null ? budget.toLocaleString() : (t('profile.access.adUnlimited') || 'Unlimited')}</span>
469
+ </div>
470
+ </div>
471
+ ` : html`
472
+ <div class="create-form">
473
+ <h4 class="card-h3 mb-half">${t('profile.access.adEditTitle') || 'Edit Agent Defaults'}</h4>
474
+ <div class="flex-col">
475
+ <div class="form-row">
476
+ <label>${t('profile.access.adRules') || 'Rules'}</label>
477
+ ${editRules.map((rule, i) => html`
478
+ <div class="mem-item" key=${i}>
479
+ <span class="mem-key">${escHtml(rule)}</span>
480
+ <button class="btn-ghost btn-danger btn-sm" onClick=${() => removeRule(i)}>
481
+ ${t('profile.access.adRemoveRule') || 'Remove'}
482
+ </button>
483
+ </div>
484
+ `)}
485
+ <div class="flex-row">
486
+ <input type="text" class="input-field input-sm"
487
+ placeholder=${t('profile.access.adRulePlaceholder') || 'Add a rule...'}
488
+ value=${newRule} onInput=${e => setNewRule(e.target.value)}
489
+ onKeyDown=${e => e.key === 'Enter' && addRule()} />
490
+ <button class="btn-outline btn-sm" onClick=${addRule}>
491
+ ${t('profile.access.adAddRule') || 'Add'}
492
+ </button>
493
+ </div>
494
+ </div>
495
+
496
+ <div class="form-row">
497
+ <label>${t('profile.access.adTokenBudget') || 'Token Budget'}</label>
498
+ <input type="number" class="input-field input-sm" min="0"
499
+ placeholder=${t('profile.access.adBudgetPlaceholder') || 'Leave empty for unlimited'}
500
+ value=${editBudget} onInput=${e => setEditBudget(e.target.value)} />
501
+ </div>
502
+
503
+ <div class="form-actions">
504
+ <button class="btn-primary btn-sm" onClick=${handleSave} disabled=${saving}>
505
+ ${saving ? '...' : (t('profile.access.adSave') || 'Save')}
506
+ </button>
507
+ <button class="btn-ghost btn-sm" onClick=${() => setEditing(false)}>
508
+ ${t('profile.access.adCancel') || 'Cancel'}
509
+ </button>
510
+ </div>
511
+ </div>
512
+ </div>
513
+ `}
514
+ `;
515
+ }
516
+
517
+ /* ═══════════════════════════════════════════════════════════════════
518
+ Main Access Tab
519
+ ═══════════════════════════════════════════════════════════════════ */
18
520
 
19
521
  export default function AccessTab({ session, showToast }) {
20
522
  const NODE_URL = getNodeUrl();
@@ -141,6 +643,7 @@ export default function AccessTab({ session, showToast }) {
141
643
  ${authConsents.filter(c => c.recipient !== '*').map(c => html`
142
644
  <div class="mem-item">
143
645
  <span class="mem-key">${escHtml(c.recipient.replace('node:', ''))}</span>
646
+ <span class="adm-text-dim" style="font-size:.85em">${c.granted_at ? new Date(c.granted_at).toLocaleDateString() : ''}</span>
144
647
  <button class="btn-ghost btn-danger" onClick=${() => removeAuthConsent(c.id)}>
145
648
  ${t('profile.access.fedRemove')}
146
649
  </button>
@@ -156,5 +659,8 @@ export default function AccessTab({ session, showToast }) {
156
659
  </button>
157
660
  </div>
158
661
  </div>
662
+
663
+ <${SharingGroupsSection} showToast=${showToast} />
664
+ <${AgentDefaultsSection} showToast=${showToast} />
159
665
  `;
160
666
  }