@bud.sh/app 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +41 -31
  2. package/dist/client/assets/bud/design.js +1 -1
  3. package/dist/client/assets/canvas-Bih9EdKJ.js +1 -0
  4. package/dist/client/assets/difference-worker-Bzg-rizy.js +8 -0
  5. package/dist/client/assets/dist-CdE5wBkg.js +5 -0
  6. package/dist/client/assets/files-1dLuoM2f.js +1 -0
  7. package/dist/client/assets/i18n-CkO6VFI0.js +1 -0
  8. package/dist/client/assets/index-Cn2mxroU.css +2 -0
  9. package/dist/client/assets/{index-ChANGtl-.js → index-DtISWZp9.js} +2 -2
  10. package/dist/client/assets/pages-BJ-tNJ4J.js +1 -0
  11. package/dist/client/assets/{project-branches-DO897zM6.js → project-branches-Ce3rXrkc.js} +1 -1
  12. package/dist/client/assets/project-comments-CPUONfs8.js +1 -0
  13. package/dist/client/assets/project-thread-links-C-TGkq59.js +1 -0
  14. package/dist/client/assets/{project-threads-Lay351p4.js → project-threads-Bv7IDBgi.js} +105 -105
  15. package/dist/client/assets/project-work-DAE9-olg.js +1 -0
  16. package/dist/client/assets/{task-design-Avb2RO4w.js → task-design-CwySIAOl.js} +3 -3
  17. package/dist/client/assets/tasks-KWsCLi_h.js +3 -0
  18. package/dist/client/assets/wasm-inline-DSUyFn1L.js +1 -0
  19. package/dist/client/assets/workspace-CVdcfaaB.js +2 -0
  20. package/dist/client/index.html +3 -3
  21. package/dist/hosted/assets/{canvas-V36732ER.js → canvas-AII16n9i.js} +97 -6
  22. package/dist/hosted/assets/{comment-data-CF2ZV_3k.js → comment-data-BXfMElfx.js} +2004 -402
  23. package/dist/hosted/assets/dist-BCSTeNf4.js +4785 -0
  24. package/dist/hosted/assets/{files-DjSCjfU7.js → files-D_1yeAVO.js} +10 -5
  25. package/dist/hosted/assets/{pages-BzjzeuPu.js → pages-CN_SbKWA.js} +3 -3
  26. package/dist/hosted/assets/{project-branches-BT97J9i7.js → project-branches-Bxp0DCwg.js} +1 -1
  27. package/dist/hosted/assets/{project-thread-links-BRLgByEe.js → project-thread-links-KqQoKBLE.js} +76 -4
  28. package/dist/{node-host/assets/screen-CZXWJEds.js → hosted/assets/screen-DpAcDUKR.js} +29 -1
  29. package/dist/hosted/assets/tasks-D66LlwxM.js +1423 -0
  30. package/dist/hosted/assets/wasm-inline-Dl9tqabx.js +4 -0
  31. package/dist/hosted/hosted.js +7885 -6219
  32. package/dist/node/assets/Stream-CAm1eJ2n.js +16604 -0
  33. package/dist/{server/assets/bridge-B_Blt55E.js → node/assets/bridge-DQSBYHmw.js} +124 -290
  34. package/dist/node/assets/config-9_jWwNBh.js +1067 -0
  35. package/dist/node/assets/load-config.server-CMVtRVmO.js +261 -0
  36. package/dist/node/assets/module-3GgtT4Xs.js +308 -0
  37. package/dist/node/assets/server-DTQFuoX2.js +846 -0
  38. package/dist/node/assets/src-D-kG1GxB.js +2 -0
  39. package/dist/node/assets/{src-CerrKjID.js → src-Dwe9APUx.js} +93 -3
  40. package/dist/node/assets/src-DysjfbM8.js +8592 -0
  41. package/dist/node/bridge.js +1 -845
  42. package/dist/node/cli.js +206 -0
  43. package/dist/node/design.js +811 -13
  44. package/dist/node/index.js +2 -739
  45. package/dist/node/plugins.js +5711 -0
  46. package/dist/node/server.js +1 -6746
  47. package/dist/node/vite.js +121 -0
  48. package/dist/{server/assets/canvas-Dc1mYCwQ.js → node-host/assets/canvas-BeDoufy1.js} +97 -7
  49. package/dist/node-host/assets/{comment-data-DyIZNpfG.js → comment-data-DE2T9yTj.js} +1980 -376
  50. package/dist/node-host/assets/dist-BCSTeNf4.js +4785 -0
  51. package/dist/node-host/assets/{files-Dh2TiQZq.js → files-Dl-PTS09.js} +11 -6
  52. package/dist/node-host/assets/{pages-BxpjbYhs.js → pages-DL2sk6_U.js} +3 -3
  53. package/dist/node-host/assets/{project-branches-B7HUGiVK.js → project-branches-DGp5ELct.js} +1 -1
  54. package/dist/{server/assets/project-thread-links-CBOpf6zk.js → node-host/assets/project-thread-links-CgBV3Jcm.js} +76 -5
  55. package/dist/{hosted/assets/screen-CKp2C7kx.js → node-host/assets/screen-B55yyVfb.js} +29 -1
  56. package/dist/node-host/assets/tasks-DZRNkoxe.js +1425 -0
  57. package/dist/node-host/assets/wasm-inline-Dl9tqabx.js +4 -0
  58. package/dist/node-host/node-host.js +6127 -4438
  59. package/dist/server/assets/{branch-previews-ClkoJ0lM.js → branch-previews-DedrpnVR.js} +1555 -673
  60. package/dist/{node-host/assets/canvas-TRUfxfL5.js → server/assets/canvas-CJWQ-jjv.js} +98 -6
  61. package/dist/server/assets/{comment-data-CsjukwAW.js → comment-data-Rg42ToTW.js} +1666 -47
  62. package/dist/server/assets/dist-BCSTeNf4.js +4785 -0
  63. package/dist/server/assets/{events-iHpLGr3k.js → events-BH_rAu7O.js} +155 -20
  64. package/dist/server/assets/{files-E9mSFeoc.js → files-CPJqKeMo.js} +12 -7
  65. package/dist/server/assets/{listener-DN5TyOjJ.js → listener-D61O6PzF.js} +708 -12
  66. package/dist/server/assets/{pages-BBBXyJWV.js → pages-KJY_Ba92.js} +4 -4
  67. package/dist/server/assets/{project-branches-B0YIK6Ur.js → project-branches-qG9ACZvo.js} +2 -2
  68. package/dist/{node-host/assets/project-thread-links-CauJF0Cz.js → server/assets/project-thread-links-CqK0lqCF.js} +77 -4
  69. package/dist/{node-host/assets/tasks-request-ZWmbc8fE.js → server/assets/project-work-DoIwxWMm.js} +87 -2
  70. package/dist/server/assets/run-BJ8r5jSh.js +572 -0
  71. package/dist/server/assets/{screen-BIQA2mr4.js → screen-CBrHPFug.js} +30 -2
  72. package/dist/server/assets/{server-DxK-UB_Z.js → server-Dkbp5stG.js} +1521 -793
  73. package/dist/server/assets/{services-BRrgXYlT.js → services-BTfig8A8.js} +234 -997
  74. package/dist/server/assets/tasks-Bgu5Lg9Y.js +1427 -0
  75. package/dist/server/assets/wasm-inline-Dl9tqabx.js +4 -0
  76. package/dist/server/capture.js +1 -2
  77. package/dist/server/migration.js +569 -12
  78. package/dist/server/runtime.js +7 -5
  79. package/dist/server/server.js +3 -3
  80. package/dist/types/assets/{config-DIC2cf_S.d.ts → config-CvcYmE2s.d.ts} +188 -50
  81. package/dist/types/assets/{contract-CAT-XFNq.d.ts → contract-B7yuuqSn.d.ts} +44 -2
  82. package/dist/types/assets/{items-CaVkByHk.d.ts → items-BQdaVksf.d.ts} +12 -1
  83. package/dist/types/assets/memory-state-BBW-FAVA.d.ts +236 -0
  84. package/dist/types/assets/picker-Be5Gx4WR.d.ts +9 -0
  85. package/dist/types/assets/{task-design-xJOhRNWh.d.ts → task-design-BDHKFHpp.d.ts} +3 -1
  86. package/dist/types/bridge.d.ts +1 -1
  87. package/dist/types/companion.d.ts +3 -3
  88. package/dist/types/design.d.ts +2 -2
  89. package/dist/types/hosted.d.ts +3 -3
  90. package/dist/types/index.d.ts +2 -2
  91. package/dist/types/node-host.d.ts +2 -2
  92. package/dist/types/plugins.d.ts +445 -0
  93. package/dist/types/screen.d.ts +2 -2
  94. package/dist/types/server.d.ts +2 -228
  95. package/dist/types/vite.d.ts +16 -0
  96. package/package.json +19 -3
  97. package/dist/client/assets/canvas-Cu6R6xxT.js +0 -1
  98. package/dist/client/assets/difference-worker-jfTSn-Tw.js +0 -8
  99. package/dist/client/assets/files-js6ElfkU.js +0 -1
  100. package/dist/client/assets/i18n-DxqFr2mi.js +0 -1
  101. package/dist/client/assets/index-CFFxP0gS.css +0 -2
  102. package/dist/client/assets/pages-6_lhiQmz.js +0 -1
  103. package/dist/client/assets/project-comments-DFFKVpia.js +0 -1
  104. package/dist/client/assets/project-thread-links-NLFWQRD2.js +0 -1
  105. package/dist/client/assets/project-work-du0Y-L5Y.js +0 -1
  106. package/dist/client/assets/tasks-CA-E8bbK.js +0 -1
  107. package/dist/client/assets/tasks-request-C55IeuiP.js +0 -1
  108. package/dist/client/assets/workspace-Cw5HvX5d.js +0 -2
  109. package/dist/hosted/assets/tasks-Dj7AyBJB.js +0 -649
  110. package/dist/hosted/assets/tasks-request-DZob623r.js +0 -113
  111. package/dist/node-host/assets/tasks-Bs1IOpeU.js +0 -651
  112. package/dist/server/assets/project-work-qSKFO5yj.js +0 -88
  113. package/dist/server/assets/tasks-CiXodsLN.js +0 -652
  114. package/dist/server/assets/tasks-request-DhwCzpRi.js +0 -115
  115. package/dist/types/assets/picker-D1Bw3ndx.d.ts +0 -14
