aimeat 1.7.0 → 1.9.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 (261) hide show
  1. package/dist/.env.example +4 -1
  2. package/dist/locales/en.json +573 -10
  3. package/dist/locales/fi.json +572 -9
  4. package/dist/public/css/views/admin-agent-integration.css +304 -0
  5. package/dist/public/css/views/agents-detail.css +1697 -120
  6. package/dist/public/css/views/profile.css +22 -2
  7. package/dist/public/css/views/public-knowledge-viewer.css +479 -0
  8. package/dist/public/js/i18n.js +9 -3
  9. package/dist/public/js/services/admin-agent-integration.js +52 -0
  10. package/dist/public/js/services/agent-integration.js +80 -0
  11. package/dist/public/js/services/agent-messages.js +3 -1
  12. package/dist/public/js/services/generator-spec-validate.js +23 -0
  13. package/dist/public/js/services/memory.js +39 -0
  14. package/dist/public/lib/live-updates.js +9 -4
  15. package/dist/public/llms-template.txt +106 -0
  16. package/dist/public/spa.html +7 -2
  17. package/dist/public/views/admin/agent-integration-tab.js +390 -0
  18. package/dist/public/views/admin/federation-tab.js +5 -5
  19. package/dist/public/views/admin/prompts-tab.js +9 -10
  20. package/dist/public/views/admin.js +2 -0
  21. package/dist/public/views/profile/access-tab.js +18 -0
  22. package/dist/public/views/profile/agents/agent-card.js +396 -0
  23. package/dist/public/views/profile/agents/shared-board.js +97 -0
  24. package/dist/public/views/profile/agents/state-detector.js +62 -0
  25. package/dist/public/views/profile/agents/tab-activity.js +232 -0
  26. package/dist/public/views/profile/agents/tab-agent-config.js +199 -0
  27. package/dist/public/views/profile/agents/tab-data-access.js +304 -0
  28. package/dist/public/views/profile/agents/tab-directives.js +178 -0
  29. package/dist/public/views/profile/agents/tab-integration.js +505 -0
  30. package/dist/public/views/profile/agents/tab-messages.js +278 -0
  31. package/dist/public/views/profile/agents/tab-services.js +17 -0
  32. package/dist/public/views/profile/agents/tab-tasks.js +17 -0
  33. package/dist/public/views/profile/agents-messages-subtab.js +12 -10
  34. package/dist/public/views/profile/agents-services-subtab.js +17 -11
  35. package/dist/public/views/profile/agents-tab.js +159 -255
  36. package/dist/public/views/profile/agents-task-builder.js +403 -0
  37. package/dist/public/views/profile/agents-tasks-subtab.js +186 -140
  38. package/dist/public/views/profile/generator-detail.js +8 -1
  39. package/dist/public/views/profile/memory-tab.js +371 -7
  40. package/dist/public/views/profile/wallet-tab.js +14 -0
  41. package/dist/public/views/public-knowledge-viewer.js +650 -0
  42. package/dist/src/auth/middleware.d.ts.map +1 -1
  43. package/dist/src/auth/middleware.js +17 -0
  44. package/dist/src/auth/middleware.js.map +1 -1
  45. package/dist/src/config.d.ts +1 -0
  46. package/dist/src/config.d.ts.map +1 -1
  47. package/dist/src/config.js +1 -0
  48. package/dist/src/config.js.map +1 -1
  49. package/dist/src/middleware/readiness-gate.d.ts +18 -0
  50. package/dist/src/middleware/readiness-gate.d.ts.map +1 -0
  51. package/dist/src/middleware/readiness-gate.js +50 -0
  52. package/dist/src/middleware/readiness-gate.js.map +1 -0
  53. package/dist/src/models/agent-capabilities-schemas.d.ts +3 -0
  54. package/dist/src/models/agent-capabilities-schemas.d.ts.map +1 -1
  55. package/dist/src/models/agent-capabilities-schemas.js +3 -0
  56. package/dist/src/models/agent-capabilities-schemas.js.map +1 -1
  57. package/dist/src/models/agent-directives-schemas.d.ts +12 -0
  58. package/dist/src/models/agent-directives-schemas.d.ts.map +1 -1
  59. package/dist/src/models/agent-directives-schemas.js +7 -0
  60. package/dist/src/models/agent-directives-schemas.js.map +1 -1
  61. package/dist/src/models/agent-onboarding-schemas.d.ts +45 -0
  62. package/dist/src/models/agent-onboarding-schemas.d.ts.map +1 -0
  63. package/dist/src/models/agent-onboarding-schemas.js +91 -0
  64. package/dist/src/models/agent-onboarding-schemas.js.map +1 -0
  65. package/dist/src/models/webhook-schemas.d.ts +266 -0
  66. package/dist/src/models/webhook-schemas.d.ts.map +1 -0
  67. package/dist/src/models/webhook-schemas.js +137 -0
  68. package/dist/src/models/webhook-schemas.js.map +1 -0
  69. package/dist/src/routes/admin-agent-integration.d.ts +24 -0
  70. package/dist/src/routes/admin-agent-integration.d.ts.map +1 -0
  71. package/dist/src/routes/admin-agent-integration.js +186 -0
  72. package/dist/src/routes/admin-agent-integration.js.map +1 -0
  73. package/dist/src/routes/admin-monitoring.js +12 -7
  74. package/dist/src/routes/admin-monitoring.js.map +1 -1
  75. package/dist/src/routes/agent-activity.d.ts.map +1 -1
  76. package/dist/src/routes/agent-activity.js +17 -0
  77. package/dist/src/routes/agent-activity.js.map +1 -1
  78. package/dist/src/routes/agent-capabilities.d.ts +1 -0
  79. package/dist/src/routes/agent-capabilities.d.ts.map +1 -1
  80. package/dist/src/routes/agent-capabilities.js +9 -0
  81. package/dist/src/routes/agent-capabilities.js.map +1 -1
  82. package/dist/src/routes/agent-directives.d.ts +5 -1
  83. package/dist/src/routes/agent-directives.d.ts.map +1 -1
  84. package/dist/src/routes/agent-directives.js +74 -20
  85. package/dist/src/routes/agent-directives.js.map +1 -1
  86. package/dist/src/routes/agent-integration.d.ts +1 -0
  87. package/dist/src/routes/agent-integration.d.ts.map +1 -1
  88. package/dist/src/routes/agent-integration.js +128 -11
  89. package/dist/src/routes/agent-integration.js.map +1 -1
  90. package/dist/src/routes/agent-messages.d.ts +5 -1
  91. package/dist/src/routes/agent-messages.d.ts.map +1 -1
  92. package/dist/src/routes/agent-messages.js +20 -1
  93. package/dist/src/routes/agent-messages.js.map +1 -1
  94. package/dist/src/routes/agent-onboarding.d.ts +23 -0
  95. package/dist/src/routes/agent-onboarding.d.ts.map +1 -0
  96. package/dist/src/routes/agent-onboarding.js +374 -0
  97. package/dist/src/routes/agent-onboarding.js.map +1 -0
  98. package/dist/src/routes/agent-skill-bundle.d.ts +16 -0
  99. package/dist/src/routes/agent-skill-bundle.d.ts.map +1 -0
  100. package/dist/src/routes/agent-skill-bundle.js +133 -0
  101. package/dist/src/routes/agent-skill-bundle.js.map +1 -0
  102. package/dist/src/routes/agent-tasks.d.ts +8 -1
  103. package/dist/src/routes/agent-tasks.d.ts.map +1 -1
  104. package/dist/src/routes/agent-tasks.js +192 -14
  105. package/dist/src/routes/agent-tasks.js.map +1 -1
  106. package/dist/src/routes/agent-telemetry.d.ts +15 -0
  107. package/dist/src/routes/agent-telemetry.d.ts.map +1 -0
  108. package/dist/src/routes/agent-telemetry.js +99 -0
  109. package/dist/src/routes/agent-telemetry.js.map +1 -0
  110. package/dist/src/routes/agent-webhook.d.ts +18 -0
  111. package/dist/src/routes/agent-webhook.d.ts.map +1 -0
  112. package/dist/src/routes/agent-webhook.js +243 -0
  113. package/dist/src/routes/agent-webhook.js.map +1 -0
  114. package/dist/src/routes/agents.d.ts.map +1 -1
  115. package/dist/src/routes/agents.js +203 -4
  116. package/dist/src/routes/agents.js.map +1 -1
  117. package/dist/src/routes/auth.d.ts.map +1 -1
  118. package/dist/src/routes/auth.js +45 -2
  119. package/dist/src/routes/auth.js.map +1 -1
  120. package/dist/src/routes/federation-auth.d.ts.map +1 -1
  121. package/dist/src/routes/federation-auth.js +3 -1
  122. package/dist/src/routes/federation-auth.js.map +1 -1
  123. package/dist/src/routes/federation-peer.d.ts.map +1 -1
  124. package/dist/src/routes/federation-peer.js +11 -2
  125. package/dist/src/routes/federation-peer.js.map +1 -1
  126. package/dist/src/routes/federation-sync.d.ts +1 -0
  127. package/dist/src/routes/federation-sync.d.ts.map +1 -1
  128. package/dist/src/routes/federation-sync.js +29 -0
  129. package/dist/src/routes/federation-sync.js.map +1 -1
  130. package/dist/src/routes/ghii.d.ts.map +1 -1
  131. package/dist/src/routes/ghii.js +42 -5
  132. package/dist/src/routes/ghii.js.map +1 -1
  133. package/dist/src/routes/knowledge.d.ts.map +1 -1
  134. package/dist/src/routes/knowledge.js +19 -7
  135. package/dist/src/routes/knowledge.js.map +1 -1
  136. package/dist/src/routes/memory.d.ts +9 -0
  137. package/dist/src/routes/memory.d.ts.map +1 -1
  138. package/dist/src/routes/memory.js +307 -12
  139. package/dist/src/routes/memory.js.map +1 -1
  140. package/dist/src/routes/portal.d.ts.map +1 -1
  141. package/dist/src/routes/portal.js +1 -0
  142. package/dist/src/routes/portal.js.map +1 -1
  143. package/dist/src/routes/prompts.d.ts +1 -0
  144. package/dist/src/routes/prompts.d.ts.map +1 -1
  145. package/dist/src/routes/prompts.js +40 -1
  146. package/dist/src/routes/prompts.js.map +1 -1
  147. package/dist/src/routes/sharing-groups.d.ts.map +1 -1
  148. package/dist/src/routes/sharing-groups.js +8 -2
  149. package/dist/src/routes/sharing-groups.js.map +1 -1
  150. package/dist/src/routes/wallet.d.ts.map +1 -1
  151. package/dist/src/routes/wallet.js +2 -0
  152. package/dist/src/routes/wallet.js.map +1 -1
  153. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  154. package/dist/src/server-bootstrap/routes-loader.js +47 -3
  155. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  156. package/dist/src/services/config-schema.d.ts.map +1 -1
  157. package/dist/src/services/config-schema.js +2 -1
  158. package/dist/src/services/config-schema.js.map +1 -1
  159. package/dist/src/services/core-jobs.d.ts.map +1 -1
  160. package/dist/src/services/core-jobs.js +3 -2
  161. package/dist/src/services/core-jobs.js.map +1 -1
  162. package/dist/src/services/federation-helpers.d.ts +1 -0
  163. package/dist/src/services/federation-helpers.d.ts.map +1 -1
  164. package/dist/src/services/federation-helpers.js +1 -1
  165. package/dist/src/services/federation-helpers.js.map +1 -1
  166. package/dist/src/services/generator-autopilot.d.ts.map +1 -1
  167. package/dist/src/services/generator-autopilot.js +125 -26
  168. package/dist/src/services/generator-autopilot.js.map +1 -1
  169. package/dist/src/services/generator-prompts/index.d.ts +1 -1
  170. package/dist/src/services/generator-prompts/index.d.ts.map +1 -1
  171. package/dist/src/services/generator-prompts/index.js +1 -1
  172. package/dist/src/services/generator-prompts/index.js.map +1 -1
  173. package/dist/src/services/generator-prompts/spec-validate.d.ts +1 -0
  174. package/dist/src/services/generator-prompts/spec-validate.d.ts.map +1 -1
  175. package/dist/src/services/generator-prompts/spec-validate.js +20 -0
  176. package/dist/src/services/generator-prompts/spec-validate.js.map +1 -1
  177. package/dist/src/services/generator-prompts/validate.d.ts +7 -1
  178. package/dist/src/services/generator-prompts/validate.d.ts.map +1 -1
  179. package/dist/src/services/generator-prompts/validate.js +70 -0
  180. package/dist/src/services/generator-prompts/validate.js.map +1 -1
  181. package/dist/src/services/onboarding-validator.d.ts +22 -0
  182. package/dist/src/services/onboarding-validator.d.ts.map +1 -0
  183. package/dist/src/services/onboarding-validator.js +202 -0
  184. package/dist/src/services/onboarding-validator.js.map +1 -0
  185. package/dist/src/services/platform-detector.d.ts +27 -0
  186. package/dist/src/services/platform-detector.d.ts.map +1 -0
  187. package/dist/src/services/platform-detector.js +73 -0
  188. package/dist/src/services/platform-detector.js.map +1 -0
  189. package/dist/src/services/prompt-defaults.d.ts +1 -0
  190. package/dist/src/services/prompt-defaults.d.ts.map +1 -1
  191. package/dist/src/services/prompt-defaults.js +875 -47
  192. package/dist/src/services/prompt-defaults.js.map +1 -1
  193. package/dist/src/services/prompt-seeder.js +1 -1
  194. package/dist/src/services/prompt-seeder.js.map +1 -1
  195. package/dist/src/services/readiness-scorer.d.ts +34 -0
  196. package/dist/src/services/readiness-scorer.d.ts.map +1 -0
  197. package/dist/src/services/readiness-scorer.js +87 -0
  198. package/dist/src/services/readiness-scorer.js.map +1 -0
  199. package/dist/src/services/skill-bundle/generator.d.ts +17 -0
  200. package/dist/src/services/skill-bundle/generator.d.ts.map +1 -0
  201. package/dist/src/services/skill-bundle/generator.js +387 -0
  202. package/dist/src/services/skill-bundle/generator.js.map +1 -0
  203. package/dist/src/services/skill-bundle/generic-adapter.d.ts +16 -0
  204. package/dist/src/services/skill-bundle/generic-adapter.d.ts.map +1 -0
  205. package/dist/src/services/skill-bundle/generic-adapter.js +96 -0
  206. package/dist/src/services/skill-bundle/generic-adapter.js.map +1 -0
  207. package/dist/src/services/skill-bundle/hermes-adapter.d.ts +25 -0
  208. package/dist/src/services/skill-bundle/hermes-adapter.d.ts.map +1 -0
  209. package/dist/src/services/skill-bundle/hermes-adapter.js +302 -0
  210. package/dist/src/services/skill-bundle/hermes-adapter.js.map +1 -0
  211. package/dist/src/services/skill-bundle/types.d.ts +54 -0
  212. package/dist/src/services/skill-bundle/types.d.ts.map +1 -0
  213. package/dist/src/services/skill-bundle/types.js +8 -0
  214. package/dist/src/services/skill-bundle/types.js.map +1 -0
  215. package/dist/src/services/task-stall-detector.d.ts +10 -2
  216. package/dist/src/services/task-stall-detector.d.ts.map +1 -1
  217. package/dist/src/services/task-stall-detector.js +34 -5
  218. package/dist/src/services/task-stall-detector.js.map +1 -1
  219. package/dist/src/services/webhook-dispatcher.d.ts +71 -0
  220. package/dist/src/services/webhook-dispatcher.d.ts.map +1 -0
  221. package/dist/src/services/webhook-dispatcher.js +259 -0
  222. package/dist/src/services/webhook-dispatcher.js.map +1 -0
  223. package/dist/src/storage/interface.d.ts +82 -2
  224. package/dist/src/storage/interface.d.ts.map +1 -1
  225. package/dist/src/storage/providers/mongodb/index.d.ts +20 -1
  226. package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
  227. package/dist/src/storage/providers/mongodb/index.js +254 -3
  228. package/dist/src/storage/providers/mongodb/index.js.map +1 -1
  229. package/dist/src/storage/providers/sqlite/index.d.ts +18 -1
  230. package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
  231. package/dist/src/storage/providers/sqlite/index.js +173 -4
  232. package/dist/src/storage/providers/sqlite/index.js.map +1 -1
  233. package/dist/src/storage/providers/sqlite/repos/agent-directives.d.ts.map +1 -1
  234. package/dist/src/storage/providers/sqlite/repos/agent-directives.js +8 -4
  235. package/dist/src/storage/providers/sqlite/repos/agent-directives.js.map +1 -1
  236. package/dist/src/storage/providers/sqlite/repos/agent.d.ts.map +1 -1
  237. package/dist/src/storage/providers/sqlite/repos/agent.js +25 -4
  238. package/dist/src/storage/providers/sqlite/repos/agent.js.map +1 -1
  239. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  240. package/dist/src/storage/providers/sqlite/schema.js +73 -1
  241. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  242. package/dist/src/storage/repositories/agent-onboarding.repository.d.ts +16 -0
  243. package/dist/src/storage/repositories/agent-onboarding.repository.d.ts.map +1 -0
  244. package/dist/src/storage/repositories/agent-onboarding.repository.js +8 -0
  245. package/dist/src/storage/repositories/agent-onboarding.repository.js.map +1 -0
  246. package/dist/src/storage/repositories/agent-webhook.repository.d.ts +21 -0
  247. package/dist/src/storage/repositories/agent-webhook.repository.d.ts.map +1 -0
  248. package/dist/src/storage/repositories/agent-webhook.repository.js +2 -0
  249. package/dist/src/storage/repositories/agent-webhook.repository.js.map +1 -0
  250. package/dist/src/storage/repositories/agent.repository.d.ts +1 -0
  251. package/dist/src/storage/repositories/agent.repository.d.ts.map +1 -1
  252. package/dist/src/storage/repositories/index.d.ts +2 -0
  253. package/dist/src/storage/repositories/index.d.ts.map +1 -1
  254. package/dist/src/utils/env-config.d.ts.map +1 -1
  255. package/dist/src/utils/env-config.js +7 -1
  256. package/dist/src/utils/env-config.js.map +1 -1
  257. package/dist/src/utils/url-validator.d.ts.map +1 -1
  258. package/dist/src/utils/url-validator.js +3 -0
  259. package/dist/src/utils/url-validator.js.map +1 -1
  260. package/package.json +1 -1
  261. package/prisma/schema.prisma +67 -7
