replicas-mcp 0.2.1 → 0.2.3

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 (36) hide show
  1. package/README.md +1 -1
  2. package/dist/bowser-SUS2LALV.js +2822 -0
  3. package/dist/chunk-2KQN26CJ.js +2094 -0
  4. package/dist/chunk-2TPRCPOE.js +2865 -0
  5. package/dist/chunk-67ORAF4B.js +1490 -0
  6. package/dist/chunk-C6IOMGXW.js +1052 -0
  7. package/dist/chunk-PTKAHAQW.js +576 -0
  8. package/dist/chunk-YPGSID6T.js +436 -0
  9. package/dist/{dist-es-BPXINP6D.js → dist-es-7BMXPGZZ.js} +21 -31
  10. package/dist/{dist-es-SCPV3ZCZ.js → dist-es-7SO54G6Q.js} +25 -23
  11. package/dist/{dist-es-RNSS2U3E.js → dist-es-E6ZIDLCG.js} +27 -32
  12. package/dist/{dist-es-HU5E5HQ2.js → dist-es-IW3K6GSR.js} +9 -10
  13. package/dist/{dist-es-VRURAF5E.js → dist-es-RAHG6NR3.js} +4 -3
  14. package/dist/{dist-es-7T436X7S.js → dist-es-ULKA5ONB.js} +10 -11
  15. package/dist/{dist-es-BSYEGR6D.js → dist-es-UUUR3KKD.js} +47 -51
  16. package/dist/event-streams-3PLTDEYP.js +1377 -0
  17. package/dist/index.js +2026 -221
  18. package/dist/{loadSso-XSERNFCM.js → loadSso-EFZHEVVK.js} +84 -61
  19. package/dist/{signin-GATCKLJP.js → signin-VWN2NRES.js} +94 -82
  20. package/dist/{sso-oidc-JF4BALR2.js → sso-oidc-GJQTR2P3.js} +102 -63
  21. package/dist/{sts-UFAVCISZ.js → sts-5SKYP3PH.js} +4964 -5055
  22. package/package.json +1 -1
  23. package/src/index.ts +2 -2
  24. package/dist/chunk-2KQ6OUSY.js +0 -1033
  25. package/dist/chunk-2Y7PD56W.js +0 -164
  26. package/dist/chunk-5VUQ55WW.js +0 -242
  27. package/dist/chunk-AAVVX4U5.js +0 -175
  28. package/dist/chunk-CXFLI7S3.js +0 -5706
  29. package/dist/chunk-ERL3EC7G.js +0 -44
  30. package/dist/chunk-SGITM26Q.js +0 -877
  31. package/dist/chunk-ST5JVROM.js +0 -39
  32. package/dist/chunk-SWX24AGM.js +0 -62
  33. package/dist/chunk-WPAL27HA.js +0 -29
  34. package/dist/chunk-ZDZBYCXV.js +0 -52
  35. package/dist/chunk-ZNARSMJG.js +0 -14
  36. package/dist/event-streams-EHSSWA6E.js +0 -253
package/dist/index.js CHANGED
@@ -5,9 +5,9 @@ import {
5
5
  __toESM
6
6
  } from "./chunk-MO4EEYFW.js";
7
7
 