@@ -803,7 +803,7 @@ function matches$2(pattern) {
803
803
  * @param maximum - The longest length allowed.
804
804
  * @returns The string schema.
805
805
  */
806
- function text$8(maximum = 6e4) {
806
+ function text$7(maximum = 6e4) {
807
807
  return string$2().pipe(maxLength(maximum), noNul$2);
808
808
  }
809
809
  /**
@@ -812,7 +812,7 @@ function text$8(maximum = 6e4) {
812
812
  * @returns The string schema.
813
813
  */
814
814
  function nonempty(maximum = 512) {
815
- return text$8(maximum).refine((value) => !!value.trim());
815
+ return text$7(maximum).refine((value) => !!value.trim());
816
816
  }
817
817
  var identifier$1 = nonempty().pipe(matches$2(/^[a-zA-Z0-9][a-zA-Z0-9._:-]*$/), { check: (value) => !reserved$1.includes(value) });
818
818
  /**
@@ -832,9 +832,9 @@ function number$1(minimum = -Number.MAX_SAFE_INTEGER, maximum = Number.MAX_SAFE_
832
832
  function integer$2(maximum = Number.MAX_SAFE_INTEGER) {
833
833
  return number$1(0, maximum).pipe(safeInteger$2);
834
834
  }
835
- var timestamp$2 = text$8(64).pipe(matches$2(/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?(?:Z|[+-]\d\d:\d\d)$/)).refine((value) => Number.isFinite(Date.parse(value)));
836
- var date$1 = text$8(10).pipe(matches$2(/^\d{4}-\d\d-\d\d$/)).refine((value) => Number.isFinite(Date.parse(value)) && new Date(value).toISOString().slice(0, 10) === value);
837
- var revision$2 = nullable(nonempty(256));
835
+ var timestamp$2 = text$7(64).pipe(matches$2(/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?(?:Z|[+-]\d\d:\d\d)$/)).refine((value) => Number.isFinite(Date.parse(value)));
836
+ var date$1 = text$7(10).pipe(matches$2(/^\d{4}-\d\d-\d\d$/)).refine((value) => Number.isFinite(Date.parse(value)) && new Date(value).toISOString().slice(0, 10) === value);
837
+ var revision$1 = nullable(nonempty(256));
838
838
  var InvalidJson = class {
839
839
  path;
840
840
  constructor(path) {
@@ -1066,7 +1066,7 @@ function statusCategory(schema, value) {
1066
1066
  var MessageAuthorSchema = field("author", strict$2({
1067
1067
  id: nonempty(256),
1068
1068
  name: nonempty(1e3),
1069
- email: text$8(1e3)
1069
+ email: text$7(1e3)
1070
1070
  }));
1071
1071
  /** A message returned by storage, never a browser write request. */
1072
1072
  var MessageSchema = field("message", strict$2({
@@ -1149,11 +1149,11 @@ function cached(schema, key, build) {
1149
1149
  var PersonSchema = strict$2({
1150
1150
  id: nonempty(),
1151
1151
  name: nonempty(),
1152
- email: optional(text$8(1e3))
1152
+ email: optional(text$7(1e3))
1153
1153
  });
1154
1154
  var itemRefShape = strict$2({
1155
1155
  id: identifier$1,
1156
- title: optional(text$8(1e3)),
1156
+ title: optional(text$7(1e3)),
1157
1157
  status: optional(identifier$1),
1158
1158
  type: optional(identifier$1),
1159
1159
  priority: optional(number$1())
@@ -1170,14 +1170,14 @@ function webUrl(value) {
1170
1170
  }
1171
1171
  function kindSchema(field, schema) {
1172
1172
  switch (field.kind) {
1173
- case "text": return field.required ? nonempty(6e4) : text$8();
1174
- case "markdown": return text$8();
1173
+ case "text": return field.required ? nonempty(6e4) : text$7();
1174
+ case "markdown": return text$7();
1175
1175
  case "number": return number$1();
1176
1176
  case "duration": return number$1(0);
1177
1177
  case "boolean": return boolean$1();
1178
1178
  case "date": return date$1;
1179
1179
  case "datetime": return timestamp$2;
1180
- case "url": return text$8(4096).refine((url) => !url && !field.required || webUrl(url));
1180
+ case "url": return text$7(4096).refine((url) => !url && !field.required || webUrl(url));
1181
1181
  case "person": return PersonSchema;
1182
1182
  case "people": return uniqueList(PersonSchema, 100, (person) => person.id);
1183
1183
  case "labels": return uniqueList(nonempty(128), 100, (label) => label);
@@ -1233,6 +1233,25 @@ var counts = verify(both(record, record$1(enum_([
1233
1233
  "incoming"
1234
1234
  ]), integer$2())), (counts) => counts.children !== void 0 && counts.childrenDone !== void 0 && counts.childrenDone > counts.children ? ["childrenDone"] : void 0);
1235
1235
  /**
1236
+ * Summarizes the run record an adapter keeps on an item (`budRun`) for its board badge.
1237
+ * @param value - The stored record; anything else gives no summary.
1238
+ * @returns The run's state and error, or undefined without a readable run.
1239
+ */
1240
+ function workRunSummary(value) {
1241
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
1242
+ let { state, error } = value;
1243
+ if (typeof state !== "string" || !/^[a-z_]{1,32}$/.test(state)) return void 0;
1244
+ let message = error && typeof error === "object" && typeof error.message === "string" ? error.message.slice(0, 500) : null;
1245
+ return value.asleep === true ? {
1246
+ state,
1247
+ error: message,
1248
+ asleep: true
1249
+ } : {
1250
+ state,
1251
+ error: message
1252
+ };
1253
+ }
1254
+ /**
1236
1255
  * Creates the schema for an adapter item against its current schema.
1237
1256
  * @param schema - Its adapter's validated field and relation declarations.
1238
1257
  * @returns The schema for a complete or explicitly brief item.
@@ -1246,12 +1265,17 @@ function createWorkItemSchema(schema) {
1246
1265
  });
1247
1266
  let item = (mode) => strict$2({
1248
1267
  id: identifier$1,
1249
- revision: revision$2,
1268
+ revision: revision$1,
1250
1269
  values: field("values", valuesSchema(schema, mode)),
1251
1270
  relations: uniqueList(relation, MAX_WORK_ITEMS, (entry) => `${entry.type}:${entry.direction}:${entry.item.id}`),
1252
1271
  counts,
1253
1272
  ready: optional(boolean$1()),
1254
1273
  closeable: optional(boolean$1()),
1274
+ run: optional(strict$2({
1275
+ state: identifier$1,
1276
+ error: nullable(text$7(500)),
1277
+ asleep: optional(boolean$1())
1278
+ })),
1255
1279
  contentLoaded: boolean$1(),
1256
1280
  extra: JsonSchema
1257
1281
  });
@@ -1349,8 +1373,8 @@ var WorkActivitySchema = field("activity", strict$2({
1349
1373
  ]),
1350
1374
  summary: nonempty(4e3),
1351
1375
  field: optional(identifier$1),
1352
- from: optional(nullable(text$8(4e3))),
1353
- to: optional(nullable(text$8(4e3)))
1376
+ from: optional(nullable(text$7(4e3))),
1377
+ to: optional(nullable(text$7(4e3)))
1354
1378
  }));
1355
1379
  /**
1356
1380
  * Creates the schema for a historical item snapshot; a backend may expose only its revision.
@@ -1477,7 +1501,7 @@ function createWorkMutationResultSchema(schema) {
1477
1501
  /** Optional list modifiers and a bounded result limit. */
1478
1502
  var WorkQuerySchema = field("query", strict$2({
1479
1503
  limit: defaulted(integer$2(MAX_WORK_ITEMS).refine((limit) => limit !== 0), MAX_WORK_ITEMS),
1480
- search: optional(text$8(1e3)),
1504
+ search: optional(text$7(1e3)),
1481
1505
  status: optional(identifier$1)
1482
1506
  }));
1483
1507
  var direction = enum_([
@@ -1506,16 +1530,6 @@ function parseWorkItemRef(value, field = "itemRef") {
1506
1530
  return parseWork(itemRefShape, value, field);
1507
1531
  }
1508
1532
  /**
1509
- * Validates a field value against its declared kind and options.
1510
- * @param value - Untrusted data from a request, adapter or response.
1511
- * @param field - The field declaration whose kind and options apply.
1512
- * @param schema - The adapter’s validated schema.
1513
- * @returns The validated value for the declared field kind.
1514
- */
1515
- function parseWorkValue(value, field, schema) {
1516
- return parseWork(createWorkValueSchema(field, schema), value, `values.${field.id}`);
1517
- }
1518
- /**
1519
1533
  * Validates an adapter item against its current schema.
1520
1534
  * @param value - The untrusted record.
1521
1535
  * @param schema - Its adapter's validated field and relation declarations.
@@ -1698,7 +1712,7 @@ var ElementAnchorSchema = strict$2({
1698
1712
  contentHash: nonempty(128),
1699
1713
  label: nonempty(500),
1700
1714
  tagName: nonempty(100),
1701
- text: text$8(1e3),
1715
+ text: text$7(1e3),
1702
1716
  offsetX: number$1(0, 1),
1703
1717
  offsetY: number$1(0, 1),
1704
1718
  block: optional(nullable(ElementBlockSchema)),
@@ -1861,7 +1875,7 @@ function keyed(keys, schema) {
1861
1875
  * @param requireWellFormed - Whether lone surrogates are rejected.
1862
1876
  * @returns The string schema.
1863
1877
  */
1864
- function text$7(maximum = 4096, requireWellFormed = false) {
1878
+ function text$6(maximum = 4096, requireWellFormed = false) {
1865
1879
  let checks = [maxLength(maximum), noNul$1];
1866
1880
  if (requireWellFormed) checks.push(wellFormed);
1867
1881
  return string$2().pipe(...checks);
@@ -1896,9 +1910,9 @@ function list$5(item, maximum, minimum = 0, message = "Expected a bounded list."
1896
1910
  function unique$1(values, key) {
1897
1911
  return new Set(values.map(key)).size === values.length;
1898
1912
  }
1899
- var revision$1 = described$2(string$2().pipe(matches$1(/^[a-f0-9]{64}$/)), "Expected a complete content revision.");
1913
+ var revision = described$2(string$2().pipe(matches$1(/^[a-f0-9]{64}$/)), "Expected a complete content revision.");
1900
1914
  var identifier = described$2(string$2().pipe(matches$1(/^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/)), "Invalid identifier.");
1901
- var timestamp$1 = text$7(30).refine((value) => Number.isFinite(Date.parse(value)) && new Date(value).toISOString() === value, "Invalid timestamp.");
1915
+ var timestamp$1 = text$6(30).refine((value) => Number.isFinite(Date.parse(value)) && new Date(value).toISOString() === value, "Invalid timestamp.");
1902
1916
  //#endregion
1903
1917
  //#region ../files/src/lib/paths.ts
1904
1918
  var reserved = /* @__PURE__ */ new Set([
@@ -2000,7 +2014,7 @@ strict$1({
2000
2014
  includeIgnored: fallback(boolean$1(), false),
2001
2015
  includeDotfiles: fallback(boolean$1(), true),
2002
2016
  visibility: fallback(enum_(["all", ...visibilities]), "all"),
2003
- search: fallback(text$7(256), "")
2017
+ search: fallback(text$6(256), "")
2004
2018
  });
2005
2019
  var FileEntrySchema = strict$1({
2006
2020
  path: FilePathSchema,
@@ -2031,22 +2045,22 @@ var FileWatchStatusSchema = strict$1({
2031
2045
  }).refine((status) => status.directories <= status.limit, "Expected a bounded integer.");
2032
2046
  var FileIndexSchema = strict$1({
2033
2047
  directory: FileDirectorySchema,
2034
- revision: revision$1,
2048
+ revision,
2035
2049
  entries: list$5(FileEntrySchema, 1e5).refine((entries) => unique$1(entries, (entry) => entry.path), "Duplicate file paths."),
2036
2050
  truncated: boolean$1(),
2037
2051
  maxEntries: integer$1(1e5),
2038
2052
  issues: list$5(strict$1({
2039
- path: text$7(),
2053
+ path: text$6(),
2040
2054
  code: enum_(issueCodes),
2041
- message: text$7(512)
2055
+ message: text$6(512)
2042
2056
  }), 256),
2043
2057
  git: enum_(["available", "unavailable"]),
2044
2058
  watch: FileWatchStatusSchema
2045
2059
  }).refine((index) => index.entries.length <= index.maxEntries, "Expected a bounded list.");
2046
2060
  var FileDocumentSchema = strict$1({
2047
2061
  entry: FileEntrySchema,
2048
- contents: nullable(text$7(67108864)),
2049
- revision: nullable(revision$1),
2062
+ contents: nullable(text$6(67108864)),
2063
+ revision: nullable(revision),
2050
2064
  encoding: nullable(enum_(["utf8", "utf8-bom"])),
2051
2065
  lineEnding: nullable(enum_([
2052
2066
  "lf",
@@ -2164,11 +2178,11 @@ function ordered(match) {
2164
2178
  strict$1(matchShape).refine(ordered, "Expected a bounded integer.");
2165
2179
  var FileSearchResultSchema = strict$1({
2166
2180
  query: FileSearchQuerySchema,
2167
- indexRevision: revision$1,
2181
+ indexRevision: revision,
2168
2182
  matches: list$5(strict$1({
2169
2183
  ...matchShape,
2170
2184
  path: FilePathSchema,
2171
- revision: revision$1
2185
+ revision
2172
2186
  }).refine(ordered, "Expected a bounded integer."), 500, 0, "Invalid search matches."),
2173
2187
  scannedFiles: integer$1(1e5),
2174
2188
  scannedBytes: integer$1(134217728),
@@ -8700,7 +8714,7 @@ function replacementEdits(contents, pattern, replacement, expectedContents, sele
8700
8714
  }
8701
8715
  //#endregion
8702
8716
  //#region ../files/src/lib/review-parsers.ts
8703
- var oid = text$7(64).refine((value) => /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(value), "Expected a full Git object ID.");
8717
+ var oid = text$6(64).refine((value) => /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(value), "Expected a full Git object ID.");
8704
8718
  var mode = enum_([
8705
8719
  "100644",
8706
8720
  "100755",
@@ -8719,7 +8733,7 @@ var statusCodes = [
8719
8733
  "?",
8720
8734
  "!"
8721
8735
  ];
8722
- var ReviewRevisionSchema = text$7(1024).refine((input) => input === "HEAD" || /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(input) || input.startsWith("refs/") && !/[\x00-\x20\x7f~^:?*\[\\]/.test(input) && !input.includes("..") && !input.includes("@{") && !input.endsWith(".") && !input.split("/").some((part) => !part || part.startsWith(".") || part.endsWith(".lock")), "Choose HEAD, a full object ID, or a full refs/... name.");
8736
+ var ReviewRevisionSchema = text$6(1024).refine((input) => input === "HEAD" || /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(input) || input.startsWith("refs/") && !/[\x00-\x20\x7f~^:?*\[\\]/.test(input) && !input.includes("..") && !input.includes("@{") && !input.endsWith(".") && !input.split("/").some((part) => !part || part.startsWith(".") || part.endsWith(".lock")), "Choose HEAD, a full object ID, or a full refs/... name.");
8723
8737
  var noEndpoint = described$2(undefined_(), "Commit endpoints require a commit comparison.");
8724
8738
  var ReviewComparisonSchema = keyed([
8725
8739
  "mode",
@@ -8745,14 +8759,14 @@ var ReviewComparisonSchema = keyed([
8745
8759
  strict$1({
8746
8760
  comparison: ReviewComparisonSchema,
8747
8761
  path: FilePathSchema,
8748
- expectedRevision: optional(revision$1)
8762
+ expectedRevision: optional(revision)
8749
8763
  });
8750
8764
  var commit = oid.refine((value) => !/^0+$/.test(value), "Expected a nonzero commit ID.");
8751
8765
  strict$1({
8752
8766
  path: FilePathSchema,
8753
8767
  commit
8754
8768
  });
8755
- var cursor = text$7(80).refine((value) => /^(?:[a-f0-9]{40}|[a-f0-9]{64}):(?:0|[1-9]\d{0,4})$/.test(value), "Invalid history cursor.").refine((value) => Number(value.split(":")[1]) <= 1e4, "History cursor exceeds the history bound.");
8769
+ var cursor = text$6(80).refine((value) => /^(?:[a-f0-9]{40}|[a-f0-9]{64}):(?:0|[1-9]\d{0,4})$/.test(value), "Invalid history cursor.").refine((value) => Number(value.split(":")[1]) <= 1e4, "History cursor exceeds the history bound.");
8756
8770
  strict$1({
8757
8771
  path: FilePathSchema,
8758
8772
  revision: optional(ReviewRevisionSchema),
@@ -8788,7 +8802,7 @@ var ReviewRepositorySchema = strict$1({
8788
8802
  references: list$5(ReviewReferenceSchema, 1e3),
8789
8803
  status: list$5(ReviewStatusSchema, 1e4),
8790
8804
  truncated: boolean$1(),
8791
- revision: revision$1
8805
+ revision
8792
8806
  }).refine(({ available, head, branch, unborn, detached }) => unborn === (available && head === null) && detached === (available && head !== null && branch === null) && (branch === null || branch.startsWith("refs/heads/")) && (available || head === null && branch === null), "Inconsistent repository state.");
8793
8807
  var ReviewEntrySchema = strict$1({
8794
8808
  path: FilePathSchema,
@@ -8820,7 +8834,7 @@ function pinned({ comparison, base, target }) {
8820
8834
  var unpinned = "Inconsistent pinned comparison endpoints.";
8821
8835
  var ReviewSnapshotSchema = strict$1({
8822
8836
  ...endpointShape,
8823
- revision: revision$1,
8837
+ revision,
8824
8838
  entries: list$5(ReviewEntrySchema, 1e4).refine((entries) => unique$1(entries, (entry) => entry.path), "Duplicate review paths."),
8825
8839
  truncated: boolean$1()
8826
8840
  }).refine(pinned, unpinned);
@@ -8837,7 +8851,7 @@ var ReviewFileSchema = strict$1({
8837
8851
  "unavailable"
8838
8852
  ]),
8839
8853
  size: nullable(integer$1()),
8840
- contents: nullable(text$7(67108864)),
8854
+ contents: nullable(text$6(67108864)),
8841
8855
  encoding: nullable(enum_(["utf8", "utf8-bom"])),
8842
8856
  lineEnding: nullable(enum_([
8843
8857
  "lf",
@@ -8845,8 +8859,8 @@ var ReviewFileSchema = strict$1({
8845
8859
  "mixed",
8846
8860
  "none"
8847
8861
  ])),
8848
- revision: nullable(revision$1),
8849
- cacheKey: revision$1
8862
+ revision: nullable(revision),
8863
+ cacheKey: revision
8850
8864
  }).refine((file) => file.kind === "text" === (file.contents !== null && file.revision !== null && file.encoding !== null && file.lineEnding !== null), "Inconsistent review content.").refine((file) => file.kind === "text" || file.contents === null && file.encoding === null && file.lineEnding === null, "Unsupported review files cannot expose text.").refine((file) => file.kind === "symlink" === (file.mode === "120000") && file.kind === "gitlink" === (file.mode === "160000") && (file.kind === "text" || file.kind === "binary" || file.revision === null), "Inconsistent review file descriptor.");
8851
8865
  var ReviewSourceSchema = strict$1({
8852
8866
  path: FilePathSchema,
@@ -8855,8 +8869,8 @@ var ReviewSourceSchema = strict$1({
8855
8869
  }).refine(({ path, commit, file }) => !file || file.name === path && file.oid !== null && file.oid.length === commit.length, "Inconsistent immutable file source.");
8856
8870
  var ReviewDiffSchema = strict$1({
8857
8871
  ...endpointShape,
8858
- metadataRevision: revision$1,
8859
- revision: revision$1,
8872
+ metadataRevision: revision,
8873
+ revision,
8860
8874
  entry: ReviewEntrySchema,
8861
8875
  oldFile: nullable(ReviewFileSchema),
8862
8876
  newFile: nullable(ReviewFileSchema),
@@ -8870,15 +8884,15 @@ var ReviewCommitSchema = strict$1({
8870
8884
  commit: oid,
8871
8885
  parents: list$5(oid, 256),
8872
8886
  author: strict$1({
8873
- name: text$7(),
8874
- email: text$7()
8887
+ name: text$6(),
8888
+ email: text$6()
8875
8889
  }),
8876
- authoredAt: text$7(40).refine((value) => Number.isFinite(Date.parse(value)), "Invalid commit date."),
8877
- subject: text$7(65536),
8878
- message: text$7(1048576),
8890
+ authoredAt: text$6(40).refine((value) => Number.isFinite(Date.parse(value)), "Invalid commit date."),
8891
+ subject: text$6(65536),
8892
+ message: text$6(1048576),
8879
8893
  path: FilePathSchema,
8880
8894
  previousPath: optional(FilePathSchema),
8881
- change: nullable(text$7(4).refine((value) => /^[ACDMRTU](?:\d{1,3})?$/.test(value), "Invalid history change."))
8895
+ change: nullable(text$6(4).refine((value) => /^[ACDMRTU](?:\d{1,3})?$/.test(value), "Invalid history change."))
8882
8896
  });
8883
8897
  var ReviewHistorySchema = strict$1({
8884
8898
  path: FilePathSchema,
@@ -9001,7 +9015,7 @@ var FileMutationIntentSchema = keyed([
9001
9015
  "create-file": strict$1({
9002
9016
  kind: literal("create-file"),
9003
9017
  path: FilePathSchema,
9004
- contents: text$7(2097152, true)
9018
+ contents: text$6(2097152, true)
9005
9019
  }),
9006
9020
  "create-folder": strict$1({
9007
9021
  kind: literal("create-folder"),
@@ -9020,14 +9034,14 @@ var FileMutationIntentSchema = keyed([
9020
9034
  }));
9021
9035
  strict$1({
9022
9036
  id: identifier,
9023
- revision: revision$1
9037
+ revision
9024
9038
  });
9025
9039
  var itemShape = {
9026
9040
  source: nullable(FilePathSchema),
9027
9041
  destination: nullable(FilePathSchema),
9028
9042
  kind: enum_(["file", "directory"]),
9029
9043
  bytes: integer$1(),
9030
- revision: nullable(revision$1)
9044
+ revision: nullable(revision)
9031
9045
  };
9032
9046
  var endpoint = "A file action needs a source or destination.";
9033
9047
  function hasEndpoint(item) {
@@ -9036,14 +9050,14 @@ function hasEndpoint(item) {
9036
9050
  var FileMutationItemSchema = strict$1(itemShape).refine(hasEndpoint, endpoint);
9037
9051
  var FileMutationPlanSchema = strict$1({
9038
9052
  id: identifier,
9039
- revision: revision$1,
9053
+ revision,
9040
9054
  kind: enum_(kinds$1),
9041
9055
  expiresAt: timestamp$1,
9042
9056
  items: list$5(FileMutationItemSchema, 100, 1)
9043
9057
  });
9044
9058
  var FileMutationProblemSchema = strict$1({
9045
9059
  code: enum_(codes),
9046
- message: text$7(512, true),
9060
+ message: text$6(512, true),
9047
9061
  path: nullable(FilePathSchema)
9048
9062
  });
9049
9063
  var FileMutationResultSchema = strict$1({
@@ -9130,13 +9144,13 @@ var maxFileSaveBytes = 2097152;
9130
9144
  var encoder$1 = new TextEncoder();
9131
9145
  var FileSaveRequestSchema = strict$1({
9132
9146
  path: FilePathSchema,
9133
- expectedRevision: revision$1,
9147
+ expectedRevision: revision,
9134
9148
  contents: described$2(string$2().pipe(maxLength(maxFileSaveBytes)).refine((contents) => !contents.includes("\0") && contents.isWellFormed() && encoder$1.encode(contents).byteLength <= 2097152), "Save a valid UTF-8 text file of at most 2 MiB.")
9135
9149
  });
9136
9150
  var FileSaveResultSchema = strict$1({
9137
9151
  path: FilePathSchema,
9138
- previousRevision: revision$1,
9139
- revision: revision$1,
9152
+ previousRevision: revision,
9153
+ revision,
9140
9154
  bytes: integer$1(maxFileSaveBytes),
9141
9155
  status: enum_(["saved", "unchanged"]),
9142
9156
  refresh: enum_(["complete", "failed"])
@@ -9205,7 +9219,7 @@ function selectionIntent(kind) {
9205
9219
  return strict$1({
9206
9220
  kind: literal(kind),
9207
9221
  path: FilePathSchema,
9208
- expectedRevision: revision$1,
9222
+ expectedRevision: revision,
9209
9223
  selection: ReviewActionSelectionSchema
9210
9224
  });
9211
9225
  }
@@ -9223,7 +9237,7 @@ keyed([
9223
9237
  "mark-resolved": strict$1({
9224
9238
  kind: literal("mark-resolved"),
9225
9239
  path: FilePathSchema,
9226
- expectedRevision: revision$1,
9240
+ expectedRevision: revision,
9227
9241
  conflict: described$2(string$2().pipe(matches$1(conflictIdentity)).refine((conflict) => conflict !== "-|-|-"), "The original conflict stages are required.")
9228
9242
  }),
9229
9243
  undo: strict$1({
@@ -9233,11 +9247,11 @@ keyed([
9233
9247
  }));
9234
9248
  strict$1({
9235
9249
  id: identifier,
9236
- revision: revision$1
9250
+ revision
9237
9251
  });
9238
9252
  var ReviewActionPlanSchema = strict$1({
9239
9253
  id: identifier,
9240
- revision: revision$1,
9254
+ revision,
9241
9255
  kind: enum_(kinds),
9242
9256
  target,
9243
9257
  paths: paths$1,
@@ -15041,7 +15055,7 @@ var textEntitySubset = ["<", "&"];
15041
15055
  * @returns {string}
15042
15056
  * Serialized node.
15043
15057
  */
15044
- function text$6(node, _, parent, state) {
15058
+ function text$5(node, _, parent, state) {
15045
15059
  return parent && parent.type === "element" && (parent.tagName === "script" || parent.tagName === "style") ? node.value : stringifyEntities(node.value, Object.assign({}, state.settings.characterReferences, { subset: textEntitySubset }));
15046
15060
  }
15047
15061
  //#endregion
@@ -15066,7 +15080,7 @@ function text$6(node, _, parent, state) {
15066
15080
  * Serialized node.
15067
15081
  */
15068
15082
  function raw(node, index, parent, state) {
15069
- return state.settings.allowDangerousHtml ? node.value : text$6(node, index, parent, state);
15083
+ return state.settings.allowDangerousHtml ? node.value : text$5(node, index, parent, state);
15070
15084
  }
15071
15085
  //#endregion
15072
15086
  //#region ../../node_modules/.pnpm/hast-util-to-html@9.0.5/node_modules/hast-util-to-html/lib/handle/root.js
@@ -15109,7 +15123,7 @@ var handle = zwitch("type", {
15109
15123
  element,
15110
15124
  raw,
15111
15125
  root,
15112
- text: text$6
15126
+ text: text$5
15113
15127
  }
15114
15128
  });
15115
15129
  /**
@@ -37651,7 +37665,7 @@ var ThreadSchema = field("thread", verify(strict$2({
37651
37665
  messagesTruncated: boolean$1(),
37652
37666
  createdAt: timestamp$2,
37653
37667
  updatedAt: timestamp$2,
37654
- revision: revision$2,
37668
+ revision: revision$1,
37655
37669
  metadata: optional(JsonSchema)
37656
37670
  }), (thread) => {
37657
37671
  let { messages, messageCount, messagesLoaded, messagesTruncated } = thread;
@@ -37723,7 +37737,7 @@ var ThreadLinkInputSchema = field("link", verify(strict$2({
37723
37737
  /** Optional discussion filters, without a store, root or capability. */
37724
37738
  var ThreadFilterSchema = field("filter", strict$2({
37725
37739
  anchorKind: optional(enum_(["canvas", "code"])),
37726
- pagePath: optional(both(text$8(4096), field("anchor.pagePath", PagePathSchema))),
37740
+ pagePath: optional(both(text$7(4096), field("anchor.pagePath", PagePathSchema))),
37727
37741
  itemId: optional(identifier$1)
37728
37742
  }));
37729
37743
  /**
@@ -37759,14 +37773,6 @@ function parseThread(value) {
37759
37773
  return parseWork(ThreadSchema, value, "thread");
37760
37774
  }
37761
37775
  /**
37762
- * Validates which discussion operations an adapter supports.
37763
- * @param value - Untrusted data from a request, adapter or response.
37764
- * @returns The supported discussion operations.
37765
- */
37766
- function parseThreadCapabilities(value) {
37767
- return parseWork(ThreadCapabilitiesSchema, value, "capabilities");
37768
- }
37769
- /**
37770
37776
  * Validates a thread list with its availability and operation capabilities.
37771
37777
  * @param value - Untrusted data from a request, adapter or response.
37772
37778
  * @returns The validated connection and thread list.
@@ -38102,7 +38108,7 @@ function list$4(item, maximum, message) {
38102
38108
  let items = array(item);
38103
38109
  return createSchema((value, context) => !Array.isArray(value) || value.length > maximum ? fail(message, context.path) : items["~run"](value, context));
38104
38110
  }
38105
- function text$5(maximum) {
38111
+ function text$4(maximum) {
38106
38112
  return string$2().pipe(maxLength(maximum), noNul);
38107
38113
  }
38108
38114
  function integer(maximum = Number.MAX_SAFE_INTEGER, minimum = 0) {
@@ -38122,7 +38128,7 @@ function strict(shape) {
38122
38128
  });
38123
38129
  }
38124
38130
  /** A route identity used in preview URLs. */
38125
- var PreviewIdSchema = text$5(512).refine((id) => id !== "", "Expected a preview identity.");
38131
+ var PreviewIdSchema = text$4(512).refine((id) => id !== "", "Expected a preview identity.");
38126
38132
  /** A color scheme. */
38127
38133
  var PreviewThemeSchema = described$1(enum_(["light", "dark"]), "Unsupported preview theme.");
38128
38134
  /** The SHA-256 content hash that addresses a captured image. */
@@ -38143,7 +38149,7 @@ var MAX_PREVIEW_PINS = 1e3;
38143
38149
  var coordinate = (maximum) => nullable(number$2().refine((value) => Number.isFinite(value) && value >= 0 && value <= maximum));
38144
38150
  /** Where a capture found a commented element. */
38145
38151
  var PreviewPinSchema = strict({
38146
- id: text$5(512).refine((id) => id.length > 0),
38152
+ id: text$4(512).refine((id) => id.length > 0),
38147
38153
  match: described$1(enum_([
38148
38154
  "element",
38149
38155
  "block",
@@ -38179,17 +38185,17 @@ var PreviewCaptureSchema = strict({
38179
38185
  var oneCapturePerTheme = "Expected at most one capture per theme and viewport.";
38180
38186
  var captureVariant = (capture) => `${capture.theme}\0${capture.viewport ?? capture.width}`;
38181
38187
  /** A branch name, as Git allows it for a local branch. */
38182
- var PreviewBranchSchema = described$1(text$5(255).refine((value) => /^[A-Za-z0-9._/-]+$/.test(value) && !value.startsWith("-") && !value.startsWith("/") && !value.endsWith("/") && !value.endsWith(".lock") && !value.includes("..") && !value.includes("//")), "Expected a branch name.");
38188
+ var PreviewBranchSchema = described$1(text$4(255).refine((value) => /^[A-Za-z0-9._/-]+$/.test(value) && !value.startsWith("-") && !value.startsWith("/") && !value.endsWith("/") && !value.endsWith(".lock") && !value.includes("..") && !value.includes("//")), "Expected a branch name.");
38183
38189
  /** One preview from the API. */
38184
38190
  var PreviewSchema = strict({
38185
38191
  id: PreviewIdSchema,
38186
- path: text$5(4096),
38192
+ path: text$4(4096),
38187
38193
  state: described$1(enum_([
38188
38194
  "pending",
38189
38195
  "ready",
38190
38196
  "failed"
38191
38197
  ]), "Unsupported preview state."),
38192
- error: nullable(text$5(2048)),
38198
+ error: nullable(text$4(2048)),
38193
38199
  captures: list$4(PreviewCaptureSchema, 8, oneCapturePerTheme).refine((captures) => new Set(captures.map(captureVariant)).size === captures.length, oneCapturePerTheme),
38194
38200
  updating: boolean$1(),
38195
38201
  sequence: integer(),
@@ -40062,6 +40068,147 @@ function buildRouteMap(base, defs) {
40062
40068
  return routes;
40063
40069
  }
40064
40070
  //#endregion
40071
+ //#region ../../node_modules/.pnpm/@remix-run+fetch-router@1.0.0/node_modules/@remix-run/fetch-router/dist/lib/route-helpers/method.js
40072
+ /**
40073
+ * Shorthand for a GET route.
40074
+ *
40075
+ * @alias get
40076
+ * @param pattern The route pattern string or pre-parsed AST
40077
+ * @returns A Route configured for GET requests
40078
+ */
40079
+ function createGetRoute(pattern) {
40080
+ return new Route$1("GET", pattern);
40081
+ }
40082
+ /**
40083
+ * Shorthand for a POST route.
40084
+ *
40085
+ * @alias post
40086
+ * @param pattern The route pattern string or pre-parsed AST
40087
+ * @returns A Route configured for POST requests
40088
+ */
40089
+ function createPostRoute(pattern) {
40090
+ return new Route$1("POST", pattern);
40091
+ }
40092
+ //#endregion
40093
+ //#region ../ui/src/lib/routes.ts
40094
+ /** Places in Bud's task screen, shared by links and the screen's matcher. */
40095
+ var taskRoutes = createRoutes("/tasks", {
40096
+ index: createGetRoute("/"),
40097
+ show: createGetRoute("/:id"),
40098
+ agent: createGetRoute("/:id/agent")
40099
+ });
40100
+ /** Places in Bud's browser of the project's live pages: a page's own path follows the screen's. */
40101
+ var pageRoutes = createRoutes("/pages", {
40102
+ index: createGetRoute("/"),
40103
+ page: createGetRoute("/*path")
40104
+ });
40105
+ /** Places in Bud's file browser and review. */
40106
+ var fileRoutes = createRoutes("/files", {
40107
+ index: createGetRoute("/"),
40108
+ file: createGetRoute("/*path"),
40109
+ escaped: createGetRoute("/path/*path"),
40110
+ review: createGetRoute("/review/:mode(/*path)"),
40111
+ compare: createGetRoute("/compare/:base...:target(/*path)")
40112
+ });
40113
+ /** A conversation's stable place, independent of its canvas or code anchor. */
40114
+ var conversationRoutes = createRoutes("/comments", { show: createGetRoute("/:id") });
40115
+ //#endregion
40116
+ //#region app/routes.ts
40117
+ var routes = createRoutes({
40118
+ screen: createGetRoute("/(:screen)(/*rest)"),
40119
+ screenModule: createGetRoute("/__bud/screens/:name.js"),
40120
+ logo: createGetRoute("/__bud/logo/:theme"),
40121
+ health: createGetRoute("/health"),
40122
+ conversation: conversationRoutes.show,
40123
+ agentApi: {
40124
+ tasks: createPostRoute("/api/agent/tasks"),
40125
+ tasksStream: createGetRoute("/api/agent/tasks")
40126
+ },
40127
+ factoryApi: {
40128
+ status: createGetRoute("/api/factory"),
40129
+ addStatuses: createPostRoute("/api/factory/statuses"),
40130
+ run: createGetRoute("/api/factory/tasks/:id/run"),
40131
+ start: createPostRoute("/api/factory/tasks/:id/start"),
40132
+ changes: createPostRoute("/api/factory/tasks/:id/changes"),
40133
+ answer: createPostRoute("/api/factory/tasks/:id/answer"),
40134
+ approve: createPostRoute("/api/factory/tasks/:id/approve"),
40135
+ discard: createPostRoute("/api/factory/tasks/:id/discard"),
40136
+ retry: createPostRoute("/api/factory/tasks/:id/retry"),
40137
+ preview: createGetRoute("/api/factory/tasks/:id/preview"),
40138
+ wake: createPostRoute("/api/factory/tasks/:id/wake"),
40139
+ touch: createPostRoute("/api/factory/tasks/:id/touch"),
40140
+ terminal: createGetRoute("/api/factory/tasks/:id/terminal/:session"),
40141
+ terminalInput: createPostRoute("/api/factory/tasks/:id/terminal/:session/input"),
40142
+ terminalResize: createPostRoute("/api/factory/tasks/:id/terminal/:session/resize")
40143
+ },
40144
+ tasksApi: {
40145
+ index: createGetRoute("/api/tasks"),
40146
+ schema: createGetRoute("/api/tasks/schema"),
40147
+ workspace: createGetRoute("/api/tasks/workspace"),
40148
+ show: createGetRoute("/api/tasks/items/:id"),
40149
+ section: createGetRoute("/api/tasks/items/:id/sections/:section"),
40150
+ context: createGetRoute("/api/tasks/items/:id/context"),
40151
+ attachment: createGetRoute("/api/tasks/attachments/:hash.jpg"),
40152
+ create: createPostRoute("/api/tasks"),
40153
+ update: createPostRoute("/api/tasks/items/:id"),
40154
+ mutate: createPostRoute("/api/tasks/items/:id/actions"),
40155
+ sync: createPostRoute("/api/tasks/sync")
40156
+ },
40157
+ filesApi: {
40158
+ index: createGetRoute("/api/files"),
40159
+ entry: createGetRoute("/api/files/entry"),
40160
+ read: createGetRoute("/api/files/read"),
40161
+ refresh: createPostRoute("/api/files/refresh")
40162
+ },
40163
+ fileSearchApi: { search: createGetRoute("/api/files/search") },
40164
+ fileReviewApi: {
40165
+ repository: createGetRoute("/api/files/repository"),
40166
+ compare: createGetRoute("/api/files/compare"),
40167
+ diff: createGetRoute("/api/files/diff"),
40168
+ source: createGetRoute("/api/files/source"),
40169
+ history: createGetRoute("/api/files/history")
40170
+ },
40171
+ fileMutationsApi: {
40172
+ prepare: createPostRoute("/api/files/mutations/prepare"),
40173
+ apply: createPostRoute("/api/files/mutations/apply"),
40174
+ recoveries: createGetRoute("/api/files/mutations/recoveries")
40175
+ },
40176
+ fileSavesApi: { save: createPostRoute("/api/files/save") },
40177
+ fileReviewActionsApi: {
40178
+ prepare: createPostRoute("/api/files/review-actions/prepare"),
40179
+ apply: createPostRoute("/api/files/review-actions/apply"),
40180
+ recoveries: createGetRoute("/api/files/review-actions/recoveries")
40181
+ },
40182
+ liveApi: { stream: createGetRoute("/api/live") },
40183
+ previewsApi: {
40184
+ show: createGetRoute("/api/previews/items/*id"),
40185
+ image: createGetRoute("/api/previews/images/:hash.jpg"),
40186
+ refresh: createPostRoute("/api/previews/refresh/*id"),
40187
+ describe: createPostRoute("/api/previews/describe/*id"),
40188
+ locate: createPostRoute("/api/previews/locate/*id")
40189
+ },
40190
+ branchesApi: {
40191
+ list: createGetRoute("/api/branches"),
40192
+ activate: createPostRoute("/api/branches/activate/*name"),
40193
+ deactivate: createPostRoute("/api/branches/deactivate/*name"),
40194
+ capture: createPostRoute("/api/branches/capture/*name")
40195
+ },
40196
+ comments: {
40197
+ list: createGetRoute("/api/comments"),
40198
+ get: createGetRoute("/api/comments/:id"),
40199
+ create: createPostRoute("/api/comments"),
40200
+ update: createPostRoute("/api/comments/:id"),
40201
+ reply: createPostRoute("/api/comments/:id/replies"),
40202
+ status: createPostRoute("/api/comments/:id/status"),
40203
+ link: createPostRoute("/api/comments/:id/links"),
40204
+ unlink: createPostRoute("/api/comments/:id/links/remove"),
40205
+ makeTask: createPostRoute("/api/comments/:id/task"),
40206
+ deleteMessage: createPostRoute("/api/comments/:id/messages/remove"),
40207
+ sync: createPostRoute("/api/comments/sync"),
40208
+ viewer: createGetRoute("/api/viewer")
40209
+ }
40210
+ });
40211
+ //#endregion
40065
40212
  //#region ../../node_modules/.pnpm/@remix-run+component@1.0.0_patch_hash=ed95ce6ac654c31698f27fd52f980c5f1d3e725ba0116b6d666a9b6b3a67016b/node_modules/@remix-run/component/dist/runtime/core/vnode.js
40066
40213
  function createRemixElement(type, props, key) {
40067
40214
  return {
@@ -46586,6 +46733,30 @@ function attrs(defaults) {
46586
46733
  * This source code is licensed under the ISC license.
46587
46734
  * See the LICENSE file in the root directory of this source tree.
46588
46735
  */
46736
+ /**
46737
+ * @license @lucide/icons v1.58.0 - ISC
46738
+ *
46739
+ * This source code is licensed under the ISC license.
46740
+ * See the LICENSE file in the root directory of this source tree.
46741
+ */
46742
+ /**
46743
+ * @license @lucide/icons v1.58.0 - ISC
46744
+ *
46745
+ * This source code is licensed under the ISC license.
46746
+ * See the LICENSE file in the root directory of this source tree.
46747
+ */
46748
+ /**
46749
+ * @license @lucide/icons v1.58.0 - ISC
46750
+ *
46751
+ * This source code is licensed under the ISC license.
46752
+ * See the LICENSE file in the root directory of this source tree.
46753
+ */
46754
+ /**
46755
+ * @license @lucide/icons v1.58.0 - ISC
46756
+ *
46757
+ * This source code is licensed under the ISC license.
46758
+ * See the LICENSE file in the root directory of this source tree.
46759
+ */
46589
46760
  //#endregion
46590
46761
  //#region ../ui/src/lib/icon.tsx
46591
46762
  var icons$1 = {
@@ -47881,6 +48052,32 @@ var icons$1 = {
47881
48052
  }]
47882
48053
  ]
47883
48054
  },
48055
+ "task-add": {
48056
+ name: "list-plus",
48057
+ size: 24,
48058
+ node: [
48059
+ ["path", {
48060
+ d: "M16 5H3",
48061
+ key: "m91uny"
48062
+ }],
48063
+ ["path", {
48064
+ d: "M11 12H3",
48065
+ key: "51ecnj"
48066
+ }],
48067
+ ["path", {
48068
+ d: "M16 19H3",
48069
+ key: "zzsher"
48070
+ }],
48071
+ ["path", {
48072
+ d: "M18 9v6",
48073
+ key: "1twb98"
48074
+ }],
48075
+ ["path", {
48076
+ d: "M21 12h-6",
48077
+ key: "bt1uis"
48078
+ }]
48079
+ ]
48080
+ },
47884
48081
  files: {
47885
48082
  name: "files",
47886
48083
  size: 24,
@@ -48279,6 +48476,60 @@ var icons$1 = {
48279
48476
  }]
48280
48477
  ]
48281
48478
  },
48479
+ terminal: {
48480
+ name: "square-terminal",
48481
+ size: 24,
48482
+ node: [
48483
+ ["path", {
48484
+ d: "m7 11 2-2-2-2",
48485
+ key: "1lz0vl"
48486
+ }],
48487
+ ["path", {
48488
+ d: "M11 13h4",
48489
+ key: "1p7l4v"
48490
+ }],
48491
+ ["rect", {
48492
+ width: "18",
48493
+ height: "18",
48494
+ x: "3",
48495
+ y: "3",
48496
+ rx: "2",
48497
+ ry: "2",
48498
+ key: "1m3agn"
48499
+ }]
48500
+ ],
48501
+ aliases: ["terminal-square"]
48502
+ },
48503
+ "panel-right": {
48504
+ name: "panel-right",
48505
+ size: 24,
48506
+ node: [["rect", {
48507
+ width: "18",
48508
+ height: "18",
48509
+ x: "3",
48510
+ y: "3",
48511
+ rx: "2",
48512
+ key: "afitv7"
48513
+ }], ["path", {
48514
+ d: "M15 3v18",
48515
+ key: "14nvp0"
48516
+ }]]
48517
+ },
48518
+ "panel-bottom": {
48519
+ name: "panel-bottom",
48520
+ size: 24,
48521
+ node: [["rect", {
48522
+ width: "18",
48523
+ height: "18",
48524
+ x: "3",
48525
+ y: "3",
48526
+ rx: "2",
48527
+ key: "afitv7"
48528
+ }], ["path", {
48529
+ d: "M3 15h18",
48530
+ key: "5xshup"
48531
+ }]]
48532
+ },
48282
48533
  eye: {
48283
48534
  name: "eye",
48284
48535
  size: 24,
@@ -48891,6 +49142,34 @@ function HeadlessButton(handle) {
48891
49142
  //#region ../ui/src/lib/i18n/de.ts
48892
49143
  /** Bud's interface text in German, by message key. */
48893
49144
  var de = {
49145
+ "app.client.agentPanel.agent": {
49146
+ text: "Agent",
49147
+ source: "f5a4f646"
49148
+ },
49149
+ "app.client.agentPanel.changesRefused": {
49150
+ text: "Der Agent kann Änderungen gerade nicht entgegennehmen",
49151
+ source: "bdb2edb4"
49152
+ },
49153
+ "app.client.agentPanel.changesSent": {
49154
+ text: "An den Agenten gesendet",
49155
+ source: "7f5e7626"
49156
+ },
49157
+ "app.client.agentPanel.devServer": {
49158
+ text: "Dev-Server",
49159
+ source: "27e53ed7"
49160
+ },
49161
+ "app.client.agentPanel.ended": {
49162
+ text: "Die Sitzung wurde beendet. Wenn du dich wieder verbindest, startet sie erneut.",
49163
+ source: "bf6ebbec"
49164
+ },
49165
+ "app.client.agentPanel.failed": {
49166
+ text: "Die Factory hat nicht geantwortet.",
49167
+ source: "3bd3ae7a"
49168
+ },
49169
+ "app.client.agentPanel.shell": {
49170
+ text: "Shell",
49171
+ source: "ba1969a1"
49172
+ },
48894
49173
  "app.client.commentsRequest.emptyResponse": {
48895
49174
  text: "Der Kommentarservice hat eine leere Antwort zurückgegeben.",
48896
49175
  source: "c739d1f9"
@@ -48979,6 +49258,62 @@ var de = {
48979
49258
  text: "Die Bilder konnten nicht verglichen werden.",
48980
49259
  source: "8fd04955"
48981
49260
  },
49261
+ "app.client.factoryRun.discardAndMove": {
49262
+ text: "Lauf verwerfen & verschieben",
49263
+ source: "9b3e9067"
49264
+ },
49265
+ "app.client.factoryRun.failed": {
49266
+ text: "Bud konnte die Factory nicht erreichen.",
49267
+ source: "00cea450"
49268
+ },
49269
+ "app.client.factoryRun.keepRun": {
49270
+ text: "Lauf behalten",
49271
+ source: "88a5de36"
49272
+ },
49273
+ "app.client.factoryRun.moveQuestion": {
49274
+ text: "Für {id} läuft ein Agent. Wenn du die Aufgabe nach {status} verschiebst, werden der Lauf und seine Sandbox verworfen. Es wurde nichts gepusht, daher geht die Arbeit des Agents verloren.",
49275
+ source: "d0c22345"
49276
+ },
49277
+ "app.client.factoryRun.moveTitle": {
49278
+ text: "Lauf des Agents verwerfen?",
49279
+ source: "5ce9ffe3"
49280
+ },
49281
+ "app.client.factoryRun.noPreview": {
49282
+ text: "Der Dev-Server des Runs ist nicht erreichbar.",
49283
+ source: "6dd54cb3"
49284
+ },
49285
+ "app.client.factoryRun.previewFailed": {
49286
+ text: "Die Live-Vorschau konnte nicht geöffnet werden",
49287
+ source: "a96d281a"
49288
+ },
49289
+ "app.client.factoryRun.refused": {
49290
+ text: "Der Run wurde nicht geändert",
49291
+ source: "a5fc457d"
49292
+ },
49293
+ "app.client.factoryRun.statusesMissing": {
49294
+ text: "Füge oben die Factory-Status hinzu, bevor du Aufgaben startest.",
49295
+ source: "2a26077f"
49296
+ },
49297
+ "app.client.factorySetup.add": {
49298
+ text: "Factory-Status hinzufügen",
49299
+ source: "7992be24"
49300
+ },
49301
+ "app.client.factorySetup.added": {
49302
+ text: "Factory-Status hinzugefügt",
49303
+ source: "02f6f293"
49304
+ },
49305
+ "app.client.factorySetup.failed": {
49306
+ text: "Factory-Status konnten nicht hinzugefügt werden",
49307
+ source: "8500af1b"
49308
+ },
49309
+ "app.client.factorySetup.missing": {
49310
+ text: "In deinem Aufgaben-Store braucht die Factory diese Status: {statuses}.",
49311
+ source: "573be4b6"
49312
+ },
49313
+ "app.client.factorySetup.otherKind": {
49314
+ text: "Dein Aufgaben-Store führt diese Factory-Status als anderen Statustyp: {statuses}. Ordne andere Status in factory.statuses zu.",
49315
+ source: "1b96d5e4"
49316
+ },
48982
49317
  "app.client.fileDrafts.deleteWithUnsavedDrafts": {
48983
49318
  text: "Speichere oder verwerfe die ungespeicherten Entwürfe in dieser Auswahl, bevor du sie löschst.",
48984
49319
  source: "1deabbed"
@@ -49387,6 +49722,10 @@ var de = {
49387
49722
  text: "Der Kommentardienst hat eine andere Diskussion zurückgegeben.",
49388
49723
  source: "c0151231"
49389
49724
  },
49725
+ "app.client.projectComments.taskCreated": {
49726
+ text: "Aufgabe erstellt",
49727
+ source: "4e52cadc"
49728
+ },
49390
49729
  "app.client.projectComments.waitForCurrentOperation": {
49391
49730
  text: "Warte, bis der aktuelle Kommentarvorgang abgeschlossen ist.",
49392
49731
  source: "3c6007dd"
@@ -49594,6 +49933,10 @@ var de = {
49594
49933
  text: "Aufgaben konnten nicht geladen werden.",
49595
49934
  source: "b5dd285f"
49596
49935
  },
49936
+ "app.client.projectTasks.closeAgentView": {
49937
+ text: "Agent-Ansicht schliessen",
49938
+ source: "0d888f27"
49939
+ },
49597
49940
  "app.client.projectTasks.couldNotLoadTask": {
49598
49941
  text: "Diese Aufgabe konnte nicht geladen werden.",
49599
49942
  source: "370587a2"
@@ -49610,10 +49953,22 @@ var de = {
49610
49953
  text: "Der Aufgabendienst hat eine andere Aufgabe zurückgegeben. Aktualisiere vor dem erneuten Versuch.",
49611
49954
  source: "91adeaa0"
49612
49955
  },
49956
+ "app.client.projectTasks.openAgentView": {
49957
+ text: "Agent-Ansicht öffnen",
49958
+ source: "99976d29"
49959
+ },
49613
49960
  "app.client.projectTasks.refreshBeforeChanges": {
49614
49961
  text: "Aktualisiere die Aufgaben, bevor du Änderungen vornimmst.",
49615
49962
  source: "9f4e6583"
49616
49963
  },
49964
+ "app.client.projectTasks.runKept": {
49965
+ text: "Die Aufgabe bleibt, wo sie ist, während der Agent läuft.",
49966
+ source: "ed653075"
49967
+ },
49968
+ "app.client.projectTasks.runPushing": {
49969
+ text: "Der Branch der Aufgabe wird gepusht. Verschiebe sie, sobald der Push abgeschlossen ist.",
49970
+ source: "c4f8b8c6"
49971
+ },
49617
49972
  "app.client.projectTasks.undidTaskChange": {
49618
49973
  text: "Bud hat eine Aufgabenänderung rückgängig gemacht",
49619
49974
  source: "7f50e04c"
@@ -49630,6 +49985,10 @@ var de = {
49630
49985
  text: "Aufgaben verknüpfen",
49631
49986
  source: "b6640aab"
49632
49987
  },
49988
+ "app.client.projectThreadLinks.makeTask": {
49989
+ text: "Aufgabe erstellen",
49990
+ source: "f5eaf1d4"
49991
+ },
49633
49992
  "app.client.projectThreadLinks.reviewLinksBeforeSaving": {
49634
49993
  text: "Überprüfe die neuesten Verknüpfungen, bevor du speicherst.",
49635
49994
  source: "c567f897"
@@ -49662,6 +50021,38 @@ var de = {
49662
50021
  text: "Erneut versuchen",
49663
50022
  source: "8036af59"
49664
50023
  },
50024
+ "app.client.taskContextBlock.branch": {
50025
+ text: "Branch",
50026
+ source: "a3e27665"
50027
+ },
50028
+ "app.client.taskContextBlock.code": {
50029
+ text: "Code",
50030
+ source: "795db914"
50031
+ },
50032
+ "app.client.taskContextBlock.context": {
50033
+ text: "Kontext",
50034
+ source: "bd317f1c"
50035
+ },
50036
+ "app.client.taskContextBlock.element": {
50037
+ text: "Element",
50038
+ source: "7d376697"
50039
+ },
50040
+ "app.client.taskContextBlock.page": {
50041
+ text: "Seite",
50042
+ source: "e83d9196"
50043
+ },
50044
+ "app.client.taskContextBlock.screenshot": {
50045
+ text: "Die Seite rund um den Kommentar, mit markierter Stelle",
50046
+ source: "a97331f6"
50047
+ },
50048
+ "app.client.taskContextBlock.source": {
50049
+ text: "Quelle",
50050
+ source: "61e2a3f8"
50051
+ },
50052
+ "app.client.taskContextBlock.viewport": {
50053
+ text: "Ansicht",
50054
+ source: "60b5afe3"
50055
+ },
49665
50056
  "app.client.taskDiscussion.addContextPlaceholder": {
49666
50057
  text: "Füge Kontext für dein Team hinzu…",
49667
50058
  source: "af3fe6ea"
@@ -49769,6 +50160,10 @@ var de = {
49769
50160
  text: "Die Änderung der Aufgabenverknüpfung wurde nicht bestätigt. Überprüfe die neuesten Verknüpfungen, bevor du erneut speicherst.",
49770
50161
  source: "7616ef3c"
49771
50162
  },
50163
+ "app.client.workspace.agentView": {
50164
+ text: "{task} · Agent",
50165
+ source: "d5c33796"
50166
+ },
49772
50167
  "app.client.workspace.connectProjectToOpenDiscussion": {
49773
50168
  text: "Verbinde ein Projekt, um diese Diskussion zu öffnen.",
49774
50169
  source: "fc0ca04e"
@@ -49809,6 +50204,49 @@ var de = {
49809
50204
  text: "Diskussion",
49810
50205
  source: "52a76f71"
49811
50206
  },
50207
+ "app.server.commentTask.discussion": {
50208
+ text: "Diskussion",
50209
+ source: "52a76f71"
50210
+ },
50211
+ "app.server.commentTask.element": {
50212
+ text: "Element",
50213
+ source: "7d376697"
50214
+ },
50215
+ "app.server.commentTask.linkedTasks": {
50216
+ text: "verknüpfte Aufgaben",
50217
+ source: "b827f1f2"
50218
+ },
50219
+ "app.server.commentTask.replies": {
50220
+ text: "Antworten",
50221
+ source: "43e07f5f"
50222
+ },
50223
+ "app.server.commentTask.replyCount": {
50224
+ text: {
50225
+ one: "{count} Antwort",
50226
+ other: "{count} Antworten"
50227
+ },
50228
+ source: "2b046207"
50229
+ },
50230
+ "app.server.commentTask.source": {
50231
+ text: "Quelle",
50232
+ source: "61e2a3f8"
50233
+ },
50234
+ "app.server.commentTask.title": {
50235
+ text: "Kommentar zu {place}",
50236
+ source: "553c8e8c"
50237
+ },
50238
+ "app.server.commentTask.uncommitted": {
50239
+ text: "nicht committet",
50240
+ source: "fa6d4090"
50241
+ },
50242
+ "app.server.commentTask.where": {
50243
+ text: "Wo",
50244
+ source: "91dad0f8"
50245
+ },
50246
+ "app.server.commentTask.workingTree": {
50247
+ text: "Working Tree",
50248
+ source: "7674e9c0"
50249
+ },
49812
50250
  "appShell.mainNavigation": {
49813
50251
  text: "Hauptnavigation",
49814
50252
  source: "c5a8374a"
@@ -49962,10 +50400,6 @@ var de = {
49962
50400
  text: "Leinwand verschieben",
49963
50401
  source: "233eddf0"
49964
50402
  },
49965
- "canvas.canvasWorkspace.reload": {
49966
- text: "Neu laden",
49967
- source: "1a43a2ac"
49968
- },
49969
50403
  "canvas.canvasWorkspace.savingComments": {
49970
50404
  text: "Kommentare werden gespeichert",
49971
50405
  source: "1f15fbfb"
@@ -52890,6 +53324,114 @@ var de = {
52890
53324
  text: "Tabs",
52891
53325
  source: "8ec4824d"
52892
53326
  },
53327
+ "tasks.agentBrowser.address": {
53328
+ text: "Vorschauadresse",
53329
+ source: "37f7f743"
53330
+ },
53331
+ "tasks.agentBrowser.asleep": {
53332
+ text: "Die Sandbox ist im Ruhezustand, um Kosten zu sparen.",
53333
+ source: "662bf5ad"
53334
+ },
53335
+ "tasks.agentBrowser.back": {
53336
+ text: "Zurück",
53337
+ source: "c2954bc2"
53338
+ },
53339
+ "tasks.agentBrowser.commentOnElement": {
53340
+ text: "Kommentiere ein Element für den Agenten",
53341
+ source: "0dd8635f"
53342
+ },
53343
+ "tasks.agentBrowser.forward": {
53344
+ text: "Vorwärts",
53345
+ source: "e50883ba"
53346
+ },
53347
+ "tasks.agentBrowser.newComment": {
53348
+ text: "Änderung für den Agenten",
53349
+ source: "4d74ba2c"
53350
+ },
53351
+ "tasks.agentBrowser.noPreview": {
53352
+ text: "Hier wird die Vorschau angezeigt, sobald die Sandbox des Laufs mit dem Dev-Server läuft.",
53353
+ source: "65d4e271"
53354
+ },
53355
+ "tasks.agentBrowser.openInNewWindow": {
53356
+ text: "Vorschau in einem neuen Fenster öffnen",
53357
+ source: "e0d3f63c"
53358
+ },
53359
+ "tasks.agentBrowser.preview": {
53360
+ text: "Live-Vorschau",
53361
+ source: "7e42b06f"
53362
+ },
53363
+ "tasks.agentBrowser.reload": {
53364
+ text: "Neu laden",
53365
+ source: "1a43a2ac"
53366
+ },
53367
+ "tasks.agentBrowser.status": {
53368
+ text: "Vorschau-Status",
53369
+ source: "94b339ff"
53370
+ },
53371
+ "tasks.agentBrowser.tryAgain": {
53372
+ text: "Erneut versuchen",
53373
+ source: "213e90fa"
53374
+ },
53375
+ "tasks.agentBrowser.wake": {
53376
+ text: "Aufwecken",
53377
+ source: "d0fedeca"
53378
+ },
53379
+ "tasks.agentBrowser.waking": {
53380
+ text: "Sandbox wird aufgeweckt…",
53381
+ source: "1f99ad40"
53382
+ },
53383
+ "tasks.agentTerminal.disconnected": {
53384
+ text: "Verbindung wird wiederhergestellt…",
53385
+ source: "2f039284"
53386
+ },
53387
+ "tasks.agentTerminal.sessions": {
53388
+ text: "Terminal-Sitzungen",
53389
+ source: "0257839a"
53390
+ },
53391
+ "tasks.agentTerminal.terminal": {
53392
+ text: "Terminal {name}",
53393
+ source: "99a8191c"
53394
+ },
53395
+ "tasks.agentView.agentPanes": {
53396
+ text: "Browser oder Terminal",
53397
+ source: "9c5631e4"
53398
+ },
53399
+ "tasks.agentView.browser": {
53400
+ text: "Browser",
53401
+ source: "8df5852f"
53402
+ },
53403
+ "tasks.agentView.browserAndTerminal": {
53404
+ text: "Browser & Terminal",
53405
+ source: "50b6394f"
53406
+ },
53407
+ "tasks.agentView.details": {
53408
+ text: "Details",
53409
+ source: "0ec24245"
53410
+ },
53411
+ "tasks.agentView.hideTerminal": {
53412
+ text: "Terminal ausblenden",
53413
+ source: "b355c54b"
53414
+ },
53415
+ "tasks.agentView.showTerminal": {
53416
+ text: "Terminal anzeigen",
53417
+ source: "93576794"
53418
+ },
53419
+ "tasks.agentView.terminal": {
53420
+ text: "Terminal",
53421
+ source: "93c562d1"
53422
+ },
53423
+ "tasks.agentView.terminalBelow": {
53424
+ text: "Terminal unter dem Browser",
53425
+ source: "8f840a73"
53426
+ },
53427
+ "tasks.agentView.terminalBeside": {
53428
+ text: "Terminal neben dem Browser",
53429
+ source: "9f744076"
53430
+ },
53431
+ "tasks.agentView.view": {
53432
+ text: "Agent-Ansicht",
53433
+ source: "498637bb"
53434
+ },
52893
53435
  "tasks.taskActions.actionInProgress": {
52894
53436
  text: "Eine Aufgabenaktion läuft bereits.",
52895
53437
  source: "1ae83c01"
@@ -53076,6 +53618,14 @@ var de = {
53076
53618
  text: "In Bearbeitung",
53077
53619
  source: "2948b425"
53078
53620
  },
53621
+ "tasks.taskData.label.merged": {
53622
+ text: "Zusammengeführt",
53623
+ source: "28064199"
53624
+ },
53625
+ "tasks.taskData.label.needs_approval": {
53626
+ text: "Benötigt Freigabe",
53627
+ source: "ecf5c9c5"
53628
+ },
53079
53629
  "tasks.taskData.label.open": {
53080
53630
  text: "Offen",
53081
53631
  source: "538b10e9"
@@ -53088,6 +53638,10 @@ var de = {
53088
53638
  text: "Bereit",
53089
53639
  source: "0bca3294"
53090
53640
  },
53641
+ "tasks.taskData.label.ready_to_merge": {
53642
+ text: "Bereit zum Zusammenführen",
53643
+ source: "b0ea5dc5"
53644
+ },
53091
53645
  "tasks.taskData.label.task": {
53092
53646
  text: "Aufgabe",
53093
53647
  source: "76ef3d8c"
@@ -53419,6 +53973,160 @@ var de = {
53419
53973
  text: "Unerledigter Eintrag",
53420
53974
  source: "eee80db8"
53421
53975
  },
53976
+ "tasks.taskRunBadge.failed": {
53977
+ text: "Run fehlgeschlagen",
53978
+ source: "e2b5681f"
53979
+ },
53980
+ "tasks.taskRunBadge.merged": {
53981
+ text: "Zusammengeführt",
53982
+ source: "28064199"
53983
+ },
53984
+ "tasks.taskRunBadge.needsContext": {
53985
+ text: "Braucht Kontext",
53986
+ source: "18701779"
53987
+ },
53988
+ "tasks.taskRunBadge.pushed": {
53989
+ text: "Gepusht",
53990
+ source: "79d81944"
53991
+ },
53992
+ "tasks.taskRunBadge.pushing": {
53993
+ text: "Wird gepusht",
53994
+ source: "5dd372a3"
53995
+ },
53996
+ "tasks.taskRunBadge.review": {
53997
+ text: "Freigabe nötig",
53998
+ source: "ecf5c9c5"
53999
+ },
54000
+ "tasks.taskRunBadge.settingUp": {
54001
+ text: "Wird eingerichtet",
54002
+ source: "aee4ff74"
54003
+ },
54004
+ "tasks.taskRunBadge.working": {
54005
+ text: "Agent arbeitet",
54006
+ source: "102da6c1"
54007
+ },
54008
+ "tasks.taskRunPanel.activity": {
54009
+ text: "Aktivität des Agents",
54010
+ source: "3457114f"
54011
+ },
54012
+ "tasks.taskRunPanel.agent": {
54013
+ text: "Agent",
54014
+ source: "f5a4f646"
54015
+ },
54016
+ "tasks.taskRunPanel.answer": {
54017
+ text: "Dem Agenten antworten",
54018
+ source: "d2d2b425"
54019
+ },
54020
+ "tasks.taskRunPanel.answerPlaceholder": {
54021
+ text: "Was muss der Agent wissen?",
54022
+ source: "92f7895f"
54023
+ },
54024
+ "tasks.taskRunPanel.approve": {
54025
+ text: "Freigeben & pushen",
54026
+ source: "7110783c"
54027
+ },
54028
+ "tasks.taskRunPanel.asleep": {
54029
+ text: "Die Sandbox schläft, um Kosten zu sparen. Sie wacht auf, wenn du die Vorschau öffnest, Änderungen anforderst oder freigibst.",
54030
+ source: "110af9ad"
54031
+ },
54032
+ "tasks.taskRunPanel.cancel": {
54033
+ text: "Abbrechen",
54034
+ source: "35afca3b"
54035
+ },
54036
+ "tasks.taskRunPanel.changesPlaceholder": {
54037
+ text: "Was soll der Agent ändern?",
54038
+ source: "80c05411"
54039
+ },
54040
+ "tasks.taskRunPanel.confirmApprove": {
54041
+ text: "{branch} ins Repository pushen?",
54042
+ source: "2d1354f2"
54043
+ },
54044
+ "tasks.taskRunPanel.confirmDiscard": {
54045
+ text: "Diesen Run und seine Sandbox verwerfen? Es wurde nichts gepusht.",
54046
+ source: "6ac090ee"
54047
+ },
54048
+ "tasks.taskRunPanel.discard": {
54049
+ text: "Verwerfen",
54050
+ source: "1e706c21"
54051
+ },
54052
+ "tasks.taskRunPanel.failed": {
54053
+ text: "Der Run ist fehlgeschlagen.",
54054
+ source: "49b620f0"
54055
+ },
54056
+ "tasks.taskRunPanel.loading": {
54057
+ text: "Run wird geladen …",
54058
+ source: "331b7fa5"
54059
+ },
54060
+ "tasks.taskRunPanel.merged": {
54061
+ text: "{branch} ist zusammengeführt.",
54062
+ source: "e9b50ea9"
54063
+ },
54064
+ "tasks.taskRunPanel.minutes": {
54065
+ text: {
54066
+ one: "1 Min.",
54067
+ other: "{count} Min."
54068
+ },
54069
+ source: "f87c3e0b"
54070
+ },
54071
+ "tasks.taskRunPanel.needsContext": {
54072
+ text: "Der Agent braucht mehr Kontext, um fortzufahren.",
54073
+ source: "98437cea"
54074
+ },
54075
+ "tasks.taskRunPanel.preview": {
54076
+ text: "Live-Vorschau öffnen",
54077
+ source: "62e9491d"
54078
+ },
54079
+ "tasks.taskRunPanel.pushed": {
54080
+ text: "{branch} wurde bei {commit} gepusht.",
54081
+ source: "78703afe"
54082
+ },
54083
+ "tasks.taskRunPanel.pushing": {
54084
+ text: "{branch} wird gepusht …",
54085
+ source: "9b951555"
54086
+ },
54087
+ "tasks.taskRunPanel.requestChanges": {
54088
+ text: "Änderungen anfordern",
54089
+ source: "637e8883"
54090
+ },
54091
+ "tasks.taskRunPanel.retry": {
54092
+ text: "Erneut versuchen",
54093
+ source: "8036af59"
54094
+ },
54095
+ "tasks.taskRunPanel.review": {
54096
+ text: "Der Agent ist fertig und wartet auf deine Prüfung.",
54097
+ source: "7e509cde"
54098
+ },
54099
+ "tasks.taskRunPanel.seconds": {
54100
+ text: {
54101
+ one: "1 s",
54102
+ other: "{count} s"
54103
+ },
54104
+ source: "24364243"
54105
+ },
54106
+ "tasks.taskRunPanel.settingUp": {
54107
+ text: "Sandbox wird eingerichtet …",
54108
+ source: "be97ea8e"
54109
+ },
54110
+ "tasks.taskRunPanel.showOnCanvas": {
54111
+ text: "Auf der Leinwand anzeigen",
54112
+ source: "b076f243"
54113
+ },
54114
+ "tasks.taskRunPanel.start": {
54115
+ text: "Aufgabe starten",
54116
+ source: "dbc9a724"
54117
+ },
54118
+ "tasks.taskRunPanel.startAgain": {
54119
+ text: "Erneut starten",
54120
+ source: "9a468407"
54121
+ },
54122
+ "tasks.taskRunPanel.startHint": {
54123
+ text: "Ein Agent bearbeitet diese Aufgabe in einer Sandbox. Erst nach deiner Freigabe wird etwas gepusht.",
54124
+ source: "ccf1c6a4"
54125
+ },
54126
+ "tasks.taskRunPanel.working": {
54127
+ text: "Der Agent arbeitet …",
54128
+ source: "202318fe"
54129
+ },
53422
54130
  "tasks.taskSections.latestEvents": {
53423
54131
  text: {
53424
54132
  one: "Das neueste Ereignis wird angezeigt.",
@@ -53536,6 +54244,10 @@ var de = {
53536
54244
  text: "Erstelle eine Aufgabe, um mit der Planung deiner Arbeit zu beginnen.",
53537
54245
  source: "7c21b645"
53538
54246
  },
54247
+ "tasks.taskWorkspace.fewerStatuses": {
54248
+ text: "Weniger Statuswerte anzeigen",
54249
+ source: "1de3f0ed"
54250
+ },
53539
54251
  "tasks.taskWorkspace.filterEpic": {
53540
54252
  text: "Epic filtern",
53541
54253
  source: "19c2ed58"
@@ -53604,6 +54316,17 @@ var de = {
53604
54316
  text: "Noch kein {label}-Arbeitsbereich vorhanden",
53605
54317
  source: "233c23c9"
53606
54318
  },
54319
+ "tasks.taskWorkspace.otherStatuses": {
54320
+ text: {
54321
+ one: "+1 in einem anderen Status",
54322
+ other: "+{count} in anderen Statuswerten"
54323
+ },
54324
+ source: "6cae97c5"
54325
+ },
54326
+ "tasks.taskWorkspace.otherStatusesEmpty": {
54327
+ text: "Weitere Status",
54328
+ source: "d56d45a5"
54329
+ },
53607
54330
  "tasks.taskWorkspace.priority": {
53608
54331
  text: "Priorität",
53609
54332
  source: "e68d9f29"
@@ -53675,6 +54398,13 @@ var de = {
53675
54398
  text: "Deine lokalen Aufgabenänderungen teilen",
53676
54399
  source: "1dad116c"
53677
54400
  },
54401
+ "tasks.taskWorkspace.showTasks": {
54402
+ text: {
54403
+ one: "1 Aufgabe anzeigen",
54404
+ other: "{count} Aufgaben anzeigen"
54405
+ },
54406
+ source: "56258faa"
54407
+ },
53678
54408
  "tasks.taskWorkspace.showingCount": {
53679
54409
  text: "Zeigt {shown} von {total}",
53680
54410
  source: "e8675f4a"
@@ -53771,6 +54501,13 @@ var de = {
53771
54501
  * and the thing (`canvas.zoomIn`); `pnpm translate` keeps the other languages in step.
53772
54502
  */
53773
54503
  var en = {
54504
+ "app.client.agentPanel.agent": "Agent",
54505
+ "app.client.agentPanel.changesRefused": "The agent can’t take changes now",
54506
+ "app.client.agentPanel.changesSent": "Sent to the agent",
54507
+ "app.client.agentPanel.devServer": "Dev server",
54508
+ "app.client.agentPanel.ended": "The session ended. It starts again when you reconnect.",
54509
+ "app.client.agentPanel.failed": "The factory didn’t answer.",
54510
+ "app.client.agentPanel.shell": "Shell",
53774
54511
  "app.client.commentsRequest.emptyResponse": "The comments service returned an empty response.",
53775
54512
  "app.client.commentsRequest.invalidData": "The comments service returned invalid data.",
53776
54513
  "app.client.commentsRequest.invalidEndpoint": "Invalid comments endpoint.",
@@ -53793,6 +54530,20 @@ var en = {
53793
54530
  "app.client.differenceView.slideStatus": "{kind} · change {change} of {count} · {index} / {total}",
53794
54531
  "app.client.differenceView.slideshowLabel": "Differences slideshow",
53795
54532
  "app.client.differenceWorker.compareError": "The pictures could not be compared.",
54533
+ "app.client.factoryRun.discardAndMove": "Discard run & move",
54534
+ "app.client.factoryRun.failed": "Bud couldn’t reach the factory.",
54535
+ "app.client.factoryRun.keepRun": "Keep the run",
54536
+ "app.client.factoryRun.moveQuestion": "{id} has an agent run. Moving it to {status} discards the run and its sandbox; nothing was pushed, so the agent’s work is lost.",
54537
+ "app.client.factoryRun.moveTitle": "Discard the agent’s run?",
54538
+ "app.client.factoryRun.noPreview": "The run’s dev server isn’t up.",
54539
+ "app.client.factoryRun.previewFailed": "Couldn’t open the live preview",
54540
+ "app.client.factoryRun.refused": "The run didn’t change",
54541
+ "app.client.factoryRun.statusesMissing": "Add the factory statuses above before starting tasks.",
54542
+ "app.client.factorySetup.add": "Add factory statuses",
54543
+ "app.client.factorySetup.added": "Factory statuses added",
54544
+ "app.client.factorySetup.failed": "Couldn’t add the factory statuses",
54545
+ "app.client.factorySetup.missing": "The factory needs these statuses in your task store: {statuses}.",
54546
+ "app.client.factorySetup.otherKind": "Your task store has these factory statuses as another kind of status: {statuses}. Map other statuses in factory.statuses.",
53796
54547
  "app.client.fileDrafts.deleteWithUnsavedDrafts": "Save or discard the unsaved drafts in this selection before deleting it.",
53797
54548
  "app.client.fileDrafts.destinationDraftConflict": "The destination acquired an unsaved draft while the move was running. Both drafts remain available at their original paths; download or review them before continuing.",
53798
54549
  "app.client.fileDrafts.destinationHasDraft": "A destination has an unsaved draft. Save or discard it before moving files here.",
@@ -53904,6 +54655,7 @@ var en = {
53904
54655
  "app.client.projectComments.refreshBeforeTryingAgain": "The comment write could not be confirmed. Refresh before trying again.",
53905
54656
  "app.client.projectComments.reloadDiscussionBeforeSaving": "Reload this discussion before saving.",
53906
54657
  "app.client.projectComments.serviceReturnedAnotherDiscussion": "The comments service returned another discussion.",
54658
+ "app.client.projectComments.taskCreated": "Task created",
53907
54659
  "app.client.projectComments.waitForCurrentOperation": "Wait for the current comment operation to finish.",
53908
54660
  "app.client.projectDifferences.comparisonFailed": "The pictures could not be compared.",
53909
54661
  "app.client.projectFileReview.commentsUnavailable": "Comments are stored by your storage adapter. Beads: run bd init in this project.",
@@ -53958,15 +54710,20 @@ var en = {
53958
54710
  "app.client.projectPreviews.requestFailed": "Preview request failed ({status}).",
53959
54711
  "app.client.projectTaskPicker.adapterUnavailable": "The task adapter is unavailable.",
53960
54712
  "app.client.projectTaskPicker.loadFailed": "Could not load tasks.",
54713
+ "app.client.projectTasks.closeAgentView": "Close Agent view",
53961
54714
  "app.client.projectTasks.couldNotLoadTask": "Could not load this task.",
53962
54715
  "app.client.projectTasks.couldNotLoadTasks": "Could not load tasks.",
53963
54716
  "app.client.projectTasks.differentTaskRefresh": "The task service returned a different task. Refresh and try again.",
53964
54717
  "app.client.projectTasks.differentTaskRefreshRetry": "The task service returned a different task. Refresh before retrying.",
54718
+ "app.client.projectTasks.openAgentView": "Open Agent view",
53965
54719
  "app.client.projectTasks.refreshBeforeChanges": "Refresh tasks before making changes.",
54720
+ "app.client.projectTasks.runKept": "The task stays where it is while its agent runs.",
54721
+ "app.client.projectTasks.runPushing": "The task’s branch is being pushed; move it once the push is done.",
53966
54722
  "app.client.projectTasks.undidTaskChange": "Bud undid a task change",
53967
54723
  "app.client.projectTasks.writeNotConfirmed": "The write was not confirmed.",
53968
54724
  "app.client.projectThreadLinks.anotherDiscussion": "The service returned another discussion.",
53969
54725
  "app.client.projectThreadLinks.linkTasks": "Link tasks",
54726
+ "app.client.projectThreadLinks.makeTask": "Make task",
53970
54727
  "app.client.projectThreadLinks.reviewLinksBeforeSaving": "Review the latest links before saving.",
53971
54728
  "app.client.screenHost.couldNotOpen": "Could not open {label}.",
53972
54729
  "app.client.screenHost.didntOpen": "{label} didn't open",
@@ -53975,6 +54732,14 @@ var en = {
53975
54732
  "app.client.screenHost.loading": "Loading {label}…",
53976
54733
  "app.client.screenHost.noRouteMatches": "No screen route matches {href}.",
53977
54734
  "app.client.screenHost.retry": "Retry",
54735
+ "app.client.taskContextBlock.branch": "Branch",
54736
+ "app.client.taskContextBlock.code": "Code",
54737
+ "app.client.taskContextBlock.context": "Context",
54738
+ "app.client.taskContextBlock.element": "Element",
54739
+ "app.client.taskContextBlock.page": "Page",
54740
+ "app.client.taskContextBlock.screenshot": "The page around the comment, with its point marked",
54741
+ "app.client.taskContextBlock.source": "Source",
54742
+ "app.client.taskContextBlock.viewport": "Viewport",
53978
54743
  "app.client.taskDiscussion.addContextPlaceholder": "Add context for your team…",
53979
54744
  "app.client.taskDiscussion.addTaskComment": "Add task comment",
53980
54745
  "app.client.taskDiscussion.cancel": "Cancel",
@@ -54004,6 +54769,7 @@ var en = {
54004
54769
  },
54005
54770
  "app.client.threadLinks.taskDiscussionNeedsLinkedTask": "A task discussion needs at least one linked task.",
54006
54771
  "app.client.threadLinks.taskLinkChangeNotConfirmed": "The task link change was not confirmed. Review the latest links before saving again.",
54772
+ "app.client.workspace.agentView": "{task} · Agent",
54007
54773
  "app.client.workspace.connectProjectToOpenDiscussion": "Connect a project to open this discussion.",
54008
54774
  "app.client.workspace.couldNotOpenDiscussion": "Could not open this discussion.",
54009
54775
  "app.client.workspace.discussion": "Discussion",
@@ -54014,6 +54780,19 @@ var en = {
54014
54780
  "app.client.workspace.startProjectWithBudVitePlugin": "Start your project with the Bud Vite plugin, or run Bud from its directory. Its screens appear here when the companion connects.",
54015
54781
  "app.client.workspace.yourProjectSideBySide": "Your project, side by side.",
54016
54782
  "app.controller.discussion": "Discussion",
54783
+ "app.server.commentTask.discussion": "Discussion",
54784
+ "app.server.commentTask.element": "Element",
54785
+ "app.server.commentTask.linkedTasks": "linked tasks",
54786
+ "app.server.commentTask.replies": "Replies",
54787
+ "app.server.commentTask.replyCount": {
54788
+ one: "{count} reply",
54789
+ other: "{count} replies"
54790
+ },
54791
+ "app.server.commentTask.source": "Source",
54792
+ "app.server.commentTask.title": "Comment on {place}",
54793
+ "app.server.commentTask.uncommitted": "uncommitted",
54794
+ "app.server.commentTask.where": "Where",
54795
+ "app.server.commentTask.workingTree": "working tree",
54017
54796
  "appShell.mainNavigation": "Main navigation",
54018
54797
  "breadcrumb.navigationLabel": "Breadcrumb",
54019
54798
  "canvas.artboardCanvas.chooseCollectionPage": "Choose a {collection} page",
@@ -54059,7 +54838,6 @@ var en = {
54059
54838
  "canvas.canvasWorkspace.interactWithPages": "Interact with pages",
54060
54839
  "canvas.canvasWorkspace.newComment": "New comment",
54061
54840
  "canvas.canvasWorkspace.panCanvas": "Pan canvas",
54062
- "canvas.canvasWorkspace.reload": "Reload",
54063
54841
  "canvas.canvasWorkspace.savingComments": "Saving comments",
54064
54842
  "canvas.canvasWorkspace.showDarkPages": "Show dark pages",
54065
54843
  "canvas.canvasWorkspace.showFullPages": "Show full pages",
@@ -54872,6 +55650,33 @@ var en = {
54872
55650
  other: "{count} tabs"
54873
55651
  },
54874
55652
  "shellTabBar.tabsLabel": "Tabs",
55653
+ "tasks.agentBrowser.address": "Preview address",
55654
+ "tasks.agentBrowser.asleep": "The sandbox is asleep to save costs.",
55655
+ "tasks.agentBrowser.back": "Back",
55656
+ "tasks.agentBrowser.commentOnElement": "Comment on an element for the agent",
55657
+ "tasks.agentBrowser.forward": "Forward",
55658
+ "tasks.agentBrowser.newComment": "Change for the agent",
55659
+ "tasks.agentBrowser.noPreview": "The preview shows here while the run’s sandbox is up with its dev server.",
55660
+ "tasks.agentBrowser.openInNewWindow": "Open the preview in a new window",
55661
+ "tasks.agentBrowser.preview": "Live preview",
55662
+ "tasks.agentBrowser.reload": "Reload",
55663
+ "tasks.agentBrowser.status": "Preview status",
55664
+ "tasks.agentBrowser.tryAgain": "Try again",
55665
+ "tasks.agentBrowser.wake": "Wake it",
55666
+ "tasks.agentBrowser.waking": "Waking the sandbox…",
55667
+ "tasks.agentTerminal.disconnected": "Reconnecting…",
55668
+ "tasks.agentTerminal.sessions": "Terminal sessions",
55669
+ "tasks.agentTerminal.terminal": "{name} terminal",
55670
+ "tasks.agentView.agentPanes": "Browser or terminal",
55671
+ "tasks.agentView.browser": "Browser",
55672
+ "tasks.agentView.browserAndTerminal": "Browser & terminal",
55673
+ "tasks.agentView.details": "Details",
55674
+ "tasks.agentView.hideTerminal": "Hide terminal",
55675
+ "tasks.agentView.showTerminal": "Show terminal",
55676
+ "tasks.agentView.terminal": "Terminal",
55677
+ "tasks.agentView.terminalBelow": "Terminal below the browser",
55678
+ "tasks.agentView.terminalBeside": "Terminal beside the browser",
55679
+ "tasks.agentView.view": "Agent view",
54875
55680
  "tasks.taskActions.actionInProgress": "A task action is already in progress.",
54876
55681
  "tasks.taskActions.actions": "Actions",
54877
55682
  "tasks.taskActions.changeNotConfirmed": "The change was not confirmed. Refresh before trying again.",
@@ -54923,9 +55728,12 @@ var en = {
54923
55728
  "tasks.taskData.label.feature": "Feature",
54924
55729
  "tasks.taskData.label.hooked": "Hooked",
54925
55730
  "tasks.taskData.label.in_progress": "In progress",
55731
+ "tasks.taskData.label.merged": "Merged",
55732
+ "tasks.taskData.label.needs_approval": "Needs approval",
54926
55733
  "tasks.taskData.label.open": "Open",
54927
55734
  "tasks.taskData.label.pinned": "Pinned",
54928
55735
  "tasks.taskData.label.ready": "Ready",
55736
+ "tasks.taskData.label.ready_to_merge": "Ready to merge",
54929
55737
  "tasks.taskData.label.task": "Task",
54930
55738
  "tasks.taskData.low": "Low",
54931
55739
  "tasks.taskData.noEpic": "No epic",
@@ -55011,6 +55819,49 @@ var en = {
55011
55819
  "tasks.taskMarkdown.completedItem": "Completed item",
55012
55820
  "tasks.taskMarkdown.image": "Image",
55013
55821
  "tasks.taskMarkdown.incompleteItem": "Incomplete item",
55822
+ "tasks.taskRunBadge.failed": "Run failed",
55823
+ "tasks.taskRunBadge.merged": "Merged",
55824
+ "tasks.taskRunBadge.needsContext": "Needs context",
55825
+ "tasks.taskRunBadge.pushed": "Pushed",
55826
+ "tasks.taskRunBadge.pushing": "Pushing",
55827
+ "tasks.taskRunBadge.review": "Needs approval",
55828
+ "tasks.taskRunBadge.settingUp": "Setting up",
55829
+ "tasks.taskRunBadge.working": "Agent working",
55830
+ "tasks.taskRunPanel.activity": "Agent activity",
55831
+ "tasks.taskRunPanel.agent": "Agent",
55832
+ "tasks.taskRunPanel.answer": "Answer the agent",
55833
+ "tasks.taskRunPanel.answerPlaceholder": "What does the agent need to know?",
55834
+ "tasks.taskRunPanel.approve": "Approve & push",
55835
+ "tasks.taskRunPanel.asleep": "The sandbox sleeps to save cost. It wakes up when you open the preview, request changes or approve.",
55836
+ "tasks.taskRunPanel.cancel": "Cancel",
55837
+ "tasks.taskRunPanel.changesPlaceholder": "What should the agent change?",
55838
+ "tasks.taskRunPanel.confirmApprove": "Push {branch} to the repository?",
55839
+ "tasks.taskRunPanel.confirmDiscard": "Discard this run and its sandbox? Nothing was pushed.",
55840
+ "tasks.taskRunPanel.discard": "Discard",
55841
+ "tasks.taskRunPanel.failed": "The run failed.",
55842
+ "tasks.taskRunPanel.loading": "Loading the run…",
55843
+ "tasks.taskRunPanel.merged": "{branch} is merged.",
55844
+ "tasks.taskRunPanel.minutes": {
55845
+ one: "1 min",
55846
+ other: "{count} min"
55847
+ },
55848
+ "tasks.taskRunPanel.needsContext": "The agent needs more context to go on.",
55849
+ "tasks.taskRunPanel.preview": "Open live preview",
55850
+ "tasks.taskRunPanel.pushed": "Pushed {branch} at {commit}.",
55851
+ "tasks.taskRunPanel.pushing": "Pushing {branch}…",
55852
+ "tasks.taskRunPanel.requestChanges": "Request changes",
55853
+ "tasks.taskRunPanel.retry": "Retry",
55854
+ "tasks.taskRunPanel.review": "The agent is done and waits for your review.",
55855
+ "tasks.taskRunPanel.seconds": {
55856
+ one: "1 s",
55857
+ other: "{count} s"
55858
+ },
55859
+ "tasks.taskRunPanel.settingUp": "Setting up the sandbox…",
55860
+ "tasks.taskRunPanel.showOnCanvas": "Show on canvas",
55861
+ "tasks.taskRunPanel.start": "Start task",
55862
+ "tasks.taskRunPanel.startAgain": "Start again",
55863
+ "tasks.taskRunPanel.startHint": "An agent works on this task in a sandbox. Nothing is pushed until you approve.",
55864
+ "tasks.taskRunPanel.working": "The agent is working…",
55014
55865
  "tasks.taskSections.latestEvents": {
55015
55866
  one: "Showing the latest {count} event.",
55016
55867
  other: "Showing the latest {count} events."
@@ -55047,6 +55898,7 @@ var en = {
55047
55898
  "tasks.taskWorkspace.connectProject": "Connect a project",
55048
55899
  "tasks.taskWorkspace.createTask": "Create task",
55049
55900
  "tasks.taskWorkspace.createToPlan": "Create a task to start planning your work.",
55901
+ "tasks.taskWorkspace.fewerStatuses": "Show fewer statuses",
55050
55902
  "tasks.taskWorkspace.filterEpic": "Filter epic",
55051
55903
  "tasks.taskWorkspace.filterField": "Filter {field}",
55052
55904
  "tasks.taskWorkspace.filters": "Filters",
@@ -55064,6 +55916,11 @@ var en = {
55064
55916
  "tasks.taskWorkspace.noMatches": "No tasks match this view",
55065
55917
  "tasks.taskWorkspace.noRemote": "No {label} remote is configured",
55066
55918
  "tasks.taskWorkspace.noWorkspace": "No {label} workspace yet",
55919
+ "tasks.taskWorkspace.otherStatuses": {
55920
+ one: "+1 in other statuses",
55921
+ other: "+{count} in other statuses"
55922
+ },
55923
+ "tasks.taskWorkspace.otherStatusesEmpty": "Other statuses",
55067
55924
  "tasks.taskWorkspace.priority": "Priority",
55068
55925
  "tasks.taskWorkspace.projectTasks": "Project tasks",
55069
55926
  "tasks.taskWorkspace.pullChanges": "Pull changes",
@@ -55084,6 +55941,10 @@ var en = {
55084
55941
  "tasks.taskWorkspace.searchPlaceholder": "Search tasks, IDs, labels…",
55085
55942
  "tasks.taskWorkspace.searchTasks": "Search tasks",
55086
55943
  "tasks.taskWorkspace.shareLocalChanges": "Share your local task changes",
55944
+ "tasks.taskWorkspace.showTasks": {
55945
+ one: "Show 1 task",
55946
+ other: "Show {count} tasks"
55947
+ },
55087
55948
  "tasks.taskWorkspace.showingCount": "Showing {shown} of {total}",
55088
55949
  "tasks.taskWorkspace.sortTasks": "Sort tasks",
55089
55950
  "tasks.taskWorkspace.startBud": "Start Bud from your web project to see its tasks.",
@@ -67907,50 +68768,6 @@ function CommentComposerCard(handle) {
67907
68768
  });
67908
68769
  }
67909
68770
  //#endregion
67910
- //#region ../../node_modules/.pnpm/@remix-run+fetch-router@1.0.0/node_modules/@remix-run/fetch-router/dist/lib/route-helpers/method.js
67911
- /**
67912
- * Shorthand for a GET route.
67913
- *
67914
- * @alias get
67915
- * @param pattern The route pattern string or pre-parsed AST
67916
- * @returns A Route configured for GET requests
67917
- */
67918
- function createGetRoute(pattern) {
67919
- return new Route$1("GET", pattern);
67920
- }
67921
- /**
67922
- * Shorthand for a POST route.
67923
- *
67924
- * @alias post
67925
- * @param pattern The route pattern string or pre-parsed AST
67926
- * @returns A Route configured for POST requests
67927
- */
67928
- function createPostRoute(pattern) {
67929
- return new Route$1("POST", pattern);
67930
- }
67931
- //#endregion
67932
- //#region ../ui/src/lib/routes.ts
67933
- /** Places in Bud's task screen, shared by links and the screen's matcher. */
67934
- var taskRoutes = createRoutes("/tasks", {
67935
- index: createGetRoute("/"),
67936
- show: createGetRoute("/:id")
67937
- });
67938
- /** Places in Bud's browser of the project's live pages: a page's own path follows the screen's. */
67939
- var pageRoutes = createRoutes("/pages", {
67940
- index: createGetRoute("/"),
67941
- page: createGetRoute("/*path")
67942
- });
67943
- /** Places in Bud's file browser and review. */
67944
- var fileRoutes = createRoutes("/files", {
67945
- index: createGetRoute("/"),
67946
- file: createGetRoute("/*path"),
67947
- escaped: createGetRoute("/path/*path"),
67948
- review: createGetRoute("/review/:mode(/*path)"),
67949
- compare: createGetRoute("/compare/:base...:target(/*path)")
67950
- });
67951
- /** A conversation's stable place, independent of its canvas or code anchor. */
67952
- var conversationRoutes = createRoutes("/comments", { show: createGetRoute("/:id") });
67953
- //#endregion
67954
68771
  //#region ../ui/src/lib/files/file-location.ts
67955
68772
  var matcher = createMultiMatcher();
67956
68773
  for (let [name, route] of Object.entries(fileRoutes)) matcher.add(route.pattern, name);
@@ -68693,6 +69510,7 @@ function taskFields(item, schema) {
68693
69510
  //#endregion
68694
69511
  //#region ../ui/src/lib/tasks/task-data.ts
68695
69512
  var taskMatcher = createMatcher(taskRoutes.show.pattern);
69513
+ var agentMatcher = createMatcher(taskRoutes.agent.pattern);
68696
69514
  var defaultTaskView = {
68697
69515
  query: "",
68698
69516
  fields: {},
@@ -68874,6 +69692,26 @@ function taskHref(id) {
68874
69692
  }
68875
69693
  }
68876
69694
  /**
69695
+ * Builds the URL of a task's Agent view: its details beside its run's preview and terminal.
69696
+ * @param id - The task's id.
69697
+ * @returns The typed URL.
69698
+ */
69699
+ function taskAgentHref(id) {
69700
+ return taskRoutes.agent.href({ id: parseWorkItemRef({ id }).id });
69701
+ }
69702
+ /**
69703
+ * Whether a location is a task's Agent view.
69704
+ * @param location - The current location.
69705
+ * @returns True for `/tasks/:id/agent`.
69706
+ */
69707
+ function agentViewOpen(location) {
69708
+ try {
69709
+ return Boolean(agentMatcher.match(new URL(location, "http://bud.invalid/tasks")));
69710
+ } catch {
69711
+ return false;
69712
+ }
69713
+ }
69714
+ /**
68877
69715
  * Reads the typed task place, or one older query selection on the board URL.
68878
69716
  * @param location - The current location or legacy query link.
68879
69717
  * @returns The validated task ID, or null for the board or an invalid link.
@@ -68882,7 +69720,7 @@ function selectedTask(location) {
68882
69720
  try {
68883
69721
  let url = new URL(location, "http://bud.invalid/tasks");
68884
69722
  if (url.href.length > 32768) return null;
68885
- let value = url.pathname === taskRoutes.index.href() && url.searchParams.getAll("issue").length === 1 ? url.searchParams.get("issue") : taskMatcher.match(url)?.params.id;
69723
+ let value = url.pathname === taskRoutes.index.href() && url.searchParams.getAll("issue").length === 1 ? url.searchParams.get("issue") : (taskMatcher.match(url) ?? agentMatcher.match(url))?.params.id;
68886
69724
  return value ? parseWorkItemRef({ id: value }).id : null;
68887
69725
  } catch {
68888
69726
  return null;
@@ -82270,40 +83108,6 @@ function object(value) {
82270
83108
  return value;
82271
83109
  }
82272
83110
  /**
82273
- * Checks a nonblank string within a length limit.
82274
- * @param value - Untrusted data.
82275
- * @param label - What the error message calls it.
82276
- * @param limit - The most characters it may have.
82277
- * @returns The string.
82278
- */
82279
- function text$4(value, label, limit) {
82280
- return parseRecord(bounded(label, limit), value);
82281
- }
82282
- /**
82283
- * Checks a conversation or message ID.
82284
- * @param value - Untrusted data.
82285
- * @returns The ID.
82286
- */
82287
- function conversationId(value) {
82288
- return parseRecord(ConversationIdSchema, value);
82289
- }
82290
- /**
82291
- * Checks a comments branch revision.
82292
- * @param value - Untrusted data.
82293
- * @returns The revision, or null before the branch's first commit.
82294
- */
82295
- function revision(value) {
82296
- return parseRecord(CommentRevisionSchema, value);
82297
- }
82298
- /**
82299
- * Checks a conversation status.
82300
- * @param value - Untrusted data.
82301
- * @returns The status.
82302
- */
82303
- function commentStatus(value) {
82304
- return parseRecord(CommentStatusSchema, value);
82305
- }
82306
- /**
82307
83111
  * Reads legacy page captures while discarding the extension properties older parsers ignored.
82308
83112
  * @param value - A stored canvas anchor.
82309
83113
  * @returns Its validated canonical capture.
@@ -82389,131 +83193,13 @@ function versioned(version, anchor) {
82389
83193
  anchor: thread.anchor
82390
83194
  }));
82391
83195
  }
82392
- /** A versioned conversation from the comments branch, read as leniently as earlier releases. */
82393
- var CommentThreadSchema = variant("version", {
82394
- 1: versioned(1, delegate(storedCanvasAnchor)),
82395
- 2: versioned(2, delegate(parseCodeAnchor))
82396
- });
82397
83196
  object$1({
82398
83197
  head: CommentRevisionSchema,
82399
- threads: list$1(CommentThreadSchema, "Invalid comments response.").refine((threads) => unique(threads, (thread) => thread.id), "Duplicate conversation ID.")
83198
+ threads: list$1(variant("version", {
83199
+ 1: versioned(1, delegate(storedCanvasAnchor)),
83200
+ 2: versioned(2, delegate(parseCodeAnchor))
83201
+ }), "Invalid comments response.").refine((threads) => unique(threads, (thread) => thread.id), "Duplicate conversation ID.")
82400
83202
  }).refine(({ head, threads }) => head !== null || !threads.length, "Comments are missing their Git revision.");
82401
- /**
82402
- * Validates a stored or requested thread.
82403
- * @param value - Untrusted data.
82404
- * @returns The thread.
82405
- */
82406
- function parseCommentThread(value) {
82407
- return parseRecord(CommentThreadSchema, value);
82408
- }
82409
- //#endregion
82410
- //#region ../comments/src/lib/input.ts
82411
- /** A browser's comment request is invalid; its message is safe to show. */
82412
- var CommentInputError = class extends Error {};
82413
- /**
82414
- * Validates a browser's request to start a conversation, or to reply to or update one.
82415
- * @param value - The request body.
82416
- * @param routes - The routes a new canvas conversation may belong to.
82417
- * @param id - The conversation being replied to or updated; absent for a new one.
82418
- * @returns The revision the request was based on and the change it asks for.
82419
- */
82420
- function parseCommentInput(value, routes, id) {
82421
- try {
82422
- let input = object(value);
82423
- let head = revision(input.head);
82424
- let body = input.body === void 0 ? void 0 : text$4(input.body, "Comment", 1e4).trim();
82425
- if (id !== void 0) {
82426
- conversationId(id);
82427
- let status = input.status === void 0 ? void 0 : commentStatus(input.status);
82428
- if (!body && !status) throw new Error("Add a reply or choose a status.");
82429
- let parentId = input.parentId == null ? null : conversationId(input.parentId);
82430
- if (parentId && !body) throw new Error("A reply needs a message.");
82431
- return {
82432
- head,
82433
- change: {
82434
- id,
82435
- body,
82436
- status,
82437
- ...input.parentId === void 0 ? {} : { parentId }
82438
- }
82439
- };
82440
- }
82441
- if (!body) throw new Error("Write a comment before saving.");
82442
- if (input.parentId != null) throw new Error("A new conversation cannot have a parent message.");
82443
- if (object(input.anchor).type === "code") return {
82444
- head,
82445
- change: {
82446
- anchor: parseCodeAnchor(input.anchor),
82447
- body
82448
- }
82449
- };
82450
- let anchor = parseCanvasAnchor(input.anchor);
82451
- if (!routes.some((route) => route.id === anchor.pageId && route.path === anchor.pagePath)) throw new Error("The comment must belong to a configured route.");
82452
- return {
82453
- head,
82454
- change: {
82455
- anchor,
82456
- body
82457
- }
82458
- };
82459
- } catch (error) {
82460
- throw new CommentInputError(error instanceof Error ? error.message : "Invalid comment.");
82461
- }
82462
- }
82463
- //#endregion
82464
- //#region ../comments/src/lib/merge.ts
82465
- /** Two versions of a thread conflict and need resolving in Git by hand. */
82466
- var CommentMergeError = class extends Error {};
82467
- /**
82468
- * Serializes a value as JSON with sorted object keys, so equal records compare equal.
82469
- * @param value - The value to serialize.
82470
- * @returns Its JSON text.
82471
- */
82472
- function stableJson(value) {
82473
- if (value === null || typeof value !== "object") return JSON.stringify(value);
82474
- if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
82475
- return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, child]) => `${JSON.stringify(key)}:${stableJson(child)}`).join(",")}}`;
82476
- }
82477
- /**
82478
- * Merges two versions of one thread: their messages combine and a status change on one side wins.
82479
- * @param local - This checkout's version.
82480
- * @param remote - The fetched version.
82481
- * @param base - Their common ancestor, when there is one.
82482
- * @returns The merged thread, or throws a CommentMergeError when they conflict.
82483
- */
82484
- function mergeThreads(local, remote, base) {
82485
- local = parseCommentThread(local);
82486
- remote = parseCommentThread(remote);
82487
- if (base) base = parseCommentThread(base);
82488
- let { comments: localComments, status: localStatus, updatedAt: localTime, ...localIdentity } = local;
82489
- let { comments: remoteComments, status: remoteStatus, updatedAt: remoteTime, ...remoteIdentity } = remote;
82490
- let baseIdentity = base && {
82491
- version: base.version,
82492
- id: base.id,
82493
- project: base.project,
82494
- branch: base.branch,
82495
- createdCommit: base.createdCommit,
82496
- anchor: base.anchor,
82497
- createdAt: base.createdAt
82498
- };
82499
- if (stableJson(localIdentity) !== stableJson(remoteIdentity) || baseIdentity && stableJson(localIdentity) !== stableJson(baseIdentity)) throw new CommentMergeError("Conflicting thread anchors in the comments branch. Resolve this record in Git before syncing.");
82500
- if (stableJson(local) === stableJson(remote)) return local;
82501
- if (base && stableJson(local) === stableJson(base)) return remote;
82502
- if (base && stableJson(remote) === stableJson(base)) return local;
82503
- let comments = /* @__PURE__ */ new Map();
82504
- for (let comment of [...localComments, ...remoteComments]) {
82505
- if (comments.has(comment.id) && stableJson(comments.get(comment.id)) !== stableJson(comment)) throw new CommentMergeError("Conflicting versions of a comment. Resolve this record in Git before syncing.");
82506
- comments.set(comment.id, comment);
82507
- }
82508
- let status = localStatus === base?.status ? remoteStatus : remoteStatus === base?.status || localStatus === remoteStatus ? localStatus : void 0;
82509
- if (!status) throw new CommentMergeError("Conflicting thread statuses. Resolve this record in Git before syncing.");
82510
- return {
82511
- ...local,
82512
- status,
82513
- updatedAt: localTime > remoteTime ? localTime : remoteTime,
82514
- comments: [...comments.values()].sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id))
82515
- };
82516
- }
82517
83203
  //#endregion
82518
83204
  //#region ../ui/src/lib/canvas/coordinates.ts
82519
83205
  /**
@@ -82980,23 +83666,13 @@ function CanvasWorkspace(handle) {
82980
83666
  if (zoomLabel) zoomLabel.textContent = `${Math.round(scale * 100)}%`;
82981
83667
  }
82982
83668
  }),
82983
- handle.props.error || handle.props.commentsUnavailable || notice ? /* @__PURE__ */ jsx("div", {
82984
- role: handle.props.error ? "alert" : "status",
82985
- class: `absolute top-3 left-3 max-w-[calc(100%-24px)] bud-overlay rounded-lg px-3 py-2 ${handle.props.error ? "text-red-500" : "text-muted"}`,
82986
- children: [/* @__PURE__ */ jsx(Text$1, {
83669
+ handle.props.commentsUnavailable || notice ? /* @__PURE__ */ jsx("div", {
83670
+ role: "status",
83671
+ class: "absolute top-3 left-3 max-w-[calc(100%-24px)] bud-overlay rounded-lg px-3 py-2 text-muted",
83672
+ children: /* @__PURE__ */ jsx(Text$1, {
82987
83673
  variant: "ui-caption",
82988
- children: handle.props.error || handle.props.commentsUnavailable || notice
82989
- }), handle.props.error ? /* @__PURE__ */ jsx("button", {
82990
- type: "button",
82991
- class: "ml-2 underline",
82992
- mix: on("click", () => {
82993
- handle.props.onReload?.();
82994
- }),
82995
- children: /* @__PURE__ */ jsx(Text$1, {
82996
- variant: "ui-caption",
82997
- children: t$2("canvas.canvasWorkspace.reload")
82998
- })
82999
- }) : null]
83674
+ children: handle.props.commentsUnavailable || notice
83675
+ })
83000
83676
  }) : null,
83001
83677
  panel && !handle.props.commentsUnavailable ? /* @__PURE__ */ jsx(ConversationSidebar, {
83002
83678
  threads: handle.props.snapshot.threads,
@@ -83480,6 +84156,85 @@ function TaskEditor(handle) {
83480
84156
  };
83481
84157
  }
83482
84158
  //#endregion
84159
+ //#region ../ui/src/lib/tasks/task-run-badge.tsx
84160
+ /**
84161
+ * What a factory run's badge says: busy states with a spinner, then review, a question for a
84162
+ * person, pushed or failed.
84163
+ * @param run - The run's state and error.
84164
+ * @returns Its tone, label and whether it spins, or null for a run that leaves no badge.
84165
+ */
84166
+ function taskRunBadge(run) {
84167
+ switch (run.state) {
84168
+ case "provisioning": return {
84169
+ tone: "busy",
84170
+ label: t$2("tasks.taskRunBadge.settingUp")
84171
+ };
84172
+ case "working":
84173
+ case "changes": return {
84174
+ tone: "busy",
84175
+ label: t$2("tasks.taskRunBadge.working")
84176
+ };
84177
+ case "review": return {
84178
+ tone: "review",
84179
+ label: t$2("tasks.taskRunBadge.review")
84180
+ };
84181
+ case "needs_context": return {
84182
+ tone: "question",
84183
+ label: t$2("tasks.taskRunBadge.needsContext")
84184
+ };
84185
+ case "approved":
84186
+ case "pushing": return {
84187
+ tone: "busy",
84188
+ label: t$2("tasks.taskRunBadge.pushing")
84189
+ };
84190
+ case "pushed": return {
84191
+ tone: "done",
84192
+ label: t$2("tasks.taskRunBadge.pushed")
84193
+ };
84194
+ case "merged": return {
84195
+ tone: "done",
84196
+ label: t$2("tasks.taskRunBadge.merged")
84197
+ };
84198
+ case "failed": return {
84199
+ tone: "failed",
84200
+ label: t$2("tasks.taskRunBadge.failed")
84201
+ };
84202
+ default: return null;
84203
+ }
84204
+ }
84205
+ var tones = {
84206
+ busy: "text-muted",
84207
+ review: "text-amber-600 dark:text-amber-400",
84208
+ question: "text-violet-600 dark:text-violet-400",
84209
+ done: "text-emerald-600 dark:text-emerald-400",
84210
+ failed: "text-red-600 dark:text-red-400"
84211
+ };
84212
+ /**
84213
+ * A task card's factory run badge: where the agent's run is, with a failed run's reason on hover.
84214
+ * @param handle - The run's summary.
84215
+ * @returns The badge render function; nothing for a run that leaves no badge.
84216
+ */
84217
+ function TaskRunBadge(handle) {
84218
+ return () => {
84219
+ let badge = taskRunBadge(handle.props.run);
84220
+ if (!badge) return null;
84221
+ return /* @__PURE__ */ jsx("span", {
84222
+ class: `flex min-w-0 items-center gap-1 ${tones[badge.tone]}`,
84223
+ title: handle.props.run.error ?? void 0,
84224
+ "data-testid": "task-run-badge",
84225
+ "data-state": handle.props.run.state,
84226
+ children: [badge.tone === "busy" ? /* @__PURE__ */ jsx(Spinner, { size: 11 }) : /* @__PURE__ */ jsx(Icon$1, {
84227
+ name: badge.tone === "failed" ? "circle-alert" : handle.props.run.state === "merged" ? "circle-check" : badge.tone === "done" ? "push" : badge.tone === "question" ? "message" : "circle-dot",
84228
+ size: 12
84229
+ }), /* @__PURE__ */ jsx(Text$1, {
84230
+ variant: "ui-caption",
84231
+ class: "truncate",
84232
+ children: badge.label
84233
+ })]
84234
+ });
84235
+ };
84236
+ }
84237
+ //#endregion
83483
84238
  //#region ../ui/src/lib/tasks/task-card.tsx
83484
84239
  var statusTone = {
83485
84240
  backlog: "bg-violet-400",
@@ -83519,7 +84274,8 @@ function TaskCard(handle) {
83519
84274
  let issue = taskFields(item, schema);
83520
84275
  let linked = issue.dependencyCount ?? issue.dependencies.length;
83521
84276
  let dependents = issue.dependentCount ?? issue.dependents.length;
83522
- let hasMeta = ready || blocked || !!issue.assignee || !!issue.parentId || !!linked || !!dependents || !!issue.commentCount;
84277
+ let run = item.run && taskRunBadge(item.run) ? item.run : null;
84278
+ let hasMeta = !!run || ready || blocked || !!issue.assignee || !!issue.parentId || !!linked || !!dependents || !!issue.commentCount;
83523
84279
  let priority = /* @__PURE__ */ jsx(Text$1, {
83524
84280
  variant: "ui-caption",
83525
84281
  weight: "medium",
@@ -83528,6 +84284,7 @@ function TaskCard(handle) {
83528
84284
  children: typeof issue.priority === "number" ? `P${issue.priority}` : issue.priorityLabel
83529
84285
  });
83530
84286
  let meta = /* @__PURE__ */ jsx(Fragment, { children: [
84287
+ run ? /* @__PURE__ */ jsx(TaskRunBadge, { run }) : null,
83531
84288
  ready ? /* @__PURE__ */ jsx("span", {
83532
84289
  class: "flex items-center gap-1 text-emerald-600 dark:text-emerald-400",
83533
84290
  children: [/* @__PURE__ */ jsx(Icon$1, {
@@ -99204,6 +99961,7 @@ function TaskDetails(handle) {
99204
99961
  ]
99205
99962
  }),
99206
99963
  children: [
99964
+ handle.props.actions ?? null,
99207
99965
  /* @__PURE__ */ jsx(IconButton, {
99208
99966
  icon: "link",
99209
99967
  label: t$2("tasks.taskDetails.copyTaskLink"),
@@ -99229,13 +99987,13 @@ function TaskDetails(handle) {
99229
99987
  }),
99230
99988
  /* @__PURE__ */ jsx("div", {
99231
99989
  "data-task-detail-scroll": "",
99232
- class: "flex min-h-0 flex-1 flex-col overflow-y-auto overscroll-contain",
99990
+ class: "@container/page flex min-h-0 flex-1 flex-col overflow-y-auto overscroll-contain",
99233
99991
  "aria-busy": loading ? "true" : "false",
99234
99992
  mix: scrollFade("y"),
99235
99993
  children: [
99236
99994
  loading && !issue ? /* @__PURE__ */ jsx(Loader, { label: t$2("tasks.taskDetails.loadingTask") }) : null,
99237
99995
  error ? /* @__PURE__ */ jsx("div", {
99238
- class: "px-4 pb-6 md:px-6",
99996
+ class: "px-4 pb-6 @min-[40rem]/page:px-6",
99239
99997
  children: /* @__PURE__ */ jsx(FieldCard, {
99240
99998
  class: "max-w-2xl",
99241
99999
  role: "alert",
@@ -99250,7 +100008,7 @@ function TaskDetails(handle) {
99250
100008
  })
99251
100009
  }) : null,
99252
100010
  issue && item && detail ? /* @__PURE__ */ jsx("div", {
99253
- class: "mx-auto grid w-full max-w-6xl gap-8 px-4 pt-6 pb-12 md:px-6 lg:grid-cols-[minmax(0,1fr)_18rem] lg:gap-12",
100011
+ class: "mx-auto grid w-full max-w-6xl gap-8 px-4 pt-6 pb-12 @min-[40rem]/page:px-6 @min-[56rem]/page:grid-cols-[minmax(0,1fr)_18rem] @min-[56rem]/page:gap-12",
99254
100012
  children: [/* @__PURE__ */ jsx("article", {
99255
100013
  class: "flex min-w-0 flex-col gap-8",
99256
100014
  children: [
@@ -99372,7 +100130,7 @@ function TaskDetails(handle) {
99372
100130
  })
99373
100131
  ]
99374
100132
  }), /* @__PURE__ */ jsx("aside", {
99375
- class: "flex min-w-0 flex-col gap-4 lg:sticky lg:top-6 lg:self-start",
100133
+ class: "flex min-w-0 flex-col gap-4 @min-[56rem]/page:sticky @min-[56rem]/page:top-6 @min-[56rem]/page:self-start",
99376
100134
  children: [/* @__PURE__ */ jsx(Properties, {
99377
100135
  ...context,
99378
100136
  item,
@@ -99557,6 +100315,8 @@ function TaskWorkspace(handle) {
99557
100315
  }
99558
100316
  return draft;
99559
100317
  }
100318
+ let expanded = /* @__PURE__ */ new Set();
100319
+ let allColumns = false;
99560
100320
  async function move(id, status) {
99561
100321
  let issue = handle.props.snapshot?.items.find((candidate) => candidate.id === id);
99562
100322
  if (!issue || !handle.props.operations || actionBusy || !handle.props.schema || taskRole(issue, handle.props.schema, "status") === status) return;
@@ -99649,7 +100409,12 @@ function TaskWorkspace(handle) {
99649
100409
  restore = null;
99650
100410
  handle.queueTask(() => scroll?.scrollTo(position));
99651
100411
  }
99652
- let statuses = schema ? taskStatuses(schema, snapshot?.items) : [];
100412
+ let allStatuses = schema ? taskStatuses(schema, snapshot?.items) : [];
100413
+ let columns = handle.props.columns;
100414
+ let arranged = columns ? [...columns.shown, ...columns.collapsed ?? []].flatMap((value) => allStatuses.filter((status) => status.value === value)) : allStatuses;
100415
+ let statuses = columns && !allColumns && !view.status ? arranged : allStatuses;
100416
+ let hiddenStatuses = allStatuses.filter((status) => !arranged.includes(status));
100417
+ let hiddenTasks = (snapshot?.items ?? []).filter((item) => hiddenStatuses.some((status) => status.value === taskRole(item, schema, "status"))).length;
99653
100418
  let ready = new Set(snapshot?.items.filter((item) => item.ready).map((item) => item.id) ?? []);
99654
100419
  let activeFilters = [
99655
100420
  view.status,
@@ -100141,10 +100906,11 @@ function TaskWorkspace(handle) {
100141
100906
  })
100142
100907
  })] }) : /* @__PURE__ */ jsx("div", {
100143
100908
  class: "flex items-start gap-3",
100144
- children: statuses.filter((status) => !view.status || view.status === status.value).map((status) => {
100909
+ children: [statuses.filter((status) => !view.status || view.status === status.value).map((status) => {
100145
100910
  let issues = group.issues.filter((issue) => taskRole(issue, schema, "status") === status.value);
100911
+ let collapsedColumn = !!columns?.collapsed?.includes(status.value) && !expanded.has(status.value) && issues.length > 0;
100146
100912
  return /* @__PURE__ */ jsx("section", {
100147
- class: `flex flex-col gap-2 ${issues.length ? "min-w-60 max-w-sm flex-1 basis-0" : "w-32 shrink-0"}`,
100913
+ class: `flex flex-col gap-2 ${issues.length && !collapsedColumn ? "min-w-60 max-w-sm flex-1 basis-0" : "w-max min-w-32 max-w-48 shrink-0"}`,
100148
100914
  "aria-label": t$2("tasks.taskWorkspace.statusColumn", { status: status.label }),
100149
100915
  mix: [on("dragover", (event) => {
100150
100916
  if (event.dataTransfer?.types.includes("application/x-bud-task") && !actionBusy && status.value) {
@@ -100163,10 +100929,29 @@ function TaskWorkspace(handle) {
100163
100929
  item: null,
100164
100930
  status,
100165
100931
  items: issues,
100166
- children: issues.map(renderCard)
100932
+ children: collapsedColumn ? /* @__PURE__ */ jsx(Button, {
100933
+ variant: "ghost",
100934
+ size: "small",
100935
+ class: "justify-start",
100936
+ mix: on("click", () => {
100937
+ expanded.add(status.value);
100938
+ handle.update();
100939
+ }),
100940
+ children: t$2("tasks.taskWorkspace.showTasks", { count: issues.length })
100941
+ }) : issues.map(renderCard)
100167
100942
  })
100168
100943
  }, status.value);
100169
- })
100944
+ }), columns && !view.status && (hiddenStatuses.length || allColumns) ? /* @__PURE__ */ jsx(Button, {
100945
+ variant: "ghost",
100946
+ size: "small",
100947
+ class: "mt-1 shrink-0",
100948
+ "data-testid": "board-other-statuses",
100949
+ mix: on("click", () => {
100950
+ allColumns = !allColumns;
100951
+ handle.update();
100952
+ }),
100953
+ children: allColumns ? t$2("tasks.taskWorkspace.fewerStatuses") : hiddenTasks ? t$2("tasks.taskWorkspace.otherStatuses", { count: hiddenTasks }) : t$2("tasks.taskWorkspace.otherStatusesEmpty")
100954
+ }) : null]
100170
100955
  })]
100171
100956
  }, group.id)) : null
100172
100957
  ]
@@ -100198,7 +100983,7 @@ function TaskWorkspace(handle) {
100198
100983
  }
100199
100984
  })
100200
100985
  }) : null,
100201
- selectedId && schema ? /* @__PURE__ */ createElement(Page, {
100986
+ selectedId && schema ? (handle.props.pageFrame ?? ((page) => page))(/* @__PURE__ */ createElement(Page, {
100202
100987
  ...context(detail?.item.id === selectedId ? detail.item : null),
100203
100988
  item: detail?.item.id === selectedId ? detail.item : null,
100204
100989
  design: handle.props.design,
@@ -100215,10 +101000,876 @@ function TaskWorkspace(handle) {
100215
101000
  loading: detailLoading,
100216
101001
  error: detailError,
100217
101002
  onSelect: select,
100218
- onReload: onReloadDetail
101003
+ onReload: onReloadDetail,
101004
+ actions: handle.props.pageActions
101005
+ })) : null
101006
+ ] })
101007
+ });
101008
+ };
101009
+ }
101010
+ //#endregion
101011
+ //#region ../ui/src/lib/tasks/agent-terminal.tsx
101012
+ function Session(handle) {
101013
+ let state = "connecting";
101014
+ let term = null;
101015
+ let mount = ref((node, signal) => {
101016
+ (async () => {
101017
+ let { WTerm } = await import("./dist-BCSTeNf4.js");
101018
+ if (signal.aborted) return;
101019
+ let connection = null;
101020
+ let size = {
101021
+ cols: 0,
101022
+ rows: 0
101023
+ };
101024
+ let resizing;
101025
+ let pending = [];
101026
+ let instance = new WTerm(node, {
101027
+ cursorBlink: true,
101028
+ renderingPaused: !handle.props.active,
101029
+ onData: (data) => connection ? connection.input(data) : pending.push(data),
101030
+ onResize: (cols, rows) => {
101031
+ clearTimeout(resizing);
101032
+ resizing = setTimeout(() => {
101033
+ if (cols === size.cols && rows === size.rows) return;
101034
+ size = {
101035
+ cols,
101036
+ rows
101037
+ };
101038
+ connection?.resize(cols, rows);
101039
+ }, 150);
101040
+ }
101041
+ });
101042
+ await instance.init();
101043
+ if (signal.aborted) return instance.destroy();
101044
+ requestAnimationFrame(() => {
101045
+ if (!signal.aborted) instance.fit();
101046
+ });
101047
+ document.fonts?.ready.then(() => {
101048
+ if (!signal.aborted) instance.fit();
101049
+ });
101050
+ term = instance;
101051
+ signal.addEventListener("abort", () => instance.destroy(), { once: true });
101052
+ size = {
101053
+ cols: instance.cols,
101054
+ rows: instance.rows
101055
+ };
101056
+ connection = handle.props.connect(handle.props.tab.id, size, {
101057
+ write: (bytes) => instance.write(bytes),
101058
+ state: (next) => {
101059
+ state = next;
101060
+ if (!signal.aborted) handle.update();
101061
+ }
101062
+ }, signal);
101063
+ for (let data of pending.splice(0)) connection.input(data);
101064
+ if (handle.props.active) instance.focus();
101065
+ })();
101066
+ });
101067
+ let shown = false;
101068
+ return () => {
101069
+ let { active, tab } = handle.props;
101070
+ if (active !== shown) {
101071
+ shown = active;
101072
+ term?.setRenderingPaused(!active);
101073
+ if (active) handle.queueTask(() => {
101074
+ term?.fit();
101075
+ term?.focus();
101076
+ });
101077
+ }
101078
+ return /* @__PURE__ */ jsx("div", {
101079
+ class: `absolute inset-0 ${active ? "" : "invisible"}`,
101080
+ "aria-hidden": active ? void 0 : "true",
101081
+ inert: active ? void 0 : true,
101082
+ "data-terminal-tab": tab.id,
101083
+ "data-terminal-state": state,
101084
+ children: [/* @__PURE__ */ jsx("div", {
101085
+ class: "bud-terminal absolute inset-0 overflow-hidden",
101086
+ "aria-label": t$2("tasks.agentTerminal.terminal", { name: tab.label }),
101087
+ mix: mount
101088
+ }), state === "closed" ? /* @__PURE__ */ jsx(Text$1, {
101089
+ variant: "ui-caption",
101090
+ tone: "muted",
101091
+ class: "bud-overlay pointer-events-none absolute right-3 bottom-3 rounded-lg px-2.5 py-1",
101092
+ children: t$2("tasks.agentTerminal.disconnected")
101093
+ }) : null]
101094
+ });
101095
+ };
101096
+ }
101097
+ /**
101098
+ * The terminal in Agent view, on @wterm/dom: one session per tab, kept while another tab shows so
101099
+ * its output stays, connected through the app's broker.
101100
+ * @param handle - The tabs, the shown one and how to connect a tab.
101101
+ * @returns The terminal's render function.
101102
+ */
101103
+ function AgentTerminal(handle) {
101104
+ let opened = /* @__PURE__ */ new Set();
101105
+ return () => {
101106
+ let { tabs, active, connect } = handle.props;
101107
+ opened.add(active);
101108
+ return /* @__PURE__ */ jsx("div", {
101109
+ class: "absolute inset-0",
101110
+ "data-testid": "agent-terminal",
101111
+ children: tabs.filter((tab) => opened.has(tab.id)).map((tab) => /* @__PURE__ */ jsx(Session, {
101112
+ tab,
101113
+ connect,
101114
+ active: tab.id === active
101115
+ }, tab.id))
101116
+ });
101117
+ };
101118
+ }
101119
+ //#endregion
101120
+ //#region ../ui/src/lib/tasks/agent-view.tsx
101121
+ var LAYOUT = "bud:agent-view";
101122
+ /**
101123
+ * Reads the person's Agent view layout.
101124
+ * @param value - The stored preference.
101125
+ * @returns The layout, with the terminal shown beside the browser by default.
101126
+ */
101127
+ function agentLayout(value) {
101128
+ let input = value ?? {};
101129
+ return {
101130
+ terminal: input.terminal !== false,
101131
+ placement: input.placement === "below" ? "below" : "right"
101132
+ };
101133
+ }
101134
+ function Segments(handle) {
101135
+ return () => /* @__PURE__ */ jsx("div", {
101136
+ role: "group",
101137
+ "aria-label": handle.props.label,
101138
+ class: `bud-segmented ${handle.props.class ?? ""}`,
101139
+ children: handle.props.options.map((option) => /* @__PURE__ */ jsx("button", {
101140
+ type: "button",
101141
+ "aria-pressed": handle.props.value === option.id ? "true" : "false",
101142
+ "data-agent-pane": option.id,
101143
+ mix: on("click", () => handle.props.onChange(option.id)),
101144
+ children: [/* @__PURE__ */ jsx(Icon$1, {
101145
+ name: option.icon,
101146
+ size: 15
101147
+ }), /* @__PURE__ */ jsx(Text$1, {
101148
+ variant: "ui",
101149
+ class: "@max-[24rem]/agent:sr-only",
101150
+ children: option.label
101151
+ })]
101152
+ }, option.id))
101153
+ });
101154
+ }
101155
+ /**
101156
+ * Agent view: a task's details beside the browser on its run's preview and the terminal. It lays
101157
+ * itself out by the room it has (container queries), so it works in tabs and side panels too:
101158
+ * with little room a switch at the top picks details or the agent's panes, and in a narrow agent
101159
+ * column a switch in the browser's toolbar picks the browser or the terminal, unless the terminal
101160
+ * sits below the browser. The layout is remembered per person.
101161
+ * @param handle - The details, the browser and the terminal.
101162
+ * @returns The view's render function.
101163
+ */
101164
+ function AgentView(handle) {
101165
+ let layout = agentLayout(readPreference(LAYOUT));
101166
+ let panes = {
101167
+ main: "agent",
101168
+ agent: "browser"
101169
+ };
101170
+ let setLayout = (next) => {
101171
+ layout = {
101172
+ ...layout,
101173
+ ...next
101174
+ };
101175
+ writePreference(LAYOUT, layout);
101176
+ if (next.terminal) panes = {
101177
+ ...panes,
101178
+ agent: "terminal"
101179
+ };
101180
+ if (next.terminal === false) panes = {
101181
+ ...panes,
101182
+ agent: "browser"
101183
+ };
101184
+ handle.update();
101185
+ };
101186
+ let setPanes = (next) => {
101187
+ panes = {
101188
+ ...panes,
101189
+ ...next
101190
+ };
101191
+ handle.update();
101192
+ };
101193
+ return () => {
101194
+ let { details, browser, terminal } = handle.props;
101195
+ let shown = Boolean(terminal) && layout.terminal;
101196
+ let beside = shown && layout.placement === "right";
101197
+ let below = shown && layout.placement === "below";
101198
+ let switcher = beside ? /* @__PURE__ */ jsx(Segments, {
101199
+ label: t$2("tasks.agentView.agentPanes"),
101200
+ class: "@min-[52rem]/panes:hidden",
101201
+ value: panes.agent,
101202
+ options: [{
101203
+ id: "browser",
101204
+ label: t$2("tasks.agentView.browser"),
101205
+ icon: "browser"
101206
+ }, {
101207
+ id: "terminal",
101208
+ label: t$2("tasks.agentView.terminal"),
101209
+ icon: "terminal"
101210
+ }],
101211
+ onChange: (id) => setPanes({ agent: id })
101212
+ }) : null;
101213
+ let controls = terminal ? /* @__PURE__ */ jsx(Fragment, { children: [shown ? /* @__PURE__ */ jsx(IconButton, {
101214
+ tooltip: true,
101215
+ class: "@max-[34rem]/panes:hidden",
101216
+ icon: layout.placement === "right" ? "panel-bottom" : "panel-right",
101217
+ label: layout.placement === "right" ? t$2("tasks.agentView.terminalBelow") : t$2("tasks.agentView.terminalBeside"),
101218
+ "data-testid": "agent-terminal-placement",
101219
+ mix: on("click", () => setLayout({ placement: layout.placement === "right" ? "below" : "right" }))
101220
+ }) : null, /* @__PURE__ */ jsx(IconButton, {
101221
+ tooltip: true,
101222
+ icon: "terminal",
101223
+ active: shown,
101224
+ label: shown ? t$2("tasks.agentView.hideTerminal") : t$2("tasks.agentView.showTerminal"),
101225
+ "data-testid": "agent-terminal-toggle",
101226
+ mix: on("click", () => setLayout({ terminal: !shown }))
101227
+ })] }) : null;
101228
+ let hideBrowser = beside && panes.agent === "terminal" ? "@max-[52rem]/panes:hidden" : "";
101229
+ let hideTerminal = beside && panes.agent === "browser" ? "@max-[52rem]/panes:hidden" : "";
101230
+ return /* @__PURE__ */ jsx("div", {
101231
+ class: "@container/agent flex h-full min-h-0 flex-col",
101232
+ "data-testid": "agent-view",
101233
+ "data-terminal": shown ? layout.placement : "hidden",
101234
+ children: [/* @__PURE__ */ jsx("div", {
101235
+ class: "flex h-12 shrink-0 items-center gap-2 border-b border-line px-2 @min-[48rem]/agent:hidden",
101236
+ children: /* @__PURE__ */ jsx(Segments, {
101237
+ label: t$2("tasks.agentView.view"),
101238
+ value: panes.main,
101239
+ options: [{
101240
+ id: "details",
101241
+ label: t$2("tasks.agentView.details"),
101242
+ icon: "text"
101243
+ }, {
101244
+ id: "agent",
101245
+ label: terminal ? t$2("tasks.agentView.browserAndTerminal") : t$2("tasks.agentView.browser"),
101246
+ icon: "browser"
101247
+ }],
101248
+ onChange: (id) => setPanes({ main: id })
101249
+ })
101250
+ }), /* @__PURE__ */ jsx("div", {
101251
+ class: "flex min-h-0 flex-1",
101252
+ children: [/* @__PURE__ */ jsx("div", {
101253
+ class: `flex min-h-0 w-full min-w-0 flex-col @min-[48rem]/agent:w-[clamp(20rem,34%,30rem)] @min-[48rem]/agent:shrink-0 @min-[48rem]/agent:border-e @min-[48rem]/agent:border-line ${panes.main === "agent" ? "@max-[48rem]/agent:hidden" : ""}`,
101254
+ "data-agent-region": "details",
101255
+ children: details
101256
+ }), /* @__PURE__ */ jsx("div", {
101257
+ class: `@container/panes flex min-h-0 min-w-0 flex-1 bg-[var(--bud-editor)] ${below ? "flex-col" : ""} ${panes.main === "details" ? "@max-[48rem]/agent:hidden" : ""}`,
101258
+ "data-agent-region": "agent",
101259
+ children: [/* @__PURE__ */ jsx("section", {
101260
+ "aria-label": t$2("tasks.agentView.browser"),
101261
+ class: `flex min-h-0 min-w-0 flex-col ${below ? "flex-[3]" : "flex-1"} ${hideBrowser}`,
101262
+ "data-agent-region": "browser",
101263
+ children: [
101264
+ /* @__PURE__ */ jsx("div", {
101265
+ class: "bud-toolbar flex h-12 shrink-0 items-center gap-1.5 border-b border-line px-2",
101266
+ children: [
101267
+ switcher,
101268
+ /* @__PURE__ */ jsx("div", {
101269
+ class: "flex min-w-0 flex-1 items-center gap-1.5",
101270
+ children: browser.toolbar
101271
+ }),
101272
+ browser.actions,
101273
+ controls
101274
+ ]
101275
+ }),
101276
+ /* @__PURE__ */ jsx("div", {
101277
+ class: "relative min-h-0 flex-1",
101278
+ children: browser.content
101279
+ }),
101280
+ browser.status
101281
+ ]
101282
+ }), shown && terminal ? /* @__PURE__ */ jsx("section", {
101283
+ "aria-label": t$2("tasks.agentView.terminal"),
101284
+ class: `flex min-h-0 min-w-0 flex-col bg-[var(--bud-editor)] ${below ? "flex-[2] border-t border-line" : "flex-1 @min-[52rem]/panes:max-w-[44rem] @min-[52rem]/panes:border-s @min-[52rem]/panes:border-line"} ${hideTerminal}`,
101285
+ "data-agent-region": "terminal",
101286
+ children: [/* @__PURE__ */ jsx("div", {
101287
+ class: "bud-toolbar flex h-12 shrink-0 items-center gap-1.5 border-b border-line px-2",
101288
+ children: [
101289
+ beside ? /* @__PURE__ */ jsx("div", {
101290
+ class: "@min-[52rem]/panes:hidden",
101291
+ children: switcher
101292
+ }) : null,
101293
+ /* @__PURE__ */ jsx("div", {
101294
+ class: "flex min-w-0 flex-1 items-center overflow-x-auto [scrollbar-width:none]",
101295
+ children: terminal.tabs
101296
+ }),
101297
+ beside ? /* @__PURE__ */ jsx("div", {
101298
+ class: "flex items-center gap-1.5 @min-[52rem]/panes:hidden",
101299
+ children: controls
101300
+ }) : null
101301
+ ]
101302
+ }), /* @__PURE__ */ jsx("div", {
101303
+ class: "relative min-h-0 flex-1",
101304
+ children: terminal.content
101305
+ })]
101306
+ }) : null]
101307
+ })]
101308
+ })]
101309
+ });
101310
+ };
101311
+ }
101312
+ //#endregion
101313
+ //#region ../ui/src/lib/tasks/agent-browser.tsx
101314
+ /**
101315
+ * Agent view's browser on the run's live preview: a sandboxed frame on the preview's own origin,
101316
+ * never Bud's, followed through the dev bridge the project's pages carry, with back, forward,
101317
+ * reload and the address, and comments on picked elements that go to the agent as changes.
101318
+ * @param handle - The details, the preview, the terminal and their actions.
101319
+ * @returns The view's render function.
101320
+ */
101321
+ function AgentBrowser(handle) {
101322
+ let frame;
101323
+ let path = "/";
101324
+ let title = "";
101325
+ let src = null;
101326
+ let load = 0;
101327
+ let picking = null;
101328
+ let draft = null;
101329
+ let busy = false;
101330
+ let tab = null;
101331
+ let origin = () => {
101332
+ let preview = handle.props.preview;
101333
+ return preview.state === "ready" ? new URL(preview.url).origin : null;
101334
+ };
101335
+ let post = (type, data = {}) => {
101336
+ let target = origin();
101337
+ if (target) frame?.contentWindow?.postMessage({
101338
+ ...data,
101339
+ type
101340
+ }, target);
101341
+ };
101342
+ let update = () => {
101343
+ if (!handle.signal.aborted) handle.update();
101344
+ };
101345
+ let frameRef = ref((node, signal) => {
101346
+ frame = node;
101347
+ signal.addEventListener("abort", () => frame = void 0, { once: true });
101348
+ });
101349
+ let keepInside = ref((card, signal) => {
101350
+ let position = () => {
101351
+ if (!frame) return;
101352
+ card.style.setProperty("--pages-card-x", "0px");
101353
+ card.style.setProperty("--pages-card-y", "0px");
101354
+ let offset = canvasPopoverOffset(card.getBoundingClientRect(), frame.getBoundingClientRect());
101355
+ card.style.setProperty("--pages-card-x", `${offset.x}px`);
101356
+ card.style.setProperty("--pages-card-y", `${offset.y}px`);
101357
+ };
101358
+ let observer = new ResizeObserver(position);
101359
+ observer.observe(card);
101360
+ position();
101361
+ signal.addEventListener("abort", () => observer.disconnect(), { once: true });
101362
+ });
101363
+ let listen = ref((_node, signal) => {
101364
+ window.addEventListener("message", (event) => {
101365
+ if (!frame || event.source !== frame.contentWindow || event.origin !== origin()) return;
101366
+ let data = event.data;
101367
+ if (data?.type === "bud:location" && typeof data.path === "string") {
101368
+ path = data.path.startsWith("/") ? data.path.slice(0, 4096) : path;
101369
+ title = typeof data.title === "string" ? data.title.slice(0, 200) : "";
101370
+ update();
101371
+ } else if (data?.type === "bud:picked" && picking && data.id === picking) {
101372
+ picking = null;
101373
+ draft = readPagePick(data);
101374
+ update();
101375
+ }
101376
+ }, { signal });
101377
+ });
101378
+ let navigate = (to) => {
101379
+ let preview = handle.props.preview;
101380
+ if (preview.state !== "ready") return;
101381
+ let url = new URL(preview.url);
101382
+ let target = new URL(to, url);
101383
+ if (target.origin !== url.origin) return;
101384
+ for (let [key, value] of url.searchParams) if (!target.searchParams.has(key)) target.searchParams.set(key, value);
101385
+ src = target.href;
101386
+ load++;
101387
+ update();
101388
+ };
101389
+ return () => {
101390
+ let { preview, details, terminal, onComment } = handle.props;
101391
+ let ready = preview.state === "ready" ? preview : null;
101392
+ if (ready && src === null) src = ready.url;
101393
+ if (!ready) {
101394
+ src = null;
101395
+ picking = null;
101396
+ }
101397
+ let host = ready ? new URL(ready.url).host : "";
101398
+ let shownTab = terminal?.tabs.find((entry) => entry.id === tab)?.id ?? terminal?.tabs[0]?.id;
101399
+ let toolbar = /* @__PURE__ */ jsx(Fragment, { children: [/* @__PURE__ */ jsx("div", {
101400
+ class: "flex shrink-0 items-center gap-0.5",
101401
+ children: [
101402
+ /* @__PURE__ */ jsx(IconButton, {
101403
+ tooltip: true,
101404
+ class: "@max-[34rem]/panes:hidden",
101405
+ icon: "arrow-left",
101406
+ label: t$2("tasks.agentBrowser.back"),
101407
+ disabled: !ready,
101408
+ mix: on("click", () => post("bud:back"))
101409
+ }),
101410
+ /* @__PURE__ */ jsx(IconButton, {
101411
+ tooltip: true,
101412
+ class: "@max-[34rem]/panes:hidden",
101413
+ icon: "arrow-right",
101414
+ label: t$2("tasks.agentBrowser.forward"),
101415
+ disabled: !ready,
101416
+ mix: on("click", () => post("bud:forward"))
101417
+ }),
101418
+ /* @__PURE__ */ jsx(IconButton, {
101419
+ tooltip: true,
101420
+ icon: "sync",
101421
+ label: t$2("tasks.agentBrowser.reload"),
101422
+ disabled: !ready,
101423
+ mix: on("click", () => navigate(path))
101424
+ })
101425
+ ]
101426
+ }), /* @__PURE__ */ jsx("form", {
101427
+ class: "flex min-w-0 flex-1 @max-[34rem]/panes:hidden",
101428
+ mix: on("submit", (event) => {
101429
+ event.preventDefault();
101430
+ let input = event.currentTarget.elements.namedItem("address");
101431
+ navigate(input.value.trim() || "/");
101432
+ }),
101433
+ children: /* @__PURE__ */ jsx("label", {
101434
+ class: "bud-control bud-field flex h-control min-w-0 flex-1 items-center gap-2 rounded-lg px-2.5 text-muted",
101435
+ children: [/* @__PURE__ */ jsx(Icon$1, {
101436
+ name: "globe",
101437
+ size: 14,
101438
+ class: "shrink-0"
101439
+ }), /* @__PURE__ */ jsx("input", {
101440
+ name: "address",
101441
+ "aria-label": t$2("tasks.agentBrowser.address"),
101442
+ class: "h-full min-w-0 flex-1 bg-transparent pb-0.5 text-sm/5 text-ink outline-none",
101443
+ spellcheck: false,
101444
+ autocomplete: "off",
101445
+ disabled: !ready,
101446
+ value: ready ? path : ""
101447
+ })]
101448
+ })
101449
+ })] });
101450
+ let actions = /* @__PURE__ */ jsx(Fragment, { children: [onComment ? /* @__PURE__ */ jsx(IconButton, {
101451
+ tooltip: true,
101452
+ icon: "crosshair",
101453
+ label: t$2("tasks.agentBrowser.commentOnElement"),
101454
+ active: Boolean(picking),
101455
+ disabled: !ready,
101456
+ "data-testid": "agent-browser-pick",
101457
+ mix: on("click", () => {
101458
+ if (picking) {
101459
+ post("bud:pick-cancel");
101460
+ picking = null;
101461
+ } else {
101462
+ draft = null;
101463
+ picking = crypto.randomUUID();
101464
+ post("bud:pick", { id: picking });
101465
+ }
101466
+ update();
101467
+ })
101468
+ }) : null, /* @__PURE__ */ jsx(IconButton, {
101469
+ tooltip: true,
101470
+ class: "@max-[34rem]/panes:hidden",
101471
+ icon: "external",
101472
+ label: t$2("tasks.agentBrowser.openInNewWindow"),
101473
+ disabled: !ready,
101474
+ mix: on("click", () => {
101475
+ if (src) window.open(src, "_blank", "noopener,noreferrer");
101476
+ })
101477
+ })] });
101478
+ let content = ready ? /* @__PURE__ */ jsx(Fragment, { children: [/* @__PURE__ */ jsx("iframe", {
101479
+ title: title || t$2("tasks.agentBrowser.preview"),
101480
+ src: src ?? ready.url,
101481
+ sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-modals",
101482
+ referrerpolicy: "no-referrer",
101483
+ class: "absolute inset-0 size-full border-0 bg-white",
101484
+ "data-testid": "agent-browser-frame",
101485
+ mix: [frameRef, on("load", () => {
101486
+ post("bud:hello");
101487
+ if (picking) post("bud:pick", { id: picking });
101488
+ })]
101489
+ }, `${load}`), draft && onComment ? /* @__PURE__ */ jsx("div", {
101490
+ role: "dialog",
101491
+ "aria-label": t$2("tasks.agentBrowser.newComment"),
101492
+ class: `absolute z-10 ${draft.client ? "" : "top-3 right-3"}`,
101493
+ style: draft.client ? {
101494
+ left: `${draft.client.x}px`,
101495
+ top: `${draft.client.y}px`,
101496
+ transform: "translate(calc(12px + var(--pages-card-x, 0px)), calc(-8px + var(--pages-card-y, 0px)))"
101497
+ } : void 0,
101498
+ mix: [...draft.client ? [keepInside] : [], on("keydown", (event) => {
101499
+ if (event.key === "Escape") {
101500
+ draft = null;
101501
+ update();
101502
+ }
101503
+ })],
101504
+ children: /* @__PURE__ */ jsx(CommentComposerCard, {
101505
+ busy,
101506
+ heading: /* @__PURE__ */ jsx("div", {
101507
+ class: "flex min-w-0 flex-col gap-1 px-1 pt-1",
101508
+ children: [/* @__PURE__ */ jsx(Text$1, {
101509
+ variant: "ui-caption",
101510
+ tone: "muted",
101511
+ class: "truncate",
101512
+ children: [
101513
+ draft.path,
101514
+ " · ",
101515
+ draft.element?.label || draft.element?.tagName || ""
101516
+ ]
101517
+ }), draft.element?.source ? /* @__PURE__ */ jsx(ElementSourceLink, { source: draft.element.source }) : null]
101518
+ }),
101519
+ onCancel: () => {
101520
+ draft = null;
101521
+ update();
101522
+ },
101523
+ onSubmit: async (body) => {
101524
+ let pick = draft;
101525
+ busy = true;
101526
+ update();
101527
+ try {
101528
+ await onComment({
101529
+ body,
101530
+ path: pick.path,
101531
+ element: pick.element
101532
+ });
101533
+ draft = null;
101534
+ } finally {
101535
+ busy = false;
101536
+ update();
101537
+ }
101538
+ }
101539
+ })
101540
+ }, draft.client ? `${draft.client.x},${draft.client.y}` : "corner") : null] }) : /* @__PURE__ */ jsx("div", {
101541
+ class: "flex h-full flex-col items-center justify-center gap-3 p-6 text-center",
101542
+ children: preview.state === "waking" ? /* @__PURE__ */ jsx(Loader, { label: t$2("tasks.agentBrowser.waking") }) : /* @__PURE__ */ jsx(Fragment, { children: [
101543
+ /* @__PURE__ */ jsx(Icon$1, {
101544
+ name: "browser",
101545
+ size: 20,
101546
+ class: "text-muted"
101547
+ }),
101548
+ /* @__PURE__ */ jsx(Text$1, {
101549
+ as: "p",
101550
+ variant: "ui",
101551
+ tone: "muted",
101552
+ class: "max-w-xs text-balance",
101553
+ children: preview.state === "asleep" ? t$2("tasks.agentBrowser.asleep") : preview.state === "failed" ? preview.message : t$2("tasks.agentBrowser.noPreview")
101554
+ }),
101555
+ preview.state === "asleep" || preview.state === "failed" ? /* @__PURE__ */ jsx(Button, {
101556
+ variant: "secondary",
101557
+ size: "small",
101558
+ "data-testid": "agent-browser-wake",
101559
+ mix: on("click", handle.props.onWake),
101560
+ children: preview.state === "asleep" ? t$2("tasks.agentBrowser.wake") : t$2("tasks.agentBrowser.tryAgain")
100219
101561
  }) : null
100220
101562
  ] })
100221
101563
  });
101564
+ let status = /* @__PURE__ */ jsx("footer", {
101565
+ class: "flex h-9 shrink-0 items-center gap-3 overflow-hidden whitespace-nowrap border-t border-line ps-3 pe-2 text-muted",
101566
+ "aria-label": t$2("tasks.agentBrowser.status"),
101567
+ children: [/* @__PURE__ */ jsx(Text$1, {
101568
+ variant: "ui-caption",
101569
+ class: "truncate",
101570
+ children: ready ? title || path : ""
101571
+ }), /* @__PURE__ */ jsx(Text$1, {
101572
+ variant: "ui-caption",
101573
+ class: "ms-auto truncate",
101574
+ children: host
101575
+ })]
101576
+ });
101577
+ return /* @__PURE__ */ jsx("div", {
101578
+ class: "h-full min-h-0",
101579
+ mix: listen,
101580
+ children: /* @__PURE__ */ jsx(AgentView, {
101581
+ details,
101582
+ browser: {
101583
+ toolbar,
101584
+ actions,
101585
+ content,
101586
+ status
101587
+ },
101588
+ terminal: terminal ? {
101589
+ tabs: /* @__PURE__ */ jsx("div", {
101590
+ class: "bud-segmented",
101591
+ role: "group",
101592
+ "aria-label": t$2("tasks.agentTerminal.sessions"),
101593
+ children: terminal.tabs.map((entry) => /* @__PURE__ */ jsx("button", {
101594
+ type: "button",
101595
+ "aria-pressed": entry.id === shownTab ? "true" : "false",
101596
+ "data-terminal-select": entry.id,
101597
+ mix: on("click", () => {
101598
+ tab = entry.id;
101599
+ update();
101600
+ }),
101601
+ children: /* @__PURE__ */ jsx(Text$1, {
101602
+ variant: "ui",
101603
+ children: entry.label
101604
+ })
101605
+ }, entry.id))
101606
+ }),
101607
+ content: /* @__PURE__ */ jsx(AgentTerminal, {
101608
+ tabs: terminal.tabs,
101609
+ active: shownTab,
101610
+ connect: terminal.connect
101611
+ })
101612
+ } : null
101613
+ })
101614
+ });
101615
+ };
101616
+ }
101617
+ //#endregion
101618
+ //#region ../ui/src/lib/tasks/task-run-panel.tsx
101619
+ function elapsed(from, now) {
101620
+ let seconds = Math.max(0, Math.round((now - Date.parse(from)) / 1e3));
101621
+ if (seconds < 60) return t$2("tasks.taskRunPanel.seconds", { count: seconds });
101622
+ return t$2("tasks.taskRunPanel.minutes", { count: Math.round(seconds / 60) });
101623
+ }
101624
+ /**
101625
+ * The factory's run on a task, above its discussion: Start task, the agent's progress, its summary
101626
+ * with Request changes, Approve & push and Discard, a failure with Retry, and the pushed branch.
101627
+ * @param handle - The run, whether it can start, and the actions.
101628
+ * @returns The panel render function.
101629
+ */
101630
+ function TaskRunPanel(handle) {
101631
+ let acting = null;
101632
+ let confirming = null;
101633
+ let requesting = false;
101634
+ function update() {
101635
+ if (!handle.signal.aborted) handle.update();
101636
+ }
101637
+ async function act(name, action) {
101638
+ if (acting) return;
101639
+ acting = name;
101640
+ update();
101641
+ try {
101642
+ await action();
101643
+ } catch {} finally {
101644
+ acting = null;
101645
+ confirming = null;
101646
+ update();
101647
+ }
101648
+ }
101649
+ let button = (name, label, action, variant = "secondary") => /* @__PURE__ */ jsx(Button, {
101650
+ variant,
101651
+ size: "small",
101652
+ disabled: acting !== null,
101653
+ "data-testid": `run-${name}`,
101654
+ mix: on("click", () => void act(name, action)),
101655
+ children: [acting === name ? /* @__PURE__ */ jsx(Spinner, { size: 12 }) : null, label]
101656
+ });
101657
+ let confirm = (kind, question, label) => /* @__PURE__ */ jsx("div", {
101658
+ class: "flex min-w-0 flex-wrap items-center gap-2",
101659
+ role: "group",
101660
+ "aria-label": question,
101661
+ "data-testid": `run-confirm-${kind}`,
101662
+ children: [
101663
+ /* @__PURE__ */ jsx(Text$1, {
101664
+ variant: "ui-caption",
101665
+ tone: "muted",
101666
+ class: "me-auto",
101667
+ children: question
101668
+ }),
101669
+ /* @__PURE__ */ jsx(Button, {
101670
+ variant: "ghost",
101671
+ size: "small",
101672
+ disabled: acting !== null,
101673
+ mix: on("click", () => {
101674
+ confirming = null;
101675
+ update();
101676
+ }),
101677
+ children: t$2("tasks.taskRunPanel.cancel")
101678
+ }),
101679
+ button(`${kind}-confirmed`, label, kind === "approve" ? handle.props.onApprove : handle.props.onDiscard, "primary")
101680
+ ]
101681
+ });
101682
+ let ask = (kind, label, variant) => /* @__PURE__ */ jsx(Button, {
101683
+ variant,
101684
+ size: "small",
101685
+ disabled: acting !== null,
101686
+ "data-testid": `run-${kind}`,
101687
+ mix: on("click", () => {
101688
+ confirming = kind;
101689
+ requesting = false;
101690
+ update();
101691
+ }),
101692
+ children: label
101693
+ });
101694
+ return () => {
101695
+ let { run, blocked, preview, now = Date.now() } = handle.props;
101696
+ let state = run?.state;
101697
+ let fresh = !run || state === "discarded";
101698
+ let working = state === "provisioning" || state === "working" || state === "changes" || state === "approved";
101699
+ let line = (icon, text, tone = "") => /* @__PURE__ */ jsx("div", {
101700
+ class: `flex min-w-0 items-center gap-2 ${tone}`,
101701
+ "data-testid": "run-state",
101702
+ children: [
101703
+ icon,
101704
+ /* @__PURE__ */ jsx(Text$1, {
101705
+ variant: "ui",
101706
+ class: "min-w-0 [overflow-wrap:anywhere]",
101707
+ children: text
101708
+ }),
101709
+ run && working ? /* @__PURE__ */ jsx(Text$1, {
101710
+ variant: "ui-caption",
101711
+ tone: "muted",
101712
+ class: "ms-auto shrink-0 tabular-nums",
101713
+ children: elapsed(run.activity.findLast((entry) => entry.kind === "status")?.at ?? run.createdAt, now)
101714
+ }) : null
101715
+ ]
101716
+ });
101717
+ let activity = (run?.activity ?? []).filter((entry) => entry.kind !== "status").slice(-6);
101718
+ return /* @__PURE__ */ jsx("section", {
101719
+ class: "flex min-w-0 flex-col gap-3",
101720
+ "aria-label": t$2("tasks.taskRunPanel.agent"),
101721
+ "data-testid": "task-run-panel",
101722
+ "data-state": state ?? (run === null ? "none" : "loading"),
101723
+ children: [/* @__PURE__ */ jsx("div", {
101724
+ class: "flex items-center gap-2",
101725
+ children: [/* @__PURE__ */ jsx(Text$1, {
101726
+ as: "h3",
101727
+ variant: "ui",
101728
+ weight: "medium",
101729
+ children: t$2("tasks.taskRunPanel.agent")
101730
+ }), run && !fresh ? /* @__PURE__ */ jsx(Text$1, {
101731
+ variant: "ui-caption",
101732
+ tone: "muted",
101733
+ class: "min-w-0 truncate font-mono",
101734
+ children: run.branch
101735
+ }) : null]
101736
+ }), /* @__PURE__ */ jsx("div", {
101737
+ class: "flex min-w-0 flex-col gap-3 rounded-lg bg-[var(--bud-card)] p-3 ring-1 ring-[var(--bud-card-border)]",
101738
+ children: run === void 0 ? line(/* @__PURE__ */ jsx(Spinner, { size: 14 }), t$2("tasks.taskRunPanel.loading"), "text-muted") : fresh ? /* @__PURE__ */ jsx("div", {
101739
+ class: "flex min-w-0 flex-wrap items-center gap-3",
101740
+ children: [/* @__PURE__ */ jsx(Text$1, {
101741
+ variant: "ui-caption",
101742
+ tone: "muted",
101743
+ class: "min-w-0 flex-1",
101744
+ children: blocked ?? t$2("tasks.taskRunPanel.startHint")
101745
+ }), blocked ? null : button("start", t$2("tasks.taskRunPanel.start"), handle.props.onStart, "primary")]
101746
+ }) : /* @__PURE__ */ jsx(Fragment, { children: [
101747
+ state === "provisioning" ? line(/* @__PURE__ */ jsx(Spinner, { size: 14 }), t$2("tasks.taskRunPanel.settingUp")) : state === "working" || state === "changes" ? line(/* @__PURE__ */ jsx(Spinner, { size: 14 }), t$2("tasks.taskRunPanel.working")) : state === "approved" || state === "pushing" ? line(/* @__PURE__ */ jsx(Spinner, { size: 14 }), t$2("tasks.taskRunPanel.pushing", { branch: run.branch })) : state === "review" ? line(/* @__PURE__ */ jsx(Icon$1, {
101748
+ name: "circle-dot",
101749
+ size: 14
101750
+ }), t$2("tasks.taskRunPanel.review"), "text-amber-600 dark:text-amber-400") : state === "needs_context" ? line(/* @__PURE__ */ jsx(Icon$1, {
101751
+ name: "message",
101752
+ size: 14
101753
+ }), t$2("tasks.taskRunPanel.needsContext"), "text-violet-600 dark:text-violet-400") : state === "merged" ? line(/* @__PURE__ */ jsx(Icon$1, {
101754
+ name: "circle-check",
101755
+ size: 14
101756
+ }), t$2("tasks.taskRunPanel.merged", { branch: run.branch }), "text-emerald-600 dark:text-emerald-400") : state === "pushed" ? line(/* @__PURE__ */ jsx(Icon$1, {
101757
+ name: "push",
101758
+ size: 14
101759
+ }), t$2("tasks.taskRunPanel.pushed", {
101760
+ branch: run.branch,
101761
+ commit: (run.pushed ?? "").slice(0, 7)
101762
+ }), "text-emerald-600 dark:text-emerald-400") : line(/* @__PURE__ */ jsx(Icon$1, {
101763
+ name: "circle-alert",
101764
+ size: 14
101765
+ }), run.error?.message ?? t$2("tasks.taskRunPanel.failed"), "text-red-600 dark:text-red-400"),
101766
+ run.asleep && (state === "review" || state === "needs_context" || state === "failed") ? /* @__PURE__ */ jsx("div", {
101767
+ class: "flex min-w-0 items-center gap-2 text-muted",
101768
+ "data-testid": "run-asleep",
101769
+ children: [/* @__PURE__ */ jsx(Icon$1, {
101770
+ name: "moon",
101771
+ size: 13,
101772
+ class: "shrink-0"
101773
+ }), /* @__PURE__ */ jsx(Text$1, {
101774
+ variant: "ui-caption",
101775
+ tone: "muted",
101776
+ class: "min-w-0",
101777
+ children: t$2("tasks.taskRunPanel.asleep")
101778
+ })]
101779
+ }) : null,
101780
+ state === "needs_context" && run.question ? /* @__PURE__ */ jsx("div", {
101781
+ class: "min-w-0 rounded-md bg-[var(--bud-control)] px-3 py-2",
101782
+ "data-testid": "run-question",
101783
+ children: /* @__PURE__ */ jsx(TaskMarkdown, { children: run.question })
101784
+ }) : null,
101785
+ state === "review" && run.summary ? /* @__PURE__ */ jsx("div", {
101786
+ class: "min-w-0",
101787
+ "data-testid": "run-summary",
101788
+ children: /* @__PURE__ */ jsx(TaskMarkdown, { children: run.summary })
101789
+ }) : null,
101790
+ activity.length && state !== "pushed" && state !== "merged" ? /* @__PURE__ */ jsx("ol", {
101791
+ class: "flex min-w-0 flex-col gap-1",
101792
+ "aria-label": t$2("tasks.taskRunPanel.activity"),
101793
+ children: activity.map((entry, index) => /* @__PURE__ */ jsx("li", {
101794
+ class: "flex min-w-0 items-baseline gap-2",
101795
+ children: [/* @__PURE__ */ jsx(Icon$1, {
101796
+ name: entry.kind === "tool" ? "code" : entry.kind === "error" ? "warning" : "circle",
101797
+ size: 11,
101798
+ class: "shrink-0 translate-y-px text-muted"
101799
+ }), /* @__PURE__ */ jsx(Text$1, {
101800
+ variant: "ui-caption",
101801
+ tone: "muted",
101802
+ class: "min-w-0 truncate font-mono",
101803
+ children: entry.text
101804
+ })]
101805
+ }, `${entry.at}-${index}`))
101806
+ }) : null,
101807
+ confirming === "approve" ? confirm("approve", t$2("tasks.taskRunPanel.confirmApprove", { branch: run.branch }), t$2("tasks.taskRunPanel.approve")) : confirming === "discard" ? confirm("discard", t$2("tasks.taskRunPanel.confirmDiscard"), t$2("tasks.taskRunPanel.discard")) : state === "needs_context" && handle.props.onAnswer ? /* @__PURE__ */ jsx("div", {
101808
+ class: "flex min-w-0 flex-col gap-2",
101809
+ children: [/* @__PURE__ */ jsx(CommentComposer, {
101810
+ label: t$2("tasks.taskRunPanel.answer"),
101811
+ placeholder: t$2("tasks.taskRunPanel.answerPlaceholder"),
101812
+ busy: acting !== null,
101813
+ onSubmit: async (message) => {
101814
+ await handle.props.onAnswer(message);
101815
+ }
101816
+ }), /* @__PURE__ */ jsx("span", {
101817
+ class: "ms-auto",
101818
+ children: ask("discard", t$2("tasks.taskRunPanel.discard"), "ghost")
101819
+ })]
101820
+ }) : requesting && state === "review" ? /* @__PURE__ */ jsx(CommentComposer, {
101821
+ label: t$2("tasks.taskRunPanel.requestChanges"),
101822
+ placeholder: t$2("tasks.taskRunPanel.changesPlaceholder"),
101823
+ autoFocus: true,
101824
+ busy: acting !== null,
101825
+ onSubmit: async (message) => {
101826
+ await handle.props.onChanges(message);
101827
+ requesting = false;
101828
+ update();
101829
+ },
101830
+ footer: /* @__PURE__ */ jsx(Button, {
101831
+ variant: "ghost",
101832
+ size: "small",
101833
+ mix: on("click", () => {
101834
+ requesting = false;
101835
+ update();
101836
+ }),
101837
+ children: t$2("tasks.taskRunPanel.cancel")
101838
+ })
101839
+ }) : /* @__PURE__ */ jsx("div", {
101840
+ class: "flex min-w-0 flex-wrap items-center gap-2",
101841
+ children: [
101842
+ state === "review" ? ask("approve", t$2("tasks.taskRunPanel.approve"), "primary") : null,
101843
+ state === "review" ? /* @__PURE__ */ jsx(Button, {
101844
+ variant: "secondary",
101845
+ size: "small",
101846
+ disabled: acting !== null,
101847
+ "data-testid": "run-changes",
101848
+ mix: on("click", () => {
101849
+ requesting = true;
101850
+ update();
101851
+ }),
101852
+ children: t$2("tasks.taskRunPanel.requestChanges")
101853
+ }) : null,
101854
+ state === "failed" && run.error?.retryable && run.failedIn ? button("retry", t$2("tasks.taskRunPanel.retry"), handle.props.onRetry, "primary") : null,
101855
+ preview && (state === "working" || state === "changes" || state === "review" || state === "needs_context") ? button("preview", t$2("tasks.taskRunPanel.preview"), handle.props.onPreview) : null,
101856
+ state === "pushed" && handle.props.onCanvas ? /* @__PURE__ */ jsx(Button, {
101857
+ variant: "secondary",
101858
+ size: "small",
101859
+ "data-testid": "run-canvas",
101860
+ mix: on("click", () => handle.props.onCanvas?.()),
101861
+ children: t$2("tasks.taskRunPanel.showOnCanvas")
101862
+ }) : null,
101863
+ state === "pushed" || state === "merged" ? button("start", t$2("tasks.taskRunPanel.startAgain"), handle.props.onStart, "ghost") : null,
101864
+ state !== "pushed" && state !== "merged" && state !== "pushing" && state !== "approved" ? /* @__PURE__ */ jsx("span", {
101865
+ class: "ms-auto",
101866
+ children: ask("discard", t$2("tasks.taskRunPanel.discard"), "ghost")
101867
+ }) : null
101868
+ ]
101869
+ })
101870
+ ] })
101871
+ })]
101872
+ });
100222
101873
  };
100223
101874
  }
100224
101875
  //#endregion
@@ -105949,7 +107600,7 @@ function ItemDiscussion(handle) {
105949
107600
  */
105950
107601
  function ThreadTaskLinks(handle) {
105951
107602
  return () => {
105952
- let { itemIds, items, href, onEdit, busy } = handle.props;
107603
+ let { itemIds, items, href, onEdit, busy, schema, runs } = handle.props;
105953
107604
  if (!itemIds.length && !onEdit) return null;
105954
107605
  let names = new Map(items.map((item) => [item.id, item]));
105955
107606
  return /* @__PURE__ */ jsx("div", {
@@ -105961,15 +107612,33 @@ function ThreadTaskLinks(handle) {
105961
107612
  href: href(id),
105962
107613
  title: item?.title ?? id,
105963
107614
  class: "bud-interaction bud-control inline-flex min-h-6 max-w-full items-center gap-1.5 rounded-md px-2 py-0.5",
105964
- children: [/* @__PURE__ */ jsx(Text$1, {
105965
- variant: "code",
105966
- class: "shrink-0",
105967
- children: id
105968
- }), item?.title ? /* @__PURE__ */ jsx(Text$1, {
105969
- variant: "ui-caption",
105970
- class: "truncate",
105971
- children: item.title
105972
- }) : null]
107615
+ children: [
107616
+ /* @__PURE__ */ jsx(Text$1, {
107617
+ variant: "code",
107618
+ class: "shrink-0",
107619
+ children: id
107620
+ }),
107621
+ item?.title ? /* @__PURE__ */ jsx(Text$1, {
107622
+ variant: "ui-caption",
107623
+ class: "truncate",
107624
+ children: item.title
107625
+ }) : null,
107626
+ item?.status && schema ? /* @__PURE__ */ jsx("span", {
107627
+ class: "flex shrink-0 items-center gap-1 text-muted",
107628
+ "data-task-status": true,
107629
+ children: [/* @__PURE__ */ jsx(StatusDot, {
107630
+ status: item.status,
107631
+ schema
107632
+ }), /* @__PURE__ */ jsx(Text$1, {
107633
+ variant: "ui-caption",
107634
+ children: schema.statuses.find((status) => status.value === item.status)?.label ?? taskLabel(item.status)
107635
+ })]
107636
+ }) : null,
107637
+ runs?.[id] && taskRunBadge(runs[id]) ? /* @__PURE__ */ jsx("span", {
107638
+ class: "shrink-0",
107639
+ children: /* @__PURE__ */ jsx(TaskRunBadge, { run: runs[id] })
107640
+ }) : null
107641
+ ]
105973
107642
  }, id);
105974
107643
  }), onEdit ? /* @__PURE__ */ jsx(IconButton, {
105975
107644
  icon: "tasks",
@@ -106293,78 +107962,6 @@ function equal(left, right) {
106293
107962
  return JSON.stringify(left) === JSON.stringify(right);
106294
107963
  }
106295
107964
  //#endregion
106296
- //#region app/routes.ts
106297
- var routes = createRoutes({
106298
- screen: createGetRoute("/(:screen)(/*rest)"),
106299
- screenModule: createGetRoute("/__bud/screens/:name.js"),
106300
- logo: createGetRoute("/__bud/logo/:theme"),
106301
- health: createGetRoute("/health"),
106302
- conversation: conversationRoutes.show,
106303
- tasksApi: {
106304
- index: createGetRoute("/api/tasks"),
106305
- schema: createGetRoute("/api/tasks/schema"),
106306
- workspace: createGetRoute("/api/tasks/workspace"),
106307
- show: createGetRoute("/api/tasks/items/:id"),
106308
- section: createGetRoute("/api/tasks/items/:id/sections/:section"),
106309
- create: createPostRoute("/api/tasks"),
106310
- update: createPostRoute("/api/tasks/items/:id"),
106311
- mutate: createPostRoute("/api/tasks/items/:id/actions"),
106312
- sync: createPostRoute("/api/tasks/sync")
106313
- },
106314
- filesApi: {
106315
- index: createGetRoute("/api/files"),
106316
- entry: createGetRoute("/api/files/entry"),
106317
- read: createGetRoute("/api/files/read"),
106318
- refresh: createPostRoute("/api/files/refresh")
106319
- },
106320
- fileSearchApi: { search: createGetRoute("/api/files/search") },
106321
- fileReviewApi: {
106322
- repository: createGetRoute("/api/files/repository"),
106323
- compare: createGetRoute("/api/files/compare"),
106324
- diff: createGetRoute("/api/files/diff"),
106325
- source: createGetRoute("/api/files/source"),
106326
- history: createGetRoute("/api/files/history")
106327
- },
106328
- fileMutationsApi: {
106329
- prepare: createPostRoute("/api/files/mutations/prepare"),
106330
- apply: createPostRoute("/api/files/mutations/apply"),
106331
- recoveries: createGetRoute("/api/files/mutations/recoveries")
106332
- },
106333
- fileSavesApi: { save: createPostRoute("/api/files/save") },
106334
- fileReviewActionsApi: {
106335
- prepare: createPostRoute("/api/files/review-actions/prepare"),
106336
- apply: createPostRoute("/api/files/review-actions/apply"),
106337
- recoveries: createGetRoute("/api/files/review-actions/recoveries")
106338
- },
106339
- liveApi: { stream: createGetRoute("/api/live") },
106340
- previewsApi: {
106341
- show: createGetRoute("/api/previews/items/*id"),
106342
- image: createGetRoute("/api/previews/images/:hash.jpg"),
106343
- refresh: createPostRoute("/api/previews/refresh/*id"),
106344
- describe: createPostRoute("/api/previews/describe/*id"),
106345
- locate: createPostRoute("/api/previews/locate/*id")
106346
- },
106347
- branchesApi: {
106348
- list: createGetRoute("/api/branches"),
106349
- activate: createPostRoute("/api/branches/activate/*name"),
106350
- deactivate: createPostRoute("/api/branches/deactivate/*name"),
106351
- capture: createPostRoute("/api/branches/capture/*name")
106352
- },
106353
- comments: {
106354
- list: createGetRoute("/api/comments"),
106355
- get: createGetRoute("/api/comments/:id"),
106356
- create: createPostRoute("/api/comments"),
106357
- update: createPostRoute("/api/comments/:id"),
106358
- reply: createPostRoute("/api/comments/:id/replies"),
106359
- status: createPostRoute("/api/comments/:id/status"),
106360
- link: createPostRoute("/api/comments/:id/links"),
106361
- unlink: createPostRoute("/api/comments/:id/links/remove"),
106362
- deleteMessage: createPostRoute("/api/comments/:id/messages/remove"),
106363
- sync: createPostRoute("/api/comments/sync"),
106364
- viewer: createGetRoute("/api/viewer")
106365
- }
106366
- });
106367
- //#endregion
106368
107965
  //#region ../live/src/lib/sse.ts
106369
107966
  /**
106370
107967
  * Reads Server-Sent Events from a response body, following the HTML event-stream format.
@@ -106588,6 +108185,11 @@ var endpoints = [
106588
108185
  write: true,
106589
108186
  list: false
106590
108187
  },
108188
+ {
108189
+ route: routes.comments.makeTask,
108190
+ write: true,
108191
+ list: false
108192
+ },
106591
108193
  {
106592
108194
  route: routes.comments.deleteMessage,
106593
108195
  write: true,
@@ -107221,4 +108823,4 @@ function unavailableComments(message = commentsUnavailable) {
107221
108823
  };
107222
108824
  }
107223
108825
  //#endregion
107224
- export { FileSearchPanel as $, createSchema as $i, parsePreviewViewport as $n, parseReviewActionResult as $r, Button as $t, parseEditorPreferences as A, parseWorkSnapshot as Ai, normalizeAttributeName as An, areDiffTargetsEqual as Ar, defaultReviewView as At, TaskWorkspace as B, withoutMessages as Bi, createMultiMatcher as Bn, areThemesEqual as Br, fileHref as Bt, ThreadTaskLinks as C, parseWorkConnection as Ci, composeMixedProps as Cn, createCodeAnchor as Cr, legacyConversationHref as Ct, ReviewActionDialog as D, parseWorkItemRef as Di, FRAMEWORK_PROPS as Dn, renderDiffWithHighlighter as Dr, taskHref as Dt, FileConflictPanel as E, parseWorkItem as Ei, isEntry as En, isDiffPlainText as Er, selectedTask as Et, FileWorkspace as F, valueByRole as Fi, Frame as Fn, markWorkerErrorReported as Fr, reviewComparison as Ft, mergeThreads as G, identifier$1 as Gi, PREVIEW_THUMBNAIL_WIDTHS as Gn, themeResolver as Gr, fileRoutes as Gt, CanvasWorkspace as H, parseWorkSchema as Hi, joinPatterns as Hn, prepareThemeResolution as Hr, readFileLocation as Ht, defaultFileDestination as I, messageDeletionRefusal as Ii, createComponent as In, isFilePlainText as Ir, reviewContextKey as It, conversationId as J, record as Ji, parsePreviewBranch as Jn, resolveLanguage as Jr, CommentThreadDetail as Jt, stableJson as K, nonempty as Ki, PREVIEW_TILE_HEIGHT as Kn, getThemes as Kr, pageRoutes as Kt, fileActionIntent as L, messageDeletionRefusals as Li, createFrameHandle as Ln, renderFileWithHighlighter as Lr, reviewHref as Lt, FileMutationDialog as M, parseWorkSyncResult as Mi, serializeStyleObject as Mn, WorkerPoolTerminatedError as Mr, parseReviewSession as Mt, FileReviewPanel as N, parseWorkUpdate as Ni, shouldStringifyBooleanAttribute as Nn, WorkerPoolWorkerError as Nr, readReviewLocation as Nt, FileEditorPanel as O, parseWorkMutationResult as Oi, SELF_CLOSING_TAGS as On, areDiffRenderOptionsEqual as Or, taskRole as Ot, codeThemes as P, parseWorkValue as Pi, Fragment as Pn, isHandledWorkerPoolError as Pr, rememberReviewPosition as Pt, text$4 as Q, boolean$1 as Qi, parsePreviewPins as Qn, parseReviewActionRecoveries as Qr, Spinner as Qt, mutationFileView as R, parseMessage as Ri, jsx as Rn, areFileRenderOptionsEqual as Rr, closeFileTab as Rt, writeRows as S, parseWorkActivity as Si, normalizeUnsafeHTMLProps as Sn, parseThreadStatusInput as Sr, isCodeConversation as St, ItemDiscussion as T, parseWorkDetail as Ti, clientEntry as Tn, reviewConflictIdentity as Tr, readConversationLocation as Tt, captureCanvasPoint as U, statusCategory as Ui, RoutePattern as Un, validateResolvedThemeName as Ur, reconcileFileView as Ut, parseTaskDesign as V, fieldByRole as Vi, equal$1 as Vn, getSharedHighlighter as Vr, parseFileView as Vt, CommentMergeError as W, WorkValidationError as Wi, MAX_PREVIEW_HEIGHT as Wn, attachResolvedThemes as Wr, rememberFile as Wt, parseCommentThread as X, any as Xi, parsePreviewHash as Xn, ResolvedLanguages as Xr, CommentComposer as Xt, object as Y, strict$2 as Yi, parsePreviewCapture as Yn, areLanguagesAttached as Yr, CommentThreadItem as Yt, revision as Z, array as Zi, parsePreviewId as Zn, parseReviewActionPlan as Zr, Loader as Zt, requestComments as _, MAX_CANVAS_Y as _i, Icon$1 as _n, parseThreadInput as _r, PagesWorkspace as _t, saveThreads as a, object$1 as aa, parseRecoveries as ai, LiveStatus as an, predictThreadStatus as ar, FieldCardHeader as at, plainRow as b, parseSectionData as bi, stripFlushMarkers as bn, parseThreadSnapshot as br, conversationHref as bt, previewKey as c, parseSafe as ca, parseReviewRepository as ci, toast as cn, predictWorkUpdate as cr, initialShellTabs as ct, saveWorkspace as d, parseFileSearchQuery as di, hasMessage as dn, parseAnchor as dr, readTabsCookie as dt, defaulted as ea, parseFileSaveRequest as ei, ToolbarSeparator as en, RESYNC as er, BranchSidebar as et, storeDocument as f, parseFileSearchResult as fi, isLocale as fn, parseThread as fr, stepShellTab as ft, CommentsRequestError as g, parseFilePath as gi, Text$1 as gn, parseThreadId as gr, visitShellTab as gt, storedWorkspace as h, parseFileIndex as hi, useLocaleSource as hn, parseThreadFilter as hr, tabsCookieValue as ht, saveThread as i, number$2 as ia, parseMutationResult as ii, IconButton as in, predictThreadReply as ir, FieldCardContent as it, FileRecoveryDialog as j, parseWorkSync as ji, sanitizeUrlAttribute as jn, WorkerPoolTaskCanceledError as jr, legacyFileHref as jt, defaultEditorPreferences as k, parseWorkQuery as ki, isAllowedHostPropName as kn, areFilesEqual as kr, defaultReviewPosition as kt, projectStore as l, string$2 as la, parseReviewSnapshot as li, readPreference as ln, parseWorkChange as lr, openShellTab as lt, storedFiles as m, parseFileDocument as mi, t$2 as mn, parseThreadDeleteInput as mr, tabsCookieName as mt, unavailableComments as n, fail as na, maxFileSaveBytes as ni, ShellTabBar as nn, predictThreadCreate as nr, CommentThreadHeading as nt, threadMatches as o, optional as oa, parseReviewDiff as oi, Tooltip as on, predictWorkAction as or, activeTab as ot, storedDocument as p, parseFileChange as pi, locale as pn, parseThreadCapabilities as pr, tabHref as pt, parseCommentInput as q, parseWork as qi, parsePreview as qn, getResolvedOrResolveLanguage as qr, taskRoutes as qt, followThreads as r, nullable as ra, parseMutationPlan as ri, Select as rn, predictThreadDelete as rr, FieldCard as rt, applyFileUpdate as s, parse$1 as sa, parseReviewHistory as si, AppShell as sn, predictWorkCreate as sr, closeShellTab as st, commentsUnavailable as t, enum_ as ta, parseFileSaveResult as ti, WorkspaceLayout as tn, parseLiveId as tr, ConversationSidebar as tt, saveFiles as u, parseReviewSource as ui, writePreference as un, MAX_THREADS as ur, parseShellTabs as ut, projectLive as v, parseElementAnchor as vi, ref as vn, parseThreadLinkInput as vr, codeCommentCounts as vt, ThreadTaskPicker as w, parseWorkCreate as wi, resolveMixDescriptors as wn, parseFileUpdate as wr, locateCodeConversations as wt, writeOptimistically as x, parseWorkActionInput as xi, on as xn, parseThreadStatus as xr, conversationLabel as xt, routes as y, parseWorkWorkspace as yi, appendFlushMarker as yn, parseThreadReplyInput as yr, conversationDestination as yt, remainingMutationIntent as z, parseMessageAuthor as zi, Route$1 as zn, hasResolvedThemes as zr, defaultFileView as zt };
108826
+ export { Dialog as $, nullable as $i, parseLiveId as $n, maxFileSaveBytes as $r, LiveStatus as $t, FileRecoveryDialog as A, parseWorkUpdate as Ai, createComponent as An, WorkerPoolWorkerError as Ar, readReviewLocation as At, AgentBrowser as B, WorkValidationError as Bi, joinPatterns as Bn, validateResolvedThemeName as Br, reconcileFileView as Bt, ThreadTaskPicker as C, parseWorkItem as Ci, isAllowedHostPropName as Cn, isDiffPlainText as Cr, taskHref as Ct, FileEditorPanel as D, parseWorkSnapshot as Di, shouldStringifyBooleanAttribute as Dn, areDiffTargetsEqual as Dr, defaultReviewView as Dt, ReviewActionDialog as E, parseWorkQuery as Ei, serializeStyleObject as En, areFilesEqual as Er, defaultReviewPosition as Et, defaultFileDestination as F, parseMessage as Fi, pageRoutes as Fn, areFileRenderOptionsEqual as Fr, closeFileTab as Ft, FileSearchPanel as G, strict$2 as Gi, parsePreview as Gn, resolveLanguage as Gr, Loader as Gt, parseTaskDesign as H, nonempty as Hi, MAX_PREVIEW_HEIGHT as Hn, themeResolver as Hr, CommentThreadDetail as Ht, fileActionIntent as I, parseMessageAuthor as Ii, taskRoutes as In, hasResolvedThemes as Ir, defaultFileView as It, CommentThreadHeading as J, boolean$1 as Ji, parsePreviewHash as Jn, parseReviewActionPlan as Jr, ToolbarSeparator as Jt, BranchSidebar as K, any as Ki, parsePreviewBranch as Kn, areLanguagesAttached as Kr, Spinner as Kt, mutationFileView as L, withoutMessages as Li, Route$1 as Ln, areThemesEqual as Lr, fileHref as Lt, FileReviewPanel as M, workRunSummary as Mi, jsx as Mn, markWorkerErrorReported as Mr, reviewComparison as Mt, codeThemes as N, messageDeletionRefusal as Ni, routes as Nn, isFilePlainText as Nr, reviewContextKey as Nt, defaultEditorPreferences as O, parseWorkSync as Oi, Fragment as On, WorkerPoolTaskCanceledError as Or, legacyFileHref as Ot, FileWorkspace as P, messageDeletionRefusals as Pi, fileRoutes as Pn, renderFileWithHighlighter as Pr, reviewHref as Pt, FieldCardHeader as Q, fail as Qi, RESYNC as Qn, parseFileSaveResult as Qr, IconButton as Qt, remainingMutationIntent as R, fieldByRole as Ri, createMultiMatcher as Rn, getSharedHighlighter as Rr, parseFileView as Rt, ThreadTaskLinks as S, parseWorkDetail as Si, SELF_CLOSING_TAGS as Sn, reviewConflictIdentity as Sr, taskAgentHref as St, FileConflictPanel as T, parseWorkMutationResult as Ti, sanitizeUrlAttribute as Tn, areDiffRenderOptionsEqual as Tr, taskRole as Tt, CanvasWorkspace as U, parseWork as Ui, PREVIEW_THUMBNAIL_WIDTHS as Un, getThemes as Ur, CommentThreadItem as Ut, TaskWorkspace as V, identifier$1 as Vi, RoutePattern as Vn, attachResolvedThemes as Vr, rememberFile as Vt, captureCanvasPoint as W, record as Wi, PREVIEW_TILE_HEIGHT as Wn, getResolvedOrResolveLanguage as Wr, CommentComposer as Wt, FieldCardContent as X, defaulted as Xi, parsePreviewPins as Xn, parseReviewActionResult as Xr, ShellTabBar as Xt, FieldCard as Y, createSchema as Yi, parsePreviewId as Yn, parseReviewActionRecoveries as Yr, WorkspaceLayout as Yt, FieldCardFooter as Z, enum_ as Zi, parsePreviewViewport as Zn, parseFileSaveRequest as Zr, Select as Zt, requestComments as _, parseSectionData as _i, composeMixedProps as _n, parseThreadSnapshot as _r, legacyConversationHref as _t, saveThreads as a, string$2 as aa, parseReviewRepository as ai, hasMessage as an, predictWorkCreate as ar, readTabsCookie as at, writeOptimistically as b, parseWorkConnection as bi, isEntry as bn, createCodeAnchor as br, agentViewOpen as bt, previewKey as c, parseFileSearchQuery as ci, t$2 as cn, MAX_THREADS as cr, tabsCookieName as ct, saveWorkspace as d, parseFileDocument as di, Icon$1 as dn, parseThreadDeleteInput as dr, PagesWorkspace as dt, number$2 as ea, parseMutationPlan as ei, Tooltip as en, predictThreadCreate as er, activeTab as et, storeDocument as f, parseFileIndex as fi, ref as fn, parseThreadFilter as fr, codeCommentCounts as ft, CommentsRequestError as g, parseWorkWorkspace as gi, normalizeUnsafeHTMLProps as gn, parseThreadReplyInput as gr, isCodeConversation as gt, storedWorkspace as h, parseElementAnchor as hi, on as hn, parseThreadLinkInput as hr, conversationLabel as ht, saveThread as i, parseSafe as ia, parseReviewHistory as ii, writePreference as in, predictWorkAction as ir, parseShellTabs as it, FileMutationDialog as j, valueByRole as ji, createFrameHandle as jn, isHandledWorkerPoolError as jr, rememberReviewPosition as jt, parseEditorPreferences as k, parseWorkSyncResult as ki, Frame as kn, WorkerPoolTerminatedError as kr, parseReviewSession as kt, projectStore as l, parseFileSearchResult as li, useLocaleSource as ln, parseAnchor as lr, tabsCookieValue as lt, storedFiles as m, MAX_CANVAS_Y as mi, stripFlushMarkers as mn, parseThreadInput as mr, conversationHref as mt, unavailableComments as n, optional as na, parseRecoveries as ni, toast as nn, predictThreadReply as nr, initialShellTabs as nt, threadMatches as o, parseReviewSnapshot as oi, isLocale as on, predictWorkUpdate as or, stepShellTab as ot, storedDocument as p, parseFilePath as pi, appendFlushMarker as pn, parseThreadId as pr, conversationDestination as pt, ConversationSidebar as q, array as qi, parsePreviewCapture as qn, ResolvedLanguages as qr, Button as qt, followThreads as r, parse$1 as ra, parseReviewDiff as ri, readPreference as rn, predictThreadStatus as rr, openShellTab as rt, applyFileUpdate as s, parseReviewSource as si, locale as sn, parseWorkChange as sr, tabHref as st, commentsUnavailable as t, object$1 as ta, parseMutationResult as ti, AppShell as tn, predictThreadDelete as tr, closeShellTab as tt, saveFiles as u, parseFileChange as ui, Text$1 as un, parseThread as ur, visitShellTab as ut, projectLive as v, parseWorkActionInput as vi, resolveMixDescriptors as vn, parseThreadStatus as vr, locateCodeConversations as vt, ItemDiscussion as w, parseWorkItemRef as wi, normalizeAttributeName as wn, renderDiffWithHighlighter as wr, taskLabel as wt, writeRows as x, parseWorkCreate as xi, FRAMEWORK_PROPS as xn, parseFileUpdate as xr, selectedTask as xt, plainRow as y, parseWorkActivity as yi, clientEntry as yn, parseThreadStatusInput as yr, readConversationLocation as yt, TaskRunPanel as z, parseWorkSchema as zi, equal$1 as zn, prepareThemeResolution as zr, readFileLocation as zt };