aimeat 1.19.0 → 1.20.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 (310) hide show
  1. package/README.md +39 -3
  2. package/dist/.env.example +5 -1
  3. package/dist/locales/en.json +231 -1
  4. package/dist/locales/fi.json +233 -1
  5. package/dist/public/components/Markdown.js +88 -15
  6. package/dist/public/components/Mermaid.js +59 -0
  7. package/dist/public/components/NotificationBell.js +94 -0
  8. package/dist/public/css/theme.css +26 -0
  9. package/dist/public/css/views/admin.css +16 -0
  10. package/dist/public/css/views/agents-detail.css +93 -0
  11. package/dist/public/css/views/profile.css +241 -2
  12. package/dist/public/js/api.js +11 -5
  13. package/dist/public/js/services/admin.js +4 -0
  14. package/dist/public/js/services/agents.js +19 -0
  15. package/dist/public/js/services/organisms.js +822 -2
  16. package/dist/public/lib/mermaid/README.md +6 -0
  17. package/dist/public/lib/mermaid/mermaid.min.js +3405 -0
  18. package/dist/public/lib/toastui/toastui-editor-all.min.js +24 -0
  19. package/dist/public/lib/toastui/toastui-editor.min.css +6 -0
  20. package/dist/public/llms-template.txt +4 -0
  21. package/dist/public/spa.html +8 -0
  22. package/dist/public/views/admin/security-tab.js +93 -0
  23. package/dist/public/views/admin.js +2 -0
  24. package/dist/public/views/doc-solo.js +102 -0
  25. package/dist/public/views/profile/agents/agent-card.js +67 -8
  26. package/dist/public/views/profile/agents/tab-messages.js +51 -7
  27. package/dist/public/views/profile/agents-tab.js +184 -4
  28. package/dist/public/views/profile/agents-tasks-subtab.js +11 -1
  29. package/dist/public/views/profile/generator-dashboard/use-autopilot.js +5 -2
  30. package/dist/public/views/profile/landing-page.js +12 -4
  31. package/dist/public/views/profile/organisms-tab.js +1640 -2
  32. package/dist/public/views/profile/schedule-item.js +15 -1
  33. package/dist/public/views/profile.js +6 -3
  34. package/dist/src/cli/connect/mcp/tools/index.d.ts.map +1 -1
  35. package/dist/src/cli/connect/mcp/tools/index.js +2 -0
  36. package/dist/src/cli/connect/mcp/tools/index.js.map +1 -1
  37. package/dist/src/cli/connect/mcp/tools/organisms.d.ts.map +1 -1
  38. package/dist/src/cli/connect/mcp/tools/organisms.js +31 -0
  39. package/dist/src/cli/connect/mcp/tools/organisms.js.map +1 -1
  40. package/dist/src/cli/connect/mcp/tools/workspaces.d.ts +15 -0
  41. package/dist/src/cli/connect/mcp/tools/workspaces.d.ts.map +1 -0
  42. package/dist/src/cli/connect/mcp/tools/workspaces.js +240 -0
  43. package/dist/src/cli/connect/mcp/tools/workspaces.js.map +1 -0
  44. package/dist/src/cli/connect/tool-call.d.ts +5 -0
  45. package/dist/src/cli/connect/tool-call.d.ts.map +1 -1
  46. package/dist/src/cli/connect/tool-call.js +255 -0
  47. package/dist/src/cli/connect/tool-call.js.map +1 -1
  48. package/dist/src/cli/init-wizard.d.ts.map +1 -1
  49. package/dist/src/cli/init-wizard.js +16 -8
  50. package/dist/src/cli/init-wizard.js.map +1 -1
  51. package/dist/src/config.d.ts +1 -1
  52. package/dist/src/config.d.ts.map +1 -1
  53. package/dist/src/config.js +4 -1
  54. package/dist/src/config.js.map +1 -1
  55. package/dist/src/generated/api-types.d.ts +998 -23
  56. package/dist/src/generated/api-types.d.ts.map +1 -1
  57. package/dist/src/generated/prisma-postgres/client.d.ts +1 -0
  58. package/dist/src/generated/prisma-postgres/client.js +5 -0
  59. package/dist/src/generated/prisma-postgres/default.d.ts +1 -0
  60. package/dist/src/generated/prisma-postgres/default.js +5 -0
  61. package/dist/src/generated/prisma-postgres/edge.d.ts +1 -0
  62. package/dist/src/generated/prisma-postgres/edge.js +1530 -0
  63. package/dist/src/generated/prisma-postgres/index-browser.js +1516 -0
  64. package/dist/src/generated/prisma-postgres/index.d.ts +128983 -0
  65. package/dist/src/generated/prisma-postgres/index.js +1551 -0
  66. package/dist/src/generated/prisma-postgres/package.json +183 -0
  67. package/dist/src/generated/prisma-postgres/query_engine-windows.dll.node +0 -0
  68. package/dist/src/generated/prisma-postgres/query_engine_bg.js +2 -0
  69. package/dist/src/generated/prisma-postgres/query_engine_bg.wasm +0 -0
  70. package/dist/src/generated/prisma-postgres/runtime/edge-esm.js +35 -0
  71. package/dist/src/generated/prisma-postgres/runtime/edge.js +35 -0
  72. package/dist/src/generated/prisma-postgres/runtime/index-browser.d.ts +370 -0
  73. package/dist/src/generated/prisma-postgres/runtime/index-browser.js +17 -0
  74. package/dist/src/generated/prisma-postgres/runtime/library.d.ts +3982 -0
  75. package/dist/src/generated/prisma-postgres/runtime/library.js +147 -0
  76. package/dist/src/generated/prisma-postgres/runtime/react-native.js +84 -0
  77. package/dist/src/generated/prisma-postgres/runtime/wasm-compiler-edge.js +85 -0
  78. package/dist/src/generated/prisma-postgres/runtime/wasm-engine-edge.js +38 -0
  79. package/dist/src/generated/prisma-postgres/schema.prisma +1465 -0
  80. package/dist/src/generated/prisma-postgres/wasm-edge-light-loader.mjs +5 -0
  81. package/dist/src/generated/prisma-postgres/wasm-worker-loader.mjs +5 -0
  82. package/dist/src/generated/prisma-postgres/wasm.d.ts +1 -0
  83. package/dist/src/generated/prisma-postgres/wasm.js +1537 -0
  84. package/dist/src/index.js +1 -1
  85. package/dist/src/mcp/agent-messages.d.ts +3 -0
  86. package/dist/src/mcp/agent-messages.d.ts.map +1 -1
  87. package/dist/src/mcp/agent-messages.js +9 -3
  88. package/dist/src/mcp/agent-messages.js.map +1 -1
  89. package/dist/src/mcp/annotations.d.ts.map +1 -1
  90. package/dist/src/mcp/annotations.js +12 -0
  91. package/dist/src/mcp/annotations.js.map +1 -1
  92. package/dist/src/mcp/catalog/definitions.d.ts.map +1 -1
  93. package/dist/src/mcp/catalog/definitions.js +139 -0
  94. package/dist/src/mcp/catalog/definitions.js.map +1 -1
  95. package/dist/src/mcp/catalog/surfaces.d.ts.map +1 -1
  96. package/dist/src/mcp/catalog/surfaces.js +9 -2
  97. package/dist/src/mcp/catalog/surfaces.js.map +1 -1
  98. package/dist/src/mcp/index.d.ts.map +1 -1
  99. package/dist/src/mcp/index.js +2 -0
  100. package/dist/src/mcp/index.js.map +1 -1
  101. package/dist/src/mcp/organisms.d.ts +2 -0
  102. package/dist/src/mcp/organisms.d.ts.map +1 -1
  103. package/dist/src/mcp/organisms.js +106 -21
  104. package/dist/src/mcp/organisms.js.map +1 -1
  105. package/dist/src/mcp/workspaces.d.ts +34 -0
  106. package/dist/src/mcp/workspaces.d.ts.map +1 -0
  107. package/dist/src/mcp/workspaces.js +464 -0
  108. package/dist/src/mcp/workspaces.js.map +1 -0
  109. package/dist/src/middleware/workspace-access.d.ts +13 -0
  110. package/dist/src/middleware/workspace-access.d.ts.map +1 -1
  111. package/dist/src/middleware/workspace-access.js +12 -7
  112. package/dist/src/middleware/workspace-access.js.map +1 -1
  113. package/dist/src/models/schemas.d.ts +2 -2
  114. package/dist/src/routes/admin-prompts.d.ts.map +1 -1
  115. package/dist/src/routes/admin-prompts.js +4 -1
  116. package/dist/src/routes/admin-prompts.js.map +1 -1
  117. package/dist/src/routes/admin-security.d.ts +19 -0
  118. package/dist/src/routes/admin-security.d.ts.map +1 -0
  119. package/dist/src/routes/admin-security.js +87 -0
  120. package/dist/src/routes/admin-security.js.map +1 -0
  121. package/dist/src/routes/agent-messages.d.ts +3 -0
  122. package/dist/src/routes/agent-messages.d.ts.map +1 -1
  123. package/dist/src/routes/agent-messages.js +27 -2
  124. package/dist/src/routes/agent-messages.js.map +1 -1
  125. package/dist/src/routes/agent-tasks.d.ts +5 -1
  126. package/dist/src/routes/agent-tasks.d.ts.map +1 -1
  127. package/dist/src/routes/agent-tasks.js +43 -3
  128. package/dist/src/routes/agent-tasks.js.map +1 -1
  129. package/dist/src/routes/apps.d.ts +13 -0
  130. package/dist/src/routes/apps.d.ts.map +1 -1
  131. package/dist/src/routes/apps.js +74 -42
  132. package/dist/src/routes/apps.js.map +1 -1
  133. package/dist/src/routes/bootstrap.d.ts.map +1 -1
  134. package/dist/src/routes/bootstrap.js +1 -0
  135. package/dist/src/routes/bootstrap.js.map +1 -1
  136. package/dist/src/routes/extensions.d.ts.map +1 -1
  137. package/dist/src/routes/extensions.js +5 -1
  138. package/dist/src/routes/extensions.js.map +1 -1
  139. package/dist/src/routes/generator-autopilot.d.ts +1 -0
  140. package/dist/src/routes/generator-autopilot.d.ts.map +1 -1
  141. package/dist/src/routes/generator-autopilot.js +8 -2
  142. package/dist/src/routes/generator-autopilot.js.map +1 -1
  143. package/dist/src/routes/generator.d.ts.map +1 -1
  144. package/dist/src/routes/generator.js +20 -0
  145. package/dist/src/routes/generator.js.map +1 -1
  146. package/dist/src/routes/libs.d.ts +4 -0
  147. package/dist/src/routes/libs.d.ts.map +1 -1
  148. package/dist/src/routes/libs.js +134 -5
  149. package/dist/src/routes/libs.js.map +1 -1
  150. package/dist/src/routes/memory.d.ts +2 -0
  151. package/dist/src/routes/memory.d.ts.map +1 -1
  152. package/dist/src/routes/memory.js +20 -10
  153. package/dist/src/routes/memory.js.map +1 -1
  154. package/dist/src/routes/notifications.d.ts +18 -0
  155. package/dist/src/routes/notifications.d.ts.map +1 -0
  156. package/dist/src/routes/notifications.js +64 -0
  157. package/dist/src/routes/notifications.js.map +1 -0
  158. package/dist/src/routes/organisms.d.ts +29 -0
  159. package/dist/src/routes/organisms.d.ts.map +1 -1
  160. package/dist/src/routes/organisms.js +1042 -2
  161. package/dist/src/routes/organisms.js.map +1 -1
  162. package/dist/src/routes/schedules.d.ts.map +1 -1
  163. package/dist/src/routes/schedules.js +10 -2
  164. package/dist/src/routes/schedules.js.map +1 -1
  165. package/dist/src/routes/storage-files.d.ts +5 -0
  166. package/dist/src/routes/storage-files.d.ts.map +1 -1
  167. package/dist/src/routes/storage-files.js +83 -16
  168. package/dist/src/routes/storage-files.js.map +1 -1
  169. package/dist/src/routes/upload.d.ts +3 -0
  170. package/dist/src/routes/upload.d.ts.map +1 -1
  171. package/dist/src/routes/upload.js +9 -1
  172. package/dist/src/routes/upload.js.map +1 -1
  173. package/dist/src/server-bootstrap/config-init.d.ts.map +1 -1
  174. package/dist/src/server-bootstrap/config-init.js +1 -0
  175. package/dist/src/server-bootstrap/config-init.js.map +1 -1
  176. package/dist/src/server-bootstrap/middleware-guards.d.ts.map +1 -1
  177. package/dist/src/server-bootstrap/middleware-guards.js +4 -2
  178. package/dist/src/server-bootstrap/middleware-guards.js.map +1 -1
  179. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  180. package/dist/src/server-bootstrap/routes-loader.js +4 -0
  181. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  182. package/dist/src/server-bootstrap/service-init.d.ts +17 -0
  183. package/dist/src/server-bootstrap/service-init.d.ts.map +1 -1
  184. package/dist/src/server-bootstrap/service-init.js +26 -0
  185. package/dist/src/server-bootstrap/service-init.js.map +1 -1
  186. package/dist/src/services/access-guard.d.ts +52 -0
  187. package/dist/src/services/access-guard.d.ts.map +1 -0
  188. package/dist/src/services/access-guard.js +30 -0
  189. package/dist/src/services/access-guard.js.map +1 -0
  190. package/dist/src/services/config-schema.js +1 -1
  191. package/dist/src/services/config-schema.js.map +1 -1
  192. package/dist/src/services/consent.d.ts.map +1 -1
  193. package/dist/src/services/consent.js +37 -1
  194. package/dist/src/services/consent.js.map +1 -1
  195. package/dist/src/services/gate-expiry.d.ts +25 -0
  196. package/dist/src/services/gate-expiry.d.ts.map +1 -0
  197. package/dist/src/services/gate-expiry.js +26 -0
  198. package/dist/src/services/gate-expiry.js.map +1 -0
  199. package/dist/src/services/gate-policy.d.ts +50 -0
  200. package/dist/src/services/gate-policy.d.ts.map +1 -0
  201. package/dist/src/services/gate-policy.js +82 -0
  202. package/dist/src/services/gate-policy.js.map +1 -0
  203. package/dist/src/services/generator-autopilot.d.ts +18 -1
  204. package/dist/src/services/generator-autopilot.d.ts.map +1 -1
  205. package/dist/src/services/generator-autopilot.js +94 -154
  206. package/dist/src/services/generator-autopilot.js.map +1 -1
  207. package/dist/src/services/handbooks/agent.d.ts +3 -1
  208. package/dist/src/services/handbooks/agent.d.ts.map +1 -1
  209. package/dist/src/services/handbooks/agent.js +10 -3
  210. package/dist/src/services/handbooks/agent.js.map +1 -1
  211. package/dist/src/services/manifest-schema.d.ts +48 -0
  212. package/dist/src/services/manifest-schema.d.ts.map +1 -0
  213. package/dist/src/services/manifest-schema.js +88 -0
  214. package/dist/src/services/manifest-schema.js.map +1 -0
  215. package/dist/src/services/notify.d.ts +19 -0
  216. package/dist/src/services/notify.d.ts.map +1 -0
  217. package/dist/src/services/notify.js +43 -0
  218. package/dist/src/services/notify.js.map +1 -0
  219. package/dist/src/services/organism-export.d.ts +13 -0
  220. package/dist/src/services/organism-export.d.ts.map +1 -0
  221. package/dist/src/services/organism-export.js +58 -0
  222. package/dist/src/services/organism-export.js.map +1 -0
  223. package/dist/src/services/organism-import.d.ts +16 -0
  224. package/dist/src/services/organism-import.d.ts.map +1 -0
  225. package/dist/src/services/organism-import.js +82 -0
  226. package/dist/src/services/organism-import.js.map +1 -0
  227. package/dist/src/services/prompt-defaults.d.ts.map +1 -1
  228. package/dist/src/services/prompt-defaults.js +75 -0
  229. package/dist/src/services/prompt-defaults.js.map +1 -1
  230. package/dist/src/services/safe-zip.d.ts +27 -0
  231. package/dist/src/services/safe-zip.d.ts.map +1 -0
  232. package/dist/src/services/safe-zip.js +131 -0
  233. package/dist/src/services/safe-zip.js.map +1 -0
  234. package/dist/src/services/scheduler.d.ts +19 -1
  235. package/dist/src/services/scheduler.d.ts.map +1 -1
  236. package/dist/src/services/scheduler.js +49 -17
  237. package/dist/src/services/scheduler.js.map +1 -1
  238. package/dist/src/services/security-incident.d.ts +25 -0
  239. package/dist/src/services/security-incident.d.ts.map +1 -0
  240. package/dist/src/services/security-incident.js +49 -0
  241. package/dist/src/services/security-incident.js.map +1 -0
  242. package/dist/src/services/skill-bundle/generator.d.ts +2 -0
  243. package/dist/src/services/skill-bundle/generator.d.ts.map +1 -1
  244. package/dist/src/services/skill-bundle/generator.js +11 -5
  245. package/dist/src/services/skill-bundle/generator.js.map +1 -1
  246. package/dist/src/services/template-bundles.d.ts +37 -0
  247. package/dist/src/services/template-bundles.d.ts.map +1 -0
  248. package/dist/src/services/template-bundles.js +130 -0
  249. package/dist/src/services/template-bundles.js.map +1 -0
  250. package/dist/src/services/workspace-export.d.ts +63 -0
  251. package/dist/src/services/workspace-export.d.ts.map +1 -0
  252. package/dist/src/services/workspace-export.js +145 -0
  253. package/dist/src/services/workspace-export.js.map +1 -0
  254. package/dist/src/services/workspace-import.d.ts +44 -0
  255. package/dist/src/services/workspace-import.d.ts.map +1 -0
  256. package/dist/src/services/workspace-import.js +120 -0
  257. package/dist/src/services/workspace-import.js.map +1 -0
  258. package/dist/src/services/workspace-meta.d.ts +39 -0
  259. package/dist/src/services/workspace-meta.d.ts.map +1 -0
  260. package/dist/src/services/workspace-meta.js +95 -0
  261. package/dist/src/services/workspace-meta.js.map +1 -0
  262. package/dist/src/storage/interface.d.ts +26 -0
  263. package/dist/src/storage/interface.d.ts.map +1 -1
  264. package/dist/src/storage/interface.js.map +1 -1
  265. package/dist/src/storage/pattern-utils.d.ts +26 -1
  266. package/dist/src/storage/pattern-utils.d.ts.map +1 -1
  267. package/dist/src/storage/pattern-utils.js +37 -8
  268. package/dist/src/storage/pattern-utils.js.map +1 -1
  269. package/dist/src/storage/providers/mongodb/index.d.ts +50 -7
  270. package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
  271. package/dist/src/storage/providers/mongodb/index.js +244 -15
  272. package/dist/src/storage/providers/mongodb/index.js.map +1 -1
  273. package/dist/src/storage/providers/postgres/index.d.ts +6 -0
  274. package/dist/src/storage/providers/postgres/index.d.ts.map +1 -0
  275. package/dist/src/storage/providers/postgres/index.js +33 -0
  276. package/dist/src/storage/providers/postgres/index.js.map +1 -0
  277. package/dist/src/storage/providers/sqlite/index.d.ts +11 -1
  278. package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
  279. package/dist/src/storage/providers/sqlite/index.js +152 -2
  280. package/dist/src/storage/providers/sqlite/index.js.map +1 -1
  281. package/dist/src/storage/providers/sqlite/repos/agent-task.d.ts +1 -0
  282. package/dist/src/storage/providers/sqlite/repos/agent-task.d.ts.map +1 -1
  283. package/dist/src/storage/providers/sqlite/repos/agent-task.js +5 -1
  284. package/dist/src/storage/providers/sqlite/repos/agent-task.js.map +1 -1
  285. package/dist/src/storage/providers/sqlite/repos/storage-file.d.ts.map +1 -1
  286. package/dist/src/storage/providers/sqlite/repos/storage-file.js +6 -2
  287. package/dist/src/storage/providers/sqlite/repos/storage-file.js.map +1 -1
  288. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  289. package/dist/src/storage/providers/sqlite/schema.js +23 -0
  290. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  291. package/dist/src/storage/repositories/app.repository.d.ts +42 -0
  292. package/dist/src/storage/repositories/app.repository.d.ts.map +1 -1
  293. package/dist/src/storage/repositories/organism.repository.d.ts +8 -1
  294. package/dist/src/storage/repositories/organism.repository.d.ts.map +1 -1
  295. package/dist/src/storage/storage-factory.d.ts +1 -1
  296. package/dist/src/storage/storage-factory.d.ts.map +1 -1
  297. package/dist/src/storage/storage-factory.js +6 -0
  298. package/dist/src/storage/storage-factory.js.map +1 -1
  299. package/dist/src/utils/env-config.js +5 -5
  300. package/dist/src/utils/env-config.js.map +1 -1
  301. package/dist/src/utils/env-validator.js +6 -6
  302. package/dist/src/utils/env-validator.js.map +1 -1
  303. package/dist/src/utils/stable-json.d.ts +22 -0
  304. package/dist/src/utils/stable-json.d.ts.map +1 -0
  305. package/dist/src/utils/stable-json.js +36 -0
  306. package/dist/src/utils/stable-json.js.map +1 -0
  307. package/dist/static/app-catalog.html +936 -221
  308. package/package.json +6 -3
  309. package/prisma/schema.postgres.prisma +1467 -0
  310. package/prisma/schema.prisma +27 -0
