@crewx/cli 0.8.0-rc.66 → 0.8.0-rc.82

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 (281) hide show
  1. package/bin/crewx +2 -0
  2. package/dist/bootstrap/crewx-cli.d.ts +11 -0
  3. package/dist/bootstrap/crewx-cli.js +31 -0
  4. package/dist/builtin.d.ts +15 -0
  5. package/dist/{cli/builtin.handler.js → builtin.js} +21 -7
  6. package/dist/commands/agent.d.ts +12 -0
  7. package/dist/commands/agent.js +246 -0
  8. package/dist/commands/doctor.d.ts +12 -0
  9. package/dist/commands/doctor.js +190 -0
  10. package/dist/commands/execute.d.ts +21 -0
  11. package/dist/commands/execute.js +117 -0
  12. package/dist/commands/hook/install.d.ts +21 -0
  13. package/dist/commands/hook/install.js +175 -0
  14. package/dist/commands/hook/paths.d.ts +19 -0
  15. package/dist/commands/hook/paths.js +94 -0
  16. package/dist/commands/hook/status.d.ts +7 -0
  17. package/dist/commands/hook/status.js +86 -0
  18. package/dist/commands/hook/uninstall.d.ts +8 -0
  19. package/dist/commands/hook/uninstall.js +71 -0
  20. package/dist/commands/hook-dispatch.d.ts +15 -0
  21. package/dist/commands/hook-dispatch.js +180 -0
  22. package/dist/commands/init.d.ts +24 -0
  23. package/dist/commands/init.js +133 -0
  24. package/dist/commands/kill.d.ts +12 -0
  25. package/dist/commands/kill.js +49 -0
  26. package/dist/commands/log.d.ts +13 -0
  27. package/dist/commands/log.js +97 -0
  28. package/dist/commands/parse-agent-message.d.ts +31 -0
  29. package/dist/commands/parse-agent-message.js +52 -0
  30. package/dist/commands/parse-common-flags.d.ts +36 -0
  31. package/dist/commands/parse-common-flags.js +105 -0
  32. package/dist/commands/ps.d.ts +12 -0
  33. package/dist/commands/ps.js +71 -0
  34. package/dist/commands/query.d.ts +21 -0
  35. package/dist/commands/query.js +117 -0
  36. package/dist/commands/result.d.ts +13 -0
  37. package/dist/commands/result.js +73 -0
  38. package/dist/commands/slack.d.ts +12 -0
  39. package/dist/commands/slack.js +559 -0
  40. package/dist/commands/task-db.d.ts +33 -0
  41. package/dist/commands/task-db.js +107 -0
  42. package/dist/examples/deny-secrets-plugin.d.ts +22 -0
  43. package/dist/examples/deny-secrets-plugin.js +40 -0
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.js +5 -0
  46. package/dist/logging.d.ts +21 -0
  47. package/dist/logging.js +86 -0
  48. package/dist/main.d.ts +10 -0
  49. package/dist/main.js +246 -256
  50. package/dist/plugins/examples/echo-hook.d.ts +24 -0
  51. package/dist/plugins/examples/echo-hook.js +60 -0
  52. package/dist/plugins/examples/verify-echo-hook.d.ts +8 -0
  53. package/dist/plugins/examples/verify-echo-hook.js +47 -0
  54. package/dist/plugins/sqlite-tracing.d.ts +13 -0
  55. package/dist/plugins/sqlite-tracing.js +20 -0
  56. package/dist/register-builtin-tools.d.ts +5 -0
  57. package/dist/register-builtin-tools.js +9 -0
  58. package/dist/slack/file-download.d.ts +17 -0
  59. package/dist/slack/file-download.js +134 -0
  60. package/dist/slack/markdown.d.ts +5 -0
  61. package/dist/slack/markdown.js +33 -0
  62. package/dist/utils/env-defaults.d.ts +5 -0
  63. package/dist/utils/env-defaults.js +10 -0
  64. package/dist/utils/version.d.ts +1 -0
  65. package/dist/utils/version.js +28 -0
  66. package/package.json +32 -115
  67. package/README.md +0 -663
  68. package/dist/ai-provider.service.d.ts +0 -36
  69. package/dist/ai-provider.service.js +0 -315
  70. package/dist/ai-provider.service.js.map +0 -1
  71. package/dist/ai.service.d.ts +0 -17
  72. package/dist/ai.service.js +0 -51
  73. package/dist/ai.service.js.map +0 -1
  74. package/dist/app.module.d.ts +0 -5
  75. package/dist/app.module.js +0 -165
  76. package/dist/app.module.js.map +0 -1
  77. package/dist/cli/agent.handler.d.ts +0 -2
  78. package/dist/cli/agent.handler.js +0 -186
  79. package/dist/cli/agent.handler.js.map +0 -1
  80. package/dist/cli/builtin.handler.d.ts +0 -3
  81. package/dist/cli/builtin.handler.js.map +0 -1
  82. package/dist/cli/chat.handler.d.ts +0 -20
  83. package/dist/cli/chat.handler.js +0 -446
  84. package/dist/cli/chat.handler.js.map +0 -1
  85. package/dist/cli/cli.handler.d.ts +0 -4
  86. package/dist/cli/cli.handler.js +0 -119
  87. package/dist/cli/cli.handler.js.map +0 -1
  88. package/dist/cli/doctor.handler.d.ts +0 -38
  89. package/dist/cli/doctor.handler.js +0 -495
  90. package/dist/cli/doctor.handler.js.map +0 -1
  91. package/dist/cli/execute.handler.d.ts +0 -2
  92. package/dist/cli/execute.handler.js +0 -376
  93. package/dist/cli/execute.handler.js.map +0 -1
  94. package/dist/cli/help.handler.d.ts +0 -2
  95. package/dist/cli/help.handler.js +0 -10
  96. package/dist/cli/help.handler.js.map +0 -1
  97. package/dist/cli/init.handler.d.ts +0 -26
  98. package/dist/cli/init.handler.js +0 -450
  99. package/dist/cli/init.handler.js.map +0 -1
  100. package/dist/cli/log.handler.d.ts +0 -2
  101. package/dist/cli/log.handler.js +0 -69
  102. package/dist/cli/log.handler.js.map +0 -1
  103. package/dist/cli/mcp.handler.d.ts +0 -3
  104. package/dist/cli/mcp.handler.js +0 -121
  105. package/dist/cli/mcp.handler.js.map +0 -1
  106. package/dist/cli/query.handler.d.ts +0 -2
  107. package/dist/cli/query.handler.js +0 -392
  108. package/dist/cli/query.handler.js.map +0 -1
  109. package/dist/cli/skill.handler.d.ts +0 -2
  110. package/dist/cli/skill.handler.js +0 -252
  111. package/dist/cli/skill.handler.js.map +0 -1
  112. package/dist/cli/slack-files.handler.d.ts +0 -2
  113. package/dist/cli/slack-files.handler.js +0 -291
  114. package/dist/cli/slack-files.handler.js.map +0 -1
  115. package/dist/cli/template.handler.d.ts +0 -2
  116. package/dist/cli/template.handler.js +0 -188
  117. package/dist/cli/template.handler.js.map +0 -1
  118. package/dist/cli/templates.handler.d.ts +0 -2
  119. package/dist/cli/templates.handler.js +0 -100
  120. package/dist/cli/templates.handler.js.map +0 -1
  121. package/dist/cli-options.d.ts +0 -40
  122. package/dist/cli-options.js +0 -371
  123. package/dist/cli-options.js.map +0 -1
  124. package/dist/config/timeout.config.d.ts +0 -14
  125. package/dist/config/timeout.config.js +0 -34
  126. package/dist/config/timeout.config.js.map +0 -1
  127. package/dist/conversation/base-conversation-history.provider.d.ts +0 -12
  128. package/dist/conversation/base-conversation-history.provider.js +0 -45
  129. package/dist/conversation/base-conversation-history.provider.js.map +0 -1
  130. package/dist/conversation/cli-box-reader.adapter.d.ts +0 -6
  131. package/dist/conversation/cli-box-reader.adapter.js +0 -10
  132. package/dist/conversation/cli-box-reader.adapter.js.map +0 -1
  133. package/dist/conversation/cli-conversation-history.provider.d.ts +0 -16
  134. package/dist/conversation/cli-conversation-history.provider.js +0 -112
  135. package/dist/conversation/cli-conversation-history.provider.js.map +0 -1
  136. package/dist/conversation/cli-task-reader.adapter.d.ts +0 -6
  137. package/dist/conversation/cli-task-reader.adapter.js +0 -25
  138. package/dist/conversation/cli-task-reader.adapter.js.map +0 -1
  139. package/dist/conversation/conversation-provider.factory.d.ts +0 -10
  140. package/dist/conversation/conversation-provider.factory.js +0 -50
  141. package/dist/conversation/conversation-provider.factory.js.map +0 -1
  142. package/dist/conversation/index.d.ts +0 -8
  143. package/dist/conversation/index.js +0 -29
  144. package/dist/conversation/index.js.map +0 -1
  145. package/dist/conversation/slack-conversation-history.provider.d.ts +0 -29
  146. package/dist/conversation/slack-conversation-history.provider.js +0 -302
  147. package/dist/conversation/slack-conversation-history.provider.js.map +0 -1
  148. package/dist/crewx.tool.d.ts +0 -360
  149. package/dist/crewx.tool.js +0 -2531
  150. package/dist/crewx.tool.js.map +0 -1
  151. package/dist/crewx.tool.spec.d.ts +0 -1
  152. package/dist/crewx.tool.spec.js +0 -222
  153. package/dist/crewx.tool.spec.js.map +0 -1
  154. package/dist/guards/bearer-auth.guard.d.ts +0 -7
  155. package/dist/guards/bearer-auth.guard.js +0 -44
  156. package/dist/guards/bearer-auth.guard.js.map +0 -1
  157. package/dist/health.controller.d.ts +0 -6
  158. package/dist/health.controller.js +0 -32
  159. package/dist/health.controller.js.map +0 -1
  160. package/dist/main.js.map +0 -1
  161. package/dist/mcp.controller.d.ts +0 -8
  162. package/dist/mcp.controller.js +0 -62
  163. package/dist/mcp.controller.js.map +0 -1
  164. package/dist/package.json +0 -3
  165. package/dist/providers/dynamic-provider.factory.d.ts +0 -17
  166. package/dist/providers/dynamic-provider.factory.js +0 -138
  167. package/dist/providers/dynamic-provider.factory.js.map +0 -1
  168. package/dist/providers/logger.adapter.d.ts +0 -7
  169. package/dist/providers/logger.adapter.js +0 -107
  170. package/dist/providers/logger.adapter.js.map +0 -1
  171. package/dist/services/agent-loader.service.d.ts +0 -35
  172. package/dist/services/agent-loader.service.js +0 -623
  173. package/dist/services/agent-loader.service.js.map +0 -1
  174. package/dist/services/auth.service.d.ts +0 -9
  175. package/dist/services/auth.service.js +0 -47
  176. package/dist/services/auth.service.js.map +0 -1
  177. package/dist/services/config-validator.service.d.ts +0 -29
  178. package/dist/services/config-validator.service.js +0 -483
  179. package/dist/services/config-validator.service.js.map +0 -1
  180. package/dist/services/config.service.d.ts +0 -45
  181. package/dist/services/config.service.js +0 -352
  182. package/dist/services/config.service.js.map +0 -1
  183. package/dist/services/document-loader.service.d.ts +0 -26
  184. package/dist/services/document-loader.service.js +0 -186
  185. package/dist/services/document-loader.service.js.map +0 -1
  186. package/dist/services/help.service.d.ts +0 -5
  187. package/dist/services/help.service.js +0 -139
  188. package/dist/services/help.service.js.map +0 -1
  189. package/dist/services/intelligent-compression.service.d.ts +0 -20
  190. package/dist/services/intelligent-compression.service.js +0 -179
  191. package/dist/services/intelligent-compression.service.js.map +0 -1
  192. package/dist/services/mcp-client.service.d.ts +0 -26
  193. package/dist/services/mcp-client.service.js +0 -81
  194. package/dist/services/mcp-client.service.js.map +0 -1
  195. package/dist/services/parallel-processing.service.d.ts +0 -108
  196. package/dist/services/parallel-processing.service.js +0 -333
  197. package/dist/services/parallel-processing.service.js.map +0 -1
  198. package/dist/services/provider-bridge.service.d.ts +0 -35
  199. package/dist/services/provider-bridge.service.js +0 -224
  200. package/dist/services/provider-bridge.service.js.map +0 -1
  201. package/dist/services/remote-agent.service.d.ts +0 -50
  202. package/dist/services/remote-agent.service.js +0 -171
  203. package/dist/services/remote-agent.service.js.map +0 -1
  204. package/dist/services/result-formatter.service.d.ts +0 -27
  205. package/dist/services/result-formatter.service.js +0 -126
  206. package/dist/services/result-formatter.service.js.map +0 -1
  207. package/dist/services/skill-loader.service.d.ts +0 -15
  208. package/dist/services/skill-loader.service.js +0 -278
  209. package/dist/services/skill-loader.service.js.map +0 -1
  210. package/dist/services/skill.service.d.ts +0 -69
  211. package/dist/services/skill.service.js +0 -779
  212. package/dist/services/skill.service.js.map +0 -1
  213. package/dist/services/skill.service.spec.d.ts +0 -1
  214. package/dist/services/skill.service.spec.js +0 -168
  215. package/dist/services/skill.service.spec.js.map +0 -1
  216. package/dist/services/task-management.service.d.ts +0 -71
  217. package/dist/services/task-management.service.js +0 -324
  218. package/dist/services/task-management.service.js.map +0 -1
  219. package/dist/services/template.service.d.ts +0 -61
  220. package/dist/services/template.service.js +0 -416
  221. package/dist/services/template.service.js.map +0 -1
  222. package/dist/services/tool-call.service.d.ts +0 -16
  223. package/dist/services/tool-call.service.js +0 -302
  224. package/dist/services/tool-call.service.js.map +0 -1
  225. package/dist/services/tracing.service.d.ts +0 -197
  226. package/dist/services/tracing.service.js +0 -1267
  227. package/dist/services/tracing.service.js.map +0 -1
  228. package/dist/slack/formatters/message.formatter.d.ts +0 -43
  229. package/dist/slack/formatters/message.formatter.js +0 -505
  230. package/dist/slack/formatters/message.formatter.js.map +0 -1
  231. package/dist/slack/services/slack-file-download.service.d.ts +0 -58
  232. package/dist/slack/services/slack-file-download.service.js +0 -558
  233. package/dist/slack/services/slack-file-download.service.js.map +0 -1
  234. package/dist/slack/slack-bot.d.ts +0 -33
  235. package/dist/slack/slack-bot.js +0 -568
  236. package/dist/slack/slack-bot.js.map +0 -1
  237. package/dist/stderr.logger.d.ts +0 -8
  238. package/dist/stderr.logger.js +0 -26
  239. package/dist/stderr.logger.js.map +0 -1
  240. package/dist/types/usage.types.d.ts +0 -107
  241. package/dist/types/usage.types.js +0 -3
  242. package/dist/types/usage.types.js.map +0 -1
  243. package/dist/utils/config-utils.d.ts +0 -15
  244. package/dist/utils/config-utils.js +0 -69
  245. package/dist/utils/config-utils.js.map +0 -1
  246. package/dist/utils/extract-text.d.ts +0 -1
  247. package/dist/utils/extract-text.js +0 -15
  248. package/dist/utils/extract-text.js.map +0 -1
  249. package/dist/utils/mcp-installer.d.ts +0 -20
  250. package/dist/utils/mcp-installer.js +0 -199
  251. package/dist/utils/mcp-installer.js.map +0 -1
  252. package/dist/utils/project-hash.d.ts +0 -6
  253. package/dist/utils/project-hash.js +0 -70
  254. package/dist/utils/project-hash.js.map +0 -1
  255. package/dist/utils/simple-security.d.ts +0 -3
  256. package/dist/utils/simple-security.js +0 -20
  257. package/dist/utils/simple-security.js.map +0 -1
  258. package/dist/utils/stdin-utils.d.ts +0 -6
  259. package/dist/utils/stdin-utils.js +0 -109
  260. package/dist/utils/stdin-utils.js.map +0 -1
  261. package/dist/utils/template-processor.d.ts +0 -27
  262. package/dist/utils/template-processor.js +0 -395
  263. package/dist/utils/template-processor.js.map +0 -1
  264. package/dist/utils/terminal-message-formatter.d.ts +0 -23
  265. package/dist/utils/terminal-message-formatter.js +0 -136
  266. package/dist/utils/terminal-message-formatter.js.map +0 -1
  267. package/dist/version.d.ts +0 -1
  268. package/dist/version.js +0 -17
  269. package/dist/version.js.map +0 -1
  270. package/dist/workspace.service.d.ts +0 -44
  271. package/dist/workspace.service.js +0 -299
  272. package/dist/workspace.service.js.map +0 -1
  273. package/scripts/backfill-tokens.js +0 -218
  274. package/scripts/postbuild-cli.mjs +0 -88
  275. package/scripts/postinstall-cli.mjs +0 -30
  276. package/templates/agents/default.yaml +0 -490
  277. package/templates/agents/minimal.yaml +0 -16
  278. package/templates/documents/conversation-history-default.hbs +0 -17
  279. package/templates/documents/crewx-manual.md +0 -2278
  280. package/templates/documents/crewx-quick-guide.md +0 -147
  281. package/templates/versions.json +0 -19
