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,403 @@
1
+ /**
2
+ * @file agents-task-builder.js
3
+ * @description Split-panel task creation builder with Living Proposal (3 tabs)
4
+ * and chat panel. Implements the design spec's conversational task creation flow:
5
+ * user describes what they want -> agent proposes plan -> user reviews and starts.
6
+ * @structure
7
+ * - TaskCreationBuilder (default export) -- main split-panel component
8
+ * - ProposalPanel -- left panel with Requirements/TODO/Technical tabs
9
+ * - BuilderChat -- right panel with task-scoped messaging
10
+ * @version-history
11
+ * v1.0.0 -- 2026-05-22 -- Initial creation per design spec Part 1
12
+ */
13
+ import { h } from 'preact';
14
+ import { useState, useEffect, useRef } from 'preact/hooks';
15
+ import htm from 'htm';
16
+ const html = htm.bind(h);
17
+ import { t } from '/js/i18n.js';
18
+ import { timeAgo } from '/js/utils.js';
19
+ import { createTask, getTask, startTask } from '/js/services/agent-tasks.js';
20
+ import { sendMessage, listMessages } from '/js/services/agent-messages.js';
21
+
22
+ const PROPOSAL_TABS = ['requirements', 'todo', 'technical'];
23
+
24
+ function ProposalPanel({ task, taskId }) {
25
+ const [activeTab, setActiveTab] = useState('requirements');
26
+
27
+ const tabBar = html`
28
+ <div class="agd-proposal-tabs">
29
+ ${PROPOSAL_TABS.map(tab => html`
30
+ <button key=${tab}
31
+ class="agd-proposal-tab ${activeTab === tab ? 'agd-proposal-tab-active' : ''}"
32
+ onClick=${() => setActiveTab(tab)}>
33
+ ${t(`profile.agents.tasks.builder.tab${tab.charAt(0).toUpperCase() + tab.slice(1)}`)}
34
+ </button>
35
+ `)}
36
+ </div>
37
+ `;
38
+
39
+ if (!taskId) {
40
+ return html`<div class="agd-proposal">
41
+ ${tabBar}
42
+ <div class="agd-proposal-content">
43
+ <div class="agd-builder-analyzing">${t('profile.agents.tasks.builder.initial')}</div>
44
+ </div>
45
+ </div>`;
46
+ }
47
+
48
+ if (!task) {
49
+ return html`<div class="agd-proposal">
50
+ ${tabBar}
51
+ <div class="agd-proposal-content">
52
+ <div class="agd-builder-analyzing">${t('profile.agents.tasks.builder.analyzing')}</div>
53
+ </div>
54
+ </div>`;
55
+ }
56
+
57
+ const hasTodos = task.todos && task.todos.length > 0;
58
+ const hasScope = task.scope && task.scope.length > 0;
59
+ const hasRules = task.rules && task.rules.length > 0;
60
+ const hasVerification = task.verification?.userExpects || (task.verification?.technicalChecks?.length > 0);
61
+ const hasResources = task.resources && (
62
+ task.resources.knowledgePackages?.length > 0 ||
63
+ task.resources.memoryKeys?.length > 0 ||
64
+ task.resources.memoryPrefixes?.length > 0
65
+ );
66
+ const hasProposal = hasTodos || hasScope || hasRules || hasVerification;
67
+
68
+ const noData = html`<div class="agd-prop-empty">${t('profile.agents.tasks.builder.noDataYet')}</div>`;
69
+
70
+ return html`
71
+ <div class="agd-proposal">
72
+ <div class="agd-proposal-tabs">
73
+ ${PROPOSAL_TABS.map(tab => html`
74
+ <button key=${tab}
75
+ class="agd-proposal-tab ${activeTab === tab ? 'agd-proposal-tab-active' : ''}"
76
+ onClick=${() => setActiveTab(tab)}>
77
+ ${t(`profile.agents.tasks.builder.tab${tab.charAt(0).toUpperCase() + tab.slice(1)}`)}
78
+ </button>
79
+ `)}
80
+ </div>
81
+
82
+ <div class="agd-proposal-content">
83
+ ${activeTab === 'requirements' && html`
84
+ <div class="agd-prop-section">
85
+ <div class="agd-prop-label">${t('profile.agents.tasks.builder.whatItDoes')}</div>
86
+ <div class="agd-prop-value">${task.description || task.title}</div>
87
+ </div>
88
+
89
+ ${hasScope ? html`
90
+ <div class="agd-prop-section">
91
+ <div class="agd-prop-label">${t('profile.agents.tasks.builder.scope')}</div>
92
+ ${task.scope.map(s => html`
93
+ <div class="agd-scope-item" key=${s.name}>
94
+ <span class="agd-scope-name">${s.description || s.name}</span>
95
+ <span class="agd-prop-code">${s.value}</span>
96
+ <span class="agd-scope-type">${s.type}</span>
97
+ </div>
98
+ `)}
99
+ </div>
100
+ ` : ''}
101
+
102
+ ${hasRules ? html`
103
+ <div class="agd-prop-section">
104
+ <div class="agd-prop-label">${t('profile.agents.tasks.builder.rules')}</div>
105
+ <ul class="agd-prop-list">
106
+ ${task.rules.map((r, i) => html`<li key=${i}>${r}</li>`)}
107
+ </ul>
108
+ </div>
109
+ ` : ''}
110
+
111
+ ${hasVerification ? html`
112
+ <div class="agd-prop-section">
113
+ <div class="agd-prop-label">${t('profile.agents.tasks.builder.verification')}</div>
114
+ ${task.verification.userExpects && html`
115
+ <div class="agd-prop-check">${task.verification.userExpects}</div>
116
+ `}
117
+ ${task.verification.technicalChecks?.map((c, i) => html`
118
+ <div class="agd-prop-check" key=${i}><span class="agd-prop-code">${c}</span></div>
119
+ `)}
120
+ </div>
121
+ ` : ''}
122
+
123
+ ${!hasProposal ? html`
124
+ <div class="agd-builder-analyzing">${t('profile.agents.tasks.builder.waitingTodos')}</div>
125
+ ` : ''}
126
+ `}
127
+
128
+ ${activeTab === 'todo' && html`
129
+ ${hasTodos ? html`
130
+ <div>
131
+ <div class="agd-todo-header">
132
+ <strong>${t('profile.agents.tasks.todoLabel')}</strong>
133
+ <span class="agd-todo-summary">
134
+ ${(() => {
135
+ const aimeatSteps = task.todos.filter(td => td.environment === 'aimeat').length;
136
+ const agentSteps = task.todos.filter(td => td.environment === 'agent').length;
137
+ const totalMinutes = task.todos.reduce((sum, td) => sum + (td.estimateMinutes || 0), 0);
138
+ return html`
139
+ ${aimeatSteps > 0 && html`<span class="agd-env-badge agd-env-aimeat">${t('profile.agents.tasks.envAimeat')}: ${aimeatSteps}</span>`}
140
+ ${agentSteps > 0 && html`<span class="agd-env-badge agd-env-agent">${t('profile.agents.tasks.envAgent')}: ${agentSteps}</span>`}
141
+ ${totalMinutes > 0 && html`<span class="agd-todo-time">~${totalMinutes} ${t('profile.agents.tasks.minuteShort')}</span>`}
142
+ `;
143
+ })()}
144
+ </span>
145
+ </div>
146
+ <div class="agd-todo-list">
147
+ ${task.todos.map((td, i) => html`
148
+ <div class="agd-todo-item agd-todo-${td.status || 'pending'}" key=${td.id || i}>
149
+ <span class="agd-todo-icon">${td.status === 'done' ? '✅' : '⬜'}</span>
150
+ <div class="agd-todo-content">
151
+ <div class="agd-todo-title">
152
+ <span>${i + 1}. ${td.title}</span>
153
+ <span class="agd-env-badge agd-env-${td.environment || 'agent'}">${td.environment === 'aimeat' ? t('profile.agents.tasks.envAimeat') : t('profile.agents.tasks.envAgent')}</span>
154
+ ${td.estimateMinutes && html`<span class="agd-todo-est">${td.estimateMinutes} ${t('profile.agents.tasks.minuteShort')}</span>`}
155
+ </div>
156
+ ${td.description && html`<div class="agd-todo-desc">${td.description}</div>`}
157
+ ${td.environmentReason && html`<div class="agd-todo-reason">${td.environmentReason}</div>`}
158
+ ${td.verification && html`<div class="agd-todo-verify">${td.verification}</div>`}
159
+ </div>
160
+ </div>
161
+ `)}
162
+ </div>
163
+ </div>
164
+ ` : html`
165
+ <div class="agd-builder-analyzing">${t('profile.agents.tasks.builder.waitingTodos')}</div>
166
+ `}
167
+ `}
168
+
169
+ ${activeTab === 'technical' && html`
170
+ ${hasScope && task.scope.filter(s => s.type === 'cron').length > 0 ? html`
171
+ <div class="agd-prop-section">
172
+ <div class="agd-prop-label">${t('profile.agents.tasks.builder.cronSchedules')}</div>
173
+ ${task.scope.filter(s => s.type === 'cron').map(s => html`
174
+ <div key=${s.name}><span class="agd-prop-code">${s.value}</span> -- ${s.name}</div>
175
+ `)}
176
+ </div>
177
+ ` : ''}
178
+
179
+ ${task.verification?.technicalChecks?.length > 0 ? html`
180
+ <div class="agd-prop-section">
181
+ <div class="agd-prop-label">${t('profile.agents.tasks.builder.technicalChecks')}</div>
182
+ ${task.verification.technicalChecks.map((c, i) => html`
183
+ <div key=${i} class="agd-prop-code" style="margin-bottom:0.25rem">${c}</div>
184
+ `)}
185
+ </div>
186
+ ` : ''}
187
+
188
+ ${hasResources ? html`
189
+ <div class="agd-prop-section">
190
+ <div class="agd-prop-label">${t('profile.agents.tasks.builder.resources')}</div>
191
+ ${task.resources.memoryKeys?.map(k => html`
192
+ <div key=${k}><span class="agd-prop-code">${k}</span></div>
193
+ `)}
194
+ ${task.resources.memoryPrefixes?.map(p => html`
195
+ <div key=${p}><span class="agd-prop-code">${p}*</span></div>
196
+ `)}
197
+ ${task.resources.knowledgePackages?.map(p => html`
198
+ <div key=${p}>${p}</div>
199
+ `)}
200
+ </div>
201
+ ` : ''}
202
+
203
+ ${!hasScope && !hasResources && !(task.verification?.technicalChecks?.length > 0) ? noData : ''}
204
+ `}
205
+ </div>
206
+ </div>
207
+ `;
208
+ }
209
+
210
+ function BuilderChat({ agentName, taskId, threadId, onTaskCreated, showToast }) {
211
+ const [messages, setMessages] = useState([]);
212
+ const [draft, setDraft] = useState('');
213
+ const [sending, setSending] = useState(false);
214
+ const historyRef = useRef(null);
215
+
216
+ async function loadMessages() {
217
+ if (!threadId) return;
218
+ try {
219
+ const res = await listMessages(agentName, { threadId });
220
+ setMessages(res?.data?.messages || []);
221
+ } catch {
222
+ setMessages([]);
223
+ }
224
+ }
225
+
226
+ useEffect(() => { loadMessages(); }, [threadId]);
227
+
228
+ useEffect(() => {
229
+ if (!threadId) return;
230
+ const handler = () => loadMessages();
231
+ window.addEventListener('aimeat-live-update', handler);
232
+ return () => window.removeEventListener('aimeat-live-update', handler);
233
+ }, [threadId]);
234
+
235
+ useEffect(() => {
236
+ if (historyRef.current) {
237
+ historyRef.current.scrollTop = historyRef.current.scrollHeight;
238
+ }
239
+ }, [messages]);
240
+
241
+ async function handleSend() {
242
+ const text = draft.trim();
243
+ if (!text) return;
244
+ setSending(true);
245
+ try {
246
+ if (!taskId) {
247
+ await onTaskCreated(text);
248
+ } else {
249
+ await sendMessage(agentName, text, threadId, taskId);
250
+ }
251
+ setDraft('');
252
+ await loadMessages();
253
+ } catch (err) {
254
+ showToast(err.message || t('profile.agents.messages.sendError'), true);
255
+ }
256
+ setSending(false);
257
+ }
258
+
259
+ function handleKeyDown(e) {
260
+ if (e.key === 'Enter' && !e.shiftKey) {
261
+ e.preventDefault();
262
+ handleSend();
263
+ }
264
+ }
265
+
266
+ const sorted = [...messages].sort((a, b) => new Date(a.createdAt || 0) - new Date(b.createdAt || 0));
267
+ const placeholder = taskId
268
+ ? t('profile.agents.tasks.builder.chatPlaceholder')
269
+ : t('profile.agents.tasks.builder.placeholder');
270
+
271
+ return html`
272
+ <div class="agd-builder-chat">
273
+ <div class="agd-builder-chat-history" ref=${historyRef}>
274
+ ${sorted.map(msg => {
275
+ const isInbound = msg.direction === 'inbound';
276
+ return html`
277
+ <div key=${msg.id}>
278
+ <div class="agd-msg-bubble ${isInbound ? 'agd-msg-inbound' : 'agd-msg-outbound'}">
279
+ ${msg.content}
280
+ </div>
281
+ <div class="agd-msg-meta ${isInbound ? 'agd-msg-meta-right' : ''}">
282
+ ${msg.createdAt ? html`
283
+ <span class="agd-msg-time">${new Date(msg.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</span>
284
+ ${' '}${timeAgo(msg.createdAt)}
285
+ ` : ''}
286
+ </div>
287
+ </div>
288
+ `;
289
+ })}
290
+ ${taskId && messages.length === 0 && html`
291
+ <div class="agd-builder-analyzing">${t('profile.agents.tasks.builder.analyzing')}</div>
292
+ `}
293
+ </div>
294
+ <div class="agd-builder-chat-input">
295
+ <textarea
296
+ value=${draft}
297
+ onInput=${(e) => setDraft(e.target.value)}
298
+ onKeyDown=${handleKeyDown}
299
+ placeholder=${placeholder}
300
+ rows="1"
301
+ />
302
+ <button class="btn-primary btn-sm" onClick=${handleSend} disabled=${sending || !draft.trim()}>
303
+ ${taskId ? t('profile.agents.messages.send') : t('profile.agents.tasks.builder.send')}
304
+ </button>
305
+ </div>
306
+ </div>
307
+ `;
308
+ }
309
+
310
+ export default function TaskCreationBuilder({ agentName, session, showToast, onClose }) {
311
+ const [taskId, setTaskId] = useState(null);
312
+ const [threadId, setThreadId] = useState(null);
313
+ const [task, setTask] = useState(null);
314
+ const [starting, setStarting] = useState(false);
315
+ const [version, setVersion] = useState(0);
316
+
317
+ async function loadTask() {
318
+ if (!taskId) return;
319
+ try {
320
+ const resp = await getTask(agentName, taskId);
321
+ const newTask = resp?.data?.task;
322
+ if (newTask) {
323
+ if (task && JSON.stringify(newTask.todos) !== JSON.stringify(task.todos)) {
324
+ setVersion(v => v + 1);
325
+ }
326
+ setTask(newTask);
327
+ }
328
+ } catch { /* task may not exist yet */ }
329
+ }
330
+
331
+ useEffect(() => { loadTask(); }, [taskId]);
332
+
333
+ const loadRef = useRef(loadTask);
334
+ loadRef.current = loadTask;
335
+ useEffect(() => {
336
+ if (!taskId) return;
337
+ const handler = () => loadRef.current();
338
+ window.addEventListener('aimeat-live-update', handler);
339
+ return () => window.removeEventListener('aimeat-live-update', handler);
340
+ }, [taskId]);
341
+
342
+ async function handleFirstMessage(text) {
343
+ const newThreadId = crypto.randomUUID();
344
+ try {
345
+ const resp = await createTask(agentName, { title: text, status: 'queued' });
346
+ const newTaskId = resp?.data?.task?.id;
347
+ if (!newTaskId) throw new Error('No task ID returned');
348
+ setTaskId(newTaskId);
349
+ setThreadId(newThreadId);
350
+ await sendMessage(agentName, text, newThreadId, newTaskId);
351
+ } catch (err) {
352
+ showToast(err.message || t('profile.agents.tasks.createError'), true);
353
+ }
354
+ }
355
+
356
+ async function handleStart() {
357
+ setStarting(true);
358
+ try {
359
+ await startTask(agentName, taskId);
360
+ showToast(t('profile.agents.tasks.builder.startTask'));
361
+ onClose();
362
+ } catch (err) {
363
+ showToast(err.message || t('profile.agents.tasks.startError'), true);
364
+ }
365
+ setStarting(false);
366
+ }
367
+
368
+ const hasTodos = task?.todos?.length > 0;
369
+ const canStart = hasTodos && (task?.status === 'queued' || task?.status === 'draft');
370
+
371
+ return html`
372
+ <div class="agd-builder">
373
+ <div class="agd-builder-header">
374
+ <h4>${t('profile.agents.tasks.builder.title')}</h4>
375
+ ${version > 0 && html`<span class="agd-version-badge">${t('profile.agents.tasks.builder.version').replace('{n}', String(version))}</span>`}
376
+ </div>
377
+
378
+ <div class="agd-builder-panels">
379
+ <${ProposalPanel} task=${task} taskId=${taskId} />
380
+ <${BuilderChat}
381
+ agentName=${agentName}
382
+ taskId=${taskId}
383
+ threadId=${threadId}
384
+ onTaskCreated=${handleFirstMessage}
385
+ showToast=${showToast}
386
+ />
387
+ </div>
388
+
389
+ <div class="agd-builder-actions">
390
+ <div>
391
+ ${canStart && html`
392
+ <button class="btn-primary btn-sm" onClick=${handleStart} disabled=${starting}>
393
+ ${starting ? '...' : t('profile.agents.tasks.builder.startTask')}
394
+ </button>
395
+ `}
396
+ </div>
397
+ <div class="agd-builder-actions-right">
398
+ <button class="btn-outline btn-sm" onClick=${onClose}>${t('profile.agents.tasks.builder.cancel')}</button>
399
+ </div>
400
+ </div>
401
+ </div>
402
+ `;
403
+ }