@@ -1,44 +1,36 @@
1
1
  /**
2
2
  * @file agents-tab.js
3
- * @description Profile tab for managing AI agents — device auth flow, agent prompt,
4
- * platform instructions, scope management modal, and agent detail cards.
3
+ * @description Profile tab for managing AI agents -- Shared Agent Board,
4
+ * expandable agent cards with Two-Zone Header + 8-tab interface,
5
+ * device auth flow, scope management modal.
5
6
  * @version-history
6
- * v1.0.0 — 2026-03-17 — Refactor: replace all inline styles with CSS utility classes
7
- * v1.1.0 — 2026-03-18 — Rewrite agent prompt to use device-auth flow; remove connectivity key UI
8
- * v1.2.0 — 2026-03-19 — Replace profile-initiated device auth with inline pending request approval
9
- * v1.3.0 — 2026-05-21 — Shorten agent prompt to delegate to tier1; add Download/Copy Instructions buttons
10
- * v1.4.0 — 2026-05-21 — Add sub-tab navigation (Tasks, Directives) in expanded agent detail view
11
- * v1.5.0 — 2026-05-22 — Add Capabilities sub-tab with technical/domain skill display
12
- * v1.6.0 — 2026-05-22 — Add Activity sub-tab with stats, chart, scheduled jobs, event log
13
- * v1.7.0 — 2026-05-22 — Add Services and Messages sub-tabs
7
+ * v1.0.0 -- 2026-03-17 -- Refactor: replace all inline styles with CSS utility classes
8
+ * v1.1.0 -- 2026-03-18 -- Rewrite agent prompt to use device-auth flow; remove connectivity key UI
9
+ * v1.2.0 -- 2026-03-19 -- Replace profile-initiated device auth with inline pending request approval
10
+ * v1.3.0 -- 2026-05-21 -- Shorten agent prompt to delegate to tier1; add Download/Copy Instructions buttons
11
+ * v1.4.0 -- 2026-05-21 -- Add sub-tab navigation (Tasks, Directives) in expanded agent detail view
12
+ * v1.5.0 -- 2026-05-22 -- Add Capabilities sub-tab with technical/domain skill display
13
+ * v1.6.0 -- 2026-05-22 -- Add Activity sub-tab with stats, chart, scheduled jobs, event log
14
+ * v1.7.0 -- 2026-05-22 -- Add Services and Messages sub-tabs
15
+ * v2.1.0 -- 2026-05-24 -- Fix: scroll-to on board click, agent count badge in header
16
+ * v2.0.0 -- 2026-05-24 -- Plan 4: Shared Agent Board + expandable cards with Two-Zone Header + 8-tab bar
17
+ * v2.2.0 -- 2026-05-24 -- Fix M2: compact Connect Agent, C1: load task stats for production cards
14
18
  */
