aimeat 1.16.2 → 1.18.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 (281) hide show
  1. package/dist/.env.example +6 -1
  2. package/dist/locales/en.json +166 -4
  3. package/dist/locales/fi.json +166 -4
  4. package/dist/public/components/Card.js +17 -3
  5. package/dist/public/components/Collapsible.js +39 -0
  6. package/dist/public/components/CopyButton.js +55 -24
  7. package/dist/public/components/DataTable.js +57 -0
  8. package/dist/public/components/EmptyState.js +28 -0
  9. package/dist/public/components/KeyValueRow.js +37 -0
  10. package/dist/public/components/Modal.js +22 -5
  11. package/dist/public/components/Pagination.js +70 -0
  12. package/dist/public/components/SearchBar.js +44 -0
  13. package/dist/public/components/StatusDot.js +29 -0
  14. package/dist/public/components/TagList.js +53 -0
  15. package/dist/public/components/ToggleSwitch.js +28 -0
  16. package/dist/public/components/index.js +41 -1
  17. package/dist/public/css/components/tags.css +24 -0
  18. package/dist/public/css/style-testbed.css +135 -0
  19. package/dist/public/css/theme.css +556 -34
  20. package/dist/public/css/views/admin-agent-integration.css +2 -33
  21. package/dist/public/css/views/admin.css +730 -686
  22. package/dist/public/css/views/agents-detail.css +402 -14
  23. package/dist/public/css/views/help.css +2 -1
  24. package/dist/public/css/views/hobbies.css +53 -33
  25. package/dist/public/css/views/marketplace.css +73 -60
  26. package/dist/public/css/views/openclaw.css +12 -6
  27. package/dist/public/css/views/portal-classic.css +34 -26
  28. package/dist/public/css/views/portal-dev.css +41 -32
  29. package/dist/public/css/views/portal.css +14 -18
  30. package/dist/public/css/views/profile.css +252 -164
  31. package/dist/public/css/views/public-knowledge-viewer.css +18 -6
  32. package/dist/public/css/views/scheduler.css +100 -0
  33. package/dist/public/js/format.js +41 -0
  34. package/dist/public/js/services/agent-tasks.js +14 -1
  35. package/dist/public/js/services/generator-spec-validate.js +5 -1
  36. package/dist/public/js/services/schedules.js +53 -0
  37. package/dist/public/js/style-testbed.js +170 -0
  38. package/dist/public/js/theme.js +114 -0
  39. package/dist/public/spa.html +74 -16
  40. package/dist/public/style-testbed.html +420 -0
  41. package/dist/public/views/admin/agent-integration-tab.js +23 -38
  42. package/dist/public/views/admin/agent-tasks-tab.js +14 -21
  43. package/dist/public/views/admin/chat-instances-tab.js +1 -1
  44. package/dist/public/views/admin/config-tab.js +7 -2
  45. package/dist/public/views/admin/cortex-tab.js +20 -14
  46. package/dist/public/views/admin/csm-tab.js +22 -18
  47. package/dist/public/views/admin/directory-tab.js +3 -3
  48. package/dist/public/views/admin/email-tab.js +23 -28
  49. package/dist/public/views/admin/federation-tab.js +15 -5
  50. package/dist/public/views/admin/generator-debug-tab.js +10 -8
  51. package/dist/public/views/admin/genesis-tab.js +4 -4
  52. package/dist/public/views/admin/ghii-tab.js +3 -3
  53. package/dist/public/views/admin/knowledge-tab.js +15 -5
  54. package/dist/public/views/admin/matching-tab.js +3 -3
  55. package/dist/public/views/admin/memory-tab.js +16 -20
  56. package/dist/public/views/admin/msm-tab.js +30 -17
  57. package/dist/public/views/admin/overview-tab.js +7 -7
  58. package/dist/public/views/admin/packages-tab.js +10 -9
  59. package/dist/public/views/admin/portal-tab.js +14 -4
  60. package/dist/public/views/admin/prompts-tab.js +5 -5
  61. package/dist/public/views/admin/push-tab.js +15 -4
  62. package/dist/public/views/admin/realtime-tab.js +3 -3
  63. package/dist/public/views/admin/services-tab.js +18 -27
  64. package/dist/public/views/admin/shared.js +48 -58
  65. package/dist/public/views/admin/sharing-groups-tab.js +5 -10
  66. package/dist/public/views/admin/stats-tab.js +3 -3
  67. package/dist/public/views/guides.js +9 -13
  68. package/dist/public/views/help.js +3 -24
  69. package/dist/public/views/hobbies.js +47 -41
  70. package/dist/public/views/marketplace.js +42 -34
  71. package/dist/public/views/openclaw.js +0 -1
  72. package/dist/public/views/portal-classic.js +4 -15
  73. package/dist/public/views/portal-dev.js +28 -30
  74. package/dist/public/views/portal.js +16 -21
  75. package/dist/public/views/portfolio.js +11 -12
  76. package/dist/public/views/profile/access-tab.js +250 -1
  77. package/dist/public/views/profile/agents/agent-card.js +75 -4
  78. package/dist/public/views/profile/agents/tab-activity.js +15 -13
  79. package/dist/public/views/profile/agents/tab-agent-config.js +60 -6
  80. package/dist/public/views/profile/agents/tab-integration.js +37 -60
  81. package/dist/public/views/profile/agents/tab-messages.js +10 -1
  82. package/dist/public/views/profile/agents/tab-quality.js +25 -19
  83. package/dist/public/views/profile/agents/tab-schedules.js +110 -0
  84. package/dist/public/views/profile/agents-activity-subtab.js +4 -4
  85. package/dist/public/views/profile/agents-services-subtab.js +5 -4
  86. package/dist/public/views/profile/agents-tab.js +141 -37
  87. package/dist/public/views/profile/agents-tasks-subtab.js +221 -26
  88. package/dist/public/views/profile/calibrator-batch.js +5 -11
  89. package/dist/public/views/profile/calibrator-tab.js +4 -9
  90. package/dist/public/views/profile/chat-sessions-tab.js +9 -5
  91. package/dist/public/views/profile/email-tab.js +2 -2
  92. package/dist/public/views/profile/extensions-tab.js +27 -22
  93. package/dist/public/views/profile/federation-tab.js +4 -1
  94. package/dist/public/views/profile/foundry-detail.js +22 -23
  95. package/dist/public/views/profile/foundry-tab.js +12 -13
  96. package/dist/public/views/profile/generator-dashboard/DebugPanel.js +4 -7
  97. package/dist/public/views/profile/generator-dashboard/use-dashboard-core.js +4 -1
  98. package/dist/public/views/profile/generator-dashboard/use-edit-mode.js +3 -2
  99. package/dist/public/views/profile/generator-detail.js +26 -30
  100. package/dist/public/views/profile/generator-tab.js +5 -5
  101. package/dist/public/views/profile/knowledge-tab.js +12 -12
  102. package/dist/public/views/profile/landing-page.js +100 -149
  103. package/dist/public/views/profile/memory-tab.js +15 -11
  104. package/dist/public/views/profile/node-stats-tab.js +3 -3
  105. package/dist/public/views/profile/nodes-tab.js +10 -3
  106. package/dist/public/views/profile/notifications-tab.js +3 -3
  107. package/dist/public/views/profile/packages-tab.js +14 -14
  108. package/dist/public/views/profile/scheduler-tab.js +340 -0
  109. package/dist/public/views/profile/services-tab.js +1 -1
  110. package/dist/public/views/profile/shared.js +16 -12
  111. package/dist/public/views/profile/wallet-tab.js +27 -50
  112. package/dist/public/views/profile/work-tab.js +29 -31
  113. package/dist/public/views/profile.js +24 -0
  114. package/dist/public/views/public-knowledge-viewer.js +9 -18
  115. package/dist/src/auth/middleware.d.ts +3 -2
  116. package/dist/src/auth/middleware.d.ts.map +1 -1
  117. package/dist/src/auth/middleware.js +78 -3
  118. package/dist/src/auth/middleware.js.map +1 -1
  119. package/dist/src/cli/init-wizard.d.ts.map +1 -1
  120. package/dist/src/cli/init-wizard.js +13 -1
  121. package/dist/src/cli/init-wizard.js.map +1 -1
  122. package/dist/src/config.d.ts +6 -0
  123. package/dist/src/config.d.ts.map +1 -1
  124. package/dist/src/config.js +12 -1
  125. package/dist/src/config.js.map +1 -1
  126. package/dist/src/generated/api-types.d.ts +708 -8
  127. package/dist/src/generated/api-types.d.ts.map +1 -1
  128. package/dist/src/mcp/agent-schedules.d.ts +23 -0
  129. package/dist/src/mcp/agent-schedules.d.ts.map +1 -0
  130. package/dist/src/mcp/agent-schedules.js +175 -0
  131. package/dist/src/mcp/agent-schedules.js.map +1 -0
  132. package/dist/src/mcp/annotations.d.ts.map +1 -1
  133. package/dist/src/mcp/annotations.js +6 -0
  134. package/dist/src/mcp/annotations.js.map +1 -1
  135. package/dist/src/mcp/catalog/definitions.d.ts.map +1 -1
  136. package/dist/src/mcp/catalog/definitions.js +55 -0
  137. package/dist/src/mcp/catalog/definitions.js.map +1 -1
  138. package/dist/src/mcp/catalog/scopes.d.ts.map +1 -1
  139. package/dist/src/mcp/catalog/scopes.js +12 -0
  140. package/dist/src/mcp/catalog/scopes.js.map +1 -1
  141. package/dist/src/mcp/catalog/surfaces.d.ts.map +1 -1
  142. package/dist/src/mcp/catalog/surfaces.js +2 -0
  143. package/dist/src/mcp/catalog/surfaces.js.map +1 -1
  144. package/dist/src/mcp/index.d.ts.map +1 -1
  145. package/dist/src/mcp/index.js +2 -0
  146. package/dist/src/mcp/index.js.map +1 -1
  147. package/dist/src/models/agent-task-schemas.d.ts +6 -0
  148. package/dist/src/models/agent-task-schemas.d.ts.map +1 -1
  149. package/dist/src/models/agent-task-schemas.js +6 -0
  150. package/dist/src/models/agent-task-schemas.js.map +1 -1
  151. package/dist/src/models/schemas.d.ts +1 -0
  152. package/dist/src/models/schemas.d.ts.map +1 -1
  153. package/dist/src/models/schemas.js +4 -0
  154. package/dist/src/models/schemas.js.map +1 -1
  155. package/dist/src/routes/access-tokens.d.ts +17 -0
  156. package/dist/src/routes/access-tokens.d.ts.map +1 -0
  157. package/dist/src/routes/access-tokens.js +164 -0
  158. package/dist/src/routes/access-tokens.js.map +1 -0
  159. package/dist/src/routes/agent-tasks.d.ts +2 -0
  160. package/dist/src/routes/agent-tasks.d.ts.map +1 -1
  161. package/dist/src/routes/agent-tasks.js +118 -23
  162. package/dist/src/routes/agent-tasks.js.map +1 -1
  163. package/dist/src/routes/agents.d.ts.map +1 -1
  164. package/dist/src/routes/agents.js +46 -0
  165. package/dist/src/routes/agents.js.map +1 -1
  166. package/dist/src/routes/ai.d.ts +6 -9
  167. package/dist/src/routes/ai.d.ts.map +1 -1
  168. package/dist/src/routes/ai.js +26 -175
  169. package/dist/src/routes/ai.js.map +1 -1
  170. package/dist/src/routes/apps.d.ts.map +1 -1
  171. package/dist/src/routes/apps.js +104 -34
  172. package/dist/src/routes/apps.js.map +1 -1
  173. package/dist/src/routes/auth.d.ts.map +1 -1
  174. package/dist/src/routes/auth.js +77 -4
  175. package/dist/src/routes/auth.js.map +1 -1
  176. package/dist/src/routes/cortex.d.ts +2 -1
  177. package/dist/src/routes/cortex.d.ts.map +1 -1
  178. package/dist/src/routes/cortex.js +13 -8
  179. package/dist/src/routes/cortex.js.map +1 -1
  180. package/dist/src/routes/extensions.d.ts.map +1 -1
  181. package/dist/src/routes/extensions.js +85 -51
  182. package/dist/src/routes/extensions.js.map +1 -1
  183. package/dist/src/routes/generator.d.ts.map +1 -1
  184. package/dist/src/routes/generator.js +109 -43
  185. package/dist/src/routes/generator.js.map +1 -1
  186. package/dist/src/routes/ghii.d.ts.map +1 -1
  187. package/dist/src/routes/ghii.js +34 -13
  188. package/dist/src/routes/ghii.js.map +1 -1
  189. package/dist/src/routes/libs.d.ts +15 -0
  190. package/dist/src/routes/libs.d.ts.map +1 -1
  191. package/dist/src/routes/libs.js +178 -55
  192. package/dist/src/routes/libs.js.map +1 -1
  193. package/dist/src/routes/portal.d.ts.map +1 -1
  194. package/dist/src/routes/portal.js +1 -0
  195. package/dist/src/routes/portal.js.map +1 -1
  196. package/dist/src/routes/schedules.d.ts +33 -0
  197. package/dist/src/routes/schedules.d.ts.map +1 -0
  198. package/dist/src/routes/schedules.js +380 -0
  199. package/dist/src/routes/schedules.js.map +1 -0
  200. package/dist/src/server-bootstrap/config-init.js +2 -2
  201. package/dist/src/server-bootstrap/config-init.js.map +1 -1
  202. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  203. package/dist/src/server-bootstrap/routes-loader.js +7 -0
  204. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  205. package/dist/src/server-bootstrap/service-init.d.ts.map +1 -1
  206. package/dist/src/server-bootstrap/service-init.js +2 -1
  207. package/dist/src/server-bootstrap/service-init.js.map +1 -1
  208. package/dist/src/services/access-token.d.ts +28 -0
  209. package/dist/src/services/access-token.d.ts.map +1 -0
  210. package/dist/src/services/access-token.js +37 -0
  211. package/dist/src/services/access-token.js.map +1 -0
  212. package/dist/src/services/ai-completion.d.ts +83 -0
  213. package/dist/src/services/ai-completion.d.ts.map +1 -0
  214. package/dist/src/services/ai-completion.js +187 -0
  215. package/dist/src/services/ai-completion.js.map +1 -0
  216. package/dist/src/services/config-schema.d.ts.map +1 -1
  217. package/dist/src/services/config-schema.js +3 -0
  218. package/dist/src/services/config-schema.js.map +1 -1
  219. package/dist/src/services/generator-prompt-seeds.d.ts.map +1 -1
  220. package/dist/src/services/generator-prompt-seeds.js +6 -3
  221. package/dist/src/services/generator-prompt-seeds.js.map +1 -1
  222. package/dist/src/services/generator-prompts/spec-validate.d.ts.map +1 -1
  223. package/dist/src/services/generator-prompts/spec-validate.js +6 -2
  224. package/dist/src/services/generator-prompts/spec-validate.js.map +1 -1
  225. package/dist/src/services/generator-registration.d.ts +12 -4
  226. package/dist/src/services/generator-registration.d.ts.map +1 -1
  227. package/dist/src/services/generator-registration.js +71 -0
  228. package/dist/src/services/generator-registration.js.map +1 -1
  229. package/dist/src/services/generator-validate.d.ts +10 -0
  230. package/dist/src/services/generator-validate.d.ts.map +1 -1
  231. package/dist/src/services/generator-validate.js +180 -36
  232. package/dist/src/services/generator-validate.js.map +1 -1
  233. package/dist/src/services/owner-session.d.ts +43 -0
  234. package/dist/src/services/owner-session.d.ts.map +1 -0
  235. package/dist/src/services/owner-session.js +175 -0
  236. package/dist/src/services/owner-session.js.map +1 -0
  237. package/dist/src/services/schedule-constraints.d.ts +65 -0
  238. package/dist/src/services/schedule-constraints.d.ts.map +1 -0
  239. package/dist/src/services/schedule-constraints.js +106 -0
  240. package/dist/src/services/schedule-constraints.js.map +1 -0
  241. package/dist/src/services/scheduler.d.ts +34 -0
  242. package/dist/src/services/scheduler.d.ts.map +1 -1
  243. package/dist/src/services/scheduler.js +266 -22
  244. package/dist/src/services/scheduler.js.map +1 -1
  245. package/dist/src/services/skill-bundle/generator.js +19 -0
  246. package/dist/src/services/skill-bundle/generator.js.map +1 -1
  247. package/dist/src/storage/interface.d.ts +48 -4
  248. package/dist/src/storage/interface.d.ts.map +1 -1
  249. package/dist/src/storage/interface.js.map +1 -1
  250. package/dist/src/storage/providers/mongodb/index.d.ts +31 -0
  251. package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
  252. package/dist/src/storage/providers/mongodb/index.js +187 -9
  253. package/dist/src/storage/providers/mongodb/index.js.map +1 -1
  254. package/dist/src/storage/providers/sqlite/index.d.ts +31 -0
  255. package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
  256. package/dist/src/storage/providers/sqlite/index.js +131 -8
  257. package/dist/src/storage/providers/sqlite/index.js.map +1 -1
  258. package/dist/src/storage/providers/sqlite/repos/agent-task.d.ts.map +1 -1
  259. package/dist/src/storage/providers/sqlite/repos/agent-task.js +6 -4
  260. package/dist/src/storage/providers/sqlite/repos/agent-task.js.map +1 -1
  261. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  262. package/dist/src/storage/providers/sqlite/schema.js +79 -8
  263. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  264. package/dist/src/storage/repositories/pat.repository.d.ts +40 -0
  265. package/dist/src/storage/repositories/pat.repository.d.ts.map +1 -0
  266. package/dist/src/storage/repositories/pat.repository.js +14 -0
  267. package/dist/src/storage/repositories/pat.repository.js.map +1 -0
  268. package/dist/src/storage/repositories/scheduler.repository.d.ts +2 -0
  269. package/dist/src/storage/repositories/scheduler.repository.d.ts.map +1 -1
  270. package/dist/src/storage/repositories/session.repository.d.ts +51 -0
  271. package/dist/src/storage/repositories/session.repository.d.ts.map +1 -1
  272. package/dist/src/storage/repositories/session.repository.js +12 -0
  273. package/dist/src/storage/repositories/session.repository.js.map +1 -1
  274. package/dist/src/utils/env-config.d.ts.map +1 -1
  275. package/dist/src/utils/env-config.js +25 -1
  276. package/dist/src/utils/env-config.js.map +1 -1
  277. package/dist/src/utils/env-validator.d.ts.map +1 -1
  278. package/dist/src/utils/env-validator.js +4 -0
  279. package/dist/src/utils/env-validator.js.map +1 -1
  280. package/package.json +1 -1
  281. package/prisma/schema.prisma +48 -0
