@pellux/goodvibes-sdk 0.25.8 → 0.25.11

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 (245) hide show
  1. package/README.md +4 -0
  2. package/dist/_internal/contracts/artifacts/operator-contract.json +178 -6
  3. package/dist/_internal/contracts/generated/foundation-client-types.d.ts +16 -1
  4. package/dist/_internal/contracts/generated/foundation-client-types.d.ts.map +1 -1
  5. package/dist/_internal/contracts/generated/foundation-metadata.d.ts +2 -2
  6. package/dist/_internal/contracts/generated/foundation-metadata.js +2 -2
  7. package/dist/_internal/contracts/generated/operator-contract.d.ts.map +1 -1
  8. package/dist/_internal/contracts/generated/operator-contract.js +178 -6
  9. package/dist/_internal/contracts/generated/operator-method-ids.d.ts +1 -1
  10. package/dist/_internal/contracts/generated/operator-method-ids.d.ts.map +1 -1
  11. package/dist/_internal/contracts/generated/operator-method-ids.js +1 -0
  12. package/dist/_internal/daemon/context.d.ts +1 -0
  13. package/dist/_internal/daemon/context.d.ts.map +1 -1
  14. package/dist/_internal/daemon/integration-route-types.d.ts +1 -0
  15. package/dist/_internal/daemon/integration-route-types.d.ts.map +1 -1
  16. package/dist/_internal/daemon/integration-routes.d.ts +1 -1
  17. package/dist/_internal/daemon/integration-routes.d.ts.map +1 -1
  18. package/dist/_internal/daemon/integration-routes.js +3 -0
  19. package/dist/_internal/daemon/operator.d.ts +1 -1
  20. package/dist/_internal/daemon/operator.d.ts.map +1 -1
  21. package/dist/_internal/daemon/operator.js +2 -0
  22. package/dist/_internal/daemon/runtime-route-types.d.ts +1 -1
  23. package/dist/_internal/daemon/runtime-route-types.d.ts.map +1 -1
  24. package/dist/_internal/platform/adapters/discord/index.d.ts.map +1 -1
  25. package/dist/_internal/platform/adapters/discord/index.js +4 -5
  26. package/dist/_internal/platform/adapters/github/index.d.ts.map +1 -1
  27. package/dist/_internal/platform/adapters/github/index.js +4 -5
  28. package/dist/_internal/platform/adapters/google-chat/index.d.ts.map +1 -1
  29. package/dist/_internal/platform/adapters/google-chat/index.js +7 -5
  30. package/dist/_internal/platform/adapters/helpers.d.ts +2 -1
  31. package/dist/_internal/platform/adapters/helpers.d.ts.map +1 -1
  32. package/dist/_internal/platform/adapters/helpers.js +3 -34
  33. package/dist/_internal/platform/adapters/homeassistant/index.d.ts +3 -0
  34. package/dist/_internal/platform/adapters/homeassistant/index.d.ts.map +1 -0
  35. package/dist/_internal/platform/adapters/homeassistant/index.js +177 -0
  36. package/dist/_internal/platform/adapters/index.d.ts +1 -0
  37. package/dist/_internal/platform/adapters/index.d.ts.map +1 -1
  38. package/dist/_internal/platform/adapters/index.js +1 -0
  39. package/dist/_internal/platform/adapters/mattermost/index.d.ts.map +1 -1
  40. package/dist/_internal/platform/adapters/mattermost/index.js +6 -2
  41. package/dist/_internal/platform/adapters/slack/index.d.ts.map +1 -1
  42. package/dist/_internal/platform/adapters/slack/index.js +4 -5
  43. package/dist/_internal/platform/adapters/telegram/index.d.ts.map +1 -1
  44. package/dist/_internal/platform/adapters/telegram/index.js +7 -5
  45. package/dist/_internal/platform/adapters/types.d.ts +1 -1
  46. package/dist/_internal/platform/adapters/types.d.ts.map +1 -1
  47. package/dist/_internal/platform/adapters/webhook/index.d.ts.map +1 -1
  48. package/dist/_internal/platform/adapters/webhook/index.js +4 -1
  49. package/dist/_internal/platform/automation/types.d.ts +1 -1
  50. package/dist/_internal/platform/automation/types.d.ts.map +1 -1
  51. package/dist/_internal/platform/batch/manager.d.ts.map +1 -1
  52. package/dist/_internal/platform/batch/manager.js +4 -0
  53. package/dist/_internal/platform/batch/types.d.ts +4 -0
  54. package/dist/_internal/platform/batch/types.d.ts.map +1 -1
  55. package/dist/_internal/platform/channels/builtin/accounts.d.ts.map +1 -1
  56. package/dist/_internal/platform/channels/builtin/accounts.js +22 -0
  57. package/dist/_internal/platform/channels/builtin/contracts.d.ts.map +1 -1
  58. package/dist/_internal/platform/channels/builtin/contracts.js +9 -0
  59. package/dist/_internal/platform/channels/builtin/descriptors.d.ts.map +1 -1
  60. package/dist/_internal/platform/channels/builtin/descriptors.js +9 -2
  61. package/dist/_internal/platform/channels/builtin/homeassistant.d.ts +64 -0
  62. package/dist/_internal/platform/channels/builtin/homeassistant.d.ts.map +1 -0
  63. package/dist/_internal/platform/channels/builtin/homeassistant.js +380 -0
  64. package/dist/_internal/platform/channels/builtin/plugins.d.ts.map +1 -1
  65. package/dist/_internal/platform/channels/builtin/plugins.js +2 -1
  66. package/dist/_internal/platform/channels/builtin/presentation.d.ts.map +1 -1
  67. package/dist/_internal/platform/channels/builtin/presentation.js +4 -0
  68. package/dist/_internal/platform/channels/builtin/setup-schema.d.ts.map +1 -1
  69. package/dist/_internal/platform/channels/builtin/setup-schema.js +46 -0
  70. package/dist/_internal/platform/channels/builtin/shared.d.ts +1 -1
  71. package/dist/_internal/platform/channels/builtin/shared.d.ts.map +1 -1
  72. package/dist/_internal/platform/channels/builtin/shared.js +2 -0
  73. package/dist/_internal/platform/channels/builtin/surfaces.d.ts.map +1 -1
  74. package/dist/_internal/platform/channels/builtin/surfaces.js +1 -0
  75. package/dist/_internal/platform/channels/builtin/targets.d.ts.map +1 -1
  76. package/dist/_internal/platform/channels/builtin/targets.js +24 -0
  77. package/dist/_internal/platform/channels/builtin-runtime.d.ts.map +1 -1
  78. package/dist/_internal/platform/channels/builtin-runtime.js +6 -0
  79. package/dist/_internal/platform/channels/delivery/strategies-core.d.ts +1 -0
  80. package/dist/_internal/platform/channels/delivery/strategies-core.d.ts.map +1 -1
  81. package/dist/_internal/platform/channels/delivery/strategies-core.js +41 -1
  82. package/dist/_internal/platform/channels/delivery-router.d.ts.map +1 -1
  83. package/dist/_internal/platform/channels/delivery-router.js +2 -1
  84. package/dist/_internal/platform/channels/reply-pipeline.d.ts.map +1 -1
  85. package/dist/_internal/platform/channels/reply-pipeline.js +9 -0
  86. package/dist/_internal/platform/channels/route-manager.d.ts.map +1 -1
  87. package/dist/_internal/platform/channels/route-manager.js +1 -0
  88. package/dist/_internal/platform/channels/surface-registry.d.ts.map +1 -1
  89. package/dist/_internal/platform/channels/surface-registry.js +4 -0
  90. package/dist/_internal/platform/channels/types.d.ts +1 -1
  91. package/dist/_internal/platform/channels/types.d.ts.map +1 -1
  92. package/dist/_internal/platform/cloudflare/client.d.ts +3 -0
  93. package/dist/_internal/platform/cloudflare/client.d.ts.map +1 -0
  94. package/dist/_internal/platform/cloudflare/client.js +9 -0
  95. package/dist/_internal/platform/cloudflare/config.d.ts +8 -0
  96. package/dist/_internal/platform/cloudflare/config.d.ts.map +1 -0
  97. package/dist/_internal/platform/cloudflare/config.js +48 -0
  98. package/dist/_internal/platform/cloudflare/constants.d.ts +18 -0
  99. package/dist/_internal/platform/cloudflare/constants.d.ts.map +1 -0
  100. package/dist/_internal/platform/cloudflare/constants.js +36 -0
  101. package/dist/_internal/platform/cloudflare/discovery.d.ts +23 -0
  102. package/dist/_internal/platform/cloudflare/discovery.d.ts.map +1 -0
  103. package/dist/_internal/platform/cloudflare/discovery.js +57 -0
  104. package/dist/_internal/platform/cloudflare/index.d.ts +6 -0
  105. package/dist/_internal/platform/cloudflare/index.d.ts.map +1 -0
  106. package/dist/_internal/platform/cloudflare/index.js +4 -0
  107. package/dist/_internal/platform/cloudflare/manager.d.ts +30 -0
  108. package/dist/_internal/platform/cloudflare/manager.d.ts.map +1 -0
  109. package/dist/_internal/platform/cloudflare/manager.js +674 -0
  110. package/dist/_internal/platform/cloudflare/resources.d.ts +79 -0
  111. package/dist/_internal/platform/cloudflare/resources.d.ts.map +1 -0
  112. package/dist/_internal/platform/cloudflare/resources.js +353 -0
  113. package/dist/_internal/platform/cloudflare/types.d.ts +694 -0
  114. package/dist/_internal/platform/cloudflare/types.d.ts.map +1 -0
  115. package/dist/_internal/platform/cloudflare/types.js +10 -0
  116. package/dist/_internal/platform/cloudflare/utils.d.ts +14 -0
  117. package/dist/_internal/platform/cloudflare/utils.d.ts.map +1 -0
  118. package/dist/_internal/platform/cloudflare/utils.js +216 -0
  119. package/dist/_internal/platform/cloudflare/worker-source.d.ts +2 -0
  120. package/dist/_internal/platform/cloudflare/worker-source.d.ts.map +1 -0
  121. package/dist/_internal/platform/cloudflare/worker-source.js +165 -0
  122. package/dist/_internal/platform/companion/companion-chat-manager.d.ts +24 -4
  123. package/dist/_internal/platform/companion/companion-chat-manager.d.ts.map +1 -1
  124. package/dist/_internal/platform/companion/companion-chat-manager.js +128 -78
  125. package/dist/_internal/platform/config/schema-domain-runtime.d.ts +24 -0
  126. package/dist/_internal/platform/config/schema-domain-runtime.d.ts.map +1 -1
  127. package/dist/_internal/platform/config/schema-domain-runtime.js +169 -0
  128. package/dist/_internal/platform/config/schema-domain-surfaces.d.ts +11 -0
  129. package/dist/_internal/platform/config/schema-domain-surfaces.d.ts.map +1 -1
  130. package/dist/_internal/platform/config/schema-domain-surfaces.js +59 -0
  131. package/dist/_internal/platform/config/schema-types.d.ts +38 -2
  132. package/dist/_internal/platform/config/schema-types.d.ts.map +1 -1
  133. package/dist/_internal/platform/control-plane/gateway-utils.d.ts +37 -0
  134. package/dist/_internal/platform/control-plane/gateway-utils.d.ts.map +1 -0
  135. package/dist/_internal/platform/control-plane/gateway-utils.js +97 -0
  136. package/dist/_internal/platform/control-plane/gateway.d.ts +4 -9
  137. package/dist/_internal/platform/control-plane/gateway.d.ts.map +1 -1
  138. package/dist/_internal/platform/control-plane/gateway.js +26 -61
  139. package/dist/_internal/platform/control-plane/method-catalog-runtime.d.ts.map +1 -1
  140. package/dist/_internal/platform/control-plane/method-catalog-runtime.js +11 -1
  141. package/dist/_internal/platform/control-plane/operator-contract-schemas-admin.d.ts.map +1 -1
  142. package/dist/_internal/platform/control-plane/operator-contract-schemas-admin.js +3 -2
  143. package/dist/_internal/platform/control-plane/operator-contract-schemas-control.d.ts +1 -0
  144. package/dist/_internal/platform/control-plane/operator-contract-schemas-control.d.ts.map +1 -1
  145. package/dist/_internal/platform/control-plane/operator-contract-schemas-control.js +26 -0
  146. package/dist/_internal/platform/control-plane/routes/operator.d.ts +1 -1
  147. package/dist/_internal/platform/control-plane/routes/operator.d.ts.map +1 -1
  148. package/dist/_internal/platform/control-plane/routes/operator.js +2 -0
  149. package/dist/_internal/platform/control-plane/types.d.ts +1 -1
  150. package/dist/_internal/platform/control-plane/types.d.ts.map +1 -1
  151. package/dist/_internal/platform/daemon/control-plane.d.ts.map +1 -1
  152. package/dist/_internal/platform/daemon/control-plane.js +50 -6
  153. package/dist/_internal/platform/daemon/facade-composition.d.ts.map +1 -1
  154. package/dist/_internal/platform/daemon/facade-composition.js +30 -2
  155. package/dist/_internal/platform/daemon/facade-types.d.ts +1 -1
  156. package/dist/_internal/platform/daemon/facade-types.d.ts.map +1 -1
  157. package/dist/_internal/platform/daemon/http/cloudflare-routes.d.ts +7 -0
  158. package/dist/_internal/platform/daemon/http/cloudflare-routes.d.ts.map +1 -0
  159. package/dist/_internal/platform/daemon/http/cloudflare-routes.js +201 -0
  160. package/dist/_internal/platform/daemon/http/router.d.ts +3 -3
  161. package/dist/_internal/platform/daemon/http/router.d.ts.map +1 -1
  162. package/dist/_internal/platform/daemon/http/router.js +22 -16
  163. package/dist/_internal/platform/daemon/http/runtime-route-types.d.ts +1 -1
  164. package/dist/_internal/platform/daemon/http/runtime-route-types.d.ts.map +1 -1
  165. package/dist/_internal/platform/daemon/http-listener.d.ts.map +1 -1
  166. package/dist/_internal/platform/daemon/http-listener.js +4 -8
  167. package/dist/_internal/platform/daemon/surface-actions.d.ts +1 -1
  168. package/dist/_internal/platform/daemon/surface-actions.d.ts.map +1 -1
  169. package/dist/_internal/platform/daemon/surface-delivery.d.ts +1 -1
  170. package/dist/_internal/platform/daemon/surface-delivery.d.ts.map +1 -1
  171. package/dist/_internal/platform/daemon/surface-delivery.js +1 -0
  172. package/dist/_internal/platform/daemon/surface-policy.d.ts +1 -1
  173. package/dist/_internal/platform/daemon/surface-policy.d.ts.map +1 -1
  174. package/dist/_internal/platform/daemon/surface-policy.js +8 -0
  175. package/dist/_internal/platform/daemon/types.d.ts +2 -2
  176. package/dist/_internal/platform/daemon/types.d.ts.map +1 -1
  177. package/dist/_internal/platform/integrations/homeassistant.d.ts +58 -0
  178. package/dist/_internal/platform/integrations/homeassistant.d.ts.map +1 -0
  179. package/dist/_internal/platform/integrations/homeassistant.js +174 -0
  180. package/dist/_internal/platform/integrations/index.d.ts +2 -0
  181. package/dist/_internal/platform/integrations/index.d.ts.map +1 -1
  182. package/dist/_internal/platform/integrations/index.js +1 -0
  183. package/dist/_internal/platform/runtime/events/control-plane.d.ts +1 -1
  184. package/dist/_internal/platform/runtime/events/control-plane.d.ts.map +1 -1
  185. package/dist/_internal/platform/runtime/events/control-plane.js +1 -0
  186. package/dist/_internal/platform/runtime/events/routes.d.ts +1 -1
  187. package/dist/_internal/platform/runtime/events/routes.d.ts.map +1 -1
  188. package/dist/_internal/platform/runtime/events/routes.js +1 -0
  189. package/dist/_internal/platform/runtime/feature-flags/flags.d.ts.map +1 -1
  190. package/dist/_internal/platform/runtime/feature-flags/flags.js +9 -0
  191. package/dist/_internal/platform/runtime/feature-flags/gates.d.ts.map +1 -1
  192. package/dist/_internal/platform/runtime/feature-flags/gates.js +2 -0
  193. package/dist/_internal/platform/runtime/index.d.ts +2 -0
  194. package/dist/_internal/platform/runtime/index.d.ts.map +1 -1
  195. package/dist/_internal/platform/runtime/index.js +1 -0
  196. package/dist/_internal/platform/runtime/integration/helpers.d.ts +4 -0
  197. package/dist/_internal/platform/runtime/integration/helpers.d.ts.map +1 -1
  198. package/dist/_internal/platform/runtime/integration/helpers.js +4 -0
  199. package/dist/_internal/platform/runtime/security-settings.d.ts +19 -0
  200. package/dist/_internal/platform/runtime/security-settings.d.ts.map +1 -0
  201. package/dist/_internal/platform/runtime/security-settings.js +187 -0
  202. package/dist/_internal/platform/runtime/services.d.ts.map +1 -1
  203. package/dist/_internal/platform/runtime/services.js +1 -0
  204. package/dist/_internal/platform/security/user-auth.d.ts +1 -1
  205. package/dist/_internal/platform/security/user-auth.d.ts.map +1 -1
  206. package/dist/_internal/platform/security/user-auth.js +18 -3
  207. package/dist/_internal/platform/tools/edit/core.d.ts.map +1 -1
  208. package/dist/_internal/platform/tools/edit/core.js +4 -47
  209. package/dist/_internal/platform/tools/exec/runtime.d.ts.map +1 -1
  210. package/dist/_internal/platform/tools/exec/runtime.js +7 -1
  211. package/dist/_internal/platform/tools/exec/schema.d.ts +1 -0
  212. package/dist/_internal/platform/tools/exec/schema.d.ts.map +1 -1
  213. package/dist/_internal/platform/tools/exec/schema.js +1 -0
  214. package/dist/_internal/platform/tools/fetch/runtime.d.ts.map +1 -1
  215. package/dist/_internal/platform/tools/fetch/runtime.js +140 -19
  216. package/dist/_internal/platform/tools/fetch/schema.d.ts +1 -0
  217. package/dist/_internal/platform/tools/fetch/schema.d.ts.map +1 -1
  218. package/dist/_internal/platform/tools/fetch/schema.js +1 -0
  219. package/dist/_internal/platform/tools/find/executor.d.ts.map +1 -1
  220. package/dist/_internal/platform/tools/find/executor.js +7 -1
  221. package/dist/_internal/platform/tools/find/schema.d.ts.map +1 -1
  222. package/dist/_internal/platform/tools/find/schema.js +2 -0
  223. package/dist/_internal/platform/tools/read/index.d.ts.map +1 -1
  224. package/dist/_internal/platform/tools/read/index.js +7 -1
  225. package/dist/_internal/platform/tools/read/schema.d.ts +1 -0
  226. package/dist/_internal/platform/tools/read/schema.d.ts.map +1 -1
  227. package/dist/_internal/platform/tools/read/schema.js +1 -0
  228. package/dist/_internal/platform/tools/shared/process-manager.d.ts +2 -0
  229. package/dist/_internal/platform/tools/shared/process-manager.d.ts.map +1 -1
  230. package/dist/_internal/platform/tools/shared/process-manager.js +67 -5
  231. package/dist/_internal/platform/tools/write/index.d.ts.map +1 -1
  232. package/dist/_internal/platform/tools/write/index.js +3 -36
  233. package/dist/_internal/platform/utils/concurrency.d.ts +3 -0
  234. package/dist/_internal/platform/utils/concurrency.d.ts.map +1 -0
  235. package/dist/_internal/platform/utils/concurrency.js +17 -0
  236. package/dist/_internal/platform/utils/logger.d.ts.map +1 -1
  237. package/dist/_internal/platform/utils/logger.js +19 -1
  238. package/dist/_internal/platform/utils/request-body.d.ts +4 -0
  239. package/dist/_internal/platform/utils/request-body.d.ts.map +1 -0
  240. package/dist/_internal/platform/utils/request-body.js +45 -0
  241. package/dist/_internal/platform/version.js +1 -1
  242. package/dist/workers.d.ts +9 -0
  243. package/dist/workers.d.ts.map +1 -1
  244. package/dist/workers.js +67 -3
  245. package/package.json +2 -1
