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
@@ -0,0 +1,505 @@
1
+ /**
2
+ * @file tab-integration.js
3
+ * @description Integration tab for agent detail view. Shows onboarding checklist
4
+ * during onboarding or production status (connection, platform, readiness,
5
+ * identity, delivery log) after completion.
6
+ * @version-history
7
+ * v1.0.0 -- 2026-05-24 -- Initial creation for Agent Detail Tab-View
8
+ * v1.1.0 -- 2026-05-24 -- Fix 9 UI audit findings: pending icon, readiness score, webhook edit,
9
+ * strengths/gaps, last validated, roles badge, platform version, bundle update, copy install cmd
10
+ * v1.3.0 -- 2026-05-24 -- Audit fix: always show delivery log section, add warn icon for step pills
11
+ * v1.2.0 -- 2026-05-24 -- Add delivery status indicator dot, show polling fallback interval
12
+ */
13
+
14
+ import { h } from 'preact';
15
+ import { useState, useEffect, useRef } from 'preact/hooks';
16
+ import htm from 'htm';
17
+ import { t } from '/js/i18n.js';
18
+ import { timeAgo, copyToClipboard } from '/js/utils.js';
19
+ import { detectAgentState } from './state-detector.js';
20
+ import {
21
+ getOnboarding, startOnboarding,
22
+ getWebhookConfig, testWebhook, updateWebhook,
23
+ getSkillBundleVersion, getSkillBundleUrl, updateSkillBundle,
24
+ getDeliveryLog
25
+ } from '/js/services/agent-integration.js';
26
+
27
+ const html = htm.bind(h);
28
+
29
+ export default function TabIntegration({ agent, onboarding, session, showToast, agentName }) {
30
+ const state = detectAgentState(agent, onboarding);
31
+ const [webhook, setWebhook] = useState(null);
32
+ const [bundleVersion, setBundleVersion] = useState(null);
33
+ const [deliveries, setDeliveries] = useState([]);
34
+ const [loading, setLoading] = useState(true);
35
+ const [testing, setTesting] = useState(false);
36
+ const [rerunning, setRerunning] = useState(false);
37
+ const [copiedCmd, setCopiedCmd] = useState(false);
38
+ const [copiedInstall, setCopiedInstall] = useState(false);
39
+ const [showAllDeliveries, setShowAllDeliveries] = useState(false);
40
+ const [allDeliveries, setAllDeliveries] = useState(null);
41
+ const [editingWebhook, setEditingWebhook] = useState(false);
42
+ const [webhookDraft, setWebhookDraft] = useState('');
43
+ const [savingWebhook, setSavingWebhook] = useState(false);
44
+ const [updatingBundle, setUpdatingBundle] = useState(false);
45
+ const [copiedPrompt, setCopiedPrompt] = useState(false);
46
+
47
+ async function loadData() {
48
+ setLoading(true);
49
+ try {
50
+ const [whResp, sbResp, dlResp] = await Promise.all([
51
+ getWebhookConfig(agentName).catch(() => null),
52
+ getSkillBundleVersion(agentName).catch(() => null),
53
+ getDeliveryLog(agentName, 10).catch(() => null),
54
+ ]);
55
+ setWebhook(whResp?.data || null);
56
+ setBundleVersion(sbResp?.data || null);
57
+ setDeliveries(dlResp?.data?.deliveries || []);
58
+ } catch { /* silent */ }
59
+ setLoading(false);
60
+ }
61
+
62
+ useEffect(() => { loadData(); }, [agentName]);
63
+
64
+ const loadRef = useRef(loadData);
65
+ loadRef.current = loadData;
66
+ useEffect(() => {
67
+ const handler = () => loadRef.current();
68
+ window.addEventListener('aimeat-live-update', handler);
69
+ return () => window.removeEventListener('aimeat-live-update', handler);
70
+ }, []);
71
+
72
+ async function handleTestWebhook(e) {
73
+ e.stopPropagation();
74
+ setTesting(true);
75
+ try {
76
+ const resp = await testWebhook(agentName);
77
+ if (resp?.data?.success) {
78
+ showToast(t('profile.agents.webhook.testSuccess'));
79
+ } else {
80
+ showToast(t('profile.agents.webhook.testFailed'), true);
81
+ }
82
+ loadData();
83
+ } catch {
84
+ showToast(t('profile.agents.webhook.testFailed'), true);
85
+ }
86
+ setTesting(false);
87
+ }
88
+
89
+ async function handleRerun(e) {
90
+ e.stopPropagation();
91
+ setRerunning(true);
92
+ try {
93
+ await startOnboarding(agentName);
94
+ showToast(t('profile.agents.detail.integration.rerunStarted'));
95
+ loadData();
96
+ } catch (err) {
97
+ showToast(err.message || t('profile.agents.detail.integration.startError'), true);
98
+ }
99
+ setRerunning(false);
100
+ }
101
+
102
+ function handleCopyInstall(e) {
103
+ e.stopPropagation();
104
+ const url = getSkillBundleUrl(agentName);
105
+ copyToClipboard(`curl -o skill-bundle.zip ${location.origin}${url}`).then(() => {
106
+ setCopiedCmd(true);
107
+ setTimeout(() => setCopiedCmd(false), 2000);
108
+ });
109
+ }
110
+
111
+ function handleCopyInstallCommand(e) {
112
+ e.stopPropagation();
113
+ const platform = onboarding?.platformName || onboarding?.detectedPlatform || '';
114
+ const url = `${location.origin}${getSkillBundleUrl(agentName)}`;
115
+ let cmd;
116
+ if (platform.toLowerCase().includes('hermes') || platform.toLowerCase().includes('openclaw')) {
117
+ cmd = `hermes skills install ${url}`;
118
+ } else {
119
+ cmd = `curl -o skill-bundle.zip ${url} && unzip skill-bundle.zip`;
120
+ }
121
+ copyToClipboard(cmd).then(() => {
122
+ setCopiedInstall(true);
123
+ setTimeout(() => setCopiedInstall(false), 2000);
124
+ });
125
+ }
126
+
127
+ function handleCopyAgentPrompt(e) {
128
+ e.stopPropagation();
129
+ const url = `${location.origin}${getSkillBundleUrl(agentName)}`;
130
+ const prompt = `Download and install your skill bundle from AIMEAT.
131
+
132
+ Your skill bundle URL: ${url}
133
+
134
+ Steps:
135
+ 1. Authenticate with your agent token: POST ${location.origin}/v1/auth/token
136
+ Sign the challenge with your private key to get a JWT.
137
+
138
+ 2. Download the skill bundle ZIP:
139
+ GET ${url}
140
+ Header: Authorization: Bearer <your-jwt>
141
+ Save the response as a ZIP file.
142
+
143
+ 3. Extract the ZIP. It contains:
144
+ - SKILL.md -- your operating instructions, directives, and API reference
145
+ - Reference documents for task lifecycle, messaging, telemetry protocols
146
+ - Platform-specific scripts (if applicable)
147
+
148
+ 4. Read SKILL.md first -- it has your personalized directives, rules, and all the API endpoints you need.
149
+
150
+ If you already have a JWT token, you can do this in one step:
151
+ curl -H "Authorization: Bearer <jwt>" -o skill-bundle.zip "${url}" && unzip skill-bundle.zip && cat */SKILL.md`;
152
+ copyToClipboard(prompt).then(() => {
153
+ setCopiedPrompt(true);
154
+ setTimeout(() => setCopiedPrompt(false), 3000);
155
+ });
156
+ }
157
+
158
+ function handleEditWebhook(e) {
159
+ e.stopPropagation();
160
+ setWebhookDraft(webhook?.url || agent.webhook_url || '');
161
+ setEditingWebhook(true);
162
+ }
163
+
164
+ async function handleSaveWebhook(e) {
165
+ e.stopPropagation();
166
+ setSavingWebhook(true);
167
+ try {
168
+ await updateWebhook(agentName, { url: webhookDraft });
169
+ showToast(t('profile.agents.detail.integration.webhookUpdated'));
170
+ setEditingWebhook(false);
171
+ loadData();
172
+ } catch {
173
+ showToast(t('profile.agents.detail.integration.webhookUpdateError'), true);
174
+ }
175
+ setSavingWebhook(false);
176
+ }
177
+
178
+ function handleCancelWebhook(e) {
179
+ e.stopPropagation();
180
+ setEditingWebhook(false);
181
+ }
182
+
183
+ async function handleUpdateBundle(e) {
184
+ e.stopPropagation();
185
+ setUpdatingBundle(true);
186
+ try {
187
+ await updateSkillBundle(agentName);
188
+ showToast(t('profile.agents.detail.integration.update'));
189
+ loadData();
190
+ } catch { /* silent */ }
191
+ setUpdatingBundle(false);
192
+ }
193
+
194
+ if (loading) {
195
+ return html`<div class="pf-agd-empty">${t('profile.loading')}</div>`;
196
+ }
197
+
198
+ const isOnboarding = state === 'new' || state === 'onboarding';
199
+
200
+ if (isOnboarding) {
201
+ return renderOnboardingView(onboarding, agentName, handleRerun, rerunning, handleCopyInstall, copiedCmd, handleCopyInstallCommand, copiedInstall, handleCopyAgentPrompt, copiedPrompt);
202
+ }
203
+
204
+ async function handleShowAll() {
205
+ if (showAllDeliveries) { setShowAllDeliveries(false); return; }
206
+ try {
207
+ const resp = await getDeliveryLog(agentName, 200);
208
+ setAllDeliveries(resp?.data?.deliveries || []);
209
+ } catch { /* silent */ }
210
+ setShowAllDeliveries(true);
211
+ }
212
+
213
+ const displayDeliveries = showAllDeliveries && allDeliveries ? allDeliveries : deliveries;
214
+
215
+ return renderProductionView(agent, onboarding, webhook, bundleVersion, displayDeliveries, handleTestWebhook, testing, handleRerun, rerunning, handleCopyInstall, copiedCmd, handleShowAll, showAllDeliveries, editingWebhook, webhookDraft, setWebhookDraft, handleEditWebhook, handleSaveWebhook, handleCancelWebhook, savingWebhook, handleUpdateBundle, updatingBundle, handleCopyInstallCommand, copiedInstall, handleCopyAgentPrompt, copiedPrompt);
216
+ }
217
+
218
+ function renderOnboardingView(onboarding, agentName, handleRerun, rerunning, handleCopyInstall, copiedCmd, handleCopyInstallCommand, copiedInstall, handleCopyAgentPrompt, copiedPrompt) {
219
+ const steps = onboarding?.steps || [];
220
+ const passed = steps.filter(s => s.status === 'passed').length;
221
+ const total = steps.length || 11;
222
+ const pct = total > 0 ? Math.round((passed / total) * 100) : 0;
223
+
224
+ return html`
225
+ <div>
226
+ <div class="pf-agd-section">
227
+ <div class="pf-agd-section-label">
228
+ ${t('profile.agents.detail.integration.checklistTitle')}
229
+ ${' -- '}${t('profile.agents.detail.integration.readinessScore')}: ${pct > 0 ? `${pct} / 100` : '--'}
230
+ </div>
231
+ <div class="pf-agd-progress-bar">
232
+ <div class="pf-agd-progress-fill" style="width: ${pct}%"></div>
233
+ </div>
234
+ <div class="pf-agd-section-header pf-agd-progress-header">
235
+ <span>${t('profile.agents.detail.integration.progress')}: ${passed}/${total}</span>
236
+ <span>${pct}%</span>
237
+ </div>
238
+ </div>
239
+
240
+ <div class="pf-agd-checklist">
241
+ ${steps.map((step, i) => html`
242
+ <div key=${step.id || i} class="pf-agd-step pf-agd-step--${step.status}">
243
+ <span class="pf-agd-step-icon">
244
+ ${step.status === 'passed' ? '✓' : step.status === 'failed' ? '✗' : '○'}
245
+ </span>
246
+ <span class="pf-agd-step-name">${i + 1}. ${t('agentOnboarding.steps.' + step.id) || step.title || step.id}</span>
247
+ <span class="pf-agd-step-detail">
248
+ ${step.validatedAt ? timeAgo(step.validatedAt) : ''}
249
+ ${step.validationDetail ? ` -- ${step.validationDetail}` : ''}
250
+ </span>
251
+ </div>
252
+ `)}
253
+ </div>
254
+
255
+ <div class="pf-agd-section">
256
+ <div class="pf-agd-section-label">${t('profile.agents.skillBundle.title')}</div>
257
+ <div class="pf-agd-form-actions">
258
+ <button class="btn-primary btn-sm" onClick=${handleCopyAgentPrompt}>
259
+ ${copiedPrompt ? '✓ ' + t('profile.agents.detail.integration.promptCopied') : t('profile.agents.detail.integration.copyAgentPrompt')}
260
+ </button>
261
+ <button class="btn-outline btn-sm" onClick=${handleCopyInstallCommand}>
262
+ ${copiedInstall ? '✓ ' + t('profile.agents.detail.integration.installCommandCopied') : t('profile.agents.detail.integration.copyInstallCommand')}
263
+ </button>
264
+ <button class="btn-outline btn-sm" onClick=${handleCopyInstall}>
265
+ ${copiedCmd ? '✓ ' + t('profile.agents.copied') : t('profile.agents.skillBundle.copyCurl')}
266
+ </button>
267
+ <a class="btn-outline btn-sm" href=${getSkillBundleUrl(agentName)} download>
268
+ ${t('profile.agents.skillBundle.downloadZip')}
269
+ </a>
270
+ </div>
271
+ </div>
272
+
273
+ <div class="pf-agd-form-actions">
274
+ <button class="btn-primary btn-sm" onClick=${handleRerun} disabled=${rerunning}>
275
+ ${rerunning ? '...' : (passed > 0 ? t('profile.agents.detail.integration.rerun') : t('profile.agents.detail.integration.startOnboarding'))}
276
+ </button>
277
+ </div>
278
+ </div>
279
+ `;
280
+ }
281
+
282
+ function renderProductionView(agent, onboarding, webhook, bundleVersion, displayDeliveries, handleTestWebhook, testing, handleRerun, rerunning, handleCopyInstall, copiedCmd, handleShowAll, showAllDeliveries, editingWebhook, webhookDraft, setWebhookDraft, handleEditWebhook, handleSaveWebhook, handleCancelWebhook, savingWebhook, handleUpdateBundle, updatingBundle, handleCopyInstallCommand, copiedInstall, handleCopyAgentPrompt, copiedPrompt) {
283
+ const steps = onboarding?.steps || [];
284
+ const agentName = agent.name;
285
+
286
+ const passedSteps = steps.filter(s => s.status === 'passed');
287
+ const gapSteps = steps.filter(s => s.status !== 'passed');
288
+ const strengthNames = passedSteps.map(s => s.name || s.id).join(', ');
289
+ const gapNames = gapSteps.map(s => s.name || s.id).join(', ');
290
+
291
+ const lastValidatedTs = steps.reduce((latest, s) => {
292
+ if (!s.validatedAt) return latest;
293
+ const d = new Date(s.validatedAt).getTime();
294
+ return d > latest ? d : latest;
295
+ }, 0);
296
+
297
+ const platformVersion = onboarding?.platform?.version || onboarding?.platformVersion || null;
298
+ const detectionMethod = onboarding?.detectedPlatform
299
+ ? t('profile.agents.detail.integration.autoDetected')
300
+ : t('profile.agents.detail.integration.manual');
301
+
302
+ return html`
303
+ <div>
304
+ <!-- CONNECTION -->
305
+ <div class="pf-agd-section">
306
+ <div class="pf-agd-section-label">${t('profile.agents.detail.connection')}</div>
307
+ <div class="pf-agd-info-row">
308
+ <span class="pf-agd-info-label">${t('profile.agents.detail.integration.deliveryMethod')}</span>
309
+ <span class="pf-agd-info-value">
310
+ <span class="pf-agd-status-dot ${webhook && (webhook.failCount ?? 0) < 5 ? 'pf-agd-status-dot--active' : webhook && (webhook.failCount ?? 0) >= 5 ? 'pf-agd-status-dot--error' : 'pf-agd-status-dot--inactive'}"></span>
311
+ ${webhook ? t('profile.agents.detail.deliveryWebhook') : t('profile.agents.detail.deliveryPolling')}
312
+ </span>
313
+ </div>
314
+ ${webhook ? html`
315
+ <div class="pf-agd-info-row">
316
+ <span class="pf-agd-info-label">${t('profile.agents.webhook.url')}</span>
317
+ <span class="pf-agd-info-value">${webhook.url || '--'}</span>
318
+ </div>
319
+ <div class="pf-agd-info-row">
320
+ <span class="pf-agd-info-label">${t('profile.agents.webhook.failCount')}</span>
321
+ <span class="pf-agd-info-value">${webhook.failCount ?? 0}</span>
322
+ </div>
323
+ <div class="pf-agd-info-row">
324
+ <span class="pf-agd-info-label">${t('profile.agents.webhook.lastSuccess')}</span>
325
+ <span class="pf-agd-info-value">${webhook.lastSuccessAt ? timeAgo(webhook.lastSuccessAt) : '--'}</span>
326
+ </div>
327
+ ${editingWebhook ? html`
328
+ <div class="pf-agd-webhook-form">
329
+ <input
330
+ type="url"
331
+ value=${webhookDraft}
332
+ onInput=${e => setWebhookDraft(e.target.value)}
333
+ placeholder="https://..."
334
+ />
335
+ <button class="btn-primary btn-sm" onClick=${handleSaveWebhook} disabled=${savingWebhook}>
336
+ ${savingWebhook ? '...' : t('common.save')}
337
+ </button>
338
+ <button class="btn-outline btn-sm" onClick=${handleCancelWebhook}>
339
+ ${t('common.cancel')}
340
+ </button>
341
+ </div>
342
+ ` : html`
343
+ <div class="pf-agd-form-actions">
344
+ <button class="btn-outline btn-sm" onClick=${handleTestWebhook} disabled=${testing}>
345
+ ${testing ? '...' : t('profile.agents.webhook.test')}
346
+ </button>
347
+ <button class="btn-outline btn-sm" onClick=${handleEditWebhook}>
348
+ ${t('profile.agents.detail.integration.editWebhook')}
349
+ </button>
350
+ </div>
351
+ `}
352
+ ` : html`
353
+ <div class="pf-agd-info-row">
354
+ <span class="pf-agd-info-label">${t('profile.agents.detail.integration.pollingInterval')}</span>
355
+ <span class="pf-agd-info-value">${agent.pollingInterval || agent.polling_interval || '60s'}</span>
356
+ </div>
357
+ `}
358
+ <div class="pf-agd-info-row">
359
+ <span class="pf-agd-info-label">${t('profile.agents.detail.lastSeen')}</span>
360
+ <span class="pf-agd-info-value">${agent.last_seen ? timeAgo(agent.last_seen) : '--'}</span>
361
+ </div>
362
+ </div>
363
+
364
+ <!-- PLATFORM & SKILL -->
365
+ <div class="pf-agd-section">
366
+ <div class="pf-agd-section-label">${t('profile.agents.detail.platform')} & ${t('profile.agents.detail.skillBundle')}</div>
367
+ <div class="pf-agd-info-row">
368
+ <span class="pf-agd-info-label">${t('profile.agents.detail.platform')}</span>
369
+ <span class="pf-agd-info-value">${onboarding?.platformName || onboarding?.detectedPlatform || '--'}</span>
370
+ </div>
371
+ <div class="pf-agd-info-row">
372
+ <span class="pf-agd-info-label">${t('profile.agents.detail.integration.platformVersion')}</span>
373
+ <span class="pf-agd-info-value">${platformVersion || '--'}</span>
374
+ </div>
375
+ <div class="pf-agd-info-row">
376
+ <span class="pf-agd-info-label">${t('profile.agents.detail.integration.detectionMethod')}</span>
377
+ <span class="pf-agd-info-value">${detectionMethod}</span>
378
+ </div>
379
+ ${bundleVersion ? html`
380
+ <div class="pf-agd-info-row">
381
+ <span class="pf-agd-info-label">${t('profile.agents.skillBundle.versionLabel')}</span>
382
+ <span class="pf-agd-info-value">${bundleVersion.version || '--'}</span>
383
+ </div>
384
+ ` : ''}
385
+ <div class="pf-agd-form-actions">
386
+ <button class="btn-primary btn-sm" onClick=${handleCopyAgentPrompt}>
387
+ ${copiedPrompt ? '✓ ' + t('profile.agents.detail.integration.promptCopied') : t('profile.agents.detail.integration.copyAgentPrompt')}
388
+ </button>
389
+ <button class="btn-outline btn-sm" onClick=${handleCopyInstall}>
390
+ ${copiedCmd ? '✓ ' + t('profile.agents.copied') : t('profile.agents.skillBundle.reinstall')}
391
+ </button>
392
+ <button class="btn-outline btn-sm" onClick=${handleUpdateBundle} disabled=${updatingBundle}>
393
+ ${updatingBundle ? '...' : t('profile.agents.detail.integration.update')}
394
+ </button>
395
+ </div>
396
+ </div>
397
+
398
+ <!-- READINESS -->
399
+ <div class="pf-agd-section">
400
+ <div class="pf-agd-section-label">${t('profile.agents.detail.readiness')}</div>
401
+ <div class="pf-agd-step-pills">
402
+ ${steps.map(s => html`
403
+ <span key=${s.id} class="pf-agd-step-pill pf-agd-step-pill--${s.status}">
404
+ ${s.status === 'passed' ? '✓' : s.status === 'failed' ? '✗' : s.status === 'warn' ? '⚠' : '○'} ${s.name?.split(' ').slice(0, 2).join(' ') || s.id}
405
+ </span>
406
+ `)}
407
+ </div>
408
+ ${onboarding?.readinessScore != null && html`
409
+ <div class="pf-agd-info-row">
410
+ <span class="pf-agd-info-label">${t('profile.agents.detail.readiness')}</span>
411
+ <span class="pf-agd-info-value">${onboarding.readinessLevel} (${onboarding.readinessScore})</span>
412
+ </div>
413
+ `}
414
+ <div class="pf-agd-strengths-gaps">
415
+ <div>
416
+ <span class="pf-agd-strengths-gaps-label">${t('profile.agents.detail.integration.strengths')}: </span>
417
+ <span class="pf-agd-strengths-gaps-value">${strengthNames || t('profile.agents.detail.integration.noStrengths')}</span>
418
+ </div>
419
+ <div>
420
+ <span class="pf-agd-strengths-gaps-label">${t('profile.agents.detail.integration.gaps')}: </span>
421
+ <span class="pf-agd-strengths-gaps-value">${gapNames || t('profile.agents.detail.integration.noGaps')}</span>
422
+ </div>
423
+ </div>
424
+ ${lastValidatedTs > 0 && html`
425
+ <div class="pf-agd-info-row">
426
+ <span class="pf-agd-info-label">${t('profile.agents.detail.integration.lastValidated')}</span>
427
+ <span class="pf-agd-info-value">${timeAgo(lastValidatedTs)}</span>
428
+ </div>
429
+ `}
430
+ <div class="pf-agd-form-actions">
431
+ <button class="btn-outline btn-sm" onClick=${handleRerun} disabled=${rerunning}>
432
+ ${rerunning ? '...' : t('profile.agents.detail.integration.rerun')}
433
+ </button>
434
+ </div>
435
+ </div>
436
+
437
+ <!-- IDENTITY -->
438
+ <div class="pf-agd-section">
439
+ <div class="pf-agd-section-label">${t('profile.agents.detail.identity')}</div>
440
+ <div class="pf-agd-info-row">
441
+ <span class="pf-agd-info-label">GAII</span>
442
+ <span class="pf-agd-info-value">${agent.gaii || '--'}</span>
443
+ </div>
444
+ ${agent.public_key && html`
445
+ <div class="pf-agd-info-row">
446
+ <span class="pf-agd-info-label">${t('profile.agents.publicKey')}</span>
447
+ <span class="pf-agd-info-value">${truncateKey(agent.public_key)}</span>
448
+ </div>
449
+ `}
450
+ <div class="pf-agd-info-row">
451
+ <span class="pf-agd-info-label">${t('profile.agents.created')}</span>
452
+ <span class="pf-agd-info-value">${agent.created_at ? new Date(agent.created_at).toLocaleDateString() : '--'}</span>
453
+ </div>
454
+ ${agent.roles && agent.roles.length > 0 && html`
455
+ <div class="pf-agd-info-row">
456
+ <span class="pf-agd-info-label">${t('profile.agents.detail.integration.roles')}</span>
457
+ <span class="pf-agd-info-value">
458
+ ${agent.roles.map(r => html`<span key=${r} class="pf-agd-role-badge">${r}</span> `)}
459
+ </span>
460
+ </div>
461
+ `}
462
+ </div>
463
+
464
+ <!-- DELIVERY LOG -->
465
+ <div class="pf-agd-section">
466
+ <div class="pf-agd-section-label">${t('profile.agents.detail.deliveryLog')}</div>
467
+ ${displayDeliveries.length > 0 ? html`
468
+ <table class="pf-agd-delivery-log">
469
+ <thead>
470
+ <tr>
471
+ <th>${t('profile.agents.detail.integration.time')}</th>
472
+ <th>${t('profile.agents.detail.integration.event')}</th>
473
+ <th>${t('profile.agents.detail.integration.channel')}</th>
474
+ <th>${t('profile.agents.detail.integration.result')}</th>
475
+ <th>${t('profile.agents.detail.integration.latency')}</th>
476
+ </tr>
477
+ </thead>
478
+ <tbody>
479
+ ${displayDeliveries.map((d, i) => html`
480
+ <tr key=${d.id || i}>
481
+ <td>${d.timestamp ? timeAgo(d.timestamp) : '--'}</td>
482
+ <td>${d.eventType || d.event || '--'}</td>
483
+ <td>${d.channel || '--'}</td>
484
+ <td>${d.success ? '✓' : '✗'}</td>
485
+ <td>${d.latencyMs ? `${(d.latencyMs / 1000).toFixed(1)}s` : '--'}</td>
486
+ </tr>
487
+ `)}
488
+ </tbody>
489
+ </table>
490
+ <button class="btn-ghost btn-sm pf-agd-delivery-toggle" onClick=${handleShowAll}>
491
+ ${showAllDeliveries ? t('profile.agents.detail.showLess') : t('profile.agents.detail.showAll')}
492
+ </button>
493
+ ` : html`
494
+ <div class="pf-agd-empty-hint">${t('profile.agents.detail.integration.noDeliveries')}</div>
495
+ `}
496
+ </div>
497
+ </div>
498
+ `;
499
+ }
500
+
501
+ function truncateKey(key) {
502
+ if (!key) return '--';
503
+ if (key.length <= 20) return key;
504
+ return key.slice(0, 10) + '...' + key.slice(-10);
505
+ }