@todoforai/cli 0.1.10 → 0.1.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.
Files changed (2) hide show
  1. package/dist/todoai.js +1558 -508
  2. package/package.json +1 -1
package/dist/todoai.js CHANGED
@@ -2024,11 +2024,11 @@ var require_core = __commonJS((exports, module) => {
2024
2024
  cmode.illegalRe = langRe(mode.illegal);
2025
2025
  if (!mode.contains)
2026
2026
  mode.contains = [];
2027
- mode.contains = [].concat(...mode.contains.map(function(c) {
2028
- return expandOrCloneMode(c === "self" ? mode : c);
2027
+ mode.contains = [].concat(...mode.contains.map(function(c2) {
2028
+ return expandOrCloneMode(c2 === "self" ? mode : c2);
2029
2029
  }));
2030
- mode.contains.forEach(function(c) {
2031
- compileMode(c, cmode);
2030
+ mode.contains.forEach(function(c2) {
2031
+ compileMode(c2, cmode);
2032
2032
  });
2033
2033
  if (mode.starts) {
2034
2034
  compileMode(mode.starts, parent);
@@ -2685,8 +2685,8 @@ https://github.com/highlightjs/highlight.js/issues/2277`);
2685
2685
  return;
2686
2686
  initHighlighting.called = true;
2687
2687
  deprecated("10.6.0", "initHighlighting() is deprecated. Use highlightAll() instead.");
2688
- const blocks = document.querySelectorAll("pre code");
2689
- blocks.forEach(highlightElement);
2688
+ const blocks3 = document.querySelectorAll("pre code");
2689
+ blocks3.forEach(highlightElement);
2690
2690
  };
2691
2691
  function initHighlightingOnLoad() {
2692
2692
  deprecated("10.6.0", "initHighlightingOnLoad() is deprecated. Use highlightAll() instead.");
@@ -2698,8 +2698,8 @@ https://github.com/highlightjs/highlight.js/issues/2277`);
2698
2698
  wantsHighlight = true;
2699
2699
  return;
2700
2700
  }
2701
- const blocks = document.querySelectorAll("pre code");
2702
- blocks.forEach(highlightElement);
2701
+ const blocks3 = document.querySelectorAll("pre code");
2702
+ blocks3.forEach(highlightElement);
2703
2703
  }
2704
2704
  function boot() {
2705
2705
  if (wantsHighlight)
@@ -6049,7 +6049,7 @@ var require_c = __commonJS((exports, module) => {
6049
6049
  const joined = args.map((x) => source(x)).join("");
6050
6050
  return joined;
6051
6051
  }
6052
- function c(hljs) {
6052
+ function c2(hljs) {
6053
6053
  const C_LINE_COMMENT_MODE = hljs.COMMENT("//", "$", {
6054
6054
  contains: [
6055
6055
  {
@@ -6266,7 +6266,7 @@ var require_c = __commonJS((exports, module) => {
6266
6266
  }
6267
6267
  };
6268
6268
  }
6269
- module.exports = c;
6269
+ module.exports = c2;
6270
6270
  });
6271
6271
 
6272
6272
  // node_modules/highlight.js/lib/languages/cal.js
@@ -15883,10 +15883,10 @@ var require_less = __commonJS((exports, module) => {
15883
15883
  const INTERP_IDENT_RE = "(" + IDENT_RE + "|@\\{" + IDENT_RE + "\\})";
15884
15884
  const RULES = [];
15885
15885
  const VALUE_MODES = [];
15886
- const STRING_MODE = function(c) {
15886
+ const STRING_MODE = function(c2) {
15887
15887
  return {
15888
15888
  className: "string",
15889
- begin: "~?" + c + ".*?" + c
15889
+ begin: "~?" + c2 + ".*?" + c2
15890
15890
  };
15891
15891
  };
15892
15892
  const IDENT_MODE = function(name, begin, relevance) {
@@ -41132,10 +41132,10 @@ var require_conversions = __commonJS((exports, module) => {
41132
41132
  if (convert[model].labels.length !== convert[model].channels) {
41133
41133
  throw new Error("channel and label counts mismatch: " + model);
41134
41134
  }
41135
- const { channels, labels } = convert[model];
41135
+ const { channels: channels2, labels } = convert[model];
41136
41136
  delete convert[model].channels;
41137
41137
  delete convert[model].labels;
41138
- Object.defineProperty(convert[model], "channels", { value: channels });
41138
+ Object.defineProperty(convert[model], "channels", { value: channels2 });
41139
41139
  Object.defineProperty(convert[model], "labels", { value: labels });
41140
41140
  }
41141
41141
  convert.rgb.hsl = function(rgb) {
@@ -41181,8 +41181,8 @@ var require_conversions = __commonJS((exports, module) => {
41181
41181
  const b = rgb[2] / 255;
41182
41182
  const v = Math.max(r, g, b);
41183
41183
  const diff = v - Math.min(r, g, b);
41184
- const diffc = function(c) {
41185
- return (v - c) / 6 / diff + 1 / 2;
41184
+ const diffc = function(c2) {
41185
+ return (v - c2) / 6 / diff + 1 / 2;
41186
41186
  };
41187
41187
  if (diff === 0) {
41188
41188
  h = 0;
@@ -41225,10 +41225,10 @@ var require_conversions = __commonJS((exports, module) => {
41225
41225
  const g = rgb[1] / 255;
41226
41226
  const b = rgb[2] / 255;
41227
41227
  const k = Math.min(1 - r, 1 - g, 1 - b);
41228
- const c = (1 - r - k) / (1 - k) || 0;
41228
+ const c2 = (1 - r - k) / (1 - k) || 0;
41229
41229
  const m = (1 - g - k) / (1 - k) || 0;
41230
41230
  const y = (1 - b - k) / (1 - k) || 0;
41231
- return [c * 100, m * 100, y * 100, k * 100];
41231
+ return [c2 * 100, m * 100, y * 100, k * 100];
41232
41232
  };
41233
41233
  function comparativeDistance(x, y) {
41234
41234
  return (x[0] - y[0]) ** 2 + (x[1] - y[1]) ** 2 + (x[2] - y[2]) ** 2;
@@ -41430,11 +41430,11 @@ var require_conversions = __commonJS((exports, module) => {
41430
41430
  return [r * 255, g * 255, b * 255];
41431
41431
  };
41432
41432
  convert.cmyk.rgb = function(cmyk) {
41433
- const c = cmyk[0] / 100;
41433
+ const c2 = cmyk[0] / 100;
41434
41434
  const m = cmyk[1] / 100;
41435
41435
  const y = cmyk[2] / 100;
41436
41436
  const k = cmyk[3] / 100;
41437
- const r = 1 - Math.min(1, c * (1 - k) + k);
41437
+ const r = 1 - Math.min(1, c2 * (1 - k) + k);
41438
41438
  const g = 1 - Math.min(1, m * (1 - k) + k);
41439
41439
  const b = 1 - Math.min(1, y * (1 - k) + k);
41440
41440
  return [r * 255, g * 255, b * 255];
@@ -41503,16 +41503,16 @@ var require_conversions = __commonJS((exports, module) => {
41503
41503
  if (h < 0) {
41504
41504
  h += 360;
41505
41505
  }
41506
- const c = Math.sqrt(a * a + b * b);
41507
- return [l, c, h];
41506
+ const c2 = Math.sqrt(a * a + b * b);
41507
+ return [l, c2, h];
41508
41508
  };
41509
41509
  convert.lch.lab = function(lch) {
41510
41510
  const l = lch[0];
41511
- const c = lch[1];
41511
+ const c2 = lch[1];
41512
41512
  const h = lch[2];
41513
41513
  const hr = h / 360 * 2 * Math.PI;
41514
- const a = c * Math.cos(hr);
41515
- const b = c * Math.sin(hr);
41514
+ const a = c2 * Math.cos(hr);
41515
+ const b = c2 * Math.sin(hr);
41516
41516
  return [l, a, b];
41517
41517
  };
41518
41518
  convert.rgb.ansi16 = function(args, saturation = null) {
@@ -41564,8 +41564,8 @@ var require_conversions = __commonJS((exports, module) => {
41564
41564
  };
41565
41565
  convert.ansi256.rgb = function(args) {
41566
41566
  if (args >= 232) {
41567
- const c = (args - 232) * 10 + 8;
41568
- return [c, c, c];
41567
+ const c2 = (args - 232) * 10 + 8;
41568
+ return [c2, c2, c2];
41569
41569
  }
41570
41570
  args -= 16;
41571
41571
  let rem;
@@ -41626,28 +41626,28 @@ var require_conversions = __commonJS((exports, module) => {
41626
41626
  convert.hsl.hcg = function(hsl) {
41627
41627
  const s = hsl[1] / 100;
41628
41628
  const l = hsl[2] / 100;
41629
- const c = l < 0.5 ? 2 * s * l : 2 * s * (1 - l);
41629
+ const c2 = l < 0.5 ? 2 * s * l : 2 * s * (1 - l);
41630
41630
  let f = 0;
41631
- if (c < 1) {
41632
- f = (l - 0.5 * c) / (1 - c);
41631
+ if (c2 < 1) {
41632
+ f = (l - 0.5 * c2) / (1 - c2);
41633
41633
  }
41634
- return [hsl[0], c * 100, f * 100];
41634
+ return [hsl[0], c2 * 100, f * 100];
41635
41635
  };
41636
41636
  convert.hsv.hcg = function(hsv) {
41637
41637
  const s = hsv[1] / 100;
41638
41638
  const v = hsv[2] / 100;
41639
- const c = s * v;
41639
+ const c2 = s * v;
41640
41640
  let f = 0;
41641
- if (c < 1) {
41642
- f = (v - c) / (1 - c);
41641
+ if (c2 < 1) {
41642
+ f = (v - c2) / (1 - c2);
41643
41643
  }
41644
- return [hsv[0], c * 100, f * 100];
41644
+ return [hsv[0], c2 * 100, f * 100];
41645
41645
  };
41646
41646
  convert.hcg.rgb = function(hcg) {
41647
41647
  const h = hcg[0] / 360;
41648
- const c = hcg[1] / 100;
41648
+ const c2 = hcg[1] / 100;
41649
41649
  const g = hcg[2] / 100;
41650
- if (c === 0) {
41650
+ if (c2 === 0) {
41651
41651
  return [g * 255, g * 255, g * 255];
41652
41652
  }
41653
41653
  const pure = [0, 0, 0];
@@ -41686,51 +41686,51 @@ var require_conversions = __commonJS((exports, module) => {
41686
41686
  pure[1] = 0;
41687
41687
  pure[2] = w;
41688
41688
  }
41689
- mg = (1 - c) * g;
41689
+ mg = (1 - c2) * g;
41690
41690
  return [
41691
- (c * pure[0] + mg) * 255,
41692
- (c * pure[1] + mg) * 255,
41693
- (c * pure[2] + mg) * 255
41691
+ (c2 * pure[0] + mg) * 255,
41692
+ (c2 * pure[1] + mg) * 255,
41693
+ (c2 * pure[2] + mg) * 255
41694
41694
  ];
41695
41695
  };
41696
41696
  convert.hcg.hsv = function(hcg) {
41697
- const c = hcg[1] / 100;
41697
+ const c2 = hcg[1] / 100;
41698
41698
  const g = hcg[2] / 100;
41699
- const v = c + g * (1 - c);
41699
+ const v = c2 + g * (1 - c2);
41700
41700
  let f = 0;
41701
41701
  if (v > 0) {
41702
- f = c / v;
41702
+ f = c2 / v;
41703
41703
  }
41704
41704
  return [hcg[0], f * 100, v * 100];
41705
41705
  };
41706
41706
  convert.hcg.hsl = function(hcg) {
41707
- const c = hcg[1] / 100;
41707
+ const c2 = hcg[1] / 100;
41708
41708
  const g = hcg[2] / 100;
41709
- const l = g * (1 - c) + 0.5 * c;
41709
+ const l = g * (1 - c2) + 0.5 * c2;
41710
41710
  let s = 0;
41711
41711
  if (l > 0 && l < 0.5) {
41712
- s = c / (2 * l);
41712
+ s = c2 / (2 * l);
41713
41713
  } else if (l >= 0.5 && l < 1) {
41714
- s = c / (2 * (1 - l));
41714
+ s = c2 / (2 * (1 - l));
41715
41715
  }
41716
41716
  return [hcg[0], s * 100, l * 100];
41717
41717
  };
41718
41718
  convert.hcg.hwb = function(hcg) {
41719
- const c = hcg[1] / 100;
41719
+ const c2 = hcg[1] / 100;
41720
41720
  const g = hcg[2] / 100;
41721
- const v = c + g * (1 - c);
41722
- return [hcg[0], (v - c) * 100, (1 - v) * 100];
41721
+ const v = c2 + g * (1 - c2);
41722
+ return [hcg[0], (v - c2) * 100, (1 - v) * 100];
41723
41723
  };
41724
41724
  convert.hwb.hcg = function(hwb) {
41725
41725
  const w = hwb[1] / 100;
41726
41726
  const b = hwb[2] / 100;
41727
41727
  const v = 1 - b;
41728
- const c = v - w;
41728
+ const c2 = v - w;
41729
41729
  let g = 0;
41730
- if (c < 1) {
41731
- g = (v - c) / (1 - c);
41730
+ if (c2 < 1) {
41731
+ g = (v - c2) / (1 - c2);
41732
41732
  }
41733
- return [hwb[0], c * 100, g * 100];
41733
+ return [hwb[0], c2 * 100, g * 100];
41734
41734
  };
41735
41735
  convert.apple.rgb = function(apple) {
41736
41736
  return [apple[0] / 65535 * 255, apple[1] / 65535 * 255, apple[2] / 65535 * 255];
@@ -42194,16 +42194,16 @@ var require_templates = __commonJS((exports, module) => {
42194
42194
  ["e", "\x1B"],
42195
42195
  ["a", "\x07"]
42196
42196
  ]);
42197
- function unescape(c) {
42198
- const u = c[0] === "u";
42199
- const bracket = c[1] === "{";
42200
- if (u && !bracket && c.length === 5 || c[0] === "x" && c.length === 3) {
42201
- return String.fromCharCode(parseInt(c.slice(1), 16));
42197
+ function unescape(c2) {
42198
+ const u = c2[0] === "u";
42199
+ const bracket = c2[1] === "{";
42200
+ if (u && !bracket && c2.length === 5 || c2[0] === "x" && c2.length === 3) {
42201
+ return String.fromCharCode(parseInt(c2.slice(1), 16));
42202
42202
  }
42203
42203
  if (u && bracket) {
42204
- return String.fromCodePoint(parseInt(c.slice(2, -1), 16));
42204
+ return String.fromCodePoint(parseInt(c2.slice(2, -1), 16));
42205
42205
  }
42206
- return ESCAPES.get(c) || c;
42206
+ return ESCAPES.get(c2) || c2;
42207
42207
  }
42208
42208
  function parseArguments(name, arguments_) {
42209
42209
  const results = [];
@@ -42798,7 +42798,10 @@ class ApiClient {
42798
42798
  return this.request("GET", `/api/v1/todos/${todoId}`);
42799
42799
  }
42800
42800
  updateTodoStatus(todoId, status) {
42801
- return this.request("PUT", `/api/v1/todos/${todoId}`, { status });
42801
+ return this.request("PATCH", `/api/v1/todos/${todoId}/status`, { status });
42802
+ }
42803
+ deleteTodo(todoId) {
42804
+ return this.request("DELETE", `/api/v1/todos/${todoId}`);
42802
42805
  }
42803
42806
  listAgentSettings(filters) {
42804
42807
  const params = new URLSearchParams;
@@ -43134,7 +43137,802 @@ var package_default = {
43134
43137
  typescript: "^5.7.0"
43135
43138
  }
43136
43139
  };
43140
+ // ../packages/shared-fbe/src/enums.ts
43141
+ var TodoStatus;
43142
+ ((TodoStatus2) => {
43143
+ TodoStatus2["TODO"] = "TODO";
43144
+ TodoStatus2["SCHEDULED"] = "SCHEDULED";
43145
+ TodoStatus2["PAUSED"] = "PAUSED";
43146
+ TodoStatus2["POSTPONED"] = "POSTPONED";
43147
+ TodoStatus2["REVIEW_REQUESTED"] = "REVIEW_REQUESTED";
43148
+ TodoStatus2["RUNNING"] = "RUNNING";
43149
+ TodoStatus2["COMPACTING"] = "COMPACTING";
43150
+ TodoStatus2["STOPPING"] = "STOPPING";
43151
+ TodoStatus2["READY"] = "READY";
43152
+ TodoStatus2["READY_CHECKED"] = "READY_CHECKED";
43153
+ TodoStatus2["DONE"] = "DONE";
43154
+ TodoStatus2["CANCELLED"] = "CANCELLED";
43155
+ TodoStatus2["CANCELLED_CHECKED"] = "CANCELLED_CHECKED";
43156
+ TodoStatus2["ERROR"] = "ERROR";
43157
+ TodoStatus2["ERROR_CHECKED"] = "ERROR_CHECKED";
43158
+ TodoStatus2["ARCHIVED"] = "ARCHIVED";
43159
+ TodoStatus2["DELETED"] = "DELETED";
43160
+ })(TodoStatus ||= {});
43161
+ // ../packages/shared-fbe/src/mimetypes.json
43162
+ var mimetypes_default = {
43163
+ conversionProfiles: {
43164
+ to_jpeg_90: { toMime: "image/jpeg", toExt: "jpg", quality: 0.9 }
43165
+ },
43166
+ types: {
43167
+ image: { icon: "mdi:file-image", color: "yellow", prefixRule: "image/", needsObjectUrl: true },
43168
+ audio: { icon: "mdi:file-music", color: "grey", prefixRule: "audio/", needsObjectUrl: true },
43169
+ video: { icon: "mdi:file-video", color: "yellow", prefixRule: "video/", needsObjectUrl: true },
43170
+ pdf: { icon: "mdi:pdf-box", color: "red", needsObjectUrl: true },
43171
+ document: { icon: "mdi:file-word", color: "lightblue" },
43172
+ spreadsheet: { icon: "mdi:file-excel", color: "green" },
43173
+ text: { icon: "mdi:file", color: "white", prefixRule: "text/" },
43174
+ archive: { icon: "mdi:folder-zip", color: "purple" },
43175
+ unknown: { icon: "mdi:file", color: "grey" },
43176
+ mcp_text: { icon: "mdi:robot", color: "purple" },
43177
+ mcp_image: { icon: "mdi:robot", color: "purple", needsObjectUrl: true },
43178
+ mcp_audio: { icon: "mdi:robot", color: "purple", needsObjectUrl: true },
43179
+ mcp_resource: { icon: "mdi:cloud", color: "purple" }
43180
+ },
43181
+ extensions: {
43182
+ txt: { mime: "text/plain", type: "text" },
43183
+ md: { mime: "text/markdown", type: "text" },
43184
+ json: { mime: "application/json", type: "text" },
43185
+ js: { mime: "text/javascript", type: "text" },
43186
+ ts: { mime: "text/typescript", type: "text" },
43187
+ html: { mime: "text/html", type: "text" },
43188
+ css: { mime: "text/css", type: "text" },
43189
+ xml: { mime: "text/xml", type: "text" },
43190
+ py: { mime: "text/x-python", type: "text" },
43191
+ java: { mime: "text/x-java-source", type: "text" },
43192
+ cpp: { mime: "text/x-c++src", type: "text" },
43193
+ c: { mime: "text/x-csrc", type: "text" },
43194
+ h: { mime: "text/x-chdr", type: "text" },
43195
+ yml: { mime: "text/yaml", type: "text" },
43196
+ yaml: { mime: "text/yaml", type: "text" },
43197
+ csv: { mime: "text/csv", type: "spreadsheet" },
43198
+ png: { mime: "image/png", type: "image" },
43199
+ jpg: { mime: "image/jpeg", type: "image" },
43200
+ jpeg: { mime: "image/jpeg", type: "image" },
43201
+ gif: { mime: "image/gif", type: "image" },
43202
+ webp: { mime: "image/webp", type: "image" },
43203
+ bmp: { mime: "image/bmp", type: "image" },
43204
+ svg: { mime: "image/svg+xml", type: "text" },
43205
+ heic: { mime: "image/heic", type: "image", conversionProfile: "to_jpeg_90" },
43206
+ heif: { mime: "image/heif", type: "image", conversionProfile: "to_jpeg_90" },
43207
+ mp3: { mime: "audio/mpeg", type: "audio" },
43208
+ wav: { mime: "audio/wav", type: "audio" },
43209
+ ogg: { mime: "audio/ogg", type: "audio" },
43210
+ flac: { mime: "audio/flac", type: "audio" },
43211
+ aac: { mime: "audio/aac", type: "audio" },
43212
+ m4a: { mime: "audio/mp4", type: "audio" },
43213
+ wma: { mime: "audio/x-ms-wma", type: "audio" },
43214
+ mp4: { mime: "video/mp4", type: "video" },
43215
+ webm: { mime: "video/webm", type: "video" },
43216
+ avi: { mime: "video/x-msvideo", type: "video" },
43217
+ mkv: { mime: "video/x-matroska", type: "video" },
43218
+ mov: { mime: "video/quicktime", type: "video" },
43219
+ wmv: { mime: "video/x-ms-wmv", type: "video" },
43220
+ flv: { mime: "video/x-flv", type: "video" },
43221
+ pdf: { mime: "application/pdf", type: "pdf" },
43222
+ doc: { mime: "application/msword", type: "document" },
43223
+ docx: { mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", type: "document", tags: ["docx"] },
43224
+ ppt: { mime: "application/vnd.ms-powerpoint", type: "document" },
43225
+ pptx: { mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation", type: "document" },
43226
+ xls: { mime: "application/vnd.ms-excel", type: "spreadsheet" },
43227
+ xlsx: { mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", type: "spreadsheet" },
43228
+ zip: { mime: "application/zip", type: "archive" },
43229
+ rar: { mime: "application/vnd.rar", type: "archive" },
43230
+ tar: { mime: "application/x-tar", type: "archive" },
43231
+ gz: { mime: "application/gzip", type: "archive" },
43232
+ "7z": { mime: "application/x-7z-compressed", type: "archive" }
43233
+ },
43234
+ aliases: {
43235
+ "application/xml": "text",
43236
+ "application/javascript": "text",
43237
+ "application/x-javascript": "text",
43238
+ "application/typescript": "text",
43239
+ "application/x-typescript": "text",
43240
+ "application/yaml": "text",
43241
+ "application/x-yaml": "text",
43242
+ "application/x-python": "text",
43243
+ "application/x-java-source": "text",
43244
+ "application/x-c++src": "text",
43245
+ "application/x-csrc": "text",
43246
+ "application/x-chdr": "text",
43247
+ "application/octet-stream": "unknown",
43248
+ "text/mcp": "mcp_text",
43249
+ "image/mcp": "mcp_image",
43250
+ "audio/mcp": "mcp_audio"
43251
+ }
43252
+ };
43137
43253
 
43254
+ // ../packages/shared-fbe/src/attachmentUtils.ts
43255
+ var MCP_TEXT_MIME = Object.entries(mimetypes_default.aliases).find(([, type]) => type === "mcp_text")[0];
43256
+ var MCP_AUDIO_MIME = Object.entries(mimetypes_default.aliases).find(([, type]) => type === "mcp_audio")[0];
43257
+ var AttachmentType = Object.fromEntries(Object.keys(mimetypes_default.types).map((k) => [k.toUpperCase(), k]));
43258
+ var EXT_TO_MIME = {};
43259
+ var MIME_TO_TYPE = {};
43260
+ var PREFIX_RULES = [];
43261
+ for (const [ext, entry] of Object.entries(mimetypes_default.extensions)) {
43262
+ const { mime, type } = entry;
43263
+ EXT_TO_MIME[ext] = mime;
43264
+ MIME_TO_TYPE[mime] = type;
43265
+ }
43266
+ for (const [mime, type] of Object.entries(mimetypes_default.aliases)) {
43267
+ MIME_TO_TYPE[mime] = type;
43268
+ }
43269
+ for (const [type, meta] of Object.entries(mimetypes_default.types)) {
43270
+ const { prefixRule } = meta;
43271
+ if (prefixRule)
43272
+ PREFIX_RULES.push([prefixRule, type]);
43273
+ }
43274
+ var TAG_TO_MIMES = {};
43275
+ for (const [, entry] of Object.entries(mimetypes_default.extensions)) {
43276
+ const { mime, tags } = entry;
43277
+ if (tags) {
43278
+ for (const tag of tags) {
43279
+ (TAG_TO_MIMES[tag] ??= new Set).add(mime);
43280
+ }
43281
+ }
43282
+ }
43283
+ var NEEDS_OBJECT_URL = new Set(Object.entries(mimetypes_default.types).filter(([, meta]) => meta.needsObjectUrl).map(([type]) => type));
43284
+ var MIME_TO_EXT = {};
43285
+ for (const [ext, entry] of Object.entries(mimetypes_default.extensions)) {
43286
+ const { mime } = entry;
43287
+ if (!MIME_TO_EXT[mime])
43288
+ MIME_TO_EXT[mime] = ext;
43289
+ }
43290
+ // ../packages/shared-fbe/src/blocks/index.ts
43291
+ var USER_INPUT_BLOCK_TYPES = new Set([
43292
+ "question" /* Question */,
43293
+ "login_prompt" /* Login */,
43294
+ "business_onboarding" /* BusinessOnboarding */
43295
+ ]);
43296
+ var EDGE_TOOL_TYPES = new Set([
43297
+ "read" /* Read */,
43298
+ "create" /* Create */,
43299
+ "write" /* Write */,
43300
+ "edit" /* Edit */,
43301
+ "modify_file" /* ModifyFile */,
43302
+ "bash" /* Bash */,
43303
+ "search" /* Search */,
43304
+ "grep" /* Grep */,
43305
+ "list" /* List */
43306
+ ]);
43307
+ var BROWSER_TOOL_TYPES = new Set([
43308
+ "browser_interactable" /* BrowserInteractable */,
43309
+ "browser_dom_tree" /* BrowserDomTree */,
43310
+ "browser_navigate" /* BrowserNavigate */,
43311
+ "browser_screenshot" /* BrowserScreenshot */,
43312
+ "browser_click" /* BrowserClick */,
43313
+ "browser_type" /* BrowserType */,
43314
+ "browser_fill" /* BrowserFill */,
43315
+ "browser_scroll" /* BrowserScroll */,
43316
+ "browser_mouse_move" /* BrowserMouseMove */,
43317
+ "browser_key" /* BrowserKey */,
43318
+ "browser_evaluate" /* BrowserEvaluate */,
43319
+ "browser_select" /* BrowserSelect */,
43320
+ "browser_hover" /* BrowserHover */,
43321
+ "browser_text_content" /* BrowserTextContent */,
43322
+ "browser_back" /* BrowserBack */,
43323
+ "browser_forward" /* BrowserForward */,
43324
+ "browser_reload" /* BrowserReload */,
43325
+ "browser_upload_file" /* BrowserUploadFile */,
43326
+ "browser_find_text" /* BrowserFindText */,
43327
+ "browser_find_role" /* BrowserFindRole */,
43328
+ "browser_find_label" /* BrowserFindLabel */,
43329
+ "browser_find_placeholder" /* BrowserFindPlaceholder */,
43330
+ "browser_wait" /* BrowserWait */,
43331
+ "browser_drag" /* BrowserDrag */,
43332
+ "browser_dialog" /* BrowserDialog */,
43333
+ "browser_network_wait" /* BrowserNetworkWait */,
43334
+ "browser_check" /* BrowserCheck */,
43335
+ "browser_uncheck" /* BrowserUncheck */,
43336
+ "browser_focus" /* BrowserFocus */,
43337
+ "browser_find_test_id" /* BrowserFindTestId */,
43338
+ "browser_cookies" /* BrowserCookies */,
43339
+ "browser_storage" /* BrowserStorage */,
43340
+ "browser_pdf" /* BrowserPdf */,
43341
+ "browser_clipboard_read" /* BrowserClipboardRead */,
43342
+ "browser_clipboard_write" /* BrowserClipboardWrite */,
43343
+ "browser_snapshot" /* BrowserSnapshot */,
43344
+ "browser_iframe" /* BrowserIframe */,
43345
+ "browser_console" /* BrowserConsole */,
43346
+ "browser_scroll_into_view" /* BrowserScrollIntoView */,
43347
+ "browser_network_requests" /* BrowserNetworkRequests */,
43348
+ "browser_tap" /* BrowserTap */,
43349
+ "browser_swipe" /* BrowserSwipe */
43350
+ ]);
43351
+ var API_TOOL_TYPES = new Set([
43352
+ "api_get_current_context" /* ApiGetCurrentContext */,
43353
+ "api_get_todo" /* ApiGetTodo */,
43354
+ "api_add_todo_message" /* ApiAddTodoMessage */,
43355
+ "api_update_todo_status" /* ApiUpdateTodoStatus */,
43356
+ "api_delete_todo" /* ApiDeleteTodo */,
43357
+ "api_list_projects" /* ApiListProjects */,
43358
+ "api_get_project" /* ApiGetProject */,
43359
+ "api_create_project" /* ApiCreateProject */,
43360
+ "api_list_project_todos" /* ApiListProjectTodos */,
43361
+ "api_create_todo" /* ApiCreateTodo */,
43362
+ "api_list_agents" /* ApiListAgents */,
43363
+ "api_get_agent" /* ApiGetAgent */,
43364
+ "api_update_agent" /* ApiUpdateAgent */,
43365
+ "api_list_business_contexts" /* ApiListBusinessContexts */,
43366
+ "api_get_business_context" /* ApiGetBusinessContext */,
43367
+ "api_get_context_item" /* ApiGetContextItem */,
43368
+ "api_create_context_item" /* ApiCreateContextItem */,
43369
+ "api_update_context_item" /* ApiUpdateContextItem */,
43370
+ "api_delete_context_item" /* ApiDeleteContextItem */,
43371
+ "api_list_edges" /* ApiListEdges */,
43372
+ "api_get_edge" /* ApiGetEdge */,
43373
+ "api_list_mcps" /* ApiListMcps */,
43374
+ "api_get_usage" /* ApiGetUsage */,
43375
+ "api_get_balance" /* ApiGetBalance */,
43376
+ "api_get_api_schema" /* ApiGetApiSchema */
43377
+ ]);
43378
+ var FILE_TOOL_TYPES = new Set([
43379
+ "read" /* Read */,
43380
+ "create" /* Create */,
43381
+ "write" /* Write */,
43382
+ "edit" /* Edit */,
43383
+ "modify_file" /* ModifyFile */
43384
+ ]);
43385
+ // ../packages/shared-fbe/src/channels.ts
43386
+ var SERVER_TO_FRONTENDS = {
43387
+ task: {
43388
+ actionUpdate: (userId) => `${"task_action:update" /* TASK_ACTION_UPDATE */}:${userId}`
43389
+ },
43390
+ businessContext: {
43391
+ updated: (userId) => `${"business_context:updated" /* BUSINESS_CONTEXT_UPDATED */}:${userId}`
43392
+ },
43393
+ resource: {
43394
+ contentUpdated: (userId) => `${"resource:content_updated" /* RESOURCE_CONTENT_UPDATED */}:${userId}`
43395
+ },
43396
+ hexGrid: {
43397
+ updated: (projectId) => `${"hexgrid:updated" /* HEXGRID_UPDATED */}:${projectId}`
43398
+ },
43399
+ sandbox: {
43400
+ state: (userId) => `${"sandbox:state" /* SANDBOX_STATE */}:${userId}`
43401
+ },
43402
+ device: {
43403
+ status: (userId) => `${"device:status" /* DEVICE_STATUS */}:${userId}`
43404
+ },
43405
+ agent: {
43406
+ status: (userId) => `${"agent:status" /* AGENT_STATUS */}:${userId}`,
43407
+ mcpList: () => `${"agent:mcp_list" /* AGENT_MCP_LIST */}:ALL`
43408
+ },
43409
+ edge: {
43410
+ status: (userId) => `${"edge:status" /* EDGE_STATUS */}:${userId}`,
43411
+ configUpdate: (userId) => `${"EDGE_CONFIG_UPDATE" /* EDGE_CONFIG_UPDATE */}:${userId}`,
43412
+ cdResult: (edgeId) => `${"edge:cd_response" /* EDGE_CD_RESPONSE */}:${edgeId}`,
43413
+ getFoldersResult: (edgeId) => `${"edge:get_folders_response" /* EDGE_GET_FOLDERS_RESPONSE */}:${edgeId}`,
43414
+ createFolderResult: (edgeId) => `${"edge:create_folder_response" /* EDGE_CREATE_FOLDER_RESPONSE */}:${edgeId}`,
43415
+ deletePathResult: (edgeId) => `${"edge:delete_path_response" /* EDGE_DELETE_PATH_RESPONSE */}:${edgeId}`,
43416
+ writeFileResult: (edgeId) => `${"edge:write_file_response" /* EDGE_WRITE_FILE_RESPONSE */}:${edgeId}`
43417
+ },
43418
+ project: {
43419
+ new_message: (projectId) => `${"task:new_update" /* TASK_NEW */}:${projectId}`,
43420
+ new_todo: (projectId) => `${"todo:new" /* NEW_TODO */}:${projectId}`,
43421
+ status: (projectId) => `${"project:status" /* PROJECT_STATUS */}:${projectId}`
43422
+ },
43423
+ todo: {
43424
+ msgStart: (todoId) => `${"todo:msg_start" /* TODO_MSG_START */}:${todoId}`,
43425
+ msgDone: (todoId) => `${"todo:msg_done" /* TODO_MSG_DONE */}:${todoId}`,
43426
+ msgStopSequence: (todoId) => `${"todo:msg_stop_sequence" /* TODO_MSG_STOP_SEQUENCE */}:${todoId}`,
43427
+ msgMetaUsr: (todoId) => `${"todo:msg_meta_usr" /* TODO_MSG_META_USR */}:${todoId}`,
43428
+ msgMetaAi: (todoId) => `${"todo:msg_meta_ai" /* TODO_MSG_META_AI */}:${todoId}`,
43429
+ start_universal: (todoId) => `${"block:start_universal" /* BLOCK_START_UNIVERSAL */}:${todoId}`,
43430
+ message: (todoId) => `${"block:message" /* BLOCK_MESSAGE */}:${todoId}`,
43431
+ end: (todoId) => `${"block:end" /* BLOCK_END */}:${todoId}`,
43432
+ new_message: (todoId) => `${"todo:new_message" /* TODO_NEW_MESSAGE */}:${todoId}`,
43433
+ sh_msg_result: (todoId) => `${"block:sh_msg_result" /* BLOCK_SH_MSG_RESULT */}:${todoId}`,
43434
+ sh_msg_start_result: (todoId) => `${"block:sh_msg_start" /* BLOCK_SH_MSG_START */}:${todoId}`,
43435
+ sh_msg_done_result: (todoId) => `${"block:sh_done" /* BLOCK_SH_DONE */}:${todoId}`,
43436
+ save_result: (todoId) => `${"block:save_result" /* BLOCK_SAVE_RESULT */}:${todoId}`,
43437
+ diff_result: (todoId) => `${"block:diff_result" /* BLOCK_DIFF_RESULT */}:${todoId}`,
43438
+ frontend_file_chunk_result: (todoId) => `${"frontend:file_chunk_result" /* FRONTEND_FILE_CHUNK_RESULT */}:${todoId}`,
43439
+ status: (todoId) => `todo:${todoId}:status`,
43440
+ block_update: (todoId) => `todo:${todoId}:block_update`,
43441
+ error_result: (todoId) => `${"block:error_result" /* BLOCK_ERROR_RESULT */}:${todoId}`,
43442
+ meta_result: (todoId) => `${"block:meta_result" /* BLOCK_META_RESULT */}:${todoId}`,
43443
+ file_changed: (edgeId, path3) => `${"block:file_changed" /* BLOCK_FILE_CHANGED */}:${edgeId}:${path3}`,
43444
+ notify: (todoId) => `${"NOTIFY" /* NOTIFY */}:${todoId}`
43445
+ },
43446
+ notify: {
43447
+ user: (userId) => `${"NOTIFY" /* NOTIFY */}:user:${userId}`
43448
+ },
43449
+ payment: {
43450
+ status: (userId) => `${"payment:status" /* PAYMENT_STATUS */}:${userId}`
43451
+ },
43452
+ functions: {}
43453
+ };
43454
+ // ../packages/shared-fbe/src/bashPatterns.ts
43455
+ function splitShellCommands(input) {
43456
+ const parts = [];
43457
+ let current = "";
43458
+ let i = 0;
43459
+ const len = input.length;
43460
+ while (i < len) {
43461
+ const ch = input[i];
43462
+ if (ch === "\\" && i + 1 < len && input[i + 1] === `
43463
+ `) {
43464
+ current += " ";
43465
+ i += 2;
43466
+ continue;
43467
+ }
43468
+ if (ch === "\\" && i + 1 < len) {
43469
+ current += ch + input[i + 1];
43470
+ i += 2;
43471
+ continue;
43472
+ }
43473
+ if (ch === "<" && i + 1 < len && input[i + 1] === "<") {
43474
+ i += 2;
43475
+ if (i < len && input[i] === "-")
43476
+ i++;
43477
+ while (i < len && (input[i] === " " || input[i] === "\t"))
43478
+ i++;
43479
+ let delim = "";
43480
+ if (i < len && (input[i] === "'" || input[i] === '"')) {
43481
+ const q = input[i];
43482
+ i++;
43483
+ while (i < len && input[i] !== q) {
43484
+ delim += input[i];
43485
+ i++;
43486
+ }
43487
+ if (i < len)
43488
+ i++;
43489
+ } else {
43490
+ while (i < len && /\w/.test(input[i])) {
43491
+ delim += input[i];
43492
+ i++;
43493
+ }
43494
+ }
43495
+ if (delim) {
43496
+ const rest = input.slice(i);
43497
+ const m = rest.match(new RegExp(`^${delim}$`, "m"));
43498
+ if (m && m.index !== undefined) {
43499
+ i += m.index + delim.length;
43500
+ } else {
43501
+ i = len;
43502
+ }
43503
+ }
43504
+ continue;
43505
+ }
43506
+ if (ch === "#" && (current.length === 0 || /\s$/.test(current))) {
43507
+ while (i < len && input[i] !== `
43508
+ `)
43509
+ i++;
43510
+ continue;
43511
+ }
43512
+ if (ch === '"' || ch === "'") {
43513
+ const quote = ch;
43514
+ current += ch;
43515
+ i++;
43516
+ while (i < len && input[i] !== quote) {
43517
+ if (input[i] === "\\" && quote === '"' && i + 1 < len) {
43518
+ current += input[i] + input[i + 1];
43519
+ i += 2;
43520
+ } else {
43521
+ current += input[i];
43522
+ i++;
43523
+ }
43524
+ }
43525
+ if (i < len)
43526
+ current += input[i];
43527
+ i++;
43528
+ continue;
43529
+ }
43530
+ if (ch === "|" && i + 1 < len && input[i + 1] === "|") {
43531
+ parts.push(current);
43532
+ current = "";
43533
+ i += 2;
43534
+ } else if (ch === "&" && i + 1 < len && input[i + 1] === "&") {
43535
+ parts.push(current);
43536
+ current = "";
43537
+ i += 2;
43538
+ } else if (ch === "|") {
43539
+ parts.push(current);
43540
+ current = "";
43541
+ i++;
43542
+ } else if (ch === ";" || ch === `
43543
+ `) {
43544
+ parts.push(current);
43545
+ current = "";
43546
+ i++;
43547
+ } else {
43548
+ current += ch;
43549
+ i++;
43550
+ }
43551
+ }
43552
+ parts.push(current);
43553
+ return parts.map((s) => s.trim()).filter(Boolean);
43554
+ }
43555
+ function generalizeToken(token) {
43556
+ if (/^\d+$/.test(token))
43557
+ return "*";
43558
+ if (/^[0-9a-f]{4,}$/i.test(token) && /\d/.test(token))
43559
+ return "*";
43560
+ if (/^[0-9a-f]{8}-[0-9a-f]{4}-/i.test(token))
43561
+ return "*";
43562
+ if (/^https?:\/\//i.test(token)) {
43563
+ try {
43564
+ const u = new URL(token);
43565
+ return `${u.protocol}//${u.host}/*`;
43566
+ } catch {
43567
+ return token;
43568
+ }
43569
+ }
43570
+ return token;
43571
+ }
43572
+ var SAFE_FLAGS = new Set(["--help", "-h", "--version", "-V", "-v"]);
43573
+ function splitTokens(cmd) {
43574
+ const tokens = [];
43575
+ let current = "";
43576
+ let i = 0;
43577
+ const len = cmd.length;
43578
+ while (i < len) {
43579
+ const ch = cmd[i];
43580
+ if (ch === "\\" && i + 1 < len && cmd[i + 1] === `
43581
+ `) {
43582
+ i += 2;
43583
+ continue;
43584
+ }
43585
+ if (ch === "\\" && i + 1 < len) {
43586
+ current += ch + cmd[i + 1];
43587
+ i += 2;
43588
+ continue;
43589
+ }
43590
+ if (ch === '"' || ch === "'") {
43591
+ const q = ch;
43592
+ current += ch;
43593
+ i++;
43594
+ while (i < len && cmd[i] !== q) {
43595
+ if (cmd[i] === "\\" && q === '"' && i + 1 < len) {
43596
+ current += cmd[i] + cmd[i + 1];
43597
+ i += 2;
43598
+ } else {
43599
+ current += cmd[i];
43600
+ i++;
43601
+ }
43602
+ }
43603
+ if (i < len) {
43604
+ current += cmd[i];
43605
+ i++;
43606
+ }
43607
+ continue;
43608
+ }
43609
+ if (/\s/.test(ch)) {
43610
+ if (current) {
43611
+ tokens.push(current);
43612
+ current = "";
43613
+ }
43614
+ i++;
43615
+ continue;
43616
+ }
43617
+ current += ch;
43618
+ i++;
43619
+ }
43620
+ if (current)
43621
+ tokens.push(current);
43622
+ return tokens;
43623
+ }
43624
+ function parseSingle(cmd) {
43625
+ const tokens = splitTokens(cmd);
43626
+ while (tokens.length && /^[A-Za-z_]\w*=/.test(tokens[0])) {
43627
+ const val = tokens[0].slice(tokens[0].indexOf("=") + 1);
43628
+ if (/\$\(|`/.test(val))
43629
+ return { tokens: [], defaultKeep: 0 };
43630
+ tokens.shift();
43631
+ }
43632
+ if (tokens.length === 0)
43633
+ return { tokens: [], defaultKeep: 0 };
43634
+ if (tokens[0].startsWith("#"))
43635
+ return { tokens: [], defaultKeep: 0 };
43636
+ const positionals = [tokens[0]];
43637
+ let hitFlag = false;
43638
+ let defaultKeep = -1;
43639
+ for (let t = 1;t < tokens.length; t++) {
43640
+ if (!hitFlag && SAFE_FLAGS.has(tokens[t])) {
43641
+ positionals.push(tokens[t]);
43642
+ return { tokens: positionals, defaultKeep: positionals.length };
43643
+ }
43644
+ if (tokens[t].startsWith("-")) {
43645
+ if (!hitFlag) {
43646
+ hitFlag = true;
43647
+ defaultKeep = Math.min(3, positionals.length);
43648
+ }
43649
+ positionals.push(tokens[t]);
43650
+ continue;
43651
+ }
43652
+ const g = generalizeToken(tokens[t]);
43653
+ positionals.push(g);
43654
+ if (g !== tokens[t])
43655
+ break;
43656
+ }
43657
+ if (defaultKeep < 0)
43658
+ defaultKeep = Math.min(3, positionals.length);
43659
+ return { tokens: positionals, defaultKeep };
43660
+ }
43661
+ function buildBashPattern(parsed, keep) {
43662
+ if (parsed.tokens.length === 0)
43663
+ return "BASH(cmd: *)";
43664
+ const k = Math.max(1, Math.min(keep ?? parsed.defaultKeep, parsed.tokens.length));
43665
+ const kept = parsed.tokens.slice(0, k);
43666
+ const suffix = kept[kept.length - 1] === "*" ? "" : " *";
43667
+ return `BASH(cmd: ${kept.join(" ")}${suffix})`;
43668
+ }
43669
+ function parseBashCmd(fullCmd) {
43670
+ return splitShellCommands(fullCmd).map(parseSingle).filter((p) => p.tokens.length > 0);
43671
+ }
43672
+ function generalizeBashCmd(fullCmd) {
43673
+ return parseBashCmd(fullCmd).map((p) => buildBashPattern(p));
43674
+ }
43675
+ function getBlockServerPrefix(block) {
43676
+ const agentPattern = typeof block.generalized_pattern === "string" ? block.generalized_pattern : "";
43677
+ const prefixMatch = agentPattern.match(/^(.*?:)BASH(?:\(|$)/);
43678
+ return prefixMatch ? prefixMatch[1] : "";
43679
+ }
43680
+ var BASH_LIKE_BLOCK_TYPES = new Set(["bash", "machine_exec"]);
43681
+ function getBlockPatterns(block) {
43682
+ if (Array.isArray(block.generalized_pattern))
43683
+ return block.generalized_pattern;
43684
+ const agentPattern = typeof block.generalized_pattern === "string" ? block.generalized_pattern : "";
43685
+ const isBashLike = BASH_LIKE_BLOCK_TYPES.has(block.type.toLowerCase()) || /:BASH(\(|$)/.test(agentPattern);
43686
+ if (isBashLike && block.cmd) {
43687
+ const prefix = getBlockServerPrefix(block);
43688
+ return generalizeBashCmd(block.cmd).map((p) => prefix + p);
43689
+ }
43690
+ if (block.generalized_pattern)
43691
+ return [block.generalized_pattern];
43692
+ return [`${block.type}(*)`];
43693
+ }
43694
+ function getBlockServerId(block) {
43695
+ const prefix = getBlockServerPrefix(block);
43696
+ return prefix ? prefix.slice(0, -1) : "*";
43697
+ }
43698
+
43699
+ // ../packages/shared-fbe/src/permissionUtils.ts
43700
+ function parsePattern(pattern) {
43701
+ const colonIndex = pattern.indexOf(":");
43702
+ if (colonIndex === -1)
43703
+ return null;
43704
+ const serverId = pattern.slice(0, colonIndex);
43705
+ if (!/^[A-Za-z0-9_*-]+$/.test(serverId)) {
43706
+ return { serverId: "*", toolName: pattern };
43707
+ }
43708
+ return { serverId, toolName: pattern.slice(colonIndex + 1) };
43709
+ }
43710
+ var SCOPE_BUILTIN = "builtin";
43711
+ var SCOPE_DEVICE = "device";
43712
+ var SCOPE_CLOUD = "cloud";
43713
+ var isDeviceId = (s) => s !== "*" && s !== SCOPE_BUILTIN && s !== SCOPE_DEVICE && s !== SCOPE_CLOUD && !s.includes("*");
43714
+ function serverIdMatches(ruleServerId, targetServerId, ctx) {
43715
+ if (ruleServerId === targetServerId)
43716
+ return true;
43717
+ if (ruleServerId === "*")
43718
+ return true;
43719
+ if (ruleServerId === SCOPE_DEVICE)
43720
+ return isDeviceId(targetServerId);
43721
+ if (ruleServerId === SCOPE_CLOUD)
43722
+ return !!ctx?.primaryCloudId && targetServerId === ctx.primaryCloudId;
43723
+ if (ruleServerId.includes("*")) {
43724
+ const escaped = ruleServerId.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
43725
+ const regex = new RegExp("^" + escaped.replace(/\*/g, "[^:]*") + "$");
43726
+ return regex.test(targetServerId);
43727
+ }
43728
+ if (targetServerId.startsWith(ruleServerId + "_"))
43729
+ return true;
43730
+ return false;
43731
+ }
43732
+ function patternMatches(rulePattern, targetPattern, ctx) {
43733
+ const rule = parsePattern(rulePattern);
43734
+ const target = parsePattern(targetPattern);
43735
+ if (!rule || !target)
43736
+ return rulePattern === targetPattern;
43737
+ if (!serverIdMatches(rule.serverId, target.serverId, ctx))
43738
+ return false;
43739
+ if (rule.toolName === target.toolName)
43740
+ return true;
43741
+ if (rule.toolName === "*")
43742
+ return true;
43743
+ if (rule.toolName.endsWith(" *)")) {
43744
+ const rulePrefix = rule.toolName.slice(0, -2);
43745
+ return target.toolName.startsWith(rulePrefix);
43746
+ }
43747
+ return false;
43748
+ }
43749
+ function bashRuleMatchesCmd(rulePattern, serverId, cmd) {
43750
+ const rule = parsePattern(rulePattern);
43751
+ if (!rule)
43752
+ return false;
43753
+ if (!serverIdMatches(rule.serverId, serverId))
43754
+ return false;
43755
+ if (rule.toolName === "*" || rule.toolName === "BASH")
43756
+ return true;
43757
+ const m = rule.toolName.match(/^BASH\(cmd:\s*(.*)\)$/);
43758
+ if (!m)
43759
+ return false;
43760
+ let body = m[1];
43761
+ const isPrefix = body.endsWith(" *") || body.endsWith("*");
43762
+ if (isPrefix)
43763
+ body = body.replace(/\s*\*$/, "");
43764
+ const subs = splitShellCommands(cmd);
43765
+ if (subs.length === 0)
43766
+ return false;
43767
+ return subs.every((sub) => isPrefix ? sub === body || sub.startsWith(body + " ") : sub === body);
43768
+ }
43769
+ function isPatternInList(list, pattern) {
43770
+ if (!list)
43771
+ return false;
43772
+ return list.some((p) => patternMatches(p, pattern));
43773
+ }
43774
+ function isPatternAllowed(permissions, pattern) {
43775
+ return isPatternInList(permissions?.allow, pattern);
43776
+ }
43777
+ function getNewPatterns(patterns, permissions) {
43778
+ return patterns.filter((p) => !isPatternAllowed(permissions, p));
43779
+ }
43780
+ function getBlockNewPatterns(block, permissions) {
43781
+ const allow = permissions?.allow ?? [];
43782
+ if (Array.isArray(block.generalized_pattern)) {
43783
+ return getNewPatterns(block.generalized_pattern, permissions);
43784
+ }
43785
+ const agentPattern = typeof block.generalized_pattern === "string" ? block.generalized_pattern : "";
43786
+ const isBash = (block.type.toLowerCase() === "bash" || agentPattern.includes(":BASH(")) && !!block.cmd;
43787
+ if (!isBash) {
43788
+ return getBlockPatterns(block).filter((p) => !isPatternAllowed(permissions, p));
43789
+ }
43790
+ const serverId = getBlockServerId(block);
43791
+ const prefix = serverId === "*" ? "" : `${serverId}:`;
43792
+ const rawSubs = splitShellCommands(block.cmd);
43793
+ const pairs = [];
43794
+ for (const raw of rawSubs) {
43795
+ const parsed = parseBashCmd(raw);
43796
+ if (parsed.length === 0)
43797
+ continue;
43798
+ pairs.push({ raw, pattern: prefix + buildBashPattern(parsed[0]) });
43799
+ }
43800
+ return pairs.filter(({ raw, pattern }) => !isPatternAllowed(permissions, pattern) && !allow.some((rule) => bashRuleMatchesCmd(rule, serverId, raw))).map(({ pattern }) => pattern);
43801
+ }
43802
+ // ../packages/shared-fbe/src/outputLimits.ts
43803
+ var MAX_LINE_LEN = 300;
43804
+ var STREAM_FIRST = 1e4;
43805
+ var STREAM_LAST = 1e4;
43806
+ var RUN_OUTPUT_CAP = 256 * 1024;
43807
+ var OUTPUT_POLICIES = {
43808
+ safe: { firstLimit: STREAM_FIRST, lastLimit: STREAM_LAST, hardCap: STREAM_FIRST + STREAM_LAST, lineLimit: MAX_LINE_LEN },
43809
+ wide: { firstLimit: STREAM_FIRST, lastLimit: STREAM_LAST, hardCap: STREAM_FIRST + STREAM_LAST, lineLimit: Infinity },
43810
+ full: { firstLimit: Infinity, lastLimit: 0, hardCap: RUN_OUTPUT_CAP, lineLimit: MAX_LINE_LEN },
43811
+ raw: { firstLimit: Infinity, lastLimit: 0, hardCap: Infinity, lineLimit: Infinity }
43812
+ };
43813
+ // ../packages/shared-fbe/src/realtime/topics.ts
43814
+ var TOPICS = {
43815
+ ["todo:new" /* NEW_TODO */]: {
43816
+ channel: (p) => SERVER_TO_FRONTENDS.project.new_todo(p.projectId),
43817
+ audience: "frontend"
43818
+ },
43819
+ ["todo:new_message" /* TODO_NEW_MESSAGE */]: {
43820
+ channel: (p) => SERVER_TO_FRONTENDS.project.new_message(p.projectId),
43821
+ audience: "frontend"
43822
+ },
43823
+ ["todo:new_message_created" /* TODO_NEW_MESSAGE_CREATED */]: {
43824
+ channel: (p) => SERVER_TO_FRONTENDS.todo.new_message(p.todoId),
43825
+ audience: "frontend"
43826
+ },
43827
+ ["business_context:updated" /* BUSINESS_CONTEXT_UPDATED */]: {
43828
+ channel: (p) => SERVER_TO_FRONTENDS.businessContext.updated(p.userId),
43829
+ audience: "frontend"
43830
+ },
43831
+ ["resource:content_updated" /* RESOURCE_CONTENT_UPDATED */]: {
43832
+ channel: (p) => SERVER_TO_FRONTENDS.resource.contentUpdated(p.userId),
43833
+ audience: "frontend"
43834
+ },
43835
+ ["hexgrid:updated" /* HEXGRID_UPDATED */]: {
43836
+ channel: (p) => SERVER_TO_FRONTENDS.hexGrid.updated(p.projectId),
43837
+ audience: "frontend"
43838
+ },
43839
+ ["sandbox:state" /* SANDBOX_STATE */]: {
43840
+ channel: (p) => SERVER_TO_FRONTENDS.sandbox.state(p.userId),
43841
+ audience: "frontend"
43842
+ },
43843
+ ["device:status" /* DEVICE_STATUS */]: {
43844
+ channel: (p) => SERVER_TO_FRONTENDS.device.status(p.userId),
43845
+ audience: "frontend"
43846
+ },
43847
+ ["NOTIFY" /* NOTIFY */]: {
43848
+ channel: (p) => p.userId ? SERVER_TO_FRONTENDS.notify.user(p.userId) : SERVER_TO_FRONTENDS.todo.notify(p.todoId),
43849
+ audience: "frontend"
43850
+ },
43851
+ ["todo:msg_done" /* TODO_MSG_DONE */]: {
43852
+ channel: (p) => SERVER_TO_FRONTENDS.todo.msgDone(p.todoId),
43853
+ audience: "frontend"
43854
+ },
43855
+ ["block:start_universal" /* BLOCK_START_UNIVERSAL */]: {
43856
+ channel: (p) => SERVER_TO_FRONTENDS.todo.start_universal(p.todoId),
43857
+ audience: "frontend"
43858
+ },
43859
+ ["block:message" /* BLOCK_MESSAGE */]: {
43860
+ channel: (p) => SERVER_TO_FRONTENDS.todo.message(p.todoId),
43861
+ audience: "frontend"
43862
+ },
43863
+ ["BLOCK_UPDATE" /* BLOCK_UPDATE */]: {
43864
+ channel: (p) => SERVER_TO_FRONTENDS.todo.block_update(p.todoId),
43865
+ audience: "frontend"
43866
+ },
43867
+ ["block:end" /* BLOCK_END */]: {
43868
+ channel: (p) => SERVER_TO_FRONTENDS.todo.end(p.todoId),
43869
+ audience: "frontend"
43870
+ },
43871
+ ["todo:msg_start" /* TODO_MSG_START */]: {
43872
+ channel: (p) => SERVER_TO_FRONTENDS.todo.msgStart(p.todoId),
43873
+ audience: "frontend"
43874
+ },
43875
+ ["todo:msg_meta_ai" /* TODO_MSG_META_AI */]: {
43876
+ channel: (p) => SERVER_TO_FRONTENDS.todo.msgMetaAi(p.todoId),
43877
+ audience: "frontend"
43878
+ },
43879
+ ["todo:msg_meta_usr" /* TODO_MSG_META_USR */]: {
43880
+ channel: (p) => SERVER_TO_FRONTENDS.todo.msgMetaUsr(p.todoId),
43881
+ audience: "frontend"
43882
+ },
43883
+ ["todo:msg_stop_sequence" /* TODO_MSG_STOP_SEQUENCE */]: {
43884
+ channel: (p) => SERVER_TO_FRONTENDS.todo.msgStopSequence(p.todoId),
43885
+ audience: "frontend"
43886
+ },
43887
+ ["block:diff_result" /* BLOCK_DIFF_RESULT */]: {
43888
+ channel: (p) => SERVER_TO_FRONTENDS.todo.diff_result(p.todoId),
43889
+ audience: "frontend"
43890
+ },
43891
+ ["frontend:file_chunk_result" /* FRONTEND_FILE_CHUNK_RESULT */]: {
43892
+ channel: (p) => SERVER_TO_FRONTENDS.todo.frontend_file_chunk_result(p.todoId),
43893
+ audience: "frontend"
43894
+ },
43895
+ ["block:save_result" /* BLOCK_SAVE_RESULT */]: {
43896
+ channel: (p) => SERVER_TO_FRONTENDS.todo.save_result(p.todoId),
43897
+ audience: "frontend"
43898
+ },
43899
+ ["block:sh_msg_start" /* BLOCK_SH_MSG_START */]: {
43900
+ channel: (p) => SERVER_TO_FRONTENDS.todo.sh_msg_start_result(p.todoId),
43901
+ audience: "frontend"
43902
+ },
43903
+ ["block:sh_msg_result" /* BLOCK_SH_MSG_RESULT */]: {
43904
+ channel: (p) => SERVER_TO_FRONTENDS.todo.sh_msg_result(p.todoId),
43905
+ audience: "frontend"
43906
+ },
43907
+ ["block:sh_done" /* BLOCK_SH_DONE */]: {
43908
+ channel: (p) => SERVER_TO_FRONTENDS.todo.sh_msg_done_result(p.todoId),
43909
+ audience: "frontend"
43910
+ },
43911
+ ["edge:status" /* EDGE_STATUS */]: {
43912
+ channel: (p) => SERVER_TO_FRONTENDS.edge.status(p.userId),
43913
+ audience: "frontend"
43914
+ },
43915
+ ["EDGE_CONFIG_UPDATE" /* EDGE_CONFIG_UPDATE */]: {
43916
+ channel: (p) => SERVER_TO_FRONTENDS.edge.configUpdate(p.ownerId),
43917
+ audience: "frontend"
43918
+ },
43919
+ ["project:status" /* PROJECT_STATUS */]: {
43920
+ channel: (p) => SERVER_TO_FRONTENDS.project.status(p.projectId),
43921
+ audience: "frontend"
43922
+ },
43923
+ ["todo:status" /* TODO_STATUS */]: {
43924
+ channel: (p) => SERVER_TO_FRONTENDS.todo.status(p.todoId),
43925
+ audience: "frontend"
43926
+ },
43927
+ ["payment:status" /* PAYMENT_STATUS */]: {
43928
+ channel: (p) => SERVER_TO_FRONTENDS.payment.status(p.userId),
43929
+ audience: "frontend"
43930
+ },
43931
+ ["payment:webhook" /* PAYMENT_WEBHOOK */]: {
43932
+ channel: (p) => SERVER_TO_FRONTENDS.payment.status(p.userId),
43933
+ audience: "frontend"
43934
+ }
43935
+ };
43138
43936
  // src/args.ts
43139
43937
  var DEFAULT_API_URL = "https://api.todofor.ai";
43140
43938
  var VERSION = package_default.version;
@@ -43151,12 +43949,16 @@ Usage:
43151
43949
  todoai -n "Quick task" # Non-interactive (run and exit)
43152
43950
  echo "content" | todoai # Pipe from stdin
43153
43951
  todoai --path /my/project "Fix bug" # Explicit workspace path
43154
- todoai -c # Resume last todo
43155
- todoai --resume <todo-id> # Resume specific todo
43156
- todoai --inspect <todo-id>[:<msg-id>] # Print full chat log (read-only); :<msg-id> truncates inclusive
43157
- todoai --inspect :<msg-id> # Same, using $TODOFORAI_TODO_ID from edge env
43952
+ todoai -c ["prompt"] # Resume last todo (optional prompt sent on attach)
43953
+ todoai --resume <todo-id> ["prompt"] # Resume specific todo (optional prompt sent on attach)
43954
+ todoai --inspect <todo-id>[@<slice>] # Read chat log. <slice> = -3:, :1, 5:10, 7 (Python-style)
43158
43955
  todoai --template <id> [--input k=v] # Start from a registry template
43159
43956
  todoai --list-agents # List available agents and exit
43957
+ todoai agent update <agent> model=<model> # Update agent settings (see 'agent --help')
43958
+ todoai list [-n 30] [--all] [--status S] # List todos (open + recent first); see 'list --help'
43959
+ todoai status <todo-id> <STATUS> # Update a todo's status (run 'status --help' for the full list)
43960
+ todoai delete <todo-id> # Permanently delete a todo
43961
+ todoai addmessage <todo-id> "text" # Add a message to an existing todo
43160
43962
 
43161
43963
  Options:
43162
43964
  --path <dir> Workspace path (default: cwd)
@@ -43165,7 +43967,7 @@ Options:
43165
43967
  --list-agents List available agents (name, id, workspace paths) and exit
43166
43968
  --api-url <url> API URL
43167
43969
  --api-key <key> API key
43168
- --inspect, -i [<todo-id>][:<msg-id>] Print full chat log; empty todo-id uses $TODOFORAI_TODO_ID
43970
+ --inspect, -i <todo-id>[@<slice>] Print chat log (read-only)
43169
43971
  --template, -t <id> Start from a registry template
43170
43972
  --input <key=value> Template input (repeatable)
43171
43973
  --resume, -r [todo-id] Resume existing todo
@@ -43176,6 +43978,8 @@ Options:
43176
43978
  --no-watch Create todo and exit
43177
43979
  --no-edge Do not auto-spawn edge daemon
43178
43980
  --json Output as JSON
43981
+ --detailed 'inspect --json': keep ids, timestamps, agentSettingsId, scheduledTimestamp
43982
+ --format-anthropic 'inspect --json': Anthropic-style shape (tool_result in next user msg); attachment sources are uri-typed, so not a 1:1 messages.create input
43179
43983
  --safe Validate API key upfront
43180
43984
  --debug, -d Debug output
43181
43985
  --show-config Show config
@@ -43184,6 +43988,27 @@ Options:
43184
43988
  --help, -h Show this help
43185
43989
  `);
43186
43990
  }
43991
+ var STATUS_HELP = {
43992
+ ["READY" /* READY */]: "AI finished the work on the TODO",
43993
+ ["READY_CHECKED" /* READY_CHECKED */]: "AI finished and the user reviewed it",
43994
+ ["DONE" /* DONE */]: "Completed and finalized",
43995
+ ["REVIEW_REQUESTED" /* REVIEW_REQUESTED */]: "Asks the user to review",
43996
+ ["POSTPONED" /* POSTPONED */]: "Put off for later",
43997
+ ["ARCHIVED" /* ARCHIVED */]: "Archived (hidden from active list)",
43998
+ ["DELETED" /* DELETED */]: "Marked for deletion"
43999
+ };
44000
+ function printStatusHelp() {
44001
+ process.stderr.write(`
44002
+ todoai status <todo-id> <STATUS>
44003
+
44004
+ Common statuses:
44005
+ ${Object.entries(STATUS_HELP).map(([s, d]) => ` ${s.padEnd(18)}${d}`).join(`
44006
+ `)}
44007
+
44008
+ All valid statuses:
44009
+ ${Object.values(TodoStatus).join(", ")}
44010
+ `);
44011
+ }
43187
44012
  function parseCliArgs() {
43188
44013
  const { values, positionals } = parseArgs({
43189
44014
  args: process.argv.slice(2),
@@ -43191,6 +44016,7 @@ function parseCliArgs() {
43191
44016
  path: { type: "string", default: "." },
43192
44017
  project: { type: "string" },
43193
44018
  agent: { type: "string", short: "a" },
44019
+ model: { type: "string" },
43194
44020
  "list-agents": { type: "boolean", default: false },
43195
44021
  "api-url": { type: "string" },
43196
44022
  "api-key": { type: "string" },
@@ -43205,6 +44031,8 @@ function parseCliArgs() {
43205
44031
  "no-watch": { type: "boolean", default: false },
43206
44032
  "no-edge": { type: "boolean", default: false },
43207
44033
  json: { type: "boolean", default: false },
44034
+ detailed: { type: "boolean", default: false },
44035
+ "format-anthropic": { type: "boolean", default: false },
43208
44036
  safe: { type: "boolean", default: false },
43209
44037
  debug: { type: "boolean", short: "d", default: false },
43210
44038
  "show-config": { type: "boolean", default: false },
@@ -43223,21 +44051,23 @@ function parseCliArgs() {
43223
44051
  import { createInterface } from "readline";
43224
44052
 
43225
44053
  // src/colors.ts
43226
- var YELLOW = "\x1B[33m";
43227
- var GREEN = "\x1B[32m";
43228
- var RED = "\x1B[31m";
43229
- var DIM = "\x1B[90m";
43230
- var CYAN = "\x1B[36m";
43231
- var BOLD = "\x1B[1m";
43232
- var WHITE = "\x1B[38;2;255;255;255m";
43233
- var BRIGHT_WHITE = "\x1B[97m";
43234
- var BRAND = "\x1B[38;2;249;110;46m";
43235
- var RESET = "\x1B[0m";
43236
- var DIM_ATTR = "\x1B[2m";
43237
- var BG_RED = "\x1B[48;2;55;20;20m";
43238
- var BG_GREEN = "\x1B[48;2;20;45;20m";
43239
- var BG_RED_HL = "\x1B[48;2;100;35;35m";
43240
- var BG_GREEN_HL = "\x1B[48;2;35;85;35m";
44054
+ var on = !process.env.NO_COLOR && !!process.stdout.isTTY;
44055
+ var c = (seq) => on ? seq : "";
44056
+ var YELLOW = c("\x1B[33m");
44057
+ var GREEN = c("\x1B[32m");
44058
+ var RED = c("\x1B[31m");
44059
+ var DIM = c("\x1B[90m");
44060
+ var CYAN = c("\x1B[36m");
44061
+ var BOLD = c("\x1B[1m");
44062
+ var WHITE = c("\x1B[38;2;255;255;255m");
44063
+ var BRIGHT_WHITE = c("\x1B[97m");
44064
+ var BRAND = c("\x1B[38;2;249;110;46m");
44065
+ var RESET = c("\x1B[0m");
44066
+ var DIM_ATTR = c("\x1B[2m");
44067
+ var BG_RED = c("\x1B[48;2;55;20;20m");
44068
+ var BG_GREEN = c("\x1B[48;2;20;45;20m");
44069
+ var BG_RED_HL = c("\x1B[48;2;100;35;35m");
44070
+ var BG_GREEN_HL = c("\x1B[48;2;35;85;35m");
43241
44071
 
43242
44072
  // src/input.ts
43243
44073
  function readLine(prompt) {
@@ -43475,26 +44305,26 @@ function readMultiline(prompt, history) {
43475
44305
  const ps = s.indexOf("\x1B[200~");
43476
44306
  const chunk = ps >= 0 ? s.slice(0, ps) : s;
43477
44307
  for (let i = 0;i < chunk.length && !done; i++) {
43478
- const c = chunk.charCodeAt(i);
43479
- if (c === 3) {
44308
+ const c2 = chunk.charCodeAt(i);
44309
+ if (c2 === 3) {
43480
44310
  finish(true);
43481
44311
  return;
43482
44312
  }
43483
- if (c === 13 || c === 10) {
44313
+ if (c2 === 13 || c2 === 10) {
43484
44314
  finish(false);
43485
44315
  return;
43486
44316
  }
43487
- if (c === 23) {
44317
+ if (c2 === 23) {
43488
44318
  deleteWordBack();
43489
- } else if (c === 11) {
44319
+ } else if (c2 === 11) {
43490
44320
  killToEnd();
43491
- } else if (c === 127 || c === 8) {
44321
+ } else if (c2 === 127 || c2 === 8) {
43492
44322
  if (cursor > 0) {
43493
44323
  buf = buf.slice(0, cursor - 1) + buf.slice(cursor);
43494
44324
  cursor--;
43495
44325
  redraw();
43496
44326
  }
43497
- } else if (c === 27) {
44327
+ } else if (c2 === 27) {
43498
44328
  if (i + 1 < chunk.length && chunk.charCodeAt(i + 1) === 13) {
43499
44329
  buf = buf.slice(0, cursor) + `
43500
44330
  ` + buf.slice(cursor);
@@ -43504,13 +44334,13 @@ function readMultiline(prompt, history) {
43504
44334
  } else {
43505
44335
  i = handleCSI(chunk, i) - 1;
43506
44336
  }
43507
- } else if (c === 1) {
44337
+ } else if (c2 === 1) {
43508
44338
  cursor = 0;
43509
44339
  redraw();
43510
- } else if (c === 5) {
44340
+ } else if (c2 === 5) {
43511
44341
  cursor = buf.length;
43512
44342
  redraw();
43513
- } else if (c >= 32) {
44343
+ } else if (c2 >= 32) {
43514
44344
  buf = buf.slice(0, cursor) + chunk[i] + buf.slice(cursor);
43515
44345
  cursor++;
43516
44346
  redraw();
@@ -43787,11 +44617,11 @@ var LETTERS = {
43787
44617
  var GAP = " ";
43788
44618
  var WORD = "todo4ai";
43789
44619
  function renderHalfBlock(top, bot) {
43790
- const W = "\x1B[38;2;249;110;46m";
43791
- const G = "\x1B[38;2;140;60;20m";
43792
- const BW = "\x1B[48;2;249;110;46m";
43793
- const BG = "\x1B[48;2;140;60;20m";
43794
- const R = "\x1B[0m";
44620
+ const W = c("\x1B[38;2;249;110;46m");
44621
+ const G = c("\x1B[38;2;140;60;20m");
44622
+ const BW = c("\x1B[48;2;249;110;46m");
44623
+ const BG = c("\x1B[48;2;140;60;20m");
44624
+ const R = c("\x1B[0m");
43795
44625
  if (top === " " && bot === " ")
43796
44626
  return " ";
43797
44627
  if (top === bot) {
@@ -43846,7 +44676,232 @@ function printLogo() {
43846
44676
  }
43847
44677
 
43848
44678
  // src/inspect.ts
43849
- function printFullChat(todo, frontendUrl, untilMessageId) {
44679
+ var xmlAttr = (v) => JSON.stringify(String(v));
44680
+ var DROP_IF_EMPTY = new Set(["runMeta", "meta", "attachments", "blocks"]);
44681
+ var ALWAYS_DROP = new Set(["messageIds", "data"]);
44682
+ var DETAILED_ONLY = new Set([
44683
+ "id",
44684
+ "createdAt",
44685
+ "lastActivityAt",
44686
+ "modifiedAt",
44687
+ "agentSettingsId",
44688
+ "scheduledTimestamp",
44689
+ "workflowVersion",
44690
+ "todoId",
44691
+ "blockId",
44692
+ "parentBlockId",
44693
+ "stop_sequence",
44694
+ "permissions",
44695
+ "isPublic",
44696
+ "metadata"
44697
+ ]);
44698
+ var DEBUG_ONLY = new Set([
44699
+ "runMeta",
44700
+ "generationCompleted",
44701
+ "userId",
44702
+ "deviceId",
44703
+ "runMode"
44704
+ ]);
44705
+ var isEmpty = (x) => Array.isArray(x) && x.length === 0 || x && typeof x === "object" && !Array.isArray(x) && Object.keys(x).length === 0;
44706
+ function pruneEmpty(v, mode = "default") {
44707
+ if (Array.isArray(v))
44708
+ return v.map((x) => pruneEmpty(x, mode));
44709
+ if (v && typeof v === "object") {
44710
+ const o = {};
44711
+ for (const [k, raw] of Object.entries(v)) {
44712
+ if (ALWAYS_DROP.has(k))
44713
+ continue;
44714
+ if (DEBUG_ONLY.has(k) && mode !== "debug")
44715
+ continue;
44716
+ if (DETAILED_ONLY.has(k) && mode === "default")
44717
+ continue;
44718
+ if (raw === "")
44719
+ continue;
44720
+ if (k === "scheduledTimestamp" && (raw === 0 || raw === 1))
44721
+ continue;
44722
+ if (DROP_IF_EMPTY.has(k) && isEmpty(raw))
44723
+ continue;
44724
+ o[k] = pruneEmpty(raw, mode);
44725
+ }
44726
+ return o;
44727
+ }
44728
+ return v;
44729
+ }
44730
+ var BLOCK_META_KEYS = new Set([
44731
+ "type",
44732
+ "id",
44733
+ "parentBlockId",
44734
+ "toolCallId",
44735
+ "status",
44736
+ "results",
44737
+ "content",
44738
+ "modifiedContent",
44739
+ "originalContent",
44740
+ "error_message",
44741
+ "stacktrace",
44742
+ "runMeta",
44743
+ "runMode",
44744
+ "generationCompleted",
44745
+ "userId",
44746
+ "deviceId"
44747
+ ]);
44748
+ function blockToAnthropic(block, mode, format) {
44749
+ const t = block.type;
44750
+ if (t === "text")
44751
+ return [{ type: "text", text: block.content ?? "" }];
44752
+ if (t === "reason")
44753
+ return [{ type: "thinking", thinking: block.content ?? "" }];
44754
+ if (t === "error") {
44755
+ const msg = block.error_message || block.content || "(unknown error)";
44756
+ return [{ type: "text", text: `[error] ${msg}` }];
44757
+ }
44758
+ const inputFields = [];
44759
+ for (const [k, v] of Object.entries(block)) {
44760
+ if (BLOCK_META_KEYS.has(k))
44761
+ continue;
44762
+ if (v === undefined || v === null || v === "")
44763
+ continue;
44764
+ inputFields.push([k, v]);
44765
+ }
44766
+ const use = format === "anthropic" ? { type: "tool_use", id: block.id, name: t, input: Object.fromEntries(inputFields) } : { type: "tool_use", content: `<${t}${inputFields.map(([k, v]) => ` ${k}=${xmlAttr(v)}`).join("")}/>` };
44767
+ if (format === "compact" && mode !== "default")
44768
+ use.id = block.id;
44769
+ const items = [use];
44770
+ if (block.results?.length) {
44771
+ if (format === "anthropic") {
44772
+ const content = block.results.flatMap((r) => {
44773
+ const parts = [];
44774
+ for (const att of r.attachments ?? []) {
44775
+ const isImage = (att.mimeType || "").startsWith("image/");
44776
+ const isAutoName = /^(bash|read|list|explore|edit|write|grep):/.test(att.originalName ?? "");
44777
+ const source = { type: "uri", uri: att.uri, mimeType: att.mimeType, size: att.fileSize };
44778
+ if (att.originalName && !isAutoName)
44779
+ source.name = att.originalName;
44780
+ parts.push({ type: isImage ? "image" : "document", source });
44781
+ }
44782
+ if (typeof r.content === "string" && r.content)
44783
+ parts.push({ type: "text", text: r.content });
44784
+ return parts;
44785
+ });
44786
+ const result = { type: "tool_result", tool_use_id: block.id };
44787
+ if (content.length)
44788
+ result.content = content;
44789
+ if (block.status && block.status !== "COMPLETED")
44790
+ result.is_error = true;
44791
+ items.push(result);
44792
+ } else {
44793
+ const parts = [];
44794
+ for (const r of block.results) {
44795
+ for (const att of r.attachments ?? []) {
44796
+ const isAutoName = /^(bash|read|list|explore|edit|write|grep):/.test(att.originalName ?? "");
44797
+ const nameAttr = att.originalName && !isAutoName ? ` name=${xmlAttr(att.originalName)}` : "";
44798
+ parts.push(`<attachment uri=${xmlAttr(att.uri)}${nameAttr} size=${att.fileSize}/>`);
44799
+ }
44800
+ if (typeof r.content === "string" && r.content)
44801
+ parts.push(r.content);
44802
+ }
44803
+ const result = { type: "tool_result", content: parts.join(`
44804
+ `) };
44805
+ if (mode !== "default")
44806
+ result.tool_use_id = block.id;
44807
+ if (block.status && block.status !== "COMPLETED")
44808
+ result.status = block.status;
44809
+ items.push(result);
44810
+ }
44811
+ }
44812
+ return items;
44813
+ }
44814
+ function toAnthropicShape(messages, mode = "default", format = "compact") {
44815
+ const out = [];
44816
+ let prevToolAttachmentIds = new Set;
44817
+ for (const m of messages) {
44818
+ const msg = { role: m.role };
44819
+ if (mode !== "default") {
44820
+ if (m.id)
44821
+ msg.id = m.id;
44822
+ if (m.createdAt)
44823
+ msg.createdAt = m.createdAt;
44824
+ }
44825
+ if (m.role === "user") {
44826
+ const atts = (m.attachments ?? []).filter((a) => !prevToolAttachmentIds.has(a.id)).map((a) => {
44827
+ const isImage = (a.mimeType || "").startsWith("image/");
44828
+ return {
44829
+ type: isImage ? "image" : "document",
44830
+ source: { type: "uri", uri: a.uri, name: a.originalName, mimeType: a.mimeType, size: a.fileSize }
44831
+ };
44832
+ });
44833
+ const hadAttachments = (m.attachments ?? []).length > 0;
44834
+ if (!m.content && hadAttachments && atts.length === 0 && mode === "default") {
44835
+ prevToolAttachmentIds = new Set;
44836
+ continue;
44837
+ }
44838
+ if (atts.length === 0) {
44839
+ msg.content = m.content ?? "";
44840
+ } else {
44841
+ msg.content = [
44842
+ ...m.content ? [{ type: "text", text: m.content }] : [],
44843
+ ...atts
44844
+ ];
44845
+ }
44846
+ out.push(pruneEmpty(msg, mode));
44847
+ prevToolAttachmentIds = new Set;
44848
+ continue;
44849
+ }
44850
+ const content = [];
44851
+ if (m.content)
44852
+ content.push({ type: "text", text: m.content });
44853
+ for (const b of m.blocks ?? []) {
44854
+ for (const r of b.results ?? []) {
44855
+ for (const a of r.attachments ?? [])
44856
+ if (a.id)
44857
+ prevToolAttachmentIds.add(a.id);
44858
+ }
44859
+ }
44860
+ for (const b of m.blocks ?? [])
44861
+ content.push(...blockToAnthropic(b, mode, format));
44862
+ if (format === "anthropic") {
44863
+ const useItems = content.filter((c2) => c2.type !== "tool_result");
44864
+ const resultItems = content.filter((c2) => c2.type === "tool_result");
44865
+ msg.content = useItems;
44866
+ if (mode === "debug" && m.runMeta?.length)
44867
+ msg.runMeta = m.runMeta;
44868
+ out.push(pruneEmpty(msg, mode));
44869
+ if (resultItems.length) {
44870
+ out.push(pruneEmpty({ role: "user", content: resultItems }, mode));
44871
+ }
44872
+ } else {
44873
+ msg.content = content;
44874
+ if (mode === "debug" && m.runMeta?.length)
44875
+ msg.runMeta = m.runMeta;
44876
+ out.push(pruneEmpty(msg, mode));
44877
+ }
44878
+ }
44879
+ return out;
44880
+ }
44881
+ function applySlice(arr, spec) {
44882
+ if (!spec.includes(":")) {
44883
+ const i = Number(spec);
44884
+ if (!Number.isInteger(i))
44885
+ throw new Error(`Bad slice: '${spec}'`);
44886
+ const r = arr.at(i);
44887
+ return r === undefined ? [] : [r];
44888
+ }
44889
+ const parts = spec.split(":");
44890
+ if (parts.length !== 2)
44891
+ throw new Error(`Bad slice: '${spec}' (use N, N:, :N, or N:M)`);
44892
+ const [a, b] = parts;
44893
+ const start = a === "" ? 0 : Number(a);
44894
+ const end = b === "" ? arr.length : Number(b);
44895
+ if (!Number.isInteger(start) || !Number.isInteger(end))
44896
+ throw new Error(`Bad slice: '${spec}'`);
44897
+ return arr.slice(start, end);
44898
+ }
44899
+ var trunc = (s, n) => s.length > n ? s.slice(0, n) + `
44900
+ ${DIM}... (${s.length} chars)${RESET}` : s;
44901
+ var indent = (s, pre) => s.split(`
44902
+ `).join(`
44903
+ ${pre}`);
44904
+ function printFullChat(todo, frontendUrl, slice, mode = "default", format = "compact") {
43850
44905
  const statusColors = {
43851
44906
  DONE: GREEN,
43852
44907
  READY: GREEN,
@@ -43871,69 +44926,83 @@ function printFullChat(todo, frontendUrl, untilMessageId) {
43871
44926
  if (todo.agentSettingsId)
43872
44927
  process.stderr.write(`${DIM}Agent:${RESET} ${todo.agentSettingsId}
43873
44928
  `);
43874
- if (untilMessageId)
43875
- process.stderr.write(`${DIM}Until:${RESET} ${untilMessageId}
44929
+ if (slice)
44930
+ process.stderr.write(`${DIM}Slice:${RESET} [${slice}]
43876
44931
  `);
43877
44932
  process.stderr.write("\u2500".repeat(60) + `
43878
44933
  `);
43879
44934
  let messages = todo.messages || [];
43880
- if (untilMessageId) {
43881
- const idx = messages.findIndex((m) => m.id === untilMessageId);
43882
- if (idx < 0) {
43883
- process.stderr.write(`${RED}Error: message ${untilMessageId} not found in todo${RESET}
44935
+ if (slice) {
44936
+ try {
44937
+ messages = applySlice(messages, slice);
44938
+ } catch (e) {
44939
+ process.stderr.write(`${RED}${e.message}${RESET}
43884
44940
  `);
43885
44941
  process.exit(2);
43886
44942
  }
43887
- messages = messages.slice(0, idx + 1);
43888
44943
  }
43889
44944
  if (!messages.length) {
43890
44945
  process.stderr.write(`${DIM}(no messages)${RESET}
43891
44946
  `);
43892
44947
  return;
43893
44948
  }
43894
- for (const msg of messages) {
43895
- const roleLabel = msg.role === "user" ? `${CYAN}\u25B6 USER${RESET}` : `${GREEN}\u25C0 ASSISTANT${RESET}`;
44949
+ const shaped = toAnthropicShape(messages, mode, format);
44950
+ let toolUseCount = 0, errorCount = 0;
44951
+ for (let i = 0;i < shaped.length; i++) {
44952
+ const msg = shaped[i];
44953
+ const orig = messages[i];
44954
+ const ts = mode !== "default" && orig?.createdAt ? ` ${DIM}${new Date(orig.createdAt).toLocaleTimeString()}${RESET}` : "";
44955
+ const label = msg.role === "user" ? `${CYAN}\u25B6 USER${RESET}` : `${GREEN}\u25C0 ASSISTANT${RESET}`;
43896
44956
  process.stderr.write(`
43897
- ${roleLabel} ${DIM}${new Date(msg.createdAt).toLocaleTimeString()}${RESET}
44957
+ ${label}${ts}
43898
44958
  `);
43899
- if (msg.content) {
43900
- const content = msg.content.length > 2000 ? msg.content.slice(0, 2000) + `
43901
- ${DIM}... (${msg.content.length} chars total)${RESET}` : msg.content;
43902
- process.stdout.write(content + `
44959
+ const items = Array.isArray(msg.content) ? msg.content : [{ type: "text", text: msg.content }];
44960
+ for (const it of items) {
44961
+ if (it.type === "text") {
44962
+ if (it.text)
44963
+ process.stdout.write(trunc(it.text, 2000) + `
43903
44964
  `);
43904
- }
43905
- for (const block of msg.blocks || []) {
43906
- const blockStatusColor = block.status === "COMPLETED" ? GREEN : block.status === "ERROR" || block.status === "DENIED" ? RED : YELLOW;
43907
- process.stderr.write(`
43908
- ${YELLOW}[${block.type}]${RESET} ${blockStatusColor}${block.status}${RESET}`);
43909
- for (const key of ["path", "cmd", "name", "server_name", "tool_name"]) {
43910
- if (block[key])
43911
- process.stderr.write(` ${DIM}${key}=${RESET}${block[key]}`);
43912
- }
43913
- process.stderr.write(`
44965
+ } else if (it.type === "image" || it.type === "document") {
44966
+ const s = it.source ?? {};
44967
+ process.stderr.write(` ${YELLOW}[${it.type}]${RESET} ${DIM}${s.mimeType ?? ""}${RESET} ${s.name ?? ""} ${DIM}(${s.size ?? "?"} bytes)${RESET}
44968
+ ${DIM}${s.uri ?? ""}${RESET}
43914
44969
  `);
43915
- if (block.content) {
43916
- const content = block.content.length > 500 ? block.content.slice(0, 500) + `
43917
- ${DIM}... (${block.content.length} chars)${RESET}` : block.content;
43918
- process.stdout.write(` ${DIM}\u2502${RESET} ${content.split(`
43919
- `).join(`
43920
- ${DIM}\u2502${RESET} `)}
44970
+ } else if (it.type === "thinking") {
44971
+ if (it.thinking)
44972
+ process.stderr.write(`${DIM}[thinking]${RESET} ${trunc(it.thinking, 500)}
43921
44973
  `);
43922
- }
43923
- if (block.result) {
43924
- const result = block.result.length > 500 ? block.result.slice(0, 500) + `
43925
- ${DIM}... (${block.result.length} chars)${RESET}` : block.result;
43926
- process.stderr.write(` ${DIM}\u2514\u2500 result:${RESET} ${result.split(`
43927
- `).join(`
43928
- ${DIM}\u2502${RESET} `)}
44974
+ } else if (it.type === "tool_use") {
44975
+ toolUseCount++;
44976
+ if (it.content) {
44977
+ process.stderr.write(` ${YELLOW}${trunc(it.content, 200)}${RESET}
43929
44978
  `);
43930
- }
43931
- if (block.error_message) {
43932
- process.stderr.write(` ${RED}\u2514\u2500 error: ${block.error_message}${RESET}
44979
+ } else {
44980
+ const argStr = Object.entries(it.input || {}).map(([k, v]) => `${DIM}${k}=${RESET}${String(v).split(`
44981
+ `)[0].slice(0, 80)}`).join(" ");
44982
+ process.stderr.write(` ${YELLOW}[${it.name}]${RESET} ${argStr}
43933
44983
  `);
43934
- }
43935
- if (block.stacktrace) {
43936
- process.stderr.write(` ${DIM}${block.stacktrace.slice(0, 300)}${block.stacktrace.length > 300 ? "..." : ""}${RESET}
44984
+ }
44985
+ } else if (it.type === "tool_result") {
44986
+ const errLabel = it.is_error ? ` ${RED}ERROR${RESET}` : it.status && it.status !== "COMPLETED" ? ` ${RED}${it.status}${RESET}` : "";
44987
+ if (errLabel)
44988
+ errorCount++;
44989
+ const status = errLabel;
44990
+ let bodyStr;
44991
+ if (typeof it.content === "string")
44992
+ bodyStr = it.content;
44993
+ else {
44994
+ bodyStr = (it.content || []).map((c2) => {
44995
+ if (c2.type === "text")
44996
+ return c2.text ?? "";
44997
+ if (c2.type === "image" || c2.type === "document") {
44998
+ const s = c2.source ?? {};
44999
+ return `[${c2.type}] ${s.mimeType ?? ""}${s.name ? " " + s.name : ""} (${s.size ?? "?"} B) ${s.uri ?? ""}`;
45000
+ }
45001
+ return "";
45002
+ }).join(`
45003
+ `);
45004
+ }
45005
+ process.stderr.write(` ${DIM}\u2514\u2500 result:${RESET}${status} ${indent(trunc(bodyStr, 500), ` ${DIM}\u2502${RESET} `)}
43937
45006
  `);
43938
45007
  }
43939
45008
  }
@@ -43941,9 +45010,7 @@ ${DIM}... (${block.result.length} chars)${RESET}` : block.result;
43941
45010
  process.stderr.write(`
43942
45011
  ` + "\u2500".repeat(60) + `
43943
45012
  `);
43944
- const blockCount = messages.reduce((n, m) => n + (m.blocks?.length || 0), 0);
43945
- const errorBlocks = messages.reduce((n, m) => n + (m.blocks || []).filter((b) => b.status === "ERROR" || b.type === "error").length, 0);
43946
- process.stderr.write(`${DIM}Messages: ${messages.length} | Blocks: ${blockCount} | Errors: ${errorBlocks}${RESET}
45013
+ process.stderr.write(`${DIM}Messages: ${shaped.length} | Tool calls: ${toolUseCount} | Tool errors: ${errorCount}${RESET}
43947
45014
  `);
43948
45015
  }
43949
45016
 
@@ -44093,347 +45160,6 @@ Please choose an agent:
44093
45160
  })();
44094
45161
  }
44095
45162
 
44096
- // ../packages/shared-fbe/src/bashPatterns.ts
44097
- function splitShellCommands(input) {
44098
- const parts = [];
44099
- let current = "";
44100
- let i = 0;
44101
- const len = input.length;
44102
- while (i < len) {
44103
- const ch = input[i];
44104
- if (ch === "\\" && i + 1 < len && input[i + 1] === `
44105
- `) {
44106
- current += " ";
44107
- i += 2;
44108
- continue;
44109
- }
44110
- if (ch === "\\" && i + 1 < len) {
44111
- current += ch + input[i + 1];
44112
- i += 2;
44113
- continue;
44114
- }
44115
- if (ch === "<" && i + 1 < len && input[i + 1] === "<") {
44116
- i += 2;
44117
- if (i < len && input[i] === "-")
44118
- i++;
44119
- while (i < len && (input[i] === " " || input[i] === "\t"))
44120
- i++;
44121
- let delim = "";
44122
- if (i < len && (input[i] === "'" || input[i] === '"')) {
44123
- const q = input[i];
44124
- i++;
44125
- while (i < len && input[i] !== q) {
44126
- delim += input[i];
44127
- i++;
44128
- }
44129
- if (i < len)
44130
- i++;
44131
- } else {
44132
- while (i < len && /\w/.test(input[i])) {
44133
- delim += input[i];
44134
- i++;
44135
- }
44136
- }
44137
- if (delim) {
44138
- const rest = input.slice(i);
44139
- const m = rest.match(new RegExp(`^${delim}$`, "m"));
44140
- if (m && m.index !== undefined) {
44141
- i += m.index + delim.length;
44142
- } else {
44143
- i = len;
44144
- }
44145
- }
44146
- continue;
44147
- }
44148
- if (ch === "#" && (current.length === 0 || /\s$/.test(current))) {
44149
- while (i < len && input[i] !== `
44150
- `)
44151
- i++;
44152
- continue;
44153
- }
44154
- if (ch === '"' || ch === "'") {
44155
- const quote = ch;
44156
- current += ch;
44157
- i++;
44158
- while (i < len && input[i] !== quote) {
44159
- if (input[i] === "\\" && quote === '"' && i + 1 < len) {
44160
- current += input[i] + input[i + 1];
44161
- i += 2;
44162
- } else {
44163
- current += input[i];
44164
- i++;
44165
- }
44166
- }
44167
- if (i < len)
44168
- current += input[i];
44169
- i++;
44170
- continue;
44171
- }
44172
- if (ch === "|" && i + 1 < len && input[i + 1] === "|") {
44173
- parts.push(current);
44174
- current = "";
44175
- i += 2;
44176
- } else if (ch === "&" && i + 1 < len && input[i + 1] === "&") {
44177
- parts.push(current);
44178
- current = "";
44179
- i += 2;
44180
- } else if (ch === "|") {
44181
- parts.push(current);
44182
- current = "";
44183
- i++;
44184
- } else if (ch === ";" || ch === `
44185
- `) {
44186
- parts.push(current);
44187
- current = "";
44188
- i++;
44189
- } else {
44190
- current += ch;
44191
- i++;
44192
- }
44193
- }
44194
- parts.push(current);
44195
- return parts.map((s) => s.trim()).filter(Boolean);
44196
- }
44197
- function generalizeToken(token) {
44198
- if (/^\d+$/.test(token))
44199
- return "*";
44200
- if (/^[0-9a-f]{4,}$/i.test(token) && /\d/.test(token))
44201
- return "*";
44202
- if (/^[0-9a-f]{8}-[0-9a-f]{4}-/i.test(token))
44203
- return "*";
44204
- if (/^https?:\/\//i.test(token)) {
44205
- try {
44206
- const u = new URL(token);
44207
- return `${u.protocol}//${u.host}/*`;
44208
- } catch {
44209
- return token;
44210
- }
44211
- }
44212
- return token;
44213
- }
44214
- var SAFE_FLAGS = new Set(["--help", "-h", "--version", "-V", "-v"]);
44215
- function splitTokens(cmd) {
44216
- const tokens = [];
44217
- let current = "";
44218
- let i = 0;
44219
- const len = cmd.length;
44220
- while (i < len) {
44221
- const ch = cmd[i];
44222
- if (ch === "\\" && i + 1 < len && cmd[i + 1] === `
44223
- `) {
44224
- i += 2;
44225
- continue;
44226
- }
44227
- if (ch === "\\" && i + 1 < len) {
44228
- current += ch + cmd[i + 1];
44229
- i += 2;
44230
- continue;
44231
- }
44232
- if (ch === '"' || ch === "'") {
44233
- const q = ch;
44234
- current += ch;
44235
- i++;
44236
- while (i < len && cmd[i] !== q) {
44237
- if (cmd[i] === "\\" && q === '"' && i + 1 < len) {
44238
- current += cmd[i] + cmd[i + 1];
44239
- i += 2;
44240
- } else {
44241
- current += cmd[i];
44242
- i++;
44243
- }
44244
- }
44245
- if (i < len) {
44246
- current += cmd[i];
44247
- i++;
44248
- }
44249
- continue;
44250
- }
44251
- if (/\s/.test(ch)) {
44252
- if (current) {
44253
- tokens.push(current);
44254
- current = "";
44255
- }
44256
- i++;
44257
- continue;
44258
- }
44259
- current += ch;
44260
- i++;
44261
- }
44262
- if (current)
44263
- tokens.push(current);
44264
- return tokens;
44265
- }
44266
- function parseSingle(cmd) {
44267
- const tokens = splitTokens(cmd);
44268
- while (tokens.length && /^[A-Za-z_]\w*=/.test(tokens[0])) {
44269
- const val = tokens[0].slice(tokens[0].indexOf("=") + 1);
44270
- if (/\$\(|`/.test(val))
44271
- return { tokens: [], defaultKeep: 0 };
44272
- tokens.shift();
44273
- }
44274
- if (tokens.length === 0)
44275
- return { tokens: [], defaultKeep: 0 };
44276
- if (tokens[0].startsWith("#"))
44277
- return { tokens: [], defaultKeep: 0 };
44278
- const positionals = [tokens[0]];
44279
- let hitFlag = false;
44280
- let defaultKeep = -1;
44281
- for (let t = 1;t < tokens.length; t++) {
44282
- if (!hitFlag && SAFE_FLAGS.has(tokens[t])) {
44283
- positionals.push(tokens[t]);
44284
- return { tokens: positionals, defaultKeep: positionals.length };
44285
- }
44286
- if (tokens[t].startsWith("-")) {
44287
- if (!hitFlag) {
44288
- hitFlag = true;
44289
- defaultKeep = Math.min(3, positionals.length);
44290
- }
44291
- positionals.push(tokens[t]);
44292
- continue;
44293
- }
44294
- const g = generalizeToken(tokens[t]);
44295
- positionals.push(g);
44296
- if (g !== tokens[t])
44297
- break;
44298
- }
44299
- if (defaultKeep < 0)
44300
- defaultKeep = Math.min(3, positionals.length);
44301
- return { tokens: positionals, defaultKeep };
44302
- }
44303
- function buildBashPattern(parsed, keep) {
44304
- if (parsed.tokens.length === 0)
44305
- return "BASH(cmd: *)";
44306
- const k = Math.max(1, Math.min(keep ?? parsed.defaultKeep, parsed.tokens.length));
44307
- const kept = parsed.tokens.slice(0, k);
44308
- const suffix = kept[kept.length - 1] === "*" ? "" : " *";
44309
- return `BASH(cmd: ${kept.join(" ")}${suffix})`;
44310
- }
44311
- function parseBashCmd(fullCmd) {
44312
- return splitShellCommands(fullCmd).map(parseSingle).filter((p) => p.tokens.length > 0);
44313
- }
44314
- function generalizeBashCmd(fullCmd) {
44315
- return parseBashCmd(fullCmd).map((p) => buildBashPattern(p));
44316
- }
44317
- function getBlockServerPrefix(block) {
44318
- const agentPattern = typeof block.generalized_pattern === "string" ? block.generalized_pattern : "";
44319
- const prefixMatch = agentPattern.match(/^(.*?:)BASH(?:\(|$)/);
44320
- return prefixMatch ? prefixMatch[1] : "";
44321
- }
44322
- var BASH_LIKE_BLOCK_TYPES = new Set(["bash", "machine_exec"]);
44323
- function getBlockPatterns(block) {
44324
- if (Array.isArray(block.generalized_pattern))
44325
- return block.generalized_pattern;
44326
- const agentPattern = typeof block.generalized_pattern === "string" ? block.generalized_pattern : "";
44327
- const isBashLike = BASH_LIKE_BLOCK_TYPES.has(block.type.toLowerCase()) || /:BASH(\(|$)/.test(agentPattern);
44328
- if (isBashLike && block.cmd) {
44329
- const prefix = getBlockServerPrefix(block);
44330
- return generalizeBashCmd(block.cmd).map((p) => prefix + p);
44331
- }
44332
- if (block.generalized_pattern)
44333
- return [block.generalized_pattern];
44334
- return [`${block.type}(*)`];
44335
- }
44336
- function getBlockServerId(block) {
44337
- const prefix = getBlockServerPrefix(block);
44338
- return prefix ? prefix.slice(0, -1) : "*";
44339
- }
44340
-
44341
- // ../packages/shared-fbe/src/permissionUtils.ts
44342
- function parsePattern(pattern) {
44343
- const colonIndex = pattern.indexOf(":");
44344
- if (colonIndex === -1)
44345
- return null;
44346
- const serverId = pattern.slice(0, colonIndex);
44347
- if (!/^[A-Za-z0-9_*-]+$/.test(serverId)) {
44348
- return { serverId: "*", toolName: pattern };
44349
- }
44350
- return { serverId, toolName: pattern.slice(colonIndex + 1) };
44351
- }
44352
- function serverIdMatches(ruleServerId, targetServerId) {
44353
- if (ruleServerId === targetServerId)
44354
- return true;
44355
- if (ruleServerId === "*")
44356
- return true;
44357
- if (ruleServerId.includes("*")) {
44358
- const escaped = ruleServerId.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
44359
- const regex = new RegExp("^" + escaped.replace(/\*/g, "[^:]*") + "$");
44360
- return regex.test(targetServerId);
44361
- }
44362
- if (targetServerId.startsWith(ruleServerId + "_"))
44363
- return true;
44364
- return false;
44365
- }
44366
- function patternMatches(rulePattern, targetPattern) {
44367
- const rule = parsePattern(rulePattern);
44368
- const target = parsePattern(targetPattern);
44369
- if (!rule || !target)
44370
- return rulePattern === targetPattern;
44371
- if (!serverIdMatches(rule.serverId, target.serverId))
44372
- return false;
44373
- if (rule.toolName === target.toolName)
44374
- return true;
44375
- if (rule.toolName === "*")
44376
- return true;
44377
- if (rule.toolName.endsWith(" *)")) {
44378
- const rulePrefix = rule.toolName.slice(0, -2);
44379
- return target.toolName.startsWith(rulePrefix);
44380
- }
44381
- return false;
44382
- }
44383
- function bashRuleMatchesCmd(rulePattern, serverId, cmd) {
44384
- const rule = parsePattern(rulePattern);
44385
- if (!rule)
44386
- return false;
44387
- if (!serverIdMatches(rule.serverId, serverId))
44388
- return false;
44389
- if (rule.toolName === "*" || rule.toolName === "BASH")
44390
- return true;
44391
- const m = rule.toolName.match(/^BASH\(cmd:\s*(.*)\)$/);
44392
- if (!m)
44393
- return false;
44394
- let body = m[1];
44395
- const isPrefix = body.endsWith(" *") || body.endsWith("*");
44396
- if (isPrefix)
44397
- body = body.replace(/\s*\*$/, "");
44398
- const subs = splitShellCommands(cmd);
44399
- if (subs.length === 0)
44400
- return false;
44401
- return subs.every((sub) => isPrefix ? sub === body || sub.startsWith(body + " ") : sub === body);
44402
- }
44403
- function isPatternInList(list, pattern) {
44404
- if (!list)
44405
- return false;
44406
- return list.some((p) => patternMatches(p, pattern));
44407
- }
44408
- function isPatternAllowed(permissions, pattern) {
44409
- return isPatternInList(permissions?.allow, pattern);
44410
- }
44411
- function getNewPatterns(patterns, permissions) {
44412
- return patterns.filter((p) => !isPatternAllowed(permissions, p));
44413
- }
44414
- function getBlockNewPatterns(block, permissions) {
44415
- const allow = permissions?.allow ?? [];
44416
- if (Array.isArray(block.generalized_pattern)) {
44417
- return getNewPatterns(block.generalized_pattern, permissions);
44418
- }
44419
- const agentPattern = typeof block.generalized_pattern === "string" ? block.generalized_pattern : "";
44420
- const isBash = (block.type.toLowerCase() === "bash" || agentPattern.includes(":BASH(")) && !!block.cmd;
44421
- if (!isBash) {
44422
- return getBlockPatterns(block).filter((p) => !isPatternAllowed(permissions, p));
44423
- }
44424
- const serverId = getBlockServerId(block);
44425
- const prefix = serverId === "*" ? "" : `${serverId}:`;
44426
- const rawSubs = splitShellCommands(block.cmd);
44427
- const pairs = [];
44428
- for (const raw of rawSubs) {
44429
- const parsed = parseBashCmd(raw);
44430
- if (parsed.length === 0)
44431
- continue;
44432
- pairs.push({ raw, pattern: prefix + buildBashPattern(parsed[0]) });
44433
- }
44434
- return pairs.filter(({ raw, pattern }) => !isPatternAllowed(permissions, pattern) && !allow.some((rule) => bashRuleMatchesCmd(rule, serverId, raw))).map(({ pattern }) => pattern);
44435
- }
44436
-
44437
45163
  // src/diff-view.ts
44438
45164
  var import_diff_match_patch = __toESM(require_diff_match_patch(), 1);
44439
45165
  var import_cli_highlight = __toESM(require_dist(), 1);
@@ -44635,8 +45361,8 @@ function renderDiff(originalContent, modifiedContent, filePath) {
44635
45361
  return "";
44636
45362
  const visible = new Set;
44637
45363
  for (const idx of changed) {
44638
- for (let c = Math.max(0, idx - CONTEXT_LINES);c <= Math.min(lines.length - 1, idx + CONTEXT_LINES); c++) {
44639
- visible.add(c);
45364
+ for (let c2 = Math.max(0, idx - CONTEXT_LINES);c2 <= Math.min(lines.length - 1, idx + CONTEXT_LINES); c2++) {
45365
+ visible.add(c2);
44640
45366
  }
44641
45367
  }
44642
45368
  const parts = [`${CYAN}\u2500\u2500 ${filePath} \u2500\u2500${RESET}
@@ -44799,12 +45525,12 @@ ${YELLOW}Interrupting... (Ctrl+C again to force exit)${RESET}
44799
45525
  if (approvalPromptActive || pendingBlocks.length === 0)
44800
45526
  return;
44801
45527
  approvalPromptActive = true;
44802
- const blocks = pendingBlocks.splice(0).map((bi) => {
45528
+ const blocks3 = pendingBlocks.splice(0).map((bi) => {
44803
45529
  const latest = bi?.blockId ? blocksStore.get(bi.blockId) || {} : {};
44804
45530
  return { ...latest, ...bi };
44805
45531
  });
44806
45532
  if (approveAll) {
44807
- for (const bi of blocks) {
45533
+ for (const bi of blocks3) {
44808
45534
  const [tl, disp] = blockDisplay(bi);
44809
45535
  process.stderr.write(`
44810
45536
  ${YELLOW}\u26A0 Auto-approving [${tl}]${RESET} ${disp}
@@ -44817,14 +45543,14 @@ ${YELLOW}\u26A0 Auto-approving [${tl}]${RESET} ${disp}
44817
45543
  }
44818
45544
  return;
44819
45545
  }
44820
- activeApprovalBlocks = blocks;
44821
- const hasFileBlocks = blocks.some((bi) => ["create", "edit"].includes(classifyBlock(bi)));
45546
+ activeApprovalBlocks = blocks3;
45547
+ const hasFileBlocks = blocks3.some((bi) => ["create", "edit"].includes(classifyBlock(bi)));
44822
45548
  if (hasFileBlocks)
44823
45549
  await new Promise((r) => setTimeout(r, 1500));
44824
45550
  process.stderr.write(`
44825
- ${YELLOW}\u26A0 ${blocks.length} action(s) awaiting approval:${RESET}
45551
+ ${YELLOW}\u26A0 ${blocks3.length} action(s) awaiting approval:${RESET}
44826
45552
  `);
44827
- for (const bi of blocks) {
45553
+ for (const bi of blocks3) {
44828
45554
  const [tl, disp] = blockDisplay(bi);
44829
45555
  process.stderr.write(` ${YELLOW}[${tl}]${RESET} ${disp}
44830
45556
  `);
@@ -44841,7 +45567,7 @@ ${YELLOW}\u26A0 ${blocks.length} action(s) awaiting approval:${RESET}
44841
45567
  process.stderr.write(renderDiff(diff.originalContent, diff.modifiedContent, filePath));
44842
45568
  }
44843
45569
  }
44844
- const newPatterns = blocks.flatMap((bi) => getBlockNewPatterns({
45570
+ const newPatterns = blocks3.flatMap((bi) => getBlockNewPatterns({
44845
45571
  type: bi.block_type || "unknown",
44846
45572
  generalized_pattern: bi.generalized_pattern,
44847
45573
  cmd: bi.cmd
@@ -44855,7 +45581,7 @@ ${YELLOW}\u26A0 ${blocks.length} action(s) awaiting approval:${RESET}
44855
45581
  }
44856
45582
  if (response === "a" || response === "y" || response === "" || response === "r") {
44857
45583
  const decision = response === "r" ? "allow_remember" : "allow_once";
44858
- for (const bi of blocks) {
45584
+ for (const bi of blocks3) {
44859
45585
  let patterns;
44860
45586
  if (response === "r") {
44861
45587
  patterns = getBlockNewPatterns({
@@ -44871,14 +45597,14 @@ ${YELLOW}\u26A0 ${blocks.length} action(s) awaiting approval:${RESET}
44871
45597
  sendApproval(ws, bi.blockId, bi.messageId, todoId, decision, patterns);
44872
45598
  }
44873
45599
  } else {
44874
- for (const bi of blocks) {
45600
+ for (const bi of blocks3) {
44875
45601
  ws.sendBlockDeny(todoId, bi.messageId, bi.blockId);
44876
45602
  }
44877
45603
  process.stderr.write(` ${RED}\u2717 Denied${RESET}
44878
45604
  `);
44879
45605
  }
44880
45606
  } catch {
44881
- for (const bi of blocks) {
45607
+ for (const bi of blocks3) {
44882
45608
  sendApproval(ws, bi.blockId, bi.messageId, todoId);
44883
45609
  }
44884
45610
  }
@@ -45028,6 +45754,239 @@ async function listAgentsCommand(api, opts) {
45028
45754
  }
45029
45755
  }
45030
45756
 
45757
+ // src/agent-command.ts
45758
+ function printAgentHelp() {
45759
+ process.stderr.write(`
45760
+ todoai agent \u2014 inspect and update agent settings
45761
+
45762
+ Usage:
45763
+ todoai agent list List agents (name, model, id, paths)
45764
+ todoai agent get <agent> Show a single agent's settings
45765
+ todoai agent update <agent> <field=value>\u2026 Update one or more settings
45766
+
45767
+ <agent> is a name or id (unique partial name also works).
45768
+ Fields map directly to agent settings; values are parsed as JSON when possible
45769
+ (numbers, booleans), otherwise treated as strings. Common fields:
45770
+ model e.g. claude | anthropic:anthropic/claude-opus-4.8
45771
+ ('claude' is the rolling alias \u2192 latest Claude Opus)
45772
+ systemMessage freeform prompt text (alias: sysmsg)
45773
+ temperature number, e.g. 0.7
45774
+ thinkingLevel low | medium | high | xhigh | max
45775
+ name agent display name
45776
+
45777
+ Examples:
45778
+ todoai agent update <agent> model=claude
45779
+ todoai agent update <agent> model=anthropic:anthropic/claude-opus-4.8 temperature=0.5
45780
+ todoai agent update <agent> sysmsg="You are a terse video editor."
45781
+ `);
45782
+ }
45783
+ var FIELD_ALIASES = {
45784
+ sysmsg: "systemMessage",
45785
+ prompt: "systemMessage",
45786
+ temp: "temperature",
45787
+ thinking: "thinkingLevel"
45788
+ };
45789
+ function parseAssignment(arg) {
45790
+ const eq = arg.indexOf("=");
45791
+ if (eq < 1) {
45792
+ process.stderr.write(`${RED}Invalid field assignment '${arg}', expected field=value${RESET}
45793
+ `);
45794
+ process.exit(2);
45795
+ }
45796
+ const rawKey = arg.slice(0, eq);
45797
+ const key = FIELD_ALIASES[rawKey] || rawKey;
45798
+ const raw = arg.slice(eq + 1);
45799
+ try {
45800
+ return [key, JSON.parse(raw)];
45801
+ } catch {
45802
+ return [key, raw];
45803
+ }
45804
+ }
45805
+ function resolveAgent(agents, query) {
45806
+ const byId = agents.find((a) => getItemId(a) === query);
45807
+ if (byId)
45808
+ return byId;
45809
+ const q = query.toLowerCase();
45810
+ const exact = agents.filter((a) => getDisplayName(a).toLowerCase() === q);
45811
+ if (exact.length === 1)
45812
+ return exact[0];
45813
+ const partial = agents.filter((a) => getDisplayName(a).toLowerCase().includes(q));
45814
+ if (partial.length === 1)
45815
+ return partial[0];
45816
+ if (partial.length > 1) {
45817
+ process.stderr.write(`${RED}Ambiguous agent '${query}', matches:${RESET}
45818
+ `);
45819
+ for (const a of partial)
45820
+ process.stderr.write(` ${getDisplayName(a)} ${DIM}${getItemId(a)}${RESET}
45821
+ `);
45822
+ process.exit(2);
45823
+ }
45824
+ process.stderr.write(`${RED}No agent matching '${query}'${RESET}
45825
+ `);
45826
+ process.exit(2);
45827
+ }
45828
+ async function agentCommand(api, positionals, args, formatPath) {
45829
+ const sub = positionals[1];
45830
+ if (!sub || sub === "list" || sub === "ls") {
45831
+ await listAgentsCommand(api, { json: !!args.json, formatPath });
45832
+ return;
45833
+ }
45834
+ if (sub === "get") {
45835
+ const agents = await api.listAgentSettings();
45836
+ const agent = resolveAgent(agents, positionals[2] || "");
45837
+ if (args.json) {
45838
+ console.log(JSON.stringify(agent, null, 2));
45839
+ return;
45840
+ }
45841
+ process.stderr.write(`${BRAND}${getDisplayName(agent)}${RESET} ${DIM}${getItemId(agent)}${RESET}
45842
+ `);
45843
+ process.stderr.write(` ${DIM}model:${RESET} ${CYAN}${agent.model || "(default)"}${RESET}
45844
+ `);
45845
+ const paths = getAgentWorkspacePaths(agent).map(formatPath);
45846
+ if (paths.length)
45847
+ process.stderr.write(` ${DIM}paths:${RESET} ${paths.join(", ")}
45848
+ `);
45849
+ return;
45850
+ }
45851
+ if (sub === "update") {
45852
+ const query = positionals[2];
45853
+ const assignments = positionals.slice(3);
45854
+ if (!query || !assignments.length) {
45855
+ process.stderr.write(`${RED}Usage: todoai agent update <name|id> <field=value>\u2026${RESET}
45856
+ `);
45857
+ process.exit(2);
45858
+ }
45859
+ const updates = Object.fromEntries(assignments.map(parseAssignment));
45860
+ const agents = await api.listAgentSettings();
45861
+ const agent = resolveAgent(agents, query);
45862
+ const id = getItemId(agent);
45863
+ const updated = await api.updateAgentSettings(id, id, updates);
45864
+ if (args.json) {
45865
+ console.log(JSON.stringify(updated, null, 2));
45866
+ return;
45867
+ }
45868
+ const summary = Object.keys(updates).map((k) => `${k}=${JSON.stringify(updated[k])}`).join(" ");
45869
+ process.stderr.write(`${GREEN}\u2705 ${getDisplayName(agent)} updated: ${summary}${RESET}
45870
+ `);
45871
+ return;
45872
+ }
45873
+ process.stderr.write(`${RED}Unknown 'agent' subcommand: ${sub}${RESET}
45874
+ `);
45875
+ printAgentHelp();
45876
+ process.exit(2);
45877
+ }
45878
+
45879
+ // src/list-todos.ts
45880
+ import { parseArgs as parseArgs2 } from "util";
45881
+ var STATUS_COLOR = {
45882
+ DONE: GREEN,
45883
+ READY: GREEN,
45884
+ READY_CHECKED: GREEN,
45885
+ ERROR: RED,
45886
+ ERROR_CHECKED: RED,
45887
+ CANCELLED: RED,
45888
+ CANCELLED_CHECKED: RED,
45889
+ RUNNING: YELLOW,
45890
+ STOPPING: YELLOW,
45891
+ COMPACTING: YELLOW,
45892
+ REVIEW_REQUESTED: YELLOW,
45893
+ TODO: CYAN,
45894
+ SCHEDULED: CYAN,
45895
+ POSTPONED: CYAN,
45896
+ PAUSED: CYAN
45897
+ };
45898
+ var CLOSED = new Set([
45899
+ "DONE",
45900
+ "READY_CHECKED",
45901
+ "CANCELLED",
45902
+ "CANCELLED_CHECKED",
45903
+ "ERROR_CHECKED",
45904
+ "ARCHIVED",
45905
+ "DELETED"
45906
+ ]);
45907
+ var VALID_STATUS = new Set(Object.values(TodoStatus));
45908
+ var isOpen = (s) => !CLOSED.has(s);
45909
+ function printHelp() {
45910
+ process.stderr.write(`
45911
+ todoai list \u2014 list todos in a project (recent first)
45912
+
45913
+ Usage:
45914
+ todoai list [flags]
45915
+
45916
+ Flags:
45917
+ -n, --limit <n> Max rows to show (default: 30)
45918
+ -s, --status <S[,S2]> Filter by status (comma-separated, union).
45919
+ -A, --all Include DONE (also CANCELLED, ARCHIVED, \u2026)
45920
+ --project <id> Project ID (default: current default project)
45921
+ --json Output raw JSON
45922
+ -h, --help Show this help
45923
+
45924
+ Examples:
45925
+ todoai list # 30 most recent open todos
45926
+ todoai list -n 50 # last 50 open
45927
+ todoai list --all # include DONE
45928
+ todoai list -s RUNNING,REVIEW_REQUESTED
45929
+ todoai list --json | jq '.[].id'
45930
+ `);
45931
+ }
45932
+ async function listTodosCommand(api, defaultProjectId, argv) {
45933
+ const { values } = parseArgs2({
45934
+ args: argv,
45935
+ options: {
45936
+ limit: { type: "string", short: "n" },
45937
+ status: { type: "string", short: "s" },
45938
+ all: { type: "boolean", short: "A", default: false },
45939
+ project: { type: "string" },
45940
+ json: { type: "boolean", default: false },
45941
+ help: { type: "boolean", short: "h", default: false }
45942
+ },
45943
+ strict: true
45944
+ });
45945
+ if (values.help) {
45946
+ printHelp();
45947
+ return;
45948
+ }
45949
+ const projectId = values.project || defaultProjectId;
45950
+ if (!projectId) {
45951
+ process.stderr.write(`${RED}Error: no project (pass --project <id> or set a default)${RESET}
45952
+ `);
45953
+ process.exit(1);
45954
+ }
45955
+ const limit = values.limit ? Math.max(1, Number(values.limit)) : 30;
45956
+ const requested = values.status ? String(values.status).split(",").map((s) => s.trim().toUpperCase()).filter(Boolean) : null;
45957
+ const wantOpen = !!requested?.some((s) => s === "OPEN" || !VALID_STATUS.has(s));
45958
+ const wanted = requested ? new Set(requested.filter((s) => VALID_STATUS.has(s))) : null;
45959
+ const includeClosed = !!values.all || !!wanted && wanted.size > 0;
45960
+ const todos = await api.listTodos(projectId);
45961
+ let rows = todos.filter((t) => includeClosed || !CLOSED.has(String(t.status).toUpperCase())).filter((t) => {
45962
+ if (!requested)
45963
+ return true;
45964
+ const s = String(t.status).toUpperCase();
45965
+ return wantOpen && isOpen(s) || (wanted?.has(s) ?? false);
45966
+ }).sort((a, b) => (b.lastActivityAt ?? b.createdAt ?? 0) - (a.lastActivityAt ?? a.createdAt ?? 0)).slice(0, limit);
45967
+ if (values.json) {
45968
+ process.stdout.write(JSON.stringify(rows, null, 2) + `
45969
+ `);
45970
+ return;
45971
+ }
45972
+ if (!rows.length) {
45973
+ process.stderr.write(`${DIM}(no todos)${RESET}
45974
+ `);
45975
+ return;
45976
+ }
45977
+ const statusW = rows.reduce((n, r) => Math.max(n, String(r.status).length), 0);
45978
+ for (const t of rows) {
45979
+ const sc = STATUS_COLOR[t.status] || DIM;
45980
+ const ts = new Date(t.lastActivityAt ?? t.createdAt).toISOString().slice(0, 16).replace("T", " ");
45981
+ const title = String(t.content ?? "").split(`
45982
+ `)[0].slice(0, 100);
45983
+ process.stdout.write(`${sc}${String(t.status).padEnd(statusW)}${RESET} ${DIM}${ts}${RESET} ${t.id} ${title}
45984
+ `);
45985
+ }
45986
+ process.stderr.write(`${DIM}${rows.length} todo(s)${RESET}
45987
+ `);
45988
+ }
45989
+
45031
45990
  // src/ensure-edge.ts
45032
45991
  import { spawn, spawnSync } from "child_process";
45033
45992
  import fs2 from "fs";
@@ -45171,7 +46130,15 @@ Cancelled by user (Ctrl+C)
45171
46130
  console.log(VERSION);
45172
46131
  process.exit(0);
45173
46132
  }
45174
- if (args.help) {
46133
+ if (positionals[0] === "status" && args.help) {
46134
+ printStatusHelp();
46135
+ process.exit(0);
46136
+ }
46137
+ if (positionals[0] === "agent" && args.help) {
46138
+ printAgentHelp();
46139
+ process.exit(0);
46140
+ }
46141
+ if (args.help && !["list", "ls", "agent"].includes(positionals[0])) {
45175
46142
  printUsage();
45176
46143
  process.exit(0);
45177
46144
  }
@@ -45194,7 +46161,7 @@ Cancelled by user (Ctrl+C)
45194
46161
  const cfgScope = cfg.scope(apiUrl);
45195
46162
  async function deviceLogin() {
45196
46163
  const loginApi = new ApiClient(apiUrl, "");
45197
- const { code, url, expiresIn } = await loginApi.initDeviceLogin("cli");
46164
+ const { code, url, expiresIn } = await loginApi.initDeviceLogin("edge");
45198
46165
  const userCode = new URL(url).searchParams.get("user_code") || code.slice(-8).toUpperCase();
45199
46166
  const formattedCode = userCode.length === 8 ? `${userCode.slice(0, 4)}-${userCode.slice(4)}` : userCode;
45200
46167
  process.stderr.write(`
@@ -45247,26 +46214,100 @@ Cancelled by user (Ctrl+C)
45247
46214
  await deviceLogin();
45248
46215
  return;
45249
46216
  }
45250
- let apiKey = args["api-key"] || getEnv("API_TOKEN") || getEnv("API_KEY") || readCredential(apiUrl) || "";
46217
+ let apiKey = args["api-key"] || readCredential(apiUrl) || getEnv("API_TOKEN") || "";
45251
46218
  if (!apiKey) {
45252
46219
  apiKey = await deviceLogin();
45253
46220
  }
45254
46221
  const api = new ApiClient(apiUrl, apiKey);
46222
+ if (positionals[0] === "status") {
46223
+ const [, todoId, status] = positionals;
46224
+ if (!todoId || !status) {
46225
+ printStatusHelp();
46226
+ process.exit(2);
46227
+ }
46228
+ await api.updateTodoStatus(todoId, status);
46229
+ process.stderr.write(`${GREEN}\u2705 Status of ${todoId} set to ${status}${RESET}
46230
+ `);
46231
+ return;
46232
+ }
46233
+ if (positionals[0] === "delete") {
46234
+ const todoId = positionals[1];
46235
+ if (!todoId) {
46236
+ process.stderr.write(`${RED}Usage: todoai delete <todo-id>${RESET}
46237
+ `);
46238
+ process.exit(2);
46239
+ }
46240
+ await api.deleteTodo(todoId);
46241
+ process.stderr.write(`${GREEN}\u2705 Deleted ${todoId}${RESET}
46242
+ `);
46243
+ return;
46244
+ }
46245
+ if (positionals[0] === "addmessage") {
46246
+ const [, todoId, ...rest] = positionals;
46247
+ const content2 = rest.join(" ") || await readStdin();
46248
+ if (!todoId || !content2) {
46249
+ process.stderr.write(`${RED}Usage: todoai addmessage <todo-id> "content"${RESET}
46250
+ `);
46251
+ process.exit(2);
46252
+ }
46253
+ const todo2 = await api.getTodo(todoId);
46254
+ const msg = await api.addMessage(todo2.projectId, content2, todo2.agentSettings || { id: todo2.agentSettingsId }, todoId);
46255
+ if (args.json)
46256
+ console.log(JSON.stringify(msg, null, 2));
46257
+ else
46258
+ process.stderr.write(`${GREEN}\u2705 Message added to ${todoId}${RESET}
46259
+ `);
46260
+ return;
46261
+ }
45255
46262
  if (args["list-agents"]) {
45256
46263
  await listAgentsCommand(api, { json: !!args.json, formatPath: formatPathWithTilde });
45257
46264
  return;
45258
46265
  }
46266
+ if (positionals[0] === "agent") {
46267
+ await agentCommand(api, positionals, args, formatPathWithTilde);
46268
+ return;
46269
+ }
46270
+ if (positionals[0] === "list" || positionals[0] === "ls") {
46271
+ let defaultProjectId = args.project || cfgScope.data.default_project_id;
46272
+ if (!defaultProjectId) {
46273
+ const projects2 = await api.listProjects();
46274
+ defaultProjectId = projects2.find((p) => p.project?.isDefault)?.project?.id || projects2[0]?.project?.id;
46275
+ }
46276
+ const sub = process.argv.slice(process.argv.indexOf(positionals[0]) + 1);
46277
+ await listTodosCommand(api, defaultProjectId ?? undefined, sub);
46278
+ return;
46279
+ }
45259
46280
  if (args.inspect !== undefined) {
45260
46281
  const raw = String(args.inspect);
45261
- const [rawTodoId, untilMessageId] = raw.includes(":") ? raw.split(":", 2) : [raw, undefined];
45262
- const todoId = rawTodoId || getEnv("TODO_ID");
46282
+ const at = raw.indexOf("@");
46283
+ const todoId = at < 0 ? raw : raw.slice(0, at);
46284
+ const slice = at < 0 ? undefined : raw.slice(at + 1);
45263
46285
  if (!todoId) {
45264
- process.stderr.write(`${RED}Error: --inspect requires a todoId (or $TODOFORAI_TODO_ID env var)${RESET}
46286
+ process.stderr.write(`${RED}Error: --inspect requires a todoId${RESET}
45265
46287
  `);
45266
46288
  process.exit(2);
45267
46289
  }
45268
46290
  const todo2 = await api.getTodo(todoId);
45269
- printFullChat(todo2, getFrontendUrl(apiUrl, todo2.projectId, todoId), untilMessageId || undefined);
46291
+ if (args.json) {
46292
+ let messages = todo2.messages || [];
46293
+ if (slice) {
46294
+ try {
46295
+ messages = applySlice(messages, slice);
46296
+ } catch (e) {
46297
+ process.stderr.write(`${RED}${e.message}${RESET}
46298
+ `);
46299
+ process.exit(2);
46300
+ }
46301
+ }
46302
+ const mode2 = args.debug ? "debug" : args.detailed ? "detailed" : "default";
46303
+ const format2 = args["format-anthropic"] ? "anthropic" : "compact";
46304
+ process.stdout.write(JSON.stringify(toAnthropicShape(messages, mode2, format2), null, 2) + `
46305
+ `);
46306
+ return;
46307
+ }
46308
+ const mode = args.debug ? "debug" : args.detailed ? "detailed" : "default";
46309
+ const format = args["format-anthropic"] ? "anthropic" : "compact";
46310
+ printFullChat(todo2, getFrontendUrl(apiUrl, todo2.projectId, todoId), slice, mode, format);
45270
46311
  return;
45271
46312
  }
45272
46313
  if (process.stderr.isTTY)
@@ -45370,7 +46411,7 @@ ${"\u2500".repeat(40)}
45370
46411
  }
45371
46412
  const todo2 = await api.getTodo(todoId);
45372
46413
  const projectId2 = todo2.projectId;
45373
- const agent2 = todo2.agentSettings || { name: "default" };
46414
+ const agent2 = todo2.agentSettings || await api.getAgentSettings(todo2.agentSettingsId);
45374
46415
  for (const msg of todo2.messages || []) {
45375
46416
  const role = msg.role === "user" ? `${CYAN}You${RESET}` : `${GREEN}AI${RESET}`;
45376
46417
  process.stderr.write(`${role}: ${(msg.content || "").slice(0, 200)}
@@ -45378,11 +46419,20 @@ ${"\u2500".repeat(40)}
45378
46419
  }
45379
46420
  process.stderr.write(`
45380
46421
  ${"\u2500".repeat(40)}
45381
- Resumed todo: ${todoId}
46422
+ Resumed: ${CYAN}${getFrontendUrl(apiUrl, projectId2, todoId)}${RESET}
45382
46423
  `);
45383
46424
  const ws2 = new FrontendWebSocket(apiUrl, apiKey);
45384
46425
  await ws2.connect();
45385
- await interactiveLoop(ws2, api, todoId, projectId2, agent2, !!args.json, false, cfg);
46426
+ const autoApprove = !!args["dangerously-skip-permissions"];
46427
+ const followUp = positionals.length > 0 ? positionals.join(" ") : process.stdin.isTTY ? "" : await readStdin();
46428
+ if (followUp) {
46429
+ cfg.addToHistory(followUp);
46430
+ await api.addMessage(projectId2, followUp, agent2, todoId);
46431
+ await watchTodo(ws2, todoId, projectId2, { json: !!args.json, autoApprove, agentSettings: agent2 });
46432
+ }
46433
+ if (!args["non-interactive"]) {
46434
+ await interactiveLoop(ws2, api, todoId, projectId2, agent2, !!args.json, autoApprove, cfg);
46435
+ }
45386
46436
  await ws2.close();
45387
46437
  return;
45388
46438
  }