@agentrix/cli 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@ var chalk = require('chalk');
6
6
  var shared = require('@agentrix/shared');
7
7
  var node_crypto = require('node:crypto');
8
8
  var axios = require('axios');
9
- var _package = require('./logger-DVI_I2D6.cjs');
9
+ var _package = require('./logger---ZD5a2u.cjs');
10
10
  var fs$1 = require('node:fs');
11
11
  var node_readline = require('node:readline');
12
12
  var fs = require('fs');
@@ -23,13 +23,13 @@ var fastify = require('fastify');
23
23
  var zod = require('zod');
24
24
  var fastifyTypeProviderZod = require('fastify-type-provider-zod');
25
25
  var require$$7 = require('url');
26
+ var promises = require('node:stream/promises');
26
27
  var claudeAgentSdk = require('@anthropic-ai/claude-agent-sdk');
27
28
  var simpleGit = require('simple-git');
28
- var promises = require('node:fs/promises');
29
+ var promises$1 = require('node:fs/promises');
29
30
  var require$$1 = require('crypto');
30
31
  var codexSdk = require('@openai/codex-sdk');
31
32
  var v3 = require('zod/v3');
32
- var promises$1 = require('node:stream/promises');
33
33
 
34
34
  function _interopNamespaceDefault(e) {
35
35
  var n = Object.create(null);
@@ -12613,6 +12613,29 @@ function createWorkerEventHandlers(context) {
12613
12613
  class WorkerClient {
12614
12614
  client;
12615
12615
  context;
12616
+ /**
12617
+ * Static helper method to send error message and exit event
12618
+ * Used when worker fails during initialization before context is set up
12619
+ *
12620
+ * @param config - Worker client configuration
12621
+ * @param errorMessage - Error message to send to user
12622
+ */
12623
+ static async sendErrorAndExit(config, errorMessage) {
12624
+ try {
12625
+ const workClient = new WorkerClient(config, {
12626
+ stopTask: async () => {
12627
+ },
12628
+ onTaskMessage: async () => {
12629
+ }
12630
+ });
12631
+ await workClient.connect();
12632
+ workClient.sendSystemErrorMessage(errorMessage);
12633
+ await workClient.client.flush(2e3);
12634
+ workClient.sendWorkerExit("error");
12635
+ await workClient.disconnect();
12636
+ } catch {
12637
+ }
12638
+ }
12616
12639
  constructor(config, options) {
12617
12640
  const { taskId, userId, machineId, cwd, ...socketConfig } = config;
12618
12641
  const normalizedCwd = cwd.endsWith("/") ? cwd : `${cwd}/`;
@@ -12711,6 +12734,41 @@ class WorkerClient {
12711
12734
  };
12712
12735
  this.client.send("worker-exit", workerExitEvent);
12713
12736
  }
12737
+ /**
12738
+ * Send system error message and worker exit event, then disconnect
12739
+ * Used when worker exits with error after context is set up
12740
+ *
12741
+ * @param errorMessage - Error message to send to user
12742
+ */
12743
+ async sendErrorMessageAndExit(errorMessage) {
12744
+ this.sendSystemErrorMessage(errorMessage);
12745
+ await this.client.flush(2e3);
12746
+ this.sendWorkerExit("error");
12747
+ await this.disconnect();
12748
+ }
12749
+ sendSystemErrorMessage(errorMessage) {
12750
+ const systemMessage = {
12751
+ type: "assistant",
12752
+ session_id: "",
12753
+ uuid: crypto.randomUUID(),
12754
+ parent_tool_use_id: null,
12755
+ message: {
12756
+ role: "assistant",
12757
+ content: [
12758
+ {
12759
+ type: "text",
12760
+ text: `System Error
12761
+
12762
+ ${errorMessage}`,
12763
+ metadata: {
12764
+ messageType: "system_error"
12765
+ }
12766
+ }
12767
+ ]
12768
+ }
12769
+ };
12770
+ this.sendTaskMessage(systemMessage);
12771
+ }
12714
12772
  sendRequirePermission(toolName, toolInput) {
12715
12773
  const eventId = shared.createEventId();
12716
12774
  const permissionRequest = {
@@ -12780,6 +12838,108 @@ class WorkerClient {
12780
12838
  }
12781
12839
  }
12782
12840
 
12841
+ const MIME_TYPE_MAP = {
12842
+ // Images
12843
+ ".jpg": "image/jpeg",
12844
+ ".jpeg": "image/jpeg",
12845
+ ".png": "image/png",
12846
+ ".gif": "image/gif",
12847
+ ".webp": "image/webp",
12848
+ ".bmp": "image/bmp",
12849
+ ".svg": "image/svg+xml",
12850
+ ".ico": "image/x-icon",
12851
+ // Documents
12852
+ ".pdf": "application/pdf",
12853
+ ".doc": "application/msword",
12854
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
12855
+ ".xls": "application/vnd.ms-excel",
12856
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
12857
+ ".ppt": "application/vnd.ms-powerpoint",
12858
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
12859
+ // Text
12860
+ ".txt": "text/plain",
12861
+ ".md": "text/markdown",
12862
+ ".csv": "text/csv",
12863
+ ".json": "application/json",
12864
+ ".xml": "application/xml",
12865
+ ".html": "text/html",
12866
+ ".css": "text/css",
12867
+ ".js": "application/javascript",
12868
+ ".ts": "application/typescript",
12869
+ // Archives
12870
+ ".zip": "application/zip",
12871
+ ".tar": "application/x-tar",
12872
+ ".gz": "application/gzip",
12873
+ ".rar": "application/vnd.rar",
12874
+ // Other
12875
+ ".mp3": "audio/mpeg",
12876
+ ".mp4": "video/mp4",
12877
+ ".wav": "audio/wav",
12878
+ ".avi": "video/x-msvideo"
12879
+ };
12880
+ function detectMimeType(extension) {
12881
+ const normalized = extension.toLowerCase();
12882
+ return MIME_TYPE_MAP[normalized] || "application/octet-stream";
12883
+ }
12884
+ function extractExtension(url) {
12885
+ try {
12886
+ const urlObj = new URL(url);
12887
+ const pathExt = path$1.extname(urlObj.pathname);
12888
+ if (pathExt) {
12889
+ return pathExt;
12890
+ }
12891
+ const filenameParam = urlObj.searchParams.get("filename") || urlObj.searchParams.get("name") || urlObj.searchParams.get("file");
12892
+ if (filenameParam) {
12893
+ const paramExt = path$1.extname(filenameParam);
12894
+ if (paramExt) {
12895
+ return paramExt;
12896
+ }
12897
+ }
12898
+ return "";
12899
+ } catch {
12900
+ return "";
12901
+ }
12902
+ }
12903
+ async function downloadFile(url, targetDir, preserveFilename = false) {
12904
+ try {
12905
+ const extension = extractExtension(url) || "";
12906
+ let filename;
12907
+ if (preserveFilename) {
12908
+ try {
12909
+ const urlPath = new URL(url).pathname;
12910
+ const originalFilename = path$1.basename(urlPath);
12911
+ filename = originalFilename && path$1.extname(originalFilename) ? originalFilename : `${node_crypto.randomUUID()}${extension || ".dat"}`;
12912
+ } catch {
12913
+ filename = `${node_crypto.randomUUID()}${extension || ".dat"}`;
12914
+ }
12915
+ } else {
12916
+ filename = `${node_crypto.randomUUID()}${extension || ".dat"}`;
12917
+ }
12918
+ const filePath = path$1.join(targetDir, filename);
12919
+ const response = await fetch(url);
12920
+ if (!response.ok) {
12921
+ throw new Error(`Failed to download file: ${response.status} ${response.statusText}`);
12922
+ }
12923
+ if (!response.body) {
12924
+ throw new Error("Response body is null");
12925
+ }
12926
+ const contentType = response.headers.get("content-type");
12927
+ const mimeType = contentType?.split(";")[0].trim() || detectMimeType(extension);
12928
+ const nodeStream = response.body;
12929
+ const fileStream = fs$1.createWriteStream(filePath);
12930
+ await promises.pipeline(nodeStream, fileStream);
12931
+ return {
12932
+ filePath,
12933
+ mimeType,
12934
+ filename
12935
+ };
12936
+ } catch (error) {
12937
+ throw new Error(
12938
+ `Failed to download file from ${url}: ${error instanceof Error ? error.message : String(error)}`
12939
+ );
12940
+ }
12941
+ }
12942
+
12783
12943
  function trimIdent(text) {
12784
12944
  const lines = text.split("\n");
12785
12945
  while (lines.length > 0 && lines[0].trim() === "") {
@@ -13088,7 +13248,7 @@ async function generateAndSavePatch(workingDirectory, fromCommit, toCommit, data
13088
13248
  return void 0;
13089
13249
  }
13090
13250
  const patchPath = path$1.join(dataDir, "patch.diff");
13091
- await promises.writeFile(patchPath, patch);
13251
+ await promises$1.writeFile(patchPath, patch);
13092
13252
  return patchPath;
13093
13253
  }
13094
13254
  async function handleGitState(workingDirectory, userId, taskId, commitMessage) {
@@ -13108,7 +13268,8 @@ async function handleGitState(workingDirectory, userId, taskId, commitMessage) {
13108
13268
  throw new Error(`Initial commit hash not found for task ${taskId}`);
13109
13269
  }
13110
13270
  const lastSentHash = await _package.machine.readLastSentCommitHash(userId, taskId);
13111
- const hasNewCommits = currentCommitHash !== lastSentHash;
13271
+ const baseHash = lastSentHash ?? initialHash;
13272
+ const hasNewCommits = currentCommitHash !== baseHash;
13112
13273
  const dataDir = _package.machine.resolveDataDir(userId, taskId);
13113
13274
  const patchPath = await generateAndSavePatch(
13114
13275
  workingDirectory,
@@ -13481,7 +13642,8 @@ class ClaudeWorker {
13481
13642
  await this.exitWorker("completed");
13482
13643
  } else {
13483
13644
  this.log("warn", "AGENT", "Fatal error:", error);
13484
- await this.exitWorker("error");
13645
+ const errorMessage = error instanceof Error ? error.message : String(error);
13646
+ await this.exitWorker("error", errorMessage);
13485
13647
  throw error;
13486
13648
  }
13487
13649
  } finally {
@@ -13519,18 +13681,11 @@ class ClaudeWorker {
13519
13681
  } catch (error) {
13520
13682
  this.log("error", "GIT", "Failed to setup workspace:", error);
13521
13683
  const basicConfig = this.createBasicWorkerConfig(userId, taskId, workingDirectory);
13522
- try {
13523
- const workClient2 = new WorkerClient(basicConfig, {
13524
- stopTask: async () => {
13525
- },
13526
- onTaskMessage: async () => {
13527
- }
13528
- });
13529
- await workClient2.connect();
13530
- workClient2.sendWorkerExit("error");
13531
- await workClient2.disconnect();
13532
- } catch {
13533
- }
13684
+ const errorMessage = error instanceof Error ? error.message : String(error);
13685
+ await WorkerClient.sendErrorAndExit(
13686
+ basicConfig,
13687
+ `Failed to setup workspace: ${errorMessage}`
13688
+ );
13534
13689
  process.exit(1);
13535
13690
  }
13536
13691
  const idleTimeoutMs = Math.max(0, this.options.idleTimeoutSecond ?? 0) * 1e3;
@@ -13758,7 +13913,7 @@ Please must use the mcp__agentrix__create_pr tool to create the pull request wit
13758
13913
  this.log("info", "AGENT", `Claude agent finished for task ${this.taskId}`);
13759
13914
  }
13760
13915
  async enqueueMessage(message) {
13761
- const processedMessage = await this.processImageUrls(message);
13916
+ const processedMessage = await this.processAttachments(message);
13762
13917
  if (this.messageResolverRef.current) {
13763
13918
  const resolver = this.messageResolverRef.current;
13764
13919
  this.messageResolverRef.current = null;
@@ -13767,10 +13922,14 @@ Please must use the mcp__agentrix__create_pr tool to create the pull request wit
13767
13922
  this.messageQueue.push(processedMessage);
13768
13923
  }
13769
13924
  }
13770
- async processImageUrls(message) {
13925
+ async processAttachments(message) {
13771
13926
  if (!Array.isArray(message.message.content)) {
13772
13927
  return message;
13773
13928
  }
13929
+ const attachmentsDir = _package.machine.resolveAttachmentsDir(
13930
+ this.options.input.userId,
13931
+ this.taskId
13932
+ );
13774
13933
  const processedContent = await Promise.all(
13775
13934
  message.message.content.map(async (block) => {
13776
13935
  if (block.type === "image" && block.source?.type === "url" && block.source?.url) {
@@ -13806,6 +13965,24 @@ Please must use the mcp__agentrix__create_pr tool to create the pull request wit
13806
13965
  return block;
13807
13966
  }
13808
13967
  }
13968
+ if (block.type === "document" && block.source?.type === "url" && block.source?.url) {
13969
+ try {
13970
+ const url = block.source.url;
13971
+ this.log("info", "DOCUMENT", `Downloading document from: ${url}`);
13972
+ const { filePath, mimeType, filename } = await downloadFile(url, attachmentsDir, true);
13973
+ this.log("info", "DOCUMENT", `Document downloaded to: ${filePath}`);
13974
+ const title = block.title || filename;
13975
+ return {
13976
+ type: "text",
13977
+ text: `Document: ${filePath}
13978
+ Title: ${title}
13979
+ Type: ${mimeType}`
13980
+ };
13981
+ } catch (error) {
13982
+ this.log("error", "DOCUMENT", `Error processing document: ${error}`);
13983
+ return block;
13984
+ }
13985
+ }
13809
13986
  return block;
13810
13987
  })
13811
13988
  );
@@ -14188,14 +14365,18 @@ URL: ${result.pullRequestUrl}`
14188
14365
  }
14189
14366
  };
14190
14367
  }
14191
- async exitWorker(status) {
14368
+ async exitWorker(status, errorMessage) {
14192
14369
  if (this.coordinator) {
14193
14370
  this.coordinator.stop();
14194
14371
  }
14195
14372
  if (this.context?.workClient) {
14196
- this.context.workClient.sendWorkerExit(status);
14197
14373
  this.log("info", "WORKER", `Exiting with status: ${status} for task ${this.taskId}`);
14198
- await this.context.workClient.disconnect();
14374
+ if (status === "error" && errorMessage) {
14375
+ await this.context.workClient.sendErrorMessageAndExit(errorMessage);
14376
+ } else {
14377
+ this.context.workClient.sendWorkerExit(status);
14378
+ await this.context.workClient.disconnect();
14379
+ }
14199
14380
  }
14200
14381
  }
14201
14382
  logGitStateResult(gitStateResult, phase) {
@@ -14219,7 +14400,7 @@ URL: ${result.pullRequestUrl}`
14219
14400
  }
14220
14401
  }
14221
14402
  async createLogger(options) {
14222
- const { createLogger } = await Promise.resolve().then(function () { return require('./logger-DVI_I2D6.cjs'); }).then(function (n) { return n.logger$1; });
14403
+ const { createLogger } = await Promise.resolve().then(function () { return require('./logger---ZD5a2u.cjs'); }).then(function (n) { return n.logger$1; });
14223
14404
  return createLogger(options);
14224
14405
  }
14225
14406
  log(level, category, message, ...args) {
@@ -15843,28 +16024,6 @@ Example response format:
15843
16024
  CRITICAL: Respond with ONLY the JSON object, no additional text before or after. Now analyze the changes and provide your response:`;
15844
16025
  }
15845
16026
 
15846
- async function downloadImage(url, targetDir) {
15847
- try {
15848
- const urlPath = new URL(url).pathname;
15849
- const extension = path$1.extname(urlPath) || ".jpg";
15850
- const filename = `${node_crypto.randomUUID()}${extension}`;
15851
- const filePath = path$1.join(targetDir, filename);
15852
- const response = await fetch(url);
15853
- if (!response.ok) {
15854
- throw new Error(`Failed to download image: ${response.status} ${response.statusText}`);
15855
- }
15856
- if (!response.body) {
15857
- throw new Error("Response body is null");
15858
- }
15859
- const nodeStream = response.body;
15860
- const fileStream = fs$1.createWriteStream(filePath);
15861
- await promises$1.pipeline(nodeStream, fileStream);
15862
- return filePath;
15863
- } catch (error) {
15864
- throw new Error(`Failed to download image from ${url}: ${error instanceof Error ? error.message : String(error)}`);
15865
- }
15866
- }
15867
-
15868
16027
  class CodexWorker {
15869
16028
  constructor(credentials, options) {
15870
16029
  this.credentials = credentials;
@@ -15902,7 +16061,8 @@ class CodexWorker {
15902
16061
  await this.exitWorker("completed");
15903
16062
  } else {
15904
16063
  this.log("warn", "AGENT", "Fatal error:", error);
15905
- await this.exitWorker("error");
16064
+ const errorMessage = error instanceof Error ? error.message : String(error);
16065
+ await this.exitWorker("error", errorMessage);
15906
16066
  throw error;
15907
16067
  }
15908
16068
  } finally {
@@ -15937,18 +16097,11 @@ class CodexWorker {
15937
16097
  } catch (error) {
15938
16098
  this.log("error", "GIT", "Failed to setup workspace:", error);
15939
16099
  const basicConfig = this.createBasicWorkerConfig(userId, taskId, workingDirectory);
15940
- try {
15941
- const workClient2 = new WorkerClient(basicConfig, {
15942
- stopTask: async () => {
15943
- },
15944
- onTaskMessage: async () => {
15945
- }
15946
- });
15947
- await workClient2.connect();
15948
- workClient2.sendWorkerExit("error");
15949
- await workClient2.disconnect();
15950
- } catch {
15951
- }
16100
+ const errorMessage = error instanceof Error ? error.message : String(error);
16101
+ await WorkerClient.sendErrorAndExit(
16102
+ basicConfig,
16103
+ `Failed to setup workspace: ${errorMessage}`
16104
+ );
15952
16105
  process.exit(1);
15953
16106
  }
15954
16107
  const idleTimeoutMs = Math.max(0, this.options.idleTimeoutSecond ?? 0) * 1e3;
@@ -16170,28 +16323,7 @@ ${stats.files.map((f) => ` ${f.path}: +${f.insertions}/-${f.deletions}`).join("
16170
16323
  this.timerManager.clearIdleTimer();
16171
16324
  this.toolIdMap.clear();
16172
16325
  let input = userInput;
16173
- if (this.turnCount === 0) {
16174
- const agentConfig = await this.loadAgentConfiguration();
16175
- const systemPrompt = buildSystemPrompt(
16176
- agentConfig.customSystemPrompt,
16177
- agentConfig.systemPromptMode
16178
- );
16179
- const sysPrompt = systemPrompt instanceof String ? systemPrompt : systemPrompt.append;
16180
- if (sysPrompt) {
16181
- if (typeof userInput === "string") {
16182
- input = `${sysPrompt}
16183
-
16184
- ---
16185
-
16186
- ${userInput}`;
16187
- } else {
16188
- input = [
16189
- { type: "text", text: sysPrompt },
16190
- ...userInput
16191
- ];
16192
- }
16193
- }
16194
- }
16326
+ if (this.turnCount === 0) ;
16195
16327
  const turnOptions = this.inMergeRequest ? { outputSchema: getPROutputSchema() } : {};
16196
16328
  this.log("debug", "AGENT", "Calling thread.runStreamed");
16197
16329
  const { events } = await this.thread.runStreamed(input, turnOptions);
@@ -16370,8 +16502,8 @@ URL: ${result.pullRequestUrl}`);
16370
16502
  }
16371
16503
  /**
16372
16504
  * Convert SDKUserMessage to Codex Input format
16373
- * Handles both text-only messages and messages with images
16374
- * Downloads images from URLs to local attachments directory
16505
+ * Handles both text-only messages and messages with images and documents
16506
+ * Downloads images and documents from URLs to local attachments directory
16375
16507
  */
16376
16508
  async convertSDKMessageToCodexInput(message) {
16377
16509
  const content = message.message.content;
@@ -16380,6 +16512,10 @@ URL: ${result.pullRequestUrl}`);
16380
16512
  }
16381
16513
  if (Array.isArray(content)) {
16382
16514
  const userInputs = [];
16515
+ const attachmentsDir = _package.machine.resolveAttachmentsDir(
16516
+ this.options.input.userId,
16517
+ this.taskId
16518
+ );
16383
16519
  for (const block of content) {
16384
16520
  if (block.type === "text" && block.text) {
16385
16521
  userInputs.push({
@@ -16389,19 +16525,30 @@ URL: ${result.pullRequestUrl}`);
16389
16525
  } else if (block.type === "image" && block.source && block.source.url) {
16390
16526
  const url = block.source.url;
16391
16527
  try {
16392
- const attachmentsDir = _package.machine.resolveAttachmentsDir(
16393
- this.options.input.userId,
16394
- this.taskId
16395
- );
16396
- const localPath = await downloadImage(url, attachmentsDir);
16397
- this.log("info", "IMAGE", `Downloaded image from ${url} to ${localPath}`);
16528
+ const { filePath } = await downloadFile(url, attachmentsDir, false);
16529
+ this.log("info", "IMAGE", `Downloaded image from ${url} to ${filePath}`);
16398
16530
  userInputs.push({
16399
16531
  type: "local_image",
16400
- path: localPath
16532
+ path: filePath
16401
16533
  });
16402
16534
  } catch (error) {
16403
16535
  this.log("error", "IMAGE", `Failed to download image from ${url}:`, error);
16404
16536
  }
16537
+ } else if (block.type === "document" && block.source && block.source.url) {
16538
+ const url = block.source.url;
16539
+ try {
16540
+ const { filePath, mimeType, filename } = await downloadFile(url, attachmentsDir, true);
16541
+ this.log("info", "DOCUMENT", `Downloaded document from ${url} to ${filePath}`);
16542
+ const title = block.title || filename;
16543
+ userInputs.push({
16544
+ type: "text",
16545
+ text: `Document: ${filePath}
16546
+ Title: ${title}
16547
+ Type: ${mimeType}`
16548
+ });
16549
+ } catch (error) {
16550
+ this.log("error", "DOCUMENT", `Failed to download document from ${url}:`, error);
16551
+ }
16405
16552
  }
16406
16553
  }
16407
16554
  if (userInputs.length === 1 && userInputs[0].type === "text") {
@@ -16575,13 +16722,17 @@ URL: ${result.pullRequestUrl}`);
16575
16722
  }
16576
16723
  };
16577
16724
  }
16578
- async exitWorker(status) {
16725
+ async exitWorker(status, errorMessage) {
16579
16726
  if (this.coordinator) {
16580
16727
  this.coordinator.stop();
16581
16728
  }
16582
- this.context.workClient.sendWorkerExit(status);
16583
16729
  this.log("info", "WORKER", `Exiting with status: ${status} for task ${this.taskId}`);
16584
- await this.context.workClient.disconnect();
16730
+ if (status === "error" && errorMessage) {
16731
+ await this.context.workClient.sendErrorMessageAndExit(errorMessage);
16732
+ } else {
16733
+ this.context.workClient.sendWorkerExit(status);
16734
+ await this.context.workClient.disconnect();
16735
+ }
16585
16736
  }
16586
16737
  /**
16587
16738
  * Reports git state and sends artifacts update to API.
@@ -16921,7 +17072,7 @@ cli.command("upgrade", "Upgrade CLI to the latest version", {}, async (argv) =>
16921
17072
  }
16922
17073
  }
16923
17074
  try {
16924
- const { version } = await Promise.resolve().then(function () { return require('./logger-DVI_I2D6.cjs'); }).then(function (n) { return n._package; });
17075
+ const { version } = await Promise.resolve().then(function () { return require('./logger---ZD5a2u.cjs'); }).then(function (n) { return n._package; });
16925
17076
  console.log(chalk.green(`
16926
17077
  \u2713 Now running version: ${version}`));
16927
17078
  } catch {
@@ -17103,7 +17254,7 @@ cli.command(
17103
17254
  },
17104
17255
  async (argv) => {
17105
17256
  try {
17106
- const { testCommand } = await Promise.resolve().then(function () { return require('./index-CEbBjLT3.cjs'); });
17257
+ const { testCommand } = await Promise.resolve().then(function () { return require('./index-BdFjpsoN.cjs'); });
17107
17258
  await testCommand(argv);
17108
17259
  } catch (error) {
17109
17260
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Test mode failed");
@@ -4,10 +4,10 @@ var React = require('react');
4
4
  var ink = require('ink');
5
5
  var TextInput = require('ink-text-input');
6
6
  var SelectInput = require('ink-select-input');
7
- var _package = require('./logger-DVI_I2D6.cjs');
7
+ var _package = require('./logger---ZD5a2u.cjs');
8
8
  var shared = require('@agentrix/shared');
9
9
  var require$$0$3 = require('events');
10
- var index = require('./index-DEoriCrL.cjs');
10
+ var index = require('./index-A8QO7gdw.cjs');
11
11
  var require$$2$1 = require('http');
12
12
  var fs = require('fs');
13
13
  var require$$1$2 = require('zlib');
@@ -44,11 +44,11 @@ require('cross-spawn');
44
44
  require('fastify');
45
45
  require('zod');
46
46
  require('fastify-type-provider-zod');
47
+ require('node:stream/promises');
47
48
  require('@anthropic-ai/claude-agent-sdk');
48
49
  require('simple-git');
49
50
  require('@openai/codex-sdk');
50
51
  require('zod/v3');
51
- require('node:stream/promises');
52
52
 
53
53
  const Header = ({ agentId, model, cwd, status }) => {
54
54
  const getStatusColor = () => {
@@ -2,10 +2,10 @@ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(im
2
2
  import { Box, Text, useInput, useApp, render } from 'ink';
3
3
  import TextInput from 'ink-text-input';
4
4
  import SelectInput from 'ink-select-input';
5
- import { m as machine } from './logger-ChZYRh-E.mjs';
5
+ import { m as machine } from './logger-D-ioMWe6.mjs';
6
6
  import { loadAgentConfig, createEventId } from '@agentrix/shared';
7
7
  import require$$0$3, { EventEmitter } from 'events';
8
- import { r as requireMimeTypes, g as getAugmentedNamespace, a as getDefaultExportFromCjs, s as spawnAgentrixCLI } from './index-CWPJKpmJ.mjs';
8
+ import { r as requireMimeTypes, g as getAugmentedNamespace, a as getDefaultExportFromCjs, s as spawnAgentrixCLI } from './index-Dzjo3uhE.mjs';
9
9
  import require$$2$1, { createServer } from 'http';
10
10
  import fs from 'fs';
11
11
  import require$$1$2 from 'zlib';
@@ -42,11 +42,11 @@ import 'cross-spawn';
42
42
  import 'fastify';
43
43
  import 'zod';
44
44
  import 'fastify-type-provider-zod';
45
+ import 'node:stream/promises';
45
46
  import '@anthropic-ai/claude-agent-sdk';
46
47
  import 'simple-git';
47
48
  import '@openai/codex-sdk';
48
49
  import 'zod/v3';
49
- import 'node:stream/promises';
50
50
 
51
51
  const Header = ({ agentId, model, cwd, status }) => {
52
52
  const getStatusColor = () => {
@@ -2,11 +2,11 @@ import yargs from 'yargs';
2
2
  import { hideBin } from 'yargs/helpers';
3
3
  import chalk from 'chalk';
4
4
  import { encodeBase64, createKeyPairWithUit8Array, encryptMachineEncryptionKey, generateAESKey, decodeBase64, decryptWithEphemeralKey, createEventId, encryptFileContent, machineAuth, encryptSdkMessage, decryptSdkMessage, loadAgentConfig, getAgentContext, workerAuth } from '@agentrix/shared';
5
- import { randomBytes, randomUUID as randomUUID$1 } from 'node:crypto';
5
+ import { randomBytes, randomUUID } from 'node:crypto';
6
6
  import axios from 'axios';
7
- import { m as machine, l as logger, p as projectPath, a as packageJson, c as createLogger, g as getLogPath, b as logger$1 } from './logger-ChZYRh-E.mjs';
7
+ import { m as machine, l as logger, p as projectPath, a as packageJson, c as createLogger, g as getLogPath, b as logger$1 } from './logger-D-ioMWe6.mjs';
8
8
  import * as fs from 'node:fs';
9
- import { existsSync, rmSync, readdirSync, mkdirSync, createWriteStream } from 'node:fs';
9
+ import { existsSync, rmSync, createWriteStream, readdirSync, mkdirSync } from 'node:fs';
10
10
  import { createInterface } from 'node:readline';
11
11
  import fs$1, { readFileSync, existsSync as existsSync$1 } from 'fs';
12
12
  import path$1, { join } from 'path';
@@ -15,7 +15,7 @@ import open from 'open';
15
15
  import { io } from 'socket.io-client';
16
16
  import { EventEmitter } from 'node:events';
17
17
  import * as path from 'node:path';
18
- import { join as join$1, dirname, extname } from 'node:path';
18
+ import { join as join$1, basename, extname, dirname } from 'node:path';
19
19
  import { spawn, execSync } from 'child_process';
20
20
  import psList from 'ps-list';
21
21
  import spawn$1 from 'cross-spawn';
@@ -23,13 +23,13 @@ import fastify from 'fastify';
23
23
  import { z } from 'zod';
24
24
  import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod';
25
25
  import { pathToFileURL } from 'url';
26
+ import { pipeline } from 'node:stream/promises';
26
27
  import { AbortError, query, createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';
27
28
  import simpleGit, { CheckRepoActions } from 'simple-git';
28
29
  import { writeFile } from 'node:fs/promises';
29
- import { randomUUID } from 'crypto';
30
+ import { randomUUID as randomUUID$1 } from 'crypto';
30
31
  import { Codex } from '@openai/codex-sdk';
31
32
  import { ZodFirstPartyTypeKind } from 'zod/v3';
32
- import { pipeline } from 'node:stream/promises';
33
33
 
34
34
  async function delay(ms) {
35
35
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -12593,6 +12593,29 @@ function createWorkerEventHandlers(context) {
12593
12593
  class WorkerClient {
12594
12594
  client;
12595
12595
  context;
12596
+ /**
12597
+ * Static helper method to send error message and exit event
12598
+ * Used when worker fails during initialization before context is set up
12599
+ *
12600
+ * @param config - Worker client configuration
12601
+ * @param errorMessage - Error message to send to user
12602
+ */
12603
+ static async sendErrorAndExit(config, errorMessage) {
12604
+ try {
12605
+ const workClient = new WorkerClient(config, {
12606
+ stopTask: async () => {
12607
+ },
12608
+ onTaskMessage: async () => {
12609
+ }
12610
+ });
12611
+ await workClient.connect();
12612
+ workClient.sendSystemErrorMessage(errorMessage);
12613
+ await workClient.client.flush(2e3);
12614
+ workClient.sendWorkerExit("error");
12615
+ await workClient.disconnect();
12616
+ } catch {
12617
+ }
12618
+ }
12596
12619
  constructor(config, options) {
12597
12620
  const { taskId, userId, machineId, cwd, ...socketConfig } = config;
12598
12621
  const normalizedCwd = cwd.endsWith("/") ? cwd : `${cwd}/`;
@@ -12691,6 +12714,41 @@ class WorkerClient {
12691
12714
  };
12692
12715
  this.client.send("worker-exit", workerExitEvent);
12693
12716
  }
12717
+ /**
12718
+ * Send system error message and worker exit event, then disconnect
12719
+ * Used when worker exits with error after context is set up
12720
+ *
12721
+ * @param errorMessage - Error message to send to user
12722
+ */
12723
+ async sendErrorMessageAndExit(errorMessage) {
12724
+ this.sendSystemErrorMessage(errorMessage);
12725
+ await this.client.flush(2e3);
12726
+ this.sendWorkerExit("error");
12727
+ await this.disconnect();
12728
+ }
12729
+ sendSystemErrorMessage(errorMessage) {
12730
+ const systemMessage = {
12731
+ type: "assistant",
12732
+ session_id: "",
12733
+ uuid: crypto.randomUUID(),
12734
+ parent_tool_use_id: null,
12735
+ message: {
12736
+ role: "assistant",
12737
+ content: [
12738
+ {
12739
+ type: "text",
12740
+ text: `System Error
12741
+
12742
+ ${errorMessage}`,
12743
+ metadata: {
12744
+ messageType: "system_error"
12745
+ }
12746
+ }
12747
+ ]
12748
+ }
12749
+ };
12750
+ this.sendTaskMessage(systemMessage);
12751
+ }
12694
12752
  sendRequirePermission(toolName, toolInput) {
12695
12753
  const eventId = createEventId();
12696
12754
  const permissionRequest = {
@@ -12760,6 +12818,108 @@ class WorkerClient {
12760
12818
  }
12761
12819
  }
12762
12820
 
12821
+ const MIME_TYPE_MAP = {
12822
+ // Images
12823
+ ".jpg": "image/jpeg",
12824
+ ".jpeg": "image/jpeg",
12825
+ ".png": "image/png",
12826
+ ".gif": "image/gif",
12827
+ ".webp": "image/webp",
12828
+ ".bmp": "image/bmp",
12829
+ ".svg": "image/svg+xml",
12830
+ ".ico": "image/x-icon",
12831
+ // Documents
12832
+ ".pdf": "application/pdf",
12833
+ ".doc": "application/msword",
12834
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
12835
+ ".xls": "application/vnd.ms-excel",
12836
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
12837
+ ".ppt": "application/vnd.ms-powerpoint",
12838
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
12839
+ // Text
12840
+ ".txt": "text/plain",
12841
+ ".md": "text/markdown",
12842
+ ".csv": "text/csv",
12843
+ ".json": "application/json",
12844
+ ".xml": "application/xml",
12845
+ ".html": "text/html",
12846
+ ".css": "text/css",
12847
+ ".js": "application/javascript",
12848
+ ".ts": "application/typescript",
12849
+ // Archives
12850
+ ".zip": "application/zip",
12851
+ ".tar": "application/x-tar",
12852
+ ".gz": "application/gzip",
12853
+ ".rar": "application/vnd.rar",
12854
+ // Other
12855
+ ".mp3": "audio/mpeg",
12856
+ ".mp4": "video/mp4",
12857
+ ".wav": "audio/wav",
12858
+ ".avi": "video/x-msvideo"
12859
+ };
12860
+ function detectMimeType(extension) {
12861
+ const normalized = extension.toLowerCase();
12862
+ return MIME_TYPE_MAP[normalized] || "application/octet-stream";
12863
+ }
12864
+ function extractExtension(url) {
12865
+ try {
12866
+ const urlObj = new URL(url);
12867
+ const pathExt = extname(urlObj.pathname);
12868
+ if (pathExt) {
12869
+ return pathExt;
12870
+ }
12871
+ const filenameParam = urlObj.searchParams.get("filename") || urlObj.searchParams.get("name") || urlObj.searchParams.get("file");
12872
+ if (filenameParam) {
12873
+ const paramExt = extname(filenameParam);
12874
+ if (paramExt) {
12875
+ return paramExt;
12876
+ }
12877
+ }
12878
+ return "";
12879
+ } catch {
12880
+ return "";
12881
+ }
12882
+ }
12883
+ async function downloadFile(url, targetDir, preserveFilename = false) {
12884
+ try {
12885
+ const extension = extractExtension(url) || "";
12886
+ let filename;
12887
+ if (preserveFilename) {
12888
+ try {
12889
+ const urlPath = new URL(url).pathname;
12890
+ const originalFilename = basename(urlPath);
12891
+ filename = originalFilename && extname(originalFilename) ? originalFilename : `${randomUUID()}${extension || ".dat"}`;
12892
+ } catch {
12893
+ filename = `${randomUUID()}${extension || ".dat"}`;
12894
+ }
12895
+ } else {
12896
+ filename = `${randomUUID()}${extension || ".dat"}`;
12897
+ }
12898
+ const filePath = join$1(targetDir, filename);
12899
+ const response = await fetch(url);
12900
+ if (!response.ok) {
12901
+ throw new Error(`Failed to download file: ${response.status} ${response.statusText}`);
12902
+ }
12903
+ if (!response.body) {
12904
+ throw new Error("Response body is null");
12905
+ }
12906
+ const contentType = response.headers.get("content-type");
12907
+ const mimeType = contentType?.split(";")[0].trim() || detectMimeType(extension);
12908
+ const nodeStream = response.body;
12909
+ const fileStream = createWriteStream(filePath);
12910
+ await pipeline(nodeStream, fileStream);
12911
+ return {
12912
+ filePath,
12913
+ mimeType,
12914
+ filename
12915
+ };
12916
+ } catch (error) {
12917
+ throw new Error(
12918
+ `Failed to download file from ${url}: ${error instanceof Error ? error.message : String(error)}`
12919
+ );
12920
+ }
12921
+ }
12922
+
12763
12923
  function trimIdent(text) {
12764
12924
  const lines = text.split("\n");
12765
12925
  while (lines.length > 0 && lines[0].trim() === "") {
@@ -13088,7 +13248,8 @@ async function handleGitState(workingDirectory, userId, taskId, commitMessage) {
13088
13248
  throw new Error(`Initial commit hash not found for task ${taskId}`);
13089
13249
  }
13090
13250
  const lastSentHash = await machine.readLastSentCommitHash(userId, taskId);
13091
- const hasNewCommits = currentCommitHash !== lastSentHash;
13251
+ const baseHash = lastSentHash ?? initialHash;
13252
+ const hasNewCommits = currentCommitHash !== baseHash;
13092
13253
  const dataDir = machine.resolveDataDir(userId, taskId);
13093
13254
  const patchPath = await generateAndSavePatch(
13094
13255
  workingDirectory,
@@ -13124,7 +13285,7 @@ async function markCommitAsSent(userId, taskId, commitHash) {
13124
13285
 
13125
13286
  function executeCommandStreaming(command, cwd, callbacks, timeoutMs = 6e4) {
13126
13287
  return new Promise((resolve) => {
13127
- const toolUseId = `shell_${randomUUID().replace(/-/g, "")}`;
13288
+ const toolUseId = `shell_${randomUUID$1().replace(/-/g, "")}`;
13128
13289
  callbacks.onOutput({
13129
13290
  type: "assistant",
13130
13291
  message: {
@@ -13461,7 +13622,8 @@ class ClaudeWorker {
13461
13622
  await this.exitWorker("completed");
13462
13623
  } else {
13463
13624
  this.log("warn", "AGENT", "Fatal error:", error);
13464
- await this.exitWorker("error");
13625
+ const errorMessage = error instanceof Error ? error.message : String(error);
13626
+ await this.exitWorker("error", errorMessage);
13465
13627
  throw error;
13466
13628
  }
13467
13629
  } finally {
@@ -13499,18 +13661,11 @@ class ClaudeWorker {
13499
13661
  } catch (error) {
13500
13662
  this.log("error", "GIT", "Failed to setup workspace:", error);
13501
13663
  const basicConfig = this.createBasicWorkerConfig(userId, taskId, workingDirectory);
13502
- try {
13503
- const workClient2 = new WorkerClient(basicConfig, {
13504
- stopTask: async () => {
13505
- },
13506
- onTaskMessage: async () => {
13507
- }
13508
- });
13509
- await workClient2.connect();
13510
- workClient2.sendWorkerExit("error");
13511
- await workClient2.disconnect();
13512
- } catch {
13513
- }
13664
+ const errorMessage = error instanceof Error ? error.message : String(error);
13665
+ await WorkerClient.sendErrorAndExit(
13666
+ basicConfig,
13667
+ `Failed to setup workspace: ${errorMessage}`
13668
+ );
13514
13669
  process.exit(1);
13515
13670
  }
13516
13671
  const idleTimeoutMs = Math.max(0, this.options.idleTimeoutSecond ?? 0) * 1e3;
@@ -13738,7 +13893,7 @@ Please must use the mcp__agentrix__create_pr tool to create the pull request wit
13738
13893
  this.log("info", "AGENT", `Claude agent finished for task ${this.taskId}`);
13739
13894
  }
13740
13895
  async enqueueMessage(message) {
13741
- const processedMessage = await this.processImageUrls(message);
13896
+ const processedMessage = await this.processAttachments(message);
13742
13897
  if (this.messageResolverRef.current) {
13743
13898
  const resolver = this.messageResolverRef.current;
13744
13899
  this.messageResolverRef.current = null;
@@ -13747,10 +13902,14 @@ Please must use the mcp__agentrix__create_pr tool to create the pull request wit
13747
13902
  this.messageQueue.push(processedMessage);
13748
13903
  }
13749
13904
  }
13750
- async processImageUrls(message) {
13905
+ async processAttachments(message) {
13751
13906
  if (!Array.isArray(message.message.content)) {
13752
13907
  return message;
13753
13908
  }
13909
+ const attachmentsDir = machine.resolveAttachmentsDir(
13910
+ this.options.input.userId,
13911
+ this.taskId
13912
+ );
13754
13913
  const processedContent = await Promise.all(
13755
13914
  message.message.content.map(async (block) => {
13756
13915
  if (block.type === "image" && block.source?.type === "url" && block.source?.url) {
@@ -13786,6 +13945,24 @@ Please must use the mcp__agentrix__create_pr tool to create the pull request wit
13786
13945
  return block;
13787
13946
  }
13788
13947
  }
13948
+ if (block.type === "document" && block.source?.type === "url" && block.source?.url) {
13949
+ try {
13950
+ const url = block.source.url;
13951
+ this.log("info", "DOCUMENT", `Downloading document from: ${url}`);
13952
+ const { filePath, mimeType, filename } = await downloadFile(url, attachmentsDir, true);
13953
+ this.log("info", "DOCUMENT", `Document downloaded to: ${filePath}`);
13954
+ const title = block.title || filename;
13955
+ return {
13956
+ type: "text",
13957
+ text: `Document: ${filePath}
13958
+ Title: ${title}
13959
+ Type: ${mimeType}`
13960
+ };
13961
+ } catch (error) {
13962
+ this.log("error", "DOCUMENT", `Error processing document: ${error}`);
13963
+ return block;
13964
+ }
13965
+ }
13789
13966
  return block;
13790
13967
  })
13791
13968
  );
@@ -14168,14 +14345,18 @@ URL: ${result.pullRequestUrl}`
14168
14345
  }
14169
14346
  };
14170
14347
  }
