@pellux/goodvibes-sdk 0.25.10 → 0.25.12

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 (220) hide show
  1. package/dist/_internal/contracts/artifacts/operator-contract.json +178 -6
  2. package/dist/_internal/contracts/generated/foundation-client-types.d.ts +16 -1
  3. package/dist/_internal/contracts/generated/foundation-client-types.d.ts.map +1 -1
  4. package/dist/_internal/contracts/generated/foundation-metadata.d.ts +2 -2
  5. package/dist/_internal/contracts/generated/foundation-metadata.js +2 -2
  6. package/dist/_internal/contracts/generated/operator-contract.d.ts.map +1 -1
  7. package/dist/_internal/contracts/generated/operator-contract.js +178 -6
  8. package/dist/_internal/contracts/generated/operator-method-ids.d.ts +1 -1
  9. package/dist/_internal/contracts/generated/operator-method-ids.d.ts.map +1 -1
  10. package/dist/_internal/contracts/generated/operator-method-ids.js +1 -0
  11. package/dist/_internal/daemon/context.d.ts +1 -0
  12. package/dist/_internal/daemon/context.d.ts.map +1 -1
  13. package/dist/_internal/daemon/integration-route-types.d.ts +1 -0
  14. package/dist/_internal/daemon/integration-route-types.d.ts.map +1 -1
  15. package/dist/_internal/daemon/integration-routes.d.ts +1 -1
  16. package/dist/_internal/daemon/integration-routes.d.ts.map +1 -1
  17. package/dist/_internal/daemon/integration-routes.js +3 -0
  18. package/dist/_internal/daemon/operator.d.ts +1 -1
  19. package/dist/_internal/daemon/operator.d.ts.map +1 -1
  20. package/dist/_internal/daemon/operator.js +2 -0
  21. package/dist/_internal/daemon/runtime-route-types.d.ts +1 -1
  22. package/dist/_internal/daemon/runtime-route-types.d.ts.map +1 -1
  23. package/dist/_internal/platform/adapters/discord/index.d.ts.map +1 -1
  24. package/dist/_internal/platform/adapters/discord/index.js +4 -5
  25. package/dist/_internal/platform/adapters/github/index.d.ts.map +1 -1
  26. package/dist/_internal/platform/adapters/github/index.js +4 -5
  27. package/dist/_internal/platform/adapters/google-chat/index.d.ts.map +1 -1
  28. package/dist/_internal/platform/adapters/google-chat/index.js +7 -5
  29. package/dist/_internal/platform/adapters/helpers.d.ts +2 -1
  30. package/dist/_internal/platform/adapters/helpers.d.ts.map +1 -1
  31. package/dist/_internal/platform/adapters/helpers.js +3 -34
  32. package/dist/_internal/platform/adapters/homeassistant/index.d.ts +3 -0
  33. package/dist/_internal/platform/adapters/homeassistant/index.d.ts.map +1 -0
  34. package/dist/_internal/platform/adapters/homeassistant/index.js +185 -0
  35. package/dist/_internal/platform/adapters/index.d.ts +1 -0
  36. package/dist/_internal/platform/adapters/index.d.ts.map +1 -1
  37. package/dist/_internal/platform/adapters/index.js +1 -0
  38. package/dist/_internal/platform/adapters/mattermost/index.d.ts.map +1 -1
  39. package/dist/_internal/platform/adapters/mattermost/index.js +6 -2
  40. package/dist/_internal/platform/adapters/slack/index.d.ts.map +1 -1
  41. package/dist/_internal/platform/adapters/slack/index.js +4 -5
  42. package/dist/_internal/platform/adapters/telegram/index.d.ts.map +1 -1
  43. package/dist/_internal/platform/adapters/telegram/index.js +7 -5
  44. package/dist/_internal/platform/adapters/types.d.ts +1 -1
  45. package/dist/_internal/platform/adapters/types.d.ts.map +1 -1
  46. package/dist/_internal/platform/adapters/webhook/index.d.ts.map +1 -1
  47. package/dist/_internal/platform/adapters/webhook/index.js +4 -1
  48. package/dist/_internal/platform/automation/types.d.ts +1 -1
  49. package/dist/_internal/platform/automation/types.d.ts.map +1 -1
  50. package/dist/_internal/platform/channels/builtin/accounts.d.ts.map +1 -1
  51. package/dist/_internal/platform/channels/builtin/accounts.js +23 -0
  52. package/dist/_internal/platform/channels/builtin/contracts.d.ts.map +1 -1
  53. package/dist/_internal/platform/channels/builtin/contracts.js +9 -0
  54. package/dist/_internal/platform/channels/builtin/descriptors.d.ts.map +1 -1
  55. package/dist/_internal/platform/channels/builtin/descriptors.js +9 -2
  56. package/dist/_internal/platform/channels/builtin/homeassistant.d.ts +64 -0
  57. package/dist/_internal/platform/channels/builtin/homeassistant.d.ts.map +1 -0
  58. package/dist/_internal/platform/channels/builtin/homeassistant.js +391 -0
  59. package/dist/_internal/platform/channels/builtin/plugins.d.ts.map +1 -1
  60. package/dist/_internal/platform/channels/builtin/plugins.js +2 -1
  61. package/dist/_internal/platform/channels/builtin/presentation.d.ts.map +1 -1
  62. package/dist/_internal/platform/channels/builtin/presentation.js +4 -0
  63. package/dist/_internal/platform/channels/builtin/rendering.d.ts.map +1 -1
  64. package/dist/_internal/platform/channels/builtin/rendering.js +7 -0
  65. package/dist/_internal/platform/channels/builtin/setup-schema.d.ts.map +1 -1
  66. package/dist/_internal/platform/channels/builtin/setup-schema.js +53 -0
  67. package/dist/_internal/platform/channels/builtin/shared.d.ts +1 -1
  68. package/dist/_internal/platform/channels/builtin/shared.d.ts.map +1 -1
  69. package/dist/_internal/platform/channels/builtin/shared.js +2 -0
  70. package/dist/_internal/platform/channels/builtin/surfaces.d.ts.map +1 -1
  71. package/dist/_internal/platform/channels/builtin/surfaces.js +1 -0
  72. package/dist/_internal/platform/channels/builtin/targets.d.ts.map +1 -1
  73. package/dist/_internal/platform/channels/builtin/targets.js +24 -0
  74. package/dist/_internal/platform/channels/builtin-runtime.d.ts.map +1 -1
  75. package/dist/_internal/platform/channels/builtin-runtime.js +6 -0
  76. package/dist/_internal/platform/channels/delivery/strategies-core.d.ts +1 -0
  77. package/dist/_internal/platform/channels/delivery/strategies-core.d.ts.map +1 -1
  78. package/dist/_internal/platform/channels/delivery/strategies-core.js +60 -1
  79. package/dist/_internal/platform/channels/delivery/types.d.ts +2 -0
  80. package/dist/_internal/platform/channels/delivery/types.d.ts.map +1 -1
  81. package/dist/_internal/platform/channels/delivery-router.d.ts.map +1 -1
  82. package/dist/_internal/platform/channels/delivery-router.js +2 -1
  83. package/dist/_internal/platform/channels/reply-pipeline.d.ts.map +1 -1
  84. package/dist/_internal/platform/channels/reply-pipeline.js +9 -0
  85. package/dist/_internal/platform/channels/route-manager.d.ts.map +1 -1
  86. package/dist/_internal/platform/channels/route-manager.js +1 -0
  87. package/dist/_internal/platform/channels/surface-registry.d.ts.map +1 -1
  88. package/dist/_internal/platform/channels/surface-registry.js +4 -0
  89. package/dist/_internal/platform/channels/types.d.ts +1 -1
  90. package/dist/_internal/platform/channels/types.d.ts.map +1 -1
  91. package/dist/_internal/platform/cloudflare/manager.d.ts +1 -1
  92. package/dist/_internal/platform/cloudflare/manager.d.ts.map +1 -1
  93. package/dist/_internal/platform/cloudflare/manager.js +27 -24
  94. package/dist/_internal/platform/cloudflare/types.d.ts +5 -0
  95. package/dist/_internal/platform/cloudflare/types.d.ts.map +1 -1
  96. package/dist/_internal/platform/cloudflare/utils.d.ts.map +1 -1
  97. package/dist/_internal/platform/cloudflare/utils.js +4 -10
  98. package/dist/_internal/platform/companion/companion-chat-manager.d.ts +24 -4
  99. package/dist/_internal/platform/companion/companion-chat-manager.d.ts.map +1 -1
  100. package/dist/_internal/platform/companion/companion-chat-manager.js +128 -78
  101. package/dist/_internal/platform/config/schema-domain-surfaces.d.ts +12 -0
  102. package/dist/_internal/platform/config/schema-domain-surfaces.d.ts.map +1 -1
  103. package/dist/_internal/platform/config/schema-domain-surfaces.js +67 -0
  104. package/dist/_internal/platform/config/schema-types.d.ts +15 -2
  105. package/dist/_internal/platform/config/schema-types.d.ts.map +1 -1
  106. package/dist/_internal/platform/control-plane/gateway-utils.d.ts +37 -0
  107. package/dist/_internal/platform/control-plane/gateway-utils.d.ts.map +1 -0
  108. package/dist/_internal/platform/control-plane/gateway-utils.js +97 -0
  109. package/dist/_internal/platform/control-plane/gateway.d.ts +4 -9
  110. package/dist/_internal/platform/control-plane/gateway.d.ts.map +1 -1
  111. package/dist/_internal/platform/control-plane/gateway.js +26 -61
  112. package/dist/_internal/platform/control-plane/method-catalog-runtime.d.ts.map +1 -1
  113. package/dist/_internal/platform/control-plane/method-catalog-runtime.js +11 -1
  114. package/dist/_internal/platform/control-plane/operator-contract-schemas-admin.d.ts.map +1 -1
  115. package/dist/_internal/platform/control-plane/operator-contract-schemas-admin.js +3 -2
  116. package/dist/_internal/platform/control-plane/operator-contract-schemas-control.d.ts +1 -0
  117. package/dist/_internal/platform/control-plane/operator-contract-schemas-control.d.ts.map +1 -1
  118. package/dist/_internal/platform/control-plane/operator-contract-schemas-control.js +26 -0
  119. package/dist/_internal/platform/control-plane/routes/operator.d.ts +1 -1
  120. package/dist/_internal/platform/control-plane/routes/operator.d.ts.map +1 -1
  121. package/dist/_internal/platform/control-plane/routes/operator.js +2 -0
  122. package/dist/_internal/platform/control-plane/session-types.d.ts +2 -1
  123. package/dist/_internal/platform/control-plane/session-types.d.ts.map +1 -1
  124. package/dist/_internal/platform/control-plane/types.d.ts +1 -1
  125. package/dist/_internal/platform/control-plane/types.d.ts.map +1 -1
  126. package/dist/_internal/platform/daemon/control-plane.d.ts.map +1 -1
  127. package/dist/_internal/platform/daemon/control-plane.js +50 -6
  128. package/dist/_internal/platform/daemon/facade-composition.d.ts.map +1 -1
  129. package/dist/_internal/platform/daemon/facade-composition.js +30 -2
  130. package/dist/_internal/platform/daemon/facade-types.d.ts +1 -1
  131. package/dist/_internal/platform/daemon/facade-types.d.ts.map +1 -1
  132. package/dist/_internal/platform/daemon/http/homeassistant-routes.d.ts +40 -0
  133. package/dist/_internal/platform/daemon/http/homeassistant-routes.d.ts.map +1 -0
  134. package/dist/_internal/platform/daemon/http/homeassistant-routes.js +468 -0
  135. package/dist/_internal/platform/daemon/http/router.d.ts +4 -2
  136. package/dist/_internal/platform/daemon/http/router.d.ts.map +1 -1
  137. package/dist/_internal/platform/daemon/http/router.js +28 -16
  138. package/dist/_internal/platform/daemon/http/runtime-route-types.d.ts +1 -1
  139. package/dist/_internal/platform/daemon/http/runtime-route-types.d.ts.map +1 -1
  140. package/dist/_internal/platform/daemon/http-listener.d.ts.map +1 -1
  141. package/dist/_internal/platform/daemon/http-listener.js +4 -8
  142. package/dist/_internal/platform/daemon/surface-actions.d.ts +1 -1
  143. package/dist/_internal/platform/daemon/surface-actions.d.ts.map +1 -1
  144. package/dist/_internal/platform/daemon/surface-delivery.d.ts +1 -1
  145. package/dist/_internal/platform/daemon/surface-delivery.d.ts.map +1 -1
  146. package/dist/_internal/platform/daemon/surface-delivery.js +15 -0
  147. package/dist/_internal/platform/daemon/surface-policy.d.ts +1 -1
  148. package/dist/_internal/platform/daemon/surface-policy.d.ts.map +1 -1
  149. package/dist/_internal/platform/daemon/surface-policy.js +8 -0
  150. package/dist/_internal/platform/daemon/types.d.ts +3 -3
  151. package/dist/_internal/platform/daemon/types.d.ts.map +1 -1
  152. package/dist/_internal/platform/integrations/homeassistant.d.ts +62 -0
  153. package/dist/_internal/platform/integrations/homeassistant.d.ts.map +1 -0
  154. package/dist/_internal/platform/integrations/homeassistant.js +174 -0
  155. package/dist/_internal/platform/integrations/index.d.ts +2 -0
  156. package/dist/_internal/platform/integrations/index.d.ts.map +1 -1
  157. package/dist/_internal/platform/integrations/index.js +1 -0
  158. package/dist/_internal/platform/runtime/events/control-plane.d.ts +1 -1
  159. package/dist/_internal/platform/runtime/events/control-plane.d.ts.map +1 -1
  160. package/dist/_internal/platform/runtime/events/control-plane.js +1 -0
  161. package/dist/_internal/platform/runtime/events/routes.d.ts +1 -1
  162. package/dist/_internal/platform/runtime/events/routes.d.ts.map +1 -1
  163. package/dist/_internal/platform/runtime/events/routes.js +1 -0
  164. package/dist/_internal/platform/runtime/feature-flags/flags.d.ts.map +1 -1
  165. package/dist/_internal/platform/runtime/feature-flags/flags.js +9 -0
  166. package/dist/_internal/platform/runtime/feature-flags/gates.d.ts.map +1 -1
  167. package/dist/_internal/platform/runtime/feature-flags/gates.js +2 -0
  168. package/dist/_internal/platform/runtime/index.d.ts +2 -0
  169. package/dist/_internal/platform/runtime/index.d.ts.map +1 -1
  170. package/dist/_internal/platform/runtime/index.js +1 -0
  171. package/dist/_internal/platform/runtime/integration/helpers.d.ts +4 -0
  172. package/dist/_internal/platform/runtime/integration/helpers.d.ts.map +1 -1
  173. package/dist/_internal/platform/runtime/integration/helpers.js +4 -0
  174. package/dist/_internal/platform/runtime/security-settings.d.ts +19 -0
  175. package/dist/_internal/platform/runtime/security-settings.d.ts.map +1 -0
  176. package/dist/_internal/platform/runtime/security-settings.js +187 -0
  177. package/dist/_internal/platform/runtime/services.d.ts.map +1 -1
  178. package/dist/_internal/platform/runtime/services.js +1 -0
  179. package/dist/_internal/platform/security/user-auth.d.ts +1 -1
  180. package/dist/_internal/platform/security/user-auth.d.ts.map +1 -1
  181. package/dist/_internal/platform/security/user-auth.js +18 -3
  182. package/dist/_internal/platform/tools/edit/core.d.ts.map +1 -1
  183. package/dist/_internal/platform/tools/edit/core.js +4 -47
  184. package/dist/_internal/platform/tools/exec/runtime.d.ts.map +1 -1
  185. package/dist/_internal/platform/tools/exec/runtime.js +7 -1
  186. package/dist/_internal/platform/tools/exec/schema.d.ts +1 -0
  187. package/dist/_internal/platform/tools/exec/schema.d.ts.map +1 -1
  188. package/dist/_internal/platform/tools/exec/schema.js +1 -0
  189. package/dist/_internal/platform/tools/fetch/runtime.d.ts.map +1 -1
  190. package/dist/_internal/platform/tools/fetch/runtime.js +140 -19
  191. package/dist/_internal/platform/tools/fetch/schema.d.ts +1 -0
  192. package/dist/_internal/platform/tools/fetch/schema.d.ts.map +1 -1
  193. package/dist/_internal/platform/tools/fetch/schema.js +1 -0
  194. package/dist/_internal/platform/tools/find/executor.d.ts.map +1 -1
  195. package/dist/_internal/platform/tools/find/executor.js +7 -1
  196. package/dist/_internal/platform/tools/find/schema.d.ts.map +1 -1
  197. package/dist/_internal/platform/tools/find/schema.js +2 -0
  198. package/dist/_internal/platform/tools/read/index.d.ts.map +1 -1
  199. package/dist/_internal/platform/tools/read/index.js +7 -1
  200. package/dist/_internal/platform/tools/read/schema.d.ts +1 -0
  201. package/dist/_internal/platform/tools/read/schema.d.ts.map +1 -1
  202. package/dist/_internal/platform/tools/read/schema.js +1 -0
  203. package/dist/_internal/platform/tools/shared/process-manager.d.ts +2 -0
  204. package/dist/_internal/platform/tools/shared/process-manager.d.ts.map +1 -1
  205. package/dist/_internal/platform/tools/shared/process-manager.js +67 -5
  206. package/dist/_internal/platform/tools/write/index.d.ts.map +1 -1
  207. package/dist/_internal/platform/tools/write/index.js +3 -36
  208. package/dist/_internal/platform/utils/concurrency.d.ts +3 -0
  209. package/dist/_internal/platform/utils/concurrency.d.ts.map +1 -0
  210. package/dist/_internal/platform/utils/concurrency.js +17 -0
  211. package/dist/_internal/platform/utils/logger.d.ts.map +1 -1
  212. package/dist/_internal/platform/utils/logger.js +19 -1
  213. package/dist/_internal/platform/utils/request-body.d.ts +4 -0
  214. package/dist/_internal/platform/utils/request-body.d.ts.map +1 -0
  215. package/dist/_internal/platform/utils/request-body.js +45 -0
  216. package/dist/_internal/platform/version.js +1 -1
  217. package/dist/workers.d.ts +6 -0
  218. package/dist/workers.d.ts.map +1 -1
  219. package/dist/workers.js +55 -3
  220. package/package.json +1 -1
