@synergenius/flowweaver-pack-weaver 0.6.1 → 0.7.1

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 (170) hide show
  1. package/dist/bot/ai-client.d.ts +1 -0
  2. package/dist/bot/ai-client.d.ts.map +1 -1
  3. package/dist/bot/ai-client.js +52 -1
  4. package/dist/bot/ai-client.js.map +1 -1
  5. package/dist/bot/audit-logger.d.ts +5 -0
  6. package/dist/bot/audit-logger.d.ts.map +1 -0
  7. package/dist/bot/audit-logger.js +42 -0
  8. package/dist/bot/audit-logger.js.map +1 -0
  9. package/dist/bot/audit-store.d.ts +13 -0
  10. package/dist/bot/audit-store.d.ts.map +1 -0
  11. package/dist/bot/audit-store.js +59 -0
  12. package/dist/bot/audit-store.js.map +1 -0
  13. package/dist/bot/cli-provider.d.ts +1 -0
  14. package/dist/bot/cli-provider.d.ts.map +1 -1
  15. package/dist/bot/cli-provider.js +86 -22
  16. package/dist/bot/cli-provider.js.map +1 -1
  17. package/dist/bot/cli-stream-parser.d.ts +11 -0
  18. package/dist/bot/cli-stream-parser.d.ts.map +1 -0
  19. package/dist/bot/cli-stream-parser.js +53 -0
  20. package/dist/bot/cli-stream-parser.js.map +1 -0
  21. package/dist/bot/file-validator.d.ts +1 -1
  22. package/dist/bot/file-validator.d.ts.map +1 -1
  23. package/dist/bot/file-validator.js +13 -27
  24. package/dist/bot/file-validator.js.map +1 -1
  25. package/dist/bot/fw-api.d.ts +8 -0
  26. package/dist/bot/fw-api.d.ts.map +1 -0
  27. package/dist/bot/fw-api.js +12 -0
  28. package/dist/bot/fw-api.js.map +1 -0
  29. package/dist/bot/runner.d.ts +2 -1
  30. package/dist/bot/runner.d.ts.map +1 -1
  31. package/dist/bot/runner.js +8 -0
  32. package/dist/bot/runner.js.map +1 -1
  33. package/dist/bot/step-executor.d.ts +3 -2
  34. package/dist/bot/step-executor.d.ts.map +1 -1
  35. package/dist/bot/step-executor.js +9 -30
  36. package/dist/bot/step-executor.js.map +1 -1
  37. package/dist/bot/system-prompt.d.ts +13 -1
  38. package/dist/bot/system-prompt.d.ts.map +1 -1
  39. package/dist/bot/system-prompt.js +28 -22
  40. package/dist/bot/system-prompt.js.map +1 -1
  41. package/dist/bot/types.d.ts +9 -1
  42. package/dist/bot/types.d.ts.map +1 -1
  43. package/dist/cli-bridge.d.ts.map +1 -1
  44. package/dist/cli-bridge.js +2 -1
  45. package/dist/cli-bridge.js.map +1 -1
  46. package/dist/cli-handlers.d.ts +2 -1
  47. package/dist/cli-handlers.d.ts.map +1 -1
  48. package/dist/cli-handlers.js +69 -0
  49. package/dist/cli-handlers.js.map +1 -1
  50. package/dist/node-types/approval-gate.d.ts.map +1 -1
  51. package/dist/node-types/approval-gate.js +24 -0
  52. package/dist/node-types/approval-gate.js.map +1 -1
  53. package/dist/node-types/exec-validate-retry.d.ts.map +1 -1
  54. package/dist/node-types/exec-validate-retry.js +10 -4
  55. package/dist/node-types/exec-validate-retry.js.map +1 -1
  56. package/dist/node-types/execute-plan.js +1 -1
  57. package/dist/node-types/execute-plan.js.map +1 -1
  58. package/dist/node-types/git-ops.d.ts.map +1 -1
  59. package/dist/node-types/git-ops.js +2 -0
  60. package/dist/node-types/git-ops.js.map +1 -1
  61. package/dist/node-types/plan-task.d.ts.map +1 -1
  62. package/dist/node-types/plan-task.js +9 -1
  63. package/dist/node-types/plan-task.js.map +1 -1
  64. package/dist/node-types/send-notify.d.ts.map +1 -1
  65. package/dist/node-types/send-notify.js +4 -1
  66. package/dist/node-types/send-notify.js.map +1 -1
  67. package/dist/node-types/validate-result.d.ts +2 -2
  68. package/dist/node-types/validate-result.d.ts.map +1 -1
  69. package/dist/node-types/validate-result.js +2 -2
  70. package/dist/node-types/validate-result.js.map +1 -1
  71. package/dist/templates/weaver-bot-template.js +1 -1
  72. package/dist/templates/weaver-bot-template.js.map +1 -1
  73. package/dist/workflows/weaver-bot-batch.d.ts +4 -1
  74. package/dist/workflows/weaver-bot-batch.d.ts.map +1 -1
  75. package/dist/workflows/weaver-bot-batch.js +1 -1
  76. package/dist/workflows/weaver-bot-batch.js.map +1 -1
  77. package/dist/workflows/weaver-bot.d.ts +4 -1
  78. package/dist/workflows/weaver-bot.d.ts.map +1 -1
  79. package/dist/workflows/weaver-bot.js +1 -1
  80. package/dist/workflows/weaver-bot.js.map +1 -1
  81. package/flowweaver.manifest.json +23 -1
  82. package/package.json +3 -2
  83. package/src/bot/agent-provider.ts +273 -0
  84. package/src/bot/ai-client.ts +109 -0
  85. package/src/bot/approvals.ts +273 -0
  86. package/src/bot/audit-logger.ts +45 -0
  87. package/src/bot/audit-store.ts +69 -0
  88. package/src/bot/bot-agent-channel.ts +99 -0
  89. package/src/bot/cli-provider.ts +169 -0
  90. package/src/bot/cli-stream-parser.ts +59 -0
  91. package/src/bot/cost-store.ts +92 -0
  92. package/src/bot/cost-tracker.ts +72 -0
  93. package/src/bot/cron-parser.ts +153 -0
  94. package/src/bot/cron-scheduler.ts +48 -0
  95. package/src/bot/dashboard.ts +658 -0
  96. package/src/bot/design-checker.ts +327 -0
  97. package/src/bot/file-lock.ts +73 -0
  98. package/src/bot/file-validator.ts +41 -0
  99. package/src/bot/file-watcher.ts +103 -0
  100. package/src/bot/fw-api.ts +18 -0
  101. package/src/bot/genesis-prompt-context.ts +135 -0
  102. package/src/bot/genesis-store.ts +180 -0
  103. package/src/bot/index.ts +127 -0
  104. package/src/bot/notifications.ts +263 -0
  105. package/src/bot/pipeline-runner.ts +324 -0
  106. package/src/bot/provider-registry.ts +236 -0
  107. package/src/bot/run-store.ts +169 -0
  108. package/src/bot/runner.ts +311 -0
  109. package/src/bot/session-state.ts +73 -0
  110. package/src/bot/steering.ts +44 -0
  111. package/src/bot/step-executor.ts +34 -0
  112. package/src/bot/system-prompt.ts +280 -0
  113. package/src/bot/task-queue.ts +111 -0
  114. package/src/bot/types.ts +571 -0
  115. package/src/bot/utils.ts +17 -0
  116. package/src/bot/watch-daemon.ts +203 -0
  117. package/src/bot/web-approval.ts +240 -0
  118. package/src/cli-bridge.ts +41 -0
  119. package/src/cli-handlers.ts +1271 -0
  120. package/src/docs/weaver-config.md +135 -0
  121. package/src/index.ts +173 -0
  122. package/src/mcp-tools.ts +274 -0
  123. package/src/node-types/abort-task.ts +31 -0
  124. package/src/node-types/approval-gate.ts +95 -0
  125. package/src/node-types/bot-report.ts +82 -0
  126. package/src/node-types/build-context.ts +65 -0
  127. package/src/node-types/detect-provider.ts +75 -0
  128. package/src/node-types/exec-validate-retry.ts +175 -0
  129. package/src/node-types/execute-plan.ts +130 -0
  130. package/src/node-types/execute-target.ts +267 -0
  131. package/src/node-types/fix-errors.ts +68 -0
  132. package/src/node-types/genesis-apply-retry.ts +138 -0
  133. package/src/node-types/genesis-apply.ts +96 -0
  134. package/src/node-types/genesis-approve.ts +73 -0
  135. package/src/node-types/genesis-check-stabilize.ts +37 -0
  136. package/src/node-types/genesis-check-threshold.ts +34 -0
  137. package/src/node-types/genesis-commit.ts +71 -0
  138. package/src/node-types/genesis-compile-validate.ts +77 -0
  139. package/src/node-types/genesis-diff-fingerprint.ts +67 -0
  140. package/src/node-types/genesis-diff-workflow.ts +71 -0
  141. package/src/node-types/genesis-escrow-grace.ts +62 -0
  142. package/src/node-types/genesis-escrow-migrate.ts +138 -0
  143. package/src/node-types/genesis-escrow-recover.ts +99 -0
  144. package/src/node-types/genesis-escrow-stage.ts +104 -0
  145. package/src/node-types/genesis-escrow-validate.ts +120 -0
  146. package/src/node-types/genesis-load-config.ts +44 -0
  147. package/src/node-types/genesis-observe.ts +119 -0
  148. package/src/node-types/genesis-propose.ts +97 -0
  149. package/src/node-types/genesis-report.ts +95 -0
  150. package/src/node-types/genesis-snapshot.ts +30 -0
  151. package/src/node-types/genesis-try-apply.ts +165 -0
  152. package/src/node-types/genesis-update-history.ts +72 -0
  153. package/src/node-types/genesis-validate-proposal.ts +124 -0
  154. package/src/node-types/git-ops.ts +72 -0
  155. package/src/node-types/index.ts +36 -0
  156. package/src/node-types/load-config.ts +27 -0
  157. package/src/node-types/plan-task.ts +77 -0
  158. package/src/node-types/read-workflow.ts +68 -0
  159. package/src/node-types/receive-task.ts +92 -0
  160. package/src/node-types/report.ts +25 -0
  161. package/src/node-types/resolve-target.ts +64 -0
  162. package/src/node-types/route-task.ts +25 -0
  163. package/src/node-types/send-notify.ts +75 -0
  164. package/src/node-types/validate-result.ts +49 -0
  165. package/src/templates/index.ts +5 -0
  166. package/src/templates/weaver-bot-template.ts +106 -0
  167. package/src/workflows/genesis-task.ts +91 -0
  168. package/src/workflows/index.ts +3 -0
  169. package/src/workflows/weaver-bot-batch.ts +65 -0
  170. package/src/workflows/weaver-bot.ts +79 -0