8
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/identity.js
8
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js
9
9
  var require_identity = __commonJS({
10
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/identity.js"(exports) {
10
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js"(exports) {
11
11
  "use strict";
12
12
  var ALIAS = /* @__PURE__ */ Symbol.for("yaml.alias");
13
13
  var DOC = /* @__PURE__ */ Symbol.for("yaml.document");
@@ -62,9 +62,9 @@ var require_identity = __commonJS({
62
62
  }
63
63
  });
64
64
 
65
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/visit.js
65
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/visit.js
66
66
  var require_visit = __commonJS({
67
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/visit.js"(exports) {
67
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/visit.js"(exports) {
68
68
  "use strict";
69
69
  var identity = require_identity();
70
70
  var BREAK = /* @__PURE__ */ Symbol("break visit");
@@ -220,9 +220,9 @@ var require_visit = __commonJS({
220
220
  }
221
221
  });
222
222
 
223
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/doc/directives.js
223
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/doc/directives.js
224
224
  var require_directives = __commonJS({
225
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/doc/directives.js"(exports) {
225
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/doc/directives.js"(exports) {
226
226
  "use strict";
227
227
  var identity = require_identity();
228
228
  var visit = require_visit();
@@ -391,9 +391,9 @@ var require_directives = __commonJS({
391
391
  }
392
392
  });
393
393
 
394
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/doc/anchors.js
394
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/doc/anchors.js
395
395
  var require_anchors = __commonJS({
396
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/doc/anchors.js"(exports) {
396
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/doc/anchors.js"(exports) {
397
397
  "use strict";
398
398
  var identity = require_identity();
399
399
  var visit = require_visit();
@@ -461,9 +461,9 @@ var require_anchors = __commonJS({
461
461
  }
462
462
  });
463
463
 
464
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/doc/applyReviver.js
464
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/doc/applyReviver.js
465
465
  var require_applyReviver = __commonJS({
466
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/doc/applyReviver.js"(exports) {
466
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/doc/applyReviver.js"(exports) {
467
467
  "use strict";
468
468
  function applyReviver(reviver, obj, key, val) {
469
469
  if (val && typeof val === "object") {
@@ -511,9 +511,9 @@ var require_applyReviver = __commonJS({
511
511
  }
512
512
  });
513
513
 
514
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/toJS.js
514
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/toJS.js
515
515
  var require_toJS = __commonJS({
516
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/toJS.js"(exports) {
516
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/toJS.js"(exports) {
517
517
  "use strict";
518
518
  var identity = require_identity();
519
519
  function toJS(value, arg, ctx) {
@@ -541,9 +541,9 @@ var require_toJS = __commonJS({
541
541
  }
542
542
  });
543
543
 
544
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/Node.js
544
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/Node.js
545
545
  var require_Node = __commonJS({
546
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/Node.js"(exports) {
546
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/Node.js"(exports) {
547
547
  "use strict";
548
548
  var applyReviver = require_applyReviver();
549
549
  var identity = require_identity();
@@ -582,9 +582,9 @@ var require_Node = __commonJS({
582
582
  }
583
583
  });
584
584
 
585
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/Alias.js
585
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/Alias.js
586
586
  var require_Alias = __commonJS({
587
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/Alias.js"(exports) {
587
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/Alias.js"(exports) {
588
588
  "use strict";
589
589
  var anchors = require_anchors();
590
590
  var visit = require_visit();
@@ -698,9 +698,9 @@ var require_Alias = __commonJS({
698
698
  }
699
699
  });
700
700
 
701
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/Scalar.js
701
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/Scalar.js
702
702
  var require_Scalar = __commonJS({
703
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/Scalar.js"(exports) {
703
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/Scalar.js"(exports) {
704
704
  "use strict";
705
705
  var identity = require_identity();
706
706
  var Node = require_Node();
@@ -728,9 +728,9 @@ var require_Scalar = __commonJS({
728
728
  }
729
729
  });
730
730
 
731
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/doc/createNode.js
731
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/doc/createNode.js
732
732
  var require_createNode = __commonJS({
733
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/doc/createNode.js"(exports) {
733
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/doc/createNode.js"(exports) {
734
734
  "use strict";
735
735
  var Alias = require_Alias();
736
736
  var identity = require_identity();
@@ -803,9 +803,9 @@ var require_createNode = __commonJS({
803
803
  }
804
804
  });
805
805
 
806
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/Collection.js
806
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/Collection.js
807
807
  var require_Collection = __commonJS({
808
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/Collection.js"(exports) {
808
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/Collection.js"(exports) {
809
809
  "use strict";
810
810
  var createNode = require_createNode();
811
811
  var identity = require_identity();
@@ -946,9 +946,9 @@ var require_Collection = __commonJS({
946
946
  }
947
947
  });
948
948
 
949
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyComment.js
949
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyComment.js
950
950
  var require_stringifyComment = __commonJS({
951
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyComment.js"(exports) {
951
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyComment.js"(exports) {
952
952
  "use strict";
953
953
  var stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, "#");
954
954
  function indentComment(comment, indent) {
@@ -963,9 +963,9 @@ var require_stringifyComment = __commonJS({
963
963
  }
964
964
  });
965
965
 
966
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/foldFlowLines.js
966
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/foldFlowLines.js
967
967
  var require_foldFlowLines = __commonJS({
968
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/foldFlowLines.js"(exports) {
968
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/foldFlowLines.js"(exports) {
969
969
  "use strict";
970
970
  var FOLD_FLOW = "flow";
971
971
  var FOLD_BLOCK = "block";
@@ -1099,9 +1099,9 @@ ${indent}${text.slice(fold + 1, end2)}`;
1099
1099
  }
1100
1100
  });
1101
1101
 
1102
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyString.js
1102
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyString.js
1103
1103
  var require_stringifyString = __commonJS({
1104
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyString.js"(exports) {
1104
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyString.js"(exports) {
1105
1105
  "use strict";
1106
1106
  var Scalar = require_Scalar();
1107
1107
  var foldFlowLines = require_foldFlowLines();
@@ -1382,9 +1382,9 @@ ${indent}`);
1382
1382
  }
1383
1383
  });
1384
1384
 
1385
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringify.js
1385
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringify.js
1386
1386
  var require_stringify = __commonJS({
1387
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringify.js"(exports) {
1387
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringify.js"(exports) {
1388
1388
  "use strict";
1389
1389
  var anchors = require_anchors();
1390
1390
  var identity = require_identity();
@@ -1506,9 +1506,9 @@ ${ctx.indent}${str}`;
1506
1506
  }
1507
1507
  });
1508
1508
 
1509
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyPair.js
1509
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyPair.js
1510
1510
  var require_stringifyPair = __commonJS({
1511
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyPair.js"(exports) {
1511
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyPair.js"(exports) {
1512
1512
  "use strict";
1513
1513
  var identity = require_identity();
1514
1514
  var Scalar = require_Scalar();
@@ -1639,9 +1639,9 @@ ${ctx.indent}`;
1639
1639
  }
1640
1640
  });
1641
1641
 
1642
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/log.js
1642
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/log.js
1643
1643
  var require_log = __commonJS({
1644
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/log.js"(exports) {
1644
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/log.js"(exports) {
1645
1645
  "use strict";
1646
1646
  var node_process = __require("process");
1647
1647
  function debug(logLevel, ...messages) {
@@ -1661,9 +1661,9 @@ var require_log = __commonJS({
1661
1661
  }
1662
1662
  });
1663
1663
 
1664
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/merge.js
1664
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/merge.js
1665
1665
  var require_merge = __commonJS({
1666
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/merge.js"(exports) {
1666
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/merge.js"(exports) {
1667
1667
  "use strict";
1668
1668
  var identity = require_identity();
1669
1669
  var Scalar = require_Scalar();
@@ -1721,9 +1721,9 @@ var require_merge = __commonJS({
1721
1721
  }
1722
1722
  });
1723
1723
 
1724
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/addPairToJSMap.js
1724
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/addPairToJSMap.js
1725
1725
  var require_addPairToJSMap = __commonJS({
1726
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/addPairToJSMap.js"(exports) {
1726
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/addPairToJSMap.js"(exports) {
1727
1727
  "use strict";
1728
1728
  var log = require_log();
1729
1729
  var merge = require_merge();
@@ -1785,9 +1785,9 @@ var require_addPairToJSMap = __commonJS({
1785
1785
  }
1786
1786
  });
1787
1787
 
1788
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/Pair.js
1788
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/Pair.js
1789
1789
  var require_Pair = __commonJS({
1790
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/Pair.js"(exports) {
1790
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/Pair.js"(exports) {
1791
1791
  "use strict";
1792
1792
  var createNode = require_createNode();
1793
1793
  var stringifyPair = require_stringifyPair();
@@ -1825,9 +1825,9 @@ var require_Pair = __commonJS({
1825
1825
  }
1826
1826
  });
1827
1827
 
1828
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyCollection.js
1828
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyCollection.js
1829
1829
  var require_stringifyCollection = __commonJS({
1830
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyCollection.js"(exports) {
1830
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyCollection.js"(exports) {
1831
1831
  "use strict";
1832
1832
  var identity = require_identity();
1833
1833
  var stringify = require_stringify();
@@ -1976,9 +1976,9 @@ ${indent}${end}`;
1976
1976
  }
1977
1977
  });
1978
1978
 
1979
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/YAMLMap.js
1979
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/YAMLMap.js
1980
1980
  var require_YAMLMap = __commonJS({
1981
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/YAMLMap.js"(exports) {
1981
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/YAMLMap.js"(exports) {
1982
1982
  "use strict";
1983
1983
  var stringifyCollection = require_stringifyCollection();
1984
1984
  var addPairToJSMap = require_addPairToJSMap();
@@ -2120,9 +2120,9 @@ var require_YAMLMap = __commonJS({
2120
2120
  }
2121
2121
  });
2122
2122
 
2123
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/common/map.js
2123
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/common/map.js
2124
2124
  var require_map = __commonJS({
2125
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/common/map.js"(exports) {
2125
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/common/map.js"(exports) {
2126
2126
  "use strict";
2127
2127
  var identity = require_identity();
2128
2128
  var YAMLMap = require_YAMLMap();
@@ -2142,9 +2142,9 @@ var require_map = __commonJS({
2142
2142
  }
2143
2143
  });
2144
2144
 
2145
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/YAMLSeq.js
2145
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/YAMLSeq.js
2146
2146
  var require_YAMLSeq = __commonJS({
2147
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/nodes/YAMLSeq.js"(exports) {
2147
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/YAMLSeq.js"(exports) {
2148
2148
  "use strict";
2149
2149
  var createNode = require_createNode();
2150
2150
  var stringifyCollection = require_stringifyCollection();
@@ -2258,9 +2258,9 @@ var require_YAMLSeq = __commonJS({
2258
2258
  }
2259
2259
  });
2260
2260
 
2261
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/common/seq.js
2261
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/common/seq.js
2262
2262
  var require_seq = __commonJS({
2263
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/common/seq.js"(exports) {
2263
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/common/seq.js"(exports) {
2264
2264
  "use strict";
2265
2265
  var identity = require_identity();
2266
2266
  var YAMLSeq = require_YAMLSeq();
@@ -2280,9 +2280,9 @@ var require_seq = __commonJS({
2280
2280
  }
2281
2281
  });
2282
2282
 
2283
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/common/string.js
2283
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/common/string.js
2284
2284
  var require_string = __commonJS({
2285
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/common/string.js"(exports) {
2285
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/common/string.js"(exports) {
2286
2286
  "use strict";
2287
2287
  var stringifyString = require_stringifyString();
2288
2288
  var string = {
@@ -2299,9 +2299,9 @@ var require_string = __commonJS({
2299
2299
  }
2300
2300
  });
2301
2301
 
2302
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/common/null.js
2302
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/common/null.js
2303
2303
  var require_null = __commonJS({
2304
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/common/null.js"(exports) {
2304
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/common/null.js"(exports) {
2305
2305
  "use strict";
2306
2306
  var Scalar = require_Scalar();
2307
2307
  var nullTag = {
@@ -2317,9 +2317,9 @@ var require_null = __commonJS({
2317
2317
  }
2318
2318
  });
2319
2319
 
2320
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/core/bool.js
2320
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/core/bool.js
2321
2321
  var require_bool = __commonJS({
2322
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/core/bool.js"(exports) {
2322
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/core/bool.js"(exports) {
2323
2323
  "use strict";
2324
2324
  var Scalar = require_Scalar();
2325
2325
  var boolTag = {
@@ -2341,9 +2341,9 @@ var require_bool = __commonJS({
2341
2341
  }
2342
2342
  });
2343
2343
 
2344
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyNumber.js
2344
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyNumber.js
2345
2345
  var require_stringifyNumber = __commonJS({
2346
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyNumber.js"(exports) {
2346
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyNumber.js"(exports) {
2347
2347
  "use strict";
2348
2348
  function stringifyNumber({ format, minFractionDigits, tag, value }) {
2349
2349
  if (typeof value === "bigint")
@@ -2368,9 +2368,9 @@ var require_stringifyNumber = __commonJS({
2368
2368
  }
2369
2369
  });
2370
2370
 
2371
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/core/float.js
2371
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/core/float.js
2372
2372
  var require_float = __commonJS({
2373
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/core/float.js"(exports) {
2373
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/core/float.js"(exports) {
2374
2374
  "use strict";
2375
2375
  var Scalar = require_Scalar();
2376
2376
  var stringifyNumber = require_stringifyNumber();
@@ -2414,9 +2414,9 @@ var require_float = __commonJS({
2414
2414
  }
2415
2415
  });
2416
2416
 
2417
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/core/int.js
2417
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/core/int.js
2418
2418
  var require_int = __commonJS({
2419
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/core/int.js"(exports) {
2419
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/core/int.js"(exports) {
2420
2420
  "use strict";
2421
2421
  var stringifyNumber = require_stringifyNumber();
2422
2422
  var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
@@ -2459,9 +2459,9 @@ var require_int = __commonJS({
2459
2459
  }
2460
2460
  });
2461
2461
 
2462
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/core/schema.js
2462
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/core/schema.js
2463
2463
  var require_schema = __commonJS({
2464
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/core/schema.js"(exports) {
2464
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/core/schema.js"(exports) {
2465
2465
  "use strict";
2466
2466
  var map = require_map();
2467
2467
  var _null = require_null();
@@ -2487,9 +2487,9 @@ var require_schema = __commonJS({
2487
2487
  }
2488
2488
  });
2489
2489
 
2490
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/json/schema.js
2490
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/json/schema.js
2491
2491
  var require_schema2 = __commonJS({
2492
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/json/schema.js"(exports) {
2492
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/json/schema.js"(exports) {
2493
2493
  "use strict";
2494
2494
  var Scalar = require_Scalar();
2495
2495
  var map = require_map();
@@ -2554,9 +2554,9 @@ var require_schema2 = __commonJS({
2554
2554
  }
2555
2555
  });
2556
2556
 
2557
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/binary.js
2557
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/binary.js
2558
2558
  var require_binary = __commonJS({
2559
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/binary.js"(exports) {
2559
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/binary.js"(exports) {
2560
2560
  "use strict";
2561
2561
  var node_buffer = __require("buffer");
2562
2562
  var Scalar = require_Scalar();
@@ -2620,9 +2620,9 @@ var require_binary = __commonJS({
2620
2620
  }
2621
2621
  });
2622
2622
 
2623
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/pairs.js
2623
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/pairs.js
2624
2624
  var require_pairs = __commonJS({
2625
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/pairs.js"(exports) {
2625
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/pairs.js"(exports) {
2626
2626
  "use strict";
2627
2627
  var identity = require_identity();
2628
2628
  var Pair = require_Pair();
@@ -2698,9 +2698,9 @@ ${cn.comment}` : item.comment;
2698
2698
  }
2699
2699
  });
2700
2700
 
2701
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/omap.js
2701
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/omap.js
2702
2702
  var require_omap = __commonJS({
2703
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/omap.js"(exports) {
2703
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/omap.js"(exports) {
2704
2704
  "use strict";
2705
2705
  var identity = require_identity();
2706
2706
  var toJS = require_toJS();
@@ -2776,9 +2776,9 @@ var require_omap = __commonJS({
2776
2776
  }
2777
2777
  });
2778
2778
 
2779
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/bool.js
2779
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/bool.js
2780
2780
  var require_bool2 = __commonJS({
2781
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/bool.js"(exports) {
2781
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/bool.js"(exports) {
2782
2782
  "use strict";
2783
2783
  var Scalar = require_Scalar();
2784
2784
  function boolStringify({ value, source }, ctx) {
@@ -2808,9 +2808,9 @@ var require_bool2 = __commonJS({
2808
2808
  }
2809
2809
  });
2810
2810
 
2811
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/float.js
2811
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/float.js
2812
2812
  var require_float2 = __commonJS({
2813
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/float.js"(exports) {
2813
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/float.js"(exports) {
2814
2814
  "use strict";
2815
2815
  var Scalar = require_Scalar();
2816
2816
  var stringifyNumber = require_stringifyNumber();
@@ -2857,9 +2857,9 @@ var require_float2 = __commonJS({
2857
2857
  }
2858
2858
  });
2859
2859
 
2860
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/int.js
2860
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/int.js
2861
2861
  var require_int2 = __commonJS({
2862
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/int.js"(exports) {
2862
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/int.js"(exports) {
2863
2863
  "use strict";
2864
2864
  var stringifyNumber = require_stringifyNumber();
2865
2865
  var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
@@ -2936,9 +2936,9 @@ var require_int2 = __commonJS({
2936
2936
  }
2937
2937
  });
2938
2938
 
2939
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/set.js
2939
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/set.js
2940
2940
  var require_set = __commonJS({
2941
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/set.js"(exports) {
2941
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/set.js"(exports) {
2942
2942
  "use strict";
2943
2943
  var identity = require_identity();
2944
2944
  var Pair = require_Pair();
@@ -3025,9 +3025,9 @@ var require_set = __commonJS({
3025
3025
  }
3026
3026
  });
3027
3027
 
3028
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js
3028
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js
3029
3029
  var require_timestamp = __commonJS({
3030
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js"(exports) {
3030
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js"(exports) {
3031
3031
  "use strict";
3032
3032
  var stringifyNumber = require_stringifyNumber();
3033
3033
  function parseSexagesimal(str, asBigInt) {
@@ -3113,9 +3113,9 @@ var require_timestamp = __commonJS({
3113
3113
  }
3114
3114
  });
3115
3115
 
3116
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/schema.js
3116
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/schema.js
3117
3117
  var require_schema3 = __commonJS({
3118
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/schema.js"(exports) {
3118
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/schema.js"(exports) {
3119
3119
  "use strict";
3120
3120
  var map = require_map();
3121
3121
  var _null = require_null();
@@ -3157,9 +3157,9 @@ var require_schema3 = __commonJS({
3157
3157
  }
3158
3158
  });
3159
3159
 
3160
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/tags.js
3160
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/tags.js
3161
3161
  var require_tags = __commonJS({
3162
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/tags.js"(exports) {
3162
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/tags.js"(exports) {
3163
3163
  "use strict";
3164
3164
  var map = require_map();
3165
3165
  var _null = require_null();
@@ -3251,9 +3251,9 @@ var require_tags = __commonJS({
3251
3251
  }
3252
3252
  });
3253
3253
 
3254
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/Schema.js
3254
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/Schema.js
3255
3255
  var require_Schema = __commonJS({
3256
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/schema/Schema.js"(exports) {
3256
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/schema/Schema.js"(exports) {
3257
3257
  "use strict";
3258
3258
  var identity = require_identity();
3259
3259
  var map = require_map();
@@ -3283,9 +3283,9 @@ var require_Schema = __commonJS({
3283
3283
  }
3284
3284
  });
3285
3285
 
3286
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyDocument.js
3286
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyDocument.js
3287
3287
  var require_stringifyDocument = __commonJS({
3288
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyDocument.js"(exports) {
3288
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyDocument.js"(exports) {
3289
3289
  "use strict";
3290
3290
  var identity = require_identity();
3291
3291
  var stringify = require_stringify();
@@ -3363,9 +3363,9 @@ var require_stringifyDocument = __commonJS({
3363
3363
  }
3364
3364
  });
3365
3365
 
3366
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/doc/Document.js
3366
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/doc/Document.js
3367
3367
  var require_Document = __commonJS({
3368
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/doc/Document.js"(exports) {
3368
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/doc/Document.js"(exports) {
3369
3369
  "use strict";
3370
3370
  var Alias = require_Alias();
3371
3371
  var Collection = require_Collection();
@@ -3672,9 +3672,9 @@ var require_Document = __commonJS({
3672
3672
  }
3673
3673
  });
3674
3674
 
3675
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/errors.js
3675
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/errors.js
3676
3676
  var require_errors = __commonJS({
3677
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/errors.js"(exports) {
3677
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/errors.js"(exports) {
3678
3678
  "use strict";
3679
3679
  var YAMLError = class extends Error {
3680
3680
  constructor(name, pos, code, message) {
@@ -3737,9 +3737,9 @@ ${pointer}
3737
3737
  }
3738
3738
  });
3739
3739
 
3740
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-props.js
3740
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-props.js
3741
3741
  var require_resolve_props = __commonJS({
3742
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-props.js"(exports) {
3742
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-props.js"(exports) {
3743
3743
  "use strict";
3744
3744
  function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIndent, startOnNewline }) {
3745
3745
  let spaceBefore = false;
@@ -3871,9 +3871,9 @@ var require_resolve_props = __commonJS({
3871
3871
  }
3872
3872
  });
3873
3873
 
3874
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/util-contains-newline.js
3874
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/util-contains-newline.js
3875
3875
  var require_util_contains_newline = __commonJS({
3876
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/util-contains-newline.js"(exports) {
3876
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/util-contains-newline.js"(exports) {
3877
3877
  "use strict";
3878
3878
  function containsNewline(key) {
3879
3879
  if (!key)
@@ -3913,9 +3913,9 @@ var require_util_contains_newline = __commonJS({
3913
3913
  }
3914
3914
  });
3915
3915
 
3916
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/util-flow-indent-check.js
3916
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/util-flow-indent-check.js
3917
3917
  var require_util_flow_indent_check = __commonJS({
3918
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/util-flow-indent-check.js"(exports) {
3918
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/util-flow-indent-check.js"(exports) {
3919
3919
  "use strict";
3920
3920
  var utilContainsNewline = require_util_contains_newline();
3921
3921
  function flowIndentCheck(indent, fc, onError) {
@@ -3931,9 +3931,9 @@ var require_util_flow_indent_check = __commonJS({
3931
3931
  }
3932
3932
  });
3933
3933
 
3934
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/util-map-includes.js
3934
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/util-map-includes.js
3935
3935
  var require_util_map_includes = __commonJS({
3936
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/util-map-includes.js"(exports) {
3936
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/util-map-includes.js"(exports) {
3937
3937
  "use strict";
3938
3938
  var identity = require_identity();
3939
3939
  function mapIncludes(ctx, items, search) {
@@ -3947,9 +3947,9 @@ var require_util_map_includes = __commonJS({
3947
3947
  }
3948
3948
  });
3949
3949
 
3950
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-block-map.js
3950
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-map.js
3951
3951
  var require_resolve_block_map = __commonJS({
3952
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-block-map.js"(exports) {
3952
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-map.js"(exports) {
3953
3953
  "use strict";
3954
3954
  var Pair = require_Pair();
3955
3955
  var YAMLMap = require_YAMLMap();
@@ -4055,9 +4055,9 @@ var require_resolve_block_map = __commonJS({
4055
4055
  }
4056
4056
  });
4057
4057
 
4058
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-block-seq.js
4058
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-seq.js
4059
4059
  var require_resolve_block_seq = __commonJS({
4060
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-block-seq.js"(exports) {
4060
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-seq.js"(exports) {
4061
4061
  "use strict";
4062
4062
  var YAMLSeq = require_YAMLSeq();
4063
4063
  var resolveProps = require_resolve_props();
@@ -4106,9 +4106,9 @@ var require_resolve_block_seq = __commonJS({
4106
4106
  }
4107
4107
  });
4108
4108
 
4109
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-end.js
4109
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-end.js
4110
4110
  var require_resolve_end = __commonJS({
4111
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-end.js"(exports) {
4111
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-end.js"(exports) {
4112
4112
  "use strict";
4113
4113
  function resolveEnd(end, offset, reqSpace, onError) {
4114
4114
  let comment = "";
@@ -4149,9 +4149,9 @@ var require_resolve_end = __commonJS({
4149
4149
  }
4150
4150
  });
4151
4151
 
4152
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-flow-collection.js
4152
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-flow-collection.js
4153
4153
  var require_resolve_flow_collection = __commonJS({
4154
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-flow-collection.js"(exports) {
4154
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-flow-collection.js"(exports) {
4155
4155
  "use strict";
4156
4156
  var identity = require_identity();
4157
4157
  var Pair = require_Pair();
@@ -4343,9 +4343,9 @@ var require_resolve_flow_collection = __commonJS({
4343
4343
  }
4344
4344
  });
4345
4345
 
4346
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/compose-collection.js
4346
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/compose-collection.js
4347
4347
  var require_compose_collection = __commonJS({
4348
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/compose-collection.js"(exports) {
4348
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/compose-collection.js"(exports) {
4349
4349
  "use strict";
4350
4350
  var identity = require_identity();
4351
4351
  var Scalar = require_Scalar();
@@ -4408,9 +4408,9 @@ var require_compose_collection = __commonJS({
4408
4408
  }
4409
4409
  });
4410
4410
 
4411
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-block-scalar.js
4411
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-scalar.js
4412
4412
  var require_resolve_block_scalar = __commonJS({
4413
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-block-scalar.js"(exports) {
4413
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-scalar.js"(exports) {
4414
4414
  "use strict";
4415
4415
  var Scalar = require_Scalar();
4416
4416
  function resolveBlockScalar(ctx, scalar, onError) {
@@ -4591,9 +4591,9 @@ var require_resolve_block_scalar = __commonJS({
4591
4591
  }
4592
4592
  });
4593
4593
 
4594
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-flow-scalar.js
4594
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-flow-scalar.js
4595
4595
  var require_resolve_flow_scalar = __commonJS({
4596
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-flow-scalar.js"(exports) {
4596
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-flow-scalar.js"(exports) {
4597
4597
  "use strict";
4598
4598
  var Scalar = require_Scalar();
4599
4599
  var resolveEnd = require_resolve_end();
@@ -4811,9 +4811,9 @@ var require_resolve_flow_scalar = __commonJS({
4811
4811
  }
4812
4812
  });
4813
4813
 
4814
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/compose-scalar.js
4814
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/compose-scalar.js
4815
4815
  var require_compose_scalar = __commonJS({
4816
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/compose-scalar.js"(exports) {
4816
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/compose-scalar.js"(exports) {
4817
4817
  "use strict";
4818
4818
  var identity = require_identity();
4819
4819
  var Scalar = require_Scalar();
@@ -4892,9 +4892,9 @@ var require_compose_scalar = __commonJS({
4892
4892
  }
4893
4893
  });
4894
4894
 
4895
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/util-empty-scalar-position.js
4895
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/util-empty-scalar-position.js
4896
4896
  var require_util_empty_scalar_position = __commonJS({
4897
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/util-empty-scalar-position.js"(exports) {
4897
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/util-empty-scalar-position.js"(exports) {
4898
4898
  "use strict";
4899
4899
  function emptyScalarPosition(offset, before, pos) {
4900
4900
  if (before) {
@@ -4922,9 +4922,9 @@ var require_util_empty_scalar_position = __commonJS({
4922
4922
  }
4923
4923
  });
4924
4924
 
4925
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/compose-node.js
4925
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/compose-node.js
4926
4926
  var require_compose_node = __commonJS({
4927
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/compose-node.js"(exports) {
4927
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/compose-node.js"(exports) {
4928
4928
  "use strict";
4929
4929
  var Alias = require_Alias();
4930
4930
  var identity = require_identity();
@@ -5028,9 +5028,9 @@ var require_compose_node = __commonJS({
5028
5028
  }
5029
5029
  });
5030
5030
 
5031
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/compose-doc.js
5031
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/compose-doc.js
5032
5032
  var require_compose_doc = __commonJS({
5033
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/compose-doc.js"(exports) {
5033
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/compose-doc.js"(exports) {
5034
5034
  "use strict";
5035
5035
  var Document = require_Document();
5036
5036
  var composeNode = require_compose_node();
@@ -5071,9 +5071,9 @@ var require_compose_doc = __commonJS({
5071
5071
  }
5072
5072
  });
5073
5073
 
5074
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/composer.js
5074
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/composer.js
5075
5075
  var require_composer = __commonJS({
5076
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/compose/composer.js"(exports) {
5076
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/compose/composer.js"(exports) {
5077
5077
  "use strict";
5078
5078
  var node_process = __require("process");
5079
5079
  var directives = require_directives();
@@ -5155,8 +5155,10 @@ ${cb}` : comment;
5155
5155
  }
5156
5156
  }
5157
5157
  if (afterDoc) {
5158
- Array.prototype.push.apply(doc.errors, this.errors);
5159
- Array.prototype.push.apply(doc.warnings, this.warnings);
5158
+ for (let i = 0; i < this.errors.length; ++i)
5159
+ doc.errors.push(this.errors[i]);
5160
+ for (let i = 0; i < this.warnings.length; ++i)
5161
+ doc.warnings.push(this.warnings[i]);
5160
5162
  } else {
5161
5163
  doc.errors = this.errors;
5162
5164
  doc.warnings = this.warnings;
@@ -5277,9 +5279,9 @@ ${end.comment}` : end.comment;
5277
5279
  }
5278
5280
  });
5279
5281
 
5280
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/cst-scalar.js
5282
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/cst-scalar.js
5281
5283
  var require_cst_scalar = __commonJS({
5282
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/cst-scalar.js"(exports) {
5284
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/cst-scalar.js"(exports) {
5283
5285
  "use strict";
5284
5286
  var resolveBlockScalar = require_resolve_block_scalar();
5285
5287
  var resolveFlowScalar = require_resolve_flow_scalar();
@@ -5462,9 +5464,9 @@ var require_cst_scalar = __commonJS({
5462
5464
  }
5463
5465
  });
5464
5466
 
5465
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/cst-stringify.js
5467
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/cst-stringify.js
5466
5468
  var require_cst_stringify = __commonJS({
5467
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/cst-stringify.js"(exports) {
5469
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/cst-stringify.js"(exports) {
5468
5470
  "use strict";
5469
5471
  var stringify = (cst) => "type" in cst ? stringifyToken(cst) : stringifyItem(cst);
5470
5472
  function stringifyToken(token) {
@@ -5523,9 +5525,9 @@ var require_cst_stringify = __commonJS({
5523
5525
  }
5524
5526
  });
5525
5527
 
5526
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/cst-visit.js
5528
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/cst-visit.js
5527
5529
  var require_cst_visit = __commonJS({
5528
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/cst-visit.js"(exports) {
5530
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/cst-visit.js"(exports) {
5529
5531
  "use strict";
5530
5532
  var BREAK = /* @__PURE__ */ Symbol("break visit");
5531
5533
  var SKIP = /* @__PURE__ */ Symbol("skip children");
@@ -5585,9 +5587,9 @@ var require_cst_visit = __commonJS({
5585
5587
  }
5586
5588
  });
5587
5589
 
5588
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/cst.js
5590
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/cst.js
5589
5591
  var require_cst = __commonJS({
5590
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/cst.js"(exports) {
5592
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/cst.js"(exports) {
5591
5593
  "use strict";
5592
5594
  var cstScalar = require_cst_scalar();
5593
5595
  var cstStringify = require_cst_stringify();
@@ -5687,9 +5689,9 @@ var require_cst = __commonJS({
5687
5689
  }
5688
5690
  });
5689
5691
 
5690
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/lexer.js
5692
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/lexer.js
5691
5693
  var require_lexer = __commonJS({
5692
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/lexer.js"(exports) {
5694
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/lexer.js"(exports) {
5693
5695
  "use strict";
5694
5696
  var cst = require_cst();
5695
5697
  function isEmpty(ch) {
@@ -5889,7 +5891,7 @@ var require_lexer = __commonJS({
5889
5891
  const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
5890
5892
  this.indentNext = this.indentValue + 1;
5891
5893
  this.indentValue += n;
5892
- return yield* this.parseBlockStart();
5894
+ return "block-start";
5893
5895
  }
5894
5896
  return "doc";
5895
5897
  }
@@ -6188,28 +6190,38 @@ var require_lexer = __commonJS({
6188
6190
  return 0;
6189
6191
  }
6190
6192
  *pushIndicators() {
6191
- switch (this.charAt(0)) {
6192
- case "!":
6193
- return (yield* this.pushTag()) + (yield* this.pushSpaces(true)) + (yield* this.pushIndicators());
6194
- case "&":
6195
- return (yield* this.pushUntil(isNotAnchorChar)) + (yield* this.pushSpaces(true)) + (yield* this.pushIndicators());
6196
- case "-":
6197
- // this is an error
6198
- case "?":
6199
- // this is an error outside flow collections
6200
- case ":": {
6201
- const inFlow = this.flowLevel > 0;
6202
- const ch1 = this.charAt(1);
6203
- if (isEmpty(ch1) || inFlow && flowIndicatorChars.has(ch1)) {
6204
- if (!inFlow)
6205
- this.indentNext = this.indentValue + 1;
6206
- else if (this.flowKey)
6207
- this.flowKey = false;
6208
- return (yield* this.pushCount(1)) + (yield* this.pushSpaces(true)) + (yield* this.pushIndicators());
6193
+ let n = 0;
6194
+ loop: while (true) {
6195
+ switch (this.charAt(0)) {
6196
+ case "!":
6197
+ n += yield* this.pushTag();
6198
+ n += yield* this.pushSpaces(true);
6199
+ continue loop;
6200
+ case "&":
6201
+ n += yield* this.pushUntil(isNotAnchorChar);
6202
+ n += yield* this.pushSpaces(true);
6203
+ continue loop;
6204
+ case "-":
6205
+ // this is an error
6206
+ case "?":
6207
+ // this is an error outside flow collections
6208
+ case ":": {
6209
+ const inFlow = this.flowLevel > 0;
6210
+ const ch1 = this.charAt(1);
6211
+ if (isEmpty(ch1) || inFlow && flowIndicatorChars.has(ch1)) {
6212
+ if (!inFlow)
6213
+ this.indentNext = this.indentValue + 1;
6214
+ else if (this.flowKey)
6215
+ this.flowKey = false;
6216
+ n += yield* this.pushCount(1);
6217
+ n += yield* this.pushSpaces(true);
6218
+ continue loop;
6219
+ }
6209
6220
  }
6210
6221
  }
6222
+ break loop;
6211
6223
  }
6212
- return 0;
6224
+ return n;
6213
6225
  }
6214
6226
  *pushTag() {
6215
6227
  if (this.charAt(1) === "<") {
@@ -6266,9 +6278,9 @@ var require_lexer = __commonJS({
6266
6278
  }
6267
6279
  });
6268
6280
 
6269
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/line-counter.js
6281
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/line-counter.js
6270
6282
  var require_line_counter = __commonJS({
6271
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/line-counter.js"(exports) {
6283
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/line-counter.js"(exports) {
6272
6284
  "use strict";
6273
6285
  var LineCounter = class {
6274
6286
  constructor() {
@@ -6297,9 +6309,9 @@ var require_line_counter = __commonJS({
6297
6309
  }
6298
6310
  });
6299
6311
 
6300
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/parser.js
6312
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/parser.js
6301
6313
  var require_parser = __commonJS({
6302
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/parse/parser.js"(exports) {
6314
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/parser.js"(exports) {
6303
6315
  "use strict";
6304
6316
  var node_process = __require("process");
6305
6317
  var cst = require_cst();
@@ -6368,6 +6380,13 @@ var require_parser = __commonJS({
6368
6380
  }
6369
6381
  return prev.splice(i, prev.length);
6370
6382
  }
6383
+ function arrayPushArray(target, source) {
6384
+ if (source.length < 1e5)
6385
+ Array.prototype.push.apply(target, source);
6386
+ else
6387
+ for (let i = 0; i < source.length; ++i)
6388
+ target.push(source[i]);
6389
+ }
6371
6390
  function fixFlowSeqItems(fc) {
6372
6391
  if (fc.start.type === "flow-seq-start") {
6373
6392
  for (const it of fc.items) {
@@ -6377,11 +6396,11 @@ var require_parser = __commonJS({
6377
6396
  delete it.key;
6378
6397
  if (isFlowToken(it.value)) {
6379
6398
  if (it.value.end)
6380
- Array.prototype.push.apply(it.value.end, it.sep);
6399
+ arrayPushArray(it.value.end, it.sep);
6381
6400
  else
6382
6401
  it.value.end = it.sep;
6383
6402
  } else
6384
- Array.prototype.push.apply(it.start, it.sep);
6403
+ arrayPushArray(it.start, it.sep);
6385
6404
  delete it.sep;
6386
6405
  }
6387
6406
  }
@@ -6736,7 +6755,7 @@ var require_parser = __commonJS({
6736
6755
  const prev = map.items[map.items.length - 2];
6737
6756
  const end = prev?.value?.end;
6738
6757
  if (Array.isArray(end)) {
6739
- Array.prototype.push.apply(end, it.start);
6758
+ arrayPushArray(end, it.start);
6740
6759
  end.push(this.sourceToken);
6741
6760
  map.items.pop();
6742
6761
  return;
@@ -6924,7 +6943,7 @@ var require_parser = __commonJS({
6924
6943
  const prev = seq.items[seq.items.length - 2];
6925
6944
  const end = prev?.value?.end;
6926
6945
  if (Array.isArray(end)) {
6927
- Array.prototype.push.apply(end, it.start);
6946
+ arrayPushArray(end, it.start);
6928
6947
  end.push(this.sourceToken);
6929
6948
  seq.items.pop();
6930
6949
  return;
@@ -7164,9 +7183,9 @@ var require_parser = __commonJS({
7164
7183
  }
7165
7184
  });
7166
7185
 
7167
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/public-api.js
7186
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/public-api.js
7168
7187
  var require_public_api = __commonJS({
7169
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/public-api.js"(exports) {
7188
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/public-api.js"(exports) {
7170
7189
  "use strict";
7171
7190
  var composer = require_composer();
7172
7191
  var Document = require_Document();
@@ -7261,9 +7280,9 @@ var require_public_api = __commonJS({
7261
7280
  }
7262
7281
  });
7263
7282
 
7264
- // ../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/index.js
7283
+ // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/index.js
7265
7284
  var require_dist = __commonJS({
7266
- "../node_modules/.bun/yaml@2.8.4/node_modules/yaml/dist/index.js"(exports) {
7285
+ "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/index.js"(exports) {
7267
7286
  "use strict";
7268
7287
  var composer = require_composer();
7269
7288
  var Document = require_Document();
@@ -7318,7 +7337,14 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7318
7337
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7319
7338
  import { z } from "zod";
7320
7339
 
7340
+ // ../shared/src/type-guards.ts
7341
+ function isRecord(value) {
7342
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7343
+ }
7344
+
7321
7345
  // ../shared/src/event.ts
7346
+ var USER_MESSAGE_ID_PAYLOAD_KEY = "replicasMessageId";
7347
+ var CODEX_ASP_ITEM_ID_PAYLOAD_KEY = "codexAspItemId";
7322
7348
  var CODEX_QUOTA_STATUS_EVENT_TYPE = "codex-quota-status";
7323
7349
 
7324
7350
  // ../shared/src/pricing.ts
@@ -7367,7 +7393,7 @@ var PLANS = {
7367
7393
  "Unlimited automations",
7368
7394
  "Higher API rate limits",
7369
7395
  "Warm pools and warm hooks",
7370
- "Auto-upgraded sandbox resources (32 GB disk, 16 GB memory)",
7396
+ "Auto-upgraded sandbox resources (4 vCPU, 32 GB disk, 16 GB memory)",
7371
7397
  "Shared Slack support channel"
7372
7398
  ]
7373
7399
  },
@@ -7398,18 +7424,1497 @@ var SANDBOX_LIFECYCLE = {
7398
7424
  AUTO_DELETE_MINUTES: -1,
7399
7425
  SSH_TOKEN_EXPIRATION_MINUTES: 3 * 60
7400
7426
  };
7427
+ var WORKSPACE_SIZES = ["small", "large"];
7428
+ var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
7429
+
7430
+ // ../shared/src/default-skills/replicas-agent/abilities/computer.ts
7431
+ var SECTION = `### Computer use (Linux desktop control)
7432
+ Drive the workspace's Linux desktop - open a browser, click, type, scroll, screenshot, record - via the \`replicas computer\` CLI. Every Replicas workspace boots with Xvfb / openbox / x11vnc / noVNC pre-installed and the live noVNC viewer is automatically published as an authenticated preview, so a \`Desktop\` tab is always available in the dashboard. Use \`replicas computer info\` to get the viewer URL when you want to share it (e.g. point a user on Slack at the live stream).
7433
+
7434
+ **Reference:** \`references/COMPUTER-USE.md\`
7435
+
7436
+ Use this when:
7437
+ - A task requires interacting with a website, web app, or desktop application that has no usable API
7438
+ - You want the user to watch the agent work - they can open the \`Desktop\` tab, or you can share the URL from \`replicas computer info\`
7439
+ - You're testing UI changes in a browser before reporting them as done
7440
+ - You want to record a screen capture of a task as proof to share back`;
7441
+ var REFERENCE = `# Computer use (Linux desktop control)
7442
+
7443
+ Every Replicas workspace boots with a full Linux desktop stack - Xvfb (1920\xD71080), openbox, tint2, x11vnc, noVNC, ffmpeg, and Google Chrome. The engine also auto-registers the noVNC viewer (port 6080) as an authenticated preview at startup, so the dashboard \`Desktop\` tab is live the moment the workspace is up. You drive the desktop through the \`replicas computer\` CLI.
7444
+
7445
+ Use this for anything the user can't reasonably do via an API - clicking around web apps, filling forms, testing UI changes, dragging files between desktop apps, recording a walkthrough.
7446
+
7447
+ ## When to use it
7448
+
7449
+ - **Prefer real APIs first.** If a task has a CLI or HTTP API (GitHub, Linear, Slack, Replicas itself), use that. Driving a UI is slower, flakier, and less auditable.
7450
+ - **Use it when there's no API**: testing a frontend you just changed, navigating a vendor portal, demonstrating a flow on video.
7451
+ - **Use it when the user wants to watch.** The dashboard already shows a \`Desktop\` tab. If you're talking to the user somewhere else (e.g. Slack), call \`replicas computer info\` to get the viewer URL and paste it in.
7452
+
7453
+ ## Never use raw \`xdotool\` / \`scrot\` / \`ffmpeg\` directly
7454
+
7455
+ The CLI is the canonical surface. Chat transcripts that show \`DISPLAY=:99 xdotool key Return\` are noisy and break when the underlying stack changes. Always call the CLI:
7456
+
7457
+ \`\`\`bash
7458
+ # DO
7459
+ replicas computer key Return
7460
+ replicas computer screenshot /tmp/state.png
7461
+
7462
+ # DON'T
7463
+ DISPLAY=:99 xdotool key Return
7464
+ scrot /tmp/state.png
7465
+ \`\`\`
7466
+
7467
+ ## Quickstart
7468
+
7469
+ \`\`\`bash
7470
+ # 1) (Optional) Get the live viewer URL so you can share it with the user.
7471
+ # The desktop is already running and the preview is already registered -
7472
+ # this just looks up the URL.
7473
+ replicas computer info
7474
+
7475
+ # 2) Launch a browser on the workspace display.
7476
+ replicas computer launch chrome
7477
+
7478
+ # 3) Take a screenshot so you can see what's there.
7479
+ replicas computer screenshot /tmp/state.png
7480
+ # (Read the PNG yourself before deciding where to click.)
7481
+
7482
+ # 4) Drive the UI.
7483
+ replicas computer key ctrl+l # focus address bar
7484
+ replicas computer type "https://news.ycombinator.com"
7485
+ replicas computer key Return
7486
+ replicas computer click 521 700 # click coordinates from the screenshot
7487
+ replicas computer scroll down --amount 5
7488
+
7489
+ # 5) (Optional) Record a screencap to share back.
7490
+ replicas computer record start /tmp/demo.mp4 --fps 60
7491
+ # ... do stuff ...
7492
+ replicas computer record stop
7493
+ replicas media upload /tmp/demo.mp4
7494
+ \`\`\`
7495
+
7496
+ ## Command reference
7497
+
7498
+ ### \`replicas computer info\`
7499
+ Prints the live noVNC viewer URL (\`https://6080-<hash>.tryreplicas.com/\`) for the workspace desktop. The engine auto-registers this authenticated preview on startup; \`info\` just looks it up. Use it when you want to share the live stream URL with the user out-of-band (e.g. in a Slack reply) - the dashboard \`Desktop\` tab already points at the same URL automatically.
7500
+
7501
+ If invoked very early in the workspace lifecycle, \`info\` will poll briefly while the engine finishes registering the preview, then error if it's still not available.
7502
+
7503
+ ### \`replicas computer status\`
7504
+ Prints which desktop services are running and the active preview URL (if any). Useful for debugging when a tool call seems to be doing nothing.
7505
+
7506
+ ### \`replicas computer screenshot <path>\`
7507
+ Captures the current desktop to a PNG at the given path. Read the file (e.g. with your Read tool) to see what's on screen - coordinates from the screenshot drive subsequent \`click\` / \`move\` / \`drag\` calls.
7508
+
7509
+ ### \`replicas computer click <x> <y> [--button N] [--double] [--modifiers ctrl+shift]\`
7510
+ Move to (x, y) and click. Default is left-click (button 1); pass \`--button 3\` for right-click. \`--modifiers\` holds keys during the click (e.g. ctrl-click a link to open in a new tab).
7511
+
7512
+ ### \`replicas computer move <x> <y>\`
7513
+ Move the mouse without clicking. Useful for hovering tooltips.
7514
+
7515
+ ### \`replicas computer type <text> [--delay MS]\`
7516
+ Type a literal string into the focused field. Default per-character delay is 12ms (~80 wpm) - feels human and avoids breaking apps that debounce input. Bump \`--delay 30\` for stricter apps.
7517
+
7518
+ For key combos (not literal text), use \`key\`. \`type "ctrl+l"\` will literally type the seven characters \`c t r l + l\`.
7519
+
7520
+ ### \`replicas computer key <combo>\`
7521
+ Press a single key or combo. Examples: \`Return\`, \`Escape\`, \`Tab\`, \`ctrl+l\`, \`ctrl+shift+t\`, \`alt+Left\`, \`Page_Down\`, \`Home\`. Syntax matches \`xdotool key\`.
7522
+
7523
+ ### \`replicas computer scroll <up|down|left|right> [--amount N] [--x X --y Y]\`
7524
+ Scroll the wheel. Pass \`--x\` / \`--y\` to hover before scrolling (otherwise scrolls wherever the cursor currently is). Default amount is 3 wheel ticks.
7525
+
7526
+ ### \`replicas computer drag <fromX> <fromY> <toX> <toY>\`
7527
+ Press left mouse at (fromX, fromY), drag to (toX, toY), release. For things like dragging a file onto an upload zone.
7528
+
7529
+ ### \`replicas computer launch <app> [args...]\`
7530
+ Spawns an app on the workspace display. Built-in aliases:
7531
+ - \`chrome\` - Google Chrome with a clean profile and sane flags
7532
+ - \`chromium\` - Chromium variant
7533
+ - \`firefox\` - Firefox
7534
+ - \`terminal\` - xfce4-terminal (modern, themed); \`xterm\` for the classic
7535
+ - \`notepad\` / \`editor\` - mousepad (lightweight GTK text editor)
7536
+ - \`files\` / \`filemanager\` - thunar (file manager)
7537
+ Anything else gets \`exec\`'d verbatim, so \`replicas computer launch xeyes\` works if xeyes is installed.
7538
+
7539
+ ### \`replicas computer record start <path> [--fps N]\`
7540
+ Starts an ffmpeg screen recorder. Output is a fragmented MP4 (still playable if the workspace dies mid-record). Default 60fps; drop to 30 if the workspace is CPU-constrained.
7541
+
7542
+ Only one recording at a time. Re-running \`start\` while one is active fails - call \`stop\` first.
7543
+
7544
+ ### \`replicas computer record stop\`
7545
+ SIGINTs ffmpeg, waits for it to finalize the MP4, prints the output path. Upload it with \`replicas media upload <path>\` to share it.
7546
+
7547
+ ## Patterns
7548
+
7549
+ ### Action / screenshot loop
7550
+ You are blind between tool calls. After any action that changes the screen, take a screenshot before deciding the next coordinate:
7551
+
7552
+ \`\`\`bash
7553
+ replicas computer click 521 700
7554
+ sleep 2 # let the page settle
7555
+ replicas computer screenshot /tmp/after-click.png
7556
+ # read /tmp/after-click.png, decide next click
7557
+ \`\`\`
7558
+
7559
+ \`sleep\` is a regular shell sleep - there's no \`replicas computer wait\` command, but you can mix shell sleeps freely.
7560
+
7561
+ ### Typing into an address bar
7562
+ \`\`\`bash
7563
+ replicas computer key ctrl+l # focus address bar
7564
+ replicas computer type "https://example.com"
7565
+ replicas computer key Return
7566
+ sleep 3 # wait for page load
7567
+ replicas computer screenshot /tmp/loaded.png
7568
+ \`\`\`
7569
+
7570
+ ### Coordinates from screenshots
7571
+ The display is 1920\xD71080. Screenshot pixels map 1:1 to click coordinates - if your Read tool shows a button at pixel (520, 700), click \`replicas computer click 520 700\`. **No translation needed.** Modern image-reading models often imagine the screenshot is at a different resolution; trust the \`xdpyinfo\` value (\`replicas computer status\` shows the real size).
7572
+
7573
+ ### Letting the user watch
7574
+ The Desktop tab is already live in the dashboard - the user can open it any time. If you're communicating with the user somewhere else (Slack, PR comment, etc.), grab the URL with \`replicas computer info\` and share it inline so they can watch you work.
7575
+
7576
+ ### Recording a deliverable
7577
+ For tasks the user wants proof of:
7578
+ \`\`\`bash
7579
+ replicas computer record start /tmp/walkthrough.mp4
7580
+ # ... your work ...
7581
+ replicas computer record stop
7582
+ replicas media upload /tmp/walkthrough.mp4
7583
+ \`\`\`
7584
+ Then embed the printed \`![\u2026](\u2026)\` line in your chat reply. See \`MEDIA.md\`.
7585
+
7586
+ ## Failure modes
7587
+
7588
+ - **"Desktop services script missing"**: workspace image is older than this skill. Tell the user - nothing you can do from the CLI side.
7589
+ - **\`xdotool ... failed: Can't open display\`**: Xvfb didn't come up. \`replicas computer status\` will show which service is dead. Re-running any CLI command auto-attempts to start it.
7590
+ - **Browser doesn't appear after \`launch chrome\`**: give it 1-2s, then screenshot. Chrome cold-start on the virtual display takes ~500ms but bigger pages take longer.
7591
+ - **Live preview shows static / black screen**: the browser may have crashed. \`replicas computer status\` should show no Chrome process - re-launch.
7592
+ - **\`replicas computer info\` errors with "not registered"**: engine couldn't register the preview at startup (transient monolith error, or warming mode). Re-running the engine usually fixes it. Until it's registered, the Desktop tab will show a placeholder.
7593
+
7594
+ ## What gets baked in vs. lazy
7595
+
7596
+ | Component | Where |
7597
+ |---|---|
7598
+ | \`xvfb\`, \`openbox\`, \`tint2\`, \`x11vnc\`, \`websockify\`, \`xdotool\`, \`scrot\`, \`ffmpeg\`, \`google-chrome\` | Baked into the workspace image |
7599
+ | Xvfb / openbox / tint2 / x11vnc / websockify processes | Started at workspace boot (\`replicas-start-desktop-services\`) |
7600
+ | noVNC preview URL (port 6080) | Registered by the engine on startup (authenticated) |
7601
+ | Dashboard \`Desktop\` tab | Always available once the engine has registered the preview |
7602
+
7603
+ You can call any of the input tools (\`click\`, \`type\`, \`screenshot\`, etc.) immediately - the daemons are already running.
7604
+ `;
7605
+ var COMPUTER_ABILITY = {
7606
+ label: "Computer use",
7607
+ description: "Drive the workspace's Linux desktop and stream a live noVNC viewer.",
7608
+ bullet: "- Driving the workspace Linux desktop (open a browser, click, type, scroll, screenshot, record) and exposing a live noVNC viewer in the dashboard",
7609
+ section: SECTION,
7610
+ referenceFile: { name: "COMPUTER-USE.md", content: REFERENCE }
7611
+ };
7612
+
7613
+ // ../shared/src/default-skills/replicas-agent/abilities/docker.ts
7614
+ var SECTION2 = `### Docker
7615
+ Start and use the Docker daemon in Replicas workspaces. Docker is pre-installed but the daemon does not auto-start.
7616
+
7617
+ **Reference:** \`references/DOCKER.md\`
7618
+
7619
+ Use this when:
7620
+ - You need to run \`docker\` or \`docker compose\` commands
7621
+ - You need to build or run Docker containers
7622
+ - Your task involves containerized services or Docker-based workflows`;
7623
+ var REFERENCE2 = `# Docker
7624
+
7625
+ Docker is pre-installed in Replicas workspaces, but the daemon does **not** auto-start. You must start it manually before running any \`docker\` or \`docker compose\` commands.
7626
+
7627
+ ## Starting the Docker Daemon
7628
+
7629
+ \`\`\`bash
7630
+ sudo service docker start
7631
+ until docker info >/dev/null 2>&1; do sleep 0.2; done
7632
+ \`\`\`
7633
+
7634
+ \`service docker start\` returns before the socket is accepting connections, so immediate commands may fail without the poll.
7635
+
7636
+ ## Important Notes
7637
+
7638
+ - **Start once per session.** The daemon stays running until the workspace shuts down. You do not need to restart it between commands.
7639
+ - **Check before starting.** If you are unsure whether the daemon is already running, check first to avoid an unnecessary restart:
7640
+ \`\`\`bash
7641
+ docker info >/dev/null 2>&1 || { sudo service docker start && until docker info >/dev/null 2>&1; do sleep 0.2; done; }
7642
+ \`\`\`
7643
+ - **Sudo is only required for starting the daemon.** The workspace user is in the \`docker\` group, so regular \`docker\` commands work without sudo.
7644
+ `;
7645
+ var DOCKER_ABILITY = {
7646
+ label: "Docker",
7647
+ description: "Start the daemon, build/run containers, drive `docker compose`.",
7648
+ bullet: "- Using Docker (starting the daemon, running containers, docker compose)",
7649
+ section: SECTION2,
7650
+ referenceFile: { name: "DOCKER.md", content: REFERENCE2 }
7651
+ };
7652
+
7653
+ // ../shared/src/default-skills/replicas-agent/abilities/github.ts
7654
+ var SECTION3 = `### GitHub
7655
+ Use the pre-authenticated \`gh\` CLI for pull requests, issues, actions, and API calls.
7656
+
7657
+ **Reference:** \`references/GITHUB.md\`
7658
+
7659
+ Use this when:
7660
+ - You need to create, review, or manage pull requests
7661
+ - You need to interact with GitHub issues or actions
7662
+ - You need to use the GitHub API for advanced operations
7663
+ - You need to include images in PR descriptions`;
7664
+ var REFERENCE3 = `# GitHub Integration
7665
+
7666
+ This guide covers how to interact with GitHub from within your Replicas workspace.
7667
+
7668
+ ## Prerequisites
7669
+
7670
+ The \`gh\` CLI is pre-installed and authenticated in your workspace. You can verify this:
7671
+
7672
+ \`\`\`bash
7673
+ gh auth status
7674
+ \`\`\`
7675
+
7676
+ If authenticated, you can immediately use \`gh\` for all GitHub operations. No additional setup is needed.
7677
+
7678
+ ## Using the \`gh\` CLI
7679
+
7680
+ The GitHub CLI (\`gh\`) is the recommended way to interact with GitHub. It handles authentication, pagination, and API formatting automatically.
7681
+
7682
+ ### Pull Requests
7683
+
7684
+ \`\`\`bash
7685
+ # Create a PR
7686
+ gh pr create --title "Title" --body "Description"
7687
+
7688
+ # List open PRs
7689
+ gh pr list
7690
+
7691
+ # View a specific PR
7692
+ gh pr view 123
7693
+
7694
+ # Review/check PR status
7695
+ gh pr checks 123
7696
+
7697
+ # Merge a PR
7698
+ gh pr merge 123
7699
+ \`\`\`
7700
+
7701
+ ### Issues
7702
+
7703
+ \`\`\`bash
7704
+ # Create an issue
7705
+ gh issue create --title "Title" --body "Description"
7706
+
7707
+ # View an issue
7708
+ gh issue view 123
7709
+
7710
+ # List issues
7711
+ gh issue list
7712
+
7713
+ # Close an issue
7714
+ gh issue close 123
7715
+
7716
+ # Add a comment
7717
+ gh issue comment 123 --body "Your comment"
7718
+ \`\`\`
7719
+
7720
+ ### Repository Operations
7721
+
7722
+ \`\`\`bash
7723
+ # View repo info
7724
+ gh repo view
7725
+
7726
+ # Clone a repo
7727
+ gh repo clone owner/repo
7728
+
7729
+ # List releases
7730
+ gh release list
7731
+ \`\`\`
7732
+
7733
+ ### GitHub Actions / Checks
7734
+
7735
+ \`\`\`bash
7736
+ # List workflow runs
7737
+ gh run list
7738
+
7739
+ # View a specific run
7740
+ gh run view RUN_ID
7741
+
7742
+ # Watch a run in progress
7743
+ gh run watch RUN_ID
7744
+
7745
+ # Re-run failed jobs
7746
+ gh run rerun RUN_ID --failed
7747
+ \`\`\`
7748
+
7749
+ ### GitHub API (Advanced)
7750
+
7751
+ For operations not covered by \`gh\` subcommands, use the API directly:
7752
+
7753
+ \`\`\`bash
7754
+ # GET request
7755
+ gh api repos/owner/repo/pulls/123/comments
7756
+
7757
+ # POST request
7758
+ gh api repos/owner/repo/issues/123/comments -f body="Comment text"
7759
+
7760
+ # GraphQL query
7761
+ gh api graphql -f query='{ repository(owner: "owner", name: "repo") { issues(first: 10) { nodes { title number } } } }'
7762
+ \`\`\`
7763
+
7764
+ ### Working with PR Reviews
7765
+
7766
+ \`\`\`bash
7767
+ # View PR comments
7768
+ gh api repos/owner/repo/pulls/123/comments
7769
+
7770
+ # View PR review comments
7771
+ gh api repos/owner/repo/pulls/123/reviews
7772
+
7773
+ # Submit a review
7774
+ gh pr review 123 --approve
7775
+ gh pr review 123 --request-changes --body "Changes needed"
7776
+ \`\`\`
7777
+
7778
+ ## Image Uploads in PRs
7779
+
7780
+ GitHub does NOT have a public API for uploading images to PRs/issues. When you need to include images:
7781
+ - Do NOT use placeholder image URLs
7782
+ - Do NOT commit screenshots as files to the repository
7783
+ - Use the \`replicas-agent\` skill to share the image
7784
+ - If you were triggered from Slack, also upload the image to the Slack thread so the user can see it directly
7785
+ `;
7786
+ var GITHUB_ABILITY = {
7787
+ label: "GitHub",
7788
+ description: "Pre-authenticated `gh` CLI for PRs, issues, releases, and GraphQL.",
7789
+ bullet: "- Interacting with GitHub (creating PRs, managing issues, using the API, etc.)",
7790
+ section: SECTION3,
7791
+ referenceFile: { name: "GITHUB.md", content: REFERENCE3 }
7792
+ };
7793
+
7794
+ // ../shared/src/default-skills/replicas-agent/abilities/google.ts
7795
+ var SECTION4 = `### Google Workspace (Docs, Sheets, Forms, Drive)
7796
+ Create and edit Google Docs, Sheets, and Forms via the Replicas gateway. Files are owned by Replicas \u2014 the integration cannot access pre-existing Google content created outside of it.
7797
+
7798
+ **Reference:** \`references/GOOGLE.md\`
7799
+
7800
+ Use this when:
7801
+ - You need to create or edit a Google Doc, Sheet, or Form
7802
+ - You need to share, rename, move, or delete a Replicas-created Google file
7803
+ - You need to read responses from a Replicas-created Google Form`;
7804
+ var REFERENCE4 = `# Google Workspace (Docs, Sheets, Forms, Drive)
7805
+
7806
+ This guide covers how to create and edit Google Docs, Sheets, and Forms \u2014 plus do basic Drive file operations \u2014 from inside a Replicas workspace, using the monolith as a gateway to Google's APIs.
7807
+
7808
+ ## Prerequisites
7809
+
7810
+ The integration is configured at the org or user level by the Replicas admin. From inside a workspace you don't have a Google access token directly; instead you call the monolith's \`/v1/gdrive/*\` endpoints, authenticated with your workspace's engine secret. The monolith refreshes the org's (or user's) Google access token and proxies the call.
7811
+
7812
+ Quick check that the integration is connected:
7813
+
7814
+ \`\`\`bash
7815
+ curl -s -X GET "$MONOLITH_URL/v1/gdrive/credentials" \\
7816
+ -H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" \\
7817
+ -H "X-Workspace-Id: $WORKSPACE_ID"
7818
+ \`\`\`
7819
+
7820
+ - If \`hasCredentials\` is \`true\`: you're good to go.
7821
+ - If \`hasCredentials\` is \`false\`: Google has not been connected for this org. Ask the user to go to **Settings \u2192 Integrations \u2192 Google** in the [Replicas dashboard](https://replicas.dev) and connect a Google account. Do not attempt Google operations until it's connected.
7822
+
7823
+ Standard auth headers used by every call below:
7824
+
7825
+ \`\`\`
7826
+ Authorization: Bearer $REPLICAS_ENGINE_SECRET
7827
+ X-Workspace-Id: $WORKSPACE_ID
7828
+ \`\`\`
7829
+
7830
+ For brevity the examples below use a shell variable:
7831
+
7832
+ \`\`\`bash
7833
+ GDRIVE_AUTH=(-H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" -H "X-Workspace-Id: $WORKSPACE_ID")
7834
+ \`\`\`
7835
+
7836
+ ## Important constraint: drive.file scope
7837
+
7838
+ The integration uses the **sensitive-tier \`drive.file\` scope**. That means Replicas can only read and edit Google files **it created itself**. It **cannot**:
7839
+
7840
+ - Read or edit a user's pre-existing Google Docs, Sheets, or Forms \u2014 even ones that were shared with the connected Google account.
7841
+ - List or search the user's broader Drive.
7842
+ - Touch any file that was not created via these gateway endpoints.
7843
+
7844
+ If the user asks you to edit an existing doc that Replicas didn't create, tell them this constraint and offer to create a new doc that mirrors what they want.
7845
+
7846
+ ## Google Docs
7847
+
7848
+ ### Create a new doc
7849
+
7850
+ \`\`\`bash
7851
+ curl -s -X POST "$MONOLITH_URL/v1/gdrive/docs" "\${GDRIVE_AUTH[@]}" \\
7852
+ -H "Content-Type: application/json" \\
7853
+ -d '{"title":"Meeting notes 2026-05-14"}'
7854
+ \`\`\`
7855
+
7856
+ Returns the full Doc object; grab \`.documentId\` for follow-up calls.
7857
+
7858
+ ### Read a doc
7859
+
7860
+ \`\`\`bash
7861
+ curl -s "$MONOLITH_URL/v1/gdrive/docs/$DOC_ID" "\${GDRIVE_AUTH[@]}"
7862
+ \`\`\`
7863
+
7864
+ Returns the full document structure \u2014 \`body.content\` is an ordered list of structural elements (paragraphs, tables, etc.) with character indexes you can target for edits.
7865
+
7866
+ ### Edit a doc (batchUpdate)
7867
+
7868
+ The Docs API edits use a list of [structural requests](https://developers.google.com/workspace/docs/api/reference/rest/v1/documents/request). Insert text, then style it; or insert tables, images, page breaks, etc.
7869
+
7870
+ \`\`\`bash
7871
+ curl -s -X POST "$MONOLITH_URL/v1/gdrive/docs/$DOC_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
7872
+ -H "Content-Type: application/json" \\
7873
+ -d '{
7874
+ "requests": [
7875
+ { "insertText": { "location": { "index": 1 }, "text": "Hello, world!\\n" } }
7876
+ ]
7877
+ }'
7878
+ \`\`\`
7879
+
7880
+ Common request types:
7881
+
7882
+ - \`insertText\` \u2014 insert plain text at a given index
7883
+ - \`deleteContentRange\` \u2014 delete a range
7884
+ - \`replaceAllText\` \u2014 find-and-replace
7885
+ - \`updateTextStyle\` \u2014 bold/italic/colors/fonts/sizes for a range
7886
+ - \`updateParagraphStyle\` \u2014 headings (\`HEADING_1\`..\`HEADING_6\`), alignment, spacing
7887
+ - \`createParagraphBullets\` \u2014 turn paragraphs into bulleted/numbered lists
7888
+ - \`insertTable\` \u2014 insert a table
7889
+ - \`insertInlineImage\` \u2014 insert an image from a URL
7890
+
7891
+ Edits are verbose but powerful. Prefer batching many requests into a single \`batchUpdate\` call rather than making many round trips \u2014 it's faster and keeps the doc state consistent.
7892
+
7893
+ ## Google Sheets
7894
+
7895
+ ### Create a new spreadsheet
7896
+
7897
+ \`\`\`bash
7898
+ curl -s -X POST "$MONOLITH_URL/v1/gdrive/sheets" "\${GDRIVE_AUTH[@]}" \\
7899
+ -H "Content-Type: application/json" \\
7900
+ -d '{"title":"Q2 metrics"}'
7901
+ \`\`\`
7902
+
7903
+ Returns the full Spreadsheet object; grab \`.spreadsheetId\`.
7904
+
7905
+ ### Read a range of cells
7906
+
7907
+ \`\`\`bash
7908
+ # Range is in A1 notation, e.g. "Sheet1!A1:C10"
7909
+ curl -s "$MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/values/$(printf %s 'Sheet1!A1:C10' | jq -sRr @uri)" \\
7910
+ "\${GDRIVE_AUTH[@]}"
7911
+ \`\`\`
7912
+
7913
+ ### Write a range of cells
7914
+
7915
+ \`\`\`bash
7916
+ curl -s -X PUT \\
7917
+ "$MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/values/$(printf %s 'Sheet1!A1:B2' | jq -sRr @uri)?valueInputOption=USER_ENTERED" \\
7918
+ "\${GDRIVE_AUTH[@]}" \\
7919
+ -H "Content-Type: application/json" \\
7920
+ -d '{
7921
+ "range": "Sheet1!A1:B2",
7922
+ "majorDimension": "ROWS",
7923
+ "values": [
7924
+ ["Name", "Revenue"],
7925
+ ["Q1", "=SUM(B3:B100)"]
7926
+ ]
7927
+ }'
7928
+ \`\`\`
7929
+
7930
+ \`valueInputOption=USER_ENTERED\` makes formulas evaluate as if a human typed them. Use \`RAW\` to write literal strings.
7931
+
7932
+ ### Bulk operations (formatting, charts, new tabs, etc.)
7933
+
7934
+ \`\`\`bash
7935
+ curl -s -X POST "$MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
7936
+ -H "Content-Type: application/json" \\
7937
+ -d '{ "requests": [ { "addSheet": { "properties": { "title": "Raw data" } } } ] }'
7938
+ \`\`\`
7939
+
7940
+ \`batchUpdate\` accepts an array of [Sheets API requests](https://developers.google.com/workspace/sheets/api/reference/rest/v4/spreadsheets/request) \u2014 addSheet, updateSheetProperties, repeatCell, addChart, autoResizeDimensions, etc.
7941
+
7942
+ ## Google Forms
7943
+
7944
+ ### Create a new form
7945
+
7946
+ \`\`\`bash
7947
+ curl -s -X POST "$MONOLITH_URL/v1/gdrive/forms" "\${GDRIVE_AUTH[@]}" \\
7948
+ -H "Content-Type: application/json" \\
7949
+ -d '{"title":"Customer feedback"}'
7950
+ \`\`\`
7951
+
7952
+ Returns the form. Grab \`.formId\`.
7953
+
7954
+ ### Add questions / edit form structure
7955
+
7956
+ The Forms API uses its own \`batchUpdate\`:
7957
+
7958
+ \`\`\`bash
7959
+ curl -s -X POST "$MONOLITH_URL/v1/gdrive/forms/$FORM_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
7960
+ -H "Content-Type: application/json" \\
7961
+ -d '{
7962
+ "requests": [
7963
+ {
7964
+ "createItem": {
7965
+ "item": {
7966
+ "title": "How likely are you to recommend us?",
7967
+ "questionItem": {
7968
+ "question": {
7969
+ "required": true,
7970
+ "scaleQuestion": { "low": 0, "high": 10, "lowLabel": "Not at all", "highLabel": "Very likely" }
7971
+ }
7972
+ }
7973
+ },
7974
+ "location": { "index": 0 }
7975
+ }
7976
+ }
7977
+ ]
7978
+ }'
7979
+ \`\`\`
7980
+
7981
+ See the [Forms API Request reference](https://developers.google.com/workspace/forms/api/reference/rest/v1/forms/request) for all supported request types \u2014 text questions, multiple choice, checkboxes, scale, grid, date, time, file upload, section breaks, branching logic, quiz settings, etc.
7982
+
7983
+ ### Read responses
7984
+
7985
+ \`\`\`bash
7986
+ curl -s "$MONOLITH_URL/v1/gdrive/forms/$FORM_ID/responses" "\${GDRIVE_AUTH[@]}"
7987
+ \`\`\`
7988
+
7989
+ Pagination: pass \`?pageToken=...&pageSize=...\` to walk through responses.
7990
+
7991
+ ## Drive operations (only on Replicas-created files)
7992
+
7993
+ ### Share a file with a person
7994
+
7995
+ \`\`\`bash
7996
+ curl -s -X POST "$MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}" \\
7997
+ -H "Content-Type: application/json" \\
7998
+ -d '{
7999
+ "type": "user",
8000
+ "role": "writer",
8001
+ "emailAddress": "alice@example.com",
8002
+ "sendNotificationEmail": true
8003
+ }'
8004
+ \`\`\`
8005
+
8006
+ Roles: \`reader\`, \`commenter\`, \`writer\`. Types: \`user\`, \`group\`, \`domain\`, \`anyone\`.
8007
+
8008
+ ### Make a file viewable by anyone with the link
8009
+
8010
+ \`\`\`bash
8011
+ curl -s -X POST "$MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}" \\
8012
+ -H "Content-Type: application/json" \\
8013
+ -d '{ "type": "anyone", "role": "reader" }'
8014
+ \`\`\`
8015
+
8016
+ ### List existing permissions
8017
+
8018
+ \`\`\`bash
8019
+ curl -s "$MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}"
8020
+ \`\`\`
8021
+
8022
+ ### Rename / move a file
8023
+
8024
+ \`\`\`bash
8025
+ curl -s -X PATCH "$MONOLITH_URL/v1/gdrive/files/$FILE_ID" "\${GDRIVE_AUTH[@]}" \\
8026
+ -H "Content-Type: application/json" \\
8027
+ -d '{"name":"Final report.docx"}'
8028
+ \`\`\`
8029
+
8030
+ To move into a folder, also pass \`addParents\` and \`removeParents\` as query parameters per [Drive API docs](https://developers.google.com/workspace/drive/api/reference/rest/v3/files/update).
8031
+
8032
+ ### Get file metadata
8033
+
8034
+ \`\`\`bash
8035
+ curl -s "$MONOLITH_URL/v1/gdrive/files/$FILE_ID?fields=id,name,mimeType,webViewLink,parents,modifiedTime" \\
8036
+ "\${GDRIVE_AUTH[@]}"
8037
+ \`\`\`
8038
+
8039
+ \`webViewLink\` is the human-shareable URL that opens in Google Docs/Sheets/Forms.
8040
+
8041
+ ### Delete a file
8042
+
8043
+ \`\`\`bash
8044
+ curl -s -X DELETE "$MONOLITH_URL/v1/gdrive/files/$FILE_ID" "\${GDRIVE_AUTH[@]}"
8045
+ \`\`\`
8046
+
8047
+ ### List Replicas-created files
8048
+
8049
+ \`\`\`bash
8050
+ curl -s "$MONOLITH_URL/v1/gdrive/files?pageSize=50" "\${GDRIVE_AUTH[@]}"
8051
+ \`\`\`
8052
+
8053
+ Pass \`?q=...\` to filter using [Drive API search syntax](https://developers.google.com/workspace/drive/api/guides/search-files). Only files the app created or was granted access to will appear.
8054
+
8055
+ ## Tips
8056
+
8057
+ - **Always return the \`webViewLink\`** to the user when you create or edit a file so they can open it. Get it from \`/v1/gdrive/files/$FILE_ID?fields=webViewLink\` or from \`documents.documentId\` \u2192 \`https://docs.google.com/document/d/$ID/edit\`.
8058
+ - **Batch your edits.** A single \`batchUpdate\` with 20 requests beats 20 round-trips.
8059
+ - **Watch error responses.** A 412 from the gateway means the org has no Google credentials connected \u2014 tell the user to connect Google in the dashboard. Other 4xx responses come straight from Google and usually explain the issue clearly.
8060
+ `;
8061
+ var GOOGLE_ABILITY = {
8062
+ label: "Google Workspace",
8063
+ description: "Create / edit Docs, Sheets, Forms, and Drive files via the Replicas gateway.",
8064
+ bullet: "- Interacting with Google Workspace (creating and editing Docs, Sheets, and Forms, sharing files, reading form responses, etc.)",
8065
+ section: SECTION4,
8066
+ referenceFile: { name: "GOOGLE.md", content: REFERENCE4 }
8067
+ };
8068
+
8069
+ // ../shared/src/default-skills/replicas-agent/abilities/linear.ts
8070
+ var SECTION5 = `### Linear
8071
+ Fetch issues, update state, add comments, and search via the Linear GraphQL API.
8072
+
8073
+ **Reference:** \`references/LINEAR.md\`
8074
+
8075
+ Use this when:
8076
+ - You encounter a Linear issue link and need to understand the task
8077
+ - You need to update an issue's state (e.g. mark as done)
8078
+ - You need to comment on or search for Linear issues`;
8079
+ var REFERENCE5 = `# Linear Integration
8080
+
8081
+ This guide covers how to interact with Linear from within your Replicas workspace.
8082
+
8083
+ ## Prerequisites
8084
+
8085
+ Check if the \`LINEAR_ACCESS_TOKEN\` environment variable is set:
8086
+
8087
+ \`\`\`bash
8088
+ echo "\${LINEAR_ACCESS_TOKEN:+set}"
8089
+ \`\`\`
8090
+
8091
+ - If **set**: Your workspace has Linear access. You can use the Linear GraphQL API as described below.
8092
+ - If **not set**: Linear has not been configured for this workspace. The user needs to connect Linear in the [Replicas dashboard](https://replicas.dev) under their organization's integration settings. Let the user know and do not attempt Linear operations.
8093
+
8094
+ ## Using the Linear API
8095
+
8096
+ Linear uses a GraphQL API at \`https://api.linear.app/graphql\`. All requests use the \`$LINEAR_ACCESS_TOKEN\` for authentication.
8097
+
8098
+ ### Fetching an Issue
8099
+
8100
+ If you encounter a Linear issue link (e.g. \`https://linear.app/team/issue/ENG-123\`), the identifier is the last path segment (\`ENG-123\`).
8101
+
8102
+ \`\`\`bash
8103
+ curl -s -X POST https://api.linear.app/graphql \\
8104
+ -H "Authorization: Bearer $LINEAR_ACCESS_TOKEN" \\
8105
+ -H "Content-Type: application/json" \\
8106
+ -d '{
8107
+ "query": "query { issues(filter: { identifier: { eq: \\"ENG-123\\" } }) { nodes { id identifier title description state { name } assignee { name } parent { identifier title description } } } }"
8108
+ }'
8109
+ \`\`\`
8110
+
8111
+ ### Updating Issue State
8112
+
8113
+ \`\`\`bash
8114
+ curl -s -X POST https://api.linear.app/graphql \\
8115
+ -H "Authorization: Bearer $LINEAR_ACCESS_TOKEN" \\
8116
+ -H "Content-Type: application/json" \\
8117
+ -d '{
8118
+ "query": "mutation { issueUpdate(id: \\"ISSUE_UUID\\", input: { stateId: \\"STATE_UUID\\" }) { success issue { identifier state { name } } } }"
8119
+ }'
8120
+ \`\`\`
8121
+
8122
+ To find available states, query: \`query { workflowStates { nodes { id name } } }\`
8123
+
8124
+ ### Adding a Comment
8125
+
8126
+ \`\`\`bash
8127
+ curl -s -X POST https://api.linear.app/graphql \\
8128
+ -H "Authorization: Bearer $LINEAR_ACCESS_TOKEN" \\
8129
+ -H "Content-Type: application/json" \\
8130
+ -d '{
8131
+ "query": "mutation { commentCreate(input: { issueId: \\"ISSUE_UUID\\", body: \\"Your comment here\\" }) { success comment { id } } }"
8132
+ }'
8133
+ \`\`\`
8134
+
8135
+ ### Searching Issues
8136
+
8137
+ \`\`\`bash
8138
+ curl -s -X POST https://api.linear.app/graphql \\
8139
+ -H "Authorization: Bearer $LINEAR_ACCESS_TOKEN" \\
8140
+ -H "Content-Type: application/json" \\
8141
+ -d '{
8142
+ "query": "query { issueSearch(query: \\"search terms\\", first: 10) { nodes { identifier title state { name } } } }"
8143
+ }'
8144
+ \`\`\`
8145
+
8146
+ ### Other Operations
8147
+
8148
+ The Linear GraphQL API supports creating issues, managing projects, labels, cycles, and more. For the full schema and documentation, see: https://developers.linear.app/docs/graphql/working-with-the-graphql-api
8149
+ `;
8150
+ var LINEAR_ABILITY = {
8151
+ label: "Linear",
8152
+ description: "Fetch issues, post comments, update states via the Linear GraphQL API.",
8153
+ bullet: "- Interacting with Linear (fetching issues, updating state, commenting, etc.)",
8154
+ section: SECTION5,
8155
+ referenceFile: { name: "LINEAR.md", content: REFERENCE5 }
8156
+ };
8157
+
8158
+ // ../shared/src/default-skills/replicas-agent/abilities/media.ts
8159
+ var SECTION6 = `### Media
8160
+ Share screenshots, screen recordings, generated diagrams, and audio clips inline in the Replicas chat and natively embedded in external messages.
8161
+
8162
+ **Reference:** \`references/MEDIA.md\`
8163
+
8164
+ Use this when:
8165
+ - You produce a screenshot, recording, generated image, or audio clip the user should see
8166
+ - You record video output (browser automation, screen capture) \u2014 including the recommended aspect ratio and FPS
8167
+ - You need to embed media in a Slack/Linear/GitHub message AND keep a referenceable copy in the Replicas dashboard`;
8168
+ var REFERENCE6 = `# Media (Screenshots, Recordings, Audio)
8169
+
8170
+ This guide covers how to share screenshots, screen recordings, generated diagrams, and audio clips \u2014 both inline in the Replicas chat and natively embedded in external surfaces (Slack, Linear, GitHub).
8171
+
8172
+ ## Prerequisites
8173
+
8174
+ The \`replicas\` CLI is pre-installed and authenticated in your workspace. No additional setup is needed.
8175
+
8176
+ ## When to upload
8177
+
8178
+ Upload to Replicas in these cases \u2014 and **only** these cases:
8179
+
8180
+ 1. **Media you produce.** Any screenshot, screen recording, generated diagram, or audio clip you create that the user might want to see. Upload before doing anything else with the file (analyzing, deleting, sending elsewhere). This applies even when you're also sending the file to Slack, Linear, GitHub, etc.
8181
+ 2. **Files the user explicitly asks you to upload.** If the user sends or points at a file (image, video, audio) and asks you to upload it, run \`replicas media upload\`. Otherwise leave it alone \u2014 files in the workspace the user did not ask about should not be auto-uploaded as media.
8182
+ 3. **Anything you plan to share externally (Slack, Linear, GitHub, etc.).** Upload to Replicas *in addition to* the platform's native upload. Never as a replacement.
8183
+
8184
+ If none of these apply, don't upload.
8185
+
8186
+ ## Uploading to Replicas
8187
+
8188
+ \`\`\`bash
8189
+ replicas media upload <path-to-file> [<path-to-file> ...]
8190
+ \`\`\`
8191
+
8192
+ Pass one or more file paths. Uploading several files in a single invocation is preferred over running the command repeatedly \u2014 it's faster and keeps the output grouped.
8193
+
8194
+ For each file, the CLI prints two lines:
8195
+
8196
+ 1. \`![filename](<api-url>)\` \u2014 the chat embed (renders inline in Replicas chat **only** \u2014 see below).
8197
+ 2. \`View in Replicas: <deep-link>\` \u2014 a per-file dashboard URL of the form \`https://tryreplicas.com/workspaces/<workspace-id>?mode=media&media=<media-id>\` that opens directly to that specific file.
8198
+
8199
+ Match each "View in Replicas" line to the embed line directly above it \u2014 that's the deep link for that file.
8200
+
8201
+ ## The two URLs the CLI gives you \u2014 and where each one is allowed
8202
+
8203
+ | URL | What it is | Where it's allowed |
8204
+ |---|---|---|
8205
+ | \`https://api.tryreplicas.com/v1/media/<id>\` (inside \`![\u2026](\u2026)\`) | Authenticated API redirect to a presigned blob \u2014 requires the Replicas chat session | **Only** in the Replicas chat reply. Nowhere else. |
8206
+ | \`https://tryreplicas.com/workspaces/<workspace-id>?mode=media&media=<media-id>\` | Public dashboard deep link to the media tab, scrolled to that specific file | Everywhere external \u2014 Slack, GitHub, Linear, PR bodies, comments, emails. |
8207
+
8208
+ ### NEVER link the API redirect URL outside the Replicas chat reply
8209
+
8210
+ The \`api.tryreplicas.com/v1/media/<id>\` URL is **not public**. It's an authenticated redirect that only resolves to a presigned download when the Replicas chat session token is present. Anywhere else (Slack, Linear, GitHub, a browser tab the user opens directly, a customer copy-pasting from chat) it returns \`{"error":"Missing authorization token"}\` and renders as a broken image.
8211
+
8212
+ This rule has no exceptions:
8213
+ - \u274C Never paste it in a Slack message \u2014 upload the actual bytes via the 3-step \`files.getUploadURLExternal\` \u2192 POST bytes \u2192 \`files.completeUploadExternal\` flow instead (see below).
8214
+ - \u274C Never paste it in a GitHub PR description, issue body, review comment, or commit message.
8215
+ - \u274C Never paste it in a Linear issue body or comment \u2014 upload via Linear's \`fileUpload\` mutation instead (see below).
8216
+ - \u274C Never link to it from any external doc, email, or external chat.
8217
+ - \u274C Never include it as a "backup link" in case the dashboard link breaks \u2014 it will always break externally.
8218
+
8219
+ ### ALWAYS link the dashboard URL \u2014 never the API URL \u2014 when referencing media externally
8220
+
8221
+ When you reference an uploaded file from anywhere outside the Replicas chat reply, the link must be the dashboard form:
8222
+
8223
+ \`\`\`
8224
+ https://tryreplicas.com/workspaces/<workspace-id>?mode=media&media=<media-id>
8225
+ \`\`\`
8226
+
8227
+ Both query params are required:
8228
+ - \`mode=media\` opens the media tab in the dashboard.
8229
+ - \`media=<media-id>\` scrolls to and opens that specific file.
8230
+
8231
+ Never link \`tryreplicas.com/workspaces/<id>?mode=media\` without the \`media=<id>\` param when you have a specific file in mind \u2014 that lands on the gallery, not the file. Never link the bare workspace URL.
8232
+
8233
+ Always render as a markdown / mrkdwn hyperlink labeled **View in Replicas** \u2014 never paste a raw URL.
8234
+
8235
+ ## In your Replicas chat reply
8236
+
8237
+ Include each markdown embed line **verbatim** where you want that file to render inline. The chat substitutes each one with an embedded image, video, or audio player. Multiple embeds can appear in a single reply.
8238
+
8239
+ After (or alongside) the embeds, include a \`[View in Replicas](<deep-link>)\` hyperlink for each file using the per-file dashboard URL from the CLI. This lets the user jump to the specific item in the media tab.
8240
+
8241
+ ## On external platforms \u2014 upload natively AND link the dashboard
8242
+
8243
+ Sharing media externally is a **two-step requirement** for every file:
8244
+
8245
+ 1. **Upload the raw bytes natively to that platform** so the recipient sees the media embedded inline in the message itself.
8246
+ 2. **Link the Replicas dashboard deep link** (\`?mode=media&media=<id>\` form) so the user can jump straight to the workspace.
8247
+
8248
+ A link alone is not enough. A native upload alone is not enough. Do both.
8249
+
8250
+ The one exception is GitHub, which has no public image upload API \u2014 there, the dashboard link is the only option (see below).
8251
+
8252
+ ### Slack \u2014 embed natively via the 3-step external file upload flow
8253
+
8254
+ A Slack message that just contains a \`tryreplicas.com\` link is not acceptable when the message is supposed to show an image. The recipient should see the image inline in the thread.
8255
+
8256
+ Slack deprecated the single-shot \`files.upload\` endpoint. The raw HTTP replacement is a 3-step flow: reserve an upload URL with \`files.getUploadURLExternal\`, POST the bytes to it, then share into the channel/thread with \`files.completeUploadExternal\`. (\`files.uploadV2\` is **only** an SDK convenience wrapper \u2014 it is NOT a real Web API HTTP endpoint and \`POST https://slack.com/api/files.uploadV2\` will return \`unknown_method\`.)
8257
+
8258
+ \`\`\`bash
8259
+ FILE=/abs/path/to/screenshot.png
8260
+ FILENAME=$(basename "$FILE")
8261
+ LENGTH=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
8262
+
8263
+ # 1. Reserve an upload URL + file ID.
8264
+ RESERVE=$(curl -s -G "https://slack.com/api/files.getUploadURLExternal" \\
8265
+ -H "Authorization: Bearer $SLACK_BOT_TOKEN" \\
8266
+ --data-urlencode "filename=$FILENAME" \\
8267
+ --data-urlencode "length=$LENGTH")
8268
+ UPLOAD_URL=$(echo "$RESERVE" | jq -r '.upload_url')
8269
+ FILE_ID=$(echo "$RESERVE" | jq -r '.file_id')
8270
+
8271
+ # 2. POST the raw bytes to the reserved URL.
8272
+ # Do not use -F / multipart here \u2014 the presigned URL expects the bytes
8273
+ # directly in the request body.
8274
+ curl -s -X POST "$UPLOAD_URL" \\
8275
+ -H "Content-Type: application/octet-stream" \\
8276
+ --data-binary @"$FILE"
8277
+
8278
+ # 3. Complete the upload, sharing it into the channel/thread with the dashboard link.
8279
+ curl -s -X POST "https://slack.com/api/files.completeUploadExternal" \\
8280
+ -H "Authorization: Bearer $SLACK_BOT_TOKEN" \\
8281
+ -H "Content-Type: application/json; charset=utf-8" \\
8282
+ -d "{
8283
+ \\"files\\": [{\\"id\\": \\"$FILE_ID\\", \\"title\\": \\"Screenshot\\"}],
8284
+ \\"channel_id\\": \\"CHANNEL_ID\\",
8285
+ \\"thread_ts\\": \\"THREAD_TS\\",
8286
+ \\"initial_comment\\": \\"<https://tryreplicas.com/workspaces/<workspace-id>?mode=media&media=<media-id>|View in Replicas>\\"
8287
+ }"
8288
+ \`\`\`
8289
+
8290
+ Notes:
8291
+ - All three steps are required; do not try to POST to \`https://slack.com/api/files.uploadV2\` \u2014 that endpoint does not exist on the Web API.
8292
+ - \`initial_comment\` uses Slack mrkdwn (\`<url|label>\`), not GitHub-flavored markdown.
8293
+ - Omit \`thread_ts\` only when you genuinely want a top-level channel post.
8294
+ - For multiple files in the same message, run steps 1\u20132 per file and pass all \`{id, title}\` objects in the \`files\` array of a single \`files.completeUploadExternal\` call \u2014 they share into the thread together.
8295
+ - If you also need to post a separate text reply in the thread, send it with \`chat.postMessage\` after the upload \u2014 but the upload itself must carry the image.
8296
+
8297
+ Never paste the \`api.tryreplicas.com/v1/media/<id>\` URL into a Slack message body or \`initial_comment\` \u2014 it will render as a broken image attempt.
8298
+
8299
+ ### Linear \u2014 embed natively via the GraphQL \`fileUpload\` mutation
8300
+
8301
+ Linear comments and issue bodies support markdown image embeds, but the image URL must be publicly accessible \u2014 so you upload the file to Linear's storage first, then reference the returned \`assetUrl\` in markdown. Three steps:
8302
+
8303
+ Use \`jq\` to build the JSON bodies \u2014 the GraphQL variables (\`size\`, \`filename\`, the comment body) need to be real JSON values, not unquoted placeholders, and \`jq -n --argjson / --arg\` is the safest way to interpolate shell values without quoting bugs.
8304
+
8305
+ \`\`\`bash
8306
+ FILE=/abs/path/to/screenshot.png
8307
+ FILENAME=$(basename "$FILE")
8308
+ SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
8309
+ CONTENT_TYPE=image/png
8310
+ ISSUE_UUID=... # the Linear issue's UUID
8311
+ WORKSPACE_ID=... # the Replicas workspace ID
8312
+ MEDIA_ID=... # the media ID printed by \`replicas media upload\`
8313
+
8314
+ # 1. Ask Linear for an upload URL + assetUrl.
8315
+ RESERVE=$(curl -s -X POST https://api.linear.app/graphql \\
8316
+ -H "Authorization: Bearer $LINEAR_ACCESS_TOKEN" \\
8317
+ -H "Content-Type: application/json" \\
8318
+ -d "$(jq -n \\
8319
+ --argjson size "$SIZE" \\
8320
+ --arg contentType "$CONTENT_TYPE" \\
8321
+ --arg filename "$FILENAME" \\
8322
+ '{
8323
+ query: "mutation($size: Int!, $contentType: String!, $filename: String!) { fileUpload(size: $size, contentType: $contentType, filename: $filename) { uploadFile { uploadUrl assetUrl headers { key value } } } }",
8324
+ variables: { size: $size, contentType: $contentType, filename: $filename }
8325
+ }')")
8326
+ UPLOAD_URL=$(echo "$RESERVE" | jq -r '.data.fileUpload.uploadFile.uploadUrl')
8327
+ ASSET_URL=$(echo "$RESERVE" | jq -r '.data.fileUpload.uploadFile.assetUrl')
8328
+
8329
+ # 2. PUT the bytes to uploadUrl, replaying every header Linear returned.
8330
+ # Linear's presigned URL requires the exact Content-Type / Cache-Control /
8331
+ # etc. it gave you back, so forward each {key, value} from the headers array.
8332
+ HEADER_ARGS=()
8333
+ while IFS=$'\\t' read -r k v; do
8334
+ HEADER_ARGS+=(-H "$k: $v")
8335
+ done < <(echo "$RESERVE" | jq -r '.data.fileUpload.uploadFile.headers[] | "\\(.key)\\t\\(.value)"')
8336
+
8337
+ curl -s -X PUT "$UPLOAD_URL" \\
8338
+ "\${HEADER_ARGS[@]}" \\
8339
+ --data-binary @"$FILE"
8340
+
8341
+ # 3. Reference assetUrl inline in the comment body, alongside the dashboard link.
8342
+ BODY=$(printf '![screenshot](%s)\\n\\n[View in Replicas](https://tryreplicas.com/workspaces/%s?mode=media&media=%s)' \\
8343
+ "$ASSET_URL" "$WORKSPACE_ID" "$MEDIA_ID")
8344
+
8345
+ curl -s -X POST https://api.linear.app/graphql \\
8346
+ -H "Authorization: Bearer $LINEAR_ACCESS_TOKEN" \\
8347
+ -H "Content-Type: application/json" \\
8348
+ -d "$(jq -n \\
8349
+ --arg issueId "$ISSUE_UUID" \\
8350
+ --arg body "$BODY" \\
8351
+ '{
8352
+ query: "mutation($issueId: String!, $body: String!) { commentCreate(input: { issueId: $issueId, body: $body }) { success } }",
8353
+ variables: { issueId: $issueId, body: $body }
8354
+ }')"
8355
+ \`\`\`
8356
+
8357
+ The same flow works for issue bodies (use \`issueCreate\` / \`issueUpdate\` with the same markdown body).
8358
+
8359
+ Never paste the \`api.tryreplicas.com/v1/media/<id>\` URL into a Linear body or comment \u2014 it will render as a broken image to anyone outside your Replicas chat.
8360
+
8361
+ ### GitHub \u2014 link the dashboard deep link (no public upload API exists)
8362
+
8363
+ GitHub has **no public API** for uploading images to PRs or issues. Their web UI uses an undocumented internal endpoint that's not available to API clients. So for GitHub specifically, the only correct way to share media is the dashboard deep link, rendered as a markdown hyperlink:
8364
+
8365
+ \`\`\`markdown
8366
+ [View in Replicas](https://tryreplicas.com/workspaces/<workspace-id>?mode=media&media=<media-id>)
8367
+ \`\`\`
8368
+
8369
+ Do **not**:
8370
+ - Commit screenshots as files to the repo as a workaround.
8371
+ - Use placeholder image URLs.
8372
+ - Embed the \`api.tryreplicas.com/v1/media/<id>\` URL in markdown \u2014 it renders as a broken image for every viewer.
8373
+
8374
+ This applies to PR descriptions, PR review comments, issue bodies, issue comments, and commit messages.
8375
+
8376
+ ## Recording defaults
8377
+
8378
+ When you record video (browser automation, screen capture, etc.):
8379
+
8380
+ - **Aspect ratio:** 16:9 (1920\xD71080 or 1280\xD7720)
8381
+ - **Frame rate:** 60 FPS or whatever the user specifies
8382
+
8383
+ Tools like Playwright default to a low frame rate that produces choppy playback \u2014 explicitly configure recording dimensions and FPS:
8384
+
8385
+ \`\`\`ts
8386
+ const context = await browser.newContext({
8387
+ recordVideo: { dir: './videos', size: { width: 1280, height: 720 } },
8388
+ });
8389
+ \`\`\`
8390
+
8391
+ For \`ffmpeg\` screen captures, pass \`-r 30\` (or \`-r 60\`) to set the frame rate.
8392
+
8393
+ ## Supported formats
8394
+
8395
+ Auto-detected from the filename extension:
8396
+
8397
+ | Extension | Kind |
8398
+ |---|---|
8399
+ | \`png\`, \`jpg\`, \`jpeg\`, \`webp\` | image |
8400
+ | \`mp4\`, \`webm\` | video |
8401
+ | \`mp3\`, \`wav\` | audio |
8402
+
8403
+ For other extensions, pass \`--kind image|video|audio\` explicitly. The kind applies to every file in that invocation, so group files of the same kind together:
8404
+
8405
+ \`\`\`bash
8406
+ replicas media upload diagram.svg --kind image
8407
+ replicas media upload chart-a.svg chart-b.svg --kind image
8408
+ \`\`\`
8409
+
8410
+ ## Options
8411
+
8412
+ - \`--kind <image|video|audio>\` \u2014 override auto-detection
8413
+ - \`--session-id <id>\` \u2014 associate the upload with a specific session
8414
+ `;
8415
+ var MEDIA_ABILITY = {
8416
+ label: "Media",
8417
+ description: "Share screenshots, recordings, generated images, and audio clips.",
8418
+ bullet: "- Producing or showing the user any media \u2014 screenshots, screen recordings, generated images or diagrams, audio clips \u2014 including in your Replicas chat reply, PR descriptions/comments, and other external platforms",
8419
+ section: SECTION6,
8420
+ referenceFile: { name: "MEDIA.md", content: REFERENCE6 }
8421
+ };
8422
+
8423
+ // ../shared/src/default-skills/replicas-agent/abilities/previews.ts
8424
+ var SECTION7 = `### Previews
8425
+ Expose locally running services (web apps, APIs, databases) as public preview URLs so humans can interact with them directly.
8426
+
8427
+ **Reference:** \`references/PREVIEWS.md\`
8428
+
8429
+ Use this when:
8430
+ - You need to start a service that a human should view or interact with
8431
+ - The task involves UI work that benefits from human review
8432
+ - You are verifying frontend/backend integrations visually`;
8433
+ var REFERENCE7 = `# Preview URLs
8434
+
8435
+ When you run services on ports \u2014 such as a web app, API server, or database \u2014 humans may want to interact with them directly. You can expose your locally running services as public preview URLs.
8436
+
8437
+ ## Running Services for Preview
8438
+
8439
+ Services must run as detached background processes so they survive after your command session ends. Do not leave them attached to a foreground terminal.
8440
+
8441
+ Some potential methods:
8442
+ \`\`\`bash
8443
+ # Start a detached service with logging
8444
+ setsid -f bash -lc 'cd /path/to/app && exec yarn dev >> /tmp/app.log 2>&1'
8445
+
8446
+ # For daemons like Docker
8447
+ nohup dockerd > /tmp/dockerd.log 2>&1 &
8448
+ \`\`\`
8449
+
8450
+ After starting a service:
8451
+ 1. Verify the process is running: \`pgrep -af 'yarn dev'\`
8452
+ 2. Check logs for readiness: \`tail -f /tmp/app.log\`
8453
+ 3. Confirm it's actually serving: \`curl -s http://localhost:3000\` (or appropriate health check)
8454
+ 4. Only create the preview after the service is healthy
8455
+
8456
+ If a prior detached process exists on the same port, stop it before restarting.
8457
+
8458
+ ## Creating Previews
8459
+
8460
+ \`\`\`bash
8461
+ # Expose a local port as a public URL
8462
+ replicas preview create <port>
8463
+
8464
+ # Expose a port with authentication (requires Replicas login to access)
8465
+ replicas preview create <port> --authenticated
8466
+
8467
+ # List all active preview URLs
8468
+ replicas preview list
8469
+ \`\`\`
8470
+
8471
+ The \`create\` command prints the public URL. You can also read all active previews from \`~/.replicas/preview-ports.json\`.
8472
+
8473
+ ## Authenticated vs Unauthenticated Previews
8474
+
8475
+ Previews can optionally require cookie-based authentication. When \`--authenticated\` is set, only users who are logged in to replicas.dev can access the preview.
8476
+
8477
+ **When to use \`--authenticated\`:**
8478
+ - Frontends / web apps that humans will view directly in their browser. Since the user is already logged in to replicas.dev, the auth cookie is automatically present and the preview works seamlessly.
8479
+
8480
+ **When NOT to use \`--authenticated\`:**
8481
+ - Backend APIs and other services that are called by frontend code. The frontend runs in the user's browser under a different origin, so it cannot forward the Replicas auth cookie to the backend. Making backends authenticated will cause cross-service requests to fail with 401 errors.
8482
+
8483
+ **Rule of thumb:** Make frontend previews authenticated, leave backend/API previews unauthenticated.
8484
+
8485
+ ## Cross-Service References
8486
+
8487
+ When you expose multiple services that reference each other, you must update their configuration so they use preview URLs instead of \`localhost\`.
8488
+
8489
+ **Example:** You run a React frontend on port 3000 that makes API calls to a backend on port 8585.
8490
+
8491
+ 1. Create previews for both:
8492
+ \`\`\`bash
8493
+ replicas preview create 8585
8494
+ # Output: https://8585-<hash>.replicas.dev
8495
+ replicas preview create 3000 --authenticated
8496
+ # Output: https://3000-<hash>.replicas.dev
8497
+ \`\`\`
8498
+
8499
+ 2. Update the frontend's environment so its API base URL points to the backend's **preview URL**, not \`localhost:8585\`. For example, set \`REACT_APP_API_URL=https://8585-<hash>.replicas.dev\` or update the relevant config file.
8500
+
8501
+ **Why?** The frontend works on \`localhost\` for you because both services run on the same machine. But a human viewing the preview is on a different machine \u2014 requests to \`localhost:8585\` from their browser will fail. They need the public preview URL instead.
8502
+
8503
+ ## When to Create Previews
8504
+
8505
+ - After starting any service that a human should be able to view or interact with
8506
+ - When verifying frontend/backend integrations visually
8507
+ - When the task involves UI work that benefits from human review
8508
+
8509
+ It is your responsibility to make previews work for outsiders as well as they work for you on localhost. If at any time you need to see the public URLs that have been created, read \`~/.replicas/preview-ports.json\`.
8510
+ `;
8511
+ var PREVIEWS_ABILITY = {
8512
+ label: "Previews",
8513
+ description: "Expose locally running services on public preview URLs for humans.",
8514
+ bullet: "- Creating preview URLs for locally running services",
8515
+ section: SECTION7,
8516
+ referenceFile: { name: "PREVIEWS.md", content: REFERENCE7 }
8517
+ };
8518
+
8519
+ // ../shared/src/default-skills/replicas-agent/abilities/replicas.ts
8520
+ var SECTION8 = `### Replicas (in-workspace CLI)
8521
+ Take action *with* Replicas itself \u2014 manage automations, environments (variables, files), repos, and \`replicas.json\` config \u2014 using the pre-installed, pre-authenticated \`replicas\` CLI.
8522
+
8523
+ **Reference:** \`references/REPLICAS.md\`
8524
+
8525
+ Use this when:
8526
+ - The user asks you to create, edit, run, or delete an automation
8527
+ - The user asks you to manage environments, environment variables, or environment files
8528
+ - The user asks "what envs / repos / automations do I have?"
8529
+ - The user asks you to scaffold a \`replicas.json\` / \`replicas.yaml\` in a repo`;
8530
+ var REFERENCE8 = `# Replicas (in-workspace CLI)
8531
+
8532
+ This guide covers how to take action *with* Replicas itself from inside a Replicas workspace \u2014 managing automations, environments (and their variables/files), repos, previews, and the user's \`replicas.json\` config \u2014 using the pre-installed \`replicas\` CLI.
8533
+
8534
+ When the user asks _about_ Replicas (concepts, pricing, how a feature works), check https://docs.replicas.dev first. When the user asks you to _do_ something in their Replicas org, this is the file to use.
8535
+
8536
+ ## Prerequisites
8537
+
8538
+ The CLI is pre-installed in every workspace and pre-authenticated using the workspace's engine secret. You do **not** need to log in or set an API key. Verify:
8539
+
8540
+ \`\`\`bash
8541
+ replicas whoami
8542
+ \`\`\`
8543
+
8544
+ Expected output (in agent mode):
8545
+
8546
+ \`\`\`
8547
+ Workspace identity:
8548
+ Workspace ID: <uuid>
8549
+ Organization ID: <uuid>
8550
+ \`\`\`
8551
+
8552
+ If you get "Not logged in", the workspace is misconfigured \u2014 surface this to the user instead of trying to work around it.
8553
+
8554
+ In agent mode the CLI hides commands that don't make sense for in-workspace agents (\`login\`, \`logout\`, \`codex-auth\`, \`claude-auth\`, \`org switch\`, \`config\`, \`interact\`, \`code\`, replica/workspace top-level CRUD). What you have is:
8555
+
8556
+ | Command | What it does |
8557
+ | --- | --- |
8558
+ | \`replicas whoami\` | Print the workspace + org identity |
8559
+ | \`replicas init\` | Create a \`replicas.json\` / \`replicas.yaml\` in the current directory |
8560
+ | \`replicas connect <name>\` | SSH into another workspace (requires user creds \u2014 usually only useful when scripting locally) |
8561
+ | \`replicas repos\` | List repos connected to the org |
8562
+ | \`replicas environment ...\` | Manage environments, env vars, env files |
8563
+ | \`replicas automation ...\` | Manage automations (cron + GitHub event triggers) |
8564
+ | \`replicas preview ...\` | Register / list preview URLs (covered in \`PREVIEWS.md\`) |
8565
+ | \`replicas media ...\` | Upload screenshots, videos, audio (covered in \`MEDIA.md\`) |
8566
+
8567
+ \`replicas <command> --help\` is always the source of truth for flags.
8568
+
8569
+ ## Picking the right command for the user's request
8570
+
8571
+ | User says... | Run |
8572
+ | --- | --- |
8573
+ | "What environments do I have?" | \`replicas environment list\` |
8574
+ | "Add API key X to my staging env" | \`replicas environment vars set <env> <KEY> <VALUE>\` |
8575
+ | "Make me a \`.env\` file in the workspace with these vars" | \`replicas environment files set <env> .env --content "..."\` |
8576
+ | "Create a new env for my \`acme/web\` repo" | \`replicas environment create <name> -r acme/web\` |
8577
+ | "What automations do I have?" | \`replicas automation list\` |
8578
+ | "Run my nightly automation now" | \`replicas automation run <id>\` |
8579
+ | "Make an automation that runs every weekday at 9am" | \`replicas automation create\` (interactive) or \`--trigger-cron "0 9 * * 1-5"\` |
8580
+ | "Make an automation that runs when a PR opens on \`acme/web\`" | \`replicas automation create ... --trigger-github pull_request.opened --trigger-github-repos acme/web\` |
8581
+ | "What repos are connected?" | \`replicas repos\` |
8582
+ | "Set up a \`replicas.json\` in this repo" | \`replicas init\` (\`-y\` for YAML) |
8583
+
8584
+ ## Environments
8585
+
8586
+ Environments are the org-scoped *primitives* workspaces are built from. Each environment can bind to one repository (or repository set), carry environment variables, project files, enabled skills, and MCP servers. The \`Global\` environment is special \u2014 its vars/files/skills/MCPs apply to *every* workspace in the org, but it has no repo binding and can't back a workspace on its own.
8587
+
8588
+ ### List / get / create / edit / delete
8589
+
8590
+ \`\`\`bash
8591
+ replicas environment list
8592
+ replicas environment get <id-or-name> # use "global" for the Global env
8593
+ replicas environment create [name] \\
8594
+ --description "..." \\
8595
+ --repository <repo-name-or-id> \\
8596
+ --system-prompt "..."
8597
+ replicas environment edit <id-or-name> \\
8598
+ --name "..." --description "..." \\
8599
+ --repository <repo-name-or-id> # pass empty string to unbind
8600
+ replicas environment delete <id-or-name> [--force]
8601
+ \`\`\`
8602
+
8603
+ Notes:
8604
+ - Environments resolve by **name or UUID**. \`global\` is an alias for the org's Global env.
8605
+ - Non-global envs need a repo (or repo set) to back a workspace. If you \`create\` without \`--repository\`, the CLI prompts; in non-interactive contexts pass \`-r\`.
8606
+ - \`edit\` on the Global env is rejected by the API \u2014 manage its contents through the \`vars\` / \`files\` subcommands instead.
8607
+
8608
+ ### Environment variables
8609
+
8610
+ \`\`\`bash
8611
+ replicas environment vars list <env>
8612
+ replicas environment vars set <env> <KEY> <VALUE> # upsert (create or update)
8613
+ replicas environment vars delete <env> <KEY|VARIABLE_ID> [--force]
8614
+ \`\`\`
8615
+
8616
+ \`vars set\` is upsert: if a variable with that key already exists, it's updated; otherwise created. The CLI accepts either the variable's \`key\` or its UUID for \`delete\`.
8617
+
8618
+ These variables are injected into every workspace built from this environment as actual \`env\` vars \u2014 perfect for API keys, feature flags, etc. Anything you want available to the agent's tools (Claude, codex, your code, etc.) goes here.
8619
+
8620
+ ### Environment files
8621
+
8622
+ Files materialize on the workspace filesystem when a workspace starts, at the destination path you specify. Use this for things like \`.env\` files at the repo root, dotfiles in \`~\`, prompt files for agents, etc.
8623
+
8624
+ \`\`\`bash
8625
+ replicas environment files list <env>
8626
+ replicas environment files set <env> <destination-path> --content "..." # inline
8627
+ replicas environment files set <env> <destination-path> --file <local-path> # from local file
8628
+ replicas environment files set <env> <destination-path> --file <local-path> --name "Friendly name"
8629
+ replicas environment files delete <env> <destination-path|FILE_ID> [--force]
8630
+ \`\`\`
8631
+
8632
+ Constraints:
8633
+ - Each file is capped at 64KB.
8634
+ - \`set\` is upsert (matched by destination path).
8635
+ - The display \`--name\` defaults to the basename of the destination path; override only if it would be unclear in the dashboard list.
8636
+
8637
+ ## Automations
8638
+
8639
+ Automations are saved prompts with one or more triggers (cron schedules and/or GitHub events). When fired, they create a workspace using the configured environment and run the prompt with the user's coding agent.
8640
+
8641
+ ### List / get / run / delete
8642
+
8643
+ \`\`\`bash
8644
+ replicas automation list
8645
+ replicas automation get <id>
8646
+ replicas automation run <id> # cron-triggered automations only
8647
+ replicas automation delete <id> [--force]
8648
+ \`\`\`
8649
+
8650
+ ### Create
8651
+
8652
+ Either fully flag-driven or fully interactive \u2014 the CLI prompts for anything you don't pass.
8653
+
8654
+ \`\`\`bash
8655
+ # Cron trigger
8656
+ replicas automation create "Nightly typecheck" \\
8657
+ --prompt "Run \\\`bun typecheck\\\` and report any new errors" \\
8658
+ --environment <env-name-or-id> \\
8659
+ --trigger-cron "0 4 * * *" \\
8660
+ --trigger-cron-timezone "America/New_York"
8661
+
8662
+ # GitHub trigger (filter to specific repos)
8663
+ replicas automation create "Review my PRs" \\
8664
+ --prompt "Leave a code review on this PR" \\
8665
+ --environment <env-name-or-id> \\
8666
+ --trigger-github pull_request.opened \\
8667
+ --trigger-github-repos acme/web,acme/api
8668
+
8669
+ # Disable on creation
8670
+ replicas automation create ... --disabled
8671
+
8672
+ # Workspace lifecycle
8673
+ replicas automation create ... --lifecycle delete_when_done
8674
+ replicas automation create ... --lifecycle delete_after_inactivity --auto-stop-minutes 30
8675
+ \`\`\`
8676
+
8677
+ When the user says "make me an automation that...", default to **picking the environment for them by listing the available envs** and asking only when the user hasn't already pinned one. Same for repos in GitHub triggers. Don't pepper the user with questions you can answer by reading the existing config.
8678
+
8679
+ ### Edit
8680
+
8681
+ \`\`\`bash
8682
+ replicas automation edit <id> \\
8683
+ --name "..." \\
8684
+ --prompt "..." \\
8685
+ --enabled true|false \\
8686
+ --environment <env-name-or-id> \\
8687
+ --trigger-cron "0 4 * * *" # replaces existing triggers
8688
+ \`\`\`
8689
+
8690
+ \`replicas automation edit <id>\` with no flags drops into interactive mode.
8691
+
8692
+ ## Repositories
8693
+
8694
+ Read-only listing of repos connected to the org. Use when the user asks "what repos can I use?", or to validate a \`--repository\` value before passing it to \`environment create\` / \`automation create\`:
8695
+
8696
+ \`\`\`bash
8697
+ replicas repos
8698
+ \`\`\`
8699
+
8700
+ Repos are connected via the GitHub integration in the dashboard \u2014 not from the CLI. If the user wants a repo connected, point them at the dashboard rather than trying to do it yourself.
8701
+
8702
+ ## \`replicas.json\` / \`replicas.yaml\`
8703
+
8704
+ \`replicas init\` creates a starter config in the current directory. \`-y\` writes YAML, \`-f\` overwrites an existing file. This file controls per-repo workspace setup (warm hooks, start hooks, organization scoping for GitHub triggers). When the user asks to "set up Replicas in this repo", run \`replicas init\` and then edit the generated file based on what they need.
8705
+
8706
+ ## When NOT to use the CLI
8707
+
8708
+ - **Don't use the CLI to reach into other tools' state** (Linear, Slack, GitHub) \u2014 those have dedicated skill references in this directory.
8709
+ - **Don't try to install Replicas, log in, or switch orgs** \u2014 those flows are user-facing and aren't available in agent mode anyway.
8710
+ - **Don't create workspaces** from inside an existing workspace just to run a command. You're already in one.
8711
+
8712
+ ## Common errors
8713
+
8714
+ - \`Missing Replicas-Org-Id header\` \u2192 the workspace is hitting an older monolith that doesn't yet recognize agent auth on this endpoint. Surface this to the user; don't try to work around it by faking headers.
8715
+ - \`Workspace not found\` \u2192 the workspace was deleted while you were running. Stop and tell the user.
8716
+ - \`An environment with this name already exists\` \u2192 use \`environment edit\` instead, or pick a different name.
8717
+ - \`Cannot delete the global environment\` \u2192 there is exactly one Global env per org and it's permanent. Manage its *contents* (\`vars\`, \`files\`) instead.
8718
+ `;
8719
+ var REPLICAS_ABILITY = {
8720
+ label: "Replicas",
8721
+ description: "Teach the agent about Replicas itself \u2014 automations, environments, the in-workspace CLI.",
8722
+ // No bullet — help_instructions covers the `replicas` CLI surface in detail.
8723
+ bullet: "",
8724
+ section: SECTION8,
8725
+ referenceFile: { name: "REPLICAS.md", content: REFERENCE8 },
8726
+ locked: true
8727
+ };
8728
+
8729
+ // ../shared/src/default-skills/replicas-agent/abilities/slack.ts
8730
+ var SECTION9 = `### Slack
8731
+ Send messages, read threads, search conversations, and upload files via the Slack Web API.
8732
+
8733
+ **Reference:** \`references/SLACK.md\`
8734
+
8735
+ Use this when:
8736
+ - You need to send a message to a Slack channel or thread
8737
+ - You need to read or fetch a Slack conversation
8738
+ - You encounter a Slack message link and need to retrieve its content
8739
+ - The task asks you to notify, update, or communicate via Slack`;
8740
+ var REFERENCE9 = `# Slack Integration
8741
+
8742
+ This guide covers how to interact with Slack from within your Replicas workspace.
8743
+
8744
+ ## Prerequisites
8745
+
8746
+ Check if the \`SLACK_BOT_TOKEN\` environment variable is set:
8747
+
8748
+ \`\`\`bash
8749
+ echo "\${SLACK_BOT_TOKEN:+set}"
8750
+ \`\`\`
8751
+
8752
+ - If **set**: Your workspace has Slack access. You can use the Slack Web API as described below.
8753
+ - If **not set**: Slack has not been configured for this workspace. The user needs to connect Slack in the [Replicas dashboard](https://replicas.dev) under their organization's integration settings. Let the user know and do not attempt Slack operations.
8754
+
8755
+ ## Using the Slack API
8756
+
8757
+ All requests use the \`$SLACK_BOT_TOKEN\` for authentication via the Slack Web API.
8758
+
8759
+ ### Fetching a Thread from a Slack Link
8760
+
8761
+ If you encounter a Slack message link (e.g. \`https://team.slack.com/archives/C0123ABC/p1234567890123456\`), extract the channel ID and thread timestamp:
8762
+
8763
+ - **Channel ID**: The segment after \`/archives/\` (e.g. \`C0123ABC\`)
8764
+ - **Thread TS**: The \`p\` value with a dot inserted before the last 6 digits (e.g. \`p1234567890123456\` -> \`1234567890.123456\`)
8765
+
8766
+ \`\`\`bash
8767
+ curl -s "https://slack.com/api/conversations.replies?channel=CHANNEL_ID&ts=THREAD_TS" \\
8768
+ -H "Authorization: Bearer $SLACK_BOT_TOKEN"
8769
+ \`\`\`
8770
+
8771
+ ### Sending a Message
8772
+
8773
+ \`\`\`bash
8774
+ curl -s -X POST "https://slack.com/api/chat.postMessage" \\
8775
+ -H "Authorization: Bearer $SLACK_BOT_TOKEN" \\
8776
+ -H "Content-Type: application/json" \\
8777
+ -d '{
8778
+ "channel": "CHANNEL_ID",
8779
+ "text": "Your message here",
8780
+ "thread_ts": "OPTIONAL_THREAD_TS"
8781
+ }'
8782
+ \`\`\`
8783
+
8784
+ Omit \`thread_ts\` to post a new message to the channel. Include it to reply in a thread.
8785
+
8786
+ ### Searching Messages
8787
+
8788
+ \`\`\`bash
8789
+ curl -s "https://slack.com/api/search.messages?query=YOUR_SEARCH_QUERY" \\
8790
+ -H "Authorization: Bearer $SLACK_BOT_TOKEN"
8791
+ \`\`\`
8792
+
8793
+ ### Uploading Files
8794
+
8795
+ Slack deprecated \`files.upload\`; the raw HTTP replacement is a 3-step flow. (\`files.uploadV2\` is **only** an SDK convenience wrapper and is NOT a real Web API HTTP endpoint \u2014 \`POST https://slack.com/api/files.uploadV2\` returns \`unknown_method\`.)
8796
+
8797
+ \`\`\`bash
8798
+ FILE=/path/to/file
8799
+ FILENAME=$(basename "$FILE")
8800
+ LENGTH=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
8801
+
8802
+ # 1. Reserve an upload URL + file ID.
8803
+ RESERVE=$(curl -s -G "https://slack.com/api/files.getUploadURLExternal" \\
8804
+ -H "Authorization: Bearer $SLACK_BOT_TOKEN" \\
8805
+ --data-urlencode "filename=$FILENAME" \\
8806
+ --data-urlencode "length=$LENGTH")
8807
+ UPLOAD_URL=$(echo "$RESERVE" | jq -r '.upload_url')
8808
+ FILE_ID=$(echo "$RESERVE" | jq -r '.file_id')
8809
+
8810
+ # 2. POST the raw bytes to the reserved URL.
8811
+ # Do not use -F / multipart here \u2014 the presigned URL expects the bytes
8812
+ # directly in the request body.
8813
+ curl -s -X POST "$UPLOAD_URL" \\
8814
+ -H "Content-Type: application/octet-stream" \\
8815
+ --data-binary @"$FILE"
8816
+
8817
+ # 3. Complete the upload and share into a channel (and optionally a thread).
8818
+ curl -s -X POST "https://slack.com/api/files.completeUploadExternal" \\
8819
+ -H "Authorization: Bearer $SLACK_BOT_TOKEN" \\
8820
+ -H "Content-Type: application/json; charset=utf-8" \\
8821
+ -d "{
8822
+ \\"files\\": [{\\"id\\": \\"$FILE_ID\\", \\"title\\": \\"File title\\"}],
8823
+ \\"channel_id\\": \\"CHANNEL_ID\\",
8824
+ \\"thread_ts\\": \\"OPTIONAL_THREAD_TS\\",
8825
+ \\"initial_comment\\": \\"Optional message body\\"
8826
+ }"
8827
+ \`\`\`
8828
+
8829
+ Omit \`thread_ts\` and/or \`initial_comment\` if you don't need them.
8830
+
8831
+ ### Other Operations
8832
+
8833
+ You can list channels, read channel history, add reactions, and perform any other operation supported by the Slack Web API using the same authentication pattern.
8834
+
8835
+ For full API documentation, see: https://docs.slack.dev/apis/web-api/
8836
+ `;
8837
+ var SLACK_ABILITY = {
8838
+ label: "Slack",
8839
+ description: "Send messages, read threads, search conversations, upload files.",
8840
+ bullet: "- Interacting with Slack (sending messages, reading threads, etc.)",
8841
+ section: SECTION9,
8842
+ referenceFile: { name: "SLACK.md", content: REFERENCE9 }
8843
+ };
8844
+
8845
+ // ../shared/src/default-skills/replicas-agent/registry.ts
8846
+ var REPLICAS_AGENT_ABILITY_REGISTRY = {
8847
+ replicas: REPLICAS_ABILITY,
8848
+ computer: COMPUTER_ABILITY,
8849
+ docker: DOCKER_ABILITY,
8850
+ github: GITHUB_ABILITY,
8851
+ google: GOOGLE_ABILITY,
8852
+ linear: LINEAR_ABILITY,
8853
+ media: MEDIA_ABILITY,
8854
+ previews: PREVIEWS_ABILITY,
8855
+ slack: SLACK_ABILITY
8856
+ };
8857
+ var REPLICAS_AGENT_ABILITIES = Object.keys(
8858
+ REPLICAS_AGENT_ABILITY_REGISTRY
8859
+ );
8860
+
8861
+ // ../shared/src/routes/preferences.ts
8862
+ var DEFAULT_REPLICAS_AGENT_ABILITIES = Object.fromEntries(
8863
+ REPLICAS_AGENT_ABILITIES.map((key) => [key, true])
8864
+ );
8865
+ var DEFAULT_DEFAULT_SKILLS = {
8866
+ replicas_agent: {
8867
+ enabled: true,
8868
+ abilities: { ...DEFAULT_REPLICAS_AGENT_ABILITIES }
8869
+ }
8870
+ };
7401
8871
 
7402
8872
  // ../shared/src/replicas-config.ts
7403
8873
  var import_yaml = __toESM(require_dist());
7404
8874
 
7405
8875
  // ../shared/src/warm-hooks.ts
7406
- var DEFAULT_WARM_HOOK_TIMEOUT_MS = 5 * 60 * 1e3;
7407
- var MAX_WARM_HOOK_TIMEOUT_MS = 15 * 60 * 1e3;
8876
+ var DEFAULT_WARM_HOOK_TIMEOUT_MS = 60 * 60 * 1e3;
8877
+ var MAX_WARM_HOOK_TIMEOUT_MS = 120 * 60 * 1e3;
8878
+ var DEFAULT_START_HOOK_TIMEOUT_MS = 5 * 60 * 1e3;
7408
8879
  var HOOK_EXEC_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
7409
8880
 
8881
+ // ../shared/src/engine/types.ts
8882
+ var CLAUDE_OPUS_1M_MODEL = "opus[1m]";
8883
+ var LEGACY_CLAUDE_OPUS_1M_MODEL = "opus-1m";
8884
+ var CLAUDE_FABLE_5_MODEL = "claude-fable-5";
8885
+ var DEFAULT_CODEX_MODEL = "gpt-5.5";
8886
+ var MODEL_LABELS = {
8887
+ sonnet: "Sonnet 4.5",
8888
+ opus: "Opus 4.8",
8889
+ [CLAUDE_OPUS_1M_MODEL]: "Opus 4.8 (1M)",
8890
+ [LEGACY_CLAUDE_OPUS_1M_MODEL]: "Opus 4.8 (1M)",
8891
+ [CLAUDE_FABLE_5_MODEL]: "Fable 5",
8892
+ haiku: "Haiku 4.5",
8893
+ [DEFAULT_CODEX_MODEL]: "GPT-5.5",
8894
+ "gpt-5.4": "GPT-5.4",
8895
+ "gpt-5.4-mini": "GPT-5.4 Mini",
8896
+ "gpt-5.3-codex": "GPT-5.3 Codex",
8897
+ "gpt-5.3-codex-spark": "GPT-5.3 Codex Spark",
8898
+ "gpt-5.2-codex": "GPT-5.2 Codex",
8899
+ "gpt-5.2": "GPT-5.2",
8900
+ "gpt-5.1-codex-max": "GPT-5.1 Codex Max",
8901
+ "gpt-5.1-codex": "GPT-5.1 Codex",
8902
+ "gpt-5.1": "GPT-5.1",
8903
+ "gpt-5-codex": "GPT-5 Codex",
8904
+ "gpt-5": "GPT-5"
8905
+ };
8906
+
7410
8907
  // ../shared/src/routes/workspaces.ts
7411
8908
  var WORKSPACE_FILE_UPLOAD_MAX_SIZE_BYTES = 20 * 1024 * 1024;
7412
8909
  var WORKSPACE_FILE_CONTENT_MAX_SIZE_BYTES = 1 * 1024 * 1024;
8910
+ var WORKSPACE_STATUS_FILTERS = ["active", "sleeping", "preparing", "failed"];
8911
+ var DEFAULT_STATUS_FILTERS = [...WORKSPACE_STATUS_FILTERS];
8912
+ var DEFAULT_WORKSPACE_FILTERS = {
8913
+ statuses: [...DEFAULT_STATUS_FILTERS],
8914
+ ownerIds: [],
8915
+ activity: "any"
8916
+ };
8917
+ var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
7413
8918
 
7414
8919
  // ../shared/src/audit-log.ts
7415
8920
  var AUDIT_LOG_ACTION = {
@@ -7421,7 +8926,71 @@ var AUDIT_LOG_ACTION = {
7421
8926
  };
7422
8927
  var AUDIT_LOG_ACTIONS = Object.values(AUDIT_LOG_ACTION);
7423
8928
 
7424
- // ../shared/src/display-message/parsers/codex-parser.ts
8929
+ // ../shared/src/automations/types.ts
8930
+ var AUTOMATION_DEBOUNCE_MAX_SECONDS = 24 * 60 * 60;
8931
+
8932
+ // ../shared/src/display-message/types.ts
8933
+ var BACKGROUND_TASK_SUBTYPES = /* @__PURE__ */ new Set([
8934
+ "task_started",
8935
+ "task_progress",
8936
+ "task_updated",
8937
+ "task_notification"
8938
+ ]);
8939
+ function isBackgroundTaskSubtype(subtype) {
8940
+ return typeof subtype === "string" && BACKGROUND_TASK_SUBTYPES.has(subtype);
8941
+ }
8942
+ function optionalString(value) {
8943
+ return typeof value === "string" ? value : void 0;
8944
+ }
8945
+ function coerceBackgroundTaskPayload(payload) {
8946
+ if (!isRecord(payload)) return null;
8947
+ const subtype = payload.subtype;
8948
+ if (!isBackgroundTaskSubtype(subtype)) return null;
8949
+ const taskId = payload.task_id;
8950
+ if (typeof taskId !== "string" || !taskId) return null;
8951
+ const patch = isRecord(payload.patch) ? {
8952
+ status: optionalString(payload.patch.status),
8953
+ description: optionalString(payload.patch.description),
8954
+ error: optionalString(payload.patch.error),
8955
+ isBackgrounded: optionalBoolean(payload.patch.is_backgrounded)
8956
+ } : void 0;
8957
+ const usage = isRecord(payload.usage) ? {
8958
+ totalTokens: optionalNumber(payload.usage.total_tokens),
8959
+ toolUses: optionalNumber(payload.usage.tool_uses),
8960
+ durationMs: optionalNumber(payload.usage.duration_ms)
8961
+ } : void 0;
8962
+ return {
8963
+ subtype,
8964
+ taskId,
8965
+ description: optionalString(payload.description),
8966
+ summary: optionalString(payload.summary),
8967
+ outputFile: optionalString(payload.output_file),
8968
+ status: optionalString(payload.status),
8969
+ taskType: optionalString(payload.task_type),
8970
+ workflowName: optionalString(payload.workflow_name),
8971
+ prompt: optionalString(payload.prompt),
8972
+ lastToolName: optionalString(payload.last_tool_name),
8973
+ usage,
8974
+ patch
8975
+ };
8976
+ }
8977
+ function optionalNumber(value) {
8978
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
8979
+ }
8980
+ function optionalBoolean(value) {
8981
+ return typeof value === "boolean" ? value : void 0;
8982
+ }
8983
+ function normalizeBackgroundTaskStatus(status) {
8984
+ if (status === "completed" || status === "failed" || status === "stopped") {
8985
+ return status;
8986
+ }
8987
+ if (status === "killed") {
8988
+ return "stopped";
8989
+ }
8990
+ return "in_progress";
8991
+ }
8992
+
8993
+ // ../shared/src/json.ts
7425
8994
  function safeJsonParse(str, fallback) {
7426
8995
  try {
7427
8996
  return JSON.parse(str);
@@ -7429,9 +8998,27 @@ function safeJsonParse(str, fallback) {
7429
8998
  return fallback;
7430
8999
  }
7431
9000
  }
9001
+
9002
+ // ../shared/src/display-message/parsers/codex-parser.ts
7432
9003
  function getStatusFromExitCode(exitCode) {
7433
9004
  return exitCode === 0 ? "completed" : "failed";
7434
9005
  }
9006
+ function getPayloadString(event, key) {
9007
+ const value = event.payload?.[key];
9008
+ return typeof value === "string" ? value : null;
9009
+ }
9010
+ function displayId(event, eventIndex, prefix) {
9011
+ const stableId = getPayloadString(event, USER_MESSAGE_ID_PAYLOAD_KEY) ?? getPayloadString(event, CODEX_ASP_ITEM_ID_PAYLOAD_KEY);
9012
+ return stableId ? `${prefix}-${stableId}` : `${prefix}-${event.timestamp}-${eventIndex}`;
9013
+ }
9014
+ function userMessageImages(value) {
9015
+ if (!Array.isArray(value)) return void 0;
9016
+ const images = value.filter((item) => {
9017
+ if (!isRecord(item)) return false;
9018
+ return item.type === "image" && typeof item.mediaType === "string" && typeof item.data === "string";
9019
+ });
9020
+ return images.length > 0 ? images : void 0;
9021
+ }
7435
9022
  function parseShellOutput(raw) {
7436
9023
  const exitCodeMatch = raw.match(/^Exit code: (\d+)/m) || raw.match(/Process exited with code (\d+)/);
7437
9024
  const exitCode = exitCodeMatch ? parseInt(exitCodeMatch[1], 10) : 0;
@@ -7495,6 +9082,7 @@ function parsePatch(input) {
7495
9082
  function parseCodexEvents(events) {
7496
9083
  const messages = [];
7497
9084
  const pendingCommands = /* @__PURE__ */ new Map();
9085
+ const pendingToolCalls = /* @__PURE__ */ new Map();
7498
9086
  const pendingPatches = /* @__PURE__ */ new Map();
7499
9087
  events.forEach((event, eventIndex) => {
7500
9088
  if (event.type === CODEX_QUOTA_STATUS_EVENT_TYPE) {
@@ -7514,16 +9102,18 @@ function parseCodexEvents(events) {
7514
9102
  return;
7515
9103
  }
7516
9104
  if (event.type === "event_msg" && event.payload?.type === "user_message") {
9105
+ const message = getPayloadString(event, "message");
7517
9106
  messages.push({
7518
- id: `user-${event.timestamp}-${eventIndex}`,
9107
+ id: displayId(event, eventIndex, "user"),
7519
9108
  type: "user",
7520
- content: event.payload.message || "",
9109
+ content: message ?? "",
9110
+ images: userMessageImages(event.payload.images),
7521
9111
  timestamp: event.timestamp
7522
9112
  });
7523
9113
  }
7524
9114
  if (event.type === "event_msg" && event.payload?.type === "agent_reasoning") {
7525
9115
  messages.push({
7526
- id: `reasoning-${event.timestamp}-${eventIndex}-${messages.length}`,
9116
+ id: displayId(event, eventIndex, "reasoning"),
7527
9117
  type: "reasoning",
7528
9118
  content: event.payload.text || "",
7529
9119
  status: "completed",
@@ -7537,7 +9127,7 @@ function parseCodexEvents(events) {
7537
9127
  const textContent = content.filter((c) => c.type === "output_text").map((c) => c.text || "").join("\n");
7538
9128
  if (textContent) {
7539
9129
  messages.push({
7540
- id: `agent-${event.timestamp}-${eventIndex}`,
9130
+ id: displayId(event, eventIndex, "agent"),
7541
9131
  type: "agent",
7542
9132
  content: textContent,
7543
9133
  timestamp: event.timestamp
@@ -7577,19 +9167,25 @@ function parseCodexEvents(events) {
7577
9167
  const callId = event.payload.call_id;
7578
9168
  const name = event.payload.name;
7579
9169
  const input = event.payload.input || "";
9170
+ const server2 = typeof event.payload.server === "string" ? event.payload.server : "custom";
7580
9171
  const status = event.payload.status || "in_progress";
7581
9172
  if (name === "apply_patch") {
7582
9173
  const operations = parsePatch(input);
7583
9174
  pendingPatches.set(callId, { input, status, timestamp: event.timestamp, operations });
7584
9175
  } else {
7585
- messages.push({
7586
- id: `toolcall-${event.timestamp}-${eventIndex}`,
9176
+ const msg = {
9177
+ id: `toolcall-${callId || getPayloadString(event, CODEX_ASP_ITEM_ID_PAYLOAD_KEY) || `${event.timestamp}-${eventIndex}`}`,
7587
9178
  type: "tool_call",
7588
- server: "custom",
9179
+ server: server2,
7589
9180
  tool: name,
9181
+ input,
7590
9182
  status,
7591
9183
  timestamp: event.timestamp
7592
- });
9184
+ };
9185
+ messages.push(msg);
9186
+ if (callId) {
9187
+ pendingToolCalls.set(callId, msg);
9188
+ }
7593
9189
  }
7594
9190
  }
7595
9191
  if (payloadType === "custom_tool_call_output") {
@@ -7611,9 +9207,14 @@ function parseCodexEvents(events) {
7611
9207
  });
7612
9208
  pendingPatches.delete(callId);
7613
9209
  } else {
7614
- const toolCallMsg = messages.findLast((m) => m.type === "tool_call");
9210
+ const fallbackToolCallMsg = messages.findLast((m) => m.type === "tool_call");
9211
+ const toolCallMsg = pendingToolCalls.get(callId) ?? fallbackToolCallMsg;
7615
9212
  if (toolCallMsg) {
7616
9213
  toolCallMsg.status = getStatusFromExitCode(output.metadata?.exit_code);
9214
+ toolCallMsg.output = output.output ?? (typeof event.payload.output === "string" ? event.payload.output : "");
9215
+ if (callId) {
9216
+ pendingToolCalls.delete(callId);
9217
+ }
7617
9218
  }
7618
9219
  }
7619
9220
  }
@@ -7641,40 +9242,180 @@ function parseCodexEvents(events) {
7641
9242
  return messages;
7642
9243
  }
7643
9244
 
7644
- // ../shared/src/display-message/parsers/claude-parser.ts
7645
- function safeJsonParse2(str, fallback) {
9245
+ // ../shared/src/display-message/task-accumulator.ts
9246
+ function mapTaskStatus(status) {
9247
+ if (status === "in_progress" || status === "completed") return status;
9248
+ return "pending";
9249
+ }
9250
+ function toAccumulatorInput(input) {
9251
+ if (typeof input === "string") {
9252
+ try {
9253
+ const parsed = JSON.parse(input);
9254
+ return isRecord(parsed) ? parsed : {};
9255
+ } catch {
9256
+ return {};
9257
+ }
9258
+ }
9259
+ return isRecord(input) ? input : {};
9260
+ }
9261
+ function extractToolResultText(content, separator = "\n") {
9262
+ if (typeof content === "string") return content;
9263
+ if (!Array.isArray(content)) return "";
9264
+ const texts = [];
9265
+ for (const part of content) {
9266
+ if (isRecord(part) && part.type === "text" && typeof part.text === "string") {
9267
+ texts.push(part.text);
9268
+ }
9269
+ }
9270
+ return texts.join(separator);
9271
+ }
9272
+ function normalizeContentBlocks(content) {
9273
+ if (typeof content === "string") {
9274
+ return content ? [{ type: "text", text: content }] : [];
9275
+ }
9276
+ return content ?? [];
9277
+ }
9278
+ function parseStringField(value) {
9279
+ if (typeof value !== "string") return null;
9280
+ const trimmed = value.trim();
9281
+ return trimmed ? trimmed : null;
9282
+ }
9283
+ function parseCreateResultTaskId(resultText) {
7646
9284
  try {
7647
- return JSON.parse(str);
9285
+ const parsed = JSON.parse(resultText);
9286
+ if (isRecord(parsed) && isRecord(parsed.task)) {
9287
+ return parseStringField(parsed.task.id);
9288
+ }
7648
9289
  } catch {
7649
- return fallback;
7650
9290
  }
9291
+ return resultText.match(/\bTask\s+#?([A-Za-z0-9_-]+)\s+created\b/i)?.[1] ?? null;
7651
9292
  }
7652
- function extractToolResultContent(content) {
7653
- if (!content) return "";
7654
- if (typeof content === "string") return content;
7655
- if (Array.isArray(content)) {
7656
- return content.filter((item) => item.type === "text").map((item) => item.text || "").join("\n");
9293
+ var TaskAccumulator = class {
9294
+ tasksByTaskId = /* @__PURE__ */ new Map();
9295
+ tasksByCreateToolUseId = /* @__PURE__ */ new Map();
9296
+ orderedKeys = [];
9297
+ processToolUse(toolName, toolUseId, input) {
9298
+ if (toolName === "TaskCreate") {
9299
+ const subject = parseStringField(input.subject);
9300
+ if (!subject) return false;
9301
+ this.tasksByCreateToolUseId.set(toolUseId, { subject, status: "pending" });
9302
+ this.orderedKeys.push(toolUseId);
9303
+ return true;
9304
+ }
9305
+ if (toolName === "TaskUpdate") {
9306
+ const taskId = parseStringField(input.taskId);
9307
+ if (!taskId) return false;
9308
+ if (input.status === "deleted") {
9309
+ if (!this.tasksByTaskId.delete(taskId)) return false;
9310
+ const idx = this.orderedKeys.indexOf(taskId);
9311
+ if (idx !== -1) this.orderedKeys.splice(idx, 1);
9312
+ return true;
9313
+ }
9314
+ const existing = this.tasksByTaskId.get(taskId);
9315
+ const subject = parseStringField(input.subject) ?? existing?.subject;
9316
+ if (!subject) return false;
9317
+ const status = input.status !== void 0 ? mapTaskStatus(input.status) : existing?.status ?? "pending";
9318
+ this.tasksByTaskId.set(taskId, { subject, status });
9319
+ if (!existing) this.orderedKeys.push(taskId);
9320
+ return true;
9321
+ }
9322
+ if (toolName === "TaskList") {
9323
+ if (!Array.isArray(input.tasks)) return false;
9324
+ let changed = false;
9325
+ for (const raw of input.tasks) {
9326
+ if (!isRecord(raw)) continue;
9327
+ const id = parseStringField(raw.id);
9328
+ const subject = parseStringField(raw.subject);
9329
+ if (!id || !subject) continue;
9330
+ const existing = this.tasksByTaskId.get(id);
9331
+ const next = { subject, status: mapTaskStatus(raw.status) };
9332
+ if (existing && existing.subject === next.subject && existing.status === next.status) continue;
9333
+ this.tasksByTaskId.set(id, next);
9334
+ if (!existing) this.orderedKeys.push(id);
9335
+ changed = true;
9336
+ }
9337
+ return changed;
9338
+ }
9339
+ return false;
9340
+ }
9341
+ processCreateResult(toolUseId, resultText) {
9342
+ const pending = this.tasksByCreateToolUseId.get(toolUseId);
9343
+ if (!pending) return false;
9344
+ const taskId = parseCreateResultTaskId(resultText);
9345
+ if (!taskId) return false;
9346
+ this.tasksByTaskId.set(taskId, pending);
9347
+ this.tasksByCreateToolUseId.delete(toolUseId);
9348
+ const idx = this.orderedKeys.indexOf(toolUseId);
9349
+ if (idx !== -1) this.orderedKeys.splice(idx, 1, taskId);
9350
+ return true;
9351
+ }
9352
+ getTasks() {
9353
+ const out = [];
9354
+ for (const key of this.orderedKeys) {
9355
+ const task = this.tasksByTaskId.get(key) ?? this.tasksByCreateToolUseId.get(key);
9356
+ if (task && task.subject) out.push(task);
9357
+ }
9358
+ return out;
7657
9359
  }
7658
- return "";
9360
+ processContentBlock(block) {
9361
+ if (!isRecord(block)) return false;
9362
+ if (block.type === "tool_use" && typeof block.name === "string" && typeof block.id === "string") {
9363
+ return this.processToolUse(block.name, block.id, toAccumulatorInput(block.input));
9364
+ }
9365
+ if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
9366
+ return this.processCreateResult(block.tool_use_id, extractToolResultText(block.content, ""));
9367
+ }
9368
+ return false;
9369
+ }
9370
+ };
9371
+
9372
+ // ../shared/src/display-message/parsers/mcp.ts
9373
+ function parseMcpToolName(name) {
9374
+ const prefix = "mcp__";
9375
+ if (!name.startsWith(prefix)) return null;
9376
+ const rest = name.slice(prefix.length);
9377
+ const sep = rest.indexOf("__");
9378
+ if (sep <= 0) return null;
9379
+ const server2 = rest.slice(0, sep);
9380
+ const tool = rest.slice(sep + 2);
9381
+ if (!server2 || !tool) return null;
9382
+ return { server: server2, tool };
7659
9383
  }
9384
+
9385
+ // ../shared/src/display-message/parsers/claude-parser.ts
9386
+ var LOCAL_COMMAND_ECHO_REGEX = /^<(?:command-name|command-message|local-command-stdout|local-command-stderr)>/;
7660
9387
  function parseClaudeEvents(events, parentToolUseId) {
7661
9388
  const messages = [];
7662
9389
  const filterValue = parentToolUseId !== void 0 ? parentToolUseId : null;
7663
- const filteredEvents = events.filter(
7664
- (e) => e.payload.parent_tool_use_id === filterValue
7665
- );
9390
+ const filteredEvents = events.filter((e) => {
9391
+ const eventParentToolUseId = e.payload.parent_tool_use_id ?? null;
9392
+ return eventParentToolUseId === filterValue;
9393
+ });
7666
9394
  const toolCallMap = /* @__PURE__ */ new Map();
9395
+ const taskMessageMap = /* @__PURE__ */ new Map();
9396
+ const taskAccumulator = new TaskAccumulator();
9397
+ const taskSnapshot = () => taskAccumulator.getTasks().map((task) => ({
9398
+ text: task.subject,
9399
+ completed: task.status === "completed",
9400
+ itemStatus: task.status
9401
+ }));
7667
9402
  filteredEvents.forEach((event) => {
7668
9403
  if (event.type === "claude-user") {
7669
- const content = event.payload.message?.content || [];
9404
+ const content = normalizeContentBlocks(event.payload.message?.content);
7670
9405
  const toolResult = content.find((c) => c.type === "tool_result");
7671
9406
  if (toolResult && toolResult.tool_use_id) {
9407
+ if (!toolResult.is_error) {
9408
+ taskAccumulator.processContentBlock(toolResult);
9409
+ }
7672
9410
  return;
7673
9411
  }
7674
9412
  if (event.payload.isSynthetic) {
7675
9413
  return;
7676
9414
  }
7677
9415
  const textContent = content.filter((c) => c.type === "text").map((c) => c.text || "").join("\n");
9416
+ if (LOCAL_COMMAND_ECHO_REGEX.test(textContent.trim())) {
9417
+ return;
9418
+ }
7678
9419
  const images = content.filter((c) => c.type === "image" && c.source).map((c) => {
7679
9420
  const source = c.source;
7680
9421
  return {
@@ -7694,7 +9435,7 @@ function parseClaudeEvents(events, parentToolUseId) {
7694
9435
  }
7695
9436
  }
7696
9437
  if (event.type === "claude-assistant") {
7697
- const contentBlocks = event.payload.message?.content || [];
9438
+ const contentBlocks = normalizeContentBlocks(event.payload.message?.content);
7698
9439
  contentBlocks.forEach((block) => {
7699
9440
  if (block.type === "text" && block.text) {
7700
9441
  messages.push({
@@ -7723,7 +9464,7 @@ function parseClaudeEvents(events, parentToolUseId) {
7723
9464
  input: toolInput
7724
9465
  });
7725
9466
  if (toolName === "Task" || toolName === "Agent") {
7726
- const inputObj = typeof toolInput === "string" ? safeJsonParse2(toolInput, {}) : toolInput;
9467
+ const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
7727
9468
  const nestedEvents = events.filter((e) => e.payload.parent_tool_use_id === toolUseId).map((e) => ({
7728
9469
  timestamp: e.timestamp,
7729
9470
  type: e.type,
@@ -7742,7 +9483,7 @@ function parseClaudeEvents(events, parentToolUseId) {
7742
9483
  timestamp: event.timestamp
7743
9484
  });
7744
9485
  } else if (toolName === "Bash" || toolName === "bash" || toolName === "shell") {
7745
- const inputObj = typeof toolInput === "string" ? safeJsonParse2(toolInput, {}) : toolInput;
9486
+ const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
7746
9487
  const command = inputObj.command || "";
7747
9488
  messages.push({
7748
9489
  id: `command-${event.timestamp}-${messages.length}`,
@@ -7753,7 +9494,7 @@ function parseClaudeEvents(events, parentToolUseId) {
7753
9494
  timestamp: event.timestamp
7754
9495
  });
7755
9496
  } else if (toolName === "Write" || toolName === "Edit") {
7756
- const inputObj = typeof toolInput === "string" ? safeJsonParse2(toolInput, {}) : toolInput;
9497
+ const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
7757
9498
  const filePath = inputObj.file_path || "";
7758
9499
  const action = toolName === "Write" ? "add" : "update";
7759
9500
  let diff;
@@ -7789,24 +9530,20 @@ function parseClaudeEvents(events, parentToolUseId) {
7789
9530
  status: "in_progress",
7790
9531
  timestamp: event.timestamp
7791
9532
  });
7792
- } else if (toolName === "TodoWrite") {
7793
- const inputObj = typeof toolInput === "string" ? safeJsonParse2(toolInput, {}) : toolInput;
7794
- const todos = Array.isArray(inputObj.todos) ? inputObj.todos : [];
7795
- const todoItems = todos.map((todo) => ({
7796
- text: todo.content,
7797
- completed: todo.status === "completed"
7798
- }));
7799
- if (todoItems.length > 0) {
9533
+ } else if (toolName === "TaskCreate" || toolName === "TaskUpdate" || toolName === "TaskList") {
9534
+ taskAccumulator.processContentBlock(block);
9535
+ const snapshot = taskSnapshot();
9536
+ if (snapshot.length > 0) {
7800
9537
  messages.push({
7801
9538
  id: `todo-${event.timestamp}-${messages.length}`,
7802
9539
  type: "todo_list",
7803
- items: todoItems,
9540
+ items: snapshot,
7804
9541
  status: "completed",
7805
9542
  timestamp: event.timestamp
7806
9543
  });
7807
9544
  }
7808
9545
  } else if (toolName === "WebSearch") {
7809
- const inputObj = typeof toolInput === "string" ? safeJsonParse2(toolInput, {}) : toolInput;
9546
+ const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
7810
9547
  const query = inputObj.query || "";
7811
9548
  messages.push({
7812
9549
  id: `search-${event.timestamp}-${messages.length}`,
@@ -7816,7 +9553,7 @@ function parseClaudeEvents(events, parentToolUseId) {
7816
9553
  timestamp: event.timestamp
7817
9554
  });
7818
9555
  } else if (toolName === "Skill") {
7819
- const inputObj = typeof toolInput === "string" ? safeJsonParse2(toolInput, {}) : toolInput;
9556
+ const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
7820
9557
  messages.push({
7821
9558
  id: `skill-${event.timestamp}-${messages.length}`,
7822
9559
  type: "skill",
@@ -7826,7 +9563,7 @@ function parseClaudeEvents(events, parentToolUseId) {
7826
9563
  timestamp: event.timestamp
7827
9564
  });
7828
9565
  } else if (toolName === "mcp__relay-subagent-tools__spawn_agent") {
7829
- const inputObj = typeof toolInput === "string" ? safeJsonParse2(toolInput, {}) : toolInput;
9566
+ const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
7830
9567
  messages.push({
7831
9568
  id: `subagent-${event.timestamp}-${messages.length}`,
7832
9569
  type: "subagent",
@@ -7841,12 +9578,13 @@ function parseClaudeEvents(events, parentToolUseId) {
7841
9578
  timestamp: event.timestamp
7842
9579
  });
7843
9580
  } else if (toolName === "mcp__relay-subagent-tools__delete_agent") {
7844
- const inputObj = typeof toolInput === "string" ? safeJsonParse2(toolInput, {}) : toolInput;
9581
+ const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
9582
+ const mcp = parseMcpToolName(toolName);
7845
9583
  messages.push({
7846
9584
  id: `toolcall-${event.timestamp}-${messages.length}`,
7847
9585
  type: "tool_call",
7848
- server: "relay-subagent-tools",
7849
- tool: "delete_agent",
9586
+ server: mcp?.server ?? "relay-subagent-tools",
9587
+ tool: mcp?.tool ?? "delete_agent",
7850
9588
  input: inputObj,
7851
9589
  status: "in_progress",
7852
9590
  timestamp: event.timestamp
@@ -7878,17 +9616,81 @@ function parseClaudeEvents(events, parentToolUseId) {
7878
9616
  });
7879
9617
  }
7880
9618
  }
9619
+ if (event.type === "claude-system") {
9620
+ const payload = coerceBackgroundTaskPayload(event.payload);
9621
+ if (payload) {
9622
+ const existing = taskMessageMap.get(payload.taskId);
9623
+ const nextStatus = payload.subtype === "task_notification" ? normalizeBackgroundTaskStatus(payload.status) : payload.subtype === "task_updated" ? normalizeBackgroundTaskStatus(payload.patch?.status) : existing?.status ?? "in_progress";
9624
+ const nextMessage = {
9625
+ id: existing?.id ?? `task-${event.timestamp}-${messages.length}`,
9626
+ type: "background_task",
9627
+ taskId: payload.taskId,
9628
+ status: nextStatus,
9629
+ description: payload.description ?? payload.patch?.description ?? existing?.description,
9630
+ summary: payload.summary ?? existing?.summary,
9631
+ outputFile: payload.outputFile ?? existing?.outputFile,
9632
+ taskType: payload.taskType ?? existing?.taskType,
9633
+ workflowName: payload.workflowName ?? existing?.workflowName,
9634
+ prompt: payload.prompt ?? existing?.prompt,
9635
+ lastToolName: payload.lastToolName ?? existing?.lastToolName,
9636
+ usage: payload.usage ?? existing?.usage,
9637
+ error: payload.patch?.error ?? existing?.error,
9638
+ isBackgrounded: payload.patch?.isBackgrounded ?? existing?.isBackgrounded,
9639
+ timestamp: existing?.timestamp ?? event.timestamp
9640
+ };
9641
+ if (existing) {
9642
+ Object.assign(existing, nextMessage);
9643
+ } else {
9644
+ taskMessageMap.set(payload.taskId, nextMessage);
9645
+ messages.push(nextMessage);
9646
+ }
9647
+ }
9648
+ }
9649
+ });
9650
+ filteredEvents.forEach((event) => {
9651
+ if (event.type === "replicas-tool-input-request") {
9652
+ const payload = event.payload;
9653
+ if (!payload.toolUseId || !payload.requestId) return;
9654
+ if (!Array.isArray(payload.options) && !Array.isArray(payload.questions)) return;
9655
+ const toolInfo = toolCallMap.get(payload.toolUseId);
9656
+ if (!toolInfo) return;
9657
+ const message = messages[toolInfo.messageIndex];
9658
+ if (!message || message.type !== "tool_call") return;
9659
+ message.inputRequest = {
9660
+ requestId: payload.requestId,
9661
+ status: "pending",
9662
+ options: payload.options,
9663
+ questions: payload.questions
9664
+ };
9665
+ }
9666
+ if (event.type === "replicas-tool-input-resolved") {
9667
+ const payload = event.payload;
9668
+ if (!payload.toolUseId || !payload.selectionId) return;
9669
+ const toolInfo = toolCallMap.get(payload.toolUseId);
9670
+ if (!toolInfo) return;
9671
+ const message = messages[toolInfo.messageIndex];
9672
+ if (!message || message.type !== "tool_call" || !message.inputRequest) return;
9673
+ message.inputRequest = {
9674
+ ...message.inputRequest,
9675
+ status: payload.selectionId === "aborted" ? "aborted" : "resolved",
9676
+ selectionId: payload.selectionId,
9677
+ selectionSummary: payload.selectionSummary
9678
+ };
9679
+ }
7881
9680
  });
7882
9681
  filteredEvents.forEach((event) => {
7883
9682
  if (event.type === "claude-user") {
7884
- const content = event.payload.message?.content || [];
9683
+ const content = normalizeContentBlocks(event.payload.message?.content);
7885
9684
  const toolResult = content.find((c) => c.type === "tool_result");
7886
9685
  if (toolResult && toolResult.tool_use_id) {
7887
9686
  const toolInfo = toolCallMap.get(toolResult.tool_use_id);
7888
9687
  if (!toolInfo) return;
7889
- const resultContent = extractToolResultContent(toolResult.content);
9688
+ const resultContent = extractToolResultText(toolResult.content);
7890
9689
  const isError = toolResult.is_error || false;
7891
9690
  const status = isError ? "failed" : "completed";
9691
+ if (toolInfo.toolName === "TaskCreate" && !isError) {
9692
+ taskAccumulator.processContentBlock(toolResult);
9693
+ }
7892
9694
  const message = messages[toolInfo.messageIndex];
7893
9695
  if (!message) return;
7894
9696
  if (message.type === "command") {
@@ -7913,7 +9715,7 @@ function parseClaudeEvents(events, parentToolUseId) {
7913
9715
  message.output = resultContent;
7914
9716
  message.status = status;
7915
9717
  if (!message.chatId && resultContent) {
7916
- const parsed = safeJsonParse2(resultContent, {});
9718
+ const parsed = safeJsonParse(resultContent, {});
7917
9719
  if (parsed.chatId) {
7918
9720
  message.chatId = parsed.chatId;
7919
9721
  }
@@ -7925,6 +9727,9 @@ function parseClaudeEvents(events, parentToolUseId) {
7925
9727
  return messages;
7926
9728
  }
7927
9729
 
9730
+ // ../shared/src/display-message/parsers/codex-asp-parser.ts
9731
+ var DUPLICATE_WINDOW_MS = 5 * 60 * 1e3;
9732
+
7928
9733
  // ../shared/src/display-message/parsers/index.ts
7929
9734
  function parseAgentEvents(events, agentType) {
7930
9735
  if (agentType === "codex") {
@@ -7974,7 +9779,7 @@ function result(data, isError = false) {
7974
9779
  }
7975
9780
  var server = new McpServer({
7976
9781
  name: "replicas-mcp",
7977
- version: "0.2.1"
9782
+ version: "0.2.3"
7978
9783
  });
7979
9784
  var registerTool = server.registerTool.bind(server);
7980
9785
  registerTool(
@@ -8016,7 +9821,7 @@ registerTool(
8016
9821
  page: z.number().optional(),
8017
9822
  limit: z.number().optional(),
8018
9823
  user_id: z.string().optional().describe("Filter by creator user ID"),
8019
- source: z.enum(["api", "dashboard", "slack", "linear", "github", "automation"]).optional().describe("Filter by creation source"),
9824
+ source: z.enum(["api", "dashboard", "slack", "linear", "github", "gitlab", "automation"]).optional().describe("Filter by creation source"),
8020
9825
  status: z.enum(["active", "sleeping", "preparing"]).optional().describe("Filter by workspace status")
8021
9826
  }
8022
9827
  },