@dam-agents/cli 0.2.16 → 0.2.17

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 (2) hide show
  1. package/dist/bin.js +1028 -114
  2. package/package.json +5 -5
package/dist/bin.js CHANGED
@@ -26990,12 +26990,19 @@ var skillSourceSeedSchema = external_exports.object({
26990
26990
  path: skillSourcePathSchema.optional()
26991
26991
  });
26992
26992
  var templateCategorySchema = external_exports.enum(["harness", "preconfigured"]).default("harness");
26993
+ var harnessFamilySchema = external_exports.enum([
26994
+ "claude-code",
26995
+ "codex",
26996
+ "pi",
26997
+ "bob"
26998
+ ]);
26993
26999
  var templateSpecSchema = external_exports.object({
26994
27000
  version: external_exports.string(),
26995
27001
  image: external_exports.string(),
26996
27002
  name: external_exports.string().optional(),
26997
27003
  description: external_exports.string().optional(),
26998
27004
  category: templateCategorySchema,
27005
+ harness: harnessFamilySchema.optional(),
26999
27006
  tags: external_exports.array(external_exports.string()).optional(),
27000
27007
  docsUrl: external_exports.string().optional(),
27001
27008
  releaseNotesUrl: external_exports.string().optional(),
@@ -27098,7 +27105,8 @@ var podSessionTypeSchema = external_exports.enum([
27098
27105
  "channel_slack",
27099
27106
  "channel_telegram",
27100
27107
  "schedule_cron",
27101
- "experiment_execute"
27108
+ "experiment_execute",
27109
+ "cli_run"
27102
27110
  ]);
27103
27111
  var podSessionSchema = external_exports.object({
27104
27112
  sessionId: external_exports.string().min(1),
@@ -27122,6 +27130,16 @@ var podSessionListSchema = external_exports.object({
27122
27130
  var podSessionNoticeSchema = external_exports.object({
27123
27131
  topic: external_exports.literal("sessions")
27124
27132
  });
27133
+ var sessionDirectoryEntrySchema = external_exports.object({
27134
+ sessionId: external_exports.string().min(1),
27135
+ mode: podSessionModeSchema,
27136
+ type: podSessionTypeSchema,
27137
+ createdAt: external_exports.string()
27138
+ });
27139
+ var sessionDirectoryReportSchema = external_exports.object({
27140
+ protocolVersion: external_exports.literal("v1"),
27141
+ sessions: external_exports.array(sessionDirectoryEntrySchema).max(1e4)
27142
+ });
27125
27143
 
27126
27144
  // ../agent-runtime-api/src/modules/skills/schemas.ts
27127
27145
  var skillInstallInputSchema2 = external_exports.object({
@@ -27175,6 +27193,9 @@ var skillWriteLocalInputSchema = external_exports.object({
27175
27193
  ).min(1).max(50)
27176
27194
  });
27177
27195
 
27196
+ // ../agent-runtime-api/src/modules/skills/source-roots.ts
27197
+ var STAGED_SKILLS_DIR = "/usr/local/share/dam-skills";
27198
+
27178
27199
  // ../agent-runtime-api/src/modules/workspace/paths.ts
27179
27200
  var AGENT_HOME_DIR = "/home/agent";
27180
27201
  var AGENT_WORK_DIR = `${AGENT_HOME_DIR}/work`;
@@ -27841,7 +27862,14 @@ var artifactKindSchema = external_exports.enum([
27841
27862
  "text",
27842
27863
  "binary"
27843
27864
  ]);
27844
- var artifactVisibilitySchema = external_exports.enum(["private", "public"]);
27865
+ var artifactVisibilitySchema = external_exports.enum([
27866
+ "private",
27867
+ "restricted",
27868
+ "public"
27869
+ ]);
27870
+ var artifactCreateVisibilitySchema = external_exports.enum(["private", "public"]);
27871
+ var VIEWER_ALLOWLIST_MAX = 50;
27872
+ var viewerEmailSchema = external_exports.string().trim().toLowerCase().pipe(external_exports.email().max(254));
27845
27873
  var ARTIFACT_TITLE_MAX_LENGTH = 300;
27846
27874
  var titleSchema = external_exports.string().trim().min(1, "title is required").max(ARTIFACT_TITLE_MAX_LENGTH);
27847
27875
  var fileNameSchema = external_exports.string().trim().min(1).max(255);
@@ -27868,7 +27896,7 @@ var artifactCreateInputSchema = external_exports.object({
27868
27896
  kind: artifactKindSchema.optional(),
27869
27897
  contentType: external_exports.string().trim().min(1).max(200).optional(),
27870
27898
  folderId: external_exports.string().min(1).optional(),
27871
- visibility: artifactVisibilitySchema.optional(),
27899
+ visibility: artifactCreateVisibilitySchema.optional(),
27872
27900
  expiresInHours: expiresInHoursSchema.nullish()
27873
27901
  }).refine((v2) => v2.content == null !== (v2.uploadRef == null), {
27874
27902
  message: "provide exactly one of content or uploadRef",
@@ -27888,7 +27916,10 @@ var artifactUpdateInputSchema = external_exports.object({
27888
27916
  var artifactSharingInputSchema = external_exports.object({
27889
27917
  id: external_exports.string().min(1),
27890
27918
  visibility: artifactVisibilitySchema.optional(),
27891
- expiresInHours: expiresInHoursSchema.nullish()
27919
+ expiresInHours: expiresInHoursSchema.nullish(),
27920
+ viewers: external_exports.array(viewerEmailSchema).max(VIEWER_ALLOWLIST_MAX).transform((emails) => [...new Set(emails)]).optional().describe(
27921
+ "The whole Viewer Allowlist. Replaces the stored list; omit to leave it as is."
27922
+ )
27892
27923
  });
27893
27924
  var artifactUploadUrlInputSchema = external_exports.object({
27894
27925
  fileName: fileNameSchema
@@ -31122,6 +31153,79 @@ function templateIdForProvider(type, value) {
31122
31153
  return (matched ?? modes.find((mode) => mode.isDefault) ?? modes[0]).templateId;
31123
31154
  }
31124
31155
 
31156
+ // ../api-server-api/src/modules/case-studies/constants.ts
31157
+ var CASE_STUDY_CONTENT_MAX_CHARS = 262144;
31158
+ var CASE_STUDY_SKILL_NAME = "agent-case-study";
31159
+ var CASE_STUDY_SKILL_PATH = `${STAGED_SKILLS_DIR}/${CASE_STUDY_SKILL_NAME}/SKILL.md`;
31160
+ var CASE_STUDY_SCHEDULE_TASK = `Read ${CASE_STUDY_SKILL_PATH} and follow it to produce this week's edition of your case study. If that file does not exist, reply that this image does not ship the case-study skill and stop \u2014 do not attempt the task without it.`;
31161
+
31162
+ // ../api-server-api/src/modules/case-studies/schemas.ts
31163
+ var caseStudyStatusSchema = external_exports.enum([
31164
+ "pending",
31165
+ "released",
31166
+ "hidden",
31167
+ "deleted"
31168
+ ]);
31169
+ var caseStudyContentSourceSchema = external_exports.enum(["artifact", "submitted"]);
31170
+ var isoDateSchema = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected YYYY-MM-DD");
31171
+ var caseStudyIdInputSchema = external_exports.object({
31172
+ id: external_exports.string().min(1)
31173
+ });
31174
+ var caseStudyContentSchema = external_exports.string().min(1).max(CASE_STUDY_CONTENT_MAX_CHARS);
31175
+ var caseStudySubmitInputSchema = external_exports.object({
31176
+ content: caseStudyContentSchema,
31177
+ window_start: isoDateSchema,
31178
+ window_end: isoDateSchema,
31179
+ artifact_id: external_exports.string().min(1).optional()
31180
+ });
31181
+ var calendarDateSchema = isoDateSchema.refine((value) => {
31182
+ const parsed = new Date(value);
31183
+ return !Number.isNaN(parsed.getTime()) && parsed.toISOString().slice(0, 10) === value;
31184
+ }, "not a real calendar date");
31185
+ var caseStudyInspectionFilterSchema = external_exports.object({
31186
+ since: external_exports.string().datetime().optional().describe("Only editions updated at or after this ISO date-time."),
31187
+ week_of: calendarDateSchema.optional().describe(
31188
+ "Only editions of the week containing this date (YYYY-MM-DD, any day of that week)."
31189
+ ),
31190
+ agent_id: external_exports.string().min(1).optional().describe("Only editions submitted by this agent.")
31191
+ });
31192
+
31193
+ // ../api-server-api/src/modules/metrics/constants.ts
31194
+ var METRICS_MAX_SINCE_HOURS = 720;
31195
+ var METRICS_MAX_LIMIT = 1e3;
31196
+ var METRICS_DEFAULT_LIMIT = 100;
31197
+ var USAGE_SUMMARY_MAX_DAYS = 30;
31198
+ var USAGE_SUMMARY_DEFAULT_DAYS = 7;
31199
+
31200
+ // ../api-server-api/src/modules/metrics/schemas.ts
31201
+ var metricsOverviewInputSchema = external_exports.object({
31202
+ agentId: external_exports.string().min(1).optional(),
31203
+ sessionId: external_exports.string().min(1).optional(),
31204
+ sinceHours: external_exports.coerce.number().int().positive().max(METRICS_MAX_SINCE_HOURS).optional(),
31205
+ limit: external_exports.coerce.number().int().positive().max(METRICS_MAX_LIMIT).default(METRICS_DEFAULT_LIMIT)
31206
+ });
31207
+ var usageSummaryInputSchema = external_exports.object({
31208
+ days: external_exports.number().int().min(1).max(USAGE_SUMMARY_MAX_DAYS).default(USAGE_SUMMARY_DEFAULT_DAYS).describe(
31209
+ `Window length in days, counted back from now (default ${USAGE_SUMMARY_DEFAULT_DAYS}, max ${USAGE_SUMMARY_MAX_DAYS}).`
31210
+ )
31211
+ });
31212
+ var metricsSpendInputSchema = external_exports.object({
31213
+ from: external_exports.string().datetime(),
31214
+ to: external_exports.string().datetime()
31215
+ });
31216
+ var isValidTimeZone = (tz) => {
31217
+ try {
31218
+ Intl.DateTimeFormat(void 0, { timeZone: tz });
31219
+ return true;
31220
+ } catch {
31221
+ return false;
31222
+ }
31223
+ };
31224
+ var metricsSpendBreakdownInputSchema = metricsSpendInputSchema.extend({
31225
+ agentId: external_exports.string().min(1).optional(),
31226
+ timeZone: external_exports.string().min(1).refine(isValidTimeZone, { message: "invalid IANA timeZone" })
31227
+ });
31228
+
31125
31229
  // ../api-server-api/src/modules/secret-store/types.ts
31126
31230
  var secretRef = external_exports.object({
31127
31231
  storeId: external_exports.string().optional(),
@@ -31407,7 +31511,8 @@ var SessionType = {
31407
31511
  ChannelSlack: "channel_slack",
31408
31512
  ChannelTelegram: "channel_telegram",
31409
31513
  ScheduleCron: "schedule_cron",
31410
- ExperimentExecute: "experiment_execute"
31514
+ ExperimentExecute: "experiment_execute",
31515
+ CliRun: "cli_run"
31411
31516
  };
31412
31517
  var SessionMode = /* @__PURE__ */ ((SessionMode2) => {
31413
31518
  SessionMode2["Chat"] = "chat";
@@ -31503,6 +31608,11 @@ function describeApprovalPayload(payload) {
31503
31608
  return { title: payload.toolName ?? "tool call", subtitle: "" };
31504
31609
  }
31505
31610
 
31611
+ // ../api-server-api/src/modules/approvals/ids.ts
31612
+ function acpNativeRowId(agentId, sessionId, rpcId) {
31613
+ return `acpnative:${agentId}:${sessionId}:${rpcId}`;
31614
+ }
31615
+
31506
31616
  // ../api-server-api/src/modules/egress-rules/format.ts
31507
31617
  function formatEgressRuleSource(source) {
31508
31618
  if (source === "manual") return "manual";
@@ -31559,8 +31669,11 @@ function gatewayRestartImpact(input) {
31559
31669
  }
31560
31670
 
31561
31671
  // ../api-server-api/src/modules/acp/types.ts
31672
+ var PROMPT_QUEUE_FULL_CODE = "PROMPT_QUEUE_FULL";
31562
31673
  var platformTurnEndedParamsSchema = external_exports.object({
31563
- sessionId: external_exports.string().min(1)
31674
+ sessionId: external_exports.string().min(1),
31675
+ promptId: external_exports.string().min(1).optional(),
31676
+ stopReason: external_exports.string().min(1).optional()
31564
31677
  });
31565
31678
  var platformTurnEndedNotificationSchema = external_exports.object({
31566
31679
  jsonrpc: external_exports.literal("2.0"),
@@ -31570,6 +31683,37 @@ var platformTurnEndedNotificationSchema = external_exports.object({
31570
31683
  var platformClippedReplayMetaSchema = external_exports.object({
31571
31684
  older: external_exports.string().min(1).optional()
31572
31685
  });
31686
+ var platformReplayTurnMetaSchema = external_exports.object({
31687
+ inFlight: external_exports.boolean(),
31688
+ interruptedAt: external_exports.string().optional()
31689
+ });
31690
+ var promptBlockSchema = external_exports.discriminatedUnion("type", [
31691
+ external_exports.object({ type: external_exports.literal("text"), text: external_exports.string() }),
31692
+ external_exports.object({
31693
+ type: external_exports.literal("image"),
31694
+ data: external_exports.string(),
31695
+ mimeType: external_exports.string()
31696
+ }),
31697
+ external_exports.object({
31698
+ type: external_exports.literal("resource_link"),
31699
+ uri: external_exports.string(),
31700
+ name: external_exports.string(),
31701
+ mimeType: external_exports.string().optional(),
31702
+ size: external_exports.number().optional()
31703
+ })
31704
+ ]);
31705
+ var UNDELIVERED_INLINE_IMAGE_BYTES_CAP = 4 * 1024 * 1024;
31706
+ var platformUndeliveredPromptSchema = external_exports.object({
31707
+ id: external_exports.string().min(1),
31708
+ recordedAt: external_exports.string(),
31709
+ blocks: external_exports.array(promptBlockSchema).default([]),
31710
+ droppedAttachments: external_exports.array(external_exports.string()).default([]),
31711
+ reason: external_exports.string().optional()
31712
+ });
31713
+ var platformUndeliveredMetaSchema = external_exports.array(
31714
+ platformUndeliveredPromptSchema
31715
+ );
31716
+ var platformSupersededMetaSchema = external_exports.array(external_exports.string());
31573
31717
  var platformPromptAcceptedParamsSchema = external_exports.object({
31574
31718
  sessionId: external_exports.string().min(1),
31575
31719
  promptId: external_exports.string().min(1),
@@ -31580,6 +31724,18 @@ var platformPromptAcceptedNotificationSchema = external_exports.object({
31580
31724
  method: external_exports.literal("platform/promptAccepted"),
31581
31725
  params: platformPromptAcceptedParamsSchema
31582
31726
  });
31727
+ var platformRunResultSchema = external_exports.object({
31728
+ promptId: external_exports.string().nullable(),
31729
+ stopReason: external_exports.string().nullable(),
31730
+ finalText: external_exports.string(),
31731
+ truncated: external_exports.boolean(),
31732
+ endedAt: external_exports.string()
31733
+ });
31734
+ var platformRunResultResponseSchema = external_exports.discriminatedUnion("status", [
31735
+ external_exports.object({ status: external_exports.literal("done"), result: platformRunResultSchema }),
31736
+ external_exports.object({ status: external_exports.literal("pending") }),
31737
+ external_exports.object({ status: external_exports.literal("none") })
31738
+ ]);
31583
31739
  var platformPromptStartedParamsSchema = external_exports.object({
31584
31740
  sessionId: external_exports.string().min(1),
31585
31741
  promptId: external_exports.string().min(1)
@@ -31757,7 +31913,8 @@ var slackOutboundRecordSchema = external_exports.discriminatedUnion("kind", [
31757
31913
  external_exports.object({
31758
31914
  kind: external_exports.literal("upload"),
31759
31915
  channelId: external_exports.string(),
31760
- filename: external_exports.string()
31916
+ filename: external_exports.string(),
31917
+ threadTs: external_exports.string().optional()
31761
31918
  }).strict(),
31762
31919
  external_exports.object({
31763
31920
  kind: external_exports.literal("stream_start"),
@@ -32155,6 +32312,8 @@ var EXIT_AGENT_NOT_REACHABLE = 7;
32155
32312
  var EXIT_APPROVAL_NOT_ACTIONABLE = 8;
32156
32313
  var EXIT_SCHEDULE_NOT_FOUND = 9;
32157
32314
  var EXIT_TERMS_NOT_ACCEPTED = 10;
32315
+ var EXIT_RUN_STOPPED = 11;
32316
+ var EXIT_RUN_TIMEOUT = 12;
32158
32317
  var EXIT_SIGINT = 130;
32159
32318
 
32160
32319
  // src/modules/agent/commands/create.ts
@@ -38149,37 +38308,146 @@ function printError(e2) {
38149
38308
  }
38150
38309
  }
38151
38310
 
38152
- // src/modules/chat/commands/session-list.ts
38153
- function buildSessionListCommand(deps) {
38154
- return new Command("list").description("List sessions for an Agent").argument("<agent>", "agent name or ID").option("--server <url>", "override the configured server URL").option("--json", "emit raw JSON instead of the default table").action(
38155
- async (agentRef, opts) => {
38156
- const result = await deps.chatService.listSessions({
38157
- agentRef,
38158
- serverFlag: opts.server
38159
- });
38160
- if (!result.ok) {
38161
- printError(result.error);
38162
- process.exit(exitCodeFor2(result.error));
38163
- }
38164
- if (opts.json) {
38165
- process.stdout.write(`${JSON.stringify(result.value)}
38166
- `);
38167
- return;
38168
- }
38169
- if (result.value.length === 0) {
38170
- process.stderr.write("No sessions.\n");
38311
+ // src/modules/chat/commands/run.ts
38312
+ import { readFileSync } from "fs";
38313
+
38314
+ // src/modules/chat/services/run-service.ts
38315
+ import { randomUUID } from "crypto";
38316
+
38317
+ // ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
38318
+ var import_stream = __toESM(require_stream(), 1);
38319
+ var import_extension = __toESM(require_extension(), 1);
38320
+ var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
38321
+ var import_receiver = __toESM(require_receiver(), 1);
38322
+ var import_sender = __toESM(require_sender(), 1);
38323
+ var import_subprotocol = __toESM(require_subprotocol(), 1);
38324
+ var import_websocket = __toESM(require_websocket(), 1);
38325
+ var import_websocket_server = __toESM(require_websocket_server(), 1);
38326
+ var wrapper_default = import_websocket.default;
38327
+
38328
+ // src/modules/shared/ws-proxy.ts
38329
+ var import_http_proxy_agent = __toESM(require_dist2(), 1);
38330
+ var import_https_proxy_agent = __toESM(require_dist3(), 1);
38331
+ function proxyAgentForUrl(url2, env = process.env) {
38332
+ let target;
38333
+ try {
38334
+ target = new URL(url2);
38335
+ } catch {
38336
+ return void 0;
38337
+ }
38338
+ const secure = target.protocol === "wss:" || target.protocol === "https:";
38339
+ const proxy = secure ? env.HTTPS_PROXY ?? env.https_proxy : env.HTTP_PROXY ?? env.http_proxy;
38340
+ if (!proxy) return void 0;
38341
+ if (isNoProxy(target.hostname, env.NO_PROXY ?? env.no_proxy))
38342
+ return void 0;
38343
+ return secure ? new import_https_proxy_agent.HttpsProxyAgent(proxy) : new import_http_proxy_agent.HttpProxyAgent(proxy);
38344
+ }
38345
+ function isNoProxy(host, noProxy) {
38346
+ if (!noProxy) return false;
38347
+ for (const raw of noProxy.split(",")) {
38348
+ const entry = raw.trim();
38349
+ if (entry === "") continue;
38350
+ if (entry === "*") return true;
38351
+ const bare = (entry.startsWith(".") ? entry.slice(1) : entry).toLowerCase();
38352
+ if (host === bare || host.endsWith(`.${bare}`)) return true;
38353
+ }
38354
+ return false;
38355
+ }
38356
+
38357
+ // src/modules/chat/infrastructure/acp-run-connection.ts
38358
+ var CLIENT_ANSWERED_REQUESTS = {
38359
+ "fs/read_text_file": { content: "" },
38360
+ "fs/write_text_file": {}
38361
+ };
38362
+ async function connectRun(deps) {
38363
+ const ws = new import_websocket.default(deps.url, { agent: proxyAgentForUrl(deps.url) });
38364
+ await new Promise((resolve4, reject) => {
38365
+ ws.on("open", () => {
38366
+ resolve4();
38367
+ });
38368
+ ws.on("error", reject);
38369
+ });
38370
+ let nextId = 1;
38371
+ const pending = /* @__PURE__ */ new Map();
38372
+ const closed = new Promise((resolve4) => {
38373
+ ws.on("close", () => {
38374
+ for (const settle of pending.values())
38375
+ settle({
38376
+ ok: false,
38377
+ error: { code: -32e3, message: "connection closed" }
38378
+ });
38379
+ pending.clear();
38380
+ resolve4();
38381
+ });
38382
+ ws.on("error", () => {
38383
+ });
38384
+ });
38385
+ ws.on("message", (data) => {
38386
+ let frame;
38387
+ try {
38388
+ frame = JSON.parse(String(data));
38389
+ } catch {
38390
+ return;
38391
+ }
38392
+ if (typeof frame !== "object" || frame === null) return;
38393
+ const f = frame;
38394
+ if ("id" in f && !("method" in f)) {
38395
+ const settle = typeof f.id === "number" ? pending.get(f.id) : void 0;
38396
+ if (settle === void 0) return;
38397
+ pending.delete(f.id);
38398
+ settle(
38399
+ "error" in f && f.error !== void 0 ? { ok: false, error: f.error } : { ok: true, result: f.result }
38400
+ );
38401
+ return;
38402
+ }
38403
+ const method = typeof f.method === "string" ? f.method : "";
38404
+ if ("id" in f && f.id !== void 0 && f.id !== null) {
38405
+ if (method === "session/request_permission") {
38406
+ deps.onPermissionRequest({
38407
+ rpcId: f.id,
38408
+ params: f.params
38409
+ });
38171
38410
  return;
38172
38411
  }
38173
- const sorted = [...result.value].sort(
38174
- (a, b2) => a.createdAt.localeCompare(b2.createdAt)
38412
+ const answer = CLIENT_ANSWERED_REQUESTS[method];
38413
+ ws.send(
38414
+ JSON.stringify(
38415
+ answer === void 0 ? {
38416
+ jsonrpc: "2.0",
38417
+ id: f.id,
38418
+ error: { code: -32601, message: `unsupported: ${method}` }
38419
+ } : { jsonrpc: "2.0", id: f.id, result: answer }
38420
+ )
38175
38421
  );
38176
- const rows = [
38177
- ["SESSION ID", "MODE", "TYPE", "CREATED"],
38178
- ...sorted.map((s) => [s.sessionId, s.mode, s.type, s.createdAt])
38179
- ];
38180
- process.stdout.write(renderTable(rows));
38422
+ return;
38181
38423
  }
38182
- );
38424
+ deps.onNotification(method, f.params);
38425
+ });
38426
+ return {
38427
+ request(method, params) {
38428
+ return new Promise((resolve4) => {
38429
+ if (ws.readyState !== import_websocket.default.OPEN) {
38430
+ resolve4({
38431
+ ok: false,
38432
+ error: { code: -32e3, message: "connection closed" }
38433
+ });
38434
+ return;
38435
+ }
38436
+ const id = nextId++;
38437
+ pending.set(id, resolve4);
38438
+ ws.send(JSON.stringify({ jsonrpc: "2.0", id, method, params }));
38439
+ });
38440
+ },
38441
+ notify(method, params) {
38442
+ if (ws.readyState !== import_websocket.default.OPEN) return;
38443
+ ws.send(JSON.stringify({ jsonrpc: "2.0", method, params }));
38444
+ },
38445
+ closed,
38446
+ close() {
38447
+ if (ws.readyState === import_websocket.default.OPEN || ws.readyState === import_websocket.default.CONNECTING)
38448
+ ws.close();
38449
+ }
38450
+ };
38183
38451
  }
38184
38452
 
38185
38453
  // ../../node_modules/.pnpm/@agentclientprotocol+sdk@0.17.1_zod@4.4.3/node_modules/@agentclientprotocol/sdk/dist/schema/index.js
@@ -39853,46 +40121,6 @@ var RequestError = class _RequestError extends Error {
39853
40121
  }
39854
40122
  };
39855
40123
 
39856
- // ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
39857
- var import_stream = __toESM(require_stream(), 1);
39858
- var import_extension = __toESM(require_extension(), 1);
39859
- var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
39860
- var import_receiver = __toESM(require_receiver(), 1);
39861
- var import_sender = __toESM(require_sender(), 1);
39862
- var import_subprotocol = __toESM(require_subprotocol(), 1);
39863
- var import_websocket = __toESM(require_websocket(), 1);
39864
- var import_websocket_server = __toESM(require_websocket_server(), 1);
39865
- var wrapper_default = import_websocket.default;
39866
-
39867
- // src/modules/shared/ws-proxy.ts
39868
- var import_http_proxy_agent = __toESM(require_dist2(), 1);
39869
- var import_https_proxy_agent = __toESM(require_dist3(), 1);
39870
- function proxyAgentForUrl(url2, env = process.env) {
39871
- let target;
39872
- try {
39873
- target = new URL(url2);
39874
- } catch {
39875
- return void 0;
39876
- }
39877
- const secure = target.protocol === "wss:" || target.protocol === "https:";
39878
- const proxy = secure ? env.HTTPS_PROXY ?? env.https_proxy : env.HTTP_PROXY ?? env.http_proxy;
39879
- if (!proxy) return void 0;
39880
- if (isNoProxy(target.hostname, env.NO_PROXY ?? env.no_proxy))
39881
- return void 0;
39882
- return secure ? new import_https_proxy_agent.HttpsProxyAgent(proxy) : new import_http_proxy_agent.HttpProxyAgent(proxy);
39883
- }
39884
- function isNoProxy(host, noProxy) {
39885
- if (!noProxy) return false;
39886
- for (const raw of noProxy.split(",")) {
39887
- const entry = raw.trim();
39888
- if (entry === "") continue;
39889
- if (entry === "*") return true;
39890
- const bare = (entry.startsWith(".") ? entry.slice(1) : entry).toLowerCase();
39891
- if (host === bare || host.endsWith(`.${bare}`)) return true;
39892
- }
39893
- return false;
39894
- }
39895
-
39896
40124
  // src/modules/chat/infrastructure/acp-session-client.ts
39897
40125
  var TIMEOUT_MS = 12e4;
39898
40126
  function wsStream(url2) {
@@ -40000,13 +40228,13 @@ async function withConnection(url2, fn) {
40000
40228
  return await Promise.race([
40001
40229
  fn(connection2),
40002
40230
  new Promise((_, reject) => {
40003
- const fail = () => reject(
40231
+ const fail2 = () => reject(
40004
40232
  new Error(
40005
40233
  `ACP connection timed out after ${TIMEOUT_MS / 1e3}s of inactivity`
40006
40234
  )
40007
40235
  );
40008
- if (ac.signal.aborted) fail();
40009
- else ac.signal.addEventListener("abort", fail, { once: true });
40236
+ if (ac.signal.aborted) fail2();
40237
+ else ac.signal.addEventListener("abort", fail2, { once: true });
40010
40238
  })
40011
40239
  ]);
40012
40240
  } finally {
@@ -40041,6 +40269,701 @@ function createAcpSessionClient(opts) {
40041
40269
  };
40042
40270
  }
40043
40271
 
40272
+ // src/modules/chat/services/run-service.ts
40273
+ var DEFAULT_RUN_TIMEOUT_SECONDS = 3600;
40274
+ var RECONNECT_BACKOFF_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
40275
+ function createWaiter() {
40276
+ const buffered = [];
40277
+ let wake = null;
40278
+ return {
40279
+ push(event2) {
40280
+ buffered.push(event2);
40281
+ wake?.();
40282
+ },
40283
+ async next(deadlineAt, closed) {
40284
+ for (; ; ) {
40285
+ const head = buffered.shift();
40286
+ if (head !== void 0) return head;
40287
+ const remaining = deadlineAt - Date.now();
40288
+ if (remaining <= 0) return "timed-out";
40289
+ let timer;
40290
+ let onClosed = false;
40291
+ await Promise.race([
40292
+ new Promise((resolve4) => {
40293
+ wake = resolve4;
40294
+ timer = setTimeout(resolve4, remaining);
40295
+ }),
40296
+ closed.then(() => {
40297
+ onClosed = true;
40298
+ })
40299
+ ]);
40300
+ wake = null;
40301
+ clearTimeout(timer);
40302
+ if (buffered.length > 0) continue;
40303
+ if (onClosed) return "closed";
40304
+ if (Date.now() >= deadlineAt) return "timed-out";
40305
+ }
40306
+ }
40307
+ };
40308
+ }
40309
+ function extractText(params) {
40310
+ if (typeof params !== "object" || params === null) return null;
40311
+ const update = params.update;
40312
+ if (typeof update !== "object" || update === null) return null;
40313
+ const u = update;
40314
+ if (u.sessionUpdate !== "agent_message_chunk") return null;
40315
+ const content = u.content;
40316
+ if (typeof content !== "object" || content === null) return null;
40317
+ const c2 = content;
40318
+ return c2.type === "text" && typeof c2.text === "string" ? c2.text : null;
40319
+ }
40320
+ function sessionIdOf(params) {
40321
+ if (typeof params !== "object" || params === null) return null;
40322
+ const sid = params.sessionId;
40323
+ return typeof sid === "string" ? sid : null;
40324
+ }
40325
+ function stallLine(agentId, request) {
40326
+ const params = request.params ?? {};
40327
+ const title = typeof params.toolCall?.title === "string" ? params.toolCall.title : "tool call";
40328
+ const egressId = params.toolCall?.rawInput?.approvalId;
40329
+ const approvalId = typeof egressId === "string" ? egressId : typeof params.sessionId === "string" ? acpNativeRowId(agentId, params.sessionId, request.rpcId) : null;
40330
+ return approvalId === null ? `run stalled on a permission request (${title}) \u2014 see: dam approval list` : `run stalled on a permission request (${title}) \u2014 resolve with: dam approval approve ${approvalId}`;
40331
+ }
40332
+ function matchesPrompt(result, promptId) {
40333
+ return result.promptId === promptId || result.promptId === null;
40334
+ }
40335
+ function resultSessionId(result) {
40336
+ if (typeof result !== "object" || result === null) return null;
40337
+ const sid = result.sessionId;
40338
+ return typeof sid === "string" && sid.length > 0 ? sid : null;
40339
+ }
40340
+ function createRunService(deps) {
40341
+ async function connect(ctx, waiter, sessionFilter, onText, onPromptStarted) {
40342
+ let conn;
40343
+ try {
40344
+ conn = await connectRun({
40345
+ url: acpUrl(ctx.host, ctx.agentId, ctx.token),
40346
+ onPermissionRequest: (request) => {
40347
+ deps.errOut(stallLine(ctx.agentId, request));
40348
+ },
40349
+ onNotification: (method, params) => {
40350
+ const sid = sessionIdOf(params);
40351
+ if (sid === null || sid !== sessionFilter()) return;
40352
+ if (method === "session/update") {
40353
+ const text = extractText(params);
40354
+ if (text !== null) onText(text);
40355
+ return;
40356
+ }
40357
+ if (method === "platform/promptStarted") {
40358
+ const parsed = platformPromptStartedParamsSchema.safeParse(params);
40359
+ if (parsed.success) {
40360
+ onPromptStarted?.();
40361
+ waiter.push({ kind: "prompt-started" });
40362
+ }
40363
+ return;
40364
+ }
40365
+ if (method === "platform/promptAccepted") {
40366
+ const parsed = platformPromptAcceptedParamsSchema.safeParse(params);
40367
+ if (parsed.success && parsed.data.queued)
40368
+ waiter.push({ kind: "prompt-queued" });
40369
+ return;
40370
+ }
40371
+ if (method === "platform/turnEnded") {
40372
+ const parsed = platformTurnEndedParamsSchema.safeParse(params);
40373
+ waiter.push({
40374
+ kind: "turn-ended",
40375
+ promptId: parsed.success ? parsed.data.promptId ?? null : null,
40376
+ stopReason: parsed.success ? parsed.data.stopReason ?? null : null
40377
+ });
40378
+ }
40379
+ }
40380
+ });
40381
+ } catch {
40382
+ return null;
40383
+ }
40384
+ const init = await conn.request("initialize", {
40385
+ protocolVersion: 1,
40386
+ clientCapabilities: {},
40387
+ clientInfo: { name: "platform-cli-run", version: "1.0.0" }
40388
+ });
40389
+ if (!init.ok) {
40390
+ conn.close();
40391
+ return null;
40392
+ }
40393
+ return conn;
40394
+ }
40395
+ async function loadSession(conn, sessionId) {
40396
+ const loaded = await conn.request("session/load", {
40397
+ sessionId,
40398
+ cwd: ".",
40399
+ mcpServers: [],
40400
+ _meta: { platform: { tail: true } }
40401
+ });
40402
+ if (!loaded.ok) {
40403
+ return err2({
40404
+ kind: "run-failed",
40405
+ reason: `session '${sessionId}' could not be loaded: ${loaded.error.message}`,
40406
+ sessionId
40407
+ });
40408
+ }
40409
+ return ok2(loaded.result);
40410
+ }
40411
+ async function fetchRunResult(conn, sessionId) {
40412
+ const res = await conn.request("platform/runResult", { sessionId });
40413
+ if (!res.ok) return null;
40414
+ const parsed = platformRunResultResponseSchema.safeParse(res.result);
40415
+ return parsed.success ? parsed.data : null;
40416
+ }
40417
+ async function reconnectAndFinish(opts) {
40418
+ const { ctx, sessionId, promptId, deadlineAt } = opts;
40419
+ let backoffStep = 0;
40420
+ const finish = (result) => {
40421
+ const remainder = result.finalText.slice(opts.printedChars);
40422
+ if (remainder.length > 0) deps.out(remainder);
40423
+ if (result.truncated)
40424
+ deps.errOut("note: the recorded run output was truncated");
40425
+ return ok2({
40426
+ kind: "completed",
40427
+ sessionId,
40428
+ stopReason: result.stopReason
40429
+ });
40430
+ };
40431
+ for (; ; ) {
40432
+ if (Date.now() >= deadlineAt)
40433
+ return ok2({ kind: "timed-out", sessionId });
40434
+ const delay = RECONNECT_BACKOFF_MS[Math.min(backoffStep, RECONNECT_BACKOFF_MS.length - 1)];
40435
+ backoffStep += 1;
40436
+ await new Promise((resolve4) => setTimeout(resolve4, delay));
40437
+ const waiter = createWaiter();
40438
+ const conn = await connect(
40439
+ ctx,
40440
+ waiter,
40441
+ () => sessionId,
40442
+ () => {
40443
+ }
40444
+ );
40445
+ if (conn === null) continue;
40446
+ deps.errOut("reconnected; waiting for the turn to finish");
40447
+ try {
40448
+ const loaded = await loadSession(conn, sessionId);
40449
+ if (!loaded.ok) return loaded;
40450
+ for (; ; ) {
40451
+ const record2 = await fetchRunResult(conn, sessionId);
40452
+ if (record2?.status === "done" && matchesPrompt(record2.result, promptId))
40453
+ return finish(record2.result);
40454
+ const event2 = await waiter.next(deadlineAt, conn.closed);
40455
+ if (event2 === "timed-out")
40456
+ return ok2({ kind: "timed-out", sessionId });
40457
+ if (event2 === "closed") break;
40458
+ if (event2.kind !== "turn-ended") continue;
40459
+ if (event2.promptId !== null && event2.promptId !== promptId) continue;
40460
+ const after = await fetchRunResult(conn, sessionId);
40461
+ if (after?.status === "done" && matchesPrompt(after.result, promptId))
40462
+ return finish(after.result);
40463
+ if (event2.promptId === promptId) {
40464
+ deps.errOut(
40465
+ "note: the turn ended but no run record was found; output may be incomplete"
40466
+ );
40467
+ return ok2({
40468
+ kind: "completed",
40469
+ sessionId,
40470
+ stopReason: event2.stopReason
40471
+ });
40472
+ }
40473
+ }
40474
+ } finally {
40475
+ conn.close();
40476
+ }
40477
+ }
40478
+ }
40479
+ return {
40480
+ async run(input) {
40481
+ const ctx = await deps.bootstrap(input.agentRef, input.serverFlag);
40482
+ if (!ctx.ok) return ctx;
40483
+ const deadlineAt = Date.now() + input.timeoutSeconds * 1e3;
40484
+ const promptId = randomUUID();
40485
+ let sessionId = input.sessionId ?? null;
40486
+ const streaming = input.async !== true;
40487
+ let started = input.sessionId === void 0;
40488
+ let printedChars = 0;
40489
+ const waiter = createWaiter();
40490
+ const conn = await connect(
40491
+ ctx.value,
40492
+ waiter,
40493
+ () => sessionId,
40494
+ (text) => {
40495
+ if (!started || !streaming) return;
40496
+ deps.out(text);
40497
+ printedChars += text.length;
40498
+ },
40499
+ () => {
40500
+ started = true;
40501
+ }
40502
+ );
40503
+ if (conn === null)
40504
+ return err2({
40505
+ kind: "run-failed",
40506
+ reason: "could not connect to the agent"
40507
+ });
40508
+ let releaseInterrupt = () => {
40509
+ };
40510
+ try {
40511
+ if (sessionId === null) {
40512
+ const created = await conn.request("session/new", {
40513
+ cwd: ".",
40514
+ mcpServers: [],
40515
+ _meta: {
40516
+ platform: { mode: "chat" /* Chat */, type: SessionType.CliRun }
40517
+ }
40518
+ });
40519
+ if (!created.ok)
40520
+ return err2({
40521
+ kind: "run-failed",
40522
+ reason: `session could not be created: ${created.error.message}`
40523
+ });
40524
+ sessionId = resultSessionId(created.result);
40525
+ if (sessionId === null)
40526
+ return err2({
40527
+ kind: "run-failed",
40528
+ reason: "the agent returned no session id"
40529
+ });
40530
+ } else {
40531
+ const loaded = await loadSession(conn, sessionId);
40532
+ if (!loaded.ok) return loaded;
40533
+ }
40534
+ const sid = sessionId;
40535
+ releaseInterrupt = deps.onInterrupt?.(() => {
40536
+ deps.errOut("cancelling the run");
40537
+ conn.notify("session/cancel", { sessionId: sid });
40538
+ }) ?? (() => {
40539
+ });
40540
+ void conn.request("session/prompt", {
40541
+ sessionId: sid,
40542
+ prompt: [{ type: "text", text: input.prompt }],
40543
+ _meta: { platform: { promptId, surface: "cli" } }
40544
+ }).then((outcome) => {
40545
+ waiter.push({ kind: "prompt-response", outcome });
40546
+ });
40547
+ for (; ; ) {
40548
+ const event2 = await waiter.next(deadlineAt, conn.closed);
40549
+ if (event2 === "timed-out")
40550
+ return ok2({ kind: "timed-out", sessionId: sid });
40551
+ if (event2 === "closed") {
40552
+ deps.errOut(
40553
+ `connection lost mid-turn; the run continues on the agent (session ${sid})`
40554
+ );
40555
+ return reconnectAndFinish({
40556
+ ctx: ctx.value,
40557
+ sessionId: sid,
40558
+ promptId,
40559
+ deadlineAt,
40560
+ printedChars
40561
+ });
40562
+ }
40563
+ if (event2.kind === "prompt-response") {
40564
+ const outcome = event2.outcome;
40565
+ if (outcome.ok) {
40566
+ const stopReason = typeof outcome.result?.stopReason === "string" ? outcome.result.stopReason : null;
40567
+ return ok2({
40568
+ kind: "completed",
40569
+ sessionId: sid,
40570
+ stopReason
40571
+ });
40572
+ }
40573
+ if (outcome.error.message === "connection closed") {
40574
+ deps.errOut(
40575
+ `connection lost mid-turn; the run continues on the agent (session ${sid})`
40576
+ );
40577
+ return reconnectAndFinish({
40578
+ ctx: ctx.value,
40579
+ sessionId: sid,
40580
+ promptId,
40581
+ deadlineAt,
40582
+ printedChars
40583
+ });
40584
+ }
40585
+ const queueFull = typeof outcome.error.data === "object" && outcome.error.data !== null && outcome.error.data.code === PROMPT_QUEUE_FULL_CODE;
40586
+ return err2({
40587
+ kind: "run-failed",
40588
+ reason: queueFull ? "the session's prompt queue is full \u2014 try again later" : `prompt failed: ${outcome.error.message}`,
40589
+ sessionId: sid
40590
+ });
40591
+ }
40592
+ if (event2.kind === "prompt-queued" && !started)
40593
+ deps.errOut("prompt queued behind a running turn; waiting");
40594
+ if (event2.kind === "prompt-started") {
40595
+ started = true;
40596
+ if (input.async)
40597
+ return ok2({ kind: "async-started", sessionId: sid });
40598
+ }
40599
+ }
40600
+ } finally {
40601
+ releaseInterrupt();
40602
+ conn.close();
40603
+ }
40604
+ },
40605
+ async get(input) {
40606
+ const ctx = await deps.bootstrap(input.agentRef, input.serverFlag);
40607
+ if (!ctx.ok) return ctx;
40608
+ const deadlineAt = Date.now() + input.timeoutSeconds * 1e3;
40609
+ const sessionId = input.sessionId;
40610
+ let firstAttempt = true;
40611
+ for (; ; ) {
40612
+ if (!firstAttempt) {
40613
+ if (Date.now() >= deadlineAt)
40614
+ return ok2({ kind: "timed-out", sessionId });
40615
+ await new Promise((resolve4) => setTimeout(resolve4, 2e3));
40616
+ }
40617
+ firstAttempt = false;
40618
+ const waiter = createWaiter();
40619
+ const conn = await connect(
40620
+ ctx.value,
40621
+ waiter,
40622
+ () => sessionId,
40623
+ () => {
40624
+ }
40625
+ );
40626
+ if (conn === null) {
40627
+ if (input.wait) continue;
40628
+ return err2({
40629
+ kind: "run-failed",
40630
+ reason: "could not connect to the agent",
40631
+ sessionId
40632
+ });
40633
+ }
40634
+ try {
40635
+ const record2 = await fetchRunResult(conn, sessionId);
40636
+ if (record2 === null)
40637
+ return err2({
40638
+ kind: "run-failed",
40639
+ reason: "the agent does not support run results \u2014 update its image",
40640
+ sessionId
40641
+ });
40642
+ if (record2.status === "done")
40643
+ return ok2({ kind: "done", result: record2.result });
40644
+ if (record2.status === "none" && !input.wait)
40645
+ return ok2({ kind: "none", sessionId });
40646
+ if (!input.wait) return ok2({ kind: "pending", sessionId });
40647
+ const loaded = await loadSession(conn, sessionId);
40648
+ if (!loaded.ok) return loaded;
40649
+ for (; ; ) {
40650
+ const event2 = await waiter.next(deadlineAt, conn.closed);
40651
+ if (event2 === "timed-out")
40652
+ return ok2({ kind: "timed-out", sessionId });
40653
+ if (event2 === "closed") break;
40654
+ if (event2.kind !== "turn-ended") continue;
40655
+ const after = await fetchRunResult(conn, sessionId);
40656
+ if (after?.status === "done")
40657
+ return ok2({ kind: "done", result: after.result });
40658
+ }
40659
+ } finally {
40660
+ conn.close();
40661
+ }
40662
+ }
40663
+ },
40664
+ async cancel(input) {
40665
+ const ctx = await deps.bootstrap(input.agentRef, input.serverFlag);
40666
+ if (!ctx.ok) return ctx;
40667
+ const sessionId = input.sessionId;
40668
+ const conn = await connect(
40669
+ ctx.value,
40670
+ createWaiter(),
40671
+ () => sessionId,
40672
+ () => {
40673
+ }
40674
+ );
40675
+ if (conn === null)
40676
+ return err2({
40677
+ kind: "run-failed",
40678
+ reason: "could not connect to the agent",
40679
+ sessionId
40680
+ });
40681
+ try {
40682
+ const record2 = await fetchRunResult(conn, sessionId);
40683
+ if (record2 === null)
40684
+ return err2({
40685
+ kind: "run-failed",
40686
+ reason: "could not read the run state \u2014 the agent may not support run results; update its image, or cancel from the UI",
40687
+ sessionId
40688
+ });
40689
+ if (record2.status !== "pending")
40690
+ return ok2({ kind: "not-running", sessionId });
40691
+ conn.notify("session/cancel", { sessionId });
40692
+ return ok2({ kind: "cancelled", sessionId });
40693
+ } finally {
40694
+ conn.close();
40695
+ }
40696
+ }
40697
+ };
40698
+ }
40699
+
40700
+ // src/modules/chat/commands/run.ts
40701
+ var END_TURN = "end_turn";
40702
+ function resolvePrompt(opts) {
40703
+ if (opts.prompt !== void 0 && opts.promptFile !== void 0)
40704
+ return err2("pass exactly one of --prompt and --prompt-file");
40705
+ if (opts.prompt !== void 0) return ok2(opts.prompt);
40706
+ if (opts.promptFile === void 0)
40707
+ return err2("a prompt is required: pass --prompt or --prompt-file");
40708
+ try {
40709
+ return ok2(opts.readFile(opts.promptFile));
40710
+ } catch (e2) {
40711
+ return err2(
40712
+ `could not read prompt file '${opts.promptFile}': ${e2 instanceof Error ? e2.message : String(e2)}`
40713
+ );
40714
+ }
40715
+ }
40716
+ function readPromptFile(path2) {
40717
+ return readFileSync(path2 === "-" ? 0 : path2, "utf8");
40718
+ }
40719
+ function fail(e2) {
40720
+ if (e2.kind === "run-failed") {
40721
+ process.stderr.write(`error: ${e2.reason}
40722
+ `);
40723
+ if (e2.sessionId !== void 0)
40724
+ process.stderr.write(`session: ${e2.sessionId}
40725
+ `);
40726
+ process.exitCode = EXIT_RUNTIME_FAILURE;
40727
+ return;
40728
+ }
40729
+ printError(e2);
40730
+ process.exitCode = exitCodeFor2(e2);
40731
+ }
40732
+ function stopExitCode(stopReason) {
40733
+ return stopReason === END_TURN ? 0 : EXIT_RUN_STOPPED;
40734
+ }
40735
+ function timeoutOrInvalid(raw) {
40736
+ const seconds = parseTimeout(raw, DEFAULT_RUN_TIMEOUT_SECONDS);
40737
+ if (seconds === null) {
40738
+ process.stderr.write("error: --timeout must be a positive number\n");
40739
+ process.exit(EXIT_INVALID_INPUT);
40740
+ }
40741
+ return seconds;
40742
+ }
40743
+ function buildRunCommand(deps) {
40744
+ const run2 = new Command("run").description(
40745
+ "Run an agent headlessly: submit a prompt and stream the answer"
40746
+ ).argument("<agent>", "agent name or ID").option("--server <url>", "override the configured server URL").option("-p, --prompt <text>", "the prompt text").option("--prompt-file <path>", "read the prompt from a file ('-' = stdin)").option("--session <id>", "continue an existing session").option("--async", "exit once the prompt has started; poll with 'run get'").option(
40747
+ "--timeout <seconds>",
40748
+ `give up waiting after this many seconds (default ${String(DEFAULT_RUN_TIMEOUT_SECONDS)})`
40749
+ ).action(
40750
+ async (agentRef, opts) => {
40751
+ const prompt = resolvePrompt({
40752
+ prompt: opts.prompt,
40753
+ promptFile: opts.promptFile,
40754
+ readFile: readPromptFile
40755
+ });
40756
+ if (!prompt.ok) {
40757
+ process.stderr.write(`error: ${prompt.error}
40758
+ `);
40759
+ process.exitCode = EXIT_INVALID_INPUT;
40760
+ return;
40761
+ }
40762
+ const result = await deps.runService.run({
40763
+ agentRef,
40764
+ serverFlag: opts.server,
40765
+ prompt: prompt.value,
40766
+ sessionId: opts.session,
40767
+ async: opts.async,
40768
+ timeoutSeconds: timeoutOrInvalid(opts.timeout)
40769
+ });
40770
+ if (!result.ok) {
40771
+ fail(result.error);
40772
+ return;
40773
+ }
40774
+ const outcome = result.value;
40775
+ if (outcome.kind === "async-started") {
40776
+ process.stdout.write(`${outcome.sessionId}
40777
+ `);
40778
+ process.stderr.write(
40779
+ `run started; poll it with: dam run get ${agentRef} ${outcome.sessionId}
40780
+ `
40781
+ );
40782
+ return;
40783
+ }
40784
+ if (outcome.kind === "timed-out") {
40785
+ process.stderr.write(
40786
+ `timed out waiting; the run continues on the agent
40787
+ check it with: dam run get ${agentRef} ${outcome.sessionId}
40788
+ `
40789
+ );
40790
+ process.exitCode = EXIT_RUN_TIMEOUT;
40791
+ return;
40792
+ }
40793
+ endStdoutLine();
40794
+ process.stderr.write(
40795
+ `stopReason: ${outcome.stopReason ?? "unknown"}
40796
+ `
40797
+ );
40798
+ process.exitCode = stopExitCode(outcome.stopReason);
40799
+ }
40800
+ );
40801
+ run2.command("get").description("Read a headless run's recorded result").argument("<agent>", "agent name or ID").argument("<session-id>", "the run's session id").option("--server <url>", "override the configured server URL").option("-w, --wait", "wait for the running turn to finish").option(
40802
+ "--timeout <seconds>",
40803
+ `with --wait, give up after this many seconds (default ${String(DEFAULT_RUN_TIMEOUT_SECONDS)})`
40804
+ ).option("--json", "emit the raw run-result payload instead of plain text").action(
40805
+ async (agentRef, sessionId, opts) => {
40806
+ const result = await deps.runService.get({
40807
+ agentRef,
40808
+ serverFlag: opts.server,
40809
+ sessionId,
40810
+ wait: opts.wait,
40811
+ timeoutSeconds: timeoutOrInvalid(opts.timeout)
40812
+ });
40813
+ if (!result.ok) {
40814
+ fail(result.error);
40815
+ return;
40816
+ }
40817
+ const outcome = result.value;
40818
+ if (outcome.kind === "pending") {
40819
+ if (opts.json)
40820
+ process.stdout.write(`${JSON.stringify({ status: "pending" })}
40821
+ `);
40822
+ else process.stderr.write("still running\n");
40823
+ return;
40824
+ }
40825
+ if (outcome.kind === "none") {
40826
+ if (opts.json)
40827
+ process.stdout.write(`${JSON.stringify({ status: "none" })}
40828
+ `);
40829
+ else
40830
+ process.stderr.write(
40831
+ "no recorded result for this session \u2014 it never finished a headless run here, or the record was evicted\n"
40832
+ );
40833
+ process.exitCode = EXIT_INVALID_INPUT;
40834
+ return;
40835
+ }
40836
+ if (outcome.kind === "timed-out") {
40837
+ if (opts.json)
40838
+ process.stdout.write(`${JSON.stringify({ status: "pending" })}
40839
+ `);
40840
+ process.stderr.write("timed out waiting; the run continues\n");
40841
+ process.exitCode = EXIT_RUN_TIMEOUT;
40842
+ return;
40843
+ }
40844
+ if (opts.json) {
40845
+ process.stdout.write(
40846
+ `${JSON.stringify({ status: "done", result: outcome.result })}
40847
+ `
40848
+ );
40849
+ process.exitCode = stopExitCode(outcome.result.stopReason);
40850
+ return;
40851
+ }
40852
+ if (outcome.result.finalText.length > 0) {
40853
+ process.stdout.write(outcome.result.finalText);
40854
+ if (!outcome.result.finalText.endsWith("\n"))
40855
+ process.stdout.write("\n");
40856
+ }
40857
+ if (outcome.result.truncated)
40858
+ process.stderr.write("note: the recorded run output was truncated\n");
40859
+ process.stderr.write(
40860
+ `stopReason: ${outcome.result.stopReason ?? "unknown"}
40861
+ `
40862
+ );
40863
+ process.exitCode = stopExitCode(outcome.result.stopReason);
40864
+ }
40865
+ );
40866
+ run2.command("cancel").description("Cancel a running headless run").argument("<agent>", "agent name or ID").argument("<session-id>", "the run's session id").option("--server <url>", "override the configured server URL").action(
40867
+ async (agentRef, sessionId, opts) => {
40868
+ const result = await deps.runService.cancel({
40869
+ agentRef,
40870
+ serverFlag: opts.server,
40871
+ sessionId
40872
+ });
40873
+ if (!result.ok) {
40874
+ fail(result.error);
40875
+ return;
40876
+ }
40877
+ if (result.value.kind === "not-running") {
40878
+ process.stderr.write(
40879
+ "nothing to cancel: the session is not running\n"
40880
+ );
40881
+ process.exitCode = EXIT_INVALID_INPUT;
40882
+ return;
40883
+ }
40884
+ process.stderr.write("cancel sent\n");
40885
+ }
40886
+ );
40887
+ return run2;
40888
+ }
40889
+ var stdoutEndedWithNewline = true;
40890
+ function trackStdout(text) {
40891
+ process.stdout.write(text);
40892
+ if (text.length > 0) stdoutEndedWithNewline = text.endsWith("\n");
40893
+ }
40894
+ function endStdoutLine() {
40895
+ if (!stdoutEndedWithNewline) process.stdout.write("\n");
40896
+ }
40897
+
40898
+ // src/modules/chat/commands/session-list.ts
40899
+ function buildSessionListCommand(deps) {
40900
+ return new Command("list").description("List sessions for an Agent").argument("<agent>", "agent name or ID").option("--server <url>", "override the configured server URL").option("--json", "emit raw JSON instead of the default table").action(
40901
+ async (agentRef, opts) => {
40902
+ const result = await deps.chatService.listSessions({
40903
+ agentRef,
40904
+ serverFlag: opts.server
40905
+ });
40906
+ if (!result.ok) {
40907
+ printError(result.error);
40908
+ process.exit(exitCodeFor2(result.error));
40909
+ }
40910
+ if (opts.json) {
40911
+ process.stdout.write(`${JSON.stringify(result.value)}
40912
+ `);
40913
+ return;
40914
+ }
40915
+ if (result.value.length === 0) {
40916
+ process.stderr.write("No sessions.\n");
40917
+ return;
40918
+ }
40919
+ const sorted = [...result.value].sort(
40920
+ (a, b2) => a.createdAt.localeCompare(b2.createdAt)
40921
+ );
40922
+ const rows = [
40923
+ ["SESSION ID", "MODE", "TYPE", "CREATED"],
40924
+ ...sorted.map((s) => [s.sessionId, s.mode, s.type, s.createdAt])
40925
+ ];
40926
+ process.stdout.write(renderTable(rows));
40927
+ }
40928
+ );
40929
+ }
40930
+
40931
+ // src/modules/chat/services/bootstrap.ts
40932
+ function createBootstrap(deps) {
40933
+ return async function bootstrap(agentRef, serverFlag) {
40934
+ const flag = serverFlag ? { server: serverFlag } : void 0;
40935
+ const config2 = await deps.configService.getResolved({ flag });
40936
+ if (!config2.ok) {
40937
+ return config2.error.kind === "malformed-config" ? err2({
40938
+ kind: "malformed-config",
40939
+ reason: config2.error.reason
40940
+ }) : err2({ kind: "no-server" });
40941
+ }
40942
+ const host = config2.value.server;
40943
+ const compat = await deps.compatService.check({ flag });
40944
+ if (!compat.ok)
40945
+ return err2({
40946
+ kind: "transport",
40947
+ reason: compat.error.kind === "probe-error" ? compat.error.message : compat.error.kind
40948
+ });
40949
+ if (compat.value.kind === "below-floor") {
40950
+ return err2({
40951
+ kind: "below-floor",
40952
+ localCli: compat.value.localCli,
40953
+ serverMinClient: compat.value.serverMinClient
40954
+ });
40955
+ }
40956
+ const resolved = await createAgentResolver({
40957
+ agentService: deps.createAgentService(host)
40958
+ }).resolve(agentRef);
40959
+ if (!resolved.ok) return resolved;
40960
+ const tok = await deps.tokenProvider.getValidAccessToken(host);
40961
+ if (!tok.ok)
40962
+ return err2({ kind: "auth-required", reason: tok.error.kind });
40963
+ return ok2({ host, token: tok.value, agentId: resolved.value.id });
40964
+ };
40965
+ }
40966
+
40044
40967
  // src/modules/chat/infrastructure/terminal-bridge.ts
40045
40968
  var TERMINAL_MODE_RESET = "\x1B[<u\x1B[?1049l\x1B[?1000;1002;1003;1005;1006;1015;1016l\x1B[?1004l\x1B[?2004l\x1B[?25h\x1B[0m";
40046
40969
  function connectTerminalBridge({
@@ -40112,41 +41035,13 @@ function connectTerminalBridge({
40112
41035
 
40113
41036
  // src/modules/chat/services/chat-service.ts
40114
41037
  function createChatService(deps) {
41038
+ const bare = createBootstrap(deps);
40115
41039
  async function bootstrap(agentRef, serverFlag) {
40116
- const flag = serverFlag ? { server: serverFlag } : void 0;
40117
- const config2 = await deps.configService.getResolved({ flag });
40118
- if (!config2.ok) {
40119
- return config2.error.kind === "malformed-config" ? err2({
40120
- kind: "malformed-config",
40121
- reason: config2.error.reason
40122
- }) : err2({ kind: "no-server" });
40123
- }
40124
- const host = config2.value.server;
40125
- const compat = await deps.compatService.check({ flag });
40126
- if (!compat.ok)
40127
- return err2({
40128
- kind: "transport",
40129
- reason: compat.error.kind === "probe-error" ? compat.error.message : compat.error.kind
40130
- });
40131
- if (compat.value.kind === "below-floor") {
40132
- return err2({
40133
- kind: "below-floor",
40134
- localCli: compat.value.localCli,
40135
- serverMinClient: compat.value.serverMinClient
40136
- });
40137
- }
40138
- const resolved = await createAgentResolver({
40139
- agentService: deps.createAgentService(host)
40140
- }).resolve(agentRef);
40141
- if (!resolved.ok) return resolved;
40142
- const tok = await deps.tokenProvider.getValidAccessToken(host);
40143
- if (!tok.ok)
40144
- return err2({ kind: "auth-required", reason: tok.error.kind });
41040
+ const ctx = await bare(agentRef, serverFlag);
41041
+ if (!ctx.ok) return ctx;
40145
41042
  return ok2({
40146
- host,
40147
- token: tok.value,
40148
- agentId: resolved.value.id,
40149
- sessions: deps.createSessionsPort(host, tok.value)
41043
+ ...ctx.value,
41044
+ sessions: deps.createSessionsPort(ctx.value.host, ctx.value.token)
40150
41045
  });
40151
41046
  }
40152
41047
  return {
@@ -40208,7 +41103,7 @@ function createChatService(deps) {
40208
41103
  }
40209
41104
 
40210
41105
  // src/modules/chat/services/sessions-service.ts
40211
- import { randomUUID } from "crypto";
41106
+ import { randomUUID as randomUUID2 } from "crypto";
40212
41107
  function transportError(e2) {
40213
41108
  return {
40214
41109
  kind: "transport",
@@ -40232,7 +41127,7 @@ function createSessionsPort(deps) {
40232
41127
  terminalPath: terminalPath(sid)
40233
41128
  });
40234
41129
  try {
40235
- if (strategy.kind === "new") return ok2(ready(randomUUID()));
41130
+ if (strategy.kind === "new") return ok2(ready(randomUUID2()));
40236
41131
  const regular = (await deps.acp.list(agentId)).filter(
40237
41132
  (s) => s.type === SessionType.Regular
40238
41133
  );
@@ -40305,6 +41200,21 @@ function composeChatModule({
40305
41200
  }),
40306
41201
  isTty: Boolean(process.stdin.isTTY)
40307
41202
  });
41203
+ const runService = createRunService({
41204
+ bootstrap: createBootstrap({
41205
+ compatService,
41206
+ configService,
41207
+ tokenProvider,
41208
+ createAgentService: createAgentService2
41209
+ }),
41210
+ out: trackStdout,
41211
+ errOut: (line) => process.stderr.write(`${line}
41212
+ `),
41213
+ onInterrupt: (handler) => {
41214
+ process.once("SIGINT", handler);
41215
+ return () => process.removeListener("SIGINT", handler);
41216
+ }
41217
+ });
40308
41218
  const sessionParent = new Command("session").description(
40309
41219
  "Manage sessions for an Agent"
40310
41220
  );
@@ -40312,7 +41222,11 @@ function composeChatModule({
40312
41222
  isDefault: true
40313
41223
  });
40314
41224
  return {
40315
- commands: [buildChatCommand({ chatService }), sessionParent]
41225
+ commands: [
41226
+ buildChatCommand({ chatService }),
41227
+ buildRunCommand({ runService }),
41228
+ sessionParent
41229
+ ]
40316
41230
  };
40317
41231
  }
40318
41232
 
@@ -40571,7 +41485,7 @@ function createProcessEnvReader() {
40571
41485
 
40572
41486
  // src/modules/cli/infrastructure/package-version.ts
40573
41487
  function readPackageVersion() {
40574
- return true ? "0.2.16" : DEV_VERSION;
41488
+ return true ? "0.2.17" : DEV_VERSION;
40575
41489
  }
40576
41490
 
40577
41491
  // src/modules/cli/infrastructure/version-probe.ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dam-agents/cli",
3
3
  "author": "IBM Corp.",
4
- "version": "0.2.16",
4
+ "version": "0.2.17",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
7
  "homepage": "https://github.com/dam-agents/dam/tree/main/packages/cli#readme",
@@ -32,7 +32,10 @@
32
32
  "@types/node": "^24.0.0",
33
33
  "@types/tar-stream": "^3.1.4",
34
34
  "@types/ws": "^8.18.1",
35
+ "agent-runtime-api": "0.0.1",
36
+ "api-server-api": "0.0.1",
35
37
  "commander": "^14.0.3",
38
+ "dev-config": "0.0.1",
36
39
  "http-proxy-agent": "^7.0.2",
37
40
  "https-proxy-agent": "^7.0.6",
38
41
  "open": "^11.0.0",
@@ -42,9 +45,6 @@
42
45
  "typescript": "^6.0.2",
43
46
  "vitest": "^4.1.3",
44
47
  "ws": "^8.20.0",
45
- "zod": "^4.4.3",
46
- "agent-runtime-api": "0.0.1",
47
- "api-server-api": "0.0.1",
48
- "dev-config": "0.0.1"
48
+ "zod": "^4.4.3"
49
49
  }
50
50
  }