@@ -428,6 +428,21 @@ a { color: inherit; text-decoration: none; }
428
428
  gap: 0.75rem;
429
429
  }
430
430
 
431
+ /* Header notification bell + dropdown */
432
+ .notif-bell { position: relative; display: inline-flex; }
433
+ .notif-bell-btn { position: relative; background: none; border: none; cursor: pointer; font-size: 1.15rem; line-height: 1; padding: 4px 6px; border-radius: 8px; }
434
+ .notif-bell-btn:hover { background: var(--bg-dim); }
435
+ .notif-badge { position: absolute; top: -1px; right: -1px; background: var(--accent); color: #fff; border-radius: 10px; font-size: 0.6rem; font-weight: 700; min-width: 15px; height: 15px; padding: 0 3px; display: flex; align-items: center; justify-content: center; }
436
+ .notif-dropdown { position: absolute; right: 0; top: calc(100% + 6px); width: 320px; max-height: 60vh; overflow-y: auto; background: var(--card); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 10px 30px rgba(0,0,0,0.18); z-index: 1200; }
437
+ .notif-dropdown-head { font-weight: 700; font-size: 0.9rem; color: var(--text); padding: 0.6rem 0.85rem; border-bottom: 1px solid var(--border-subtle); position: sticky; top: 0; background: var(--card); }
438
+ .notif-empty { padding: 1rem 0.85rem; color: var(--muted); font-size: 0.85rem; }
439
+ .notif-item { display: block; width: 100%; text-align: left; background: none; border: none; border-bottom: 1px solid var(--border-subtle); padding: 0.55rem 0.85rem; cursor: pointer; }
440
+ .notif-item:hover { background: var(--bg-dim); }
441
+ .notif-item.unread { background: var(--accent-subtle); }
442
+ .notif-item-title { font-size: 0.85rem; font-weight: 600; color: var(--text); }
443
+ .notif-item-body { font-size: 0.78rem; color: var(--muted); margin-top: 0.15rem; }
444
+ .notif-item-time { font-size: 0.7rem; color: var(--muted); margin-top: 0.2rem; }
445
+
431
446
  .topnav-right a {
432
447
  font-size: 0.84rem;
433
448
  color: var(--text-dim);
@@ -824,6 +839,17 @@ a { color: inherit; text-decoration: none; }
824
839
  }
825
840
  .pill:hover { opacity: 0.8; }
826
841
 
842
+ /* ── Segmented control (canonical) ──
843
+ A row of buttons in a bordered pill; the active segment is filled with the accent. Token-only so
844
+ it flips in dark mode. The start of the deferred #8 tab-family consolidation — use this for new
845
+ in-place view toggles (Draft/Published, picker tabs, scope toggles) instead of a per-view clone. */
846
+ .seg { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--card); }
847
+ .seg-btn { padding: 0.25rem 0.7rem; font-size: 0.8rem; line-height: 1.3; background: transparent; color: var(--text-dim); border: none; cursor: pointer; transition: background 0.15s, color 0.15s; }
848
+ .seg-btn + .seg-btn { border-left: 1px solid var(--border); }
849
+ .seg-btn:hover:not(:disabled) { background: var(--bg-surface); }
850
+ .seg-btn.active { background: var(--accent); color: #fff; }
851
+ .seg-btn:disabled { opacity: 0.6; cursor: default; }
852
+
827
853
  /* ── Status dot (canonical) ──
828
854
  Small circle whose color is driven by a semantic status token. Consolidates
829
855
  the bespoke per-view dots (.live-dot, .peer-dot, .pn-status-dot,
@@ -728,3 +728,19 @@
728
728
  vertical-align: middle;
729
729
  margin-left: 6px;
730
730
  }
731
+
732
+ /* Security tab — incident list */
733
+ .adm-sec-title { font-size: 1.05rem; font-weight: 700; margin: 0 0 0.3rem; }
734
+ .adm-sec-desc { color: var(--muted); font-size: 0.85rem; margin: 0 0 0.75rem; }
735
+ .adm-sec-empty { color: var(--muted); padding: 0.75rem 0; }
736
+ .adm-sec-list { display: flex; flex-direction: column; gap: 0.5rem; }
737
+ .adm-sec-row { display: flex; gap: 0.75rem; justify-content: space-between; align-items: flex-start; border: 1px solid var(--border); border-radius: 8px; padding: 0.6rem 0.75rem; background: var(--card); }
738
+ .adm-sec-row.open { border-color: var(--danger); border-left-width: 3px; }
739
+ .adm-sec-main { min-width: 0; flex: 1; }
740
+ .adm-sec-line1 { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
741
+ .adm-sec-type { font-weight: 600; color: var(--text); }
742
+ .adm-sec-code { font-size: 0.78rem; background: var(--bg-dim); padding: 0.05rem 0.35rem; border-radius: 4px; }
743
+ .adm-sec-when { font-size: 0.74rem; color: var(--muted); margin-left: auto; }
744
+ .adm-sec-line2 { font-size: 0.82rem; color: var(--text); margin: 0.25rem 0; word-break: break-word; }
745
+ .adm-sec-line3 { font-size: 0.76rem; color: var(--muted); }
746
+ .adm-sec-actions { display: flex; gap: 0.35rem; flex-shrink: 0; flex-wrap: wrap; }
@@ -57,6 +57,8 @@
57
57
  * v2.11.0 -- 2026-05-31 -- Widen the solo pop-out window (and pf-agd-solo max-width) so the agent card matches the list-view width and the full tab bar fits
58
58
  * v2.12.0 -- 2026-05-31 -- Add completed-task deliverable styles (pf-agd-deliverable*) linking a task to its agent-memory output key
59
59
  * v2.13.0 -- 2026-05-31 -- Add per-task blur-title toggle styles (pf-agd-blur-toggle, pf-agd-task-title--blurred) for hiding sensitive titles in screen recordings
60
+ * v2.26.0 -- 2026-06-09 -- Add custom agent-group styles (pf-agd-cgroup-bar/header/toggle/name/empty) for the drag-to-assign "Custom groups" list mode
61
+ * v2.27.0 -- 2026-06-09 -- Add editable tag-strip styles (pf-agd-tag-chip--editable, pf-agd-tag-chip-remove, pf-agd-tag-add-btn/input) for inline tag add/remove in the expanded card header
60
62
  */
61
63
 
62
64
  /* Header row: title left, connect button right */
@@ -1576,6 +1578,43 @@
1576
1578
  border-color: var(--blue, #3B82F6);
1577
1579
  }
1578
1580
 
1581
+ /* Editable tag strip in the expanded card header (inline add/remove) */
1582
+ .pf .pf-agd-tag-chip--editable { cursor: default; gap: 0.3rem; padding-right: 0.3rem; }
1583
+ .pf .pf-agd-tag-chip-remove {
1584
+ background: none;
1585
+ border: none;
1586
+ cursor: pointer;
1587
+ color: var(--text-muted, #9CA3AF);
1588
+ font-size: 0.9rem;
1589
+ line-height: 1;
1590
+ padding: 0 0.1rem;
1591
+ border-radius: 9999px;
1592
+ }
1593
+ .pf .pf-agd-tag-chip-remove:hover { color: var(--danger, #E8564A); }
1594
+ .pf .pf-agd-tag-add-btn {
1595
+ display: inline-flex;
1596
+ align-items: center;
1597
+ padding: 0.15rem 0.5rem;
1598
+ font-size: 0.75rem;
1599
+ font-weight: 500;
1600
+ border-radius: 9999px;
1601
+ background: none;
1602
+ color: var(--accent, #E8564A);
1603
+ border: 1px dashed var(--border, #E5E7EB);
1604
+ cursor: pointer;
1605
+ white-space: nowrap;
1606
+ }
1607
+ .pf .pf-agd-tag-add-btn:hover { border-color: var(--accent, #E8564A); }
1608
+ .pf .pf-agd-tag-add-input {
1609
+ padding: 0.15rem 0.5rem;
1610
+ font-size: 0.75rem;
1611
+ border-radius: 9999px;
1612
+ border: 1px solid var(--accent, #E8564A);
1613
+ background: var(--card-bg, #FFFFFF);
1614
+ color: var(--text, #1A1A2E);
1615
+ width: 9rem;
1616
+ }
1617
+
1579
1618
  /* Tag filter bar + group-by control */
1580
1619
  .pf .pf-agd-filter-bar {
1581
1620
  display: flex;
@@ -1635,6 +1674,60 @@
1635
1674
  color: var(--text-muted, #6B7280);
1636
1675
  }
1637
1676
 
1677
+ /* ── Custom groups (user-defined sections, drag-to-assign) ── */
1678
+ .pf .pf-agd-cgroup-bar {
1679
+ display: flex;
1680
+ align-items: center;
1681
+ gap: 0.6rem;
1682
+ flex-wrap: wrap;
1683
+ margin-bottom: 0.75rem;
1684
+ }
1685
+ .pf .pf-agd-cgroup-hint {
1686
+ color: var(--text-muted, #6B7280);
1687
+ font-size: 0.78rem;
1688
+ }
1689
+ /* The header doubles as the drop target for filing agents into the group. */
1690
+ .pf .pf-agd-cgroup-header {
1691
+ cursor: default;
1692
+ }
1693
+ .pf .pf-agd-cgroup-toggle {
1694
+ background: none;
1695
+ border: none;
1696
+ cursor: pointer;
1697
+ color: var(--text-muted, #9CA3AF);
1698
+ font-size: 0.7rem;
1699
+ padding: 0 0.1rem;
1700
+ line-height: 1;
1701
+ }
1702
+ .pf .pf-agd-cgroup-toggle:hover { color: var(--accent, #E8564A); }
1703
+ .pf .pf-agd-cgroup-name {
1704
+ flex: 1;
1705
+ text-align: left;
1706
+ background: none;
1707
+ border: none;
1708
+ cursor: text;
1709
+ font-weight: 600;
1710
+ font-size: 0.9rem;
1711
+ color: var(--text, #1A1A2E);
1712
+ padding: 0.1rem 0.2rem;
1713
+ border-radius: 4px;
1714
+ }
1715
+ .pf .pf-agd-cgroup-name:hover { background: var(--bg-surface, #F3F4F6); }
1716
+ .pf .pf-agd-cgroup-name-input {
1717
+ flex: 1;
1718
+ font-weight: 600;
1719
+ font-size: 0.9rem;
1720
+ }
1721
+ .pf .pf-agd-cgroup-empty {
1722
+ font-size: 0.82rem;
1723
+ color: var(--text-muted, #9CA3AF);
1724
+ font-style: italic;
1725
+ padding: 0.5rem 0.25rem;
1726
+ border: 1px dashed var(--border, #E5E7EB);
1727
+ border-radius: 8px;
1728
+ margin-bottom: 0.5rem;
1729
+ }
1730
+
1638
1731
  /* ── Expanded Card ── */
1639
1732
 
1640
1733
  .pf .pf-agd-expanded {
@@ -4,6 +4,11 @@
4
4
  * wallet, memory, agents, extensions, packages, knowledge, generator, and
5
5
  * edit panels. Consumes theme.css tokens so it flips with dark/light mode.
6
6
  * @version-history
7
+ * v1.11.0 — 2026-06-08 — Full-bleed dashboard shell: drop the 1000px cap on the
8
+ * .pf wrapper so the sidebar+content fill the viewport like the admin dashboard
9
+ * (tab content was squeezed to ~760px). Sidebar stays left-anchored; .pf-content
10
+ * caps at 1360px (~1600px total) for readability on ultra-wide; login prompt
11
+ * stays a centered 1000px column.
7
12
  * v1.1.0 — 2026-06-02 — Phase 3a: tokenize hero/cta/callout gradients, card/tab/
8
13
  * stat/input surfaces, feedback banners, and undefined-var drift (via theme.css
9
14
  * alias layer) for dark mode. pf-gen-* badge contrast deferred to 3b.
@@ -51,7 +56,13 @@
51
56
  */
52
57
  .pf-hero{background:var(--pf-hero-gradient);border-bottom:1px solid var(--border,#E5E7EB)}
53
58
  .pf-hero-inner{max-width:1000px;margin:0 auto;padding:2rem 1.5rem 0}
54
- .pf{max-width:1000px;margin:0 auto;padding:1.5rem 1.5rem 2rem;position:relative;z-index:1}
59
+ /* Full-bleed dashboard shell (like the admin dashboard): the sidebar+content
60
+ flex fills the viewport instead of being capped to a narrow centered column.
61
+ The old 1000px cap squeezed tab content (organisms, etc.) into ~760px. The
62
+ not-logged-in login prompt is centered on its own (.login-prompt), and the
63
+ home dashboard / tab content get breathing room via .pf-content padding. */
64
+ .pf{max-width:none;margin:0;padding:0;position:relative;z-index:1}
65
+ .pf .login-prompt{max-width:1000px;margin:0 auto}
55
66
  .pf .bg-aurora{position:fixed;top:0;left:0;width:100%;height:100%;z-index:0;pointer-events:none}
56
67
  .pf .aurora-wave{position:absolute;width:200%;height:60%;left:-50%;border-radius:50%;filter:blur(80px);opacity:.25;animation:pfAurora 8s ease-in-out infinite alternate}
57
68
  .pf .aurora-wave:nth-child(1){top:10%;background:linear-gradient(90deg,#ff6b9d,#c44569,#ff8a80,#f48fb1);animation-duration:8s}
@@ -1969,7 +1980,11 @@
1969
1980
  .pf-side-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1970
1981
  .pf-side-badge { margin-left: auto; font-size: 0.68rem; background: var(--bg-dim); color: var(--text-dim); padding: 0.05rem 0.45rem; border-radius: var(--radius-full, 999px); }
1971
1982
 
1972
- .pf-content { flex: 1 1 auto; min-width: 0; padding: 1.25rem 1.5rem; }
1983
+ /* Content fills the space next to the (left-anchored) sidebar, but caps at
1984
+ ~1360px so the total usable width settles around 1600px on ultra-wide
1985
+ monitors — readable line lengths, no full-bleed stretch. Extra space falls
1986
+ to the right; the sidebar stays flush to the screen's left edge. */
1987
+ .pf-content { flex: 1 1 auto; min-width: 0; max-width: 1360px; padding: 1.25rem 1.5rem; }
1973
1988
  .pf-content-head { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1rem; }
1974
1989
  .pf-back-btn { background: none; border: 1px solid var(--border); color: var(--text-dim); border-radius: var(--radius-sm, 8px); padding: 0.3rem 0.7rem; cursor: pointer; font: inherit; font-size: 0.85rem; }
1975
1990
  .pf-back-btn:hover { background: var(--bg-hover, var(--bg-dim)); }
@@ -2000,3 +2015,227 @@
2000
2015
  .pf { padding: 0.6rem 0.35rem 1.5rem; }
2001
2016
  .pf-content { padding: 0.5rem 0.35rem 1.5rem; }
2002
2017
  }
2018
+
2019
+ /* ── Projects tab (pj-) ── */
2020
+ .pj-ws { display: flex; flex-direction: column; gap: 0.5rem; }
2021
+ .pj-gate { margin: 0.25rem 0 0.5rem; }
2022
+ .pj-gate-label { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.85rem; color: var(--muted); cursor: pointer; }
2023
+ .pj-inbox { border: 1px solid var(--border); border-radius: 10px; padding: 0.75rem; background: var(--bg-dim); margin-bottom: 0.5rem; }
2024
+ .pj-approval { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.4rem 0; border-top: 1px solid var(--border); }
2025
+ .pj-approval:first-of-type { border-top: none; }
2026
+ .pj-approval-text { flex: 1; font-size: 0.88rem; }
2027
+ .pj-section { border: 1px solid var(--border); border-radius: 10px; padding: 0.6rem 0.75rem; background: var(--surface); }
2028
+ .pj-section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.4rem; }
2029
+ .pj-section-title { font-weight: 600; text-transform: capitalize; }
2030
+ .pj-draft-form { margin: 0.4rem 0; }
2031
+ .pj-drafts { display: flex; flex-direction: column; gap: 0.3rem; margin-bottom: 0.3rem; }
2032
+ .pj-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0; }
2033
+ .pj-item-draft { border-left: 3px solid var(--border); padding-left: 0.5rem; }
2034
+ .pj-item-text { flex: 1; font-size: 0.9rem; }
2035
+ .pj-rec { border-radius: 6px; }
2036
+ .pj-rec-title { flex: 1; text-align: left; background: none; border: none; cursor: pointer; font-size: 0.9rem; color: var(--text); padding: 0; }
2037
+ .pj-rec-title:hover { color: var(--accent); }
2038
+ .pj-rec-fields { margin: 0.1rem 0 0.4rem 0.6rem; padding: 0.2rem 0.6rem; border-left: 2px solid var(--border); background: var(--bg-dim); border-radius: 0 6px 6px 0; }
2039
+ .pj-rec-empty { font-size: 0.82rem; padding: 0.2rem 0; }
2040
+ .pj-empty { color: var(--muted); font-size: 0.85rem; padding: 0.2rem 0; }
2041
+ .pj-decision { font-size: 0.85rem; color: var(--muted); }
2042
+ .pj-field { display: flex; flex-direction: column; gap: 0.2rem; margin-bottom: 0.35rem; }
2043
+ .pj-field > span { font-size: 0.75rem; color: var(--muted); }
2044
+ .pj-field-inline { flex-direction: row; align-items: center; gap: 0.4rem; }
2045
+ .pj-errors { border: 1px solid var(--danger); border-radius: 10px; padding: 0.6rem 0.75rem; margin: 0.5rem 0; background: var(--bg-dim); }
2046
+ .pj-errors-title { font-weight: 600; margin-bottom: 0.3rem; color: var(--danger); }
2047
+ .pj-error-line { font-size: 0.82rem; color: var(--text); padding: 0.1rem 0; }
2048
+ .pj-doc-tag { font-size: 0.68rem; color: var(--muted); border: 1px solid var(--border); border-radius: 6px; padding: 0 0.3rem; margin-left: 0.4rem; vertical-align: middle; }
2049
+ .pj-doc-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0; }
2050
+ .pj-doc-link { background: none; border: none; color: var(--accent); cursor: pointer; font-size: 0.9rem; text-align: left; flex: 1; padding: 0; }
2051
+ .pj-doc-link:hover { text-decoration: underline; }
2052
+ /* The detail / reading pane — a white, slightly elevated card so it reads as the focused content,
2053
+ distinct from the flat tree panel beside it. */
2054
+ .pj-doc-view { border: 1px solid var(--border); border-radius: 10px; padding: 1.4rem 1.8rem; margin: 0.4rem 0; background: var(--card); box-shadow: var(--shadow-sm); }
2055
+ .pj-doc-meta { margin: 0 0 0.5rem; }
2056
+ /* Popped-out single-document window (doc-solo.js) */
2057
+ .pj-doc-solo { max-width: 920px; margin: 0 auto; padding: 1rem 1.2rem 3rem; }
2058
+ .pj-doc-solo-empty { color: var(--muted); text-align: center; padding: 3rem 1rem; }
2059
+ .pj-doc-solo-toast { position: fixed; bottom: 1.1rem; left: 50%; transform: translateX(-50%); background: var(--text); color: var(--card); padding: 0.5rem 1rem; border-radius: 8px; font-size: 0.85rem; box-shadow: var(--shadow-md); z-index: 50; }
2060
+
2061
+ /* Document typography — make rendered markdown read like a real document.
2062
+ Generous line-height, clear space above headings, comfortable list + code styling. */
2063
+ .pj-doc-view .md-body { font-size: 0.95rem; line-height: 1.7; color: var(--text); max-width: 78ch; overflow-wrap: break-word; }
2064
+ .pj-doc-view .md-body > :first-child { margin-top: 0; }
2065
+ .pj-doc-view .md-body > :last-child { margin-bottom: 0; }
2066
+ .pj-doc-view .md-body h1,
2067
+ .pj-doc-view .md-body h2,
2068
+ .pj-doc-view .md-body h3,
2069
+ .pj-doc-view .md-body h4,
2070
+ .pj-doc-view .md-body h5,
2071
+ .pj-doc-view .md-body h6 { font-weight: 700; line-height: 1.3; color: var(--text); margin: 1.8em 0 0.6em; }
2072
+ .pj-doc-view .md-body h1 { font-size: 1.7rem; letter-spacing: -0.01em; padding-bottom: 0.3em; border-bottom: 2px solid var(--border); margin-top: 0.2em; }
2073
+ .pj-doc-view .md-body h2 { font-size: 1.32rem; padding-bottom: 0.25em; border-bottom: 1px solid var(--border); }
2074
+ .pj-doc-view .md-body h3 { font-size: 1.13rem; }
2075
+ .pj-doc-view .md-body h4 { font-size: 1rem; }
2076
+ .pj-doc-view .md-body h5 { font-size: 0.9rem; }
2077
+ .pj-doc-view .md-body h6 { font-size: 0.85rem; color: var(--muted); }
2078
+ .pj-doc-view .md-body p { margin: 0.85em 0; }
2079
+ .pj-doc-view .md-body ul,
2080
+ .pj-doc-view .md-body ol { margin: 0.7em 0; padding-left: 1.7em; }
2081
+ .pj-doc-view .md-body ul { list-style: disc; }
2082
+ .pj-doc-view .md-body ol { list-style: decimal; }
2083
+ .pj-doc-view .md-body li { margin: 0.32em 0; padding-left: 0.2em; }
2084
+ .pj-doc-view .md-body li > ul,
2085
+ .pj-doc-view .md-body li > ol { margin: 0.32em 0; }
2086
+ .pj-doc-view .md-body a { color: var(--accent); text-decoration: none; }
2087
+ .pj-doc-view .md-body a:hover { text-decoration: underline; }
2088
+ .pj-doc-view .md-body strong { font-weight: 700; color: var(--text); }
2089
+ .pj-doc-view .md-body .md-code { font-family: var(--font-mono, ui-monospace, "SF Mono", Menlo, Consolas, monospace); font-size: 0.85em; background: var(--bg-dim); padding: 0.12em 0.42em; border-radius: 4px; border: 1px solid var(--border-subtle, var(--border)); }
2090
+ .pj-doc-view .md-body .md-pre { background: var(--bg-dim); border: 1px solid var(--border); border-radius: 8px; padding: 0.9em 1.1em; overflow-x: auto; margin: 1em 0; line-height: 1.5; }
2091
+ .pj-doc-view .md-body .md-pre .md-code { background: none; border: none; padding: 0; font-size: 0.84rem; }
2092
+ .pj-doc-view .md-body blockquote { margin: 1em 0; padding: 0.3em 1.1em; border-left: 3px solid var(--accent); background: var(--bg-dim); border-radius: 0 6px 6px 0; color: var(--muted); }
2093
+ .pj-doc-view .md-body blockquote p { margin: 0.4em 0; }
2094
+ .pj-doc-view .md-body table { border-collapse: collapse; margin: 1em 0; width: 100%; font-size: 0.9rem; }
2095
+ .pj-doc-view .md-body th,
2096
+ .pj-doc-view .md-body td { border: 1px solid var(--border); padding: 0.45em 0.75em; text-align: left; vertical-align: top; }
2097
+ .pj-doc-view .md-body th { background: var(--bg-dim); font-weight: 600; }
2098
+ .pj-doc-view .md-body tbody tr:nth-child(even) { background: var(--bg-dim); }
2099
+ .pj-doc-view .md-body .md-img { max-width: 100%; height: auto; border-radius: 6px; margin: 0.6em 0; }
2100
+ .pj-doc-view .md-body hr { border: none; border-top: 1px solid var(--border); margin: 1.6em 0; }
2101
+ /* Deterministic Mermaid charts (organism overview, workspace edit-flow) */
2102
+ .pj-chart { border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 0.5rem 0.75rem; margin-bottom: 0.6rem; box-shadow: var(--shadow-sm); }
2103
+ .pj-chart-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.3rem; }
2104
+ .pj-chart-title { font-weight: 600; font-size: 0.9rem; color: var(--text); }
2105
+ .mmd { overflow-x: auto; text-align: center; }
2106
+ .mmd svg { max-width: 100%; height: auto; }
2107
+ .mmd-fallback { font-size: 0.74rem; white-space: pre-wrap; color: var(--text-dim); background: var(--bg-dim); padding: 0.5rem; border-radius: 6px; overflow: auto; }
2108
+ /* Participants panel — node → owner → agents listing */
2109
+ .pj-parts { padding: 0.1rem; }
2110
+ .pj-parts-list { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.7rem; }
2111
+ .pj-part-owner { border: 1px solid var(--border); border-radius: 8px; padding: 0.5rem 0.7rem; background: var(--card); }
2112
+ .pj-part-human { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; font-size: 0.88rem; }
2113
+ .pj-part-node { font-size: 0.74rem; color: var(--muted); }
2114
+ .pj-part-count { font-size: 0.72rem; color: var(--muted); background: var(--bg-dim); border-radius: 10px; padding: 0.05rem 0.45rem; }
2115
+ .pj-part-agents { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.45rem; padding-left: 1.4rem; }
2116
+ .pj-part-agent { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.8rem; border: 1px solid var(--border); border-radius: 6px; padding: 0.12rem 0.5rem; }
2117
+ .pj-part-agent.own { border-color: var(--success); }
2118
+ .pj-part-agent.ghost { color: var(--muted); border-style: dashed; opacity: 0.65; }
2119
+ /* Activity panel — GitHub-style contribution heatmap + audit-log feed */
2120
+ .pj-act { padding: 0.1rem; }
2121
+ .pj-act-count { font-size: 0.72rem; font-weight: 500; color: var(--muted); margin-left: 0.5rem; }
2122
+ .pj-act-dot { width: 9px; height: 9px; border-radius: 3px; display: inline-block; flex-shrink: 0; }
2123
+ .pj-act-dot.draft { background: var(--orange); }
2124
+ .pj-act-dot.publish { background: var(--success); }
2125
+ /* Heatmap — bigger cells, each split 2×2 (docs draft/pub · records draft/pub) */
2126
+ .pj-hm { overflow-x: auto; padding-bottom: 0.2rem; }
2127
+ .pj-hm-monthrow { display: flex; padding-left: 28px; }
2128
+ .pj-hm-month { flex: 0 0 16px; font-size: 0.64rem; color: var(--muted); white-space: nowrap; overflow: visible; }
2129
+ .pj-hm-body { display: flex; }
2130
+ .pj-hm-daycol { display: flex; flex-direction: column; gap: 2px; width: 28px; flex-shrink: 0; }
2131
+ .pj-hm-daycol span { height: 14px; line-height: 14px; font-size: 0.62rem; color: var(--muted); }
2132
+ .pj-hm-cols { display: flex; gap: 2px; }
2133
+ .pj-hm-col { display: flex; flex-direction: column; gap: 2px; }
2134
+ .pj-hm-cell { width: 14px; height: 14px; border-radius: 2px; flex-shrink: 0; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 1px; overflow: hidden; }
2135
+ .pj-hm-cell.future { background: transparent; }
2136
+ .pj-hm-cell .q { width: 100%; height: 100%; border-radius: 1px; }
2137
+ .q { display: inline-block; }
2138
+ .q.lvl0 { background: var(--bg-dim); }
2139
+ .q.lvl1 { background: color-mix(in srgb, var(--success) 32%, var(--bg-dim)); }
2140
+ .q.lvl2 { background: color-mix(in srgb, var(--success) 56%, var(--bg-dim)); }
2141
+ .q.lvl3 { background: color-mix(in srgb, var(--success) 80%, var(--bg-dim)); }
2142
+ .q.lvl4 { background: var(--success); }
2143
+ /* Legend — a 2×2 key explaining the quadrants + the Less→More intensity ramp */
2144
+ .pj-hm-legend { display: flex; align-items: center; justify-content: space-between; gap: 1.2rem; flex-wrap: wrap; margin: 0.55rem 0 0.7rem; font-size: 0.72rem; color: var(--muted); }
2145
+ .pj-hm-quadkey { display: flex; align-items: center; gap: 0.55rem; }
2146
+ .pj-hm-quadkey .pj-hm-cell { width: 28px; height: 28px; gap: 2px; }
2147
+ .pj-hm-quadlabels { display: grid; grid-template-columns: auto auto; gap: 0.12rem 0.9rem; }
2148
+ .pj-hm-intensity { display: flex; align-items: center; gap: 3px; }
2149
+ .pj-hm-intensity .q { width: 13px; height: 13px; border-radius: 2px; }
2150
+ .pj-act-list { display: flex; flex-direction: column; gap: 0.25rem; }
2151
+ .pj-act-item { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; }
2152
+ .pj-act-time { color: var(--muted); font-size: 0.72rem; min-width: 130px; }
2153
+ .pj-act-who { font-weight: 600; color: var(--text); }
2154
+ .pj-act-agent { font-size: 0.73rem; color: var(--accent); background: var(--bg-dim); border-radius: 5px; padding: 0.02rem 0.35rem; white-space: nowrap; }
2155
+ .pj-act-act { color: var(--muted); }
2156
+ .pj-act-what { color: var(--text); }
2157
+ /* Workspace list (an organism's many workspaces) */
2158
+ .pj-ws-bar { display: flex; align-items: center; gap: 0.5rem; margin: 0.5rem 0 0.75rem; }
2159
+ .pj-ws-name-input { flex: 0 1 260px; }
2160
+ .pj-ws-topbar { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; flex-wrap: wrap; }
2161
+ .pj-ws-list-label { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); margin: 0.5rem 0.1rem 0.35rem; }
2162
+ .pj-ws-list { display: flex; flex-direction: column; gap: 0.4rem; }
2163
+ .pj-ws-card { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 0.1rem 0.5rem 0.1rem 0.1rem; box-shadow: var(--shadow-sm); }
2164
+ .pj-ws-locked { cursor: default; }
2165
+ .pj-ws-locked:hover { background: none; }
2166
+ .pj-ws-inbox { flex-basis: 100%; width: 100%; border-top: 1px solid var(--border-subtle); margin: 0.1rem 0.3rem 0.4rem; padding-top: 0.45rem; display: flex; flex-direction: column; gap: 0.35rem; }
2167
+ .pj-ws-inbox-empty { font-size: 0.8rem; color: var(--muted); padding-left: 0.3rem; }
2168
+ .pj-ws-req { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; padding-left: 0.3rem; }
2169
+ .pj-ws-req-who { flex: 1; color: var(--text); }
2170
+ .pj-ws-req-msg { color: var(--muted); }
2171
+ .pj-ws-req-ok { color: var(--accent); font-size: 0.8rem; }
2172
+ .pj-ws-open { flex: 1; display: flex; align-items: baseline; gap: 0.6rem; background: none; border: none; cursor: pointer; text-align: left; padding: 0.7rem 0.85rem; border-radius: 10px; }
2173
+ .pj-ws-open:hover { background: var(--bg-surface); }
2174
+ .pj-ws-card-name { font-weight: 600; font-size: 0.95rem; color: var(--text); }
2175
+ .pj-ws-card-meta { font-size: 0.74rem; color: var(--muted); }
2176
+ .pj-ai-prompt { display: inline-flex; align-items: center; gap: 0.2rem; flex-wrap: wrap; }
2177
+ .pj-ai-prompt-label { font-size: 0.78rem; color: var(--muted); }
2178
+ .pj-spaces-add { margin-bottom: 0.6rem; }
2179
+ .pj-space-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.4rem; }
2180
+ .pj-space-row .input-field { flex: 0 1 220px; }
2181
+ .pj-doc-editor { margin: 0.4rem 0; }
2182
+ .pj-doc-editor > input { margin-bottom: 0.4rem; }
2183
+ .pj-doc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
2184
+ .pj-doc-md { font-family: var(--mono, ui-monospace, monospace); font-size: 0.82rem; line-height: 1.4; }
2185
+ .pj-doc-preview { border: 1px solid var(--border); border-radius: 10px; padding: 0.4rem 0.8rem; background: var(--bg-dim); overflow: auto; max-height: 360px; }
2186
+ @media (max-width: 640px) { .pj-doc-grid { grid-template-columns: 1fr; } }
2187
+ .pj-divider { border-top: 1px solid var(--border); margin: 0.8rem 0; }
2188
+ .pj-danger { border: 1px solid var(--danger); border-radius: 10px; padding: 0.6rem 0.75rem; margin-top: 0.8rem; }
2189
+ .pj-danger-title { font-weight: 600; color: var(--danger); margin-bottom: 0.3rem; }
2190
+ .pj-space-name { flex: 1; color: var(--text); font-size: 0.9rem; }
2191
+ .pj-docspace { display: flex; gap: 0.75rem; align-items: flex-start; }
2192
+ /* The left index/tree — white so a selected item's accent tint actually stands out against it. */
2193
+ .pj-doc-index { flex: 0 0 240px; min-width: 200px; border: 1px solid var(--border); border-radius: 10px; padding: 0.5rem; background: var(--card); max-height: 460px; overflow: auto; }
2194
+ .pj-doc-main { flex: 1; min-width: 0; }
2195
+ .pj-sec { margin-bottom: 0.25rem; }
2196
+ .pj-sec .pj-sec { margin-left: 0.85rem; border-left: 1px solid var(--border); padding-left: 0.4rem; }
2197
+ .pj-sec-head { display: flex; align-items: center; gap: 0.2rem; }
2198
+ .pj-sec-name { flex: 1; font-weight: 600; font-size: 0.82rem; }
2199
+ .pj-sec-name.pj-muted { color: var(--muted); font-weight: 500; padding: 0.15rem 0; }
2200
+ .pj-sec-name-text { flex: 1; font-weight: 600; font-size: 0.82rem; cursor: text; }
2201
+ .pj-grip { cursor: grab; color: var(--muted); font-size: 0.8rem; user-select: none; }
2202
+ .pj-doc-item[draggable="true"] { cursor: grab; }
2203
+ .pj-icon-btn { background: none; border: none; cursor: pointer; color: var(--muted); font-size: 0.85rem; padding: 0 0.2rem; line-height: 1; }
2204
+ .pj-icon-btn:hover { color: var(--accent); }
2205
+ .pj-doc-item { display: flex; align-items: center; gap: 0.3rem; padding: 0.15rem 0.3rem; border-radius: 6px; }
2206
+ .pj-doc-item:hover { background: var(--bg-surface); }
2207
+ .pj-doc-item.active { background: var(--accent-subtle); box-shadow: inset 3px 0 0 var(--accent); }
2208
+ .pj-doc-item .pj-doc-link { flex: 1; font-size: 0.85rem; color: var(--text); }
2209
+ .input-xs { padding: 0.15rem 0.35rem; font-size: 0.78rem; height: auto; }
2210
+ .pj-mini { font-size: 0.6rem; padding: 0 0.25rem; vertical-align: middle; }
2211
+ .pj-doc-toolbar { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.4rem; }
2212
+ .pj-doc-vtitle { flex: 1; font-weight: 700; font-size: 1.05rem; color: var(--text); }
2213
+ .pj-tui { margin: 0.3rem 0 0.5rem; }
2214
+ .pj-doc-imgbar { margin: 0.3rem 0; display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem; }
2215
+ .pj-file-btn { cursor: pointer; }
2216
+ .pj-file-btn input { display: none; }
2217
+ .pj-file-btn-icon { margin-right: 0.15rem; }
2218
+ .pj-imgbar-hint { font-size: 0.78rem; color: var(--muted); }
2219
+ .pj-img-vis { margin: 0.2rem 0 0.5rem; padding: 0.55rem 0.65rem; border: 1px solid var(--border); border-radius: 8px; background: var(--card); }
2220
+ .pj-img-vis-head { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.35rem; }
2221
+ .pj-img-vis-title { font-size: 0.85rem; font-weight: 600; color: var(--text); }
2222
+ .pj-img-vis-note { font-size: 0.74rem; color: var(--muted); flex: 1; }
2223
+ .pj-img-vis-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.18rem 0; border-top: 1px solid var(--border-subtle); }
2224
+ .pj-img-vis-name { flex: 1; font-size: 0.8rem; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2225
+ .pj-sources-desc { margin: 0.1rem 0 0.5rem; }
2226
+ .pj-src-picker { border: 1px solid var(--border); border-radius: 8px; padding: 0.6rem; margin-bottom: 0.6rem; background: var(--card); }
2227
+ .pj-src-controls { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin: 0.5rem 0; }
2228
+ .pj-src-search { flex: 1; min-width: 140px; }
2229
+ .pj-src-results { max-height: 240px; overflow-y: auto; display: flex; flex-direction: column; gap: 0.15rem; }
2230
+ .pj-src-result { display: flex; align-items: center; gap: 0.5rem; padding: 0.2rem 0.3rem; border-radius: 6px; }
2231
+ .pj-src-result:hover { background: var(--surface); }
2232
+ .pj-src-result-label { flex: 1; font-size: 0.82rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2233
+ .pj-src-result-meta { font-size: 0.72rem; color: var(--muted); white-space: nowrap; }
2234
+ .pj-src-list { display: flex; flex-direction: column; gap: 0.2rem; }
2235
+ .pj-src-item { display: flex; align-items: center; gap: 0.45rem; padding: 0.25rem 0.3rem; border-radius: 6px; border: 1px solid var(--border); }
2236
+ .pj-src-icon { flex: 0 0 auto; }
2237
+ .pj-src-label { flex: 1; font-size: 0.85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2238
+ .md-wikilink { color: var(--accent); cursor: pointer; text-decoration: none; border-bottom: 1px dashed var(--accent); }
2239
+ .md-wikilink:hover { border-bottom-style: solid; }
2240
+ .md-img { max-width: 100%; height: auto; border-radius: 6px; }
2241
+ @media (max-width: 640px) { .pj-docspace { flex-direction: column; } .pj-doc-index { flex: none; width: 100%; } }
@@ -33,10 +33,16 @@ export async function api(path, opts = {}) {
33
33
  }
34
34
  }
35
35
 
36
+ // Per-call timeout override (ms) — default 30s; long-running calls (e.g. AI completion on a
37
+ // slow model) pass a larger value. Don't raise the global default — failed normal calls would hang.
38
+ const timeoutMs = opts.timeoutMs || 30_000;
39
+ // Per-call retry override — a long AI call passes 0 so a timeout doesn't re-run the slow request.
40
+ const maxRetries = opts.retries != null ? opts.retries : MAX_RETRIES;
41
+
36
42
  let lastError;
37
- for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
43
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
38
44
  const controller = new AbortController();
39
- const timeoutId = setTimeout(() => controller.abort(), 30_000);
45
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
40
46
  try {
41
47
  const resp = await fetch(path, { ...opts, headers, signal: controller.signal });
42
48
 
@@ -52,7 +58,7 @@ export async function api(path, opts = {}) {
52
58
  }
53
59
  }
54
60
 
55
- if (resp.status === 429 || (resp.status >= 500 && attempt < MAX_RETRIES)) {
61
+ if (resp.status === 429 || (resp.status >= 500 && attempt < maxRetries)) {
56
62
  await sleep(RETRY_BASE_MS * Math.pow(2, attempt));
57
63
  continue;
58
64
  }
@@ -67,13 +73,13 @@ export async function api(path, opts = {}) {
67
73
  return json;
68
74
  } catch (err) {
69
75
  if (err.name === 'AbortError') {
70
- if (attempt === MAX_RETRIES) throw new Error('Request timed out after 30s');
76
+ if (attempt === maxRetries) throw new Error('Request timed out after ' + Math.round(timeoutMs / 1000) + 's');
71
77
  continue;
72
78
  }
73
79
  // Don't retry client errors (4xx) — only retry network/server errors
74
80
  if (err.status && err.status >= 400 && err.status < 500) throw err;
75
81
  lastError = err;
76
- if (attempt < MAX_RETRIES) {
82
+ if (attempt < maxRetries) {
77
83
  await sleep(RETRY_BASE_MS * Math.pow(2, attempt));
78
84
  continue;
79
85
  }
@@ -19,6 +19,10 @@ export const getTranslations = (lang) => apiGet(`/v1/admin/translations?lang=$
19
19
  // ── Agents & Owners ──
20
20
  export const getAdminAgents = () => apiGet('/v1/admin/agents');
21
21
  export const getAdminOwners = () => apiGet('/v1/admin/owners');
22
+ // Security incidents (rejected/quarantined uploads, etc.)
23
+ export const getSecurityIncidents = () => apiGet('/v1/admin/security/incidents');
24
+ export const resolveSecurityIncident = (id) => apiPost(`/v1/admin/security/incidents/${encodeURIComponent(id)}/resolve`);
25
+ export const deleteSecurityIncident = (id) => apiDelete(`/v1/admin/security/incidents/${encodeURIComponent(id)}`);
22
26
  export const getAgentDetail = (gaii) => apiGet(`/v1/agents/${encodeURIComponent(gaii)}`);
23
27
  export const getOwnerDetail = (name) => apiGet(`/v1/owners/${encodeURIComponent(name)}`);
24
28
  export const grantRole = (owner, role) => apiPost('/v1/admin/roles/grant', { owner, role });
@@ -52,6 +52,25 @@ export async function setAgentCors(name, origins) {
52
52
  });
53
53
  }
54
54
 
55
+ /** Custom agent groups (sections) for the Agents tab. Stored server-side in the
56
+ * owner's memory at `agents.groups` so the grouping follows the owner across
57
+ * devices/browsers. A group is { id, name, agents: [agentName] }; an agent
58
+ * belongs to at most one group, and any agent not listed in a group renders
59
+ * under "Ungrouped". The per-browser collapsed/expanded state is NOT stored
60
+ * here — it lives in localStorage (see agents-tab.js). */
61
+ export async function getAgentGroups() {
62
+ try {
63
+ const resp = await apiGet('/v1/memory?prefix=agents.groups');
64
+ const item = (resp?.data?.items || []).find(i => i.key === 'agents.groups');
65
+ return Array.isArray(item?.value?.groups) ? item.value.groups : [];
66
+ } catch { return []; }
67
+ }
68
+
69
+ /** Persist the owner's custom agent groups. */
70
+ export async function saveAgentGroups(groups) {
71
+ return apiPost('/v1/memory', { key: 'agents.groups', value: { groups }, visibility: 'private' });
72
+ }
73
+
55
74
  /** List chat instances (includes MCP sessions). Returns array. */
56
75
  export async function listChatInstances() {
57
76
  const data = await apiGet('/v1/chat-instances');