14171
- async exitWorker(status) {
14348
+ async exitWorker(status, errorMessage) {
14172
14349
  if (this.coordinator) {
14173
14350
  this.coordinator.stop();
14174
14351
  }
14175
14352
  if (this.context?.workClient) {
14176
- this.context.workClient.sendWorkerExit(status);
14177
14353
  this.log("info", "WORKER", `Exiting with status: ${status} for task ${this.taskId}`);
14178
- await this.context.workClient.disconnect();
14354
+ if (status === "error" && errorMessage) {
14355
+ await this.context.workClient.sendErrorMessageAndExit(errorMessage);
14356
+ } else {
14357
+ this.context.workClient.sendWorkerExit(status);
14358
+ await this.context.workClient.disconnect();
14359
+ }
14179
14360
  }
14180
14361
  }
14181
14362
  logGitStateResult(gitStateResult, phase) {
@@ -14199,7 +14380,7 @@ URL: ${result.pullRequestUrl}`
14199
14380
  }
14200
14381
  }
14201
14382
  async createLogger(options) {
14202
- const { createLogger } = await import('./logger-ChZYRh-E.mjs').then(function (n) { return n.b; });
14383
+ const { createLogger } = await import('./logger-D-ioMWe6.mjs').then(function (n) { return n.b; });
14203
14384
  return createLogger(options);
14204
14385
  }
14205
14386
  log(level, category, message, ...args) {
@@ -14220,7 +14401,7 @@ async function runClaude(credentials, options) {
14220
14401
  var require$$0 = /*@__PURE__*/getAugmentedNamespace(logger$1);
14221
14402
 
14222
14403
  function generateAndMapToolId(itemId, idMapper) {
14223
- const uniqueId = randomUUID$1();
14404
+ const uniqueId = randomUUID();
14224
14405
  idMapper.set(itemId, uniqueId);
14225
14406
  return uniqueId;
14226
14407
  }
@@ -14303,7 +14484,7 @@ function convertAgentMessage(item) {
14303
14484
  },
14304
14485
  parent_tool_use_id: null,
14305
14486
  session_id: "",
14306
- uuid: randomUUID$1().toString()
14487
+ uuid: randomUUID().toString()
14307
14488
  };
14308
14489
  }
14309
14490
  function convertCommandExecutionStarted(item, idMapper) {
@@ -15823,28 +16004,6 @@ Example response format:
15823
16004
  CRITICAL: Respond with ONLY the JSON object, no additional text before or after. Now analyze the changes and provide your response:`;
15824
16005
  }
15825
16006
 
15826
- async function downloadImage(url, targetDir) {
15827
- try {
15828
- const urlPath = new URL(url).pathname;
15829
- const extension = extname(urlPath) || ".jpg";
15830
- const filename = `${randomUUID$1()}${extension}`;
15831
- const filePath = join$1(targetDir, filename);
15832
- const response = await fetch(url);
15833
- if (!response.ok) {
15834
- throw new Error(`Failed to download image: ${response.status} ${response.statusText}`);
15835
- }
15836
- if (!response.body) {
15837
- throw new Error("Response body is null");
15838
- }
15839
- const nodeStream = response.body;
15840
- const fileStream = createWriteStream(filePath);
15841
- await pipeline(nodeStream, fileStream);
15842
- return filePath;
15843
- } catch (error) {
15844
- throw new Error(`Failed to download image from ${url}: ${error instanceof Error ? error.message : String(error)}`);
15845
- }
15846
- }
15847
-
15848
16007
  class CodexWorker {
15849
16008
  constructor(credentials, options) {
15850
16009
  this.credentials = credentials;
@@ -15882,7 +16041,8 @@ class CodexWorker {
15882
16041
  await this.exitWorker("completed");
15883
16042
  } else {
15884
16043
  this.log("warn", "AGENT", "Fatal error:", error);
15885
- await this.exitWorker("error");
16044
+ const errorMessage = error instanceof Error ? error.message : String(error);
16045
+ await this.exitWorker("error", errorMessage);
15886
16046
  throw error;
15887
16047
  }
15888
16048
  } finally {
@@ -15917,18 +16077,11 @@ class CodexWorker {
15917
16077
  } catch (error) {
15918
16078
  this.log("error", "GIT", "Failed to setup workspace:", error);
15919
16079
  const basicConfig = this.createBasicWorkerConfig(userId, taskId, workingDirectory);
15920
- try {
15921
- const workClient2 = new WorkerClient(basicConfig, {
15922
- stopTask: async () => {
15923
- },
15924
- onTaskMessage: async () => {
15925
- }
15926
- });
15927
- await workClient2.connect();
15928
- workClient2.sendWorkerExit("error");
15929
- await workClient2.disconnect();
15930
- } catch {
15931
- }
16080
+ const errorMessage = error instanceof Error ? error.message : String(error);
16081
+ await WorkerClient.sendErrorAndExit(
16082
+ basicConfig,
16083
+ `Failed to setup workspace: ${errorMessage}`
16084
+ );
15932
16085
  process.exit(1);
15933
16086
  }
15934
16087
  const idleTimeoutMs = Math.max(0, this.options.idleTimeoutSecond ?? 0) * 1e3;
@@ -16150,28 +16303,7 @@ ${stats.files.map((f) => ` ${f.path}: +${f.insertions}/-${f.deletions}`).join("
16150
16303
  this.timerManager.clearIdleTimer();
16151
16304
  this.toolIdMap.clear();
16152
16305
  let input = userInput;
16153
- if (this.turnCount === 0) {
16154
- const agentConfig = await this.loadAgentConfiguration();
16155
- const systemPrompt = buildSystemPrompt(
16156
- agentConfig.customSystemPrompt,
16157
- agentConfig.systemPromptMode
16158
- );
16159
- const sysPrompt = systemPrompt instanceof String ? systemPrompt : systemPrompt.append;
16160
- if (sysPrompt) {
16161
- if (typeof userInput === "string") {
16162
- input = `${sysPrompt}
16163
-
16164
- ---
16165
-
16166
- ${userInput}`;
16167
- } else {
16168
- input = [
16169
- { type: "text", text: sysPrompt },
16170
- ...userInput
16171
- ];
16172
- }
16173
- }
16174
- }
16306
+ if (this.turnCount === 0) ;
16175
16307
  const turnOptions = this.inMergeRequest ? { outputSchema: getPROutputSchema() } : {};
16176
16308
  this.log("debug", "AGENT", "Calling thread.runStreamed");
16177
16309
  const { events } = await this.thread.runStreamed(input, turnOptions);
@@ -16279,7 +16411,7 @@ Please try again or create the PR manually.`
16279
16411
  const message = {
16280
16412
  type: "assistant",
16281
16413
  message: {
16282
- id: randomUUID$1().toString(),
16414
+ id: randomUUID().toString(),
16283
16415
  type: "message",
16284
16416
  container: null,
16285
16417
  role: "assistant",
@@ -16296,7 +16428,7 @@ Please try again or create the PR manually.`
16296
16428
  },
16297
16429
  parent_tool_use_id: null,
16298
16430
  session_id: "",
16299
- uuid: randomUUID$1().toString()
16431
+ uuid: randomUUID().toString()
16300
16432
  };
16301
16433
  this.context.workClient.sendTaskMessage(message);
16302
16434
  }
@@ -16350,8 +16482,8 @@ URL: ${result.pullRequestUrl}`);
16350
16482
  }
16351
16483
  /**
16352
16484
  * Convert SDKUserMessage to Codex Input format
16353
- * Handles both text-only messages and messages with images
16354
- * Downloads images from URLs to local attachments directory
16485
+ * Handles both text-only messages and messages with images and documents
16486
+ * Downloads images and documents from URLs to local attachments directory
16355
16487
  */
16356
16488
  async convertSDKMessageToCodexInput(message) {
16357
16489
  const content = message.message.content;
@@ -16360,6 +16492,10 @@ URL: ${result.pullRequestUrl}`);
16360
16492
  }