@@ -1,1267 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
- return c > 3 && r && Object.defineProperty(target, key, r), r;
23
- };
24
- var __importStar = (this && this.__importStar) || (function () {
25
- var ownKeys = function(o) {
26
- ownKeys = Object.getOwnPropertyNames || function (o) {
27
- var ar = [];
28
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
- return ar;
30
- };
31
- return ownKeys(o);
32
- };
33
- return function (mod) {
34
- if (mod && mod.__esModule) return mod;
35
- var result = {};
36
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
- __setModuleDefault(result, mod);
38
- return result;
39
- };
40
- })();
41
- var __metadata = (this && this.__metadata) || function (k, v) {
42
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
- };
44
- var __param = (this && this.__param) || function (paramIndex, decorator) {
45
- return function (target, key) { decorator(target, key, paramIndex); }
46
- };
47
- var TracingService_1;
48
- Object.defineProperty(exports, "__esModule", { value: true });
49
- exports.TracingService = exports.SpanKind = exports.TaskStatus = void 0;
50
- const common_1 = require("@nestjs/common");
51
- const fs = __importStar(require("fs"));
52
- const os = __importStar(require("os"));
53
- const path = __importStar(require("path"));
54
- const sdk_1 = require("@crewx/sdk");
55
- let Database = null;
56
- try {
57
- Database = require('node-sqlite3-wasm').Database;
58
- }
59
- catch {
60
- }
61
- var TaskStatus;
62
- (function (TaskStatus) {
63
- TaskStatus["PENDING"] = "pending";
64
- TaskStatus["RUNNING"] = "running";
65
- TaskStatus["SUCCESS"] = "success";
66
- TaskStatus["FAILED"] = "failed";
67
- })(TaskStatus || (exports.TaskStatus = TaskStatus = {}));
68
- var SpanKind;
69
- (function (SpanKind) {
70
- SpanKind["INTERNAL"] = "internal";
71
- SpanKind["CLIENT"] = "client";
72
- SpanKind["SERVER"] = "server";
73
- SpanKind["PRODUCER"] = "producer";
74
- SpanKind["CONSUMER"] = "consumer";
75
- })(SpanKind || (exports.SpanKind = SpanKind = {}));
76
- let TracingService = TracingService_1 = class TracingService {
77
- constructor(options) {
78
- this.logger = new common_1.Logger(TracingService_1.name);
79
- this.db = null;
80
- if (options?.dbPath) {
81
- this.dbPath = options.dbPath;
82
- return;
83
- }
84
- this.dbPath = this.resolveDbPath();
85
- }
86
- onModuleInit() {
87
- this.initializeDatabase();
88
- }
89
- onModuleDestroy() {
90
- this.close();
91
- }
92
- initializeDatabase() {
93
- if (!Database) {
94
- this.logger.warn('node-sqlite3-wasm not available — tracing disabled');
95
- return;
96
- }
97
- try {
98
- const dir = path.dirname(this.dbPath);
99
- if (!fs.existsSync(dir)) {
100
- fs.mkdirSync(dir, { recursive: true });
101
- }
102
- this.migrateDbFileName();
103
- this.db = new Database(this.dbPath);
104
- this.db.exec('PRAGMA journal_mode = DELETE');
105
- this.db.exec('PRAGMA foreign_keys = ON');
106
- this.db.exec(`
107
- CREATE TABLE IF NOT EXISTS tasks (
108
- id TEXT PRIMARY KEY,
109
- agent_id TEXT NOT NULL,
110
- user_id TEXT,
111
- prompt TEXT NOT NULL,
112
- mode TEXT NOT NULL CHECK (mode IN ('query', 'execute')),
113
- status TEXT NOT NULL CHECK (status IN ('pending', 'running', 'success', 'failed')),
114
- result TEXT,
115
- error TEXT,
116
- started_at TEXT NOT NULL,
117
- completed_at TEXT,
118
- duration_ms INTEGER,
119
- metadata TEXT,
120
- workspace_id TEXT,
121
- workspace_name TEXT
122
- )
123
- `);
124
- this.db.exec(`
125
- CREATE TABLE IF NOT EXISTS spans (
126
- id TEXT PRIMARY KEY,
127
- task_id TEXT NOT NULL,
128
- parent_span_id TEXT,
129
- name TEXT NOT NULL,
130
- kind TEXT NOT NULL CHECK (kind IN ('internal', 'client', 'server', 'producer', 'consumer')),
131
- status TEXT NOT NULL CHECK (status IN ('ok', 'error')),
132
- started_at TEXT NOT NULL,
133
- completed_at TEXT,
134
- duration_ms INTEGER,
135
- input TEXT,
136
- output TEXT,
137
- error TEXT,
138
- attributes TEXT,
139
- FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
140
- FOREIGN KEY (parent_span_id) REFERENCES spans(id) ON DELETE SET NULL
141
- )
142
- `);
143
- this.db.exec(`
144
- CREATE INDEX IF NOT EXISTS idx_tasks_agent_id ON tasks(agent_id);
145
- CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
146
- CREATE INDEX IF NOT EXISTS idx_tasks_started_at ON tasks(started_at);
147
- CREATE INDEX IF NOT EXISTS idx_spans_task_id ON spans(task_id);
148
- CREATE INDEX IF NOT EXISTS idx_spans_parent_span_id ON spans(parent_span_id);
149
- `);
150
- this.migrateSchemaPhase3a();
151
- this.migrateSchemaPhase4();
152
- this.migrateSchemaPhase5();
153
- this.migrateWorkspaceRenaming();
154
- this.migrateSchemaPhase6();
155
- this.migrateSchemaPhase7();
156
- this.createToolCallsTable();
157
- this.createThreadBoxesTable();
158
- this.logger.log(`Tracing database initialized at ${this.dbPath}`);
159
- }
160
- catch (error) {
161
- this.logger.error(`Failed to initialize tracing database: ${error instanceof Error ? error.message : String(error)}`);
162
- }
163
- }
164
- columnExists(tableName, columnName) {
165
- if (!this.db)
166
- return false;
167
- try {
168
- const result = this.db.all(`PRAGMA table_info(${tableName})`);
169
- return result.some(col => col.name === columnName);
170
- }
171
- catch {
172
- return false;
173
- }
174
- }
175
- migrateSchemaPhase3a() {
176
- if (!this.db)
177
- return;
178
- const newColumns = [
179
- { name: 'trace_id', type: 'TEXT' },
180
- { name: 'parent_task_id', type: 'TEXT' },
181
- { name: 'caller_agent_id', type: 'TEXT' },
182
- { name: 'model', type: 'TEXT' },
183
- { name: 'platform', type: 'TEXT', default: "'cli'" },
184
- { name: 'crewx_version', type: 'TEXT' },
185
- { name: 'input_tokens', type: 'INTEGER', default: '0' },
186
- { name: 'output_tokens', type: 'INTEGER', default: '0' },
187
- { name: 'cost_usd', type: 'REAL', default: '0' },
188
- ];
189
- let migratedCount = 0;
190
- for (const col of newColumns) {
191
- if (!this.columnExists('tasks', col.name)) {
192
- try {
193
- const defaultClause = col.default ? ` DEFAULT ${col.default}` : '';
194
- this.db.exec(`ALTER TABLE tasks ADD COLUMN ${col.name} ${col.type}${defaultClause}`);
195
- migratedCount++;
196
- this.logger.debug(`Added column tasks.${col.name}`);
197
- }
198
- catch (error) {
199
- this.logger.warn(`Failed to add column ${col.name}: ${error instanceof Error ? error.message : String(error)}`);
200
- }
201
- }
202
- }
203
- const indexes = [
204
- { name: 'idx_tasks_trace_id', column: 'trace_id' },
205
- { name: 'idx_tasks_parent_task_id', column: 'parent_task_id' },
206
- { name: 'idx_tasks_crewx_version', column: 'crewx_version' },
207
- ];
208
- for (const idx of indexes) {
209
- try {
210
- this.db.exec(`CREATE INDEX IF NOT EXISTS ${idx.name} ON tasks(${idx.column})`);
211
- }
212
- catch (error) {
213
- this.logger.warn(`Failed to create index ${idx.name}: ${error instanceof Error ? error.message : String(error)}`);
214
- }
215
- }
216
- if (migratedCount > 0) {
217
- this.logger.log(`Phase 3a migration: Added ${migratedCount} new columns to tasks table`);
218
- }
219
- }
220
- migrateSchemaPhase4() {
221
- if (!this.db)
222
- return;
223
- const newColumns = [
224
- { name: 'pid', type: 'INTEGER' },
225
- { name: 'rendered_prompt', type: 'TEXT' },
226
- { name: 'command', type: 'TEXT' },
227
- { name: 'coding_agent_command', type: 'TEXT' },
228
- { name: 'exit_code', type: 'INTEGER' },
229
- { name: 'logs', type: 'TEXT' },
230
- ];
231
- let migratedCount = 0;
232
- for (const col of newColumns) {
233
- if (!this.columnExists('tasks', col.name)) {
234
- try {
235
- this.db.exec(`ALTER TABLE tasks ADD COLUMN ${col.name} ${col.type}`);
236
- migratedCount++;
237
- this.logger.debug(`Added column tasks.${col.name}`);
238
- }
239
- catch (error) {
240
- this.logger.warn(`Failed to add column ${col.name}: ${error instanceof Error ? error.message : String(error)}`);
241
- }
242
- }
243
- }
244
- try {
245
- this.db.exec(`CREATE INDEX IF NOT EXISTS idx_tasks_pid ON tasks(pid)`);
246
- }
247
- catch (error) {
248
- this.logger.warn(`Failed to create index idx_tasks_pid: ${error instanceof Error ? error.message : String(error)}`);
249
- }
250
- if (migratedCount > 0) {
251
- this.logger.log(`Phase 4 migration: Added ${migratedCount} new columns to tasks table`);
252
- }
253
- }
254
- migrateSchemaPhase5() {
255
- if (!this.db)
256
- return;
257
- const columnsToEnsure = [
258
- { newName: 'workspace_id', oldName: 'project_id', type: 'TEXT' },
259
- { newName: 'workspace_name', oldName: 'project_name', type: 'TEXT' },
260
- ];
261
- let migratedCount = 0;
262
- for (const col of columnsToEnsure) {
263
- if (!this.columnExists('tasks', col.newName) && !this.columnExists('tasks', col.oldName)) {
264
- try {
265
- this.db.exec(`ALTER TABLE tasks ADD COLUMN ${col.newName} ${col.type}`);
266
- migratedCount++;
267
- this.logger.debug(`Added column tasks.${col.newName}`);
268
- }
269
- catch (error) {
270
- this.logger.warn(`Failed to add column ${col.newName}: ${error instanceof Error ? error.message : String(error)}`);
271
- }
272
- }
273
- }
274
- try {
275
- this.db.exec(`CREATE INDEX IF NOT EXISTS idx_tasks_workspace_id ON tasks(workspace_id)`);
276
- }
277
- catch (error) {
278
- }
279
- if (migratedCount > 0) {
280
- this.logger.log(`Phase 5 migration: Added ${migratedCount} workspace columns to tasks table`);
281
- }
282
- }
283
- migrateWorkspaceRenaming() {
284
- if (!this.db)
285
- return;
286
- const projectsTableExists = !!this.db.get("SELECT name FROM sqlite_master WHERE type='table' AND name='projects'");
287
- const workspacesTableExists = !!this.db.get("SELECT name FROM sqlite_master WHERE type='table' AND name='workspaces'");
288
- if (projectsTableExists && workspacesTableExists) {
289
- try {
290
- if (this.columnExists('projects', 'repo_path')) {
291
- this.db.exec(`
292
- INSERT OR IGNORE INTO workspaces (id, slug, name, workspace_path, is_active, created_at, updated_at)
293
- SELECT id, COALESCE(slug, name, id), COALESCE(name, id), repo_path, 1, COALESCE(created_at, datetime('now')), COALESCE(updated_at, datetime('now'))
294
- FROM projects
295
- `);
296
- }
297
- else if (this.columnExists('projects', 'workspace_path')) {
298
- this.db.exec(`
299
- INSERT OR IGNORE INTO workspaces (id, slug, name, workspace_path, is_active, created_at, updated_at)
300
- SELECT id, COALESCE(slug, name, id), COALESCE(name, id), workspace_path, 1, COALESCE(created_at, datetime('now')), COALESCE(updated_at, datetime('now'))
301
- FROM projects
302
- `);
303
- }
304
- this.db.exec('DROP TABLE projects');
305
- this.logger.log('Workspace renaming migration: merged projects → workspaces, dropped projects table');
306
- }
307
- catch (error) {
308
- this.logger.warn(`Projects merge/drop failed: ${error instanceof Error ? error.message : String(error)}`);
309
- }
310
- }
311
- else if (projectsTableExists && !workspacesTableExists) {
312
- try {
313
- this.db.exec('ALTER TABLE projects RENAME TO workspaces');
314
- if (this.columnExists('workspaces', 'repo_path')) {
315
- this.db.exec('ALTER TABLE workspaces RENAME COLUMN repo_path TO workspace_path');
316
- }
317
- this.logger.log('Workspace renaming migration: projects → workspaces renamed');
318
- }
319
- catch (error) {
320
- this.logger.warn(`Projects table rename failed: ${error instanceof Error ? error.message : String(error)}`);
321
- }
322
- }
323
- if (this.columnExists('tasks', 'project_id') && this.columnExists('tasks', 'workspace_id')) {
324
- try {
325
- this.db.exec(`
326
- UPDATE tasks SET workspace_id = project_id WHERE workspace_id IS NULL AND project_id IS NOT NULL;
327
- UPDATE tasks SET workspace_name = project_name WHERE workspace_name IS NULL AND project_name IS NOT NULL;
328
- `);
329
- this.logger.log('Workspace renaming migration: copied project_id/name → workspace_id/name');
330
- }
331
- catch (error) {
332
- this.logger.warn(`Tasks data copy failed: ${error instanceof Error ? error.message : String(error)}`);
333
- }
334
- }
335
- else if (this.columnExists('tasks', 'project_id') && !this.columnExists('tasks', 'workspace_id')) {
336
- try {
337
- this.db.exec('ALTER TABLE tasks RENAME COLUMN project_id TO workspace_id');
338
- this.db.exec('ALTER TABLE tasks RENAME COLUMN project_name TO workspace_name');
339
- this.logger.log('Workspace renaming migration: tasks columns renamed');
340
- }
341
- catch (error) {
342
- this.logger.warn(`Tasks column renaming failed: ${error instanceof Error ? error.message : String(error)}`);
343
- }
344
- }
345
- if (this.columnExists('tasks', 'project_ref') && this.columnExists('tasks', 'workspace_ref')) {
346
- try {
347
- this.db.exec(`
348
- UPDATE tasks SET workspace_ref = project_ref WHERE workspace_ref IS NULL AND project_ref IS NOT NULL;
349
- `);
350
- }
351
- catch (error) {
352
- this.logger.warn(`Tasks workspace_ref data copy failed: ${error instanceof Error ? error.message : String(error)}`);
353
- }
354
- }
355
- else if (this.columnExists('tasks', 'project_ref') && !this.columnExists('tasks', 'workspace_ref')) {
356
- try {
357
- this.db.exec('ALTER TABLE tasks RENAME COLUMN project_ref TO workspace_ref');
358
- }
359
- catch (error) {
360
- this.logger.warn(`Tasks project_ref renaming failed: ${error instanceof Error ? error.message : String(error)}`);
361
- }
362
- }
363
- if (this.columnExists('threads', 'project_id') && !this.columnExists('threads', 'workspace_id')) {
364
- try {
365
- this.db.exec('ALTER TABLE threads RENAME COLUMN project_id TO workspace_id');
366
- }
367
- catch (error) {
368
- this.logger.warn(`Threads column renaming failed: ${error instanceof Error ? error.message : String(error)}`);
369
- }
370
- }
371
- try {
372
- this.db.exec(`
373
- DROP INDEX IF EXISTS idx_tasks_project_id;
374
- DROP INDEX IF EXISTS idx_tasks_project_ref;
375
- DROP INDEX IF EXISTS idx_threads_project_id;
376
- `);
377
- if (this.columnExists('tasks', 'workspace_id')) {
378
- this.db.exec('CREATE INDEX IF NOT EXISTS idx_tasks_workspace_id ON tasks(workspace_id)');
379
- }
380
- if (this.columnExists('tasks', 'workspace_ref')) {
381
- this.db.exec('CREATE INDEX IF NOT EXISTS idx_tasks_workspace_ref ON tasks(workspace_ref)');
382
- }
383
- if (this.columnExists('threads', 'workspace_id')) {
384
- this.db.exec('CREATE INDEX IF NOT EXISTS idx_threads_workspace_id ON threads(workspace_id)');
385
- }
386
- }
387
- catch (error) {
388
- this.logger.warn(`Index cleanup failed: ${error instanceof Error ? error.message : String(error)}`);
389
- }
390
- if (workspacesTableExists || !projectsTableExists) {
391
- try {
392
- const hashSlugs = this.db.all('SELECT id, name, slug FROM workspaces WHERE slug = id');
393
- for (const row of hashSlugs) {
394
- try {
395
- this.db.run('UPDATE workspaces SET slug = ? WHERE id = ?', [row.name, row.id]);
396
- }
397
- catch {
398
- this.logger.warn(`Could not update slug for workspace ${row.name}, keeping hash-based slug`);
399
- }
400
- }
401
- }
402
- catch {
403
- }
404
- }
405
- }
406
- migrateSchemaPhase6() {
407
- if (!this.db)
408
- return;
409
- try {
410
- this.db.exec(`
411
- CREATE TABLE IF NOT EXISTS workspaces (
412
- id TEXT PRIMARY KEY,
413
- slug TEXT NOT NULL UNIQUE,
414
- name TEXT NOT NULL,
415
- workspace_path TEXT,
416
- is_active INTEGER NOT NULL DEFAULT 1,
417
- created_at TEXT NOT NULL,
418
- updated_at TEXT NOT NULL
419
- )
420
- `);
421
- }
422
- catch (error) {
423
- this.logger.warn(`Failed to create workspaces table: ${error instanceof Error ? error.message : String(error)}`);
424
- }
425
- try {
426
- this.db.exec(`
427
- CREATE TABLE IF NOT EXISTS threads (
428
- id TEXT PRIMARY KEY,
429
- workspace_id TEXT,
430
- platform TEXT NOT NULL DEFAULT 'cli',
431
- title TEXT,
432
- first_message TEXT,
433
- last_message TEXT,
434
- message_count INTEGER NOT NULL DEFAULT 0,
435
- created_at TEXT NOT NULL,
436
- updated_at TEXT NOT NULL,
437
- metadata TEXT,
438
- FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE SET NULL
439
- )
440
- `);
441
- }
442
- catch (error) {
443
- this.logger.warn(`Failed to create threads table: ${error instanceof Error ? error.message : String(error)}`);
444
- }
445
- const columnsToEnsure = [
446
- { newName: 'thread_id', oldName: 'thread_id', type: 'TEXT' },
447
- { newName: 'workspace_ref', oldName: 'project_ref', type: 'TEXT' },
448
- ];
449
- let migratedCount = 0;
450
- for (const col of columnsToEnsure) {
451
- if (!this.columnExists('tasks', col.newName) && !this.columnExists('tasks', col.oldName)) {
452
- try {
453
- this.db.exec(`ALTER TABLE tasks ADD COLUMN ${col.newName} ${col.type}`);
454
- migratedCount++;
455
- this.logger.debug(`Added column tasks.${col.newName}`);
456
- }
457
- catch (error) {
458
- this.logger.warn(`Failed to add column ${col.newName}: ${error instanceof Error ? error.message : String(error)}`);
459
- }
460
- }
461
- }
462
- try {
463
- this.db.exec(`CREATE INDEX IF NOT EXISTS idx_tasks_thread_id ON tasks(thread_id)`);
464
- }
465
- catch (error) {
466
- this.logger.warn(`Failed to create index idx_tasks_thread_id: ${error instanceof Error ? error.message : String(error)}`);
467
- }
468
- try {
469
- this.db.exec(`CREATE INDEX IF NOT EXISTS idx_threads_workspace_id ON threads(workspace_id)`);
470
- }
471
- catch (error) {
472
- this.logger.warn(`Failed to create index idx_threads_workspace_id: ${error instanceof Error ? error.message : String(error)}`);
473
- }
474
- try {
475
- this.db.exec(`CREATE INDEX IF NOT EXISTS idx_tasks_workspace_ref ON tasks(workspace_ref)`);
476
- }
477
- catch (error) {
478
- this.logger.warn(`Failed to create index idx_tasks_workspace_ref: ${error instanceof Error ? error.message : String(error)}`);
479
- }
480
- if (migratedCount > 0) {
481
- this.logger.log(`Phase 6 migration: Added ${migratedCount} new columns to tasks table`);
482
- }
483
- }
484
- migrateSchemaPhase7() {
485
- if (!this.db)
486
- return;
487
- try {
488
- this.db.exec(`
489
- CREATE TABLE IF NOT EXISTS request_logs (
490
- id TEXT PRIMARY KEY,
491
- path TEXT NOT NULL,
492
- method TEXT NOT NULL,
493
- status_code INTEGER NOT NULL,
494
- duration_ms INTEGER NOT NULL,
495
- ip TEXT,
496
- request_headers TEXT,
497
- response_headers TEXT,
498
- request_body TEXT,
499
- response_body TEXT,
500
- query TEXT,
501
- user_id TEXT,
502
- project_id TEXT,
503
- partition_key TEXT NOT NULL,
504
- timestamp TEXT NOT NULL DEFAULT (datetime('now')),
505
- metadata TEXT
506
- )
507
- `);
508
- }
509
- catch (error) {
510
- this.logger.warn(`Failed to create request_logs table: ${error instanceof Error ? error.message : String(error)}`);
511
- return;
512
- }
513
- const indexes = [
514
- { name: 'idx_request_logs_timestamp', sql: 'CREATE INDEX IF NOT EXISTS idx_request_logs_timestamp ON request_logs(timestamp DESC)' },
515
- { name: 'idx_request_logs_path', sql: 'CREATE INDEX IF NOT EXISTS idx_request_logs_path ON request_logs(path)' },
516
- { name: 'idx_request_logs_status_code', sql: 'CREATE INDEX IF NOT EXISTS idx_request_logs_status_code ON request_logs(status_code)' },
517
- { name: 'idx_request_logs_partition_key', sql: 'CREATE INDEX IF NOT EXISTS idx_request_logs_partition_key ON request_logs(partition_key)' },
518
- ];
519
- for (const idx of indexes) {
520
- try {
521
- this.db.exec(idx.sql);
522
- }
523
- catch (error) {
524
- this.logger.warn(`Failed to create index ${idx.name}: ${error instanceof Error ? error.message : String(error)}`);
525
- }
526
- }
527
- this.logger.log('Phase 7 migration: Created request_logs table with 4 indexes');
528
- }
529
- createToolCallsTable() {
530
- if (!this.db)
531
- return;
532
- try {
533
- const tableExists = this.db.get("SELECT name FROM sqlite_master WHERE type='table' AND name='tool_calls'");
534
- if (!tableExists) {
535
- this.db.exec(`
536
- CREATE TABLE tool_calls (
537
- id TEXT PRIMARY KEY,
538
- task_id TEXT NOT NULL,
539
- session_id TEXT,
540
- tool_name TEXT NOT NULL,
541
- files TEXT,
542
- input TEXT,
543
- output TEXT,
544
- duration_ms INTEGER,
545
- timestamp TEXT NOT NULL,
546
- FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE
547
- )
548
- `);
549
- this.db.exec(`
550
- CREATE INDEX IF NOT EXISTS idx_tool_calls_task_id ON tool_calls(task_id);
551
- CREATE INDEX IF NOT EXISTS idx_tool_calls_tool_name ON tool_calls(tool_name);
552
- CREATE INDEX IF NOT EXISTS idx_tool_calls_timestamp ON tool_calls(timestamp);
553
- `);
554
- this.logger.log('Issue #104: Created tool_calls table for hooks observability');
555
- }
556
- }
557
- catch (error) {
558
- this.logger.warn(`Failed to create tool_calls table: ${error instanceof Error ? error.message : String(error)}`);
559
- }
560
- }
561
- createThreadBoxesTable() {
562
- if (!this.db)
563
- return;
564
- try {
565
- this.db.exec(`
566
- CREATE TABLE IF NOT EXISTS thread_boxes (
567
- id TEXT PRIMARY KEY,
568
- thread_id TEXT NOT NULL,
569
- seq INTEGER NOT NULL,
570
-
571
- first_task_id TEXT NOT NULL,
572
- mid_task_id TEXT NOT NULL,
573
- last_task_id TEXT NOT NULL,
574
- task_count INTEGER NOT NULL,
575
-
576
- summary TEXT,
577
-
578
- source_tokens INTEGER NOT NULL,
579
- summary_tokens INTEGER,
580
-
581
- created_at TEXT NOT NULL,
582
-
583
- FOREIGN KEY (thread_id) REFERENCES threads(id) ON DELETE CASCADE,
584
- UNIQUE (thread_id, seq)
585
- );
586
-
587
- CREATE INDEX IF NOT EXISTS idx_thread_boxes_thread_id ON thread_boxes(thread_id);
588
- CREATE INDEX IF NOT EXISTS idx_thread_boxes_seq ON thread_boxes(thread_id, seq DESC);
589
- `);
590
- this.logger.log('Phase 8: Created thread_boxes table with indexes');
591
- }
592
- catch (error) {
593
- this.logger.warn(`Failed to create thread_boxes table: ${error instanceof Error ? error.message : String(error)}`);
594
- }
595
- }
596
- close() {
597
- if (this.db) {
598
- this.db.close();
599
- this.db = null;
600
- this.logger.log('Tracing database connection closed');
601
- }
602
- }
603
- now() {
604
- return new Date().toISOString();
605
- }
606
- estimateTokens(text) {
607
- if (!text)
608
- return 0;
609
- return Math.ceil(text.length * 0.4);
610
- }
611
- createTask(input) {
612
- if (!this.db) {
613
- return null;
614
- }
615
- const id = input.id ?? (0, sdk_1.generateId)('tsk');
616
- const now = this.now();
617
- const { workspaceId, workspaceName } = this.resolveWorkspaceContext(input.workspace_id, input.workspace_name);
618
- const metadata = input.metadata ? { ...input.metadata } : {};
619
- const MAX_RENDERED_PROMPT_SIZE = 10 * 1024 * 1024;
620
- let renderedPrompt = input.rendered_prompt ?? null;
621
- if (renderedPrompt && renderedPrompt.length > MAX_RENDERED_PROMPT_SIZE) {
622
- renderedPrompt = renderedPrompt.slice(0, MAX_RENDERED_PROMPT_SIZE) + '\n[TRUNCATED]';
623
- this.logger.warn(`Rendered prompt for task ${id} truncated to 10MB limit`);
624
- }
625
- try {
626
- this.db.run(`
627
- INSERT INTO tasks (
628
- id, agent_id, user_id, prompt, mode, status, started_at, metadata,
629
- trace_id, parent_task_id, caller_agent_id, model, platform, crewx_version,
630
- input_tokens, output_tokens, cost_usd,
631
- pid, rendered_prompt, command, coding_agent_command, exit_code, logs,
632
- workspace_id, workspace_name,
633
- thread_id, workspace_ref
634
- )
635
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
636
- `, [
637
- id,
638
- input.agent_id,
639
- input.user_id ?? null,
640
- input.prompt,
641
- input.mode,
642
- TaskStatus.RUNNING,
643
- now,
644
- Object.keys(metadata).length > 0 ? JSON.stringify(metadata) : null,
645
- input.trace_id ?? null,
646
- input.parent_task_id ?? null,
647
- input.caller_agent_id ?? null,
648
- input.model ?? null,
649
- input.platform ?? 'cli',
650
- input.crewx_version ?? null,
651
- input.input_tokens ?? 0,
652
- input.output_tokens ?? 0,
653
- input.cost_usd ?? 0,
654
- input.pid ?? null,
655
- renderedPrompt,
656
- input.command ?? null,
657
- input.coding_agent_command ?? null,
658
- input.exit_code ?? null,
659
- '[]',
660
- workspaceId,
661
- workspaceName,
662
- input.thread_id ?? null,
663
- input.workspace_ref ?? null,
664
- ]);
665
- this.logger.debug(`Task created: ${id} for agent ${input.agent_id} (model: ${input.model ?? 'default'})`);
666
- return id;
667
- }
668
- catch (error) {
669
- this.logger.error(`Failed to create task: ${error instanceof Error ? error.message : String(error)}`);
670
- return null;
671
- }
672
- }
673
- extractUsageFromLogs(logs) {
674
- if (!logs || logs.length === 0)
675
- return null;
676
- let found = null;
677
- for (const entry of logs) {
678
- if (entry.level !== 'stdout')
679
- continue;
680
- let parsed;
681
- try {
682
- parsed = JSON.parse(entry.message);
683
- }
684
- catch {
685
- continue;
686
- }
687
- if (parsed.type === 'result' &&
688
- parsed.subtype === 'success' &&
689
- parsed.usage &&
690
- typeof parsed.usage === 'object') {
691
- const u = parsed.usage;
692
- if (typeof u.input_tokens === 'number' && typeof u.output_tokens === 'number') {
693
- found = { inputTokens: u.input_tokens, outputTokens: u.output_tokens };
694
- }
695
- }
696
- if (parsed.type === 'turn.completed' &&
697
- parsed.usage &&
698
- typeof parsed.usage === 'object') {
699
- const u = parsed.usage;
700
- if (typeof u.input_tokens === 'number' && typeof u.output_tokens === 'number') {
701
- found = { inputTokens: u.input_tokens, outputTokens: u.output_tokens };
702
- }
703
- }
704
- }
705
- return found;
706
- }
707
- completeTask(taskId, result, exitCode, usage) {
708
- if (!this.db) {
709
- return false;
710
- }
711
- try {
712
- const now = this.now();
713
- const safeResult = typeof result === 'string'
714
- ? result
715
- : Array.isArray(result)
716
- ? result.filter((c) => c?.text).map((c) => c.text).join('\n')
717
- : result != null ? String(result) : null;
718
- const task = this.getTask(taskId);
719
- const model = task?.model ?? null;
720
- const resolvedUsage = usage ?? this.extractUsageFromLogs(task?.logs);
721
- let inputTokens = 0;
722
- let outputTokens = 0;
723
- let costUsd = 0;
724
- if (resolvedUsage) {
725
- inputTokens = resolvedUsage.inputTokens;
726
- outputTokens = resolvedUsage.outputTokens;
727
- costUsd = (0, sdk_1.calculateCost)(inputTokens, outputTokens, model);
728
- }
729
- const info = this.db.run(`
730
- UPDATE tasks
731
- SET status = ?, result = ?, completed_at = ?,
732
- duration_ms = CAST((julianday(?) - julianday(started_at)) * 86400000 AS INTEGER),
733
- input_tokens = ?,
734
- output_tokens = ?,
735
- cost_usd = ?,
736
- exit_code = ?
737
- WHERE id = ?
738
- `, [
739
- TaskStatus.SUCCESS,
740
- safeResult ?? null,
741
- now,
742
- now,
743
- inputTokens,
744
- outputTokens,
745
- costUsd,
746
- exitCode ?? null,
747
- taskId,
748
- ]);
749
- return info.changes > 0;
750
- }
751
- catch (error) {
752
- this.logger.error(`Failed to complete task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
753
- return false;
754
- }
755
- }
756
- failTask(taskId, error, exitCode, usage) {
757
- if (!this.db) {
758
- return false;
759
- }
760
- try {
761
- const now = this.now();
762
- const task = this.getTask(taskId);
763
- const model = task?.model ?? null;
764
- const resolvedUsage = usage ?? this.extractUsageFromLogs(task?.logs);
765
- let inputTokens = 0;
766
- let outputTokens = 0;
767
- let costUsd = 0;
768
- if (resolvedUsage) {
769
- inputTokens = resolvedUsage.inputTokens;
770
- outputTokens = resolvedUsage.outputTokens;
771
- costUsd = (0, sdk_1.calculateCost)(inputTokens, outputTokens, model);
772
- }
773
- const info = this.db.run(`
774
- UPDATE tasks
775
- SET status = ?, error = ?, completed_at = ?,
776
- duration_ms = CAST((julianday(?) - julianday(started_at)) * 86400000 AS INTEGER),
777
- input_tokens = ?,
778
- output_tokens = ?,
779
- cost_usd = ?,
780
- exit_code = ?
781
- WHERE id = ?
782
- `, [
783
- TaskStatus.FAILED,
784
- error,
785
- now,
786
- now,
787
- inputTokens,
788
- outputTokens,
789
- costUsd,
790
- exitCode ?? null,
791
- taskId,
792
- ]);
793
- return info.changes > 0;
794
- }
795
- catch (error) {
796
- this.logger.error(`Failed to fail task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
797
- return false;
798
- }
799
- }
800
- updateTaskPid(taskId, pid) {
801
- if (!this.db) {
802
- return false;
803
- }
804
- try {
805
- const info = this.db.run(`
806
- UPDATE tasks
807
- SET pid = ?
808
- WHERE id = ?
809
- `, [pid, taskId]);
810
- if (info.changes > 0) {
811
- this.logger.debug(`Updated task ${taskId} with PID ${pid}`);
812
- }
813
- return info.changes > 0;
814
- }
815
- catch (error) {
816
- this.logger.error(`Failed to update PID for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
817
- return false;
818
- }
819
- }
820
- updateTaskCodingAgentCommand(taskId, command) {
821
- if (!this.db) {
822
- return false;
823
- }
824
- try {
825
- const info = this.db.run(`
826
- UPDATE tasks
827
- SET coding_agent_command = ?
828
- WHERE id = ?
829
- `, [command, taskId]);
830
- if (info.changes > 0) {
831
- this.logger.debug(`Updated task ${taskId} with coding agent command`);
832
- }
833
- return info.changes > 0;
834
- }
835
- catch (error) {
836
- this.logger.error(`Failed to update coding agent command for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
837
- return false;
838
- }
839
- }
840
- updateTaskRenderedPrompt(taskId, renderedPrompt) {
841
- if (!this.db) {
842
- return false;
843
- }
844
- try {
845
- const MAX_RENDERED_PROMPT_SIZE = 10 * 1024 * 1024;
846
- let truncatedPrompt = renderedPrompt;
847
- if (renderedPrompt.length > MAX_RENDERED_PROMPT_SIZE) {
848
- truncatedPrompt = renderedPrompt.slice(0, MAX_RENDERED_PROMPT_SIZE) + '\n[TRUNCATED]';
849
- this.logger.warn(`Rendered prompt for task ${taskId} truncated to 10MB limit`);
850
- }
851
- const info = this.db.run(`
852
- UPDATE tasks
853
- SET rendered_prompt = ?
854
- WHERE id = ?
855
- `, [truncatedPrompt, taskId]);
856
- return info.changes > 0;
857
- }
858
- catch (error) {
859
- this.logger.error(`Failed to update rendered_prompt for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
860
- return false;
861
- }
862
- }
863
- appendTaskLog(taskId, entry) {
864
- if (!this.db) {
865
- return false;
866
- }
867
- try {
868
- const row = this.db.get('SELECT logs FROM tasks WHERE id = ?', [taskId]);
869
- if (!row) {
870
- this.logger.warn(`Task ${taskId} not found when appending log`);
871
- return false;
872
- }
873
- let logs = [];
874
- if (row.logs) {
875
- try {
876
- logs = JSON.parse(row.logs);
877
- }
878
- catch {
879
- logs = [];
880
- }
881
- }
882
- logs.push(entry);
883
- const info = this.db.run('UPDATE tasks SET logs = ? WHERE id = ?', [JSON.stringify(logs), taskId]);
884
- return info.changes > 0;
885
- }
886
- catch (error) {
887
- this.logger.error(`Failed to append log for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
888
- return false;
889
- }
890
- }
891
- getTask(taskId) {
892
- if (!this.db) {
893
- return null;
894
- }
895
- try {
896
- const row = this.db.get('SELECT * FROM tasks WHERE id = ?', [taskId]);
897
- if (!row) {
898
- return null;
899
- }
900
- return {
901
- ...row,
902
- metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
903
- logs: row.logs ? JSON.parse(row.logs) : undefined,
904
- };
905
- }
906
- catch (error) {
907
- this.logger.error(`Failed to get task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
908
- return null;
909
- }
910
- }
911
- listTasks(options) {
912
- if (!this.db) {
913
- return [];
914
- }
915
- const limit = options?.limit ?? 20;
916
- const offset = options?.offset ?? 0;
917
- try {
918
- let query = 'SELECT * FROM tasks';
919
- const params = [];
920
- if (options?.agentId) {
921
- query += ' WHERE agent_id = ?';
922
- params.push(options.agentId);
923
- }
924
- query += ' ORDER BY started_at DESC LIMIT ? OFFSET ?';
925
- params.push(limit, offset);
926
- const rows = this.db.all(query, params);
927
- return rows.map((row) => ({
928
- ...row,
929
- metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
930
- logs: row.logs ? JSON.parse(row.logs) : undefined,
931
- }));
932
- }
933
- catch (error) {
934
- this.logger.error(`Failed to list tasks: ${error instanceof Error ? error.message : String(error)}`);
935
- return [];
936
- }
937
- }
938
- createSpan(input) {
939
- if (!this.db) {
940
- return null;
941
- }
942
- const id = (0, sdk_1.generateId)('spn');
943
- const now = this.now();
944
- try {
945
- this.db.run(`
946
- INSERT INTO spans (id, task_id, parent_span_id, name, kind, status, started_at, input, attributes)
947
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
948
- `, [
949
- id,
950
- input.task_id,
951
- input.parent_span_id ?? null,
952
- input.name,
953
- input.kind ?? SpanKind.INTERNAL,
954
- 'ok',
955
- now,
956
- input.input ?? null,
957
- input.attributes ? JSON.stringify(input.attributes) : null,
958
- ]);
959
- this.logger.debug(`Span created: ${id} for task ${input.task_id}`);
960
- return id;
961
- }
962
- catch (error) {
963
- this.logger.error(`Failed to create span: ${error instanceof Error ? error.message : String(error)}`);
964
- return null;
965
- }
966
- }
967
- completeSpan(spanId, output) {
968
- if (!this.db) {
969
- return false;
970
- }
971
- try {
972
- const now = this.now();
973
- const info = this.db.run(`
974
- UPDATE spans
975
- SET status = 'ok', output = ?, completed_at = ?,
976
- duration_ms = CAST((julianday(?) - julianday(started_at)) * 86400000 AS INTEGER)
977
- WHERE id = ?
978
- `, [output ?? null, now, now, spanId]);
979
- return info.changes > 0;
980
- }
981
- catch (error) {
982
- this.logger.error(`Failed to complete span ${spanId}: ${error instanceof Error ? error.message : String(error)}`);
983
- return false;
984
- }
985
- }
986
- failSpan(spanId, error) {
987
- if (!this.db) {
988
- return false;
989
- }
990
- try {
991
- const now = this.now();
992
- const info = this.db.run(`
993
- UPDATE spans
994
- SET status = 'error', error = ?, completed_at = ?,
995
- duration_ms = CAST((julianday(?) - julianday(started_at)) * 86400000 AS INTEGER)
996
- WHERE id = ?
997
- `, [error, now, now, spanId]);
998
- return info.changes > 0;
999
- }
1000
- catch (error) {
1001
- this.logger.error(`Failed to fail span ${spanId}: ${error instanceof Error ? error.message : String(error)}`);
1002
- return false;
1003
- }
1004
- }
1005
- getSpansForTask(taskId) {
1006
- if (!this.db) {
1007
- return [];
1008
- }
1009
- try {
1010
- const rows = this.db.all('SELECT * FROM spans WHERE task_id = ? ORDER BY started_at ASC', [taskId]);
1011
- return rows.map((row) => ({
1012
- ...row,
1013
- attributes: row.attributes ? JSON.parse(row.attributes) : undefined,
1014
- }));
1015
- }
1016
- catch (error) {
1017
- this.logger.error(`Failed to get spans for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
1018
- return [];
1019
- }
1020
- }
1021
- getSpan(spanId) {
1022
- if (!this.db) {
1023
- return null;
1024
- }
1025
- try {
1026
- const row = this.db.get('SELECT * FROM spans WHERE id = ?', [spanId]);
1027
- if (!row) {
1028
- return null;
1029
- }
1030
- return {
1031
- ...row,
1032
- attributes: row.attributes ? JSON.parse(row.attributes) : undefined,
1033
- };
1034
- }
1035
- catch (error) {
1036
- this.logger.error(`Failed to get span ${spanId}: ${error instanceof Error ? error.message : String(error)}`);
1037
- return null;
1038
- }
1039
- }
1040
- logToolCall(input) {
1041
- if (!this.db) {
1042
- return null;
1043
- }
1044
- const id = (0, sdk_1.generateId)('tcl');
1045
- const timestamp = this.now();
1046
- try {
1047
- this.db.run(`
1048
- INSERT INTO tool_calls (
1049
- id, task_id, session_id, tool_name, files, input, output, duration_ms, timestamp
1050
- )
1051
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
1052
- `, [
1053
- id,
1054
- input.task_id,
1055
- input.session_id ?? null,
1056
- input.tool_name,
1057
- input.files ? JSON.stringify(input.files) : null,
1058
- input.input ? JSON.stringify(input.input) : null,
1059
- input.output ? JSON.stringify(input.output) : null,
1060
- input.duration_ms ?? null,
1061
- timestamp,
1062
- ]);
1063
- this.logger.debug(`Tool call logged: ${input.tool_name} for task ${input.task_id}`);
1064
- return id;
1065
- }
1066
- catch (error) {
1067
- this.logger.error(`Failed to log tool call: ${error instanceof Error ? error.message : String(error)}`);
1068
- return null;
1069
- }
1070
- }
1071
- getToolCallsForTask(taskId) {
1072
- if (!this.db) {
1073
- return [];
1074
- }
1075
- try {
1076
- const rows = this.db.all('SELECT * FROM tool_calls WHERE task_id = ? ORDER BY timestamp ASC', [taskId]);
1077
- return rows.map((row) => ({
1078
- ...row,
1079
- files: row.files ? JSON.parse(row.files) : undefined,
1080
- input: row.input ? JSON.parse(row.input) : undefined,
1081
- output: row.output ? JSON.parse(row.output) : undefined,
1082
- }));
1083
- }
1084
- catch (error) {
1085
- this.logger.error(`Failed to get tool calls for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
1086
- return [];
1087
- }
1088
- }
1089
- getToolCallStats(taskId) {
1090
- if (!this.db) {
1091
- return null;
1092
- }
1093
- try {
1094
- const stats = this.db.get(`
1095
- SELECT
1096
- COUNT(*) as total_calls,
1097
- COUNT(DISTINCT tool_name) as unique_tools
1098
- FROM tool_calls
1099
- WHERE task_id = ?
1100
- `, [taskId]);
1101
- const tools = this.db.all(`
1102
- SELECT DISTINCT tool_name FROM tool_calls WHERE task_id = ?
1103
- `, [taskId]);
1104
- return {
1105
- totalCalls: stats.total_calls,
1106
- uniqueTools: stats.unique_tools,
1107
- toolsUsed: tools.map(t => t.tool_name),
1108
- };
1109
- }
1110
- catch (error) {
1111
- this.logger.error(`Failed to get tool call stats for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
1112
- return null;
1113
- }
1114
- }
1115
- cleanupOldTasks(daysToKeep = 30) {
1116
- if (!this.db) {
1117
- return 0;
1118
- }
1119
- try {
1120
- const cutoffDate = new Date();
1121
- cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);
1122
- const cutoff = cutoffDate.toISOString();
1123
- const info = this.db.run('DELETE FROM tasks WHERE started_at < ?', [cutoff]);
1124
- if (info.changes > 0) {
1125
- this.logger.log(`Cleaned up ${info.changes} old tasks`);
1126
- }
1127
- return info.changes;
1128
- }
1129
- catch (error) {
1130
- this.logger.error(`Failed to cleanup old tasks: ${error instanceof Error ? error.message : String(error)}`);
1131
- return 0;
1132
- }
1133
- }
1134
- getStats() {
1135
- if (!this.db) {
1136
- return null;
1137
- }
1138
- try {
1139
- const taskCount = this.db.get('SELECT COUNT(*) as count FROM tasks').count;
1140
- const spanCount = this.db.get('SELECT COUNT(*) as count FROM spans').count;
1141
- let toolCallCount = 0;
1142
- try {
1143
- toolCallCount = this.db.get('SELECT COUNT(*) as count FROM tool_calls').count;
1144
- }
1145
- catch {
1146
- }
1147
- let dbSizeBytes = 0;
1148
- if (fs.existsSync(this.dbPath)) {
1149
- const stats = fs.statSync(this.dbPath);
1150
- dbSizeBytes = stats.size;
1151
- }
1152
- return { taskCount, spanCount, toolCallCount, dbSizeBytes };
1153
- }
1154
- catch (error) {
1155
- this.logger.error(`Failed to get stats: ${error instanceof Error ? error.message : String(error)}`);
1156
- return null;
1157
- }
1158
- }
1159
- migrateDbFileName() {
1160
- const dirsToMigrate = new Set([
1161
- path.join(os.homedir(), '.crewx'),
1162
- path.join(process.cwd(), '.crewx'),
1163
- ]);
1164
- for (const dir of dirsToMigrate) {
1165
- const oldPath = path.join(dir, 'traces.db');
1166
- const newPath = path.join(dir, 'crewx.db');
1167
- if (fs.existsSync(oldPath) && !fs.existsSync(newPath)) {
1168
- try {
1169
- fs.renameSync(oldPath, newPath);
1170
- this.logger.log(`Migrated ${oldPath} → ${newPath}`);
1171
- }
1172
- catch (error) {
1173
- this.logger.warn(`Failed to migrate ${oldPath}: ${error instanceof Error ? error.message : String(error)}`);
1174
- }
1175
- }
1176
- }
1177
- }
1178
- resolveDbPath() {
1179
- if (process.env.CREWX_TRACES_DB || process.env.CREWX_DB) {
1180
- return process.env.CREWX_TRACES_DB || process.env.CREWX_DB;
1181
- }
1182
- return path.join(os.homedir(), '.crewx', 'crewx.db');
1183
- }
1184
- resolveWorkspaceIdForPath(dirPath) {
1185
- const workspacePath = path.resolve(dirPath);
1186
- const id = (0, sdk_1.hashWorkspaceId)(workspacePath);
1187
- const name = this.resolveWorkspaceName(workspacePath);
1188
- const slug = this.resolveWorkspaceSlug(id, workspacePath);
1189
- this.ensureWorkspaceRow(id, slug, name, workspacePath);
1190
- return { workspaceId: id, workspaceName: name };
1191
- }
1192
- resolveWorkspaceContext(workspaceId, workspaceName) {
1193
- const workspacePath = path.resolve(process.env.CREWX_WORKSPACE || process.cwd());
1194
- const id = workspaceId ?? (0, sdk_1.hashWorkspaceId)(workspacePath);
1195
- const name = workspaceName ?? this.resolveWorkspaceName(workspacePath);
1196
- const slug = this.resolveWorkspaceSlug(id, workspacePath);
1197
- this.ensureWorkspaceRow(id, slug, name, workspacePath);
1198
- return { workspaceId: id, workspaceName: name };
1199
- }
1200
- resolveWorkspaceSlug(workspaceId, workspacePath) {
1201
- const cwd = workspacePath || process.env.CREWX_WORKSPACE || process.cwd();
1202
- let slug = path.basename(cwd);
1203
- if (this.db) {
1204
- try {
1205
- const existing = this.db.get('SELECT id FROM workspaces WHERE slug = ? AND id != ?', [slug, workspaceId]);
1206
- if (existing) {
1207
- const parent = path.basename(path.dirname(cwd));
1208
- slug = `${parent}/${slug}`;
1209
- }
1210
- }
1211
- catch {
1212
- }
1213
- }
1214
- return slug;
1215
- }
1216
- ensureWorkspaceRow(id, slug, name, workspacePath) {
1217
- if (!this.db)
1218
- return;
1219
- const now = this.now();
1220
- try {
1221
- this.db.run(`
1222
- INSERT OR IGNORE INTO workspaces (id, slug, name, workspace_path, is_active, created_at, updated_at)
1223
- VALUES (?, ?, ?, ?, 1, ?, ?)
1224
- `, [id, slug, name, workspacePath, now, now]);
1225
- this.db.run(`
1226
- UPDATE workspaces SET workspace_path = ?, updated_at = ? WHERE id = ? AND workspace_path IS NULL
1227
- `, [workspacePath, now, id]);
1228
- }
1229
- catch (error) {
1230
- this.logger.warn(`Failed to ensure workspace row: ${error instanceof Error ? error.message : String(error)}`);
1231
- }
1232
- }
1233
- resolveWorkspaceName(workspacePath) {
1234
- const gitConfigPath = path.join(workspacePath, '.git', 'config');
1235
- if (fs.existsSync(gitConfigPath)) {
1236
- try {
1237
- const config = fs.readFileSync(gitConfigPath, 'utf-8');
1238
- const match = config.match(/\[remote\s+"[^"]+"\][^\[]*?url\s*=\s*(.+)/m);
1239
- if (match && match[1]) {
1240
- return this.extractRepoName(match[1].trim());
1241
- }
1242
- }
1243
- catch {
1244
- }
1245
- }
1246
- return path.basename(workspacePath);
1247
- }
1248
- extractRepoName(remoteUrl) {
1249
- const cleaned = remoteUrl.replace(/\.git$/i, '');
1250
- const parts = cleaned.split(/[/:]/).filter(Boolean);
1251
- return parts[parts.length - 1] || 'unknown';
1252
- }
1253
- isEnabled() {
1254
- return this.db !== null;
1255
- }
1256
- getDbPath() {
1257
- return this.dbPath;
1258
- }
1259
- };
1260
- exports.TracingService = TracingService;
1261
- exports.TracingService = TracingService = TracingService_1 = __decorate([
1262
- (0, common_1.Injectable)(),
1263
- __param(0, (0, common_1.Optional)()),
1264
- __param(0, (0, common_1.Inject)('TRACING_OPTIONS')),
1265
- __metadata("design:paramtypes", [Object])
1266
- ], TracingService);
1267
- //# sourceMappingURL=tracing.service.js.map