@@ -1,7 +1,19 @@
1
1
  /**
2
2
  * @file public-knowledge-viewer.css
3
3
  * @description Styles for the public knowledge package viewer (no-auth browsing)
4
- * @version-history v1.0.0 — 2026-05-26 — Initial implementation
4
+ * @version-history
5
+ * v1.2.0 — 2026-06-02 — Component unification (#23 collapsible): tokenize the
6
+ * hardcoded hex fallback in .pkv-entry-arrow (var(--text-dim, #6B7280) →
7
+ * var(--text-dim)) so the expand chevron flips in dark mode. The .pkv-entry
8
+ * toggle markup is left in place (chevron-left, rotate-90 ▶, view-scoped
9
+ * expandedEntries state); canonical /components/Collapsible.js added separately.
10
+ * v1.1.0 — 2026-06-02 — Component unification (#24 search bar): tokenize the
11
+ * hardcoded hex fallbacks in .pkv-search (var(--border, #E5E7EB) →
12
+ * var(--border); var(--card-bg, #FFFFFF) → var(--card); var(--text, #1A1A2E)
13
+ * → var(--text); var(--accent, #7c5cff) → var(--accent)) so the package
14
+ * search input flips in dark mode. Markup left on .pkv-search (view-scoped
15
+ * filter state; not migrated to canonical SearchBar).
16
+ * v1.0.0 — 2026-05-26 — Initial implementation
5
17
  */
