@agentrix/agentrix-run 0.6.0 → 0.7.0

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.
package/dist/index.cjs CHANGED
@@ -8,11 +8,12 @@ const DEFAULT_WAIT_TIMEOUT_SECONDS = 1800;
8
8
  const DEFAULT_AGENTRIX_BASE_URL = "https://agentrix.xmz.ai";
9
9
  function usage() {
10
10
  return [
11
- "Usage: agentrix-run --agent <agent> --prompt <prompt> [options]",
11
+ "Usage: agentrix-run (--agent <agent> | --resume <task-id>) --prompt <prompt> [options]",
12
12
  "",
13
13
  "Options:",
14
14
  " --title <text>",
15
15
  " --allow-filesystem-agent",
16
+ " --resume <task-id>",
16
17
  " --repo <json>",
17
18
  " --output-schema <json>",
18
19
  " --ref <ref>",
@@ -181,6 +182,10 @@ function parseArgs(argv) {
181
182
  case "--allow-filesystem-agent":
182
183
  options.allowFilesystemAgent = true;
183
184
  break;
185
+ case "--resume":
186
+ options.resumeTaskId = requireValue(argv, index, arg);
187
+ index += 1;
188
+ break;
184
189
  case "--title":
185
190
  options.title = requireValue(argv, index, arg);
186
191
  index += 1;
@@ -268,12 +273,15 @@ function parseArgs(argv) {
268
273
  throw new Error(`Unknown argument: ${arg}`);
269
274
  }
270
275
  }
271
- if (!options.agent.trim()) {
276
+ if (!options.resumeTaskId && !options.agent.trim()) {
272
277
  throw new Error("--agent is required");
273
278
  }
274
279
  if (!options.prompt.trim()) {
275
280
  throw new Error("--prompt is required");
276
281
  }
282
+ if (options.resumeTaskId !== void 0 && !options.resumeTaskId.trim()) {
283
+ throw new Error("--resume must be a non-empty task ID");
284
+ }
277
285
  return options;
278
286
  }
279
287
  function normalizeRef(value) {
@@ -483,6 +491,36 @@ async function createRun(baseUrl, apiKey, request) {
483
491
  const response = await requestJson("POST", `${baseUrl}/v1/ci/runs`, apiKey, request);
484
492
  return shared.CreateCiRunResponseSchema.parse(response);
485
493
  }
494
+ function createPromptMessage(text) {
495
+ return {
496
+ type: "user",
497
+ message: {
498
+ role: "user",
499
+ content: text.trim()
500
+ },
501
+ parent_tool_use_id: null,
502
+ session_id: ""
503
+ };
504
+ }
505
+ function buildResumeMessageRequest(options) {
506
+ return {
507
+ message: createPromptMessage(options.prompt),
508
+ target: "agent",
509
+ senderType: "human",
510
+ senderId: "agentrix-run",
511
+ senderName: "agentrix-run",
512
+ responseMode: options.responseMode
513
+ };
514
+ }
515
+ async function sendResumeMessage(baseUrl, apiKey, taskId, request) {
516
+ const response = await requestJson(
517
+ "POST",
518
+ `${baseUrl}/v1/tasks/${encodeURIComponent(taskId)}/send-message`,
519
+ apiKey,
520
+ request
521
+ );
522
+ return shared.SendTaskMessageResponseSchema.parse(response);
523
+ }
486
524
  function exitCodeForStatus(status) {
487
525
  return status === "completed" ? 0 : 1;
488
526
  }
@@ -567,12 +605,12 @@ function parseSseBlock(block) {
567
605
  data: JSON.parse(dataText)
568
606
  };
569
607
  }
570
- async function createRunStream(baseUrl, apiKey, request, deadline) {
608
+ async function streamRunRequest(baseUrl, apiKey, path, request, deadline) {
571
609
  const timeoutMs = Math.max(deadline - Date.now(), 1);
572
610
  const controller = new AbortController();
573
611
  const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs);
574
612
  try {
575
- const response = await fetch(`${baseUrl}/v1/ci/runs`, {
613
+ const response = await fetch(`${baseUrl}${path}`, {
576
614
  method: "POST",
577
615
  headers: {
578
616
  Authorization: `Bearer ${apiKey}`,
@@ -640,11 +678,44 @@ async function createRunStream(baseUrl, apiKey, request, deadline) {
640
678
  clearTimeout(timeoutHandle);
641
679
  }
642
680
  }
681
+ async function createRunStream(baseUrl, apiKey, request, deadline) {
682
+ return streamRunRequest(baseUrl, apiKey, "/v1/ci/runs", request, deadline);
683
+ }
684
+ async function resumeRunStream(baseUrl, apiKey, taskId, request, deadline) {
685
+ return streamRunRequest(
686
+ baseUrl,
687
+ apiKey,
688
+ `/v1/tasks/${encodeURIComponent(taskId)}/send-message`,
689
+ request,
690
+ deadline
691
+ );
692
+ }
643
693
  async function main(argv = process.argv.slice(2)) {
644
694
  const options = parseArgs(argv);
645
695
  const detected = detectCiContext();
646
696
  const baseUrl = resolveBaseUrl(options);
647
697
  const apiKey = resolveApiKey(options);
698
+ if (options.resumeTaskId) {
699
+ const taskId = options.resumeTaskId.trim();
700
+ const request2 = buildResumeMessageRequest(options);
701
+ if (options.responseMode === "async") {
702
+ const response = await sendResumeMessage(baseUrl, apiKey, taskId, request2);
703
+ if (!response.run) {
704
+ throw new Error("Server did not return CI run metadata for resumed task");
705
+ }
706
+ writeAsyncResultFile(options.resultFile, response.run);
707
+ printStandardFields({
708
+ runId: response.run.runId,
709
+ status: response.run.status,
710
+ detailUrl: response.run.detailUrl
711
+ });
712
+ return 0;
713
+ }
714
+ const deadline2 = ensureWaitDeadline(options);
715
+ const finalStatus2 = await resumeRunStream(baseUrl, apiKey, taskId, request2, deadline2);
716
+ writeResultFile(options.resultFile, finalStatus2);
717
+ return exitCodeForStatus(finalStatus2.status);
718
+ }
648
719
  const request = buildRequest(options, detected);
649
720
  if (options.responseMode === "async") {
650
721
  const run = await createRun(baseUrl, apiKey, request);
package/dist/index.mjs CHANGED
@@ -1,16 +1,17 @@
1
1
  import { writeFileSync, readFileSync } from 'node:fs';
2
- import { CreateCiRunRequestSchema, CiRunStatusResponseSchema, CreateCiRunResponseSchema } from '@agentrix/shared';
2
+ import { CreateCiRunRequestSchema, CiRunStatusResponseSchema, SendTaskMessageResponseSchema, CreateCiRunResponseSchema } from '@agentrix/shared';
3
3
 
4
4
  const DEFAULT_RESPONSE_MODE = "stream";
5
5
  const DEFAULT_WAIT_TIMEOUT_SECONDS = 1800;
6
6
  const DEFAULT_AGENTRIX_BASE_URL = "https://agentrix.xmz.ai";
7
7
  function usage() {
8
8
  return [
9
- "Usage: agentrix-run --agent <agent> --prompt <prompt> [options]",
9
+ "Usage: agentrix-run (--agent <agent> | --resume <task-id>) --prompt <prompt> [options]",
10
10
  "",
11
11
  "Options:",
12
12
  " --title <text>",
13
13
  " --allow-filesystem-agent",
14
+ " --resume <task-id>",
14
15
  " --repo <json>",
15
16
  " --output-schema <json>",
16
17
  " --ref <ref>",
@@ -179,6 +180,10 @@ function parseArgs(argv) {
179
180
  case "--allow-filesystem-agent":
180
181
  options.allowFilesystemAgent = true;
181
182
  break;
183
+ case "--resume":
184
+ options.resumeTaskId = requireValue(argv, index, arg);
185
+ index += 1;
186
+ break;
182
187
  case "--title":
183
188
  options.title = requireValue(argv, index, arg);
184
189
  index += 1;
@@ -266,12 +271,15 @@ function parseArgs(argv) {
266
271
  throw new Error(`Unknown argument: ${arg}`);
267
272
  }
268
273
  }
269
- if (!options.agent.trim()) {
274
+ if (!options.resumeTaskId && !options.agent.trim()) {
270
275
  throw new Error("--agent is required");
271
276
  }
272
277
  if (!options.prompt.trim()) {
273
278
  throw new Error("--prompt is required");
274
279
  }
280
+ if (options.resumeTaskId !== void 0 && !options.resumeTaskId.trim()) {
281
+ throw new Error("--resume must be a non-empty task ID");
282
+ }
275
283
  return options;
276
284
  }
277
285
  function normalizeRef(value) {
@@ -481,6 +489,36 @@ async function createRun(baseUrl, apiKey, request) {
481
489
  const response = await requestJson("POST", `${baseUrl}/v1/ci/runs`, apiKey, request);
482
490
  return CreateCiRunResponseSchema.parse(response);
483
491
  }
492
+ function createPromptMessage(text) {
493
+ return {
494
+ type: "user",
495
+ message: {
496
+ role: "user",
497
+ content: text.trim()
498
+ },
499
+ parent_tool_use_id: null,
500
+ session_id: ""
501
+ };
502
+ }
503
+ function buildResumeMessageRequest(options) {
504
+ return {
505
+ message: createPromptMessage(options.prompt),
506
+ target: "agent",
507
+ senderType: "human",
508
+ senderId: "agentrix-run",
509
+ senderName: "agentrix-run",
510
+ responseMode: options.responseMode
511
+ };
512
+ }
513
+ async function sendResumeMessage(baseUrl, apiKey, taskId, request) {
514
+ const response = await requestJson(
515
+ "POST",
516
+ `${baseUrl}/v1/tasks/${encodeURIComponent(taskId)}/send-message`,
517
+ apiKey,
518
+ request
519
+ );
520
+ return SendTaskMessageResponseSchema.parse(response);
521
+ }
484
522
  function exitCodeForStatus(status) {
485
523
  return status === "completed" ? 0 : 1;
486
524
  }
@@ -565,12 +603,12 @@ function parseSseBlock(block) {
565
603
  data: JSON.parse(dataText)
566
604
  };
567
605
  }
568
- async function createRunStream(baseUrl, apiKey, request, deadline) {
606
+ async function streamRunRequest(baseUrl, apiKey, path, request, deadline) {
569
607
  const timeoutMs = Math.max(deadline - Date.now(), 1);
570
608
  const controller = new AbortController();
571
609
  const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs);
572
610
  try {
573
- const response = await fetch(`${baseUrl}/v1/ci/runs`, {
611
+ const response = await fetch(`${baseUrl}${path}`, {
574
612
  method: "POST",
575
613
  headers: {
576
614
  Authorization: `Bearer ${apiKey}`,
@@ -638,11 +676,44 @@ async function createRunStream(baseUrl, apiKey, request, deadline) {
638
676
  clearTimeout(timeoutHandle);
639
677
  }
640
678
  }
679
+ async function createRunStream(baseUrl, apiKey, request, deadline) {
680
+ return streamRunRequest(baseUrl, apiKey, "/v1/ci/runs", request, deadline);
681
+ }
682
+ async function resumeRunStream(baseUrl, apiKey, taskId, request, deadline) {
683
+ return streamRunRequest(
684
+ baseUrl,
685
+ apiKey,
686
+ `/v1/tasks/${encodeURIComponent(taskId)}/send-message`,
687
+ request,
688
+ deadline
689
+ );
690
+ }
641
691
  async function main(argv = process.argv.slice(2)) {
642
692
  const options = parseArgs(argv);
643
693
  const detected = detectCiContext();
644
694
  const baseUrl = resolveBaseUrl(options);
645
695
  const apiKey = resolveApiKey(options);
696
+ if (options.resumeTaskId) {
697
+ const taskId = options.resumeTaskId.trim();
698
+ const request2 = buildResumeMessageRequest(options);
699
+ if (options.responseMode === "async") {
700
+ const response = await sendResumeMessage(baseUrl, apiKey, taskId, request2);
701
+ if (!response.run) {
702
+ throw new Error("Server did not return CI run metadata for resumed task");
703
+ }
704
+ writeAsyncResultFile(options.resultFile, response.run);
705
+ printStandardFields({
706
+ runId: response.run.runId,
707
+ status: response.run.status,
708
+ detailUrl: response.run.detailUrl
709
+ });
710
+ return 0;
711
+ }
712
+ const deadline2 = ensureWaitDeadline(options);
713
+ const finalStatus2 = await resumeRunStream(baseUrl, apiKey, taskId, request2, deadline2);
714
+ writeResultFile(options.resultFile, finalStatus2);
715
+ return exitCodeForStatus(finalStatus2.status);
716
+ }
646
717
  const request = buildRequest(options, detected);
647
718
  if (options.responseMode === "async") {
648
719
  const run = await createRun(baseUrl, apiKey, request);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentrix/agentrix-run",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Native CI submit-and-observe wrapper for Agentrix",
5
5
  "type": "module",
6
6
  "bin": {
@@ -32,7 +32,7 @@
32
32
  "prepublishOnly": "yarn build"
33
33
  },
34
34
  "dependencies": {
35
- "@agentrix/shared": "^2.33.0"
35
+ "@agentrix/shared": "^2.40.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": ">=20",