@@ -38,7 +38,10 @@
38
38
  * @returns onFailure [order:-1] [hidden] - On Failure
39
39
  * @returns summary [order:0] - Summary text
40
40
  */
41
- export declare function weaverBotBatch(execute: boolean, taskJson?: string, projectDir?: string, __abortSignal__?: AbortSignal): Promise<{
41
+ export declare function weaverBotBatch(execute: boolean, params: {
42
+ taskJson?: string;
43
+ projectDir?: string;
44
+ }, __abortSignal__?: AbortSignal): Promise<{
42
45
  onSuccess: boolean;
43
46
  onFailure: boolean;
44
47
  summary: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"weaver-bot-batch.d.ts","sourceRoot":"","sources":["../../src/workflows/weaver-bot-batch.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,WAAW,GAC5B,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAK7E"}
1
+ {"version":3,"file":"weaver-bot-batch.d.ts","sourceRoot":"","sources":["../../src/workflows/weaver-bot-batch.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAClD,eAAe,CAAC,EAAE,WAAW,GAC5B,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAK7E"}
@@ -40,7 +40,7 @@
40
40
  * @returns onFailure [order:-1] [hidden] - On Failure
41
41
  * @returns summary [order:0] - Summary text
42
42
  */
43
- export async function weaverBotBatch(execute, taskJson, projectDir, __abortSignal__) {
43
+ export async function weaverBotBatch(execute, params, __abortSignal__) {
44
44
  // @flow-weaver-body-start
45
45
  // (auto-generated by compiler)
46
46
  // @flow-weaver-body-end
@@ -1 +1 @@
1
- {"version":3,"file":"weaver-bot-batch.js","sourceRoot":"","sources":["../../src/workflows/weaver-bot-batch.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,mCAAmC;AAcnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAgB,EAChB,QAAiB,EACjB,UAAmB,EACnB,eAA6B;IAE7B,0BAA0B;IAC1B,+BAA+B;IAC/B,wBAAwB;IACxB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"weaver-bot-batch.js","sourceRoot":"","sources":["../../src/workflows/weaver-bot-batch.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,mCAAmC;AAcnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAgB,EAChB,MAAkD,EAClD,eAA6B;IAE7B,0BAA0B;IAC1B,+BAA+B;IAC/B,wBAAwB;IACxB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC9D,CAAC"}
@@ -50,7 +50,10 @@
50
50
  * @returns onFailure [order:-1] [hidden] - On Failure
51
51
  * @returns summary [order:0] - Summary text
52
52
  */
53
- export declare function weaverBot(execute: boolean, taskJson?: string, projectDir?: string, __abortSignal__?: AbortSignal): Promise<{
53
+ export declare function weaverBot(execute: boolean, params: {
54
+ taskJson?: string;
55
+ projectDir?: string;
56
+ }, __abortSignal__?: AbortSignal): Promise<{
54
57
  onSuccess: boolean;
55
58
  onFailure: boolean;
56
59
  summary: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"weaver-bot.d.ts","sourceRoot":"","sources":["../../src/workflows/weaver-bot.ts"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,WAAW,GAC5B,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAK7E"}
1
+ {"version":3,"file":"weaver-bot.d.ts","sourceRoot":"","sources":["../../src/workflows/weaver-bot.ts"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAClD,eAAe,CAAC,EAAE,WAAW,GAC5B,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAK7E"}
@@ -52,7 +52,7 @@
52
52
  * @returns onFailure [order:-1] [hidden] - On Failure
53
53
  * @returns summary [order:0] - Summary text
54
54
  */
55
- export async function weaverBot(execute, taskJson, projectDir, __abortSignal__) {
55
+ export async function weaverBot(execute, params, __abortSignal__) {
56
56
  // @flow-weaver-body-start
57
57
  // (auto-generated by compiler)
58
58
  // @flow-weaver-body-end
@@ -1 +1 @@
1
- {"version":3,"file":"weaver-bot.js","sourceRoot":"","sources":["../../src/workflows/weaver-bot.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,mCAAmC;AAgBnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAgB,EAChB,QAAiB,EACjB,UAAmB,EACnB,eAA6B;IAE7B,0BAA0B;IAC1B,+BAA+B;IAC/B,wBAAwB;IACxB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"weaver-bot.js","sourceRoot":"","sources":["../../src/workflows/weaver-bot.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,mCAAmC;AAgBnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAgB,EAChB,MAAkD,EAClD,eAA6B;IAE7B,0BAA0B;IAC1B,+BAA+B;IAC/B,wBAAwB;IACxB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC9D,CAAC"}
@@ -1,13 +1,35 @@
1
1
  {
2
2
  "manifestVersion": 1,
3
3
  "name": "@synergenius/flowweaver-pack-weaver",
4
- "version": "0.6.1",
4
+ "version": "0.7.1",
5
5
  "description": "AI bot for Flow Weaver. Execute tasks, run workflows, evolve autonomously.",
6
6
  "engineVersion": ">=0.19.4",
7
7
  "categories": [
8
8
  "automation",
9
9
  "ai"
10
10
  ],
11
+ "botRegistrations": [
12
+ {
13
+ "id": "weaver-bot",
14
+ "name": "Weaver Bot",
15
+ "description": "AI-powered autonomous workflow creator",
16
+ "icon": "psychology",
17
+ "color": "#6366f1",
18
+ "workflowExport": "weaverBot",
19
+ "paramName": "taskJson",
20
+ "sourceTemplateId": "weaver-bot"
21
+ },
22
+ {
23
+ "id": "weaver-genesis",
24
+ "name": "Weaver Genesis",
25
+ "description": "Self-evolution cycle for a target workflow",
26
+ "icon": "autoAwesome",
27
+ "color": "#9f5fe3",
28
+ "workflowExport": "genesisTask",
29
+ "paramName": "config",
30
+ "sourceTemplateId": "genesis-task"
31
+ }
32
+ ],
11
33
  "nodeTypes": [
12
34
  {
13
35
  "name": "weaverLoadConfig",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synergenius/flowweaver-pack-weaver",
3
- "version": "0.6.1",
3
+ "version": "0.7.1",
4
4
  "description": "AI bot for Flow Weaver. Execute tasks, run workflows, evolve autonomously.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@anthropic-ai/sdk": ">=0.30.0",
39
- "@synergenius/flow-weaver": ">=0.20.5",
39
+ "@synergenius/flow-weaver": ">=0.21.0",
40
40
  "zod": ">=3.22.0"
41
41
  },
42
42
  "peerDependenciesMeta": {
@@ -49,6 +49,7 @@
49
49
  },
50
50
  "files": [
51
51
  "dist",
52
+ "src",
52
53
  "flowweaver.manifest.json",
53
54
  "templates.js",
54
55
  "LICENSE"
@@ -0,0 +1,273 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import type { BotProviderConfig, BotConfig, BotAgentProvider, OnUsageCallback, StreamChunk, ToolDefinition, ToolUseResult } from './types.js';
3
+ import { buildSystemPrompt } from './system-prompt.js';
4
+ import { defaultRegistry, loadExternalProvider } from './provider-registry.js';
5
+ import type { ProviderRegistry } from './provider-registry.js';
6
+
7
+ const WHICH_CMD = process.platform === 'win32' ? 'where' : 'which';
8
+
9
+ export type { BotAgentProvider };
10
+
11
+ export function resolveProviderConfig(
12
+ provider: BotConfig['provider'],
13
+ ): BotProviderConfig {
14
+ if (provider === 'auto') return detectProvider();
15
+ if (typeof provider === 'string') return { name: provider };
16
+ return provider;
17
+ }
18
+
19
+ export async function createProvider(
20
+ config: BotProviderConfig,
21
+ registry: ProviderRegistry = defaultRegistry,
22
+ ): Promise<BotAgentProvider> {
23
+ // If config.module is set, load and register it first
24
+ if (config.module) {
25
+ if (!registry.has(config.name)) {
26
+ const { factory, metadata } = await loadExternalProvider(config.module);
27
+ registry.register(config.name, factory, metadata);
28
+ }
29
+ }
30
+
31
+ // Check registry (covers built-ins + loaded externals)
32
+ const entry = registry.resolve(config.name);
33
+ if (entry) {
34
+ return entry.factory({
35
+ model: config.model,
36
+ maxTokens: config.maxTokens,
37
+ options: config.options,
38
+ });
39
+ }
40
+
41
+ // Fallback: try conventional npm package names
42
+ const candidates = [
43
+ `flowweaver-provider-${config.name}`,
44
+ `@synergenius/flowweaver-provider-${config.name}`,
45
+ ];
46
+
47
+ for (const candidate of candidates) {
48
+ try {
49
+ const { factory, metadata } = await loadExternalProvider(candidate);
50
+ registry.register(config.name, factory, metadata);
51
+ return factory({
52
+ model: config.model,
53
+ maxTokens: config.maxTokens,
54
+ options: config.options,
55
+ });
56
+ } catch {
57
+ // Try next candidate
58
+ }
59
+ }
60
+
61
+ throw new Error(
62
+ `Unknown provider: ${config.name}\n` +
63
+ ` Install a provider package: npm install flowweaver-provider-${config.name}\n` +
64
+ ` Or specify a module path: { "provider": { "name": "${config.name}", "module": "./my-provider.js" } }`,
65
+ );
66
+ }
67
+
68
+ export function detectProvider(registry: ProviderRegistry = defaultRegistry): BotProviderConfig {
69
+ // Check registry metadata for env vars and CLI commands
70
+ for (const { name, metadata } of registry.list()) {
71
+ if (metadata.requiredEnvVars) {
72
+ const allPresent = metadata.requiredEnvVars.every((v) => process.env[v]);
73
+ if (allPresent) return { name };
74
+ }
75
+ }
76
+
77
+ for (const { name, metadata } of registry.list()) {
78
+ if (metadata.detectCliCommand) {
79
+ try {
80
+ execFileSync(WHICH_CMD, [metadata.detectCliCommand], { stdio: 'pipe' });
81
+ return { name };
82
+ } catch { /* not installed */ }
83
+ }
84
+ }
85
+
86
+ throw new Error(
87
+ 'No AI provider found. Options:\n' +
88
+ ' 1. Set ANTHROPIC_API_KEY environment variable\n' +
89
+ ' 2. Install Claude CLI: https://docs.anthropic.com/claude-code\n' +
90
+ ' 3. Install GitHub Copilot CLI: https://github.com/features/copilot',
91
+ );
92
+ }
93
+
94
+ export class AnthropicAgentProvider implements BotAgentProvider {
95
+ private model: string;
96
+ private maxTokens: number;
97
+ onUsage?: OnUsageCallback;
98
+
99
+ constructor(config: BotProviderConfig) {
100
+ this.model = config.model ?? 'claude-sonnet-4-6';
101
+ this.maxTokens = config.maxTokens ?? 4096;
102
+ }
103
+
104
+ async decide(request: {
105
+ agentId: string;
106
+ context: Record<string, unknown>;
107
+ prompt: string;
108
+ }): Promise<Record<string, unknown>> {
109
+ if (!process.env.ANTHROPIC_API_KEY) {
110
+ throw new Error(
111
+ 'ANTHROPIC_API_KEY environment variable is required for the Anthropic provider',
112
+ );
113
+ }
114
+
115
+ const Anthropic = await this.loadSdk();
116
+ const client = new Anthropic();
117
+ const systemPrompt = await buildSystemPrompt();
118
+
119
+ const contextStr =
120
+ typeof request.context === 'string'
121
+ ? request.context
122
+ : JSON.stringify(request.context, null, 2);
123
+
124
+ const response = await client.messages.create({
125
+ model: this.model,
126
+ max_tokens: this.maxTokens,
127
+ system: systemPrompt,
128
+ messages: [
129
+ {
130
+ role: 'user',
131
+ content: `Context:\n${contextStr}\n\nInstructions:\n${request.prompt}`,
132
+ },
133
+ ],
134
+ });
135
+
136
+ if (this.onUsage && response.usage) {
137
+ this.onUsage(request.agentId, response.model ?? this.model, {
138
+ inputTokens: response.usage.input_tokens,
139
+ outputTokens: response.usage.output_tokens,
140
+ cacheCreationInputTokens: response.usage.cache_creation_input_tokens,
141
+ cacheReadInputTokens: response.usage.cache_read_input_tokens,
142
+ });
143
+ }
144
+
145
+ const text =
146
+ response.content[0].type === 'text' ? response.content[0].text : '';
147
+ return this.parseJson(text);
148
+ }
149
+
150
+ async *stream(request: {
151
+ agentId: string;
152
+ context: Record<string, unknown>;
153
+ prompt: string;
154
+ }): AsyncIterable<StreamChunk> {
155
+ if (!process.env.ANTHROPIC_API_KEY) {
156
+ throw new Error('ANTHROPIC_API_KEY environment variable is required for the Anthropic provider');
157
+ }
158
+
159
+ const Anthropic = await this.loadSdk();
160
+ const client = new Anthropic();
161
+ const systemPrompt = await buildSystemPrompt();
162
+
163
+ const contextStr = typeof request.context === 'string'
164
+ ? request.context
165
+ : JSON.stringify(request.context, null, 2);
166
+
167
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
168
+ const stream = (client as any).messages.stream({
169
+ model: this.model,
170
+ max_tokens: this.maxTokens,
171
+ system: systemPrompt,
172
+ messages: [{ role: 'user', content: `Context:\n${contextStr}\n\nInstructions:\n${request.prompt}` }],
173
+ });
174
+
175
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
176
+ for await (const event of stream as AsyncIterable<any>) {
177
+ if (event.type === 'content_block_delta' && event.delta?.type === 'text_delta') {
178
+ yield { type: 'text', text: event.delta.text };
179
+ }
180
+ }
181
+
182
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
183
+ const finalMessage = await (stream as any).finalMessage();
184
+ if (finalMessage?.usage) {
185
+ const usage = {
186
+ inputTokens: finalMessage.usage.input_tokens,
187
+ outputTokens: finalMessage.usage.output_tokens,
188
+ cacheCreationInputTokens: finalMessage.usage.cache_creation_input_tokens,
189
+ cacheReadInputTokens: finalMessage.usage.cache_read_input_tokens,
190
+ };
191
+ if (this.onUsage) this.onUsage(request.agentId, finalMessage.model ?? this.model, usage);
192
+ yield { type: 'usage', usage };
193
+ }
194
+ yield { type: 'done' };
195
+ }
196
+
197
+ async decideWithTools(request: {
198
+ agentId: string;
199
+ context: Record<string, unknown>;
200
+ prompt: string;
201
+ tools: ToolDefinition[];
202
+ }): Promise<{ result: Record<string, unknown>; toolCalls?: ToolUseResult[] }> {
203
+ if (!process.env.ANTHROPIC_API_KEY) {
204
+ throw new Error('ANTHROPIC_API_KEY environment variable is required for the Anthropic provider');
205
+ }
206
+
207
+ const Anthropic = await this.loadSdk();
208
+ const client = new Anthropic();
209
+ const systemPrompt = await buildSystemPrompt();
210
+
211
+ const contextStr = typeof request.context === 'string'
212
+ ? request.context
213
+ : JSON.stringify(request.context, null, 2);
214
+
215
+ const response = await client.messages.create({
216
+ model: this.model,
217
+ max_tokens: this.maxTokens,
218
+ system: systemPrompt,
219
+ messages: [{ role: 'user', content: `Context:\n${contextStr}\n\nInstructions:\n${request.prompt}` }],
220
+ tools: request.tools,
221
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
222
+ } as any);
223
+
224
+ if (this.onUsage && response.usage) {
225
+ this.onUsage(request.agentId, response.model ?? this.model, {
226
+ inputTokens: response.usage.input_tokens,
227
+ outputTokens: response.usage.output_tokens,
228
+ cacheCreationInputTokens: response.usage.cache_creation_input_tokens,
229
+ cacheReadInputTokens: response.usage.cache_read_input_tokens,
230
+ });
231
+ }
232
+
233
+ const toolCalls: ToolUseResult[] = [];
234
+ let text = '';
235
+ for (const block of response.content) {
236
+ if (block.type === 'text') text = block.text;
237
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
238
+ else if (block.type === 'tool_use') toolCalls.push({ toolName: (block as any).name, toolInput: (block as any).input });
239
+ }
240
+
241
+ return { result: this.parseJson(text || '{}'), toolCalls: toolCalls.length > 0 ? toolCalls : undefined };
242
+ }
243
+
244
+ private parseJson(text: string): Record<string, unknown> {
245
+ let cleaned = text.trim();
246
+ if (cleaned.startsWith('```')) {
247
+ cleaned = cleaned.replace(/^```(?:json)?\s*\n?/, '').replace(/\n?```\s*$/, '');
248
+ }
249
+
250
+ try {
251
+ return JSON.parse(cleaned);
252
+ } catch {
253
+ const match = cleaned.match(/\{[\s\S]*\}/);
254
+ if (match) {
255
+ return JSON.parse(match[0]);
256
+ }
257
+ throw new Error(`Failed to parse AI response as JSON: ${text.slice(0, 200)}`);
258
+ }
259
+ }
260
+
261
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
262
+ private async loadSdk(): Promise<new () => any> {
263
+ try {
264
+ // @ts-expect-error -- optional peer dep, loaded at runtime
265
+ const mod = await import('@anthropic-ai/sdk');
266
+ return mod.default ?? mod.Anthropic;
267
+ } catch {
268
+ throw new Error(
269
+ 'Bot mode requires @anthropic-ai/sdk. Install it:\n npm install @anthropic-ai/sdk',
270
+ );
271
+ }
272
+ }
273
+ }
@@ -0,0 +1,109 @@
1
+ import { execSync, spawn } from 'node:child_process';
2
+ import { parseStreamLine, extractTextFromChunks } from './cli-stream-parser.js';
3
+ import type { StreamChunk } from './types.js';
4
+
5
+ // Strip CLAUDECODE from child env so nested claude CLI invocations work.
6
+ const childEnv = { ...process.env };
7
+ delete childEnv.CLAUDECODE;
8
+
9
+ export function callCli(provider: string, prompt: string, model?: string): string {
10
+ if (provider === 'claude-cli') {
11
+ const modelFlag = model ? ` --model ${model}` : '';
12
+ return execSync(`claude -p --output-format text${modelFlag}`, {
13
+ input: prompt, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 300_000, env: childEnv,
14
+ }).trim();
15
+ }
16
+ if (provider === 'copilot-cli') {
17
+ return execSync('copilot -p --silent --allow-all-tools', {
18
+ input: prompt, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 300_000, env: childEnv,
19
+ }).trim();
20
+ }
21
+ throw new Error(`Unknown CLI provider: ${provider}`);
22
+ }
23
+
24
+ export async function callCliAsync(provider: string, prompt: string, model?: string): Promise<string> {
25
+ if (provider === 'copilot-cli') {
26
+ return callCli(provider, prompt, model);
27
+ }
28
+ if (provider !== 'claude-cli') {
29
+ throw new Error(`Unknown CLI provider: ${provider}`);
30
+ }
31
+
32
+ const args = ['-p', '--output-format', 'stream-json'];
33
+ if (model) args.push('--model', model);
34
+
35
+ const child = spawn('claude', args, {
36
+ stdio: ['pipe', 'pipe', 'pipe'],
37
+ env: childEnv,
38
+ });
39
+
40
+ child.stdin.write(prompt);
41
+ child.stdin.end();
42
+
43
+ const timeout = setTimeout(() => child.kill('SIGTERM'), 300_000);
44
+
45
+ const chunks: StreamChunk[] = [];
46
+ let buffer = '';
47
+
48
+ try {
49
+ for await (const data of child.stdout) {
50
+ buffer += data.toString();
51
+ const lines = buffer.split('\n');
52
+ buffer = lines.pop()!;
53
+
54
+ for (const line of lines) {
55
+ const chunk = parseStreamLine(line);
56
+ if (chunk) chunks.push(chunk);
57
+ }
58
+ }
59
+
60
+ if (buffer.trim()) {
61
+ const chunk = parseStreamLine(buffer);
62
+ if (chunk) chunks.push(chunk);
63
+ }
64
+ } finally {
65
+ clearTimeout(timeout);
66
+ }
67
+
68
+ await new Promise<void>((resolve, reject) => {
69
+ child.on('close', (code) => {
70
+ if (code && code !== 0) reject(new Error(`claude CLI exited with code ${code}`));
71
+ else resolve();
72
+ });
73
+ child.on('error', reject);
74
+ });
75
+
76
+ return extractTextFromChunks(chunks);
77
+ }
78
+
79
+ export async function callApi(
80
+ apiKey: string, model: string, maxTokens: number,
81
+ systemPrompt: string, userPrompt: string,
82
+ ): Promise<string> {
83
+ const body = JSON.stringify({
84
+ model, max_tokens: maxTokens, system: systemPrompt,
85
+ messages: [{ role: 'user', content: userPrompt }],
86
+ });
87
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
88
+ method: 'POST',
89
+ headers: { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', 'content-type': 'application/json' },
90
+ body,
91
+ });
92
+ if (!response.ok) {
93
+ const text = await response.text();
94
+ throw new Error(`Anthropic API error ${response.status}: ${text.slice(0, 200)}`);
95
+ }
96
+ const json = await response.json() as { content: Array<{ type: string; text: string }> };
97
+ return json.content[0]?.text ?? '';
98
+ }
99
+
100
+ export function parseJsonResponse(text: string): Record<string, unknown> {
101
+ let cleaned = text.trim();
102
+ if (cleaned.startsWith('```')) {
103
+ cleaned = cleaned.replace(/^```(?:json)?\s*\n?/, '').replace(/\n?```\s*$/, '');
104
+ }
105
+ try { return JSON.parse(cleaned); } catch { /* fallthrough */ }
106
+ const match = cleaned.match(/\{[\s\S]*\}/);
107
+ if (match) return JSON.parse(match[0]);
108
+ throw new Error(`Failed to parse AI response as JSON: ${text.slice(0, 200)}`);
109
+ }