6
18
 
7
19
  /* ── Layout ── */
@@ -44,17 +56,17 @@
44
56
  flex: 1;
45
57
  min-width: 200px;
46
58
  padding: 0.6rem 1rem;
47
- border: 1px solid var(--border, #E5E7EB);
59
+ border: 1px solid var(--border);
48
60
  border-radius: 8px;
49
- background: var(--card-bg, #FFFFFF);
50
- color: var(--text, #1A1A2E);
61
+ background: var(--card);
62
+ color: var(--text);
51
63
  font-size: 0.9rem;
52
64
  outline: none;
53
65
  transition: border-color 0.15s;
54
66
  }
55
67
 
56
68
  .pkv-search:focus {
57
- border-color: var(--accent, #7c5cff);
69
+ border-color: var(--accent);
58
70
  }
59
71
 
60
72
  .pkv-filter-select {
@@ -254,7 +266,7 @@
254
266
 
255
267
  .pkv-entry-arrow {
256
268
  font-size: 0.75rem;
257
- color: var(--text-dim, #6B7280);
269
+ color: var(--text-dim);
258
270
  transition: transform 0.15s;
259
271
  }
260
272
 
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @file scheduler.css
3
+ * @description Styles for the Profile › Scheduler master view (scheduler-tab.js)
4
+ * and the agent Schedules sub-tab (agents/tab-schedules.js). Prefix: sch-.
5
+ * Theme-token driven (no hardcoded colors) so it flips with dark/light mode.
6
+ * @version-history
7
+ * v1.0.0 -- 2026-06-03 -- Initial scheduler styles
8
+ */
9
+
10
+ .sch-tab { display: flex; flex-direction: column; gap: 1.25rem; }
11
+
12
+ .sch-head {
13
+ display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem;
14
+ }
15
+
16
+ .sch-loading, .sch-empty, .sch-internal-note {
17
+ color: var(--text-dim); padding: 0.75rem 0; font-size: 0.92rem;
18
+ }
19
+ .sch-error {
20
+ background: var(--danger-bg); color: var(--danger-fg);
21
+ border: 1px solid var(--danger-border); border-radius: var(--radius-sm);
22
+ padding: 0.6rem 0.85rem;
23
+ }
24
+
25
+ .sch-section { display: flex; flex-direction: column; gap: 0.5rem; }
26
+ .sch-section-title { font-size: 1rem; font-weight: 700; color: var(--text); margin: 0.25rem 0; }
27
+
28
+ .sch-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
29
+ .sch-table th {
30
+ text-align: left; font-weight: 600; color: var(--text-dim);
31
+ padding: 0.5rem 0.6rem; border-bottom: 1px solid var(--border); font-size: 0.82rem;
32
+ }
33
+ .sch-table td {
34
+ padding: 0.55rem 0.6rem; border-bottom: 1px solid var(--border-subtle, var(--border));
35
+ vertical-align: top; color: var(--text);
36
+ }
37
+ .sch-name { font-weight: 600; }
38
+ .sch-purpose { margin-top: 0.15rem; }
39
+ .sch-muted { color: var(--text-dim); font-size: 0.82rem; }
40
+ .sch-cron { font-family: var(--font-mono, monospace); font-size: 0.82rem; color: var(--text); }
41
+
42
+ .sch-badge {
43
+ display: inline-block; padding: 0.1rem 0.5rem; border-radius: var(--radius-full, 999px);
44
+ font-size: 0.72rem; font-weight: 700; line-height: 1.5;
45
+ }
46
+ .sch-badge--ai { background: var(--info-bg); color: var(--info-fg); }
47
+ .sch-badge--agent { background: var(--warn-bg); color: var(--warn-fg); }
48
+ .sch-badge--ext { background: var(--success-bg); color: var(--success-fg); }
49
+ .sch-badge--core { background: var(--bg-dim); color: var(--text-dim); }
50
+ .sch-badge--ok { background: var(--success-bg); color: var(--success-fg); }
51
+ .sch-badge--err { background: var(--danger-bg); color: var(--danger-fg); }
52
+
53
+ .sch-tag {
54
+ display: inline-block; margin-top: 0.2rem; padding: 0.05rem 0.45rem;
55
+ border-radius: var(--radius-full, 999px); font-size: 0.68rem;
56
+ background: var(--accent-faint, var(--bg-dim)); color: var(--accent);
57
+ }
58
+
59
+ .sch-actions { white-space: nowrap; }
60
+ .sch-btn { margin-left: 0.35rem; padding: 0.25rem 0.6rem; font-size: 0.8rem; }
61
+
62
+ .sch-internal-group { margin-bottom: 0.75rem; }
63
+ .sch-internal-agent { font-weight: 600; color: var(--text); margin: 0.35rem 0 0.15rem; }
64
+
65
+ /* ── Create form ── */
66
+ .sch-form {
67
+ background: var(--card); border: 1px solid var(--border);
68
+ border-radius: var(--radius); padding: 1rem 1.1rem; display: flex; flex-direction: column; gap: 0.75rem;
69
+ }
70
+ .sch-form-row { display: flex; flex-direction: column; gap: 0.3rem; }
71
+ .sch-form-row > label { font-size: 0.82rem; font-weight: 600; color: var(--text-dim); }
72
+ .sch-form-row input[type="text"], .sch-form-row input[type="number"],
73
+ .sch-form-row select, .sch-form-row textarea {
74
+ background: var(--bg-input); color: var(--text);
75
+ border: 1px solid var(--border); border-radius: var(--radius-sm);
76
+ padding: 0.45rem 0.6rem; font: inherit; width: 100%;
77
+ }
78
+ .sch-kind-fields {
79
+ border-left: 2px solid var(--accent-soft, var(--border)); padding-left: 0.85rem;
80
+ display: flex; flex-direction: column; gap: 0.6rem;
81
+ }
82
+ .sch-presets { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.35rem; }
83
+ .sch-preset {
84
+ padding: 0.3rem 0.7rem; border-radius: var(--radius-full, 999px);
85
+ border: 1px solid var(--border); background: var(--bg-dim); color: var(--text-dim);
86
+ font-size: 0.8rem; cursor: pointer;
87
+ }
88
+ .sch-preset--on { background: var(--accent); color: var(--on-inverted, #fff); border-color: var(--accent); }
89
+ .sch-cron-input { font-family: var(--font-mono, monospace); }
90
+
91
+ .sch-constraints {
92
+ border-top: 1px solid var(--border); padding-top: 0.65rem; display: flex; flex-direction: column; gap: 0.4rem;
93
+ }
94
+ .sch-constraints-title { font-size: 0.82rem; font-weight: 700; color: var(--text-dim); }
95
+ .sch-check { display: flex; align-items: center; gap: 0.5rem; font-size: 0.88rem; color: var(--text); }
96
+ .sch-num { width: 5rem !important; }
97
+
98
+ .sch-form-actions { display: flex; justify-content: flex-end; }
99
+
100
+ .sch-budget-section { margin-bottom: 1rem; }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @file format.js
3
+ * @description Canonical display formatters shared across the frontend (number,
4
+ * date/time, uptime, bytes). Previously these lived only in admin/shared.js and
5
+ * ~29 profile views hand-inlined `.toLocaleString()` — this is the single home so
6
+ * formatting stays consistent and new views import instead of reinventing.
7
+ * @structure num, dt, fmtUp, fmtBytes
8
+ * @usage import { num, dt } from '/js/format.js';
9
+ * num(1234) → "1,234" (locale grouped; non-numbers passed through)
10
+ * dt('2026-01-02T…') → locale date-time string
11
+ * fmtUp(90061) → "1d 1h 1m" (uptime seconds → human)
12
+ * fmtBytes(2048) → "2.0 KB"
13
+ * @version-history
14
+ * v1.0.0 — 2026-06-02 — Component unification (#12): promote admin's num/dt/fmtUp/
15
+ * fmtBytes to a shared module; admin/shared.js now re-exports from here.
16
+ */
17
+
18
+ /** Format a number with locale grouping; non-numbers pass through (nullish → em dash). */
19
+ export function num(n) {
20
+ return typeof n === 'number' ? n.toLocaleString() : String(n ?? '—');
21
+ }
22
+
23
+ /** Format an ISO date string as a locale date-time (nullish → em dash). */
24
+ export function dt(s) {
25
+ return s ? new Date(s).toLocaleString() : '—';
26
+ }
27
+
28
+ /** Format uptime seconds as a human-readable "Nd Nh Nm" (sub-minute → "<1m"). */
29
+ export function fmtUp(s) {
30
+ const d = Math.floor(s / 86400);
31
+ const hr = Math.floor((s % 86400) / 3600);
32
+ const m = Math.floor((s % 3600) / 60);
33
+ return (d ? d + 'd ' : '') + (hr ? hr + 'h ' : '') + (m ? m + 'm' : '<1m');
34
+ }
35
+
36
+ /** Format a byte count as B / KB / MB. */
37
+ export function fmtBytes(b) {
38
+ if (b < 1024) return b + ' B';
39
+ if (b < 1048576) return (b / 1024).toFixed(1) + ' KB';
40
+ return (b / 1048576).toFixed(1) + ' MB';
41
+ }
@@ -7,18 +7,31 @@
7
7
  * v1.0.0 -- 2026-05-21 -- Initial creation for Agent Dashboard Phase 1
8
8
  * v1.1.0 -- 2026-05-29 -- Add requestChanges() for the owner-asks-agent-to-revise-todos flow.
9
9
  * v1.2.0 -- 2026-05-31 -- Add rateTask() and getAgentStatistics() for the Quality tab.
10
+ * v1.3.0 -- 2026-06-01 -- listTasks() gains bucket/q/updated_after/before params; add setTaskTriage() for the Recent/Keep/Archive buckets.
10
11
  */
11
- import { apiGet, apiPost, apiDelete } from '/js/api.js';
12
+ import { apiGet, apiPost, apiDelete, api } from '/js/api.js';
12
13
 
13
14
  export async function listTasks(agentName, opts = {}) {
14
15
  const params = new URLSearchParams();
15
16
  if (opts.status) params.set('status', opts.status);
17
+ if (opts.bucket) params.set('bucket', opts.bucket); // recent | keep | archive
18
+ if (opts.q) params.set('q', opts.q); // title/description search
19
+ if (opts.updated_after) params.set('updated_after', opts.updated_after);
20
+ if (opts.updated_before) params.set('updated_before', opts.updated_before);
16
21
  if (opts.page) params.set('page', String(opts.page));
17
22
  if (opts.per_page) params.set('per_page', String(opts.per_page));
18
23
  const qs = params.toString();
19
24
  return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/tasks${qs ? '?' + qs : ''}`);
20
25
  }
21
26
 
27
+ /** Move a task between Tasks-tab buckets. triage: 'kept' | 'archived' | null (restore). */
28
+ export async function setTaskTriage(agentName, taskId, triage) {
29
+ return api(`/v1/agents/${encodeURIComponent(agentName)}/tasks/${encodeURIComponent(taskId)}/triage`, {
30
+ method: 'PATCH',
31
+ body: JSON.stringify({ triage }),
32
+ });
33
+ }
34
+
22
35
  export async function getTask(agentName, taskId) {
23
36
  return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/tasks/${encodeURIComponent(taskId)}`);
24
37
  }
@@ -64,7 +64,11 @@ export function validateDataApiSpec(spec) {
64
64
 
65
65
  if (!spec.name) errors.push('Missing spec.name');
66
66
  if (!spec.libName) errors.push('Missing spec.libName — apps need AIMEAT.<libName> to call methods');
67
- if (!spec.wrapsExtension) errors.push('Missing spec.wrapsExtension — must reference the extension it wraps');
67
+ // wrapsExtension is OPTIONAL — a data cortex may wrap an extension OR read the owner's own data
68
+ // directly via AIMEAT.data (no-extension apps). The real contract is `methods`.
69
+ if (spec.wrapsExtension != null && typeof spec.wrapsExtension !== 'string') {
70
+ errors.push('spec.wrapsExtension, if present, must be the extension name (string) — omit it for own-data cortexes');
71
+ }
68
72
 
69
73
  if (!Array.isArray(spec.methods) || spec.methods.length === 0) {
70
74
  errors.push('Missing or empty spec.methods array');
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @file schedules.js
3
+ * @description Frontend API service for recurring schedules (Profile Scheduler
4
+ * master view + per-agent Schedules sub-tab). Wraps the /v1/schedules and
5
+ * /v1/agents/:name/schedules endpoints. All functions return the AIMEAT
6
+ * envelope; callers read `res.data`.
7
+ * @usage
8
+ * import { listAllSchedules, createSchedule } from '/js/services/schedules.js';
9
+ * @version-history
10
+ * v1.0.0 -- 2026-06-03 -- Initial: master + per-agent schedule CRUD/trigger
11
+ */
12
+ import { apiGet, apiPost, apiPatch, apiDelete } from '/js/api.js';
13
+
14
+ /** Master aggregate: { managed, extensions, agentInternal }. */
15
+ export async function listAllSchedules() {
16
+ return apiGet('/v1/schedules');
17
+ }
18
+
19
+ /** Per-agent view: { managed, agentInternal }. */
20
+ export async function listAgentSchedules(agentName) {
21
+ return apiGet(`/v1/agents/${encodeURIComponent(agentName)}/schedules`);
22
+ }
23
+
24
+ export async function getSchedule(id) {
25
+ return apiGet(`/v1/schedules/${encodeURIComponent(id)}`);
26
+ }
27
+
28
+ /** Create a profile-level (or agent-targeted via data.agent_name) schedule. */
29
+ export async function createSchedule(data) {
30
+ return apiPost('/v1/schedules', data);
31
+ }
32
+
33
+ /** Create a schedule targeting a specific agent. */
34
+ export async function createAgentSchedule(agentName, data) {
35
+ return apiPost(`/v1/agents/${encodeURIComponent(agentName)}/schedules`, data);
36
+ }
37
+
38
+ export async function updateSchedule(id, patch) {
39
+ return apiPatch(`/v1/schedules/${encodeURIComponent(id)}`, patch);
40
+ }
41
+
42
+ /** Pause/resume shorthand. */
43
+ export async function setScheduleEnabled(id, enabled) {
44
+ return apiPatch(`/v1/schedules/${encodeURIComponent(id)}`, { enabled });
45
+ }
46
+
47
+ export async function triggerSchedule(id) {
48
+ return apiPost(`/v1/schedules/${encodeURIComponent(id)}/trigger`, {});
49
+ }
50
+
51
+ export async function deleteSchedule(id) {
52
+ return apiDelete(`/v1/schedules/${encodeURIComponent(id)}`);
53
+ }
@@ -0,0 +1,170 @@
1
+ /*
2
+ * @file style-testbed.js
3
+ * @description Interactivity for the dev style-decision testbed
4
+ * (style-testbed.html). Injects a per-clone decision <select> into each
5
+ * variant, wires the light/dark theme toggle, and serializes every choice +
6
+ * family note live into the copyable output box. Uses addEventListener only
7
+ * (no inline handlers) to satisfy the static-asset CSP (script-src 'self').
8
+ * @version-history
9
+ * v1.0.0 — 2026-06-02 — Initial testbed behavior
10
+ */
11
+ (function () {
12
+ 'use strict';
13
+
14
+ // Decision option sets keyed by variant kind.
15
+ const OPTIONS = {
16
+ standard: [
17
+ ['', '— decide —'],
18
+ ['canonical', 'Use canonical as-is (delete clone; variants already exist)'],
19
+ ['promote', 'Add / merge into canonical (make this look shared)'],
20
+ ['separate', 'Leave separate (no change)'],
21
+ ['delete', 'Delete (unused)'],
22
+ ],
23
+ admin: [
24
+ ['', '— decide —'],
25
+ ['consolidate', 'Consolidate into the ONE admin design'],
26
+ ['promote', 'Promote this variant to admin-shared'],
27
+ ['keep', 'Keep as-is'],
28
+ ['separate', 'Leave separate'],
29
+ ],
30
+ dead: [
31
+ ['delete', 'Delete (confirmed dead)'],
32
+ ['promote', 'Actually keep → add to canonical'],
33
+ ['keep', 'Keep as-is'],
34
+ ['', '— decide —'],
35
+ ],
36
+ };
37
+
38
+ // Human-readable labels for the output summary.
39
+ const LABEL = {
40
+ canonical: 'USE CANONICAL',
41
+ promote: 'ADD TO CANONICAL',
42
+ keep: 'KEEP AS-IS',
43
+ separate: 'LEAVE SEPARATE',
44
+ delete: 'DELETE',
45
+ consolidate: 'CONSOLIDATE (admin)',
46
+ '': 'undecided',
47
+ };
48
+
49
+ function kindOf(variant) {
50
+ if (variant.hasAttribute('data-dead')) return 'dead';
51
+ if (variant.hasAttribute('data-admin')) return 'admin';
52
+ return 'standard';
53
+ }
54
+
55
+ // ── Inject decision selects ──
56
+ function buildSelects() {
57
+ document.querySelectorAll('.stb-variant').forEach((variant) => {
58
+ const wrap = variant.querySelector('.stb-decide-wrap');
59
+ if (!wrap || wrap.querySelector('select')) return;
60
+ const kind = kindOf(variant);
61
+ const sel = document.createElement('select');
62
+ sel.className = 'stb-decide';
63
+ OPTIONS[kind].forEach(([val, text]) => {
64
+ const o = document.createElement('option');
65
+ o.value = val;
66
+ o.textContent = text;
67
+ sel.appendChild(o);
68
+ });
69
+ // Dead variants default to "delete" (first option already 'delete').
70
+ if (kind === 'dead') sel.value = 'delete';
71
+ wrap.appendChild(sel);
72
+ });
73
+ }
74
+
75
+ // ── Build the output summary ──
76
+ function pad(s, n) {
77
+ s = String(s);
78
+ return s.length >= n ? s : s + ' '.repeat(n - s.length);
79
+ }
80
+
81
+ function rebuild() {
82
+ const theme = document.documentElement.getAttribute('data-theme') || 'light';
83
+ const lines = [];
84
+ lines.push('=== AIMEAT Style Decisions ===');
85
+ lines.push('(reviewed in ' + theme.toUpperCase() + ' theme · ' + new Date().toLocaleString() + ')');
86
+ lines.push('');
87
+
88
+ let decided = 0;
89
+ let total = 0;
90
+
91
+ document.querySelectorAll('.stb-family').forEach((fam) => {
92
+ const famName = fam.getAttribute('data-family') || '';
93
+ const rows = [];
94
+ fam.querySelectorAll('.stb-variant').forEach((variant) => {
95
+ const sel = variant.querySelector('.stb-decide');
96
+ if (!sel) return; // canonical reference — no decision
97
+ total += 1;
98
+ const val = sel.value;
99
+ if (val !== '') decided += 1;
100
+ sel.classList.toggle('stb-chosen', val !== '');
101
+ const clone = variant.getAttribute('data-clone') || '';
102
+ const sites = variant.getAttribute('data-sites');
103
+ const sitesStr = sites ? '(' + sites + ' sites)' : '';
104
+ rows.push(' [' + pad(LABEL[val] || val, 18) + '] ' + pad(clone, 46) + ' ' + sitesStr);
105
+ });
106
+ const note = fam.querySelector('.stb-note');
107
+ const noteVal = note && note.value.trim();
108
+
109
+ lines.push('## ' + famName);
110
+ rows.forEach((r) => lines.push(r));
111
+ if (noteVal) lines.push(' note: ' + noteVal);
112
+ lines.push('');
113
+ });
114
+
115
+ const out = document.getElementById('stb-output');
116
+ if (out) out.value = lines.join('\n');
117
+ const count = document.getElementById('stb-count');
118
+ if (count) count.textContent = '(' + decided + '/' + total + ' clones decided)';
119
+ }
120
+
121
+ // ── Theme toggle ──
122
+ function setTheme(theme) {
123
+ document.documentElement.setAttribute('data-theme', theme);
124
+ document.querySelectorAll('.stb-theme-btn').forEach((b) => {
125
+ b.classList.toggle('stb-active', b.getAttribute('data-theme-set') === theme);
126
+ });
127
+ rebuild();
128
+ }
129
+
130
+ // ── Copy ──
131
+ function copyOut() {
132
+ const out = document.getElementById('stb-output');
133
+ const btn = document.getElementById('stb-copy');
134
+ if (!out) return;
135
+ const done = () => {
136
+ if (!btn) return;
137
+ btn.classList.add('stb-copied');
138
+ const prev = btn.textContent;
139
+ btn.textContent = '✓ Copied';
140
+ setTimeout(() => { btn.classList.remove('stb-copied'); btn.textContent = prev; }, 1500);
141
+ };
142
+ if (navigator.clipboard && navigator.clipboard.writeText) {
143
+ navigator.clipboard.writeText(out.value).then(done, () => { out.select(); document.execCommand('copy'); done(); });
144
+ } else {
145
+ out.select();
146
+ document.execCommand('copy');
147
+ done();
148
+ }
149
+ }
150
+
151
+ // ── Wire up ──
152
+ function init() {
153
+ buildSelects();
154
+ document.getElementById('stb-main').addEventListener('change', rebuild);
155
+ document.getElementById('stb-main').addEventListener('input', rebuild);
156
+ document.querySelectorAll('.stb-theme-btn').forEach((b) => {
157
+ b.addEventListener('click', () => setTheme(b.getAttribute('data-theme-set')));
158
+ });
159
+ const copy = document.getElementById('stb-copy');
160
+ if (copy) copy.addEventListener('click', copyOut);
161
+ // Reflect the initial data-theme on the toggle buttons.
162
+ setTheme(document.documentElement.getAttribute('data-theme') || 'dark');
163
+ }
164
+
165
+ if (document.readyState === 'loading') {
166
+ document.addEventListener('DOMContentLoaded', init);
167
+ } else {
168
+ init();
169
+ }
170
+ })();
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @file theme.js
3
+ * @description Dark/light theme controller for the AIMEAT SPA. Owns the
4
+ * `data-theme` attribute on <html>, persists the user's explicit choice to
5
+ * localStorage (`aimeat-theme`), and — until the user makes an explicit
6
+ * choice — tracks the OS `prefers-color-scheme`. Mirrors the i18n module's
7
+ * shape (getter / setter / subscribe + a `aimeat-theme-change` CustomEvent).
8
+ * The no-flash initial paint is handled by an inline boot snippet in
9
+ * spa.html <head>; this module takes over once the SPA mounts.
10
+ * @structure getTheme, setTheme, toggleTheme, hasExplicitChoice,
11
+ * onThemeChange, initThemeSystem
12
+ * @usage
13
+ * import { initThemeSystem, getTheme, toggleTheme, onThemeChange } from '/js/theme.js';
14
+ * initThemeSystem(); // call once during boot()
15
+ * const off = onThemeChange((t) => ...); // subscribe, returns unsubscribe
16
+ * toggleTheme(); // flip light <-> dark
17
+ * @version-history
18
+ * v1.0.0 — 2026-06-02 — Initial dark/light theming (Phase 1 mechanism).
19
+ */
20
+
21
+ const STORAGE_KEY = 'aimeat-theme';
22
+ const EVENT_NAME = 'aimeat-theme-change';
23
+ const VALID = new Set(['light', 'dark']);
24
+
25
+ /** Browser chrome (address bar) colors, matched to theme.css --bg per theme. */
26
+ const META_THEME_COLOR = { light: '#FAFAF8', dark: '#14151A' };
27
+
28
+ const listeners = new Set();
29
+ let mediaQuery = null;
30
+
31
+ /** Read the stored explicit choice, or null if the user has not chosen. */
32
+ function storedChoice() {
33
+ try {
34
+ const v = localStorage.getItem(STORAGE_KEY);
35
+ return VALID.has(v) ? v : null;
36
+ } catch {
37
+ return null;
38
+ }
39
+ }
40
+
41
+ /** Resolve the OS preference (used only while there is no explicit choice). */
42
+ function osPreference() {
43
+ return (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)
44
+ ? 'dark'
45
+ : 'light';
46
+ }
47
+
48
+ /** Sync the <meta name="theme-color"> so mobile browser chrome matches. */
49
+ function syncMetaThemeColor(theme) {
50
+ const meta = document.querySelector('meta[name="theme-color"]');
51
+ if (meta) meta.setAttribute('content', META_THEME_COLOR[theme] || META_THEME_COLOR.light);
52
+ }
53
+
54
+ /** Current active theme ('light' | 'dark'). Reflects the <html data-theme>. */
55
+ export function getTheme() {
56
+ const attr = document.documentElement.dataset.theme;
57
+ return VALID.has(attr) ? attr : 'light';
58
+ }
59
+
60
+ /** True if the user has explicitly picked a theme (vs. following the OS). */
61
+ export function hasExplicitChoice() {
62
+ return storedChoice() !== null;
63
+ }
64
+
65
+ /**
66
+ * Apply a theme. `persist=true` records it as the user's explicit choice
67
+ * (stops OS-preference tracking); `persist=false` applies without recording
68
+ * (used by the OS-preference listener).
69
+ */
70
+ export function setTheme(theme, persist = true) {
71
+ const next = VALID.has(theme) ? theme : 'light';
72
+ document.documentElement.dataset.theme = next;
73
+ if (persist) {
74
+ try { localStorage.setItem(STORAGE_KEY, next); } catch { /* ignore */ }
75
+ }
76
+ syncMetaThemeColor(next);
77
+ const detail = { theme: next };
78
+ for (const fn of listeners) fn(next);
79
+ window.dispatchEvent(new CustomEvent(EVENT_NAME, { detail }));
80
+ return next;
81
+ }
82
+
83
+ /** Flip between light and dark, recording the result as an explicit choice. */
84
+ export function toggleTheme() {
85
+ return setTheme(getTheme() === 'dark' ? 'light' : 'dark');
86
+ }
87
+
88
+ /** Subscribe to theme changes. Returns an unsubscribe function. */
89
+ export function onThemeChange(fn) {
90
+ listeners.add(fn);
91
+ return () => listeners.delete(fn);
92
+ }
93
+
94
+ /**
95
+ * Initialize the theme system once at boot. The inline head snippet has
96
+ * already set <html data-theme>; here we keep meta in sync and — only while
97
+ * the user has no explicit choice — follow live OS preference changes.
98
+ */
99
+ export function initThemeSystem() {
100
+ syncMetaThemeColor(getTheme());
101
+
102
+ if (window.matchMedia) {
103
+ mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
104
+ const onOsChange = (e) => {
105
+ if (hasExplicitChoice()) return; // explicit choice wins over OS
106
+ setTheme(e.matches ? 'dark' : 'light', false);
107
+ };
108
+ if (mediaQuery.addEventListener) {
109
+ mediaQuery.addEventListener('change', onOsChange);
110
+ } else if (mediaQuery.addListener) {
111
+ mediaQuery.addListener(onOsChange); // older Safari
112
+ }
113
+ }
114
+ }