15
19
  import { h } from 'preact';
16
20
  import { useState, useEffect, useRef } from 'preact/hooks';
17
21
  import htm from 'htm';
18
22
  const html = htm.bind(h);
19
23
  import { t } from '/js/i18n.js';
20
- import { escHtml, timeAgo, copyToClipboard } from '/js/utils.js';
24
+ import { escHtml, copyToClipboard } from '/js/utils.js';
21
25
  import { Spinner } from './shared.js';
22
26
  import { apiGet, apiPost, apiPatch } from '/js/api.js';
23
27
  import { listAgents, updateAgentScopes, deleteAgent } from '/js/services/agents.js';
24
28
  import { getNodeUrl } from '/js/services/auth.js';
25
29
  import { useConfirm } from '/components/Modal.js';
26
- import AgentTasksSubtab from './agents-tasks-subtab.js';
27
- import AgentDirectivesSubtab from './agents-directives-subtab.js';
28
- import AgentCapabilitiesSubtab from './agents-capabilities-subtab.js';
29
- import AgentActivitySubtab from './agents-activity-subtab.js';
30
- import AgentServicesSubtab from './agents-services-subtab.js';
31
- import AgentMessagesSubtab from './agents-messages-subtab.js';
32
-
33
- // === Agent Detail Sub-tabs ===
34
- const AGENT_SUBTABS = [
35
- { id: 'tasks', label: 'profile.agents.subtabs.tasks' },
36
- { id: 'directives', label: 'profile.agents.subtabs.directives' },
37
- { id: 'capabilities', label: 'profile.agents.subtabs.capabilities' },
38
- { id: 'activity', label: 'profile.agents.subtabs.activity' },
39
- { id: 'services', label: 'profile.agents.subtabs.services' },
40
- { id: 'messages', label: 'profile.agents.subtabs.messages' },
41
- ];
30
+ import SharedBoard from './agents/shared-board.js';
31
+ import AgentCard from './agents/agent-card.js';
32
+ import { getOnboarding } from '/js/services/agent-integration.js';
33
+ import { listTasks } from '/js/services/agent-tasks.js';
42
34
 