16361
16493
  if (Array.isArray(content)) {
16362
16494
  const userInputs = [];
16495
+ const attachmentsDir = machine.resolveAttachmentsDir(
16496
+ this.options.input.userId,
16497
+ this.taskId
16498
+ );
16363
16499
  for (const block of content) {
16364
16500
  if (block.type === "text" && block.text) {
16365
16501
  userInputs.push({
@@ -16369,19 +16505,30 @@ URL: ${result.pullRequestUrl}`);
16369
16505
  } else if (block.type === "image" && block.source && block.source.url) {
16370
16506
  const url = block.source.url;
16371
16507
  try {
16372
- const attachmentsDir = machine.resolveAttachmentsDir(
16373
- this.options.input.userId,
16374
- this.taskId
16375
- );
16376
- const localPath = await downloadImage(url, attachmentsDir);
16377
- this.log("info", "IMAGE", `Downloaded image from ${url} to ${localPath}`);
16508
+ const { filePath } = await downloadFile(url, attachmentsDir, false);
16509
+ this.log("info", "IMAGE", `Downloaded image from ${url} to ${filePath}`);
16378
16510
  userInputs.push({
16379
16511
  type: "local_image",
16380
- path: localPath
16512
+ path: filePath
16381
16513
  });
16382
16514
  } catch (error) {
16383
16515
  this.log("error", "IMAGE", `Failed to download image from ${url}:`, error);
16384
16516
  }
16517
+ } else if (block.type === "document" && block.source && block.source.url) {
16518
+ const url = block.source.url;
16519
+ try {
16520
+ const { filePath, mimeType, filename } = await downloadFile(url, attachmentsDir, true);
16521
+ this.log("info", "DOCUMENT", `Downloaded document from ${url} to ${filePath}`);
16522
+ const title = block.title || filename;
16523
+ userInputs.push({
16524
+ type: "text",
16525
+ text: `Document: ${filePath}
16526
+ Title: ${title}
16527
+ Type: ${mimeType}`
16528
+ });
16529
+ } catch (error) {
16530
+ this.log("error", "DOCUMENT", `Failed to download document from ${url}:`, error);
16531
+ }
16385
16532
  }
16386
16533
  }
16387
16534
  if (userInputs.length === 1 && userInputs[0].type === "text") {
@@ -16555,13 +16702,17 @@ URL: ${result.pullRequestUrl}`);
16555
16702
  }
16556
16703
  };
16557
16704
  }
16558
- async exitWorker(status) {
16705
+ async exitWorker(status, errorMessage) {
16559
16706
  if (this.coordinator) {
16560
16707
  this.coordinator.stop();
16561
16708
  }
16562
- this.context.workClient.sendWorkerExit(status);
16563
16709
  this.log("info", "WORKER", `Exiting with status: ${status} for task ${this.taskId}`);
16564
- await this.context.workClient.disconnect();
16710
+ if (status === "error" && errorMessage) {
16711
+ await this.context.workClient.sendErrorMessageAndExit(errorMessage);
16712
+ } else {
16713
+ this.context.workClient.sendWorkerExit(status);
16714
+ await this.context.workClient.disconnect();
16715
+ }
16565
16716
  }
16566
16717
  /**
16567
16718
  * Reports git state and sends artifacts update to API.
@@ -16901,7 +17052,7 @@ cli.command("upgrade", "Upgrade CLI to the latest version", {}, async (argv) =>
16901
17052
  }
16902
17053
  }
16903
17054
  try {
16904
- const { version } = await import('./logger-ChZYRh-E.mjs').then(function (n) { return n._; });
17055
+ const { version } = await import('./logger-D-ioMWe6.mjs').then(function (n) { return n._; });
16905
17056
  console.log(chalk.green(`
16906
17057
  \u2713 Now running version: ${version}`));
16907
17058
  } catch {
@@ -17083,7 +17234,7 @@ cli.command(
17083
17234
  },
17084
17235
  async (argv) => {
17085
17236
  try {
17086
- const { testCommand } = await import('./index-k9I-urnJ.mjs');
17237
+ const { testCommand } = await import('./index-D1ipaIV_.mjs');
17087
17238
  await testCommand(argv);
17088
17239
  } catch (error) {
17089
17240
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Test mode failed");
package/dist/index.cjs CHANGED
@@ -3,8 +3,8 @@
3
3
  require('yargs');
4
4
  require('yargs/helpers');
5
5
  require('chalk');
6
- require('./index-DEoriCrL.cjs');
7
- require('./logger-DVI_I2D6.cjs');
6
+ require('./index-A8QO7gdw.cjs');
7
+ require('./logger---ZD5a2u.cjs');
8
8
  require('@agentrix/shared');
9
9
  require('node:crypto');
10
10
  require('axios');
@@ -24,12 +24,12 @@ require('fastify');
24
24
  require('zod');
25
25
  require('fastify-type-provider-zod');
26
26
  require('url');
27
+ require('node:stream/promises');
27
28
  require('@anthropic-ai/claude-agent-sdk');
28
29
  require('simple-git');
29
30
  require('node:fs/promises');
30
31
  require('crypto');
31
32
  require('@openai/codex-sdk');
32
33
  require('zod/v3');
33
- require('node:stream/promises');
34
34
  require('winston');
35
35
 
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import 'yargs';
2
2
  import 'yargs/helpers';
3
3
  import 'chalk';
4
- import './index-CWPJKpmJ.mjs';
5
- import './logger-ChZYRh-E.mjs';
4
+ import './index-Dzjo3uhE.mjs';
5
+ import './logger-D-ioMWe6.mjs';
6
6
  import '@agentrix/shared';
7
7
  import 'node:crypto';
8
8
  import 'axios';
@@ -22,11 +22,11 @@ import 'fastify';
22
22
  import 'zod';
23
23
  import 'fastify-type-provider-zod';
24
24
  import 'url';
25
+ import 'node:stream/promises';
25
26
  import '@anthropic-ai/claude-agent-sdk';
26
27
  import 'simple-git';
27
28
  import 'node:fs/promises';
28
29
  import 'crypto';
29
30
  import '@openai/codex-sdk';
30
31
  import 'zod/v3';
31
- import 'node:stream/promises';
32
32
  import 'winston';
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var _package = require('./logger-DVI_I2D6.cjs');
3
+ var _package = require('./logger---ZD5a2u.cjs');
4
4
  require('winston');
5
5
  require('chalk');
6
6
  require('node:os');
package/dist/lib.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { M as Machine, l as logger, m as machine } from './logger-ChZYRh-E.mjs';
1
+ export { M as Machine, l as logger, m as machine } from './logger-D-ioMWe6.mjs';
2
2
  import 'winston';
3
3
  import 'chalk';
4
4
  import 'node:os';
@@ -13,7 +13,7 @@ var require$$7 = require('url');
13
13
 
14
14
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
15
15
  var name = "@agentrix/cli";
16
- var version = "0.0.10";
16
+ var version = "0.0.12";
17
17
  var description = "Mobile and Web client for Claude Code and Codex";
18
18
  var author = "agentrix.xmz.ai";
19
19
  var type = "module";
@@ -189,7 +189,7 @@ var _package = /*#__PURE__*/Object.freeze({
189
189
  version: version
190
190
  });
191
191
 
192
- const __dirname$1 = path.dirname(require$$7.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('logger-DVI_I2D6.cjs', document.baseURI).href))));
192
+ const __dirname$1 = path.dirname(require$$7.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('logger---ZD5a2u.cjs', document.baseURI).href))));
193
193
  function projectPath() {
194
194
  const path$1 = path.resolve(__dirname$1, "..");
195
195
  return path$1;
@@ -10,7 +10,7 @@ import { dirname, resolve } from 'path';
10
10
  import { fileURLToPath } from 'url';
11
11
 
12
12
  var name = "@agentrix/cli";
13
- var version = "0.0.10";
13
+ var version = "0.0.12";
14
14
  var description = "Mobile and Web client for Claude Code and Codex";
15
15
  var author = "agentrix.xmz.ai";
16
16
  var type = "module";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentrix/cli",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "Mobile and Web client for Claude Code and Codex",
5
5
  "author": "agentrix.xmz.ai",
6
6
  "type": "module",