@crewx/sdk 0.8.0-rc.58

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 (303) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +1022 -0
  3. package/dist/adapters/MastraToolAdapter.d.ts +9 -0
  4. package/dist/adapters/MastraToolAdapter.js +66 -0
  5. package/dist/adapters/MastraToolAdapter.js.map +1 -0
  6. package/dist/api/index.d.ts +2 -0
  7. package/dist/api/index.js +8 -0
  8. package/dist/api/index.js.map +1 -0
  9. package/dist/boxing/box-storage.interface.d.ts +13 -0
  10. package/dist/boxing/box-storage.interface.js +3 -0
  11. package/dist/boxing/box-storage.interface.js.map +1 -0
  12. package/dist/boxing/box.service.d.ts +15 -0
  13. package/dist/boxing/box.service.js +70 -0
  14. package/dist/boxing/box.service.js.map +1 -0
  15. package/dist/boxing/box.types.d.ts +86 -0
  16. package/dist/boxing/box.types.js +3 -0
  17. package/dist/boxing/box.types.js.map +1 -0
  18. package/dist/boxing/context-builder.d.ts +8 -0
  19. package/dist/boxing/context-builder.js +76 -0
  20. package/dist/boxing/context-builder.js.map +1 -0
  21. package/dist/boxing/index.d.ts +6 -0
  22. package/dist/boxing/index.js +11 -0
  23. package/dist/boxing/index.js.map +1 -0
  24. package/dist/boxing/tokenizer.d.ts +3 -0
  25. package/dist/boxing/tokenizer.js +11 -0
  26. package/dist/boxing/tokenizer.js.map +1 -0
  27. package/dist/config/api-provider-parser.d.ts +58 -0
  28. package/dist/config/api-provider-parser.js +212 -0
  29. package/dist/config/api-provider-parser.js.map +1 -0
  30. package/dist/config/index.d.ts +3 -0
  31. package/dist/config/index.js +20 -0
  32. package/dist/config/index.js.map +1 -0
  33. package/dist/config/log.config.d.ts +7 -0
  34. package/dist/config/log.config.js +20 -0
  35. package/dist/config/log.config.js.map +1 -0
  36. package/dist/config/pricing.d.ts +10 -0
  37. package/dist/config/pricing.js +44 -0
  38. package/dist/config/pricing.js.map +1 -0
  39. package/dist/config/timeout.config.d.ts +14 -0
  40. package/dist/config/timeout.config.js +34 -0
  41. package/dist/config/timeout.config.js.map +1 -0
  42. package/dist/config/yaml-loader.d.ts +8 -0
  43. package/dist/config/yaml-loader.js +155 -0
  44. package/dist/config/yaml-loader.js.map +1 -0
  45. package/dist/constants/index.d.ts +4 -0
  46. package/dist/constants/index.js +8 -0
  47. package/dist/constants/index.js.map +1 -0
  48. package/dist/constants.d.ts +1 -0
  49. package/dist/constants.js +18 -0
  50. package/dist/constants.js.map +1 -0
  51. package/dist/conversation/conversation-config.d.ts +9 -0
  52. package/dist/conversation/conversation-config.js +22 -0
  53. package/dist/conversation/conversation-config.js.map +1 -0
  54. package/dist/conversation/conversation-history.interface.d.ts +36 -0
  55. package/dist/conversation/conversation-history.interface.js +3 -0
  56. package/dist/conversation/conversation-history.interface.js.map +1 -0
  57. package/dist/conversation/conversation-storage.service.d.ts +16 -0
  58. package/dist/conversation/conversation-storage.service.js +213 -0
  59. package/dist/conversation/conversation-storage.service.js.map +1 -0
  60. package/dist/conversation/index.d.ts +3 -0
  61. package/dist/conversation/index.js +20 -0
  62. package/dist/conversation/index.js.map +1 -0
  63. package/dist/core/agent/agent-factory.d.ts +37 -0
  64. package/dist/core/agent/agent-factory.js +68 -0
  65. package/dist/core/agent/agent-factory.js.map +1 -0
  66. package/dist/core/agent/agent-runtime.d.ts +52 -0
  67. package/dist/core/agent/agent-runtime.js +206 -0
  68. package/dist/core/agent/agent-runtime.js.map +1 -0
  69. package/dist/core/agent/event-bus.d.ts +44 -0
  70. package/dist/core/agent/event-bus.js +43 -0
  71. package/dist/core/agent/event-bus.js.map +1 -0
  72. package/dist/core/agent/index.d.ts +3 -0
  73. package/dist/core/agent/index.js +13 -0
  74. package/dist/core/agent/index.js.map +1 -0
  75. package/dist/core/env-defaults.d.ts +1 -0
  76. package/dist/core/env-defaults.js +7 -0
  77. package/dist/core/env-defaults.js.map +1 -0
  78. package/dist/core/parallel/helpers.d.ts +27 -0
  79. package/dist/core/parallel/helpers.js +252 -0
  80. package/dist/core/parallel/helpers.js.map +1 -0
  81. package/dist/core/parallel/index.d.ts +4 -0
  82. package/dist/core/parallel/index.js +11 -0
  83. package/dist/core/parallel/index.js.map +1 -0
  84. package/dist/core/parallel/parallel-runner.d.ts +16 -0
  85. package/dist/core/parallel/parallel-runner.js +230 -0
  86. package/dist/core/parallel/parallel-runner.js.map +1 -0
  87. package/dist/core/parallel/types.d.ts +41 -0
  88. package/dist/core/parallel/types.js +3 -0
  89. package/dist/core/parallel/types.js.map +1 -0
  90. package/dist/core/providers/MastraAPIProvider.d.ts +31 -0
  91. package/dist/core/providers/MastraAPIProvider.js +365 -0
  92. package/dist/core/providers/MastraAPIProvider.js.map +1 -0
  93. package/dist/core/providers/ai-provider.interface.d.ts +78 -0
  94. package/dist/core/providers/ai-provider.interface.js +23 -0
  95. package/dist/core/providers/ai-provider.interface.js.map +1 -0
  96. package/dist/core/providers/base-ai.provider.d.ts +80 -0
  97. package/dist/core/providers/base-ai.provider.js +1183 -0
  98. package/dist/core/providers/base-ai.provider.js.map +1 -0
  99. package/dist/core/providers/base-ai.types.d.ts +26 -0
  100. package/dist/core/providers/base-ai.types.js +3 -0
  101. package/dist/core/providers/base-ai.types.js.map +1 -0
  102. package/dist/core/providers/claude.provider.d.ts +19 -0
  103. package/dist/core/providers/claude.provider.js +170 -0
  104. package/dist/core/providers/claude.provider.js.map +1 -0
  105. package/dist/core/providers/codex.provider.d.ts +21 -0
  106. package/dist/core/providers/codex.provider.js +134 -0
  107. package/dist/core/providers/codex.provider.js.map +1 -0
  108. package/dist/core/providers/copilot.provider.d.ts +24 -0
  109. package/dist/core/providers/copilot.provider.js +146 -0
  110. package/dist/core/providers/copilot.provider.js.map +1 -0
  111. package/dist/core/providers/dynamic-provider.factory.d.ts +74 -0
  112. package/dist/core/providers/dynamic-provider.factory.js +643 -0
  113. package/dist/core/providers/dynamic-provider.factory.js.map +1 -0
  114. package/dist/core/providers/gemini.provider.d.ts +16 -0
  115. package/dist/core/providers/gemini.provider.js +101 -0
  116. package/dist/core/providers/gemini.provider.js.map +1 -0
  117. package/dist/core/providers/index.d.ts +8 -0
  118. package/dist/core/providers/index.js +20 -0
  119. package/dist/core/providers/index.js.map +1 -0
  120. package/dist/core/providers/mock.provider.d.ts +13 -0
  121. package/dist/core/providers/mock.provider.js +55 -0
  122. package/dist/core/providers/mock.provider.js.map +1 -0
  123. package/dist/core/providers/provider-factory.d.ts +3 -0
  124. package/dist/core/providers/provider-factory.js +65 -0
  125. package/dist/core/providers/provider-factory.js.map +1 -0
  126. package/dist/core/providers/tool-call.types.d.ts +39 -0
  127. package/dist/core/providers/tool-call.types.js +3 -0
  128. package/dist/core/providers/tool-call.types.js.map +1 -0
  129. package/dist/core/remote/index.d.ts +3 -0
  130. package/dist/core/remote/index.js +20 -0
  131. package/dist/core/remote/index.js.map +1 -0
  132. package/dist/core/remote/remote-agent-manager.d.ts +24 -0
  133. package/dist/core/remote/remote-agent-manager.js +195 -0
  134. package/dist/core/remote/remote-agent-manager.js.map +1 -0
  135. package/dist/core/remote/remote-transport.d.ts +15 -0
  136. package/dist/core/remote/remote-transport.js +70 -0
  137. package/dist/core/remote/remote-transport.js.map +1 -0
  138. package/dist/core/remote/types.d.ts +79 -0
  139. package/dist/core/remote/types.js +3 -0
  140. package/dist/core/remote/types.js.map +1 -0
  141. package/dist/index.d.ts +56 -0
  142. package/dist/index.js +133 -0
  143. package/dist/index.js.map +1 -0
  144. package/dist/internal/index.d.ts +1 -0
  145. package/dist/internal/index.js +6 -0
  146. package/dist/internal/index.js.map +1 -0
  147. package/dist/knowledge/DocumentManager.d.ts +4 -0
  148. package/dist/knowledge/DocumentManager.js +119 -0
  149. package/dist/knowledge/DocumentManager.js.map +1 -0
  150. package/dist/knowledge/index.d.ts +1 -0
  151. package/dist/knowledge/index.js +18 -0
  152. package/dist/knowledge/index.js.map +1 -0
  153. package/dist/parsers/agent-call.util.d.ts +3 -0
  154. package/dist/parsers/agent-call.util.js +17 -0
  155. package/dist/parsers/agent-call.util.js.map +1 -0
  156. package/dist/parsers/claude.parser.d.ts +2 -0
  157. package/dist/parsers/claude.parser.js +46 -0
  158. package/dist/parsers/claude.parser.js.map +1 -0
  159. package/dist/parsers/codex.parser.d.ts +2 -0
  160. package/dist/parsers/codex.parser.js +89 -0
  161. package/dist/parsers/codex.parser.js.map +1 -0
  162. package/dist/parsers/copilot.parser.d.ts +2 -0
  163. package/dist/parsers/copilot.parser.js +58 -0
  164. package/dist/parsers/copilot.parser.js.map +1 -0
  165. package/dist/parsers/gemini.parser.d.ts +2 -0
  166. package/dist/parsers/gemini.parser.js +36 -0
  167. package/dist/parsers/gemini.parser.js.map +1 -0
  168. package/dist/parsers/index.d.ts +7 -0
  169. package/dist/parsers/index.js +45 -0
  170. package/dist/parsers/index.js.map +1 -0
  171. package/dist/schema/skills-parser.d.ts +8 -0
  172. package/dist/schema/skills-parser.js +438 -0
  173. package/dist/schema/skills-parser.js.map +1 -0
  174. package/dist/schema/skills.types.d.ts +158 -0
  175. package/dist/schema/skills.types.js +41 -0
  176. package/dist/schema/skills.types.js.map +1 -0
  177. package/dist/schemas/api-provider.schema.d.ts +432 -0
  178. package/dist/schemas/api-provider.schema.js +50 -0
  179. package/dist/schemas/api-provider.schema.js.map +1 -0
  180. package/dist/services/index.d.ts +2 -0
  181. package/dist/services/index.js +19 -0
  182. package/dist/services/index.js.map +1 -0
  183. package/dist/services/layout-loader.service.d.ts +18 -0
  184. package/dist/services/layout-loader.service.js +271 -0
  185. package/dist/services/layout-loader.service.js.map +1 -0
  186. package/dist/services/layout-renderer.service.d.ts +34 -0
  187. package/dist/services/layout-renderer.service.js +325 -0
  188. package/dist/services/layout-renderer.service.js.map +1 -0
  189. package/dist/services/props-validator.service.d.ts +29 -0
  190. package/dist/services/props-validator.service.js +332 -0
  191. package/dist/services/props-validator.service.js.map +1 -0
  192. package/dist/skills/adapter/claude-skill-adapter.d.ts +11 -0
  193. package/dist/skills/adapter/claude-skill-adapter.js +222 -0
  194. package/dist/skills/adapter/claude-skill-adapter.js.map +1 -0
  195. package/dist/skills/index.d.ts +6 -0
  196. package/dist/skills/index.js +31 -0
  197. package/dist/skills/index.js.map +1 -0
  198. package/dist/skills/runtime/progressive-loader.d.ts +27 -0
  199. package/dist/skills/runtime/progressive-loader.js +186 -0
  200. package/dist/skills/runtime/progressive-loader.js.map +1 -0
  201. package/dist/skills/runtime/runtime-requirements-validator.d.ts +23 -0
  202. package/dist/skills/runtime/runtime-requirements-validator.js +248 -0
  203. package/dist/skills/runtime/runtime-requirements-validator.js.map +1 -0
  204. package/dist/skills/runtime/skill-runtime.service.d.ts +42 -0
  205. package/dist/skills/runtime/skill-runtime.service.js +434 -0
  206. package/dist/skills/runtime/skill-runtime.service.js.map +1 -0
  207. package/dist/tools/file-system.service.d.ts +10 -0
  208. package/dist/tools/file-system.service.js +33 -0
  209. package/dist/tools/file-system.service.js.map +1 -0
  210. package/dist/tools/find.tool.d.ts +85 -0
  211. package/dist/tools/find.tool.js +139 -0
  212. package/dist/tools/find.tool.js.map +1 -0
  213. package/dist/tools/glob.tool.d.ts +100 -0
  214. package/dist/tools/glob.tool.js +153 -0
  215. package/dist/tools/glob.tool.js.map +1 -0
  216. package/dist/tools/grep.tool.d.ts +30 -0
  217. package/dist/tools/grep.tool.js +137 -0
  218. package/dist/tools/grep.tool.js.map +1 -0
  219. package/dist/tools/index.d.ts +12 -0
  220. package/dist/tools/index.js +40 -0
  221. package/dist/tools/index.js.map +1 -0
  222. package/dist/tools/ls.tool.d.ts +24 -0
  223. package/dist/tools/ls.tool.js +94 -0
  224. package/dist/tools/ls.tool.js.map +1 -0
  225. package/dist/tools/read-file.tool.d.ts +30 -0
  226. package/dist/tools/read-file.tool.js +69 -0
  227. package/dist/tools/read-file.tool.js.map +1 -0
  228. package/dist/tools/replace.tool.d.ts +36 -0
  229. package/dist/tools/replace.tool.js +68 -0
  230. package/dist/tools/replace.tool.js.map +1 -0
  231. package/dist/tools/run-shell-command.tool.d.ts +24 -0
  232. package/dist/tools/run-shell-command.tool.js +64 -0
  233. package/dist/tools/run-shell-command.tool.js.map +1 -0
  234. package/dist/tools/tree.tool.d.ts +24 -0
  235. package/dist/tools/tree.tool.js +109 -0
  236. package/dist/tools/tree.tool.js.map +1 -0
  237. package/dist/tools/types.d.ts +42 -0
  238. package/dist/tools/types.js +13 -0
  239. package/dist/tools/types.js.map +1 -0
  240. package/dist/tools/utils/file-utils.d.ts +5 -0
  241. package/dist/tools/utils/file-utils.js +221 -0
  242. package/dist/tools/utils/file-utils.js.map +1 -0
  243. package/dist/tools/write-file.tool.d.ts +24 -0
  244. package/dist/tools/write-file.tool.js +55 -0
  245. package/dist/tools/write-file.tool.js.map +1 -0
  246. package/dist/types/agent.types.d.ts +134 -0
  247. package/dist/types/agent.types.js +16 -0
  248. package/dist/types/agent.types.js.map +1 -0
  249. package/dist/types/api-provider.types.d.ts +85 -0
  250. package/dist/types/api-provider.types.js +65 -0
  251. package/dist/types/api-provider.types.js.map +1 -0
  252. package/dist/types/index.d.ts +6 -0
  253. package/dist/types/index.js +23 -0
  254. package/dist/types/index.js.map +1 -0
  255. package/dist/types/layout.types.d.ts +115 -0
  256. package/dist/types/layout.types.js +22 -0
  257. package/dist/types/layout.types.js.map +1 -0
  258. package/dist/types/provider.types.d.ts +12 -0
  259. package/dist/types/provider.types.js +3 -0
  260. package/dist/types/provider.types.js.map +1 -0
  261. package/dist/types/skill-runtime.types.d.ts +244 -0
  262. package/dist/types/skill-runtime.types.js +44 -0
  263. package/dist/types/skill-runtime.types.js.map +1 -0
  264. package/dist/types/structured-payload.types.d.ts +46 -0
  265. package/dist/types/structured-payload.types.js +65 -0
  266. package/dist/types/structured-payload.types.js.map +1 -0
  267. package/dist/types/task-log.types.d.ts +14 -0
  268. package/dist/types/task-log.types.js +3 -0
  269. package/dist/types/task-log.types.js.map +1 -0
  270. package/dist/types/template.types.d.ts +38 -0
  271. package/dist/types/template.types.js +3 -0
  272. package/dist/types/template.types.js.map +1 -0
  273. package/dist/types.d.ts +1 -0
  274. package/dist/types.js +18 -0
  275. package/dist/types.js.map +1 -0
  276. package/dist/utils/api-provider-normalizer.d.ts +16 -0
  277. package/dist/utils/api-provider-normalizer.js +135 -0
  278. package/dist/utils/api-provider-normalizer.js.map +1 -0
  279. package/dist/utils/base-message-formatter.d.ts +32 -0
  280. package/dist/utils/base-message-formatter.js +170 -0
  281. package/dist/utils/base-message-formatter.js.map +1 -0
  282. package/dist/utils/error-utils.d.ts +3 -0
  283. package/dist/utils/error-utils.js +27 -0
  284. package/dist/utils/error-utils.js.map +1 -0
  285. package/dist/utils/index.d.ts +4 -0
  286. package/dist/utils/index.js +21 -0
  287. package/dist/utils/index.js.map +1 -0
  288. package/dist/utils/math-utils.d.ts +3 -0
  289. package/dist/utils/math-utils.js +10 -0
  290. package/dist/utils/math-utils.js.map +1 -0
  291. package/dist/utils/mention-parser.d.ts +18 -0
  292. package/dist/utils/mention-parser.js +136 -0
  293. package/dist/utils/mention-parser.js.map +1 -0
  294. package/dist/utils/string-utils.d.ts +1 -0
  295. package/dist/utils/string-utils.js +10 -0
  296. package/dist/utils/string-utils.js.map +1 -0
  297. package/dist/utils.d.ts +3 -0
  298. package/dist/utils.js +20 -0
  299. package/dist/utils.js.map +1 -0
  300. package/package.json +134 -0
  301. package/schema/api-provider-config.json +138 -0
  302. package/schema/crewx-config.json +224 -0
  303. package/schema/skills-config.json +306 -0