43
35
  // === Scope Management Constants ===
44
36
  const SCOPE_DOMAINS = [
@@ -95,15 +87,35 @@ function buildAgentPrompt(sess) {
95
87
  Owner: ${sess.owner}
96
88
  Node: ${url}
97
89
 
98
- 1. Authenticate: POST ${url}/v1/agents/device-authorize
99
- Body: { "agent_name": "your-name", "owner": "${sess.owner}" }
100
- Tell me the verification URL so I can approve.
101
-
102
- 2. After auth, download your full operating instructions:
103
- GET ${url}/v1/prompts/tier1
104
- This file contains your directives, task queue, capabilities
105
- reporting, and everything you need to operate on this node.
106
- Read it fully before doing anything else.`;
90
+ Step 1: Authenticate
91
+ If you already have a saved AIMEAT token, verify it works with GET ${url}/v1/agents/me/inbox first. If it works, skip to Step 2.
92
+ Otherwise: POST ${url}/v1/agents/device-authorize
93
+ Body: { "agent_name": "your-name", "owner": "${sess.owner}" }
94
+ Show me the verification code, then IMMEDIATELY start polling in the same turn.
95
+ Poll command (run this in a loop every 5 seconds until it returns HTTP 200):
96
+ curl -s -X POST ${url}/v1/agents/device-token -H "Content-Type: application/json" -d '{"device_code":"YOUR_DEVICE_CODE","grant_type":"urn:ietf:params:oauth:grant-type:device_code"}'
97
+ When HTTP 200: the response JSON has access_token at the top level. Save it:
98
+ echo 'RESPONSE' | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])" > ~/.aimeat_token.txt
99
+ I will approve while you poll. Keep polling until success. Only do ONE auth cycle.
100
+ IMPORTANT: Start polling right away. I do not need to tell you "approved".
101
+
102
+ Step 2: Download your skill bundle (first thing after auth)
103
+ GET ${url}/v1/agents/your-name/skill-bundle
104
+ Header: Authorization: Bearer <your-token>
105
+ Save as ZIP, extract it, and read SKILL.md.
106
+ It contains your personalized directives, rules, and complete API reference.
107
+
108
+ Step 3: Read your system prompt
109
+ GET ${url}/v1/prompts/tier1
110
+ Header: Authorization: Bearer <your-token>
111
+ This gives you your operating loop, task queue, inbox, and all endpoint URLs.
112
+
113
+ Step 4: Start Hello Integration
114
+ GET ${url}/v1/agents/me/onboarding
115
+ Header: Authorization: Bearer <your-token>
116
+ Follow the onboarding steps to reach production readiness.
117
+
118
+ Tip: Use /v1/agents/me/ as shortcut in all agent URLs -- it resolves to your name.`;
107
119
  }
108
120
 
109
121
  /* ── Platform instructions ── */
@@ -166,18 +178,18 @@ const PLATFORM_LABELS = { windows:'profile.platforms.windows', mac:'profile.plat
166
178
  export default function AgentsTab({ session, showToast, onStats }) {
167
179
  const { confirm, ConfirmUI } = useConfirm();
168
180
  const [agents, setAgents] = useState(null);
181
+ const [onboardings, setOnboardings] = useState({});
169
182
  const [promptCopied, setPromptCopied] = useState(false);
170
183
  const [platExpand, setPlatExpand] = useState(false);
171
184
  const [activePlat, setActivePlat] = useState('windows');
172
185
  const [scopesModal, setScopesModal] = useState(null);
173
186
  const [expandedAgent, setExpandedAgent] = useState(null);
174
- const [activeSubtab, setActiveSubtab] = useState('tasks');
175
- const [gaiiCopied, setGaiiCopied] = useState(null);
176
- const [keyCopied, setKeyCopied] = useState(null);
177
187
  const [pendingRequests, setPendingRequests] = useState([]);
178
188
  const [approvingCode, setApprovingCode] = useState(null);
179
189
  const [approvePreset, setApprovePreset] = useState('standard');
180
190
  const [tier1Copied, setTier1Copied] = useState(false);
191
+ const [connectExpanded, setConnectExpanded] = useState(false);
192
+ const [taskStatsMap, setTaskStatsMap] = useState({});
181
193
 
182
194
  useEffect(() => {
183
195
  if (session) loadData();
@@ -203,47 +215,46 @@ export default function AgentsTab({ session, showToast, onStats }) {
203
215
  const list = await listAgents(session.owner);
204
216
  setAgents(list);
205
217
  onStats?.({ agents: list.length });
218
+ const obMap = {};
219
+ await Promise.all(list.map(async (a) => {
220
+ try {
221
+ const resp = await getOnboarding(a.name);
222
+ obMap[a.name] = resp?.data?.onboarding || null;
223
+ } catch { obMap[a.name] = null; }
224
+ }));
225
+ setOnboardings(obMap);
226
+ const tsMap = {};
227
+ await Promise.all(list.map(async (a) => {
228
+ try {
229
+ const [doneResp, activeResp] = await Promise.all([
230
+ listTasks(a.name, { status: 'done', per_page: 100 }),
231
+ listTasks(a.name, { status: 'active', per_page: 100 }),
232
+ ]);
233
+ const today = new Date().toISOString().slice(0, 10);
234
+ const doneToday = (doneResp?.data?.tasks || []).filter(tk => tk.completedAt?.startsWith(today)).length;
235
+ const activeCount = (activeResp?.data?.tasks || []).length;
236
+ tsMap[a.name] = { done: doneToday, active: activeCount };
237
+ } catch { tsMap[a.name] = null; }
238
+ }));
239
+ setTaskStatsMap(tsMap);
206
240
  } catch { setAgents([]); }
207
241
  }
208
242
 
209
- // Live update listener
243
+ // Live update listener + fallback polling every 10s
210
244
  const loadRef = useRef(loadData);
211
245
  loadRef.current = loadData;
212
246
  useEffect(() => {
213
247
  const handler = () => loadRef.current();
214
248
  window.addEventListener('aimeat-live-update', handler);
215
- return () => window.removeEventListener('aimeat-live-update', handler);
249
+ const poller = setInterval(() => loadRef.current(), 10000);
250
+ return () => {
251
+ window.removeEventListener('aimeat-live-update', handler);
252
+ clearInterval(poller);
253
+ };
216
254
  }, []);
217
255
 
218
256
  function toggleAgent(name) {
219
257
  setExpandedAgent(prev => prev === name ? null : name);
220
- setActiveSubtab('tasks');
221
- }
222
-
223
- function truncateKey(key) {
224
- if (!key) return '-';
225
- if (key.length <= 20) return key;
226
- return key.slice(0, 10) + '...' + key.slice(-10);
227
- }
228
-
229
- function handleCopyGaii(gaii) {
230
- copyToClipboard(gaii).then(() => {
231
- setGaiiCopied(gaii);
232
- setTimeout(() => setGaiiCopied(null), 2000);
233
- });
234
- }
235
-
236
- function handleCopyKey(key) {
237
- copyToClipboard(key).then(() => {
238
- setKeyCopied(key);
239
- setTimeout(() => setKeyCopied(null), 2000);
240
- });
241
- }
242
-
243
- function formatDate(iso) {
244
- if (!iso) return '-';
245
- try { return new Date(iso).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' }); }
246
- catch { return '-'; }
247
258
  }
248
259
 
249
260
  async function handleSaveScopes(agentName, newScopes) {
@@ -272,6 +283,7 @@ export default function AgentsTab({ session, showToast, onStats }) {
272
283
  });
273
284
  if (resp?.ok !== false) {
274
285
  showToast(t('profile.agents.pendingRequests.approved'));
286
+ setPendingRequests(prev => prev.filter(r => r.user_code !== userCode));
275
287
  setApprovingCode(null);
276
288
  setApprovePreset('standard');
277
289
  loadData();
@@ -301,7 +313,11 @@ export default function AgentsTab({ session, showToast, onStats }) {
301
313
  owner_token: session.jwt,
302
314
  });
303
315
  showToast(t('profile.agents.pendingRequests.denied'));
304
- } catch { /* ignore */ }
316
+ setPendingRequests(prev => prev.filter(r => r.user_code !== userCode));
317
+ loadData();
318
+ } catch (e) {
319
+ showToast(e.message || 'Deny failed', true);
320
+ }
305
321
  }
306
322
 
307
323
  async function downloadTier1() {
@@ -339,7 +355,12 @@ export default function AgentsTab({ session, showToast, onStats }) {
339
355
  if (!agents) return html`<${Spinner} text=${t('profile.agents.loadingAgents')} />`;
340
356
 
341
357
  return html`
342
- <div class="section-title">${t('profile.agents.title')}</div>
358
+ <div class="pf-agd-header-row">
359
+ <div class="section-title">${t('profile.agents.title')}${agents.length > 0 ? html` <span class="pf-agd-count-badge">(${agents.length})</span>` : ''}</div>
360
+ <button class="${connectExpanded ? 'btn-outline' : 'btn-primary'} btn-sm" onClick=${() => setConnectExpanded(!connectExpanded)}>
361
+ ${connectExpanded ? t('profile.agents.detail.zone2.cancel') : `+ ${t('profile.agents.connect')}`}
362
+ </button>
363
+ </div>
343
364
  <div class="section-desc">${t('profile.agents.desc')}</div>
344
365
 
345
366
  ${pendingRequests.length > 0 && html`
@@ -385,7 +406,7 @@ export default function AgentsTab({ session, showToast, onStats }) {
385
406
  <button class="btn-success" onClick=${() => setApprovingCode(req.user_code)}>
386
407
  ${t('profile.agents.pendingRequests.approve')}
387
408
  </button>
388
- <button class="btn-danger" onClick=${() => handleDeny(req.user_code)}>
409
+ <button class="btn-danger-solid" onClick=${() => handleDeny(req.user_code)}>
389
410
  ${t('profile.agents.pendingRequests.deny')}
390
411
  </button>
391
412
  </div>
@@ -395,197 +416,80 @@ export default function AgentsTab({ session, showToast, onStats }) {
395
416
  </div>
396
417
  `}
397
418
 
398
- <div class="agent-cta">
399
- <h3>${t('profile.agents.connect')}</h3>
400
- <p>${t('profile.agents.connectDesc')}</p>
401
- <div class="agent-prompt-box">${buildAgentPrompt(session)}</div>
402
- <button class="copy-prompt-btn" onClick=${() => {
403
- copyToClipboard(buildAgentPrompt(session)).then(() => {
404
- setPromptCopied(true);
405
- setTimeout(() => setPromptCopied(false), 2000);
406
- });
407
- }}>${promptCopied ? '\u2705 ' + t('profile.agents.copied') : t('profile.agents.copyPrompt')}</button>
408
- ${agents.length > 0 && html`
409
- <div class="flex-row mt-half pf-tier1-buttons">
410
- <button class="btn-outline" onClick=${downloadTier1}>
411
- ${t('profile.agents.downloadInstructions')}
412
- </button>
413
- <button class="btn-outline" onClick=${copyTier1}>
414
- ${tier1Copied ? '\u2705 ' + t('profile.agents.copied') : t('profile.agents.copyFullInstructions')}
415
- </button>
416
- </div>
417
- `}
418
-
419
- <div class="pf-agent-divider">
420
- <p class="mb-half">${t('profile.agents.noAgent')}</p>
421
- <button class="expand-btn" onClick=${() => setPlatExpand(!platExpand)}>
422
- <span>${t('profile.agents.seeHow')}</span>
423
- <span class="pf-chevron ${platExpand ? 'pf-chevron-open' : ''}">\u25BC</span>
424
- </button>
425
- ${platExpand && html`
426
- <div class="platform-instructions expanded">
427
- <div class="platform-tabs">
428
- ${PLATFORM_KEYS.map(k => html`
429
- <button class="platform-tab ${k === activePlat ? 'active' : ''}" onClick=${() => setActivePlat(k)}>${t(PLATFORM_LABELS[k])}</button>
430
- `)}
431
- </div>
432
- ${/* SAFE: PLATFORMS is hardcoded developer constant, not user input */''}
433
- <div class="platform-content" dangerouslySetInnerHTML=${{ __html: PLATFORMS[activePlat] }}></div>
419
+ ${connectExpanded && html`
420
+ <div class="pf-agd-connect-content">
421
+ <p>${t('profile.agents.connectDesc')}</p>
422
+ <div class="agent-prompt-box">${buildAgentPrompt(session)}</div>
423
+ <button class="copy-prompt-btn" onClick=${() => {
424
+ copyToClipboard(buildAgentPrompt(session)).then(() => {
425
+ setPromptCopied(true);
426
+ setTimeout(() => setPromptCopied(false), 2000);
427
+ });
428
+ }}>${promptCopied ? '\u2705 ' + t('profile.agents.copied') : t('profile.agents.copyPrompt')}</button>
429
+ ${agents.length > 0 && html`
430
+ <div class="flex-row mt-half pf-tier1-buttons">
431
+ <button class="btn-outline" onClick=${downloadTier1}>
432
+ ${t('profile.agents.downloadInstructions')}
433
+ </button>
434
+ <button class="btn-outline" onClick=${copyTier1}>
435
+ ${tier1Copied ? '\u2705 ' + t('profile.agents.copied') : t('profile.agents.copyFullInstructions')}
436
+ </button>
434
437
  </div>
435
438
  `}
436
- </div>
437
- </div>
438
-
439
- ${agents.length === 0
440
- ? html`<div class="empty">${t('profile.agents.empty')}</div>`
441
- : agents.map(a => {
442
- const isExpanded = expandedAgent === a.name;
443
- return html`
444
- <div class="card agent-card ${isExpanded ? 'agent-card-expanded' : ''}">
445
- <div class="agent-card-header-clickable" onClick=${() => toggleAgent(a.name)}>
446
- <div class="card-header mb-0">
447
- <div class="flex-row">
448
- <span class="agent-expand-icon ${isExpanded ? 'pf-rotate-90' : ''}">\u25B6</span>
449
- <div class="card-title">${escHtml(a.display_name || a.name)}</div>
450
- </div>
451
- <span class="badge badge-info">${escHtml(a.name)}</span>
452
- <span class="${a.federate ? 'badge badge-success' : 'badge badge-muted'}"
453
- onClick=${(e) => { e.stopPropagation(); toggleFederate(a); }}
454
- title=${t('profile.federateTooltip')}>
455
- ${a.federate ? t('profile.federated') : t('profile.notFederated')}
456
- </span>
457
- </div>
458
- <div class="card-subtitle mt-xs">
459
- ${t('profile.agents.trust')}: ${a.trust_score ?? '-'} \u2502
460
- ${t('profile.agents.balance')}: ${a.morsel_balance ?? '-'} \u2502
461
- ${t('profile.agents.lastSeen')}: ${a.last_seen ? timeAgo(a.last_seen) : '-'}
462
- </div>
463
- </div>
464
-
465
- ${isExpanded && html`
466
- <div class="agent-details">
467
- <div class="agent-detail-row">
468
- <span class="agent-detail-label">GAII</span>
469
- <span class="agent-detail-value flex-row">
470
- <span class="text-code pf-code-break">${escHtml(a.gaii || '-')}</span>
471
- ${a.gaii && html`
472
- <button class="btn-outline agent-copy-btn" onClick=${(e) => { e.stopPropagation(); handleCopyGaii(a.gaii); }}>
473
- ${gaiiCopied === a.gaii ? '\u2713 ' + t('profile.agents.copied') : t('profile.agents.copyGaii')}
474
- </button>
475
- `}
476
- </span>
477
- </div>
478
-
479
- ${a.description ? html`
480
- <div class="agent-detail-row">
481
- <span class="agent-detail-label">${t('profile.agents.description')}</span>
482
- <span class="agent-detail-value">${escHtml(a.description)}</span>
483
- </div>
484
- ` : ''}
485
-
486
- <div class="agent-detail-row">
487
- <span class="agent-detail-label">${t('profile.agents.roles')}</span>
488
- <span class="agent-detail-value">
489
- ${(a.roles && a.roles.length > 0)
490
- ? a.roles.map(r => html`<span class="badge badge-muted pf-badge-gap">${escHtml(r)}</span>`)
491
- : html`<span class="badge badge-muted">agent</span>`
492
- }
493
- </span>
494
- </div>
495
-
496
- <div class="agent-detail-row">
497
- <span class="agent-detail-label">${t('profile.agents.trust')}</span>
498
- <span class="agent-detail-value">${a.trust_score ?? '-'}</span>
499
- </div>
500
-
501
- <div class="agent-detail-row">
502
- <span class="agent-detail-label">${t('profile.agents.balance')}</span>
503
- <span class="agent-detail-value">${a.morsel_balance ?? '-'}</span>
504
- </div>
505
-
506
- <div class="agent-detail-row">
507
- <span class="agent-detail-label">${t('profile.agents.lastSeen')}</span>
508
- <span class="agent-detail-value">${a.last_seen ? timeAgo(a.last_seen) + ' (' + formatDate(a.last_seen) + ')' : '-'}</span>
509
- </div>
510
-
511
- <div class="agent-detail-row">
512
- <span class="agent-detail-label">${t('profile.agents.created')}</span>
513
- <span class="agent-detail-value">${a.created_at ? formatDate(a.created_at) : '-'}</span>
514
- </div>
515
-
516
- ${a.public_key ? html`
517
- <div class="agent-detail-row">
518
- <span class="agent-detail-label">${t('profile.agents.publicKey')}</span>
519
- <span class="agent-detail-value flex-row">
520
- <code class="agent-pubkey">${escHtml(truncateKey(a.public_key))}</code>
521
- <button class="btn-outline agent-copy-btn" onClick=${(e) => { e.stopPropagation(); handleCopyKey(a.public_key); }}>
522
- ${keyCopied === a.public_key ? '\u2713 ' + t('profile.agents.copied') : t('profile.agents.copyGaii')}
523
- </button>
524
- </span>
525
- </div>
526
- ` : ''}
527
-
528
- ${a.capabilities?.length > 0 && html`
529
- <div class="agent-detail-row">
530
- <span class="agent-detail-label">${t('profile.agents.capabilities')}</span>
531
- <span class="agent-detail-value">
532
- <div class="caps">${a.capabilities.map(c => html`<span class="cap">${escHtml(c)}</span>`)}</div>
533
- </span>
534
- </div>
535
- `}
536
-
537
- <div class="agd-subtab-bar">
538
- ${AGENT_SUBTABS.map(tab => {
539
- const label = t(tab.label);
540
- return html`
541
- <button class="agd-subtab ${activeSubtab === tab.id ? 'agd-subtab-active' : ''}"
542
- onClick=${(e) => { e.stopPropagation(); setActiveSubtab(tab.id); }}>
543
- ${label !== tab.label ? label : tab.id.charAt(0).toUpperCase() + tab.id.slice(1)}
544
- </button>
545
- `;
546
- })}
547
- </div>
548
-
549
- <div class="agd-subtab-content" onClick=${(e) => e.stopPropagation()}>
550
- ${activeSubtab === 'tasks' && html`<${AgentTasksSubtab} agentName=${a.name} session=${session} showToast=${showToast} />`}
551
- ${activeSubtab === 'directives' && html`<${AgentDirectivesSubtab} agentName=${a.name} session=${session} showToast=${showToast} />`}
552
- ${activeSubtab === 'capabilities' && html`<${AgentCapabilitiesSubtab} agentName=${a.name} session=${session} showToast=${showToast} agent=${a} />`}
553
- ${activeSubtab === 'activity' && html`<${AgentActivitySubtab} agentName=${a.name} session=${session} showToast=${showToast} />`}
554
- ${activeSubtab === 'services' && html`<${AgentServicesSubtab} agentName=${a.name} session=${session} showToast=${showToast} />`}
555
- ${activeSubtab === 'messages' && html`<${AgentMessagesSubtab} agentName=${a.name} session=${session} showToast=${showToast} />`}
556
- </div>
557
439
 
558
- <div class="agent-detail-row mt-1">
559
- <button class="btn-danger btn-sm" onClick=${(e) => { e.stopPropagation(); handleDeleteAgent(a.name); }}>
560
- ${t('profile.agents.deleteAgent')}
561
- </button>
440
+ <div class="pf-agent-divider">
441
+ <p class="mb-half">${t('profile.agents.noAgent')}</p>
442
+ <button class="expand-btn" onClick=${() => setPlatExpand(!platExpand)}>
443
+ <span>${t('profile.agents.seeHow')}</span>
444
+ <span class="pf-chevron ${platExpand ? 'pf-chevron-open' : ''}">\u25BC</span>
445
+ </button>
446
+ ${platExpand && html`
447
+ <div class="platform-instructions expanded">
448
+ <div class="platform-tabs">
449
+ ${PLATFORM_KEYS.map(k => html`
450
+ <button class="platform-tab ${k === activePlat ? 'active' : ''}" onClick=${() => setActivePlat(k)}>${t(PLATFORM_LABELS[k])}</button>
451
+ `)}
562
452
  </div>
453
+ ${/* SAFE: PLATFORMS is hardcoded developer constant, not user input */''}
454
+ <div class="platform-content" dangerouslySetInnerHTML=${{ __html: PLATFORMS[activePlat] }}></div>
563
455
  </div>
564
456
  `}
565
-
566
- ${!isExpanded && a.capabilities?.length > 0 && html`
567
- <div class="caps mb-half">${a.capabilities.map(c => html`<span class="cap">${escHtml(c)}</span>`)}</div>
568
- `}
569
-
570
- ${(() => {
571
- const scopes = a.default_scopes ?? ['*'];
572
- const tpl = detectTemplate(scopes);
573
- const count = scopes.includes('*') ? '\u221E' : scopes.length;
574
- const isOwnerOrOp = session.roles?.includes('owner') || session.roles?.includes('operator');
575
- return html`
576
- <div class="scope-summary">
577
- <span class="scope-badge">${templateLabel(tpl)}</span>
578
- <span class="scope-count">${count} ${t('profile.agents.scopeUi.scopes')}</span>
579
- ${isOwnerOrOp
580
- ? html`<button class="scope-manage-btn" onClick=${(e) => { e.stopPropagation(); setScopesModal(a); }}>
581
- ${t('profile.agents.scopeUi.manage')} \u25B8
582
- </button>`
583
- : html`<span class="scope-lock">\uD83D\uDD12</span>`
584
- }
585
- </div>`;
586
- })()}
587
457
  </div>
588
- `; })
458
+ </div>
459
+ `}
460
+
461
+ ${agents.length === 0
462
+ ? html`<div class="empty">${t('profile.agents.empty')}</div>`
463
+ : html`
464
+ <${SharedBoard}
465
+ agents=${agents}
466
+ onboardings=${onboardings}
467
+ onAgentClick=${(name) => {
468
+ setExpandedAgent(name);
469
+ requestAnimationFrame(() => {
470
+ const el = document.querySelector(`[data-agent-name="${name}"]`);
471
+ el?.scrollIntoView({ behavior: 'smooth', block: 'start' });
472
+ });
473
+ }}
474
+ />
475
+ ${agents.map(a => html`
476
+ <div data-agent-name=${a.name}>
477
+ <${AgentCard}
478
+ key=${a.name}
479
+ agent=${{ ...a, taskStats: taskStatsMap[a.name] || null }}
480
+ onboarding=${onboardings[a.name]}
481
+ expanded=${expandedAgent === a.name}
482
+ onToggle=${toggleAgent}
483
+ session=${session}
484
+ showToast=${showToast}
485
+ allAgents=${agents}
486
+ onScopesClick=${(agent) => setScopesModal(agent)}
487
+ onDeleteClick=${handleDeleteAgent}
488
+ onFederateToggle=${toggleFederate}
489
+ />
490
+ </div>
491
+ `)}
492
+ `
589
493
  }
590
494
 
591
495
  ${scopesModal && html`<${ScopesModal}