@@ -23,17 +23,22 @@ import { randomUUID } from 'node:crypto';
23
23
  import { ConversationManager } from '../core/conversation.js';
24
24
  import { CompanionChatPersistence, defaultSessionsDir, } from './companion-chat-persistence.js';
25
25
  import { CompanionChatRateLimiter } from './companion-chat-rate-limiter.js';
26
+ import { executeToolCalls as executeOrchestratorToolCalls } from '../core/orchestrator-tool-runtime.js';
26
27
  // ---------------------------------------------------------------------------
27
28
  // Idle GC constants (customisable for tests)
28
29
  // ---------------------------------------------------------------------------
29
30
  const DEFAULT_IDLE_ACTIVE_MS = 30 * 60 * 1_000; // 30 minutes with messages
30
31
  const DEFAULT_IDLE_EMPTY_MS = 5 * 60 * 1_000; // 5 minutes empty session
31
32
  const GC_INTERVAL_MS = 60 * 1_000; // sweep every minute
33
+ const MAX_TOOL_ROUNDS_PER_TURN = 8;
32
34
  export class CompanionChatManager {
33
35
  sessions = new Map();
34
36
  provider;
35
37
  eventPublisher;
36
38
  toolRegistry;
39
+ permissionManager;
40
+ hookDispatcher;
41
+ runtimeBus;
37
42
  persistence;
38
43
  rateLimiter;
39
44
  idleActiveMs;
@@ -52,6 +57,9 @@ export class CompanionChatManager {
52
57
  this.provider = config.provider;
53
58
  this.eventPublisher = config.eventPublisher;
54
59
  this.toolRegistry = config.toolRegistry ?? null;
60
+ this.permissionManager = config.permissionManager ?? null;
61
+ this.hookDispatcher = config.hookDispatcher ?? null;
62
+ this.runtimeBus = config.runtimeBus ?? null;
55
63
  this.idleActiveMs = config.idleActiveMs ?? DEFAULT_IDLE_ACTIVE_MS;
56
64
  this.idleEmptyMs = config.idleEmptyMs ?? DEFAULT_IDLE_EMPTY_MS;
57
65
  // Persistence
@@ -309,91 +317,82 @@ export class CompanionChatManager {
309
317
  let assistantContent = '';
310
318
  const assistantMessageId = randomUUID();
311
319
  try {
312
- const messages = session.conversation.getMessagesForLLM();
313
- // Convert ProviderMessage[] to our minimal interface
314
- const chatMessages = messages.map((m) => ({
315
- role: m.role === 'user' ? 'user' : 'assistant',
316
- content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content),
317
- }));
318
- const stream = this.provider.chatStream(chatMessages, {
319
- systemPrompt: session.meta.systemPrompt,
320
- model: session.meta.model,
321
- provider: session.meta.provider,
322
- abortSignal,
323
- });
324
- for await (const chunk of stream) {
325
- if (abortSignal.aborted)
326
- break;
327
- switch (chunk.type) {
328
- case 'text_delta': {
329
- const delta = chunk.delta ?? '';
330
- assistantContent += delta;
331
- publish({ type: 'turn.delta', sessionId, turnId, delta });
320
+ const toolDefinitions = this.toolRegistry?.getToolDefinitions() ?? [];
321
+ let completed = false;
322
+ for (let round = 0; round < MAX_TOOL_ROUNDS_PER_TURN; round++) {
323
+ const stream = this.provider.chatStream([...session.conversation.getMessagesForLLM()], {
324
+ systemPrompt: session.meta.systemPrompt,
325
+ model: session.meta.model,
326
+ provider: session.meta.provider,
327
+ tools: toolDefinitions,
328
+ abortSignal,
329
+ });
330
+ let roundAssistantContent = '';
331
+ const toolCalls = [];
332
+ for await (const chunk of stream) {
333
+ if (abortSignal.aborted)
332
334
  break;
333
- }
334
- case 'tool_call': {
335
- publish({
336
- type: 'turn.tool_call',
337
- sessionId,
338
- turnId,
339
- toolCallId: chunk.toolCallId ?? '',
340
- toolName: chunk.toolName ?? '',
341
- toolInput: chunk.toolInput ?? null,
342
- });
343
- // Execute via ToolRegistry if available
344
- if (this.toolRegistry && chunk.toolName && chunk.toolCallId) {
345
- const toolCallId = chunk.toolCallId;
346
- const toolName = chunk.toolName;
335
+ switch (chunk.type) {
336
+ case 'text_delta': {
337
+ const delta = chunk.delta ?? '';
338
+ roundAssistantContent += delta;
339
+ assistantContent += delta;
340
+ publish({ type: 'turn.delta', sessionId, turnId, delta });
341
+ break;
342
+ }
343
+ case 'tool_call': {
344
+ const toolCallId = chunk.toolCallId ?? '';
345
+ const toolName = chunk.toolName ?? '';
347
346
  const toolInput = (chunk.toolInput ?? {});
348
- try {
349
- const toolResult = await this.toolRegistry.execute(toolCallId, toolName, toolInput);
350
- publish({
351
- type: 'turn.tool_result',
352
- sessionId,
353
- turnId,
354
- toolCallId,
355
- toolName,
356
- result: toolResult.output ?? null,
357
- isError: !toolResult.success,
358
- });
359
- }
360
- catch (toolErr) {
361
- const errMsg = toolErr instanceof Error ? toolErr.message : String(toolErr);
362
- publish({
363
- type: 'turn.tool_result',
364
- sessionId,
365
- turnId,
366
- toolCallId,
367
- toolName,
368
- result: errMsg,
369
- isError: true,
370
- });
347
+ publish({
348
+ type: 'turn.tool_call',
349
+ sessionId,
350
+ turnId,
351
+ toolCallId,
352
+ toolName,
353
+ toolInput,
354
+ });
355
+ if (toolCallId && toolName) {
356
+ toolCalls.push({ id: toolCallId, name: toolName, arguments: toolInput });
371
357
  }
358
+ break;
372
359
  }
373
- break;
374
- }
375
- case 'tool_result': {
376
- publish({
377
- type: 'turn.tool_result',
378
- sessionId,
379
- turnId,
380
- toolCallId: chunk.toolCallId ?? '',
381
- toolName: chunk.toolName ?? '',
382
- result: chunk.result ?? null,
383
- isError: chunk.isError ?? false,
384
- });
385
- break;
386
- }
387
- case 'error': {
388
- throw new Error(chunk.error ?? 'Provider streaming error');
360
+ case 'tool_result': {
361
+ publish({
362
+ type: 'turn.tool_result',
363
+ sessionId,
364
+ turnId,
365
+ toolCallId: chunk.toolCallId ?? '',
366
+ toolName: chunk.toolName ?? '',
367
+ result: chunk.result ?? null,
368
+ isError: chunk.isError ?? false,
369
+ });
370
+ break;
371
+ }
372
+ case 'error': {
373
+ throw new Error(chunk.error ?? 'Provider streaming error');
374
+ }
375
+ case 'done':
376
+ break;
389
377
  }
390
- case 'done':
391
- break;
392
378
  }
379
+ if (abortSignal.aborted)
380
+ break;
381
+ if (toolCalls.length === 0) {
382
+ session.conversation.addAssistantMessage(roundAssistantContent);
383
+ completed = true;
384
+ break;
385
+ }
386
+ session.conversation.addAssistantMessage(roundAssistantContent, { toolCalls });
387
+ if (!this.toolRegistry) {
388
+ completed = true;
389
+ break;
390
+ }
391
+ const toolResults = await this._executeToolCalls(toolCalls, publish, sessionId, turnId);
392
+ session.conversation.addToolResults(toolResults);
393
393
  }
394
- // Append assistant reply to conversation
395
- if (assistantContent) {
396
- session.conversation.addAssistantMessage(assistantContent);
394
+ if (!completed && !abortSignal.aborted) {
395
+ throw new Error(`Companion chat exceeded ${MAX_TOOL_ROUNDS_PER_TURN} tool rounds without a final response`);
397
396
  }
398
397
  const now = Date.now();
399
398
  const assistantMsg = {
@@ -429,6 +428,57 @@ export class CompanionChatManager {
429
428
  }
430
429
  }
431
430
  }
431
+ async _executeToolCalls(toolCalls, publish, sessionId, turnId) {
432
+ const toolRegistry = this.toolRegistry;
433
+ if (!toolRegistry)
434
+ return [];
435
+ if (!this.permissionManager) {
436
+ return toolCalls.map((call) => {
437
+ const toolResult = {
438
+ callId: call.id,
439
+ success: false,
440
+ error: 'Tool execution denied: permission manager unavailable for companion chat',
441
+ };
442
+ publish({
443
+ type: 'turn.tool_result',
444
+ sessionId,
445
+ turnId,
446
+ toolCallId: call.id,
447
+ toolName: call.name,
448
+ result: toolResult.error,
449
+ isError: true,
450
+ });
451
+ return toolResult;
452
+ });
453
+ }
454
+ const results = await executeOrchestratorToolCalls({
455
+ toolRegistry,
456
+ permissionManager: this.permissionManager,
457
+ hookDispatcher: this.hookDispatcher,
458
+ runtimeBus: this.runtimeBus,
459
+ sessionId,
460
+ emitterContext: (id) => ({
461
+ sessionId,
462
+ traceId: `${sessionId}:${id}`,
463
+ source: 'companion-chat',
464
+ }),
465
+ }, turnId, toolCalls);
466
+ for (const [index, toolResult] of results.entries()) {
467
+ const call = toolCalls[index];
468
+ if (!call)
469
+ continue;
470
+ publish({
471
+ type: 'turn.tool_result',
472
+ sessionId,
473
+ turnId,
474
+ toolCallId: call.id,
475
+ toolName: call.name,
476
+ result: toolResult.output ?? toolResult.error ?? null,
477
+ isError: !toolResult.success,
478
+ });
479
+ }
480
+ return results;
481
+ }
432
482
  // ---------------------------------------------------------------------------
433
483
  // GC sweep
434
484
  // ---------------------------------------------------------------------------
@@ -21,10 +21,34 @@ export declare const runtimeConfigDefaults: {
21
21
  cloudflare: {
22
22
  enabled: boolean;
23
23
  freeTierMode: boolean;
24
+ accountId: string;
25
+ apiTokenRef: string;
26
+ zoneId: string;
27
+ zoneName: string;
28
+ workerName: string;
29
+ workerSubdomain: string;
30
+ workerHostname: string;
24
31
  workerBaseUrl: string;
32
+ daemonBaseUrl: string;
33
+ daemonHostname: string;
25
34
  workerTokenRef: string;
35
+ workerClientTokenRef: string;
36
+ workerCron: string;
26
37
  queueName: string;
27
38
  deadLetterQueueName: string;
39
+ tunnelName: string;
40
+ tunnelId: string;
41
+ tunnelTokenRef: string;
42
+ accessAppId: string;
43
+ accessServiceTokenId: string;
44
+ accessServiceTokenRef: string;
45
+ kvNamespaceName: string;
46
+ kvNamespaceId: string;
47
+ durableObjectNamespaceName: string;
48
+ durableObjectNamespaceId: string;
49
+ r2BucketName: string;
50
+ secretsStoreName: string;
51
+ secretsStoreId: string;
28
52
  maxQueueOpsPerDay: number;
29
53
  };
30
54
  telemetry: {
@@ -1 +1 @@
1
- {"version":3,"file":"schema-domain-runtime.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/config/schema-domain-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmGjC,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,uBAAuB,EAyMjE,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,uBAAuB,EA8NnE,CAAC"}
1
+ {"version":3,"file":"schema-domain-runtime.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/config/schema-domain-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2HjC,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,uBAAuB,EAyMjE,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,uBAAuB,EA+WnE,CAAC"}
@@ -20,10 +20,34 @@ export const runtimeConfigDefaults = {
20
20
  cloudflare: {
21
21
  enabled: false,
22
22
  freeTierMode: true,
23
+ accountId: '',
24
+ apiTokenRef: '',
25
+ zoneId: '',
26
+ zoneName: '',
27
+ workerName: 'goodvibes-batch-worker',
28
+ workerSubdomain: '',
29
+ workerHostname: '',
23
30
  workerBaseUrl: '',
31
+ daemonBaseUrl: '',
32
+ daemonHostname: '',
24
33
  workerTokenRef: '',
34
+ workerClientTokenRef: '',
35
+ workerCron: '*/5 * * * *',
25
36
  queueName: 'goodvibes-batch',
26
37
  deadLetterQueueName: 'goodvibes-batch-dlq',
38
+ tunnelName: 'goodvibes-daemon',
39
+ tunnelId: '',
40
+ tunnelTokenRef: '',
41
+ accessAppId: '',
42
+ accessServiceTokenId: '',
43
+ accessServiceTokenRef: '',
44
+ kvNamespaceName: 'goodvibes-runtime',
45
+ kvNamespaceId: '',
46
+ durableObjectNamespaceName: 'GoodVibesCoordinator',
47
+ durableObjectNamespaceId: '',
48
+ r2BucketName: 'goodvibes-artifacts',
49
+ secretsStoreName: 'goodvibes',
50
+ secretsStoreId: '',
27
51
  maxQueueOpsPerDay: 10_000,
28
52
  },
29
53
  telemetry: {
@@ -488,18 +512,85 @@ export const runtimeSecondaryConfigSettings = [
488
512
  default: true,
489
513
  description: 'Prefer Cloudflare usage patterns that fit the free tier: small queue signals, local daemon storage, and bounded daily queue volume',
490
514
  },
515
+ {
516
+ key: 'cloudflare.accountId',
517
+ type: 'string',
518
+ default: '',
519
+ description: 'Cloudflare account id used by SDK-owned Worker/Queue provisioning',
520
+ },
521
+ {
522
+ key: 'cloudflare.apiTokenRef',
523
+ type: 'string',
524
+ default: '',
525
+ description: 'GoodVibes secret reference for the Cloudflare API token. If empty, the SDK falls back to CLOUDFLARE_API_TOKEN.',
526
+ },
527
+ {
528
+ key: 'cloudflare.zoneId',
529
+ type: 'string',
530
+ default: '',
531
+ description: 'Optional Cloudflare zone id selected for SDK-managed DNS and Zero Trust Access hostnames',
532
+ },
533
+ {
534
+ key: 'cloudflare.zoneName',
535
+ type: 'string',
536
+ default: '',
537
+ description: 'Optional Cloudflare zone name selected during discovery/onboarding when zone id is not known yet',
538
+ },
539
+ {
540
+ key: 'cloudflare.workerName',
541
+ type: 'string',
542
+ default: 'goodvibes-batch-worker',
543
+ description: 'Cloudflare Worker script name managed by GoodVibes provisioning',
544
+ validate: (v) => typeof v === 'string' && (/^[a-z0-9][a-z0-9-]{0,62}$/i.test(v) || v === ''),
545
+ },
546
+ {
547
+ key: 'cloudflare.workerSubdomain',
548
+ type: 'string',
549
+ default: '',
550
+ description: 'Cloudflare account workers.dev subdomain used to infer cloudflare.workerBaseUrl',
551
+ },
552
+ {
553
+ key: 'cloudflare.workerHostname',
554
+ type: 'string',
555
+ default: '',
556
+ description: 'Optional custom hostname for the GoodVibes Cloudflare Worker when DNS automation is enabled',
557
+ },
491
558
  {
492
559
  key: 'cloudflare.workerBaseUrl',
493
560
  type: 'string',
494
561
  default: '',
495
562
  description: 'Optional deployed GoodVibes Cloudflare Worker base URL used by clients that proxy batch signals through Workers',
496
563
  },
564
+ {
565
+ key: 'cloudflare.daemonBaseUrl',
566
+ type: 'string',
567
+ default: '',
568
+ description: 'Daemon origin URL the Cloudflare Worker or Tunnel uses for Worker-to-daemon batch calls',
569
+ },
570
+ {
571
+ key: 'cloudflare.daemonHostname',
572
+ type: 'string',
573
+ default: '',
574
+ description: 'Optional public daemon hostname managed through Cloudflare DNS, Tunnel, and Access provisioning',
575
+ },
497
576
  {
498
577
  key: 'cloudflare.workerTokenRef',
499
578
  type: 'string',
500
579
  default: '',
501
580
  description: 'Optional GoodVibes secret reference for the Worker-to-daemon bearer token',
502
581
  },
582
+ {
583
+ key: 'cloudflare.workerClientTokenRef',
584
+ type: 'string',
585
+ default: '',
586
+ description: 'Optional GoodVibes secret reference for the bearer token clients use when calling the Cloudflare Worker',
587
+ },
588
+ {
589
+ key: 'cloudflare.workerCron',
590
+ type: 'string',
591
+ default: '*/5 * * * *',
592
+ description: 'Cron trigger installed on the GoodVibes Cloudflare Worker for batch scheduler ticks',
593
+ },
503
594
  {
504
595
  key: 'cloudflare.queueName',
505
596
  type: 'string',
@@ -512,6 +603,84 @@ export const runtimeSecondaryConfigSettings = [
512
603
  default: 'goodvibes-batch-dlq',
513
604
  description: 'Cloudflare dead-letter queue binding/name for failed GoodVibes batch job signals',
514
605
  },
606
+ {
607
+ key: 'cloudflare.tunnelName',
608
+ type: 'string',
609
+ default: 'goodvibes-daemon',
610
+ description: 'Zero Trust Tunnel name managed by GoodVibes provisioning when tunnel integration is enabled',
611
+ },
612
+ {
613
+ key: 'cloudflare.tunnelId',
614
+ type: 'string',
615
+ default: '',
616
+ description: 'Cloudflare Zero Trust Tunnel id selected or created by GoodVibes provisioning',
617
+ },
618
+ {
619
+ key: 'cloudflare.tunnelTokenRef',
620
+ type: 'string',
621
+ default: '',
622
+ description: 'GoodVibes secret reference for the cloudflared tunnel token generated by provisioning',
623
+ },
624
+ {
625
+ key: 'cloudflare.accessAppId',
626
+ type: 'string',
627
+ default: '',
628
+ description: 'Cloudflare Zero Trust Access application id protecting the GoodVibes daemon hostname',
629
+ },
630
+ {
631
+ key: 'cloudflare.accessServiceTokenId',
632
+ type: 'string',
633
+ default: '',
634
+ description: 'Cloudflare Zero Trust Access service token id created for GoodVibes daemon access',
635
+ },
636
+ {
637
+ key: 'cloudflare.accessServiceTokenRef',
638
+ type: 'string',
639
+ default: '',
640
+ description: 'GoodVibes secret reference storing Access service token client id/secret JSON',
641
+ },
642
+ {
643
+ key: 'cloudflare.kvNamespaceName',
644
+ type: 'string',
645
+ default: 'goodvibes-runtime',
646
+ description: 'Cloudflare KV namespace name used for optional edge runtime state',
647
+ },
648
+ {
649
+ key: 'cloudflare.kvNamespaceId',
650
+ type: 'string',
651
+ default: '',
652
+ description: 'Cloudflare KV namespace id used for the GoodVibes Worker binding',
653
+ },
654
+ {
655
+ key: 'cloudflare.durableObjectNamespaceName',
656
+ type: 'string',
657
+ default: 'GoodVibesCoordinator',
658
+ description: 'Cloudflare Durable Object class/namespace name used for optional edge coordination',
659
+ },
660
+ {
661
+ key: 'cloudflare.durableObjectNamespaceId',
662
+ type: 'string',
663
+ default: '',
664
+ description: 'Cloudflare Durable Object namespace id discovered after Worker migration',
665
+ },
666
+ {
667
+ key: 'cloudflare.r2BucketName',
668
+ type: 'string',
669
+ default: 'goodvibes-artifacts',
670
+ description: 'Cloudflare R2 Standard bucket name used for optional GoodVibes artifacts',
671
+ },
672
+ {
673
+ key: 'cloudflare.secretsStoreName',
674
+ type: 'string',
675
+ default: 'goodvibes',
676
+ description: 'Cloudflare Secrets Store name managed by optional GoodVibes provisioning',
677
+ },
678
+ {
679
+ key: 'cloudflare.secretsStoreId',
680
+ type: 'string',
681
+ default: '',
682
+ description: 'Cloudflare Secrets Store id selected or created by GoodVibes provisioning',
683
+ },
515
684
  {
516
685
  key: 'cloudflare.maxQueueOpsPerDay',
517
686
  type: 'number',
@@ -36,6 +36,17 @@ export declare const surfaceConfigDefaults: {
36
36
  secret: string;
37
37
  setupVersion: number;
38
38
  };
39
+ homeassistant: {
40
+ enabled: boolean;
41
+ instanceUrl: string;
42
+ accessToken: string;
43
+ webhookSecret: string;
44
+ defaultConversationId: string;
45
+ deviceId: string;
46
+ deviceName: string;
47
+ eventType: string;
48
+ setupVersion: number;
49
+ };
39
50
  telegram: {
40
51
  enabled: boolean;
41
52
  botToken: string;
@@ -1 +1 @@
1
- {"version":3,"file":"schema-domain-surfaces.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/config/schema-domain-surfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoHjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,uBAAuB,EAmU1D,CAAC"}
1
+ {"version":3,"file":"schema-domain-surfaces.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/config/schema-domain-surfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+HjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,uBAAuB,EAmX1D,CAAC"}
@@ -35,6 +35,17 @@ export const surfaceConfigDefaults = {
35
35
  secret: '',
36
36
  setupVersion: 0,
37
37
  },
38
+ homeassistant: {
39
+ enabled: false,
40
+ instanceUrl: '',
41
+ accessToken: '',
42
+ webhookSecret: '',
43
+ defaultConversationId: 'goodvibes',
44
+ deviceId: 'goodvibes-daemon',
45
+ deviceName: 'GoodVibes Daemon',
46
+ eventType: 'goodvibes_message',
47
+ setupVersion: 0,
48
+ },
38
49
  telegram: {
39
50
  enabled: false,
40
51
  botToken: '',
@@ -262,6 +273,54 @@ export const surfaceConfigSettings = [
262
273
  default: '',
263
274
  description: 'Shared secret used to sign or verify webhook payloads',
264
275
  },
276
+ {
277
+ key: 'surfaces.homeassistant.enabled',
278
+ type: 'boolean',
279
+ default: false,
280
+ description: 'Enable the Home Assistant daemon surface',
281
+ },
282
+ {
283
+ key: 'surfaces.homeassistant.instanceUrl',
284
+ type: 'string',
285
+ default: '',
286
+ description: 'Home Assistant base URL, for example http://homeassistant.local:8123',
287
+ },
288
+ {
289
+ key: 'surfaces.homeassistant.accessToken',
290
+ type: 'string',
291
+ default: '',
292
+ description: 'Home Assistant long-lived access token or goodvibes secret URI',
293
+ },
294
+ {
295
+ key: 'surfaces.homeassistant.webhookSecret',
296
+ type: 'string',
297
+ default: '',
298
+ description: 'Shared secret used to verify inbound Home Assistant callbacks',
299
+ },
300
+ {
301
+ key: 'surfaces.homeassistant.defaultConversationId',
302
+ type: 'string',
303
+ default: 'goodvibes',
304
+ description: 'Default Home Assistant conversation id used for route binding',
305
+ },
306
+ {
307
+ key: 'surfaces.homeassistant.deviceId',
308
+ type: 'string',
309
+ default: 'goodvibes-daemon',
310
+ description: 'Stable Home Assistant device identifier for this daemon',
311
+ },
312
+ {
313
+ key: 'surfaces.homeassistant.deviceName',
314
+ type: 'string',
315
+ default: 'GoodVibes Daemon',
316
+ description: 'Home Assistant device display name for this daemon',
317
+ },
318
+ {
319
+ key: 'surfaces.homeassistant.eventType',
320
+ type: 'string',
321
+ default: 'goodvibes_message',
322
+ description: 'Home Assistant event type used for daemon-to-Home Assistant deliveries',
323
+ },
265
324
  {
266
325
  key: 'surfaces.telegram.enabled',
267
326
  type: 'boolean',