@@ -0,0 +1,1183 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseAIProvider = exports.ConsoleLogger = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ const timeout_config_1 = require("../../config/timeout.config");
8
+ const log_config_1 = require("../../config/log.config");
9
+ const parsers_1 = require("../../parsers");
10
+ class ConsoleLogger {
11
+ constructor(context) {
12
+ this.context = context;
13
+ }
14
+ log(message, ...optionalParams) {
15
+ console.log(`[${this.context}]`, message, ...optionalParams);
16
+ }
17
+ warn(message, ...optionalParams) {
18
+ console.warn(`[${this.context}]`, message, ...optionalParams);
19
+ }
20
+ error(message, ...optionalParams) {
21
+ const resolved = message instanceof Error ? message.message : message;
22
+ console.error(`[${this.context}]`, resolved, ...optionalParams);
23
+ }
24
+ }
25
+ exports.ConsoleLogger = ConsoleLogger;
26
+ class BaseAIProvider {
27
+ constructor(loggerContext, options = {}) {
28
+ this.cachedPath = null;
29
+ this.logger = options.logger ?? new ConsoleLogger(loggerContext);
30
+ this.toolCallHandler = options.toolCallHandler;
31
+ this.timeoutConfig = options.timeoutConfig ?? (0, timeout_config_1.getTimeoutConfig)();
32
+ this.logConfig = options.logConfig ?? (0, log_config_1.getLogConfig)();
33
+ this.logsDir = options.logsDir ?? (0, path_1.join)(process.cwd(), '.crewx', 'logs');
34
+ this.crewxVersion = options.crewxVersion ?? 'unknown';
35
+ this.taskLogHandler = options.taskLogHandler;
36
+ try {
37
+ (0, fs_1.mkdirSync)(this.logsDir, { recursive: true });
38
+ }
39
+ catch (error) {
40
+ }
41
+ }
42
+ getPromptInArgs() {
43
+ return false;
44
+ }
45
+ getDefaultQueryTimeout() {
46
+ const providerName = this.name.toLowerCase();
47
+ if (providerName.includes('claude'))
48
+ return this.timeoutConfig.claudeQuery;
49
+ if (providerName.includes('gemini'))
50
+ return this.timeoutConfig.geminiQuery;
51
+ if (providerName.includes('copilot'))
52
+ return this.timeoutConfig.copilotQuery;
53
+ return 600000;
54
+ }
55
+ getDefaultExecuteTimeout() {
56
+ const providerName = this.name.toLowerCase();
57
+ if (providerName.includes('claude'))
58
+ return this.timeoutConfig.claudeExecute;
59
+ if (providerName.includes('gemini'))
60
+ return this.timeoutConfig.geminiExecute;
61
+ if (providerName.includes('copilot'))
62
+ return this.timeoutConfig.copilotExecute;
63
+ return this.timeoutConfig.parallel;
64
+ }
65
+ getDefaultModel() {
66
+ return null;
67
+ }
68
+ getEnv() {
69
+ return {};
70
+ }
71
+ filterClaudePrefixedEnv(env) {
72
+ return Object.fromEntries(Object.entries(env).filter(([key]) => !key.startsWith('CLAUDE')));
73
+ }
74
+ resolveRuntimeMode(options) {
75
+ const runtime = options?.runtime;
76
+ if (!runtime) {
77
+ return 'native';
78
+ }
79
+ if (typeof runtime === 'string') {
80
+ return (runtime === 'docker' || runtime === 'podman') ? 'container' : 'native';
81
+ }
82
+ return (runtime.type === 'docker' || runtime.type === 'podman') ? 'container' : 'native';
83
+ }
84
+ resolveContainerCommand(options) {
85
+ const runtime = options?.runtime;
86
+ if (typeof runtime === 'string') {
87
+ return runtime === 'podman' ? 'podman' : 'docker';
88
+ }
89
+ if (runtime && typeof runtime === 'object') {
90
+ return runtime.type === 'podman' ? 'podman' : 'docker';
91
+ }
92
+ return 'docker';
93
+ }
94
+ resolveDockerImage(options) {
95
+ const runtime = options?.runtime;
96
+ if (runtime && typeof runtime === 'object' && runtime.image?.trim()) {
97
+ return runtime.image.trim();
98
+ }
99
+ return process.env.CREWX_DOCKER_AGENT_IMAGE || 'crewx-agent:latest';
100
+ }
101
+ resolveDockerMountPath(options) {
102
+ const runtime = options?.runtime;
103
+ if (runtime && typeof runtime === 'object' && runtime.mountPath?.trim()) {
104
+ return runtime.mountPath.trim();
105
+ }
106
+ return '/workspace';
107
+ }
108
+ resolveDockerArgs(options) {
109
+ const runtime = options?.runtime;
110
+ if (runtime && typeof runtime === 'object' && Array.isArray(runtime.dockerArgs)) {
111
+ return runtime.dockerArgs;
112
+ }
113
+ return [];
114
+ }
115
+ ensureContainerCredentials() {
116
+ if (process.platform !== 'darwin')
117
+ return;
118
+ const homeDir = process.env.HOME || '';
119
+ if (!homeDir)
120
+ return;
121
+ const credFile = (0, path_1.join)(homeDir, '.claude', '.credentials.json');
122
+ try {
123
+ const creds = (0, child_process_1.execSync)('security find-generic-password -s "Claude Code-credentials" -w', { encoding: 'utf-8', timeout: 5000 }).trim();
124
+ if (creds) {
125
+ (0, fs_1.mkdirSync)((0, path_1.join)(homeDir, '.claude'), { recursive: true });
126
+ (0, fs_1.writeFileSync)(credFile, creds, { mode: 0o600 });
127
+ this.logger.log('Extracted CLI credentials from macOS Keychain for container use');
128
+ }
129
+ }
130
+ catch {
131
+ }
132
+ }
133
+ buildDockerSpawnArgs(executable, args, cwd, env, options) {
134
+ const image = this.resolveDockerImage(options);
135
+ const mountPath = this.resolveDockerMountPath(options);
136
+ const dockerArgs = this.resolveDockerArgs(options);
137
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '';
138
+ delete env.HOME;
139
+ delete env.USERPROFILE;
140
+ const envKeys = Object.keys(env).filter((key) => env[key] !== undefined);
141
+ const envFlags = envKeys.flatMap((key) => ['-e', `${key}=${env[key]}`]);
142
+ const homeMounts = homeDir
143
+ ? [
144
+ '-v', `${homeDir}/.claude:/root/.claude`,
145
+ '-v', `${homeDir}/.claude.json:/root/.claude.json`,
146
+ ]
147
+ : [];
148
+ return [
149
+ 'run',
150
+ '--rm',
151
+ '-i',
152
+ ...dockerArgs,
153
+ '-v',
154
+ `${cwd}:${mountPath}`,
155
+ ...homeMounts,
156
+ '-w',
157
+ mountPath,
158
+ ...envFlags,
159
+ image,
160
+ executable,
161
+ ...args,
162
+ ];
163
+ }
164
+ substituteModelPlaceholders(args, model) {
165
+ return args.map(arg => arg.replace(/\{model\}/g, model));
166
+ }
167
+ setToolCallService(toolCallHandler) {
168
+ this.toolCallHandler = toolCallHandler;
169
+ }
170
+ setToolCallHandler(toolCallHandler) {
171
+ this.toolCallHandler = toolCallHandler;
172
+ }
173
+ parseToolUse(content) {
174
+ const xmlMatch = content.match(/<crew(?:code|x)_tool_call>\s*([\s\S]*?)\s*<\/crew(?:code|x)_tool_call>/);
175
+ if (xmlMatch && xmlMatch[1]) {
176
+ try {
177
+ const jsonContent = xmlMatch[1].trim();
178
+ const parsed = JSON.parse(jsonContent);
179
+ if (parsed.type === 'tool_use' && parsed.name && parsed.input !== undefined) {
180
+ this.logger.log(`Tool use detected from XML: ${parsed.name}`);
181
+ return {
182
+ isToolUse: true,
183
+ toolName: parsed.name,
184
+ toolInput: parsed.input,
185
+ };
186
+ }
187
+ }
188
+ catch (e) {
189
+ }
190
+ }
191
+ try {
192
+ const parsed = JSON.parse(content);
193
+ if (parsed.type === 'tool_use' && parsed.name && parsed.input !== undefined) {
194
+ this.logger.log(`Tool use detected from direct JSON: ${parsed.name}`);
195
+ return {
196
+ isToolUse: true,
197
+ toolName: parsed.name,
198
+ toolInput: parsed.input,
199
+ };
200
+ }
201
+ if (parsed.content && Array.isArray(parsed.content)) {
202
+ const toolUse = parsed.content.find((c) => c.type === 'tool_use');
203
+ if (toolUse && toolUse.name && toolUse.input !== undefined) {
204
+ this.logger.log(`Tool use detected from content array: ${toolUse.name}`);
205
+ return {
206
+ isToolUse: true,
207
+ toolName: toolUse.name,
208
+ toolInput: toolUse.input,
209
+ };
210
+ }
211
+ }
212
+ const providerSpecific = this.parseToolUseProviderSpecific(parsed);
213
+ if (providerSpecific.isToolUse) {
214
+ return providerSpecific;
215
+ }
216
+ }
217
+ catch (e) {
218
+ }
219
+ const codeBlockMatch = content.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
220
+ if (codeBlockMatch && codeBlockMatch[1]) {
221
+ try {
222
+ const jsonContent = codeBlockMatch[1].trim();
223
+ const parsed = JSON.parse(jsonContent);
224
+ if (parsed.type === 'tool_use' && parsed.name && parsed.input !== undefined) {
225
+ this.logger.log(`Tool use detected from code block: ${parsed.name}`);
226
+ return {
227
+ isToolUse: true,
228
+ toolName: parsed.name,
229
+ toolInput: parsed.input,
230
+ };
231
+ }
232
+ }
233
+ catch (e) {
234
+ }
235
+ }
236
+ const jsonObjectPattern = /\{[\s\S]*?"type"\s*:\s*"tool_use"[\s\S]*?\}/;
237
+ const jsonMatch = content.match(jsonObjectPattern);
238
+ if (jsonMatch) {
239
+ try {
240
+ const parsed = JSON.parse(jsonMatch[0]);
241
+ if (parsed.type === 'tool_use' && parsed.name && parsed.input !== undefined) {
242
+ this.logger.log(`Tool use detected from plain text JSON: ${parsed.name}`);
243
+ return {
244
+ isToolUse: true,
245
+ toolName: parsed.name,
246
+ toolInput: parsed.input,
247
+ };
248
+ }
249
+ }
250
+ catch (e) {
251
+ }
252
+ }
253
+ return { isToolUse: false };
254
+ }
255
+ parseToolUseProviderSpecific(_parsed) {
256
+ return { isToolUse: false };
257
+ }
258
+ parseUsage(stdout) {
259
+ if (!stdout || !stdout.trim()) {
260
+ return undefined;
261
+ }
262
+ try {
263
+ const lines = stdout.split('\n').filter(line => line.trim());
264
+ for (const line of lines) {
265
+ try {
266
+ const parsed = JSON.parse(line);
267
+ if (parsed.type === 'usage' && parsed.input_tokens !== undefined && parsed.output_tokens !== undefined) {
268
+ return {
269
+ inputTokens: parsed.input_tokens,
270
+ outputTokens: parsed.output_tokens,
271
+ };
272
+ }
273
+ if (parsed.usage?.input_tokens !== undefined && parsed.usage?.output_tokens !== undefined) {
274
+ return {
275
+ inputTokens: parsed.usage.input_tokens,
276
+ outputTokens: parsed.usage.output_tokens,
277
+ };
278
+ }
279
+ }
280
+ catch (e) {
281
+ }
282
+ }
283
+ const parsed = JSON.parse(stdout);
284
+ if (parsed.usage?.input_tokens !== undefined && parsed.usage?.output_tokens !== undefined) {
285
+ return {
286
+ inputTokens: parsed.usage.input_tokens,
287
+ outputTokens: parsed.usage.output_tokens,
288
+ };
289
+ }
290
+ }
291
+ catch (e) {
292
+ }
293
+ return undefined;
294
+ }
295
+ extractAgentMessageFromJsonLines(content) {
296
+ if (!content) {
297
+ return null;
298
+ }
299
+ const trimmed = content.trim();
300
+ if (!trimmed) {
301
+ return null;
302
+ }
303
+ const hasJsonlMarkers = /"type"\s*:\s*"(?:thread\.started|item\.completed|turn\.completed|response\.completed)"/.test(trimmed)
304
+ || /"type"\s*:\s*"(?:agent_message|assistant_message)"/.test(trimmed)
305
+ || /"item_type"\s*:\s*"assistant_message"/.test(trimmed);
306
+ if (!hasJsonlMarkers) {
307
+ return null;
308
+ }
309
+ const lines = trimmed.split('\n').map(line => line.trim()).filter(Boolean);
310
+ let agentMessage = null;
311
+ for (const line of lines) {
312
+ let parsed;
313
+ try {
314
+ parsed = JSON.parse(line);
315
+ }
316
+ catch {
317
+ continue;
318
+ }
319
+ const extracted = this.extractAgentMessageFromJsonItem(parsed);
320
+ if (extracted) {
321
+ agentMessage = extracted;
322
+ }
323
+ }
324
+ return agentMessage;
325
+ }
326
+ extractAgentMessageFromJsonItem(parsed) {
327
+ if (!parsed || typeof parsed !== 'object') {
328
+ return null;
329
+ }
330
+ if (parsed?.type === 'item.completed' &&
331
+ parsed?.item?.type === 'agent_message' &&
332
+ typeof parsed.item.text === 'string') {
333
+ return parsed.item.text.trim();
334
+ }
335
+ if (parsed?.type === 'item.completed' &&
336
+ parsed?.item?.item_type === 'assistant_message' &&
337
+ typeof parsed.item.text === 'string') {
338
+ return parsed.item.text.trim();
339
+ }
340
+ if (parsed?.item?.type === 'agent_message' &&
341
+ typeof parsed.item.text === 'string') {
342
+ return parsed.item.text.trim();
343
+ }
344
+ if (parsed?.item?.item_type === 'assistant_message' &&
345
+ typeof parsed.item.text === 'string') {
346
+ return parsed.item.text.trim();
347
+ }
348
+ if (Array.isArray(parsed?.response?.output)) {
349
+ const assistantEntries = parsed.response.output.filter((entry) => entry?.type === 'agent_message' || entry?.item_type === 'assistant_message');
350
+ if (assistantEntries.length > 0) {
351
+ const lastMessage = assistantEntries[assistantEntries.length - 1];
352
+ if (typeof lastMessage?.text === 'string') {
353
+ return lastMessage.text.trim();
354
+ }
355
+ }
356
+ }
357
+ return null;
358
+ }
359
+ filterToolUseFromResponse(content) {
360
+ if (!content)
361
+ return content;
362
+ const jsonlMessage = this.extractAgentMessageFromJsonLines(content);
363
+ if (jsonlMessage) {
364
+ return jsonlMessage;
365
+ }
366
+ let filteredContent = content;
367
+ filteredContent = filteredContent.replace(/^\s*\{[^}]*"type"\s*:\s*"tool_use"[^}]*\}\s*$/gm, '');
368
+ filteredContent = filteredContent.replace(/(?:^\s*\{[^}]*"type"\s*:\s*"tool_use"[^}]*\}\s*\n?)+/gm, '');
369
+ filteredContent = filteredContent.replace(/\n{3,}/g, '\n\n');
370
+ if (filteredContent.trim() === '') {
371
+ return '[Tool operations completed]';
372
+ }
373
+ return filteredContent.trim();
374
+ }
375
+ filterRuntimeLogs(content) {
376
+ if (!content)
377
+ return content;
378
+ let filtered = content;
379
+ if (this.shouldStripPromptContainers(filtered)) {
380
+ const promptContainerPatterns = [
381
+ /<(?:crewx_)?system_prompt\b[^>]*>[\s\S]*?<\/(?:crewx_)?system_prompt>/gi,
382
+ /<conversation_history\b[^>]*>[\s\S]*?<\/conversation_history>/gi,
383
+ /<user_query\b[^>]*>[\s\S]*?<\/user_query>/gi,
384
+ ];
385
+ for (const pattern of promptContainerPatterns) {
386
+ filtered = filtered.replace(pattern, '');
387
+ }
388
+ }
389
+ const runtimeLogPatterns = [
390
+ /^\[AgentRuntime\].*$/gm,
391
+ /^Loaded layout:.*$/gm,
392
+ /^Loaded \d+ layouts? from.*$/gm,
393
+ /^\[dotenv@[^\]]+\].*$/gm,
394
+ /^Registered custom layout:.*$/gm,
395
+ /^Updated custom layout:.*$/gm,
396
+ /^\[Layout Fallback\].*$/gm,
397
+ /^(?:💬\s*)?Message:\s*$/gm,
398
+ ];
399
+ for (const pattern of runtimeLogPatterns) {
400
+ filtered = filtered.replace(pattern, '');
401
+ }
402
+ filtered = filtered
403
+ .split('\n')
404
+ .map((line) => line.trimEnd())
405
+ .join('\n');
406
+ filtered = filtered.replace(/\n{3,}/g, '\n\n');
407
+ return filtered.trim();
408
+ }
409
+ shouldStripPromptContainers(content) {
410
+ return (/^\s*<(?:crewx_)?system_prompt\b/i.test(content) ||
411
+ /^\s*<conversation_history\b/i.test(content) ||
412
+ /^\s*<user_query\b/i.test(content) ||
413
+ /^(?:💬\s*)?Message:\s*<(?:(?:crewx_)?system_prompt|conversation_history|user_query)\b/im.test(content) ||
414
+ /^\[AgentRuntime\].*$/m.test(content) ||
415
+ /^Loaded layout:.*$/m.test(content) ||
416
+ /^Loaded \d+ layouts? from.*$/m.test(content) ||
417
+ /^\[dotenv@[^\]]+\].*$/m.test(content) ||
418
+ /^Registered custom layout:.*$/m.test(content) ||
419
+ /^Updated custom layout:.*$/m.test(content) ||
420
+ /^\[Layout Fallback\].*$/m.test(content));
421
+ }
422
+ parseProviderError(stderr, stdout, exitCode) {
423
+ if (stderr && (stderr.toLowerCase().includes('unknown option') ||
424
+ stderr.toLowerCase().includes('invalid option'))) {
425
+ return {
426
+ error: true,
427
+ message: stderr.split('\n')[0]?.trim() || 'Invalid CLI option',
428
+ };
429
+ }
430
+ const knownWarningPatterns = [
431
+ 'YOLO mode is enabled',
432
+ 'Loaded cached credentials',
433
+ 'MaxListenersExceededWarning',
434
+ 'MaxListeners is',
435
+ 'Use events.setMaxListeners()',
436
+ 'Use `node --trace-warnings',
437
+ ];
438
+ if (exitCode === 0 && stderr && !stdout) {
439
+ const isOnlyWarnings = knownWarningPatterns.some(pattern => stderr.includes(pattern));
440
+ if (isOnlyWarnings) {
441
+ return { error: false, message: '' };
442
+ }
443
+ }
444
+ if (stderr && !stdout) {
445
+ return { error: true, message: stderr };
446
+ }
447
+ return { error: false, message: '' };
448
+ }
449
+ async getToolPath() {
450
+ if (this.cachedPath !== null) {
451
+ return this.cachedPath;
452
+ }
453
+ try {
454
+ const cliCommand = this.getCliCommand();
455
+ const isWindows = process.platform === 'win32';
456
+ const command = isWindows ? `where ${cliCommand}` : `which ${cliCommand}`;
457
+ const path = (0, child_process_1.execSync)(command, { encoding: 'utf-8' }).trim();
458
+ let finalPath;
459
+ if (isWindows) {
460
+ const paths = path.split('\n').map(p => p.trim()).filter(p => p);
461
+ const pathWithExt = paths.find(p => /\.(cmd|exe|bat|ps1)$/i.test(p));
462
+ finalPath = pathWithExt || paths[0] || '';
463
+ }
464
+ else {
465
+ finalPath = path;
466
+ }
467
+ this.logger.log(`✅ Found ${this.name} CLI at: ${finalPath}`);
468
+ this.cachedPath = finalPath;
469
+ return finalPath;
470
+ }
471
+ catch (error) {
472
+ this.logger.error(`❌ ${this.name} not found in PATH: ${error.message}`);
473
+ this.cachedPath = '';
474
+ return null;
475
+ }
476
+ }
477
+ wrapUserQueryWithSecurity(userQuery, securityKey) {
478
+ return `
479
+ <user_query key="${securityKey}">
480
+ ${userQuery}
481
+ </user_query>`;
482
+ }
483
+ extractUserQuery(wrappedQuery, securityKey) {
484
+ const regex = new RegExp(`<user_query key="${securityKey}">\\s*([\\s\\S]*?)\\s*</user_query>`, 'm');
485
+ const match = wrappedQuery.match(regex);
486
+ return match && match[1] ? match[1].trim() : wrappedQuery;
487
+ }
488
+ async isAvailable() {
489
+ const path = await this.getToolPath();
490
+ return path !== null && path !== '';
491
+ }
492
+ createTaskLogFile(taskId, provider, command, agentId, model) {
493
+ const safeTaskId = taskId.replace(/[\\/]/g, '_');
494
+ const logFile = (0, path_1.join)(this.logsDir, `${safeTaskId}.log`);
495
+ const safeAgentId = agentId ? agentId.replace(/[\\/]/g, '_') : 'N/A';
496
+ const timestamp = new Date().toLocaleString();
497
+ const header = `=== TASK LOG: ${taskId} ===
498
+ CrewX Version: ${this.crewxVersion}
499
+ Provider: ${provider}
500
+ Agent: ${safeAgentId}
501
+ ${model ? `Model: ${model}\n` : ''}Command: ${command}
502
+ Started: ${timestamp}
503
+
504
+ `;
505
+ (0, fs_1.writeFileSync)(logFile, header, 'utf8');
506
+ return logFile;
507
+ }
508
+ appendTaskLog(taskId, level, message) {
509
+ const safeTaskId = taskId.replace(/[\\/]/g, '_');
510
+ const logFile = (0, path_1.join)(this.logsDir, `${safeTaskId}.log`);
511
+ const timestamp = new Date();
512
+ const logEntry = `[${timestamp.toLocaleString()}] ${level}: ${message}\n`;
513
+ try {
514
+ (0, fs_1.appendFileSync)(logFile, logEntry, 'utf8');
515
+ }
516
+ catch (error) {
517
+ this.logger.error(`Failed to append to task log ${taskId}:`, error);
518
+ }
519
+ if (this.taskLogHandler) {
520
+ try {
521
+ this.taskLogHandler({
522
+ taskId,
523
+ timestamp: timestamp.toISOString(),
524
+ level,
525
+ message,
526
+ });
527
+ }
528
+ catch (error) {
529
+ this.logger.warn(`Task log handler failed for ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
530
+ }
531
+ }
532
+ }
533
+ async query(prompt, options = {}) {
534
+ const taskId = options.taskId || `${this.name}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
535
+ const executablePath = this.getCliCommand();
536
+ const promptLength = prompt.length;
537
+ try {
538
+ const modelToUse = options.model || this.getDefaultModel();
539
+ let args = [
540
+ ...(options.additionalArgs || []),
541
+ ...this.getDefaultArgs(),
542
+ ];
543
+ if (modelToUse) {
544
+ args = this.substituteModelPlaceholders(args, modelToUse);
545
+ }
546
+ const isBuiltInProvider = this.name.startsWith('cli/');
547
+ const hasModelInArgs = args.some(arg => arg.includes('--model') || arg.includes('{model}'));
548
+ if (isBuiltInProvider && options.model && !hasModelInArgs) {
549
+ args.unshift(`--model=${options.model}`);
550
+ }
551
+ const promptInArgs = this.getPromptInArgs();
552
+ if (promptInArgs) {
553
+ args.push(prompt);
554
+ }
555
+ const runtimeMode = this.resolveRuntimeMode(options);
556
+ const command = runtimeMode === 'container'
557
+ ? `${this.resolveContainerCommand(options)} run --rm -i -v ${options.workingDirectory || process.cwd()}:${this.resolveDockerMountPath(options)} ${this.resolveDockerImage(options)} ${this.getCliCommand()} ...`
558
+ : (promptInArgs
559
+ ? `${this.getCliCommand()} ${args.slice(0, -1).join(' ')} -p "<prompt>"`
560
+ : `${this.getCliCommand()} ${args.join(' ')}`);
561
+ this.createTaskLogFile(taskId, this.name, command, options.agentId, modelToUse);
562
+ this.appendTaskLog(taskId, 'INFO', `Starting ${this.name} query mode`);
563
+ this.appendTaskLog(taskId, 'INFO', `Prompt length: ${promptLength} characters`);
564
+ this.appendTaskLog(taskId, 'INFO', `Prompt content:\n${prompt}`);
565
+ this.logger.log(`Executing ${this.name} with prompt (length: ${promptLength})`);
566
+ return new Promise((resolve) => {
567
+ const env = this.filterClaudePrefixedEnv({
568
+ ...process.env,
569
+ LANG: 'en_US.UTF-8',
570
+ LC_ALL: 'en_US.UTF-8',
571
+ CREWX_TASK_ID: taskId,
572
+ CREWX_AGENT_ID: options.agentId || '',
573
+ CREWX_USER_ID: process.env.USER || process.env.USERNAME || 'unknown',
574
+ CREWX_TRACE_ID: options.traceId || process.env.CREWX_TRACE_ID || '',
575
+ CREWX_PARENT_TASK_ID: taskId,
576
+ CREWX_CALLER_AGENT_ID: options.agentId || process.env.CREWX_CALLER_AGENT_ID || '',
577
+ ...this.getEnv(),
578
+ ...(options.env || {}),
579
+ });
580
+ if (process.platform === 'win32') {
581
+ env.PYTHONIOENCODING = 'utf-8';
582
+ }
583
+ let executable = executablePath;
584
+ let spawnArgs = args;
585
+ let useShell = false;
586
+ if (runtimeMode === 'container') {
587
+ this.ensureContainerCredentials();
588
+ delete env.CLAUDECODE;
589
+ executable = this.resolveContainerCommand(options);
590
+ spawnArgs = this.buildDockerSpawnArgs(executablePath, args, options.workingDirectory || process.cwd(), env, options);
591
+ useShell = false;
592
+ }
593
+ else if (process.platform === 'win32') {
594
+ useShell = true;
595
+ }
596
+ const startTime = Date.now();
597
+ let firstOutputAt = undefined;
598
+ const child = (0, child_process_1.spawn)(executable, spawnArgs, {
599
+ stdio: ['pipe', 'pipe', 'pipe'],
600
+ cwd: options.workingDirectory || process.cwd(),
601
+ env,
602
+ shell: useShell,
603
+ });
604
+ const childPid = child.pid;
605
+ this.notifyProcessStart(options, childPid);
606
+ let stdout = '';
607
+ let stderr = '';
608
+ let exitCode = null;
609
+ const accumulatedLogs = [];
610
+ child.stdin.on('error', (err) => {
611
+ if (err.code !== 'EPIPE') {
612
+ this.logger.warn(`stdin error: ${err.message}`);
613
+ }
614
+ });
615
+ let stdoutLineBuffer = '';
616
+ let stderrLineBuffer = '';
617
+ child.stdout.on('data', (data) => {
618
+ const output = data.toString();
619
+ if (firstOutputAt === undefined) {
620
+ firstOutputAt = Date.now();
621
+ }
622
+ stdout += output;
623
+ stdoutLineBuffer += output;
624
+ const lines = stdoutLineBuffer.split('\n');
625
+ stdoutLineBuffer = lines.pop() || '';
626
+ for (const line of lines) {
627
+ if (line.trim()) {
628
+ this.appendTaskLog(taskId, 'STDOUT', line);
629
+ const timestamp = new Date().toISOString();
630
+ const entries = (0, parsers_1.parseStdoutEvent)(timestamp, line);
631
+ if (entries.length > 0) {
632
+ accumulatedLogs.push(...entries);
633
+ }
634
+ }
635
+ }
636
+ });
637
+ child.stderr.on('data', (data) => {
638
+ const output = data.toString();
639
+ if (firstOutputAt === undefined) {
640
+ firstOutputAt = Date.now();
641
+ }
642
+ stderr += output;
643
+ stderrLineBuffer += output;
644
+ const lines = stderrLineBuffer.split('\n');
645
+ stderrLineBuffer = lines.pop() || '';
646
+ for (const line of lines) {
647
+ if (line.trim()) {
648
+ this.appendTaskLog(taskId, 'STDERR', line);
649
+ }
650
+ }
651
+ });
652
+ child.on('close', (code) => {
653
+ exitCode = code;
654
+ const completedAt = Date.now();
655
+ const durationMs = completedAt - startTime;
656
+ const timeToFirstOutputMs = firstOutputAt !== undefined ? firstOutputAt - startTime : undefined;
657
+ if (stdoutLineBuffer.trim()) {
658
+ this.appendTaskLog(taskId, 'STDOUT', stdoutLineBuffer);
659
+ const timestamp = new Date().toISOString();
660
+ const entries = (0, parsers_1.parseStdoutEvent)(timestamp, stdoutLineBuffer);
661
+ if (entries.length > 0) {
662
+ accumulatedLogs.push(...entries);
663
+ }
664
+ stdoutLineBuffer = '';
665
+ }
666
+ if (stderrLineBuffer.trim()) {
667
+ this.appendTaskLog(taskId, 'STDERR', stderrLineBuffer);
668
+ stderrLineBuffer = '';
669
+ }
670
+ this.appendTaskLog(taskId, 'INFO', `Process closed with exit code: ${exitCode}`);
671
+ if (stderr) {
672
+ this.logger.warn(`[${taskId}] ${this.name} stderr: ${stderr}`);
673
+ }
674
+ if (exitCode === 0 && stdout && stdout.trim().length > 0) {
675
+ const filteredContent = this.filterRuntimeLogs(this.filterToolUseFromResponse(stdout.trim()));
676
+ const usage = this.parseUsage(stdout);
677
+ this.appendTaskLog(taskId, 'INFO', `${this.name} query completed successfully`);
678
+ resolve({
679
+ content: filteredContent,
680
+ provider: this.name,
681
+ command,
682
+ success: true,
683
+ taskId,
684
+ pid: childPid,
685
+ exitCode,
686
+ durationMs,
687
+ timeToFirstOutputMs,
688
+ promptLength,
689
+ usage,
690
+ logs: accumulatedLogs,
691
+ });
692
+ return;
693
+ }
694
+ const providerError = this.parseProviderError(stderr, stdout, exitCode);
695
+ if (exitCode !== 0 || providerError.error) {
696
+ const errorMessage = providerError.message || stderr || `Exit code ${exitCode}`;
697
+ this.appendTaskLog(taskId, 'ERROR', `${this.name} CLI failed: ${errorMessage}`);
698
+ resolve({
699
+ content: '',
700
+ provider: this.name,
701
+ command,
702
+ success: false,
703
+ error: `${this.name} CLI failed: ${errorMessage}`,
704
+ taskId,
705
+ pid: childPid,
706
+ exitCode,
707
+ durationMs,
708
+ timeToFirstOutputMs,
709
+ promptLength,
710
+ });
711
+ return;
712
+ }
713
+ this.appendTaskLog(taskId, 'INFO', `${this.name} query completed successfully`);
714
+ let parsedContent = stdout.trim();
715
+ try {
716
+ JSON.parse(stdout);
717
+ parsedContent = stdout.trim();
718
+ this.appendTaskLog(taskId, 'INFO', 'JSON output detected and validated');
719
+ }
720
+ catch (jsonError) {
721
+ this.appendTaskLog(taskId, 'INFO', 'Plain text output (not JSON)');
722
+ }
723
+ const filteredContent = this.filterRuntimeLogs(this.filterToolUseFromResponse(parsedContent));
724
+ const usage = this.parseUsage(stdout);
725
+ resolve({
726
+ content: filteredContent,
727
+ provider: this.name,
728
+ command,
729
+ success: true,
730
+ taskId,
731
+ pid: childPid,
732
+ exitCode,
733
+ durationMs,
734
+ timeToFirstOutputMs,
735
+ promptLength,
736
+ usage,
737
+ logs: accumulatedLogs,
738
+ });
739
+ });
740
+ child.on('error', (error) => {
741
+ const durationMs = Date.now() - startTime;
742
+ const timeToFirstOutputMs = firstOutputAt !== undefined ? firstOutputAt - startTime : undefined;
743
+ this.appendTaskLog(taskId, 'ERROR', `Process error: ${error.message}`);
744
+ resolve({
745
+ content: '',
746
+ provider: this.name,
747
+ command,
748
+ success: false,
749
+ error: error.code === 'ENOENT' ? this.getNotInstalledMessage() : error.message,
750
+ taskId,
751
+ pid: childPid,
752
+ exitCode: null,
753
+ durationMs,
754
+ timeToFirstOutputMs,
755
+ promptLength,
756
+ });
757
+ });
758
+ const pipedContext = this.buildPipedContext(prompt, options);
759
+ try {
760
+ if (pipedContext && this.shouldPipeContext(options)) {
761
+ child.stdin.write(pipedContext);
762
+ if (!pipedContext.endsWith('\n')) {
763
+ child.stdin.write('\n');
764
+ }
765
+ }
766
+ if (!this.getPromptInArgs()) {
767
+ child.stdin.write(prompt);
768
+ }
769
+ }
770
+ catch (stdinError) {
771
+ if (stdinError.code !== 'EPIPE') {
772
+ this.logger.warn(`stdin write error: ${stdinError.message}`);
773
+ }
774
+ }
775
+ finally {
776
+ setImmediate(() => {
777
+ try {
778
+ child.stdin.end();
779
+ }
780
+ catch (endError) {
781
+ if (endError.code !== 'EPIPE') {
782
+ this.logger.warn(`stdin.end() error: ${endError.message}`);
783
+ }
784
+ }
785
+ });
786
+ }
787
+ const timeout = setTimeout(() => {
788
+ const durationMs = Date.now() - startTime;
789
+ const timeToFirstOutputMs = firstOutputAt !== undefined ? firstOutputAt - startTime : undefined;
790
+ child.kill();
791
+ resolve({
792
+ content: '',
793
+ provider: this.name,
794
+ command,
795
+ success: false,
796
+ error: `${this.name} CLI timeout`,
797
+ taskId,
798
+ pid: childPid,
799
+ exitCode: null,
800
+ durationMs,
801
+ timeToFirstOutputMs,
802
+ promptLength,
803
+ });
804
+ }, options.timeout || this.getDefaultQueryTimeout());
805
+ child.on('close', () => clearTimeout(timeout));
806
+ });
807
+ }
808
+ catch (error) {
809
+ this.logger.error(`${this.name} execution failed: ${error.message}`, error.stack);
810
+ return {
811
+ content: '',
812
+ provider: this.name,
813
+ command: `${this.getCliCommand()} (error)`,
814
+ success: false,
815
+ error: error.message || 'Unknown error occurred',
816
+ taskId,
817
+ exitCode: null,
818
+ promptLength,
819
+ };
820
+ }
821
+ }
822
+ async execute(prompt, options = {}) {
823
+ const taskId = options.taskId || `${this.name}_execute_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
824
+ const executablePath = this.getCliCommand();
825
+ const promptLength = prompt.length;
826
+ try {
827
+ const modelToUse = options.model || this.getDefaultModel();
828
+ let args = [
829
+ ...(options.additionalArgs || []),
830
+ ...this.getExecuteArgs(),
831
+ ];
832
+ if (modelToUse) {
833
+ args = this.substituteModelPlaceholders(args, modelToUse);
834
+ }
835
+ const isBuiltInProvider = this.name.startsWith('cli/');
836
+ const hasModelInArgs = args.some(arg => arg.includes('--model') || arg.includes('{model}'));
837
+ if (isBuiltInProvider && options.model && !hasModelInArgs) {
838
+ args.unshift(`--model=${options.model}`);
839
+ }
840
+ if (this.getPromptInArgs()) {
841
+ args.push(prompt);
842
+ }
843
+ const runtimeMode = this.resolveRuntimeMode(options);
844
+ const command = runtimeMode === 'container'
845
+ ? `${this.resolveContainerCommand(options)} run --rm -i -v ${options.workingDirectory || process.cwd()}:${this.resolveDockerMountPath(options)} ${this.resolveDockerImage(options)} ${this.getCliCommand()} ...`
846
+ : `${this.getCliCommand()} ${args.join(' ')}`;
847
+ this.createTaskLogFile(taskId, this.name, command, options.agentId, modelToUse);
848
+ this.appendTaskLog(taskId, 'INFO', `Additional Args: ${JSON.stringify(options.additionalArgs || [])}`);
849
+ this.appendTaskLog(taskId, 'INFO', `Execute Args: ${JSON.stringify(this.getExecuteArgs())}`);
850
+ this.appendTaskLog(taskId, 'INFO', `Final Args: ${JSON.stringify(args)}`);
851
+ this.appendTaskLog(taskId, 'INFO', `Starting ${this.name} execute mode`);
852
+ this.appendTaskLog(taskId, 'INFO', `Prompt length: ${promptLength} characters`);
853
+ const promptPreview = prompt.length > this.logConfig.promptMaxLength ?
854
+ prompt.substring(0, this.logConfig.promptMaxLength) + '...[truncated]' :
855
+ prompt;
856
+ this.appendTaskLog(taskId, 'INFO', `Prompt content:\n${promptPreview}`);
857
+ this.logger.log(`Executing ${this.name} in execute mode (length: ${promptLength})`);
858
+ return new Promise((resolve) => {
859
+ const env = this.filterClaudePrefixedEnv({
860
+ ...process.env,
861
+ LANG: 'en_US.UTF-8',
862
+ LC_ALL: 'en_US.UTF-8',
863
+ CREWX_TASK_ID: taskId,
864
+ CREWX_AGENT_ID: options.agentId || '',
865
+ CREWX_USER_ID: process.env.USER || process.env.USERNAME || 'unknown',
866
+ CREWX_TRACE_ID: options.traceId || process.env.CREWX_TRACE_ID || '',
867
+ CREWX_PARENT_TASK_ID: taskId,
868
+ CREWX_CALLER_AGENT_ID: options.agentId || process.env.CREWX_CALLER_AGENT_ID || '',
869
+ ...this.getEnv(),
870
+ ...(options.env || {}),
871
+ });
872
+ if (process.platform === 'win32') {
873
+ env.PYTHONIOENCODING = 'utf-8';
874
+ }
875
+ let executable = executablePath;
876
+ let spawnArgs = args;
877
+ let useShell = false;
878
+ if (runtimeMode === 'container') {
879
+ this.ensureContainerCredentials();
880
+ delete env.CLAUDECODE;
881
+ executable = this.resolveContainerCommand(options);
882
+ spawnArgs = this.buildDockerSpawnArgs(executablePath, args, options.workingDirectory || process.cwd(), env, options);
883
+ useShell = false;
884
+ }
885
+ else if (process.platform === 'win32') {
886
+ useShell = true;
887
+ }
888
+ const startTime = Date.now();
889
+ let firstOutputAt = undefined;
890
+ const child = (0, child_process_1.spawn)(executable, spawnArgs, {
891
+ stdio: ['pipe', 'pipe', 'pipe'],
892
+ cwd: options.workingDirectory || process.cwd(),
893
+ env,
894
+ shell: useShell,
895
+ });
896
+ const childPid = child.pid;
897
+ this.notifyProcessStart(options, childPid);
898
+ let stdout = '';
899
+ let stderr = '';
900
+ let exitCode = null;
901
+ const accumulatedLogs = [];
902
+ child.stdin.on('error', (err) => {
903
+ if (err.code !== 'EPIPE') {
904
+ this.logger.warn(`stdin error: ${err.message}`);
905
+ }
906
+ });
907
+ let stdoutLineBuffer = '';
908
+ let stderrLineBuffer = '';
909
+ child.stdout.on('data', (data) => {
910
+ const output = data.toString();
911
+ if (firstOutputAt === undefined) {
912
+ firstOutputAt = Date.now();
913
+ }
914
+ stdout += output;
915
+ stdoutLineBuffer += output;
916
+ const lines = stdoutLineBuffer.split('\n');
917
+ stdoutLineBuffer = lines.pop() || '';
918
+ for (const line of lines) {
919
+ if (line.trim()) {
920
+ this.appendTaskLog(taskId, 'STDOUT', line);
921
+ const timestamp = new Date().toISOString();
922
+ const entries = (0, parsers_1.parseStdoutEvent)(timestamp, line);
923
+ if (entries.length > 0) {
924
+ accumulatedLogs.push(...entries);
925
+ }
926
+ }
927
+ }
928
+ });
929
+ child.stderr.on('data', (data) => {
930
+ const output = data.toString();
931
+ if (firstOutputAt === undefined) {
932
+ firstOutputAt = Date.now();
933
+ }
934
+ stderr += output;
935
+ stderrLineBuffer += output;
936
+ const lines = stderrLineBuffer.split('\n');
937
+ stderrLineBuffer = lines.pop() || '';
938
+ for (const line of lines) {
939
+ if (line.trim()) {
940
+ this.appendTaskLog(taskId, 'STDERR', line);
941
+ }
942
+ }
943
+ });
944
+ child.on('close', (code) => {
945
+ exitCode = code;
946
+ const completedAt = Date.now();
947
+ const durationMs = completedAt - startTime;
948
+ const timeToFirstOutputMs = firstOutputAt !== undefined ? firstOutputAt - startTime : undefined;
949
+ if (stdoutLineBuffer.trim()) {
950
+ this.appendTaskLog(taskId, 'STDOUT', stdoutLineBuffer);
951
+ const timestamp = new Date().toISOString();
952
+ const entries = (0, parsers_1.parseStdoutEvent)(timestamp, stdoutLineBuffer);
953
+ if (entries.length > 0) {
954
+ accumulatedLogs.push(...entries);
955
+ }
956
+ stdoutLineBuffer = '';
957
+ }
958
+ if (stderrLineBuffer.trim()) {
959
+ this.appendTaskLog(taskId, 'STDERR', stderrLineBuffer);
960
+ stderrLineBuffer = '';
961
+ }
962
+ this.appendTaskLog(taskId, 'INFO', `Process closed with exit code: ${exitCode}`);
963
+ if (stderr) {
964
+ this.logger.warn(`[${taskId}] ${this.name} stderr: ${stderr}`);
965
+ }
966
+ if (exitCode === 0 && stdout && stdout.trim().length > 0) {
967
+ const filteredContent = this.filterRuntimeLogs(this.filterToolUseFromResponse(stdout.trim()));
968
+ const usage = this.parseUsage(stdout);
969
+ this.appendTaskLog(taskId, 'INFO', `${this.name} execution completed successfully`);
970
+ resolve({
971
+ content: filteredContent,
972
+ provider: this.name,
973
+ command,
974
+ success: true,
975
+ taskId,
976
+ pid: childPid,
977
+ exitCode,
978
+ durationMs,
979
+ timeToFirstOutputMs,
980
+ promptLength,
981
+ usage,
982
+ logs: accumulatedLogs,
983
+ });
984
+ return;
985
+ }
986
+ const providerError = this.parseProviderError(stderr, stdout, exitCode);
987
+ if (exitCode !== 0 || providerError.error) {
988
+ const errorMessage = providerError.message || stderr || `Exit code ${exitCode}`;
989
+ this.appendTaskLog(taskId, 'ERROR', `${this.name} CLI failed: ${errorMessage}`);
990
+ resolve({
991
+ content: '',
992
+ provider: this.name,
993
+ command,
994
+ success: false,
995
+ error: `${this.name} CLI execute failed: ${errorMessage}`,
996
+ taskId,
997
+ pid: childPid,
998
+ exitCode,
999
+ durationMs,
1000
+ timeToFirstOutputMs,
1001
+ promptLength,
1002
+ });
1003
+ return;
1004
+ }
1005
+ this.appendTaskLog(taskId, 'INFO', `${this.name} execute completed successfully`);
1006
+ let parsedContent = stdout.trim();
1007
+ try {
1008
+ JSON.parse(stdout);
1009
+ parsedContent = stdout.trim();
1010
+ this.appendTaskLog(taskId, 'INFO', 'JSON output detected and validated');
1011
+ }
1012
+ catch (jsonError) {
1013
+ this.appendTaskLog(taskId, 'INFO', 'Plain text output (not JSON)');
1014
+ }
1015
+ const filteredContent = this.filterRuntimeLogs(parsedContent);
1016
+ const usage = this.parseUsage(stdout);
1017
+ resolve({
1018
+ content: filteredContent,
1019
+ provider: this.name,
1020
+ command,
1021
+ success: true,
1022
+ taskId,
1023
+ pid: childPid,
1024
+ exitCode,
1025
+ durationMs,
1026
+ timeToFirstOutputMs,
1027
+ promptLength,
1028
+ usage,
1029
+ logs: accumulatedLogs,
1030
+ });
1031
+ });
1032
+ child.on('error', (error) => {
1033
+ const durationMs = Date.now() - startTime;
1034
+ const timeToFirstOutputMs = firstOutputAt !== undefined ? firstOutputAt - startTime : undefined;
1035
+ this.appendTaskLog(taskId, 'ERROR', `Process error: ${error.message}`);
1036
+ resolve({
1037
+ content: '',
1038
+ provider: this.name,
1039
+ command,
1040
+ success: false,
1041
+ error: error.code === 'ENOENT' ? this.getNotInstalledMessage() : error.message,
1042
+ taskId,
1043
+ pid: childPid,
1044
+ exitCode: null,
1045
+ durationMs,
1046
+ timeToFirstOutputMs,
1047
+ promptLength,
1048
+ });
1049
+ });
1050
+ const pipedContext = this.buildPipedContext(prompt, options);
1051
+ try {
1052
+ if (pipedContext && this.shouldPipeContext(options)) {
1053
+ child.stdin.write(pipedContext);
1054
+ if (!pipedContext.endsWith('\n')) {
1055
+ child.stdin.write('\n');
1056
+ }
1057
+ }
1058
+ if (!this.getPromptInArgs()) {
1059
+ child.stdin.write(prompt);
1060
+ }
1061
+ }
1062
+ catch (stdinError) {
1063
+ if (stdinError.code !== 'EPIPE') {
1064
+ this.logger.warn(`stdin write error: ${stdinError.message}`);
1065
+ }
1066
+ }
1067
+ finally {
1068
+ setImmediate(() => {
1069
+ try {
1070
+ child.stdin.end();
1071
+ }
1072
+ catch (endError) {
1073
+ if (endError.code !== 'EPIPE') {
1074
+ this.logger.warn(`stdin.end() error: ${endError.message}`);
1075
+ }
1076
+ }
1077
+ });
1078
+ }
1079
+ const timeout = setTimeout(() => {
1080
+ const durationMs = Date.now() - startTime;
1081
+ const timeToFirstOutputMs = firstOutputAt !== undefined ? firstOutputAt - startTime : undefined;
1082
+ child.kill();
1083
+ resolve({
1084
+ content: '',
1085
+ provider: this.name,
1086
+ command,
1087
+ success: false,
1088
+ error: `${this.name} CLI execute timeout`,
1089
+ taskId,
1090
+ pid: childPid,
1091
+ exitCode: null,
1092
+ durationMs,
1093
+ timeToFirstOutputMs,
1094
+ promptLength,
1095
+ });
1096
+ }, options.timeout || this.getDefaultExecuteTimeout());
1097
+ child.on('close', () => clearTimeout(timeout));
1098
+ });
1099
+ }
1100
+ catch (error) {
1101
+ this.logger.error(`${this.name} execute failed: ${error.message}`, error.stack);
1102
+ return {
1103
+ content: '',
1104
+ provider: this.name,
1105
+ command: `${this.getCliCommand()} execute (error)`,
1106
+ success: false,
1107
+ error: error.message || 'Unknown error occurred',
1108
+ taskId,
1109
+ exitCode: null,
1110
+ promptLength,
1111
+ };
1112
+ }
1113
+ }
1114
+ shouldPipeContext(_options) {
1115
+ return true;
1116
+ }
1117
+ notifyProcessStart(options, pid) {
1118
+ if (typeof options.onProcessStart !== 'function' || typeof pid !== 'number') {
1119
+ return;
1120
+ }
1121
+ try {
1122
+ options.onProcessStart(pid);
1123
+ }
1124
+ catch (error) {
1125
+ this.logger.warn(`onProcessStart callback failed: ${error instanceof Error ? error.message : String(error)}`);
1126
+ }
1127
+ }
1128
+ buildPipedContext(prompt, options) {
1129
+ const normalized = options?.pipedContext?.trim();
1130
+ if (normalized) {
1131
+ if (this.isStructuredPayload(normalized)) {
1132
+ return normalized;
1133
+ }
1134
+ return this.createStructuredPayload(prompt, normalized, options);
1135
+ }
1136
+ if (options?.messages && options.messages.length > 0) {
1137
+ return this.createStructuredPayload(prompt, null, options);
1138
+ }
1139
+ return null;
1140
+ }
1141
+ isStructuredPayload(value) {
1142
+ try {
1143
+ const parsed = JSON.parse(value);
1144
+ return Boolean(parsed && typeof parsed === 'object' && 'prompt' in parsed && 'messages' in parsed);
1145
+ }
1146
+ catch {
1147
+ return false;
1148
+ }
1149
+ }
1150
+ createStructuredPayload(prompt, context, options) {
1151
+ const safeMessages = Array.isArray(options?.messages) ? options.messages : [];
1152
+ const fallbackHistory = safeMessages.length > 0
1153
+ ? safeMessages
1154
+ .map((msg, index) => {
1155
+ const speaker = msg.isAssistant ? 'Assistant' : 'User';
1156
+ return `${index + 1}. ${speaker}: ${msg.text}`;
1157
+ })
1158
+ .join('\n')
1159
+ : '';
1160
+ const normalizedContext = context?.trim() ?? '';
1161
+ const payload = {
1162
+ version: '1.0',
1163
+ agent: {
1164
+ id: options?.agentId ?? null,
1165
+ provider: this.name,
1166
+ mode: options?.additionalArgs?.includes('--execute') ? 'execute' : 'query',
1167
+ model: options?.model ?? null,
1168
+ },
1169
+ prompt,
1170
+ context: normalizedContext,
1171
+ messages: safeMessages,
1172
+ metadata: {
1173
+ generatedAt: new Date().toISOString(),
1174
+ messageCount: safeMessages.length,
1175
+ formattedHistory: fallbackHistory,
1176
+ originalContext: normalizedContext,
1177
+ },
1178
+ };
1179
+ return JSON.stringify(payload);
1180
+ }
1181
+ }
1182
+ exports.BaseAIProvider = BaseAIProvider;
1183
+ //# sourceMappingURL=base-ai.provider.js.map