@@ -0,0 +1,468 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { HOME_ASSISTANT_SURFACE } from '../../channels/builtin/homeassistant.js';
3
+ const DEFAULT_WAIT_TIMEOUT_MS = 120_000;
4
+ const MAX_WAIT_TIMEOUT_MS = 10 * 60_000;
5
+ const DEFAULT_REMOTE_SESSION_TTL_MS = 20 * 60_000;
6
+ export class HomeAssistantConversationRoutes {
7
+ context;
8
+ messageIndex = new Map();
9
+ constructor(context) {
10
+ this.context = context;
11
+ }
12
+ async handle(req) {
13
+ const url = new URL(req.url);
14
+ if (!url.pathname.startsWith('/api/homeassistant'))
15
+ return null;
16
+ if ((url.pathname === '/api/homeassistant' || url.pathname === '/api/homeassistant/health') && req.method === 'GET') {
17
+ return Response.json(this.describeHealth());
18
+ }
19
+ if (url.pathname === '/api/homeassistant/conversation' && req.method === 'POST') {
20
+ const body = await this.context.parseJsonBody(req);
21
+ if (body instanceof Response)
22
+ return body;
23
+ return this.respondToSubmit(await this.submitConversation(body, req.signal));
24
+ }
25
+ if (url.pathname === '/api/homeassistant/conversation/stream' && req.method === 'POST') {
26
+ const body = await this.context.parseJsonBody(req);
27
+ if (body instanceof Response)
28
+ return body;
29
+ return this.streamConversation(body, req.signal);
30
+ }
31
+ if (url.pathname === '/api/homeassistant/conversation/cancel' && req.method === 'POST') {
32
+ const body = await this.context.parseJsonBody(req);
33
+ if (body instanceof Response)
34
+ return body;
35
+ return this.cancelConversation(body);
36
+ }
37
+ return null;
38
+ }
39
+ describeHealth() {
40
+ const enabled = Boolean(this.context.configManager.get('surfaces.homeassistant.enabled'));
41
+ return {
42
+ ok: enabled,
43
+ surface: HOME_ASSISTANT_SURFACE,
44
+ enabled,
45
+ defaultConversationId: String(this.context.configManager.get('surfaces.homeassistant.defaultConversationId') || 'goodvibes'),
46
+ eventType: String(this.context.configManager.get('surfaces.homeassistant.eventType') || 'goodvibes_message'),
47
+ remoteSessionTtlMs: this.readRemoteSessionTtlMs({}),
48
+ endpoints: {
49
+ conversation: '/api/homeassistant/conversation',
50
+ stream: '/api/homeassistant/conversation/stream',
51
+ cancel: '/api/homeassistant/conversation/cancel',
52
+ webhook: '/webhook/homeassistant',
53
+ },
54
+ capabilities: [
55
+ 'conversation-submit-wait',
56
+ 'conversation-stream',
57
+ 'conversation-cancel',
58
+ 'stable-correlation',
59
+ 'remote-session-ttl',
60
+ 'homeassistant-event-delivery',
61
+ ],
62
+ };
63
+ }
64
+ async submitConversation(body, signal) {
65
+ if (!Boolean(this.context.configManager.get('surfaces.homeassistant.enabled'))) {
66
+ return {
67
+ ok: false,
68
+ acknowledged: true,
69
+ messageId: '',
70
+ conversationId: '',
71
+ sessionId: '',
72
+ routeId: '',
73
+ mode: 'rejected',
74
+ newSession: false,
75
+ sessionExpired: false,
76
+ status: 'rejected',
77
+ error: 'Home Assistant surface is disabled.',
78
+ };
79
+ }
80
+ const input = this.parseInput(body);
81
+ if (!input.text) {
82
+ return {
83
+ ok: false,
84
+ acknowledged: true,
85
+ messageId: input.messageId,
86
+ conversationId: input.conversationId,
87
+ sessionId: '',
88
+ routeId: '',
89
+ mode: 'rejected',
90
+ newSession: false,
91
+ sessionExpired: false,
92
+ status: 'rejected',
93
+ error: 'Missing Home Assistant conversation message.',
94
+ };
95
+ }
96
+ await this.context.routeBindings.start();
97
+ await this.context.sessionBroker.start();
98
+ const binding = await this.upsertBinding(input);
99
+ const sessionResolution = await this.resolveRemoteSession(binding, input);
100
+ const routing = this.buildRouting(input);
101
+ const submission = await this.context.sessionBroker.submitMessage({
102
+ sessionId: sessionResolution.session.id,
103
+ routeId: binding.id,
104
+ surfaceKind: HOME_ASSISTANT_SURFACE,
105
+ surfaceId: input.surfaceId,
106
+ externalId: input.conversationId,
107
+ ...(input.threadId ? { threadId: input.threadId } : {}),
108
+ ...(input.userId ? { userId: input.userId } : {}),
109
+ ...(input.displayName ? { displayName: input.displayName } : {}),
110
+ title: input.title,
111
+ body: input.text,
112
+ metadata: {
113
+ source: 'homeassistant',
114
+ messageId: input.messageId,
115
+ conversationId: input.conversationId,
116
+ remoteSessionTtlMs: input.remoteSessionTtlMs,
117
+ ...(input.context ? { homeAssistantContext: input.context } : {}),
118
+ },
119
+ ...(routing ? { routing } : {}),
120
+ });
121
+ let agentId = submission.activeAgentId;
122
+ if (submission.mode === 'spawn') {
123
+ const spawnResult = this.context.trySpawnAgent({
124
+ mode: 'spawn',
125
+ task: submission.task,
126
+ ...(input.modelId ? { model: input.modelId } : {}),
127
+ ...(input.providerId ? { provider: input.providerId } : {}),
128
+ ...(input.tools?.length ? { tools: [...input.tools] } : {}),
129
+ context: `homeassistant:${input.conversationId}`,
130
+ }, 'HomeAssistantConversationRoutes.submitConversation', submission.session.id);
131
+ if (spawnResult instanceof Response) {
132
+ return this.errorFromSpawnResponse(input, sessionResolution, binding, spawnResult);
133
+ }
134
+ agentId = spawnResult.id;
135
+ await this.context.sessionBroker.bindAgent(submission.session.id, spawnResult.id);
136
+ if (input.publishEvent) {
137
+ this.context.queueSurfaceReplyFromBinding(binding, {
138
+ agentId: spawnResult.id,
139
+ task: input.text,
140
+ sessionId: submission.session.id,
141
+ });
142
+ }
143
+ }
144
+ this.indexMessage(input, submission.session.id, binding.id, agentId);
145
+ const base = {
146
+ ok: true,
147
+ acknowledged: true,
148
+ messageId: input.messageId,
149
+ conversationId: input.conversationId,
150
+ sessionId: submission.session.id,
151
+ routeId: binding.id,
152
+ ...(agentId ? { agentId } : {}),
153
+ mode: submission.mode,
154
+ newSession: sessionResolution.newSession,
155
+ sessionExpired: sessionResolution.sessionExpired,
156
+ };
157
+ if (submission.mode === 'rejected') {
158
+ return { ...base, ok: false, status: 'rejected', error: 'Home Assistant conversation was rejected.' };
159
+ }
160
+ if (!agentId || !input.wait) {
161
+ return { ...base, status: agentId ? 'running' : 'queued' };
162
+ }
163
+ const finalRecord = await this.waitForAgent(agentId, input.waitTimeoutMs, signal);
164
+ if (!finalRecord) {
165
+ return { ...base, status: 'timeout', timeoutMs: input.waitTimeoutMs };
166
+ }
167
+ return {
168
+ ...base,
169
+ status: normalizeAgentStatus(finalRecord.status),
170
+ ok: finalRecord.status === 'completed',
171
+ assistant: buildAssistantResult(finalRecord),
172
+ ...(finalRecord.status !== 'completed' ? { error: finalRecord.error ?? finalRecord.status } : {}),
173
+ };
174
+ }
175
+ respondToSubmit(result) {
176
+ if (result.error === 'Home Assistant surface is disabled.')
177
+ return Response.json(result, { status: 503 });
178
+ if (result.status === 'rejected')
179
+ return Response.json(result, { status: result.ok ? 202 : 400 });
180
+ if (result.status === 'timeout')
181
+ return Response.json(result, { status: 202 });
182
+ if (result.status === 'failed')
183
+ return Response.json(result, { status: 500 });
184
+ if (result.status === 'cancelled')
185
+ return Response.json(result, { status: 409 });
186
+ return Response.json(result, { status: result.status === 'completed' ? 200 : 202 });
187
+ }
188
+ streamConversation(body, signal) {
189
+ const encoder = new TextEncoder();
190
+ const stream = new ReadableStream({
191
+ start: async (controller) => {
192
+ const send = (event, data) => {
193
+ controller.enqueue(encoder.encode(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`));
194
+ };
195
+ try {
196
+ const result = await this.submitConversation({ ...body, wait: false }, signal);
197
+ send('ack', result);
198
+ if (!result.agentId) {
199
+ send('final', result);
200
+ controller.close();
201
+ return;
202
+ }
203
+ let lastProgress = '';
204
+ for (;;) {
205
+ if (signal.aborted)
206
+ return;
207
+ const record = this.context.agentManager.getStatus(result.agentId);
208
+ if (!record) {
209
+ send('error', { ...result, ok: false, error: 'Unknown agent.' });
210
+ controller.close();
211
+ return;
212
+ }
213
+ const progress = record.streamingContent ?? record.progress ?? '';
214
+ if (progress && progress !== lastProgress) {
215
+ lastProgress = progress;
216
+ send('progress', { messageId: result.messageId, agentId: result.agentId, text: progress });
217
+ }
218
+ if (record.status === 'completed' || record.status === 'failed' || record.status === 'cancelled') {
219
+ send('final', {
220
+ ...result,
221
+ ok: record.status === 'completed',
222
+ status: normalizeAgentStatus(record.status),
223
+ assistant: buildAssistantResult(record),
224
+ ...(record.status !== 'completed' ? { error: record.error ?? record.status } : {}),
225
+ });
226
+ controller.close();
227
+ return;
228
+ }
229
+ await delay(250, signal);
230
+ }
231
+ }
232
+ catch (error) {
233
+ if (!signal.aborted) {
234
+ send('error', { ok: false, error: error instanceof Error ? error.message : String(error) });
235
+ controller.close();
236
+ }
237
+ }
238
+ },
239
+ cancel: () => undefined,
240
+ });
241
+ return new Response(stream, {
242
+ headers: {
243
+ 'Content-Type': 'text/event-stream; charset=utf-8',
244
+ 'Cache-Control': 'no-cache, no-transform',
245
+ Connection: 'keep-alive',
246
+ },
247
+ });
248
+ }
249
+ cancelConversation(body) {
250
+ const agentId = readString(body.agentId)
251
+ ?? (readString(body.messageId ?? body.message_id)
252
+ ? this.messageIndex.get(readString(body.messageId ?? body.message_id))?.agentId
253
+ : undefined);
254
+ if (!agentId) {
255
+ return Response.json({ ok: false, error: 'agentId or known messageId is required.' }, { status: 400 });
256
+ }
257
+ const cancelled = this.context.agentManager.cancel(agentId);
258
+ return cancelled
259
+ ? Response.json({ ok: true, agentId, status: 'cancelled' })
260
+ : Response.json({ ok: false, agentId, error: 'Unknown or already finished agent.' }, { status: 404 });
261
+ }
262
+ parseInput(body) {
263
+ const threadId = readString(body.threadId ?? body.thread_id);
264
+ const userId = readString(body.userId ?? body.user_id);
265
+ const displayName = readString(body.displayName ?? body.userName ?? body.user_name);
266
+ const providerId = readString(body.providerId ?? body.provider);
267
+ const modelId = readString(body.modelId ?? body.model);
268
+ const tools = readStringList(body.tools);
269
+ const haContext = readRecord(body.context);
270
+ const conversationId = readString(body.conversationId ?? body.conversation_id)
271
+ ?? threadId
272
+ ?? readString(body.deviceId ?? body.device_id)
273
+ ?? String(this.context.configManager.get('surfaces.homeassistant.defaultConversationId') || 'goodvibes');
274
+ const surfaceId = readString(body.surfaceId ?? body.instanceId ?? body.instance_id)
275
+ ?? readString(body.hassInstanceId ?? body.hass_instance_id)
276
+ ?? 'homeassistant';
277
+ const channelId = readString(body.areaId ?? body.area_id)
278
+ ?? readString(body.entityId ?? body.entity_id)
279
+ ?? conversationId;
280
+ return {
281
+ text: readString(body.body ?? body.message ?? body.text ?? body.prompt ?? body.task) ?? '',
282
+ messageId: readString(body.messageId ?? body.message_id) ?? `ha-${randomUUID()}`,
283
+ conversationId,
284
+ surfaceId,
285
+ channelId,
286
+ ...(threadId ? { threadId } : {}),
287
+ ...(userId ? { userId } : {}),
288
+ ...(displayName ? { displayName } : {}),
289
+ title: readString(body.title) ?? 'Home Assistant',
290
+ ...(providerId ? { providerId } : {}),
291
+ ...(modelId ? { modelId } : {}),
292
+ ...(tools.length ? { tools } : {}),
293
+ ...(haContext ? { context: haContext } : {}),
294
+ publishEvent: body.publishEvent === true,
295
+ wait: body.wait !== false,
296
+ waitTimeoutMs: clampNumber(body.timeoutMs ?? body.waitTimeoutMs, DEFAULT_WAIT_TIMEOUT_MS, 1_000, MAX_WAIT_TIMEOUT_MS),
297
+ remoteSessionTtlMs: this.readRemoteSessionTtlMs(body),
298
+ };
299
+ }
300
+ async upsertBinding(input) {
301
+ return this.context.routeBindings.upsertBinding({
302
+ kind: input.threadId ? 'thread' : 'channel',
303
+ surfaceKind: HOME_ASSISTANT_SURFACE,
304
+ surfaceId: input.surfaceId,
305
+ externalId: input.conversationId,
306
+ ...(input.threadId ? { threadId: input.threadId } : {}),
307
+ channelId: input.channelId,
308
+ title: input.title,
309
+ metadata: {
310
+ source: 'homeassistant',
311
+ directoryKind: input.threadId ? 'thread' : 'user',
312
+ messageId: input.messageId,
313
+ conversationId: input.conversationId,
314
+ remoteSessionTtlMs: input.remoteSessionTtlMs,
315
+ ...(input.context ? { homeAssistantContext: input.context } : {}),
316
+ },
317
+ });
318
+ }
319
+ async resolveRemoteSession(binding, input) {
320
+ const now = Date.now();
321
+ const current = binding.sessionId ? this.context.sessionBroker.getSession(binding.sessionId) : null;
322
+ if (current && current.status !== 'closed' && !isExpiredSession(current, input.remoteSessionTtlMs, now)) {
323
+ return { session: current, newSession: false, sessionExpired: false };
324
+ }
325
+ if (current && current.status !== 'closed' && !current.activeAgentId) {
326
+ await this.context.sessionBroker.closeSession(current.id);
327
+ }
328
+ const session = await this.context.sessionBroker.createSession({
329
+ title: input.title,
330
+ metadata: {
331
+ source: 'homeassistant',
332
+ conversationId: input.conversationId,
333
+ remote: true,
334
+ remoteSessionTtlMs: input.remoteSessionTtlMs,
335
+ },
336
+ routeBinding: binding,
337
+ participant: {
338
+ surfaceKind: HOME_ASSISTANT_SURFACE,
339
+ surfaceId: input.surfaceId,
340
+ externalId: input.conversationId,
341
+ ...(input.userId ? { userId: input.userId } : {}),
342
+ ...(input.displayName ? { displayName: input.displayName } : {}),
343
+ routeId: binding.id,
344
+ lastSeenAt: now,
345
+ },
346
+ kind: 'homeassistant-remote',
347
+ });
348
+ await this.context.routeBindings.patchBinding(binding.id, {
349
+ sessionId: session.id,
350
+ metadata: {
351
+ homeAssistantSessionId: session.id,
352
+ homeAssistantSessionCreatedAt: now,
353
+ remoteSessionTtlMs: input.remoteSessionTtlMs,
354
+ },
355
+ });
356
+ return {
357
+ session,
358
+ newSession: true,
359
+ sessionExpired: Boolean(current),
360
+ };
361
+ }
362
+ buildRouting(input) {
363
+ if (!input.providerId && !input.modelId && !input.tools?.length)
364
+ return undefined;
365
+ return {
366
+ ...(input.providerId ? { providerId: input.providerId } : {}),
367
+ ...(input.modelId ? { modelId: input.modelId } : {}),
368
+ ...(input.tools?.length ? { tools: input.tools } : {}),
369
+ };
370
+ }
371
+ async waitForAgent(agentId, timeoutMs, signal) {
372
+ const startedAt = Date.now();
373
+ while (Date.now() - startedAt < timeoutMs) {
374
+ if (signal.aborted)
375
+ return null;
376
+ const record = this.context.agentManager.getStatus(agentId);
377
+ if (record && (record.status === 'completed' || record.status === 'failed' || record.status === 'cancelled')) {
378
+ return record;
379
+ }
380
+ await delay(200, signal);
381
+ }
382
+ return null;
383
+ }
384
+ errorFromSpawnResponse(input, session, binding, response) {
385
+ return {
386
+ ok: false,
387
+ acknowledged: true,
388
+ messageId: input.messageId,
389
+ conversationId: input.conversationId,
390
+ sessionId: session.session.id,
391
+ routeId: binding.id,
392
+ mode: 'rejected',
393
+ newSession: session.newSession,
394
+ sessionExpired: session.sessionExpired,
395
+ status: 'rejected',
396
+ error: `Agent spawn failed with HTTP ${response.status}.`,
397
+ };
398
+ }
399
+ indexMessage(input, sessionId, routeId, agentId) {
400
+ this.messageIndex.set(input.messageId, {
401
+ messageId: input.messageId,
402
+ ...(agentId ? { agentId } : {}),
403
+ sessionId,
404
+ routeId,
405
+ conversationId: input.conversationId,
406
+ createdAt: Date.now(),
407
+ });
408
+ if (this.messageIndex.size > 500) {
409
+ const oldest = [...this.messageIndex.values()].sort((a, b) => a.createdAt - b.createdAt).slice(0, 100);
410
+ for (const entry of oldest)
411
+ this.messageIndex.delete(entry.messageId);
412
+ }
413
+ }
414
+ readRemoteSessionTtlMs(body) {
415
+ return clampNumber(body.remoteSessionTtlMs, Number(this.context.configManager.get('surfaces.homeassistant.remoteSessionTtlMs') ?? DEFAULT_REMOTE_SESSION_TTL_MS), 60_000, 24 * 60 * 60_000);
416
+ }
417
+ }
418
+ function isExpiredSession(session, ttlMs, now) {
419
+ if (session.activeAgentId)
420
+ return false;
421
+ return now - session.lastActivityAt > ttlMs;
422
+ }
423
+ function buildAssistantResult(record) {
424
+ const text = record.status === 'completed'
425
+ ? (record.fullOutput ?? record.streamingContent ?? record.progress ?? 'Completed')
426
+ : record.error ?? record.status;
427
+ return {
428
+ text,
429
+ speechText: text,
430
+ status: record.status,
431
+ toolCallsMade: record.toolCallCount,
432
+ ...(record.usage ? { usage: record.usage } : {}),
433
+ ...(record.completedAt ? { completedAt: record.completedAt } : {}),
434
+ };
435
+ }
436
+ function normalizeAgentStatus(status) {
437
+ if (status === 'pending' || status === 'running')
438
+ return 'running';
439
+ return status;
440
+ }
441
+ function readString(value) {
442
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;
443
+ }
444
+ function readStringList(value) {
445
+ return Array.isArray(value)
446
+ ? value.filter((entry) => typeof entry === 'string' && entry.trim().length > 0).map((entry) => entry.trim())
447
+ : [];
448
+ }
449
+ function readRecord(value) {
450
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
451
+ }
452
+ function clampNumber(value, fallback, min, max) {
453
+ const parsed = typeof value === 'number' ? value : typeof value === 'string' ? Number(value) : fallback;
454
+ if (!Number.isFinite(parsed))
455
+ return fallback;
456
+ return Math.max(min, Math.min(max, Math.trunc(parsed)));
457
+ }
458
+ function delay(ms, signal) {
459
+ if (signal.aborted)
460
+ return Promise.resolve();
461
+ return new Promise((resolve) => {
462
+ const timer = setTimeout(resolve, ms);
463
+ signal.addEventListener('abort', () => {
464
+ clearTimeout(timer);
465
+ resolve();
466
+ }, { once: true });
467
+ });
468
+ }
@@ -98,7 +98,7 @@ interface DaemonHttpRouterContext {
98
98
  readonly workflowChainId?: string;
99
99
  readonly sessionId?: string;
100
100
  }) => void;
101
- readonly surfaceDeliveryEnabled: (surface: 'slack' | 'discord' | 'ntfy' | 'webhook' | 'telegram' | 'google-chat' | 'signal' | 'whatsapp' | 'imessage' | 'msteams' | 'bluebubbles' | 'mattermost' | 'matrix') => boolean;
101
+ readonly surfaceDeliveryEnabled: (surface: 'slack' | 'discord' | 'ntfy' | 'webhook' | 'homeassistant' | 'telegram' | 'google-chat' | 'signal' | 'whatsapp' | 'imessage' | 'msteams' | 'bluebubbles' | 'mattermost' | 'matrix') => boolean;
102
102
  readonly syncSpawnedAgentTask: (record: import('../../tools/agent/index.js').AgentRecord, sessionId?: string) => void;
103
103
  readonly syncFinishedAgentTask: (record: import('../../tools/agent/index.js').AgentRecord) => void;
104
104
  /**
@@ -135,14 +135,16 @@ interface DaemonHttpRouterContext {
135
135
  export declare class DaemonHttpRouter {
136
136
  private readonly context;
137
137
  private readonly telemetryApi;
138
+ private homeAssistantRoutes;
138
139
  constructor(context: DaemonHttpRouterContext);
139
140
  dispose(): void;
140
141
  handleRequest(req: Request): Promise<Response>;
141
142
  dispatchApiRoutes(req: Request): Promise<Response | null>;
143
+ private getHomeAssistantRoutes;
142
144
  parseJsonBody(req: Request): Promise<JsonRecord | Response>;
143
145
  parseOptionalJsonBody(req: Request): Promise<JsonRecord | null | Response>;
144
146
  parseJsonText(rawBody: string): JsonRecord | Response;
145
- recordApiResponse(req: Request, path: string, response: Response, clientKind?: 'web' | 'slack' | 'discord' | 'ntfy' | 'webhook' | 'telegram' | 'google-chat' | 'signal' | 'whatsapp' | 'imessage' | 'msteams' | 'bluebubbles' | 'mattermost' | 'matrix' | 'daemon'): Response;
147
+ recordApiResponse(req: Request, path: string, response: Response, clientKind?: 'web' | 'slack' | 'discord' | 'ntfy' | 'webhook' | 'homeassistant' | 'telegram' | 'google-chat' | 'signal' | 'whatsapp' | 'imessage' | 'msteams' | 'bluebubbles' | 'mattermost' | 'matrix' | 'daemon'): Response;
146
148
  private handleLogin;
147
149
  private handleGitHubWebhook;
148
150
  handleSlackWebhook(req: Request): Promise<Response>;
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/daemon/http/router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/daemon/http/router.ts"],"names":[],"mappings":"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"}
@@ -28,9 +28,12 @@ import { dispatchCompanionChatRoutes } from '../../companion/companion-chat-rout
28
28
  import { dispatchProviderRoutes } from './provider-routes.js';
29
29
  import { dispatchBatchRoutes } from './batch-routes.js';
30
30
  import { dispatchCloudflareRoutes } from './cloudflare-routes.js';
31
+ import { HomeAssistantConversationRoutes } from './homeassistant-routes.js';
32
+ import { readTextBodyWithinLimit } from '../../utils/request-body.js';
31
33
  export class DaemonHttpRouter {
32
34
  context;
33
35
  telemetryApi;
36
+ homeAssistantRoutes = null;
34
37
  constructor(context) {
35
38
  this.context = context;
36
39
  this.telemetryApi = context.runtimeStore
@@ -145,6 +148,11 @@ export class DaemonHttpRouter {
145
148
  if (cloudflareResponse)
146
149
  return cloudflareResponse;
147
150
  }
151
+ if (url.pathname.startsWith('/api/homeassistant')) {
152
+ const homeAssistantResponse = await this.getHomeAssistantRoutes().handle(req);
153
+ if (homeAssistantResponse)
154
+ return homeAssistantResponse;
155
+ }
148
156
  // Companion chat routes — scoped to /api/companion/chat/..., session-isolated.
149
157
  // Handled before the main API router so they never touch the global control-plane feed.
150
158
  // Provider discovery + model-switching routes
@@ -385,18 +393,27 @@ export class DaemonHttpRouter {
385
393
  }),
386
394
  });
387
395
  }
396
+ getHomeAssistantRoutes() {
397
+ if (!this.homeAssistantRoutes) {
398
+ this.homeAssistantRoutes = new HomeAssistantConversationRoutes({
399
+ configManager: this.context.configManager,
400
+ routeBindings: this.context.routeBindings,
401
+ sessionBroker: this.context.sessionBroker,
402
+ agentManager: this.context.agentManager,
403
+ parseJsonBody: (request) => this.parseJsonBody(request),
404
+ trySpawnAgent: (input, logLabel, sessionId) => this.context.trySpawnAgent(input, logLabel, sessionId),
405
+ queueSurfaceReplyFromBinding: (binding, input) => this.context.queueSurfaceReplyFromBinding(binding, input),
406
+ });
407
+ }
408
+ return this.homeAssistantRoutes;
409
+ }
388
410
  async parseJsonBody(req) {
389
411
  // SEC-05: cap inbound JSON bodies at 1 MiB to prevent memory exhaustion.
390
412
  const MAX_JSON_BYTES = 1 * 1024 * 1024; // 1 MiB
391
- const contentLength = req.headers.get('content-length');
392
- if (contentLength !== null && Number(contentLength) > MAX_JSON_BYTES) {
393
- return Response.json({ error: 'Request body too large' }, { status: 413 });
394
- }
395
413
  try {
396
- const text = await req.text();
397
- if (text.length > MAX_JSON_BYTES) {
398
- return Response.json({ error: 'Request body too large' }, { status: 413 });
399
- }
414
+ const text = await readTextBodyWithinLimit(req, MAX_JSON_BYTES);
415
+ if (text instanceof Response)
416
+ return text;
400
417
  return this.parseJsonText(text);
401
418
  }
402
419
  catch {
@@ -406,14 +423,9 @@ export class DaemonHttpRouter {
406
423
  async parseOptionalJsonBody(req) {
407
424
  // SEC-05: cap inbound JSON bodies at 1 MiB to prevent memory exhaustion.
408
425
  const MAX_JSON_BYTES = 1 * 1024 * 1024; // 1 MiB
409
- const contentLength = req.headers.get('content-length');
410
- if (contentLength !== null && Number(contentLength) > MAX_JSON_BYTES) {
411
- return Response.json({ error: 'Request body too large' }, { status: 413 });
412
- }
413
- const raw = await req.text();
414
- if (raw.length > MAX_JSON_BYTES) {
415
- return Response.json({ error: 'Request body too large' }, { status: 413 });
416
- }
426
+ const raw = await readTextBodyWithinLimit(req, MAX_JSON_BYTES);
427
+ if (raw instanceof Response)
428
+ return raw;
417
429
  if (!raw.trim())
418
430
  return null;
419
431
  return this.parseJsonText(raw);
@@ -234,7 +234,7 @@ export interface DaemonRuntimeRouteContext extends Omit<SdkDaemonRuntimeRouteCon
234
234
  readonly workflowChainId?: string;
235
235
  readonly sessionId?: string;
236
236
  }) => void;
237
- readonly surfaceDeliveryEnabled: (surface: 'slack' | 'discord' | 'ntfy' | 'webhook' | 'telegram' | 'google-chat' | 'signal' | 'whatsapp' | 'imessage' | 'msteams' | 'bluebubbles' | 'mattermost' | 'matrix') => boolean;
237
+ readonly surfaceDeliveryEnabled: (surface: 'slack' | 'discord' | 'ntfy' | 'webhook' | 'homeassistant' | 'telegram' | 'google-chat' | 'signal' | 'whatsapp' | 'imessage' | 'msteams' | 'bluebubbles' | 'mattermost' | 'matrix') => boolean;
238
238
  readonly syncSpawnedAgentTask: (record: AgentRecordLike, sessionId?: string) => void;
239
239
  readonly syncFinishedAgentTask: (record: AgentRecordLike) => void;
240
240
  readonly configManager: {