@posthog/agent 2.3.643 → 2.3.655

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 (37) hide show
  1. package/dist/adapters/claude/permissions/permission-options.js +700 -0
  2. package/dist/adapters/claude/permissions/permission-options.js.map +1 -1
  3. package/dist/adapters/claude/tools.js +700 -0
  4. package/dist/adapters/claude/tools.js.map +1 -1
  5. package/dist/adapters/codex/local-tools-mcp-server.d.ts +2 -0
  6. package/dist/adapters/codex/local-tools-mcp-server.js +1172 -0
  7. package/dist/adapters/codex/local-tools-mcp-server.js.map +1 -0
  8. package/dist/agent.js +1488 -219
  9. package/dist/agent.js.map +1 -1
  10. package/dist/execution-mode.js +700 -0
  11. package/dist/execution-mode.js.map +1 -1
  12. package/dist/handoff-checkpoint.js.map +1 -1
  13. package/dist/posthog-api.js +1 -1
  14. package/dist/posthog-api.js.map +1 -1
  15. package/dist/server/agent-server.js +1604 -339
  16. package/dist/server/agent-server.js.map +1 -1
  17. package/dist/server/bin.cjs +1520 -258
  18. package/dist/server/bin.cjs.map +1 -1
  19. package/package.json +3 -3
  20. package/src/adapters/claude/claude-agent.ts +32 -2
  21. package/src/adapters/claude/hooks.test.ts +54 -0
  22. package/src/adapters/claude/hooks.ts +86 -0
  23. package/src/adapters/claude/mcp/local-tools.test.ts +50 -0
  24. package/src/adapters/claude/mcp/local-tools.ts +40 -0
  25. package/src/adapters/claude/session/options.ts +14 -9
  26. package/src/adapters/claude/types.ts +1 -0
  27. package/src/adapters/codex/codex-agent.ts +117 -22
  28. package/src/adapters/codex/local-tools-mcp-server.ts +71 -0
  29. package/src/adapters/local-tools/index.ts +22 -0
  30. package/src/adapters/local-tools/registry.test.ts +57 -0
  31. package/src/adapters/local-tools/registry.ts +81 -0
  32. package/src/adapters/local-tools/tools/signed-commit.ts +26 -0
  33. package/src/adapters/session-meta.ts +16 -0
  34. package/src/adapters/signed-commit-shared.ts +82 -0
  35. package/src/server/agent-server.test.ts +2 -4
  36. package/src/server/agent-server.ts +27 -30
  37. package/src/utils/common.ts +14 -0
@@ -513,7 +513,7 @@ var require_has_flag = __commonJS({
513
513
  var require_supports_color = __commonJS({
514
514
  "../../node_modules/supports-color/index.js"(exports2, module2) {
515
515
  "use strict";
516
- var os8 = __require("os");
516
+ var os9 = __require("os");
517
517
  var tty = __require("tty");
518
518
  var hasFlag = require_has_flag();
519
519
  var { env } = process;
@@ -561,7 +561,7 @@ var require_supports_color = __commonJS({
561
561
  return min;
562
562
  }
563
563
  if (process.platform === "win32") {
564
- const osRelease = os8.release().split(".");
564
+ const osRelease = os9.release().split(".");
565
565
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
566
566
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
567
567
  }
@@ -809,10 +809,10 @@ var require_src2 = __commonJS({
809
809
  var fs_1 = __require("fs");
810
810
  var debug_1 = __importDefault(require_src());
811
811
  var log = debug_1.default("@kwsites/file-exists");
812
- function check(path17, isFile2, isDirectory) {
813
- log(`checking %s`, path17);
812
+ function check(path18, isFile2, isDirectory) {
813
+ log(`checking %s`, path18);
814
814
  try {
815
- const stat4 = fs_1.statSync(path17);
815
+ const stat4 = fs_1.statSync(path18);
816
816
  if (stat4.isFile() && isFile2) {
817
817
  log(`[OK] path represents a file`);
818
818
  return true;
@@ -832,8 +832,8 @@ var require_src2 = __commonJS({
832
832
  throw e;
833
833
  }
834
834
  }
835
- function exists2(path17, type = exports2.READABLE) {
836
- return check(path17, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
835
+ function exists2(path18, type = exports2.READABLE) {
836
+ return check(path18, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
837
837
  }
838
838
  exports2.exists = exists2;
839
839
  exports2.FILE = 1;
@@ -929,11 +929,11 @@ var require_tree_sitter = __commonJS({
929
929
  throw toThrow;
930
930
  };
931
931
  var scriptDirectory = "";
932
- function locateFile(path17) {
932
+ function locateFile(path18) {
933
933
  if (Module["locateFile"]) {
934
- return Module["locateFile"](path17, scriptDirectory);
934
+ return Module["locateFile"](path18, scriptDirectory);
935
935
  }
936
- return scriptDirectory + path17;
936
+ return scriptDirectory + path18;
937
937
  }
938
938
  var readAsync, readBinary;
939
939
  if (ENVIRONMENT_IS_NODE) {
@@ -947,10 +947,10 @@ var require_tree_sitter = __commonJS({
947
947
  };
948
948
  readAsync = (filename, binary2 = true) => {
949
949
  filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
950
- return new Promise((resolve7, reject) => {
950
+ return new Promise((resolve8, reject) => {
951
951
  fs.readFile(filename, binary2 ? void 0 : "utf8", (err2, data) => {
952
952
  if (err2) reject(err2);
953
- else resolve7(binary2 ? data.buffer : data);
953
+ else resolve8(binary2 ? data.buffer : data);
954
954
  });
955
955
  });
956
956
  };
@@ -991,13 +991,13 @@ var require_tree_sitter = __commonJS({
991
991
  }
992
992
  readAsync = (url) => {
993
993
  if (isFileURI(url)) {
994
- return new Promise((reject, resolve7) => {
994
+ return new Promise((reject, resolve8) => {
995
995
  var xhr = new XMLHttpRequest();
996
996
  xhr.open("GET", url, true);
997
997
  xhr.responseType = "arraybuffer";
998
998
  xhr.onload = () => {
999
999
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
1000
- resolve7(xhr.response);
1000
+ resolve8(xhr.response);
1001
1001
  }
1002
1002
  reject(xhr.status);
1003
1003
  };
@@ -1957,8 +1957,8 @@ var require_tree_sitter = __commonJS({
1957
1957
  }
1958
1958
  var libFile = locateFile(libName2);
1959
1959
  if (flags2.loadAsync) {
1960
- return new Promise(function(resolve7, reject) {
1961
- asyncLoad(libFile, resolve7, reject);
1960
+ return new Promise(function(resolve8, reject) {
1961
+ asyncLoad(libFile, resolve8, reject);
1962
1962
  });
1963
1963
  }
1964
1964
  if (!readBinary) {
@@ -3454,8 +3454,8 @@ var require_tree_sitter = __commonJS({
3454
3454
  } else {
3455
3455
  const url = input;
3456
3456
  if (typeof process !== "undefined" && process.versions && process.versions.node) {
3457
- const fs14 = __require("fs");
3458
- bytes = Promise.resolve(fs14.readFileSync(url));
3457
+ const fs15 = __require("fs");
3458
+ bytes = Promise.resolve(fs15.readFileSync(url));
3459
3459
  } else {
3460
3460
  bytes = fetch(url).then((response) => response.arrayBuffer().then((buffer) => {
3461
3461
  if (response.ok) {
@@ -3783,9 +3783,653 @@ ${JSON.stringify(symbolNames, null, 2)}`);
3783
3783
  }
3784
3784
  });
3785
3785
 
3786
+ // ../../node_modules/protocols/lib/index.js
3787
+ var require_lib = __commonJS({
3788
+ "../../node_modules/protocols/lib/index.js"(exports2, module2) {
3789
+ "use strict";
3790
+ module2.exports = function protocols(input, first2) {
3791
+ if (first2 === true) {
3792
+ first2 = 0;
3793
+ }
3794
+ var prots = "";
3795
+ if (typeof input === "string") {
3796
+ try {
3797
+ prots = new URL(input).protocol;
3798
+ } catch (e) {
3799
+ }
3800
+ } else if (input && input.constructor === URL) {
3801
+ prots = input.protocol;
3802
+ }
3803
+ var splits = prots.split(/\:|\+/).filter(Boolean);
3804
+ if (typeof first2 === "number") {
3805
+ return splits[first2];
3806
+ }
3807
+ return splits;
3808
+ };
3809
+ }
3810
+ });
3811
+
3812
+ // ../../node_modules/parse-path/lib/index.js
3813
+ var require_lib2 = __commonJS({
3814
+ "../../node_modules/parse-path/lib/index.js"(exports2, module2) {
3815
+ "use strict";
3816
+ var protocols = require_lib();
3817
+ function parsePath(url) {
3818
+ var output = {
3819
+ protocols: [],
3820
+ protocol: null,
3821
+ port: null,
3822
+ resource: "",
3823
+ host: "",
3824
+ user: "",
3825
+ password: "",
3826
+ pathname: "",
3827
+ hash: "",
3828
+ search: "",
3829
+ href: url,
3830
+ query: {},
3831
+ parse_failed: false
3832
+ };
3833
+ try {
3834
+ var parsed = new URL(url);
3835
+ output.protocols = protocols(parsed);
3836
+ output.protocol = output.protocols[0];
3837
+ output.port = parsed.port;
3838
+ output.resource = parsed.hostname;
3839
+ output.host = parsed.host;
3840
+ output.user = parsed.username || "";
3841
+ output.password = parsed.password || "";
3842
+ output.pathname = parsed.pathname;
3843
+ output.hash = parsed.hash.slice(1);
3844
+ output.search = parsed.search.slice(1);
3845
+ output.href = parsed.href;
3846
+ output.query = Object.fromEntries(parsed.searchParams);
3847
+ } catch (e) {
3848
+ output.protocols = ["file"];
3849
+ output.protocol = output.protocols[0];
3850
+ output.port = "";
3851
+ output.resource = "";
3852
+ output.user = "";
3853
+ output.pathname = "";
3854
+ output.hash = "";
3855
+ output.search = "";
3856
+ output.href = url;
3857
+ output.query = {};
3858
+ output.parse_failed = true;
3859
+ }
3860
+ return output;
3861
+ }
3862
+ module2.exports = parsePath;
3863
+ }
3864
+ });
3865
+
3866
+ // ../../node_modules/parse-url/dist/index.js
3867
+ var require_dist3 = __commonJS({
3868
+ "../../node_modules/parse-url/dist/index.js"(exports2, module2) {
3869
+ "use strict";
3870
+ var require$$1 = require_lib2();
3871
+ function _interopDefaultLegacy(e) {
3872
+ return e && typeof e === "object" && "default" in e ? e : { "default": e };
3873
+ }
3874
+ var require$$1__default = /* @__PURE__ */ _interopDefaultLegacy(require$$1);
3875
+ function getAugmentedNamespace(n) {
3876
+ if (n.__esModule) return n;
3877
+ var f = n.default;
3878
+ if (typeof f == "function") {
3879
+ var a = function a2() {
3880
+ if (this instanceof a2) {
3881
+ var args2 = [null];
3882
+ args2.push.apply(args2, arguments);
3883
+ var Ctor = Function.bind.apply(f, args2);
3884
+ return new Ctor();
3885
+ }
3886
+ return f.apply(this, arguments);
3887
+ };
3888
+ a.prototype = f.prototype;
3889
+ } else a = {};
3890
+ Object.defineProperty(a, "__esModule", { value: true });
3891
+ Object.keys(n).forEach(function(k) {
3892
+ var d = Object.getOwnPropertyDescriptor(n, k);
3893
+ Object.defineProperty(a, k, d.get ? d : {
3894
+ enumerable: true,
3895
+ get: function() {
3896
+ return n[k];
3897
+ }
3898
+ });
3899
+ });
3900
+ return a;
3901
+ }
3902
+ var src = {};
3903
+ var DATA_URL_DEFAULT_MIME_TYPE = "text/plain";
3904
+ var DATA_URL_DEFAULT_CHARSET = "us-ascii";
3905
+ var testParameter = (name2, filters) => filters.some((filter) => filter instanceof RegExp ? filter.test(name2) : filter === name2);
3906
+ var normalizeDataURL = (urlString, { stripHash }) => {
3907
+ const match = /^data:(?<type>[^,]*?),(?<data>[^#]*?)(?:#(?<hash>.*))?$/.exec(urlString);
3908
+ if (!match) {
3909
+ throw new Error(`Invalid URL: ${urlString}`);
3910
+ }
3911
+ let { type, data, hash } = match.groups;
3912
+ const mediaType = type.split(";");
3913
+ hash = stripHash ? "" : hash;
3914
+ let isBase64 = false;
3915
+ if (mediaType[mediaType.length - 1] === "base64") {
3916
+ mediaType.pop();
3917
+ isBase64 = true;
3918
+ }
3919
+ const mimeType = (mediaType.shift() || "").toLowerCase();
3920
+ const attributes = mediaType.map((attribute) => {
3921
+ let [key, value = ""] = attribute.split("=").map((string) => string.trim());
3922
+ if (key === "charset") {
3923
+ value = value.toLowerCase();
3924
+ if (value === DATA_URL_DEFAULT_CHARSET) {
3925
+ return "";
3926
+ }
3927
+ }
3928
+ return `${key}${value ? `=${value}` : ""}`;
3929
+ }).filter(Boolean);
3930
+ const normalizedMediaType = [
3931
+ ...attributes
3932
+ ];
3933
+ if (isBase64) {
3934
+ normalizedMediaType.push("base64");
3935
+ }
3936
+ if (normalizedMediaType.length > 0 || mimeType && mimeType !== DATA_URL_DEFAULT_MIME_TYPE) {
3937
+ normalizedMediaType.unshift(mimeType);
3938
+ }
3939
+ return `data:${normalizedMediaType.join(";")},${isBase64 ? data.trim() : data}${hash ? `#${hash}` : ""}`;
3940
+ };
3941
+ function normalizeUrl(urlString, options) {
3942
+ options = {
3943
+ defaultProtocol: "http:",
3944
+ normalizeProtocol: true,
3945
+ forceHttp: false,
3946
+ forceHttps: false,
3947
+ stripAuthentication: true,
3948
+ stripHash: false,
3949
+ stripTextFragment: true,
3950
+ stripWWW: true,
3951
+ removeQueryParameters: [/^utm_\w+/i],
3952
+ removeTrailingSlash: true,
3953
+ removeSingleSlash: true,
3954
+ removeDirectoryIndex: false,
3955
+ sortQueryParameters: true,
3956
+ ...options
3957
+ };
3958
+ urlString = urlString.trim();
3959
+ if (/^data:/i.test(urlString)) {
3960
+ return normalizeDataURL(urlString, options);
3961
+ }
3962
+ if (/^view-source:/i.test(urlString)) {
3963
+ throw new Error("`view-source:` is not supported as it is a non-standard protocol");
3964
+ }
3965
+ const hasRelativeProtocol = urlString.startsWith("//");
3966
+ const isRelativeUrl = !hasRelativeProtocol && /^\.*\//.test(urlString);
3967
+ if (!isRelativeUrl) {
3968
+ urlString = urlString.replace(/^(?!(?:\w+:)?\/\/)|^\/\//, options.defaultProtocol);
3969
+ }
3970
+ const urlObject = new URL(urlString);
3971
+ if (options.forceHttp && options.forceHttps) {
3972
+ throw new Error("The `forceHttp` and `forceHttps` options cannot be used together");
3973
+ }
3974
+ if (options.forceHttp && urlObject.protocol === "https:") {
3975
+ urlObject.protocol = "http:";
3976
+ }
3977
+ if (options.forceHttps && urlObject.protocol === "http:") {
3978
+ urlObject.protocol = "https:";
3979
+ }
3980
+ if (options.stripAuthentication) {
3981
+ urlObject.username = "";
3982
+ urlObject.password = "";
3983
+ }
3984
+ if (options.stripHash) {
3985
+ urlObject.hash = "";
3986
+ } else if (options.stripTextFragment) {
3987
+ urlObject.hash = urlObject.hash.replace(/#?:~:text.*?$/i, "");
3988
+ }
3989
+ if (urlObject.pathname) {
3990
+ const protocolRegex = /\b[a-z][a-z\d+\-.]{1,50}:\/\//g;
3991
+ let lastIndex = 0;
3992
+ let result = "";
3993
+ for (; ; ) {
3994
+ const match = protocolRegex.exec(urlObject.pathname);
3995
+ if (!match) {
3996
+ break;
3997
+ }
3998
+ const protocol = match[0];
3999
+ const protocolAtIndex = match.index;
4000
+ const intermediate = urlObject.pathname.slice(lastIndex, protocolAtIndex);
4001
+ result += intermediate.replace(/\/{2,}/g, "/");
4002
+ result += protocol;
4003
+ lastIndex = protocolAtIndex + protocol.length;
4004
+ }
4005
+ const remnant = urlObject.pathname.slice(lastIndex, urlObject.pathname.length);
4006
+ result += remnant.replace(/\/{2,}/g, "/");
4007
+ urlObject.pathname = result;
4008
+ }
4009
+ if (urlObject.pathname) {
4010
+ try {
4011
+ urlObject.pathname = decodeURI(urlObject.pathname);
4012
+ } catch {
4013
+ }
4014
+ }
4015
+ if (options.removeDirectoryIndex === true) {
4016
+ options.removeDirectoryIndex = [/^index\.[a-z]+$/];
4017
+ }
4018
+ if (Array.isArray(options.removeDirectoryIndex) && options.removeDirectoryIndex.length > 0) {
4019
+ let pathComponents = urlObject.pathname.split("/");
4020
+ const lastComponent = pathComponents[pathComponents.length - 1];
4021
+ if (testParameter(lastComponent, options.removeDirectoryIndex)) {
4022
+ pathComponents = pathComponents.slice(0, -1);
4023
+ urlObject.pathname = pathComponents.slice(1).join("/") + "/";
4024
+ }
4025
+ }
4026
+ if (urlObject.hostname) {
4027
+ urlObject.hostname = urlObject.hostname.replace(/\.$/, "");
4028
+ if (options.stripWWW && /^www\.(?!www\.)[a-z\-\d]{1,63}\.[a-z.\-\d]{2,63}$/.test(urlObject.hostname)) {
4029
+ urlObject.hostname = urlObject.hostname.replace(/^www\./, "");
4030
+ }
4031
+ }
4032
+ if (Array.isArray(options.removeQueryParameters)) {
4033
+ for (const key of [...urlObject.searchParams.keys()]) {
4034
+ if (testParameter(key, options.removeQueryParameters)) {
4035
+ urlObject.searchParams.delete(key);
4036
+ }
4037
+ }
4038
+ }
4039
+ if (options.removeQueryParameters === true) {
4040
+ urlObject.search = "";
4041
+ }
4042
+ if (options.sortQueryParameters) {
4043
+ urlObject.searchParams.sort();
4044
+ try {
4045
+ urlObject.search = decodeURIComponent(urlObject.search);
4046
+ } catch {
4047
+ }
4048
+ }
4049
+ if (options.removeTrailingSlash) {
4050
+ urlObject.pathname = urlObject.pathname.replace(/\/$/, "");
4051
+ }
4052
+ const oldUrlString = urlString;
4053
+ urlString = urlObject.toString();
4054
+ if (!options.removeSingleSlash && urlObject.pathname === "/" && !oldUrlString.endsWith("/") && urlObject.hash === "") {
4055
+ urlString = urlString.replace(/\/$/, "");
4056
+ }
4057
+ if ((options.removeTrailingSlash || urlObject.pathname === "/") && urlObject.hash === "" && options.removeSingleSlash) {
4058
+ urlString = urlString.replace(/\/$/, "");
4059
+ }
4060
+ if (hasRelativeProtocol && !options.normalizeProtocol) {
4061
+ urlString = urlString.replace(/^http:\/\//, "//");
4062
+ }
4063
+ if (options.stripProtocol) {
4064
+ urlString = urlString.replace(/^(?:https?:)?\/\//, "");
4065
+ }
4066
+ return urlString;
4067
+ }
4068
+ var normalizeUrl$1 = /* @__PURE__ */ Object.freeze({
4069
+ __proto__: null,
4070
+ "default": normalizeUrl
4071
+ });
4072
+ var require$$0 = /* @__PURE__ */ getAugmentedNamespace(normalizeUrl$1);
4073
+ Object.defineProperty(src, "__esModule", {
4074
+ value: true
4075
+ });
4076
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
4077
+ return typeof obj;
4078
+ } : function(obj) {
4079
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
4080
+ };
4081
+ var _normalizeUrl = require$$0;
4082
+ var _normalizeUrl2 = _interopRequireDefault(_normalizeUrl);
4083
+ var _parsePath = require$$1__default["default"];
4084
+ var _parsePath2 = _interopRequireDefault(_parsePath);
4085
+ function _interopRequireDefault(obj) {
4086
+ return obj && obj.__esModule ? obj : { default: obj };
4087
+ }
4088
+ var parseUrl = function parseUrl2(url) {
4089
+ var normalize3 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
4090
+ var GIT_RE = /^(?:([a-zA-Z_][a-zA-Z0-9_-]{0,31})@|https?:\/\/)([\w\.\-@]+)[\/:](([\~,\.\w,\-,\_,\/,\s]|%[0-9A-Fa-f]{2})+?(?:\.git|\/)?)$/;
4091
+ var throwErr = function throwErr2(msg) {
4092
+ var err2 = new Error(msg);
4093
+ err2.subject_url = url;
4094
+ throw err2;
4095
+ };
4096
+ if (typeof url !== "string" || !url.trim()) {
4097
+ throwErr("Invalid url.");
4098
+ }
4099
+ if (url.length > parseUrl2.MAX_INPUT_LENGTH) {
4100
+ throwErr("Input exceeds maximum length. If needed, change the value of parseUrl.MAX_INPUT_LENGTH.");
4101
+ }
4102
+ if (normalize3) {
4103
+ if ((typeof normalize3 === "undefined" ? "undefined" : _typeof(normalize3)) !== "object") {
4104
+ normalize3 = {
4105
+ stripHash: false
4106
+ };
4107
+ }
4108
+ url = (0, _normalizeUrl2.default)(url, normalize3);
4109
+ }
4110
+ var parsed = (0, _parsePath2.default)(url);
4111
+ if (parsed.parse_failed) {
4112
+ var matched = parsed.href.match(GIT_RE);
4113
+ if (matched) {
4114
+ parsed.protocols = ["ssh"];
4115
+ parsed.protocol = "ssh";
4116
+ parsed.resource = matched[2];
4117
+ parsed.host = matched[2];
4118
+ parsed.user = matched[1];
4119
+ parsed.pathname = "/" + matched[3];
4120
+ parsed.parse_failed = false;
4121
+ } else {
4122
+ throwErr("URL parsing failed.");
4123
+ }
4124
+ }
4125
+ return parsed;
4126
+ };
4127
+ parseUrl.MAX_INPUT_LENGTH = 2048;
4128
+ var _default = src.default = parseUrl;
4129
+ module2.exports = _default;
4130
+ }
4131
+ });
4132
+
4133
+ // ../../node_modules/is-ssh/lib/index.js
4134
+ var require_lib3 = __commonJS({
4135
+ "../../node_modules/is-ssh/lib/index.js"(exports2, module2) {
4136
+ "use strict";
4137
+ var protocols = require_lib();
4138
+ function isSsh(input) {
4139
+ if (Array.isArray(input)) {
4140
+ return input.indexOf("ssh") !== -1 || input.indexOf("rsync") !== -1;
4141
+ }
4142
+ if (typeof input !== "string") {
4143
+ return false;
4144
+ }
4145
+ var prots = protocols(input);
4146
+ input = input.substring(input.indexOf("://") + 3);
4147
+ if (isSsh(prots)) {
4148
+ return true;
4149
+ }
4150
+ var urlPortPattern = new RegExp(".([a-zA-Z\\d]+):(\\d+)/");
4151
+ return !input.match(urlPortPattern) && input.indexOf("@") < input.indexOf(":");
4152
+ }
4153
+ module2.exports = isSsh;
4154
+ }
4155
+ });
4156
+
4157
+ // ../../node_modules/git-up/lib/index.js
4158
+ var require_lib4 = __commonJS({
4159
+ "../../node_modules/git-up/lib/index.js"(exports2, module2) {
4160
+ "use strict";
4161
+ var parseUrl = require_dist3();
4162
+ var isSsh = require_lib3();
4163
+ function gitUp(input) {
4164
+ let output = parseUrl(input);
4165
+ output.token = "";
4166
+ if (output.password === "x-oauth-basic") {
4167
+ output.token = output.user;
4168
+ } else if (output.user === "x-token-auth") {
4169
+ output.token = output.password;
4170
+ }
4171
+ if (isSsh(output.protocols) || output.protocols.length === 0 && isSsh(input)) {
4172
+ output.protocol = "ssh";
4173
+ } else if (output.protocols.length) {
4174
+ output.protocol = output.protocols[0];
4175
+ } else {
4176
+ output.protocol = "file";
4177
+ output.protocols = ["file"];
4178
+ }
4179
+ output.href = output.href.replace(/\/$/, "");
4180
+ return output;
4181
+ }
4182
+ module2.exports = gitUp;
4183
+ }
4184
+ });
4185
+
4186
+ // ../../node_modules/git-url-parse/lib/index.js
4187
+ var require_lib5 = __commonJS({
4188
+ "../../node_modules/git-url-parse/lib/index.js"(exports2, module2) {
4189
+ "use strict";
4190
+ var gitUp = require_lib4();
4191
+ function gitUrlParse2(url, refs) {
4192
+ refs = refs || [];
4193
+ if (typeof url !== "string") {
4194
+ throw new Error("The url must be a string.");
4195
+ }
4196
+ if (!refs.every(function(item) {
4197
+ return typeof item === "string";
4198
+ })) {
4199
+ throw new Error("The refs should contain only strings");
4200
+ }
4201
+ var shorthandRe = /^([a-z\d-]{1,39})\/([-\.\w]{1,100})$/i;
4202
+ if (shorthandRe.test(url)) {
4203
+ url = "https://github.com/" + url;
4204
+ }
4205
+ var urlInfo = gitUp(url), sourceParts = urlInfo.resource.split("."), splits = null;
4206
+ urlInfo.toString = function(type) {
4207
+ return gitUrlParse2.stringify(this, type);
4208
+ };
4209
+ urlInfo.source = sourceParts.length > 2 ? sourceParts.slice(1 - sourceParts.length).join(".") : urlInfo.source = urlInfo.resource;
4210
+ urlInfo.git_suffix = /\.git$/.test(urlInfo.pathname);
4211
+ urlInfo.name = decodeURIComponent((urlInfo.pathname || urlInfo.href).replace(/(^\/)|(\/$)/g, "").replace(/\.git$/, ""));
4212
+ urlInfo.owner = decodeURIComponent(urlInfo.user);
4213
+ switch (urlInfo.source) {
4214
+ case "git.cloudforge.com":
4215
+ urlInfo.owner = urlInfo.user;
4216
+ urlInfo.organization = sourceParts[0];
4217
+ urlInfo.source = "cloudforge.com";
4218
+ break;
4219
+ case "visualstudio.com":
4220
+ if (urlInfo.resource === "vs-ssh.visualstudio.com") {
4221
+ splits = urlInfo.name.split("/");
4222
+ if (splits.length === 4) {
4223
+ urlInfo.organization = splits[1];
4224
+ urlInfo.owner = splits[2];
4225
+ urlInfo.name = splits[3];
4226
+ urlInfo.full_name = splits[2] + "/" + splits[3];
4227
+ }
4228
+ break;
4229
+ } else {
4230
+ splits = urlInfo.name.split("/");
4231
+ if (splits.length === 2) {
4232
+ urlInfo.owner = splits[1];
4233
+ urlInfo.name = splits[1];
4234
+ urlInfo.full_name = "_git/" + urlInfo.name;
4235
+ } else if (splits.length === 3) {
4236
+ urlInfo.name = splits[2];
4237
+ if (splits[0] === "DefaultCollection") {
4238
+ urlInfo.owner = splits[2];
4239
+ urlInfo.organization = splits[0];
4240
+ urlInfo.full_name = urlInfo.organization + "/_git/" + urlInfo.name;
4241
+ } else {
4242
+ urlInfo.owner = splits[0];
4243
+ urlInfo.full_name = urlInfo.owner + "/_git/" + urlInfo.name;
4244
+ }
4245
+ } else if (splits.length === 4) {
4246
+ urlInfo.organization = splits[0];
4247
+ urlInfo.owner = splits[1];
4248
+ urlInfo.name = splits[3];
4249
+ urlInfo.full_name = urlInfo.organization + "/" + urlInfo.owner + "/_git/" + urlInfo.name;
4250
+ }
4251
+ break;
4252
+ }
4253
+ // Azure DevOps (formerly Visual Studio Team Services)
4254
+ case "dev.azure.com":
4255
+ case "azure.com":
4256
+ if (urlInfo.resource === "ssh.dev.azure.com") {
4257
+ splits = urlInfo.name.split("/");
4258
+ if (splits.length === 4) {
4259
+ urlInfo.organization = splits[1];
4260
+ urlInfo.owner = splits[2];
4261
+ urlInfo.name = splits[3];
4262
+ }
4263
+ break;
4264
+ } else {
4265
+ splits = urlInfo.name.split("/");
4266
+ if (splits.length === 5) {
4267
+ urlInfo.organization = splits[0];
4268
+ urlInfo.owner = splits[1];
4269
+ urlInfo.name = splits[4];
4270
+ urlInfo.full_name = "_git/" + urlInfo.name;
4271
+ } else if (splits.length === 3) {
4272
+ urlInfo.name = splits[2];
4273
+ if (splits[0] === "DefaultCollection") {
4274
+ urlInfo.owner = splits[2];
4275
+ urlInfo.organization = splits[0];
4276
+ urlInfo.full_name = urlInfo.organization + "/_git/" + urlInfo.name;
4277
+ } else {
4278
+ urlInfo.owner = splits[0];
4279
+ urlInfo.full_name = urlInfo.owner + "/_git/" + urlInfo.name;
4280
+ }
4281
+ } else if (splits.length === 4) {
4282
+ urlInfo.organization = splits[0];
4283
+ urlInfo.owner = splits[1];
4284
+ urlInfo.name = splits[3];
4285
+ urlInfo.full_name = urlInfo.organization + "/" + urlInfo.owner + "/_git/" + urlInfo.name;
4286
+ }
4287
+ if (urlInfo.query && urlInfo.query["path"]) {
4288
+ urlInfo.filepath = urlInfo.query["path"].replace(/^\/+/g, "");
4289
+ }
4290
+ if (urlInfo.query && urlInfo.query["version"]) {
4291
+ urlInfo.ref = urlInfo.query["version"].replace(/^GB/, "");
4292
+ }
4293
+ break;
4294
+ }
4295
+ default:
4296
+ splits = urlInfo.name.split("/");
4297
+ var nameIndex = splits.length - 1;
4298
+ if (splits.length >= 2) {
4299
+ var dashIndex = splits.indexOf("-", 2);
4300
+ var blobIndex = splits.indexOf("blob", 2);
4301
+ var treeIndex = splits.indexOf("tree", 2);
4302
+ var commitIndex = splits.indexOf("commit", 2);
4303
+ var issuesIndex = splits.indexOf("issues", 2);
4304
+ var srcIndex = splits.indexOf("src", 2);
4305
+ var rawIndex = splits.indexOf("raw", 2);
4306
+ var editIndex = splits.indexOf("edit", 2);
4307
+ nameIndex = dashIndex > 0 ? dashIndex - 1 : blobIndex > 0 && treeIndex > 0 ? Math.min(blobIndex - 1, treeIndex - 1) : blobIndex > 0 ? blobIndex - 1 : issuesIndex > 0 ? issuesIndex - 1 : treeIndex > 0 ? treeIndex - 1 : commitIndex > 0 ? commitIndex - 1 : srcIndex > 0 ? srcIndex - 1 : rawIndex > 0 ? rawIndex - 1 : editIndex > 0 ? editIndex - 1 : nameIndex;
4308
+ urlInfo.owner = splits.slice(0, nameIndex).join("/");
4309
+ urlInfo.name = splits[nameIndex];
4310
+ if (commitIndex && issuesIndex < 0) {
4311
+ urlInfo.commit = splits[nameIndex + 2];
4312
+ }
4313
+ }
4314
+ urlInfo.ref = "";
4315
+ urlInfo.filepathtype = "";
4316
+ urlInfo.filepath = "";
4317
+ var offsetNameIndex = splits.length > nameIndex && splits[nameIndex + 1] === "-" ? nameIndex + 1 : nameIndex;
4318
+ if (splits.length > offsetNameIndex + 2 && ["raw", "src", "blob", "tree", "edit"].indexOf(splits[offsetNameIndex + 1]) >= 0) {
4319
+ urlInfo.filepathtype = splits[offsetNameIndex + 1];
4320
+ urlInfo.ref = splits[offsetNameIndex + 2];
4321
+ if (splits.length > offsetNameIndex + 3) {
4322
+ urlInfo.filepath = splits.slice(offsetNameIndex + 3).join("/");
4323
+ }
4324
+ }
4325
+ urlInfo.organization = urlInfo.owner;
4326
+ break;
4327
+ }
4328
+ if (!urlInfo.full_name) {
4329
+ urlInfo.full_name = urlInfo.owner;
4330
+ if (urlInfo.name) {
4331
+ urlInfo.full_name && (urlInfo.full_name += "/");
4332
+ urlInfo.full_name += urlInfo.name;
4333
+ }
4334
+ }
4335
+ if (urlInfo.owner.startsWith("scm/")) {
4336
+ urlInfo.source = "bitbucket-server";
4337
+ urlInfo.owner = urlInfo.owner.replace("scm/", "");
4338
+ urlInfo.organization = urlInfo.owner;
4339
+ urlInfo.full_name = urlInfo.owner + "/" + urlInfo.name;
4340
+ }
4341
+ var bitbucket = /(projects|users)\/(.*?)\/repos\/(.*?)((\/.*$)|$)/;
4342
+ var matches = bitbucket.exec(urlInfo.pathname);
4343
+ if (matches != null) {
4344
+ urlInfo.source = "bitbucket-server";
4345
+ if (matches[1] === "users") {
4346
+ urlInfo.owner = "~" + matches[2];
4347
+ } else {
4348
+ urlInfo.owner = matches[2];
4349
+ }
4350
+ urlInfo.organization = urlInfo.owner;
4351
+ urlInfo.name = matches[3];
4352
+ splits = matches[4].split("/");
4353
+ if (splits.length > 1) {
4354
+ if (["raw", "browse"].indexOf(splits[1]) >= 0) {
4355
+ urlInfo.filepathtype = splits[1];
4356
+ if (splits.length > 2) {
4357
+ urlInfo.filepath = splits.slice(2).join("/");
4358
+ }
4359
+ } else if (splits[1] === "commits" && splits.length > 2) {
4360
+ urlInfo.commit = splits[2];
4361
+ }
4362
+ }
4363
+ urlInfo.full_name = urlInfo.owner + "/" + urlInfo.name;
4364
+ if (urlInfo.query.at) {
4365
+ urlInfo.ref = urlInfo.query.at;
4366
+ } else {
4367
+ urlInfo.ref = "";
4368
+ }
4369
+ }
4370
+ if (refs.length !== 0 && urlInfo.ref) {
4371
+ urlInfo.ref = findLongestMatchingSubstring(urlInfo.href, refs) || urlInfo.ref;
4372
+ urlInfo.filepath = urlInfo.href.split(urlInfo.ref + "/")[1];
4373
+ }
4374
+ return urlInfo;
4375
+ }
4376
+ gitUrlParse2.stringify = function(obj, type) {
4377
+ type = type || (obj.protocols && obj.protocols.length ? obj.protocols.join("+") : obj.protocol);
4378
+ var port = obj.port ? ":" + obj.port : "";
4379
+ var user = obj.user || "git";
4380
+ var maybeGitSuffix = obj.git_suffix ? ".git" : "";
4381
+ switch (type) {
4382
+ case "ssh":
4383
+ if (port) return "ssh://" + user + "@" + obj.resource + port + "/" + obj.full_name + maybeGitSuffix;
4384
+ else return user + "@" + obj.resource + ":" + obj.full_name + maybeGitSuffix;
4385
+ case "git+ssh":
4386
+ case "ssh+git":
4387
+ case "ftp":
4388
+ case "ftps":
4389
+ return type + "://" + user + "@" + obj.resource + port + "/" + obj.full_name + maybeGitSuffix;
4390
+ case "http":
4391
+ case "https":
4392
+ var auth = obj.token ? buildToken(obj) : obj.user && (obj.protocols.includes("http") || obj.protocols.includes("https")) ? obj.user + "@" : "";
4393
+ return type + "://" + auth + obj.resource + port + "/" + buildPath(obj) + maybeGitSuffix;
4394
+ default:
4395
+ return obj.href;
4396
+ }
4397
+ };
4398
+ function buildToken(obj) {
4399
+ switch (obj.source) {
4400
+ case "bitbucket.org":
4401
+ return "x-token-auth:" + obj.token + "@";
4402
+ default:
4403
+ return obj.token + "@";
4404
+ }
4405
+ }
4406
+ function buildPath(obj) {
4407
+ switch (obj.source) {
4408
+ case "bitbucket-server":
4409
+ return "scm/" + obj.full_name;
4410
+ default:
4411
+ var encoded_full_name = obj.full_name.split("/").map(function(x) {
4412
+ return encodeURIComponent(x);
4413
+ }).join("/");
4414
+ return encoded_full_name;
4415
+ }
4416
+ }
4417
+ function findLongestMatchingSubstring(string, array) {
4418
+ var longestMatch = "";
4419
+ array.forEach(function(item) {
4420
+ if (string.includes(item) && item.length > longestMatch.length) {
4421
+ longestMatch = item;
4422
+ }
4423
+ });
4424
+ return longestMatch;
4425
+ }
4426
+ module2.exports = gitUrlParse2;
4427
+ }
4428
+ });
4429
+
3786
4430
  // src/server/agent-server.ts
3787
- import { mkdir as mkdir4, writeFile as writeFile4 } from "fs/promises";
3788
- import { basename as basename2, join as join12 } from "path";
4431
+ import { mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
4432
+ import { basename as basename3, join as join13 } from "path";
3789
4433
  import { pathToFileURL } from "url";
3790
4434
  import {
3791
4435
  ClientSideConnection as ClientSideConnection2,
@@ -3799,6 +4443,24 @@ import { createReadStream } from "fs";
3799
4443
  import * as fs3 from "fs/promises";
3800
4444
  import * as path2 from "path";
3801
4445
 
4446
+ // ../git/dist/concurrency.js
4447
+ async function mapWithConcurrency(items, concurrency, mapper, options) {
4448
+ if (items.length === 0)
4449
+ return [];
4450
+ const results = new Array(items.length);
4451
+ let index = 0;
4452
+ const worker = async () => {
4453
+ while (index < items.length) {
4454
+ if (options?.signal?.aborted)
4455
+ return;
4456
+ const i2 = index++;
4457
+ results[i2] = await mapper(items[i2]);
4458
+ }
4459
+ };
4460
+ await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
4461
+ return results;
4462
+ }
4463
+
3802
4464
  // ../../node_modules/simple-git/dist/esm/index.js
3803
4465
  var import_file_exists = __toESM(require_dist(), 1);
3804
4466
  var import_debug = __toESM(require_src(), 1);
@@ -3836,8 +4498,8 @@ function pathspec(...paths) {
3836
4498
  cache.set(key, paths);
3837
4499
  return key;
3838
4500
  }
3839
- function isPathSpec(path17) {
3840
- return path17 instanceof String && cache.has(path17);
4501
+ function isPathSpec(path18) {
4502
+ return path18 instanceof String && cache.has(path18);
3841
4503
  }
3842
4504
  function toPaths(pathSpec) {
3843
4505
  return cache.get(pathSpec) || [];
@@ -3926,8 +4588,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
3926
4588
  function forEachLineWithContent(input, callback) {
3927
4589
  return toLinesWithContent(input, true).map((line) => callback(line));
3928
4590
  }
3929
- function folderExists(path17) {
3930
- return (0, import_file_exists.exists)(path17, import_file_exists.FOLDER);
4591
+ function folderExists(path18) {
4592
+ return (0, import_file_exists.exists)(path18, import_file_exists.FOLDER);
3931
4593
  }
3932
4594
  function append(target, item) {
3933
4595
  if (Array.isArray(target)) {
@@ -4331,8 +4993,8 @@ function checkIsRepoRootTask() {
4331
4993
  commands,
4332
4994
  format: "utf-8",
4333
4995
  onError,
4334
- parser(path17) {
4335
- return /^\.(git)?$/.test(path17.trim());
4996
+ parser(path18) {
4997
+ return /^\.(git)?$/.test(path18.trim());
4336
4998
  }
4337
4999
  };
4338
5000
  }
@@ -4766,11 +5428,11 @@ function parseGrep(grep) {
4766
5428
  const paths = /* @__PURE__ */ new Set();
4767
5429
  const results = {};
4768
5430
  forEachLineWithContent(grep, (input) => {
4769
- const [path17, line, preview] = input.split(NULL);
4770
- paths.add(path17);
4771
- (results[path17] = results[path17] || []).push({
5431
+ const [path18, line, preview] = input.split(NULL);
5432
+ paths.add(path18);
5433
+ (results[path18] = results[path18] || []).push({
4772
5434
  line: asNumber(line),
4773
- path: path17,
5435
+ path: path18,
4774
5436
  preview
4775
5437
  });
4776
5438
  });
@@ -5535,14 +6197,14 @@ var init_hash_object = __esm({
5535
6197
  init_task();
5536
6198
  }
5537
6199
  });
5538
- function parseInit(bare, path17, text2) {
6200
+ function parseInit(bare, path18, text2) {
5539
6201
  const response = String(text2).trim();
5540
6202
  let result;
5541
6203
  if (result = initResponseRegex.exec(response)) {
5542
- return new InitSummary(bare, path17, false, result[1]);
6204
+ return new InitSummary(bare, path18, false, result[1]);
5543
6205
  }
5544
6206
  if (result = reInitResponseRegex.exec(response)) {
5545
- return new InitSummary(bare, path17, true, result[1]);
6207
+ return new InitSummary(bare, path18, true, result[1]);
5546
6208
  }
5547
6209
  let gitDir = "";
5548
6210
  const tokens = response.split(" ");
@@ -5553,7 +6215,7 @@ function parseInit(bare, path17, text2) {
5553
6215
  break;
5554
6216
  }
5555
6217
  }
5556
- return new InitSummary(bare, path17, /^re/i.test(response), gitDir);
6218
+ return new InitSummary(bare, path18, /^re/i.test(response), gitDir);
5557
6219
  }
5558
6220
  var InitSummary;
5559
6221
  var initResponseRegex;
@@ -5562,9 +6224,9 @@ var init_InitSummary = __esm({
5562
6224
  "src/lib/responses/InitSummary.ts"() {
5563
6225
  "use strict";
5564
6226
  InitSummary = class {
5565
- constructor(bare, path17, existing, gitDir) {
6227
+ constructor(bare, path18, existing, gitDir) {
5566
6228
  this.bare = bare;
5567
- this.path = path17;
6229
+ this.path = path18;
5568
6230
  this.existing = existing;
5569
6231
  this.gitDir = gitDir;
5570
6232
  }
@@ -5576,7 +6238,7 @@ var init_InitSummary = __esm({
5576
6238
  function hasBareCommand(command) {
5577
6239
  return command.includes(bareCommand);
5578
6240
  }
5579
- function initTask(bare = false, path17, customArgs) {
6241
+ function initTask(bare = false, path18, customArgs) {
5580
6242
  const commands = ["init", ...customArgs];
5581
6243
  if (bare && !hasBareCommand(commands)) {
5582
6244
  commands.splice(1, 0, bareCommand);
@@ -5585,7 +6247,7 @@ function initTask(bare = false, path17, customArgs) {
5585
6247
  commands,
5586
6248
  format: "utf-8",
5587
6249
  parser(text2) {
5588
- return parseInit(commands.includes("--bare"), path17, text2);
6250
+ return parseInit(commands.includes("--bare"), path18, text2);
5589
6251
  }
5590
6252
  };
5591
6253
  }
@@ -6401,12 +7063,12 @@ var init_FileStatusSummary = __esm({
6401
7063
  "use strict";
6402
7064
  fromPathRegex = /^(.+)\0(.+)$/;
6403
7065
  FileStatusSummary = class {
6404
- constructor(path17, index, working_dir) {
6405
- this.path = path17;
7066
+ constructor(path18, index, working_dir) {
7067
+ this.path = path18;
6406
7068
  this.index = index;
6407
7069
  this.working_dir = working_dir;
6408
7070
  if (index === "R" || working_dir === "R") {
6409
- const detail = fromPathRegex.exec(path17) || [null, path17, path17];
7071
+ const detail = fromPathRegex.exec(path18) || [null, path18, path18];
6410
7072
  this.from = detail[2] || "";
6411
7073
  this.path = detail[1] || "";
6412
7074
  }
@@ -6437,14 +7099,14 @@ function splitLine(result, lineStr) {
6437
7099
  default:
6438
7100
  return;
6439
7101
  }
6440
- function data(index, workingDir, path17) {
7102
+ function data(index, workingDir, path18) {
6441
7103
  const raw = `${index}${workingDir}`;
6442
7104
  const handler = parsers6.get(raw);
6443
7105
  if (handler) {
6444
- handler(result, path17);
7106
+ handler(result, path18);
6445
7107
  }
6446
7108
  if (raw !== "##" && raw !== "!!") {
6447
- result.files.push(new FileStatusSummary(path17, index, workingDir));
7109
+ result.files.push(new FileStatusSummary(path18, index, workingDir));
6448
7110
  }
6449
7111
  }
6450
7112
  }
@@ -6757,9 +7419,9 @@ var init_simple_git_api = __esm({
6757
7419
  next
6758
7420
  );
6759
7421
  }
6760
- hashObject(path17, write) {
7422
+ hashObject(path18, write) {
6761
7423
  return this._runTask(
6762
- hashObjectTask(path17, write === true),
7424
+ hashObjectTask(path18, write === true),
6763
7425
  trailingFunctionArgument(arguments)
6764
7426
  );
6765
7427
  }
@@ -7112,8 +7774,8 @@ var init_branch = __esm({
7112
7774
  }
7113
7775
  });
7114
7776
  function toPath(input) {
7115
- const path17 = input.trim().replace(/^["']|["']$/g, "");
7116
- return path17 && normalize(path17);
7777
+ const path18 = input.trim().replace(/^["']|["']$/g, "");
7778
+ return path18 && normalize(path18);
7117
7779
  }
7118
7780
  var parseCheckIgnore;
7119
7781
  var init_CheckIgnore = __esm({
@@ -7427,8 +8089,8 @@ __export(sub_module_exports, {
7427
8089
  subModuleTask: () => subModuleTask,
7428
8090
  updateSubModuleTask: () => updateSubModuleTask
7429
8091
  });
7430
- function addSubModuleTask(repo, path17) {
7431
- return subModuleTask(["add", repo, path17]);
8092
+ function addSubModuleTask(repo, path18) {
8093
+ return subModuleTask(["add", repo, path18]);
7432
8094
  }
7433
8095
  function initSubModuleTask(customArgs) {
7434
8096
  return subModuleTask(["init", ...customArgs]);
@@ -7758,8 +8420,8 @@ var require_git = __commonJS2({
7758
8420
  }
7759
8421
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
7760
8422
  };
7761
- Git2.prototype.submoduleAdd = function(repo, path17, then) {
7762
- return this._runTask(addSubModuleTask2(repo, path17), trailingFunctionArgument2(arguments));
8423
+ Git2.prototype.submoduleAdd = function(repo, path18, then) {
8424
+ return this._runTask(addSubModuleTask2(repo, path18), trailingFunctionArgument2(arguments));
7763
8425
  };
7764
8426
  Git2.prototype.submoduleUpdate = function(args2, then) {
7765
8427
  return this._runTask(
@@ -8420,10 +9082,10 @@ var AsyncReaderWriterLock = class {
8420
9082
  this.readers++;
8421
9083
  return;
8422
9084
  }
8423
- return new Promise((resolve7) => {
9085
+ return new Promise((resolve8) => {
8424
9086
  this.readQueue.push(() => {
8425
9087
  this.readers++;
8426
- resolve7();
9088
+ resolve8();
8427
9089
  });
8428
9090
  });
8429
9091
  }
@@ -8437,11 +9099,11 @@ var AsyncReaderWriterLock = class {
8437
9099
  return;
8438
9100
  }
8439
9101
  this.writerWaiting = true;
8440
- return new Promise((resolve7) => {
9102
+ return new Promise((resolve8) => {
8441
9103
  this.writeQueue.push(() => {
8442
9104
  this.writerWaiting = this.writeQueue.length > 0;
8443
9105
  this.writer = true;
8444
- resolve7();
9106
+ resolve8();
8445
9107
  });
8446
9108
  });
8447
9109
  }
@@ -8648,12 +9310,12 @@ async function inspectGitBusyState(git) {
8648
9310
 
8649
9311
  // src/server/agent-server.ts
8650
9312
  import { Hono } from "hono";
8651
- import { z as z4 } from "zod";
9313
+ import { z as z5 } from "zod";
8652
9314
 
8653
9315
  // package.json
8654
9316
  var package_default = {
8655
9317
  name: "@posthog/agent",
8656
- version: "2.3.643",
9318
+ version: "2.3.655",
8657
9319
  repository: "https://github.com/PostHog/code",
8658
9320
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
8659
9321
  exports: {
@@ -8925,17 +9587,17 @@ var Pushable = class {
8925
9587
  resolvers = [];
8926
9588
  done = false;
8927
9589
  push(item) {
8928
- const resolve7 = this.resolvers.shift();
8929
- if (resolve7) {
8930
- resolve7({ value: item, done: false });
9590
+ const resolve8 = this.resolvers.shift();
9591
+ if (resolve8) {
9592
+ resolve8({ value: item, done: false });
8931
9593
  } else {
8932
9594
  this.queue.push(item);
8933
9595
  }
8934
9596
  }
8935
9597
  end() {
8936
9598
  this.done = true;
8937
- for (const resolve7 of this.resolvers) {
8938
- resolve7({ value: void 0, done: true });
9599
+ for (const resolve8 of this.resolvers) {
9600
+ resolve8({ value: void 0, done: true });
8939
9601
  }
8940
9602
  this.resolvers = [];
8941
9603
  }
@@ -8952,8 +9614,8 @@ var Pushable = class {
8952
9614
  done: true
8953
9615
  });
8954
9616
  }
8955
- return new Promise((resolve7) => {
8956
- this.resolvers.push(resolve7);
9617
+ return new Promise((resolve8) => {
9618
+ this.resolvers.push(resolve8);
8957
9619
  });
8958
9620
  }
8959
9621
  };
@@ -9067,20 +9729,20 @@ function nodeReadableToWebReadable(nodeStream) {
9067
9729
  function nodeWritableToWebWritable(nodeStream) {
9068
9730
  return new WritableStream2({
9069
9731
  write(chunk) {
9070
- return new Promise((resolve7, reject) => {
9732
+ return new Promise((resolve8, reject) => {
9071
9733
  const ok = nodeStream.write(Buffer.from(chunk), (err2) => {
9072
9734
  if (err2) reject(err2);
9073
9735
  });
9074
9736
  if (ok) {
9075
- resolve7();
9737
+ resolve8();
9076
9738
  } else {
9077
- nodeStream.once("drain", resolve7);
9739
+ nodeStream.once("drain", resolve8);
9078
9740
  }
9079
9741
  });
9080
9742
  },
9081
9743
  close() {
9082
- return new Promise((resolve7) => {
9083
- nodeStream.end(resolve7);
9744
+ return new Promise((resolve8) => {
9745
+ nodeStream.end(resolve8);
9084
9746
  });
9085
9747
  },
9086
9748
  abort(reason) {
@@ -9093,9 +9755,9 @@ function nodeWritableToWebWritable(nodeStream) {
9093
9755
 
9094
9756
  // src/adapters/claude/claude-agent.ts
9095
9757
  import { randomUUID } from "crypto";
9096
- import * as fs9 from "fs";
9097
- import * as os5 from "os";
9098
- import * as path11 from "path";
9758
+ import * as fs10 from "fs";
9759
+ import * as os6 from "os";
9760
+ import * as path12 from "path";
9099
9761
  import {
9100
9762
  RequestError as RequestError2
9101
9763
  } from "@agentclientprotocol/sdk";
@@ -13238,10 +13900,360 @@ async function buildWrapperContext(deps, content, langId, absPath) {
13238
13900
  return { wrappersByLocalName, namespaceWrappers };
13239
13901
  }
13240
13902
 
13903
+ // ../git/dist/signed-commit.js
13904
+ import * as childProcess3 from "child_process";
13905
+
13906
+ // ../git/dist/gh.js
13907
+ import * as childProcess from "child_process";
13908
+ function execGh(args2, options = {}) {
13909
+ const env = options.env ? { ...process.env, ...options.env } : process.env;
13910
+ return new Promise((resolve8) => {
13911
+ const child = childProcess.execFile("gh", args2, { cwd: options.cwd, env, timeout: options.timeoutMs ?? 0 }, (error, stdout, stderr) => {
13912
+ if (!error) {
13913
+ resolve8({ stdout, stderr, exitCode: 0 });
13914
+ return;
13915
+ }
13916
+ const err2 = error;
13917
+ const timedOut = err2.killed === true && !!options.timeoutMs;
13918
+ const exitCode = typeof err2.code === "number" ? err2.code : err2.code === "ENOENT" ? 127 : 1;
13919
+ resolve8({
13920
+ stdout: stdout ?? err2.stdout ?? "",
13921
+ stderr: stderr ?? err2.stderr ?? "",
13922
+ exitCode,
13923
+ error: timedOut ? `gh timed out after ${options.timeoutMs}ms` : err2.message
13924
+ });
13925
+ });
13926
+ if (options.input !== void 0) {
13927
+ child.stdin?.end(options.input);
13928
+ }
13929
+ });
13930
+ }
13931
+ var TRANSIENT_GH_PATTERNS = [
13932
+ /HTTP 5\d\d/,
13933
+ /HTTP 499/,
13934
+ /\btimed out\b/i,
13935
+ /\bETIMEDOUT\b/,
13936
+ /\bECONNRESET\b/,
13937
+ /\bECONNREFUSED\b/,
13938
+ /\bEAI_AGAIN\b/,
13939
+ /connection reset/i
13940
+ ];
13941
+ function isTransientGhFailure(res) {
13942
+ if (res.exitCode === 0) {
13943
+ return false;
13944
+ }
13945
+ const text2 = `${res.stderr} ${res.error ?? ""} ${res.stdout}`;
13946
+ return TRANSIENT_GH_PATTERNS.some((re) => re.test(text2));
13947
+ }
13948
+ var sleep = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
13949
+ async function execGhWithRetry(args2, options = {}, retry = {}, exec = execGh) {
13950
+ const maxAttempts = retry.maxAttempts ?? 3;
13951
+ const backoffMs = retry.backoffMs ?? 500;
13952
+ let res = await exec(args2, options);
13953
+ for (let attempt = 2; attempt <= maxAttempts && isTransientGhFailure(res); attempt++) {
13954
+ await sleep(backoffMs * 2 ** (attempt - 2));
13955
+ res = await exec(args2, options);
13956
+ }
13957
+ return res;
13958
+ }
13959
+
13960
+ // ../git/dist/trailers.js
13961
+ function buildPostHogTrailers(taskId) {
13962
+ const trailers = ["Generated-By: PostHog Code"];
13963
+ if (taskId)
13964
+ trailers.push(`Task-Id: ${taskId}`);
13965
+ return trailers;
13966
+ }
13967
+
13968
+ // ../git/dist/utils.js
13969
+ var import_git_url_parse = __toESM(require_lib5(), 1);
13970
+ import * as childProcess2 from "child_process";
13971
+ import * as fs5 from "fs/promises";
13972
+ import * as os from "os";
13973
+ import * as path5 from "path";
13974
+ function parseGithubUrl(url) {
13975
+ if (!url)
13976
+ return null;
13977
+ let parsed;
13978
+ try {
13979
+ parsed = (0, import_git_url_parse.default)(url.trim());
13980
+ } catch {
13981
+ return null;
13982
+ }
13983
+ const resource = parsed.resource.toLowerCase();
13984
+ if (resource !== "github.com" && resource !== "ssh.github.com")
13985
+ return null;
13986
+ const raw = parsed.pathname.split("/");
13987
+ if (raw[0] !== "")
13988
+ return null;
13989
+ const parts2 = raw[raw.length - 1] === "" ? raw.slice(1, -1) : raw.slice(1);
13990
+ if (parts2.length < 2 || parts2.some((p) => p === ""))
13991
+ return null;
13992
+ const [owner, repoRaw, segment, num] = parts2;
13993
+ const repo = repoRaw.replace(/\.git$/, "");
13994
+ if (segment === "issues" || segment === "pull") {
13995
+ const number = Number(num);
13996
+ if (!Number.isInteger(number) || number <= 0)
13997
+ return null;
13998
+ return {
13999
+ kind: segment === "pull" ? "pr" : "issue",
14000
+ owner,
14001
+ repo,
14002
+ number
14003
+ };
14004
+ }
14005
+ return { kind: "repo", owner, repo };
14006
+ }
14007
+
14008
+ // ../git/dist/signed-commit.js
14009
+ var DEFAULT_MAX_PAYLOAD_BYTES = 35 * 1024 * 1024;
14010
+ var MAX_GIT_BUFFER = 256 * 1024 * 1024;
14011
+ var GH_GRAPHQL_TIMEOUT_MS = 3e4;
14012
+ var OversizedFileError = class extends Error {
14013
+ path;
14014
+ bytes;
14015
+ maxBytes;
14016
+ constructor(path18, bytes, maxBytes) {
14017
+ super(`File '${path18}' (~${Math.round(bytes / 1024 / 1024)}MB once base64-encoded) exceeds the per-commit request limit (~${Math.round(maxBytes / 1024 / 1024)}MB). A single file cannot be split across createCommitOnBranch requests; use Git LFS or a local signing key for this change.`);
14018
+ this.path = path18;
14019
+ this.bytes = bytes;
14020
+ this.maxBytes = maxBytes;
14021
+ this.name = "OversizedFileError";
14022
+ }
14023
+ };
14024
+ function runGit(args2, cwd) {
14025
+ return new Promise((resolve8) => {
14026
+ childProcess3.execFile("git", args2, { cwd, maxBuffer: MAX_GIT_BUFFER, encoding: "buffer" }, (error, stdout, stderr) => {
14027
+ const err2 = error;
14028
+ const exitCode = err2 && typeof err2.code === "number" ? err2.code : err2 ? 1 : 0;
14029
+ resolve8({
14030
+ stdout: stdout ?? Buffer.alloc(0),
14031
+ stderr: (stderr ?? Buffer.alloc(0)).toString("utf8"),
14032
+ exitCode
14033
+ });
14034
+ });
14035
+ });
14036
+ }
14037
+ async function gitText(args2, cwd) {
14038
+ const r = await runGit(args2, cwd);
14039
+ if (r.exitCode !== 0) {
14040
+ throw new Error(`git ${args2.join(" ")} failed: ${r.stderr.trim()}`);
14041
+ }
14042
+ return r.stdout.toString("utf8").trim();
14043
+ }
14044
+ async function resolveRepoNameWithOwner(ctx) {
14045
+ const url = await gitText(["remote", "get-url", "origin"], ctx.cwd);
14046
+ const parsed = parseGithubUrl(url);
14047
+ if (!parsed) {
14048
+ throw new Error(`Could not parse owner/repo from origin remote: ${url}`);
14049
+ }
14050
+ return `${parsed.owner}/${parsed.repo}`;
14051
+ }
14052
+ async function resolveBaseBranch(ctx) {
14053
+ if (ctx.baseBranch)
14054
+ return ctx.baseBranch;
14055
+ const r = await runGit(["symbolic-ref", "--short", "refs/remotes/origin/HEAD"], ctx.cwd);
14056
+ if (r.exitCode !== 0)
14057
+ return null;
14058
+ return r.stdout.toString("utf8").trim().replace(/^origin\//, "") || null;
14059
+ }
14060
+ async function resolveBranchName(ctx, input) {
14061
+ const branch = input.branch ? input.branch.replace(/^refs\/heads\//, "") : await resolveCurrentBranch(ctx);
14062
+ const baseBranch = await resolveBaseBranch(ctx);
14063
+ if (baseBranch && branch === baseBranch) {
14064
+ throw new Error(`Refusing to commit directly to base branch '${baseBranch}'. Pass a 'branch' name prefixed with posthog-code/.`);
14065
+ }
14066
+ return branch;
14067
+ }
14068
+ async function resolveCurrentBranch(ctx) {
14069
+ const current2 = await gitText(["rev-parse", "--abbrev-ref", "HEAD"], ctx.cwd);
14070
+ if (!current2 || current2 === "HEAD") {
14071
+ throw new Error("Detached HEAD \u2014 pass a `branch` to git_signed_commit (e.g. posthog-code/...).");
14072
+ }
14073
+ return current2;
14074
+ }
14075
+ async function remoteTip(ctx, branch) {
14076
+ const out2 = await gitText(["ls-remote", "--heads", "origin", branch], ctx.cwd);
14077
+ if (!out2)
14078
+ return null;
14079
+ return out2.split(" ")[0]?.trim() || null;
14080
+ }
14081
+ async function createRef(ctx, repo, branch, sha) {
14082
+ const res = await execGh([
14083
+ "api",
14084
+ "-X",
14085
+ "POST",
14086
+ `/repos/${repo}/git/refs`,
14087
+ "-f",
14088
+ `ref=refs/heads/${branch}`,
14089
+ "-f",
14090
+ `sha=${sha}`
14091
+ ], { cwd: ctx.cwd, env: ghTokenEnv(ctx.token) });
14092
+ if (res.exitCode !== 0) {
14093
+ throw new Error(`Failed to create branch '${branch}': ${res.stderr || res.error}`);
14094
+ }
14095
+ }
14096
+ var GITHUB_TOKEN_ENV_VARS = ["GH_TOKEN", "GITHUB_TOKEN"];
14097
+ function readGithubTokenFromEnv(env = process.env) {
14098
+ for (const name2 of GITHUB_TOKEN_ENV_VARS) {
14099
+ if (env[name2])
14100
+ return env[name2];
14101
+ }
14102
+ return void 0;
14103
+ }
14104
+ function ghTokenEnv(token) {
14105
+ return Object.fromEntries(GITHUB_TOKEN_ENV_VARS.map((name2) => [name2, token]));
14106
+ }
14107
+ var STAGED_READ_CONCURRENCY = 16;
14108
+ async function buildFileChanges(ctx, baseOid) {
14109
+ const diff = await runGit(["diff", "--cached", "-z", "--no-renames", "--name-status", baseOid], ctx.cwd);
14110
+ if (diff.exitCode !== 0) {
14111
+ throw new Error(`git diff --cached failed: ${diff.stderr.trim()}`);
14112
+ }
14113
+ const tokens = diff.stdout.toString("utf8").split("\0").filter(Boolean);
14114
+ const addPaths = [];
14115
+ const deletions = [];
14116
+ for (let i2 = 0; i2 + 1 < tokens.length; i2 += 2) {
14117
+ const path18 = tokens[i2 + 1];
14118
+ if (tokens[i2].startsWith("D")) {
14119
+ deletions.push({ path: path18 });
14120
+ } else {
14121
+ addPaths.push(path18);
14122
+ }
14123
+ }
14124
+ const additions = await mapWithConcurrency(addPaths, STAGED_READ_CONCURRENCY, async (path18) => {
14125
+ const r = await runGit(["show", `:${path18}`], ctx.cwd);
14126
+ if (r.exitCode !== 0) {
14127
+ throw new Error(`Failed to read staged file '${path18}': ${r.stderr.trim()}`);
14128
+ }
14129
+ return { path: path18, contents: r.stdout.toString("base64") };
14130
+ });
14131
+ return { additions, deletions };
14132
+ }
14133
+ function additionBytes(a) {
14134
+ return a.contents.length + a.path.length + 32;
14135
+ }
14136
+ function chunkFileChanges(changes, maxBytes) {
14137
+ for (const a of changes.additions) {
14138
+ const bytes = additionBytes(a);
14139
+ if (bytes > maxBytes)
14140
+ throw new OversizedFileError(a.path, bytes, maxBytes);
14141
+ }
14142
+ if (changes.additions.length === 0) {
14143
+ return [{ additions: [], deletions: changes.deletions }];
14144
+ }
14145
+ const chunks = [];
14146
+ let cur = { additions: [], deletions: [...changes.deletions] };
14147
+ let curBytes = changes.deletions.reduce((n, d) => n + d.path.length + 16, 0);
14148
+ for (const a of changes.additions) {
14149
+ const bytes = additionBytes(a);
14150
+ if (cur.additions.length > 0 && curBytes + bytes > maxBytes) {
14151
+ chunks.push(cur);
14152
+ cur = { additions: [], deletions: [] };
14153
+ curBytes = 0;
14154
+ }
14155
+ cur.additions.push(a);
14156
+ curBytes += bytes;
14157
+ }
14158
+ chunks.push(cur);
14159
+ return chunks;
14160
+ }
14161
+ var CREATE_COMMIT_MUTATION = `mutation($input: CreateCommitOnBranchInput!) {
14162
+ createCommitOnBranch(input: $input) { commit { oid url } }
14163
+ }`;
14164
+ async function createCommitOnBranch(ctx, repo, branch, expectedHeadOid, headline, body2, changes) {
14165
+ const payload = JSON.stringify({
14166
+ query: CREATE_COMMIT_MUTATION,
14167
+ variables: {
14168
+ input: {
14169
+ branch: { repositoryNameWithOwner: repo, branchName: branch },
14170
+ expectedHeadOid,
14171
+ message: { headline, body: body2 },
14172
+ fileChanges: changes
14173
+ }
14174
+ }
14175
+ });
14176
+ const res = await execGhWithRetry(["api", "graphql", "--input", "-"], {
14177
+ cwd: ctx.cwd,
14178
+ input: payload,
14179
+ env: ghTokenEnv(ctx.token),
14180
+ // Bound each attempt so a stalled connection can't hang the tool forever.
14181
+ timeoutMs: GH_GRAPHQL_TIMEOUT_MS
14182
+ }, { maxAttempts: 3 });
14183
+ if (res.exitCode !== 0) {
14184
+ throw new Error(`createCommitOnBranch failed: ${res.stderr || res.error || res.stdout}`);
14185
+ }
14186
+ let parsed;
14187
+ try {
14188
+ parsed = JSON.parse(res.stdout);
14189
+ } catch {
14190
+ throw new Error(`createCommitOnBranch returned non-JSON: ${res.stdout.slice(0, 500)}`);
14191
+ }
14192
+ if (parsed.errors) {
14193
+ throw new Error(`createCommitOnBranch errors: ${JSON.stringify(parsed.errors)}`);
14194
+ }
14195
+ const commit = parsed.data?.createCommitOnBranch?.commit;
14196
+ if (!commit?.oid) {
14197
+ throw new Error(`createCommitOnBranch returned no commit: ${res.stdout}`);
14198
+ }
14199
+ return commit;
14200
+ }
14201
+ async function syncLocalCheckout(ctx, branch, newOid) {
14202
+ const steps = [
14203
+ ["fetch", ["fetch", "--no-tags", "origin", branch]],
14204
+ ["update-ref", ["update-ref", `refs/heads/${branch}`, newOid]],
14205
+ ["symbolic-ref", ["symbolic-ref", "HEAD", `refs/heads/${branch}`]],
14206
+ ["reset", ["reset", "-q"]]
14207
+ ];
14208
+ for (const [label, args2] of steps) {
14209
+ const r = await runGit(args2, ctx.cwd);
14210
+ if (r.exitCode !== 0) {
14211
+ process.stderr.write(`[signed-commit] local sync step '${label}' failed after committing ${newOid}: ${r.stderr.trim()}
14212
+ `);
14213
+ }
14214
+ }
14215
+ }
14216
+ async function createSignedCommit(ctx, input) {
14217
+ const [repo, branch] = await Promise.all([
14218
+ resolveRepoNameWithOwner(ctx),
14219
+ resolveBranchName(ctx, input)
14220
+ ]);
14221
+ if (input.paths && input.paths.length > 0) {
14222
+ const r = await runGit(["add", "--", ...input.paths], ctx.cwd);
14223
+ if (r.exitCode !== 0) {
14224
+ throw new Error(`git add failed: ${r.stderr.trim()}`);
14225
+ }
14226
+ }
14227
+ let tip = await remoteTip(ctx, branch);
14228
+ if (tip === null) {
14229
+ const baseSha = await gitText(["rev-parse", "HEAD"], ctx.cwd);
14230
+ await createRef(ctx, repo, branch, baseSha);
14231
+ tip = baseSha;
14232
+ } else {
14233
+ await runGit(["fetch", "--no-tags", "origin", branch], ctx.cwd);
14234
+ }
14235
+ const changes = await buildFileChanges(ctx, tip);
14236
+ if (changes.additions.length === 0 && changes.deletions.length === 0) {
14237
+ throw new Error("No staged changes to commit. Stage files with `git add` first (or pass `paths`).");
14238
+ }
14239
+ const chunks = chunkFileChanges(changes, DEFAULT_MAX_PAYLOAD_BYTES);
14240
+ const body2 = [input.body, buildPostHogTrailers(ctx.taskId).join("\n")].filter(Boolean).join("\n\n");
14241
+ const commits = [];
14242
+ let expectedHeadOid = tip;
14243
+ for (let i2 = 0; i2 < chunks.length; i2++) {
14244
+ const headline = chunks.length > 1 ? `${input.message} \u2014 part ${i2 + 1}/${chunks.length}` : input.message;
14245
+ const commit = await createCommitOnBranch(ctx, repo, branch, expectedHeadOid, headline, body2, chunks[i2]);
14246
+ commits.push({ sha: commit.oid, url: commit.url });
14247
+ expectedHeadOid = commit.oid;
14248
+ }
14249
+ await syncLocalCheckout(ctx, branch, expectedHeadOid);
14250
+ return { branch, commits };
14251
+ }
14252
+
13241
14253
  // src/utils/common.ts
13242
14254
  async function withTimeout(operation, timeoutMs) {
13243
14255
  const timeoutPromise = new Promise(
13244
- (resolve7) => setTimeout(() => resolve7({ result: "timeout" }), timeoutMs)
14256
+ (resolve8) => setTimeout(() => resolve8({ result: "timeout" }), timeoutMs)
13245
14257
  );
13246
14258
  const operationPromise = operation.then((value) => ({
13247
14259
  result: "success",
@@ -13251,6 +14263,12 @@ async function withTimeout(operation, timeoutMs) {
13251
14263
  }
13252
14264
  var IS_ROOT = typeof process !== "undefined" && (process.geteuid?.() ?? process.getuid?.()) === 0;
13253
14265
  var ALLOW_BYPASS = !IS_ROOT || !!process.env.IS_SANDBOX;
14266
+ function isCloudRun(meta) {
14267
+ return !!process.env.IS_SANDBOX || !!meta?.taskRunId;
14268
+ }
14269
+ function resolveGithubToken() {
14270
+ return readGithubTokenFromEnv();
14271
+ }
13254
14272
  function unreachable(value, logger) {
13255
14273
  let valueAsString;
13256
14274
  try {
@@ -13408,8 +14426,82 @@ var BaseAcpAgent = class {
13408
14426
  }
13409
14427
  };
13410
14428
 
14429
+ // src/adapters/signed-commit-shared.ts
14430
+ import { z } from "zod";
14431
+
14432
+ // src/adapters/local-tools/registry.ts
14433
+ var LOCAL_TOOLS_MCP_NAME = "posthog-local";
14434
+ function defineLocalTool(def) {
14435
+ return def;
14436
+ }
14437
+ function qualifiedLocalToolName(toolName) {
14438
+ return `mcp__${LOCAL_TOOLS_MCP_NAME}__${toolName}`;
14439
+ }
14440
+
14441
+ // src/adapters/signed-commit-shared.ts
14442
+ var SIGNED_COMMIT_TOOL_NAME = "git_signed_commit";
14443
+ var SIGNED_COMMIT_QUALIFIED_TOOL_NAME = qualifiedLocalToolName(
14444
+ SIGNED_COMMIT_TOOL_NAME
14445
+ );
14446
+ var SIGNED_COMMIT_TOOL_DESCRIPTION = "Create a GitHub-signed (Verified) commit on the branch. Stage files with `git add` first (or pass `paths`), then call this instead of `git commit`/`git push` \u2014 those are blocked because all commits must be signed. The commit is created via GitHub's API and your local checkout is kept in sync. For a new branch, pass `branch` (prefixed with `posthog-code/`) and the tool creates it on the remote.";
14447
+ var signedCommitToolSchema = {
14448
+ message: z.string().describe("Commit headline (first line)."),
14449
+ body: z.string().optional().describe("Optional extended commit body."),
14450
+ branch: z.string().optional().describe(
14451
+ "Target branch; defaults to the current branch. Use a posthog-code/ prefix for new branches."
14452
+ ),
14453
+ paths: z.array(z.string()).optional().describe(
14454
+ "Files to stage before committing; defaults to already-staged files."
14455
+ )
14456
+ };
14457
+ function formatSignedCommitResult(result) {
14458
+ const list = result.commits.map((c) => `- ${c.sha} ${c.url}`).join("\n");
14459
+ return `Created ${result.commits.length} signed commit(s) on ${result.branch}:
14460
+ ${list}`;
14461
+ }
14462
+ async function runSignedCommitTool(ctx, args2) {
14463
+ try {
14464
+ const result = await createSignedCommit(ctx, args2);
14465
+ return {
14466
+ content: [{ type: "text", text: formatSignedCommitResult(result) }]
14467
+ };
14468
+ } catch (err2) {
14469
+ const message = err2 instanceof Error ? err2.message : String(err2);
14470
+ return {
14471
+ content: [
14472
+ { type: "text", text: `${SIGNED_COMMIT_TOOL_NAME} failed: ${message}` }
14473
+ ],
14474
+ isError: true
14475
+ };
14476
+ }
14477
+ }
14478
+
14479
+ // src/adapters/local-tools/tools/signed-commit.ts
14480
+ var signedCommitTool = defineLocalTool({
14481
+ name: SIGNED_COMMIT_TOOL_NAME,
14482
+ description: SIGNED_COMMIT_TOOL_DESCRIPTION,
14483
+ schema: signedCommitToolSchema,
14484
+ alwaysLoad: true,
14485
+ isEnabled: (ctx, meta) => isCloudRun(meta) && !!ctx.token,
14486
+ handler: (ctx, args2) => runSignedCommitTool(
14487
+ { cwd: ctx.cwd, token: ctx.token ?? "", taskId: ctx.taskId },
14488
+ args2
14489
+ )
14490
+ });
14491
+
14492
+ // src/adapters/local-tools/index.ts
14493
+ var LOCAL_TOOLS = [signedCommitTool];
14494
+ function enabledLocalTools(ctx, meta) {
14495
+ return LOCAL_TOOLS.filter((t) => t.isEnabled(ctx, meta));
14496
+ }
14497
+
14498
+ // src/adapters/session-meta.ts
14499
+ function resolveTaskId(meta) {
14500
+ return meta?.taskId ?? meta?.persistence?.taskId;
14501
+ }
14502
+
13411
14503
  // src/adapters/claude/conversion/acp-to-sdk.ts
13412
- import * as path5 from "path";
14504
+ import * as path6 from "path";
13413
14505
  import { fileURLToPath as fileURLToPath2 } from "url";
13414
14506
  var PDF_EXTENSIONS = /* @__PURE__ */ new Set(["pdf"]);
13415
14507
  var COMMON_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -13439,7 +14531,7 @@ function sdkText(value) {
13439
14531
  function formatUriAsLink(uri) {
13440
14532
  try {
13441
14533
  if (uri.startsWith("zed://")) {
13442
- const name2 = path5.basename(uri) || uri;
14534
+ const name2 = path6.basename(uri) || uri;
13443
14535
  return `[@${name2}](${uri})`;
13444
14536
  }
13445
14537
  return uri;
@@ -13448,7 +14540,7 @@ function formatUriAsLink(uri) {
13448
14540
  }
13449
14541
  }
13450
14542
  function readToolGuidanceForPath(filePath) {
13451
- const ext = path5.extname(filePath).slice(1).toLowerCase();
14543
+ const ext = path6.extname(filePath).slice(1).toLowerCase();
13452
14544
  if (PDF_EXTENSIONS.has(ext)) {
13453
14545
  return 'Optional `pages` string (e.g. "1-5") per Read call instead of loading the entire PDF.';
13454
14546
  }
@@ -13460,7 +14552,7 @@ function readToolGuidanceForPath(filePath) {
13460
14552
  function workspacePromptFromFileUri(uri) {
13461
14553
  try {
13462
14554
  const filePath = fileURLToPath2(uri);
13463
- const name2 = path5.basename(filePath) || filePath;
14555
+ const name2 = path6.basename(filePath) || filePath;
13464
14556
  return [
13465
14557
  "Attached workspace file \u2014 use Read with required `file_path`:",
13466
14558
  `- file_path: ${filePath}`,
@@ -13586,8 +14678,8 @@ var ToolContentBuilder = class {
13586
14678
  this.items.push({ type: "content", content: image(data, mimeType, uri) });
13587
14679
  return this;
13588
14680
  }
13589
- diff(path17, oldText, newText) {
13590
- this.items.push({ type: "diff", path: path17, oldText, newText });
14681
+ diff(path18, oldText, newText) {
14682
+ this.items.push({ type: "diff", path: path18, oldText, newText });
13591
14683
  return this;
13592
14684
  }
13593
14685
  build() {
@@ -13806,6 +14898,60 @@ var createSubagentRewriteHook = (logger, registeredAgents) => async (input, _too
13806
14898
  }
13807
14899
  };
13808
14900
  };
14901
+ var GIT_VALUE_FLAGS = /* @__PURE__ */ new Set([
14902
+ "-C",
14903
+ "-c",
14904
+ "--git-dir",
14905
+ "--work-tree",
14906
+ "--namespace",
14907
+ "--exec-path"
14908
+ ]);
14909
+ function gitSubcommand(segment) {
14910
+ const tokens = segment.trim().split(/\s+/).filter(Boolean);
14911
+ if (tokens.length === 0) return null;
14912
+ const head = tokens[0].split("/").pop();
14913
+ if (head !== "git") return null;
14914
+ let skipNext = false;
14915
+ for (const tok of tokens.slice(1)) {
14916
+ if (skipNext) {
14917
+ skipNext = false;
14918
+ continue;
14919
+ }
14920
+ if (GIT_VALUE_FLAGS.has(tok)) {
14921
+ skipNext = true;
14922
+ continue;
14923
+ }
14924
+ if (tok.startsWith("-")) continue;
14925
+ return tok;
14926
+ }
14927
+ return null;
14928
+ }
14929
+ function blocksUnsignedGit(command) {
14930
+ if (!command.includes("git")) return false;
14931
+ return command.split(/&&|\|\||[;\n|]/).some((segment) => {
14932
+ const sub = gitSubcommand(segment);
14933
+ return sub === "commit" || sub === "push";
14934
+ });
14935
+ }
14936
+ var createSignedCommitGuardHook = (logger) => async (input, _toolUseID) => {
14937
+ if (input.hook_event_name !== "PreToolUse") return { continue: true };
14938
+ if (input.tool_name !== "Bash") return { continue: true };
14939
+ const command = input.tool_input?.command;
14940
+ if (!command || !blocksUnsignedGit(command)) {
14941
+ return { continue: true };
14942
+ }
14943
+ logger.info(
14944
+ `[SignedCommitGuard] Blocking unsigned git command: ${command}`
14945
+ );
14946
+ return {
14947
+ continue: true,
14948
+ hookSpecificOutput: {
14949
+ hookEventName: "PreToolUse",
14950
+ permissionDecision: "deny",
14951
+ permissionDecisionReason: `Commits must be signed: \`git commit\` and \`git push\` are disabled here. Stage changes with \`git add\`, then call the \`git_signed_commit\` tool (${SIGNED_COMMIT_QUALIFIED_TOOL_NAME}) with a \`message\` to create a signed commit on the branch.`
14952
+ }
14953
+ };
14954
+ };
13809
14955
  var createPreToolUseHook = (settingsManager, logger) => async (input, _toolUseID) => {
13810
14956
  if (input.hook_event_name !== "PreToolUse") {
13811
14957
  return { continue: true };
@@ -13859,8 +15005,8 @@ var createPreToolUseHook = (settingsManager, logger) => async (input, _toolUseID
13859
15005
  };
13860
15006
 
13861
15007
  // src/adapters/claude/conversion/tool-use-to-acp.ts
13862
- import fs5 from "fs";
13863
- import path6 from "path";
15008
+ import fs6 from "fs";
15009
+ import path7 from "path";
13864
15010
 
13865
15011
  // src/adapters/claude/mcp/tool-metadata.ts
13866
15012
  var mcpToolMetadataCache = /* @__PURE__ */ new Map();
@@ -13870,7 +15016,7 @@ function buildToolKey(serverName, toolName) {
13870
15016
  return `mcp__${serverName}__${toolName}`;
13871
15017
  }
13872
15018
  function delay2(ms) {
13873
- return new Promise((resolve7) => setTimeout(resolve7, ms));
15019
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
13874
15020
  }
13875
15021
  async function fetchMcpToolMetadata(q, logger = new Logger({ debug: false, prefix: "[McpToolMetadata]" })) {
13876
15022
  let retries = 0;
@@ -13890,14 +15036,14 @@ async function fetchMcpToolMetadata(q, logger = new Logger({ debug: false, prefi
13890
15036
  continue;
13891
15037
  }
13892
15038
  let readOnlyCount = 0;
13893
- for (const tool of server.tools) {
13894
- const toolKey = buildToolKey(server.name, tool.name);
13895
- const readOnly = tool.annotations?.readOnly === true;
15039
+ for (const tool2 of server.tools) {
15040
+ const toolKey = buildToolKey(server.name, tool2.name);
15041
+ const readOnly = tool2.annotations?.readOnly === true;
13896
15042
  const existing = mcpToolMetadataCache.get(toolKey);
13897
15043
  mcpToolMetadataCache.set(toolKey, {
13898
15044
  readOnly,
13899
- name: tool.name,
13900
- description: tool.description,
15045
+ name: tool2.name,
15046
+ description: tool2.description,
13901
15047
  approvalState: existing?.approvalState
13902
15048
  });
13903
15049
  if (readOnly) readOnlyCount++;
@@ -13965,10 +15111,10 @@ function stripSystemReminders(value) {
13965
15111
  }
13966
15112
  function toDisplayPath(filePath, cwd) {
13967
15113
  if (!cwd) return filePath;
13968
- const resolvedCwd = path6.resolve(cwd);
13969
- const resolvedFile = path6.resolve(filePath);
13970
- if (resolvedFile.startsWith(resolvedCwd + path6.sep) || resolvedFile === resolvedCwd) {
13971
- return path6.relative(resolvedCwd, resolvedFile);
15114
+ const resolvedCwd = path7.resolve(cwd);
15115
+ const resolvedFile = path7.resolve(filePath);
15116
+ if (resolvedFile.startsWith(resolvedCwd + path7.sep) || resolvedFile === resolvedCwd) {
15117
+ return path7.relative(resolvedCwd, resolvedFile);
13972
15118
  }
13973
15119
  return filePath;
13974
15120
  }
@@ -14093,7 +15239,7 @@ function toolInfoFromToolUse(toolUse, options) {
14093
15239
  oldContent = options.cachedFileContent[writeFilePath];
14094
15240
  } else {
14095
15241
  try {
14096
- oldContent = fs5.readFileSync(writeFilePath, "utf-8");
15242
+ oldContent = fs6.readFileSync(writeFilePath, "utf-8");
14097
15243
  } catch {
14098
15244
  }
14099
15245
  }
@@ -14507,7 +15653,7 @@ function resolveFileContent(filePath, oldText, cachedFileContent) {
14507
15653
  }
14508
15654
  }
14509
15655
  try {
14510
- const content = fs5.readFileSync(filePath, "utf-8");
15656
+ const content = fs6.readFileSync(filePath, "utf-8");
14511
15657
  if (content.includes(oldText)) {
14512
15658
  return content;
14513
15659
  }
@@ -15160,20 +16306,45 @@ async function handleUserAssistantMessage(message, context) {
15160
16306
  return {};
15161
16307
  }
15162
16308
 
16309
+ // src/adapters/claude/mcp/local-tools.ts
16310
+ import {
16311
+ createSdkMcpServer,
16312
+ tool
16313
+ } from "@anthropic-ai/claude-agent-sdk";
16314
+ function createLocalToolsMcpServer(ctx, meta) {
16315
+ const tools = enabledLocalTools(ctx, meta);
16316
+ if (tools.length === 0) {
16317
+ return void 0;
16318
+ }
16319
+ return createSdkMcpServer({
16320
+ name: LOCAL_TOOLS_MCP_NAME,
16321
+ version: "1.0.0",
16322
+ tools: tools.map(
16323
+ (t) => tool(
16324
+ t.name,
16325
+ t.description,
16326
+ t.schema,
16327
+ async (args2) => t.handler(ctx, args2),
16328
+ { alwaysLoad: t.alwaysLoad ?? false }
16329
+ )
16330
+ )
16331
+ });
16332
+ }
16333
+
15163
16334
  // src/adapters/claude/plan/utils.ts
15164
- import * as os from "os";
15165
- import * as path7 from "path";
16335
+ import * as os2 from "os";
16336
+ import * as path8 from "path";
15166
16337
  function getClaudeConfigDir() {
15167
- return process.env.CLAUDE_CONFIG_DIR || path7.join(os.homedir(), ".claude");
16338
+ return process.env.CLAUDE_CONFIG_DIR || path8.join(os2.homedir(), ".claude");
15168
16339
  }
15169
16340
  function getClaudePlansDir() {
15170
- return path7.join(getClaudeConfigDir(), "plans");
16341
+ return path8.join(getClaudeConfigDir(), "plans");
15171
16342
  }
15172
16343
  function isClaudePlanFilePath(filePath) {
15173
16344
  if (!filePath) return false;
15174
- const resolved = path7.resolve(filePath);
15175
- const plansDir = path7.resolve(getClaudePlansDir());
15176
- return resolved === plansDir || resolved.startsWith(plansDir + path7.sep);
16345
+ const resolved = path8.resolve(filePath);
16346
+ const plansDir = path8.resolve(getClaudePlansDir());
16347
+ return resolved === plansDir || resolved.startsWith(plansDir + path8.sep);
15177
16348
  }
15178
16349
  function isPlanReady(plan) {
15179
16350
  if (!plan) return false;
@@ -15204,21 +16375,21 @@ function getLatestAssistantText(notifications) {
15204
16375
  }
15205
16376
 
15206
16377
  // src/adapters/claude/questions/utils.ts
15207
- import { z } from "zod";
16378
+ import { z as z2 } from "zod";
15208
16379
  var OPTION_PREFIX = "option_";
15209
- var QuestionOptionSchema = z.object({
15210
- label: z.string(),
15211
- description: z.string().optional()
16380
+ var QuestionOptionSchema = z2.object({
16381
+ label: z2.string(),
16382
+ description: z2.string().optional()
15212
16383
  });
15213
- var QuestionItemSchema = z.object({
15214
- question: z.string(),
15215
- header: z.string().optional(),
15216
- options: z.array(QuestionOptionSchema),
15217
- multiSelect: z.boolean().optional(),
15218
- completed: z.boolean().optional()
16384
+ var QuestionItemSchema = z2.object({
16385
+ question: z2.string(),
16386
+ header: z2.string().optional(),
16387
+ options: z2.array(QuestionOptionSchema),
16388
+ multiSelect: z2.boolean().optional(),
16389
+ completed: z2.boolean().optional()
15219
16390
  });
15220
- var QuestionMetaSchema = z.object({
15221
- questions: z.array(QuestionItemSchema)
16391
+ var QuestionMetaSchema = z2.object({
16392
+ questions: z2.array(QuestionItemSchema)
15222
16393
  });
15223
16394
  function normalizeAskUserQuestionInput(input) {
15224
16395
  if (input.questions && input.questions.length > 0) {
@@ -15990,14 +17161,14 @@ function getAvailableSlashCommands(commands) {
15990
17161
  }
15991
17162
 
15992
17163
  // src/adapters/claude/session/mcp-config.ts
15993
- import * as fs6 from "fs";
15994
- import * as os2 from "os";
15995
- import * as path8 from "path";
15996
- function loadUserClaudeJsonMcpServers(cwd, logger, homeDir = os2.homedir()) {
15997
- const claudeJsonPath = path8.join(homeDir, ".claude.json");
17164
+ import * as fs7 from "fs";
17165
+ import * as os3 from "os";
17166
+ import * as path9 from "path";
17167
+ function loadUserClaudeJsonMcpServers(cwd, logger, homeDir = os3.homedir()) {
17168
+ const claudeJsonPath = path9.join(homeDir, ".claude.json");
15998
17169
  let raw;
15999
17170
  try {
16000
- raw = fs6.readFileSync(claudeJsonPath, "utf8");
17171
+ raw = fs7.readFileSync(claudeJsonPath, "utf8");
16001
17172
  } catch {
16002
17173
  return {};
16003
17174
  }
@@ -16148,9 +17319,9 @@ function resolveModelPreference(preference, options) {
16148
17319
 
16149
17320
  // src/adapters/claude/session/options.ts
16150
17321
  import { spawn as spawn3 } from "child_process";
16151
- import * as fs7 from "fs";
16152
- import * as os3 from "os";
16153
- import * as path9 from "path";
17322
+ import * as fs8 from "fs";
17323
+ import * as os4 from "os";
17324
+ import * as path10 from "path";
16154
17325
 
16155
17326
  // src/adapters/claude/session/instructions.ts
16156
17327
  var BRANCH_NAMING = `
@@ -16225,28 +17396,27 @@ ${bedrockFallbackHeader}` : bedrockFallbackHeader;
16225
17396
  ANTHROPIC_CUSTOM_HEADERS: customHeaders
16226
17397
  };
16227
17398
  }
16228
- function buildHooks(userHooks, onModeChange, settingsManager, logger, enrichmentDeps, enrichedReadCache, registeredAgents) {
17399
+ function buildHooks(userHooks, onModeChange, settingsManager, logger, enrichmentDeps, enrichedReadCache, registeredAgents, cloudMode) {
16229
17400
  const postToolUseHooks = [createPostToolUseHook({ onModeChange })];
16230
17401
  if (enrichmentDeps && enrichedReadCache) {
16231
17402
  postToolUseHooks.push(
16232
17403
  createReadEnrichmentHook(enrichmentDeps, enrichedReadCache)
16233
17404
  );
16234
17405
  }
17406
+ const preToolUseHooks = [
17407
+ createPreToolUseHook(settingsManager, logger),
17408
+ createSubagentRewriteHook(logger, registeredAgents)
17409
+ ];
17410
+ if (cloudMode) {
17411
+ preToolUseHooks.push(createSignedCommitGuardHook(logger));
17412
+ }
16235
17413
  return {
16236
17414
  ...userHooks,
16237
17415
  PostToolUse: [
16238
17416
  ...userHooks?.PostToolUse || [],
16239
17417
  { hooks: postToolUseHooks }
16240
17418
  ],
16241
- PreToolUse: [
16242
- ...userHooks?.PreToolUse || [],
16243
- {
16244
- hooks: [
16245
- createPreToolUseHook(settingsManager, logger),
16246
- createSubagentRewriteHook(logger, registeredAgents)
16247
- ]
16248
- }
16249
- ]
17419
+ PreToolUse: [...userHooks?.PreToolUse || [], { hooks: preToolUseHooks }]
16250
17420
  };
16251
17421
  }
16252
17422
  var PH_EXPLORE_AGENT = {
@@ -16358,12 +17528,12 @@ function buildSpawnWrapper(sessionId, onProcessSpawned, onProcessExited, logger)
16358
17528
  };
16359
17529
  }
16360
17530
  function ensureLocalSettings(cwd) {
16361
- const claudeDir = path9.join(cwd, ".claude");
16362
- const localSettingsPath = path9.join(claudeDir, "settings.local.json");
17531
+ const claudeDir = path10.join(cwd, ".claude");
17532
+ const localSettingsPath = path10.join(claudeDir, "settings.local.json");
16363
17533
  try {
16364
- if (!fs7.existsSync(localSettingsPath)) {
16365
- fs7.mkdirSync(claudeDir, { recursive: true });
16366
- fs7.writeFileSync(localSettingsPath, "{}\n", { flag: "wx" });
17534
+ if (!fs8.existsSync(localSettingsPath)) {
17535
+ fs8.mkdirSync(claudeDir, { recursive: true });
17536
+ fs8.writeFileSync(localSettingsPath, "{}\n", { flag: "wx" });
16367
17537
  }
16368
17538
  } catch {
16369
17539
  }
@@ -16404,7 +17574,8 @@ function buildSessionOptions(params) {
16404
17574
  params.logger,
16405
17575
  params.enrichmentDeps,
16406
17576
  params.enrichedReadCache,
16407
- registeredAgentNames
17577
+ registeredAgentNames,
17578
+ params.cloudMode ?? false
16408
17579
  ),
16409
17580
  outputFormat: params.outputFormat,
16410
17581
  abortController: getAbortController(
@@ -16439,18 +17610,18 @@ function buildSessionOptions(params) {
16439
17610
  return options;
16440
17611
  }
16441
17612
  function clearStatsigCache() {
16442
- const statsigPath = path9.join(
16443
- process.env.CLAUDE_CONFIG_DIR || path9.join(os3.homedir(), ".claude"),
17613
+ const statsigPath = path10.join(
17614
+ process.env.CLAUDE_CONFIG_DIR || path10.join(os4.homedir(), ".claude"),
16444
17615
  "statsig"
16445
17616
  );
16446
- fs7.rm(statsigPath, { recursive: true, force: true }, () => {
17617
+ fs8.rm(statsigPath, { recursive: true, force: true }, () => {
16447
17618
  });
16448
17619
  }
16449
17620
 
16450
17621
  // src/adapters/claude/session/settings.ts
16451
- import * as fs8 from "fs";
16452
- import * as os4 from "os";
16453
- import * as path10 from "path";
17622
+ import * as fs9 from "fs";
17623
+ import * as os5 from "os";
17624
+ import * as path11 from "path";
16454
17625
  import { minimatch } from "minimatch";
16455
17626
 
16456
17627
  // src/utils/async-mutex.ts
@@ -16462,8 +17633,8 @@ var AsyncMutex = class {
16462
17633
  this.locked = true;
16463
17634
  return;
16464
17635
  }
16465
- return new Promise((resolve7) => {
16466
- this.queue.push(resolve7);
17636
+ return new Promise((resolve8) => {
17637
+ this.queue.push(resolve8);
16467
17638
  });
16468
17639
  }
16469
17640
  release() {
@@ -16531,13 +17702,13 @@ function parseRule(rule) {
16531
17702
  function normalizePath(filePath, cwd) {
16532
17703
  let resolved = filePath;
16533
17704
  if (resolved.startsWith("~/")) {
16534
- resolved = path10.join(os4.homedir(), resolved.slice(2));
17705
+ resolved = path11.join(os5.homedir(), resolved.slice(2));
16535
17706
  } else if (resolved.startsWith("./")) {
16536
- resolved = path10.join(cwd, resolved.slice(2));
16537
- } else if (!path10.isAbsolute(resolved)) {
16538
- resolved = path10.join(cwd, resolved);
17707
+ resolved = path11.join(cwd, resolved.slice(2));
17708
+ } else if (!path11.isAbsolute(resolved)) {
17709
+ resolved = path11.join(cwd, resolved);
16539
17710
  }
16540
- return path10.normalize(resolved).replace(/\\/g, "/");
17711
+ return path11.normalize(resolved).replace(/\\/g, "/");
16541
17712
  }
16542
17713
  function matchesGlob(pattern, filePath, cwd) {
16543
17714
  const normalizedPattern = normalizePath(pattern, cwd);
@@ -16584,11 +17755,11 @@ function formatRule(rule) {
16584
17755
  }
16585
17756
  async function writeFileAtomic(filePath, data) {
16586
17757
  const tmpPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
16587
- await fs8.promises.writeFile(tmpPath, data);
17758
+ await fs9.promises.writeFile(tmpPath, data);
16588
17759
  try {
16589
- await fs8.promises.rename(tmpPath, filePath);
17760
+ await fs9.promises.rename(tmpPath, filePath);
16590
17761
  } catch (error) {
16591
- await fs8.promises.rm(tmpPath, { force: true });
17762
+ await fs9.promises.rm(tmpPath, { force: true });
16592
17763
  throw error;
16593
17764
  }
16594
17765
  }
@@ -16597,7 +17768,7 @@ async function loadSettingsFile(filePath) {
16597
17768
  return {};
16598
17769
  }
16599
17770
  try {
16600
- const content = await fs8.promises.readFile(filePath, "utf-8");
17771
+ const content = await fs9.promises.readFile(filePath, "utf-8");
16601
17772
  return JSON.parse(content);
16602
17773
  } catch (error) {
16603
17774
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -16612,7 +17783,7 @@ async function loadSettingsFile(filePath) {
16612
17783
  }
16613
17784
  async function readSettingsFileForUpdate(filePath) {
16614
17785
  try {
16615
- const content = await fs8.promises.readFile(filePath, "utf-8");
17786
+ const content = await fs9.promises.readFile(filePath, "utf-8");
16616
17787
  return JSON.parse(content);
16617
17788
  } catch (error) {
16618
17789
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -16658,11 +17829,11 @@ var SettingsManager = class {
16658
17829
  return this.initPromise;
16659
17830
  }
16660
17831
  getUserSettingsPath() {
16661
- const configDir = process.env.CLAUDE_CONFIG_DIR || path10.join(os4.homedir(), ".claude");
16662
- return path10.join(configDir, "settings.json");
17832
+ const configDir = process.env.CLAUDE_CONFIG_DIR || path11.join(os5.homedir(), ".claude");
17833
+ return path11.join(configDir, "settings.json");
16663
17834
  }
16664
17835
  getProjectSettingsPath() {
16665
- return path10.join(this.cwd, ".claude", "settings.json");
17836
+ return path11.join(this.cwd, ".claude", "settings.json");
16666
17837
  }
16667
17838
  /**
16668
17839
  * Local settings are anchored to the primary worktree so every worktree of
@@ -16670,7 +17841,7 @@ var SettingsManager = class {
16670
17841
  * avoids re-prompting for the same permission in every worktree.
16671
17842
  */
16672
17843
  getLocalSettingsPath() {
16673
- return path10.join(this.repoRoot, ".claude", "settings.local.json");
17844
+ return path11.join(this.repoRoot, ".claude", "settings.local.json");
16674
17845
  }
16675
17846
  async loadAllSettings() {
16676
17847
  this.repoRoot = await resolveMainRepoPath(this.cwd);
@@ -16728,8 +17899,8 @@ var SettingsManager = class {
16728
17899
  merged.model = settings.model;
16729
17900
  }
16730
17901
  if (settings.posthogApprovedExecTools) {
16731
- for (const tool of settings.posthogApprovedExecTools) {
16732
- posthogApprovedExecTools.add(tool);
17902
+ for (const tool2 of settings.posthogApprovedExecTools) {
17903
+ posthogApprovedExecTools.add(tool2);
16733
17904
  }
16734
17905
  }
16735
17906
  }
@@ -16797,7 +17968,7 @@ var SettingsManager = class {
16797
17968
  }
16798
17969
  permissions.allow = Array.from(current2);
16799
17970
  const next = { ...existing, permissions };
16800
- await fs8.promises.mkdir(path10.dirname(filePath), { recursive: true });
17971
+ await fs9.promises.mkdir(path11.dirname(filePath), { recursive: true });
16801
17972
  await writeFileAtomic(filePath, `${JSON.stringify(next, null, 2)}
16802
17973
  `);
16803
17974
  this.localSettings = next;
@@ -16830,7 +18001,7 @@ var SettingsManager = class {
16830
18001
  ...existing,
16831
18002
  posthogApprovedExecTools: Array.from(current2)
16832
18003
  };
16833
- await fs8.promises.mkdir(path10.dirname(filePath), { recursive: true });
18004
+ await fs9.promises.mkdir(path11.dirname(filePath), { recursive: true });
16834
18005
  await writeFileAtomic(filePath, `${JSON.stringify(next, null, 2)}
16835
18006
  `);
16836
18007
  this.localSettings = next;
@@ -16936,7 +18107,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
16936
18107
  };
16937
18108
  }
16938
18109
  async newSession(params) {
16939
- if (fs9.existsSync(path11.resolve(os5.homedir(), ".claude.json.backup")) && !fs9.existsSync(path11.resolve(os5.homedir(), ".claude.json"))) {
18110
+ if (fs10.existsSync(path12.resolve(os6.homedir(), ".claude.json.backup")) && !fs10.existsSync(path12.resolve(os6.homedir(), ".claude.json"))) {
16940
18111
  throw RequestError2.authRequired();
16941
18112
  }
16942
18113
  const response = await this.createSession(params, {
@@ -17034,8 +18205,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
17034
18205
  if (this.session.promptRunning) {
17035
18206
  this.session.input.push(userMessage);
17036
18207
  const order = this.session.nextPendingOrder++;
17037
- const cancelled = await new Promise((resolve7) => {
17038
- this.session.pendingMessages.set(promptUuid, { resolve: resolve7, order });
18208
+ const cancelled = await new Promise((resolve8) => {
18209
+ this.session.pendingMessages.set(promptUuid, { resolve: resolve8, order });
17039
18210
  });
17040
18211
  if (cancelled) {
17041
18212
  return { stopReason: "cancelled" };
@@ -17557,7 +18728,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
17557
18728
  const { resume, forkSession } = creationOpts;
17558
18729
  const isResume = !!resume;
17559
18730
  const meta = params._meta;
17560
- const taskId = meta?.persistence?.taskId;
18731
+ const taskId = resolveTaskId(meta);
18732
+ const cloudRun = isCloudRun(meta);
17561
18733
  const effort = meta?.claudeCode?.options?.effort;
17562
18734
  let sessionId;
17563
18735
  if (forkSession) {
@@ -17572,6 +18744,17 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
17572
18744
  await settingsManager.initialize();
17573
18745
  const earlyModelId = settingsManager.getSettings().model || meta?.model || "";
17574
18746
  const mcpServers = supportsMcpInjection(earlyModelId) ? parseMcpServers(params) : {};
18747
+ const localToolsServer = createLocalToolsMcpServer(
18748
+ { cwd, token: resolveGithubToken(), taskId },
18749
+ meta
18750
+ );
18751
+ if (localToolsServer) {
18752
+ mcpServers[LOCAL_TOOLS_MCP_NAME] = localToolsServer;
18753
+ } else if (cloudRun) {
18754
+ this.logger.warn(
18755
+ "Cloud run registered no local tools \u2014 missing GH_TOKEN/GITHUB_TOKEN? signed commits unavailable"
18756
+ );
18757
+ }
17575
18758
  const systemPrompt = buildSystemPrompt(meta?.systemPrompt);
17576
18759
  if (meta?.mcpToolApprovals) {
17577
18760
  setMcpToolApprovalStates(meta.mcpToolApprovals);
@@ -17607,7 +18790,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
17607
18790
  onProcessExited: this.options?.onProcessExited,
17608
18791
  effort,
17609
18792
  enrichmentDeps: this.enrichment?.deps,
17610
- enrichedReadCache: this.enrichedReadCache
18793
+ enrichedReadCache: this.enrichedReadCache,
18794
+ cloudMode: cloudRun
17611
18795
  });
17612
18796
  const abortController = options.abortController;
17613
18797
  const q = query({ prompt: input, options });
@@ -17939,7 +19123,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
17939
19123
  */
17940
19124
  deferBackgroundFetches(q) {
17941
19125
  Promise.all([
17942
- new Promise((resolve7) => setTimeout(resolve7, 10)).then(
19126
+ new Promise((resolve8) => setTimeout(resolve8, 10)).then(
17943
19127
  () => this.sendAvailableCommandsUpdate()
17944
19128
  ),
17945
19129
  fetchMcpToolMetadata(q, this.logger).then(() => {
@@ -18217,9 +19401,9 @@ function resetUsage(state) {
18217
19401
  }
18218
19402
 
18219
19403
  // src/adapters/codex/settings.ts
18220
- import * as fs10 from "fs";
18221
- import * as os6 from "os";
18222
- import * as path12 from "path";
19404
+ import * as fs11 from "fs";
19405
+ import * as os7 from "os";
19406
+ import * as path13 from "path";
18223
19407
  var CodexSettingsManager = class {
18224
19408
  cwd;
18225
19409
  settings = { mcpServerNames: [] };
@@ -18230,12 +19414,12 @@ var CodexSettingsManager = class {
18230
19414
  async initialize() {
18231
19415
  }
18232
19416
  getConfigPath() {
18233
- return path12.join(os6.homedir(), ".codex", "config.toml");
19417
+ return path13.join(os7.homedir(), ".codex", "config.toml");
18234
19418
  }
18235
19419
  loadSettings() {
18236
19420
  const configPath = this.getConfigPath();
18237
19421
  try {
18238
- const content = fs10.readFileSync(configPath, "utf-8");
19422
+ const content = fs11.readFileSync(configPath, "utf-8");
18239
19423
  this.settings = parseCodexToml(content, this.cwd);
18240
19424
  } catch {
18241
19425
  this.settings = { mcpServerNames: [] };
@@ -18293,7 +19477,7 @@ function parseCodexToml(content, cwd) {
18293
19477
  // src/adapters/codex/spawn.ts
18294
19478
  import { spawn as spawn4 } from "child_process";
18295
19479
  import { existsSync as existsSync4 } from "fs";
18296
- import { delimiter, dirname as dirname5 } from "path";
19480
+ import { delimiter, dirname as dirname6 } from "path";
18297
19481
  function buildConfigArgs(options) {
18298
19482
  const args2 = [];
18299
19483
  args2.push("-c", `features.remote_models=false`);
@@ -18344,7 +19528,7 @@ function spawnCodexProcess(options) {
18344
19528
  }
18345
19529
  const { command, args: args2 } = findCodexBinary(options);
18346
19530
  if (options.binaryPath && existsSync4(options.binaryPath)) {
18347
- const binDir = dirname5(options.binaryPath);
19531
+ const binDir = dirname6(options.binaryPath);
18348
19532
  env.PATH = `${binDir}${delimiter}${env.PATH ?? ""}`;
18349
19533
  }
18350
19534
  logger.info("Spawning codex-acp process", {
@@ -18449,8 +19633,7 @@ function getCurrentPermissionMode(currentModeId, fallbackMode) {
18449
19633
  var STRUCTURED_OUTPUT_INSTRUCTIONS = `
18450
19634
 
18451
19635
  When you have completed the task, call the \`${STRUCTURED_OUTPUT_TOOL_NAME}\` tool with the final structured result. The tool's input schema matches the required output format for this task. Do not describe the result in a plain message \u2014 submitting it via the tool is required for the task to be considered complete.`;
18452
- function resolveStructuredOutputMcpScript() {
18453
- const rel = "adapters/codex/structured-output-mcp-server.js";
19636
+ function resolveBundledMcpScript(rel) {
18454
19637
  let dir = import.meta.dirname ?? __dirname;
18455
19638
  for (let i2 = 0; i2 < 5; i2++) {
18456
19639
  const candidate = resolvePath(dir, rel);
@@ -18462,7 +19645,9 @@ function resolveStructuredOutputMcpScript() {
18462
19645
  );
18463
19646
  }
18464
19647
  function buildStructuredOutputMcpServer(jsonSchema) {
18465
- const scriptPath = resolveStructuredOutputMcpScript();
19648
+ const scriptPath = resolveBundledMcpScript(
19649
+ "adapters/codex/structured-output-mcp-server.js"
19650
+ );
18466
19651
  const schemaBase64 = Buffer.from(JSON.stringify(jsonSchema)).toString(
18467
19652
  "base64"
18468
19653
  );
@@ -18473,6 +19658,30 @@ function buildStructuredOutputMcpServer(jsonSchema) {
18473
19658
  env: [{ name: "POSTHOG_OUTPUT_SCHEMA", value: schemaBase64 }]
18474
19659
  };
18475
19660
  }
19661
+ function buildLocalToolsMcpServer(ctx, enabledNames) {
19662
+ const scriptPath = resolveBundledMcpScript(
19663
+ "adapters/codex/local-tools-mcp-server.js"
19664
+ );
19665
+ const ctxBase64 = Buffer.from(JSON.stringify(ctx)).toString("base64");
19666
+ const env = [
19667
+ { name: "POSTHOG_LOCAL_TOOLS_CTX", value: ctxBase64 },
19668
+ { name: "POSTHOG_LOCAL_TOOLS_ENABLED", value: enabledNames.join(",") }
19669
+ ];
19670
+ if (ctx.token) {
19671
+ env.push(
19672
+ ...Object.entries(ghTokenEnv(ctx.token)).map(([name2, value]) => ({
19673
+ name: name2,
19674
+ value
19675
+ }))
19676
+ );
19677
+ }
19678
+ return {
19679
+ name: LOCAL_TOOLS_MCP_NAME,
19680
+ command: process.execPath,
19681
+ args: [scriptPath],
19682
+ env
19683
+ };
19684
+ }
18476
19685
  var CodexAcpAgent = class extends BaseAcpAgent {
18477
19686
  adapterName = "codex";
18478
19687
  codexProcess;
@@ -18560,14 +19769,17 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18560
19769
  async newSession(params) {
18561
19770
  const meta = params._meta;
18562
19771
  const requestedPermissionMode = toCodexPermissionMode(meta?.permissionMode);
18563
- const injectedParams = this.applyStructuredOutput(params, meta);
19772
+ const injectedParams = this.applyLocalTools(
19773
+ this.applyStructuredOutput(params, meta),
19774
+ meta
19775
+ );
18564
19776
  const response = await this.codexConnection.newSession(injectedParams);
18565
19777
  response.configOptions = normalizeCodexConfigOptions(
18566
19778
  response.configOptions
18567
19779
  );
18568
19780
  this.sessionState = createSessionState(response.sessionId, params.cwd, {
18569
19781
  taskRunId: meta?.taskRunId,
18570
- taskId: meta?.taskId ?? meta?.persistence?.taskId,
19782
+ taskId: resolveTaskId(meta),
18571
19783
  modeId: response.modes?.currentModeId ?? "auto",
18572
19784
  modelId: response.models?.currentModelId,
18573
19785
  permissionMode: requestedPermissionMode
@@ -18594,7 +19806,10 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18594
19806
  }
18595
19807
  async loadSession(params) {
18596
19808
  const meta = params._meta;
18597
- const injectedParams = this.applyStructuredOutput(params, meta);
19809
+ const injectedParams = this.applyLocalTools(
19810
+ this.applyStructuredOutput(params, meta),
19811
+ meta
19812
+ );
18598
19813
  const response = await this.codexConnection.loadSession(injectedParams);
18599
19814
  response.configOptions = normalizeCodexConfigOptions(
18600
19815
  response.configOptions
@@ -18605,7 +19820,7 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18605
19820
  );
18606
19821
  this.sessionState = createSessionState(params.sessionId, params.cwd, {
18607
19822
  taskRunId: meta?.taskRunId,
18608
- taskId: meta?.taskId ?? meta?.persistence?.taskId,
19823
+ taskId: resolveTaskId(meta),
18609
19824
  modeId: response.modes?.currentModeId ?? "auto",
18610
19825
  permissionMode: currentPermissionMode
18611
19826
  });
@@ -18622,13 +19837,16 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18622
19837
  }
18623
19838
  async unstable_resumeSession(params) {
18624
19839
  const meta = params._meta;
18625
- const injectedParams = this.applyStructuredOutput(
18626
- {
18627
- sessionId: params.sessionId,
18628
- cwd: params.cwd,
18629
- mcpServers: params.mcpServers ?? [],
18630
- _meta: params._meta
18631
- },
19840
+ const injectedParams = this.applyLocalTools(
19841
+ this.applyStructuredOutput(
19842
+ {
19843
+ sessionId: params.sessionId,
19844
+ cwd: params.cwd,
19845
+ mcpServers: params.mcpServers ?? [],
19846
+ _meta: params._meta
19847
+ },
19848
+ meta
19849
+ ),
18632
19850
  meta
18633
19851
  );
18634
19852
  const loadResponse = await this.codexConnection.loadSession(injectedParams);
@@ -18641,7 +19859,7 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18641
19859
  );
18642
19860
  this.sessionState = createSessionState(params.sessionId, params.cwd, {
18643
19861
  taskRunId: meta?.taskRunId,
18644
- taskId: meta?.taskId ?? meta?.persistence?.taskId,
19862
+ taskId: resolveTaskId(meta),
18645
19863
  modeId: loadResponse.modes?.currentModeId ?? "auto",
18646
19864
  permissionMode: currentPermissionMode
18647
19865
  });
@@ -18662,12 +19880,15 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18662
19880
  }
18663
19881
  async unstable_forkSession(params) {
18664
19882
  const meta = params._meta;
18665
- const injectedParams = this.applyStructuredOutput(
18666
- {
18667
- cwd: params.cwd,
18668
- mcpServers: params.mcpServers ?? [],
18669
- _meta: params._meta
18670
- },
19883
+ const injectedParams = this.applyLocalTools(
19884
+ this.applyStructuredOutput(
19885
+ {
19886
+ cwd: params.cwd,
19887
+ mcpServers: params.mcpServers ?? [],
19888
+ _meta: params._meta
19889
+ },
19890
+ meta
19891
+ ),
18671
19892
  meta
18672
19893
  );
18673
19894
  const newResponse = await this.codexConnection.newSession(injectedParams);
@@ -18677,7 +19898,7 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18677
19898
  const requestedPermissionMode = toCodexPermissionMode(meta?.permissionMode);
18678
19899
  this.sessionState = createSessionState(newResponse.sessionId, params.cwd, {
18679
19900
  taskRunId: meta?.taskRunId,
18680
- taskId: meta?.taskId ?? meta?.persistence?.taskId,
19901
+ taskId: resolveTaskId(meta),
18681
19902
  modeId: newResponse.modes?.currentModeId ?? "auto",
18682
19903
  permissionMode: requestedPermissionMode
18683
19904
  });
@@ -18714,6 +19935,41 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18714
19935
  }
18715
19936
  };
18716
19937
  }
19938
+ /**
19939
+ * Injects the stdio general local-tools MCP server. Tools self-gate via the
19940
+ * registry (e.g. signed-commit is cloud-only and needs a GH token), so the
19941
+ * server is only injected when at least one tool's gate passes. Their
19942
+ * instructions already live in the shared cloud system prompt, so only the
19943
+ * server needs injecting here.
19944
+ */
19945
+ applyLocalTools(request, meta) {
19946
+ const cwd = request.cwd;
19947
+ if (!cwd) {
19948
+ return request;
19949
+ }
19950
+ const ctx = {
19951
+ cwd,
19952
+ token: resolveGithubToken(),
19953
+ taskId: resolveTaskId(meta)
19954
+ };
19955
+ const tools = enabledLocalTools(ctx, meta);
19956
+ if (tools.length === 0) {
19957
+ if (isCloudRun(meta)) {
19958
+ this.logger.warn(
19959
+ "Cloud run registered no local tools \u2014 missing GH_TOKEN/GITHUB_TOKEN? signed commits unavailable"
19960
+ );
19961
+ }
19962
+ return request;
19963
+ }
19964
+ const mcpServer = buildLocalToolsMcpServer(
19965
+ ctx,
19966
+ tools.map((t) => t.name)
19967
+ );
19968
+ return {
19969
+ ...request,
19970
+ mcpServers: [...request.mcpServers ?? [], mcpServer]
19971
+ };
19972
+ }
18717
19973
  async applyInitialPermissionMode(sessionId, permissionMode, currentModeId) {
18718
19974
  if (!permissionMode) {
18719
19975
  return;
@@ -19085,20 +20341,20 @@ function createCodexConnection(config) {
19085
20341
  }
19086
20342
 
19087
20343
  // src/handoff-checkpoint.ts
19088
- import { mkdtemp as mkdtemp2, readFile as readFile4, rm as rm4, writeFile as writeFile2 } from "fs/promises";
20344
+ import { mkdtemp as mkdtemp2, readFile as readFile4, rm as rm5, writeFile as writeFile2 } from "fs/promises";
19089
20345
  import { tmpdir as tmpdir2 } from "os";
19090
- import { dirname as dirname6, join as join10 } from "path";
20346
+ import { dirname as dirname7, join as join11 } from "path";
19091
20347
 
19092
20348
  // ../git/dist/handoff.js
19093
20349
  import { spawn as spawn5 } from "child_process";
19094
- import { copyFile, mkdtemp, readFile as readFile3, rm as rm3, stat as stat3 } from "fs/promises";
20350
+ import { copyFile as copyFile2, mkdtemp, readFile as readFile3, rm as rm4, stat as stat3 } from "fs/promises";
19095
20351
  import { tmpdir } from "os";
19096
- import path14 from "path";
20352
+ import path15 from "path";
19097
20353
 
19098
20354
  // ../git/dist/sagas/checkpoint.js
19099
20355
  import { randomUUID as randomUUID2 } from "crypto";
19100
- import * as fs11 from "fs/promises";
19101
- import * as path13 from "path";
20356
+ import * as fs12 from "fs/promises";
20357
+ import * as path14 from "path";
19102
20358
 
19103
20359
  // ../shared/dist/index.js
19104
20360
  var CLOUD_PROMPT_PREFIX = "__twig_cloud_prompt_v1__:";
@@ -19384,7 +20640,7 @@ async function createWorktreeTree(git, baseDir, head) {
19384
20640
  const treeHash = await tempGit.raw(["write-tree"]);
19385
20641
  return treeHash.trim();
19386
20642
  } finally {
19387
- await fs11.rm(tempIndexPath, { force: true }).catch(() => {
20643
+ await fs12.rm(tempIndexPath, { force: true }).catch(() => {
19388
20644
  });
19389
20645
  }
19390
20646
  }
@@ -19482,7 +20738,7 @@ async function createMetaTree(git, baseDir, indexTree, worktreeTree) {
19482
20738
  const metaTree = await tempGit.raw(["write-tree"]);
19483
20739
  return metaTree.trim();
19484
20740
  } finally {
19485
- await fs11.rm(tempIndexPath, { force: true }).catch(() => {
20741
+ await fs12.rm(tempIndexPath, { force: true }).catch(() => {
19486
20742
  });
19487
20743
  }
19488
20744
  }
@@ -19499,12 +20755,12 @@ function formatCheckpointMessage(meta) {
19499
20755
  async function getGitCommonDir(git, baseDir) {
19500
20756
  const raw = await git.raw(["rev-parse", "--git-common-dir"]);
19501
20757
  const dir = raw.trim() || ".git";
19502
- return path13.isAbsolute(dir) ? dir : path13.resolve(baseDir, dir);
20758
+ return path14.isAbsolute(dir) ? dir : path14.resolve(baseDir, dir);
19503
20759
  }
19504
20760
  async function createTempIndexGit(git, baseDir, label) {
19505
- const tmpDir = path13.join(await getGitCommonDir(git, baseDir), "posthog-code-tmp");
19506
- await fs11.mkdir(tmpDir, { recursive: true });
19507
- const tempIndexPath = path13.join(tmpDir, `${label}-${Date.now()}-${randomUUID2()}`);
20761
+ const tmpDir = path14.join(await getGitCommonDir(git, baseDir), "posthog-code-tmp");
20762
+ await fs12.mkdir(tmpDir, { recursive: true });
20763
+ const tempIndexPath = path14.join(tmpDir, `${label}-${Date.now()}-${randomUUID2()}`);
19508
20764
  const tempGit = createGitClient(baseDir).env({
19509
20765
  ...process.env,
19510
20766
  GIT_INDEX_FILE: tempIndexPath
@@ -19559,7 +20815,7 @@ var GitHandoffTracker = class {
19559
20815
  packBaseline ? `^${packBaseline}` : null
19560
20816
  ].filter((ref) => !!ref);
19561
20817
  const headRef = checkpoint.head ? `${HANDOFF_HEAD_REF_PREFIX}${checkpoint.checkpointId}` : void 0;
19562
- const packPrefix = path14.join(tempDir, checkpoint.checkpointId);
20818
+ const packPrefix = path15.join(tempDir, checkpoint.checkpointId);
19563
20819
  const [headPack, indexFile, tracking] = await Promise.all([
19564
20820
  this.captureObjectPack(packPrefix, packRefs),
19565
20821
  this.statFileArtifact(reconciledIndex.indexFilePath),
@@ -19628,14 +20884,14 @@ var GitHandoffTracker = class {
19628
20884
  `);
19629
20885
  const packPath = `${packPrefix}-${hash.trim()}.pack`;
19630
20886
  const rawBytes = await this.getFileSize(packPath);
19631
- await rm3(`${packPath}.idx`, { force: true }).catch(() => {
20887
+ await rm4(`${packPath}.idx`, { force: true }).catch(() => {
19632
20888
  });
19633
20889
  return { path: packPath, rawBytes };
19634
20890
  }
19635
20891
  async reconcileHandoffIndex(git, head, indexTree, tempDir, checkpointId) {
19636
20892
  const realIndexPath = await this.getGitPath(git, "index");
19637
- const tempIndexPath = path14.join(tempDir, `${checkpointId}.index`);
19638
- await copyFile(realIndexPath, tempIndexPath);
20893
+ const tempIndexPath = path15.join(tempDir, `${checkpointId}.index`);
20894
+ await copyFile2(realIndexPath, tempIndexPath);
19639
20895
  const largePaths = await this.listLargeBlobsInTree(indexTree, MAX_HANDOFF_FILE_BYTES);
19640
20896
  if (largePaths.length === 0) {
19641
20897
  return { indexTree, indexFilePath: tempIndexPath };
@@ -19718,7 +20974,7 @@ var GitHandoffTracker = class {
19718
20974
  }
19719
20975
  async restoreIndexFile(git, indexPath) {
19720
20976
  const gitIndexPath = await this.getGitPath(git, "index");
19721
- await copyFile(indexPath, gitIndexPath);
20977
+ await copyFile2(indexPath, gitIndexPath);
19722
20978
  }
19723
20979
  async unpackPackFile(packPath) {
19724
20980
  const content = await readFile3(packPath);
@@ -19856,7 +21112,7 @@ var GitHandoffTracker = class {
19856
21112
  async getGitPath(git, gitPath) {
19857
21113
  const raw = await git.raw(["rev-parse", "--git-path", gitPath]);
19858
21114
  const resolved = raw.trim();
19859
- return path14.isAbsolute(resolved) ? resolved : path14.resolve(this.repositoryPath, resolved);
21115
+ return path15.isAbsolute(resolved) ? resolved : path15.resolve(this.repositoryPath, resolved);
19860
21116
  }
19861
21117
  async getFileSize(filePath) {
19862
21118
  return (await stat3(filePath)).size;
@@ -19869,7 +21125,7 @@ var GitHandoffTracker = class {
19869
21125
  await this.runGitProcess(args2, input);
19870
21126
  }
19871
21127
  async runGitProcessAllowingFailure(args2) {
19872
- return new Promise((resolve7, reject) => {
21128
+ return new Promise((resolve8, reject) => {
19873
21129
  const child = spawn5("git", args2, {
19874
21130
  cwd: this.repositoryPath,
19875
21131
  stdio: ["ignore", "ignore", "pipe"]
@@ -19888,12 +21144,12 @@ var GitHandoffTracker = class {
19888
21144
  reject(new Error(stderr || `git ${args2.join(" ")} failed with code ${code}`));
19889
21145
  return;
19890
21146
  }
19891
- resolve7(code);
21147
+ resolve8(code);
19892
21148
  });
19893
21149
  });
19894
21150
  }
19895
21151
  async runGitWithEnv(env, args2) {
19896
- return new Promise((resolve7, reject) => {
21152
+ return new Promise((resolve8, reject) => {
19897
21153
  const child = spawn5("git", args2, {
19898
21154
  cwd: this.repositoryPath,
19899
21155
  stdio: ["ignore", "pipe", "pipe"],
@@ -19910,7 +21166,7 @@ var GitHandoffTracker = class {
19910
21166
  child.on("error", reject);
19911
21167
  child.on("close", (code) => {
19912
21168
  if (code === 0) {
19913
- resolve7(stdout);
21169
+ resolve8(stdout);
19914
21170
  return;
19915
21171
  }
19916
21172
  reject(new Error(stderr || `git ${args2.join(" ")} failed with code ${code}`));
@@ -19918,7 +21174,7 @@ var GitHandoffTracker = class {
19918
21174
  });
19919
21175
  }
19920
21176
  runGitProcess(args2, input) {
19921
- return new Promise((resolve7, reject) => {
21177
+ return new Promise((resolve8, reject) => {
19922
21178
  const child = spawn5("git", args2, {
19923
21179
  cwd: this.repositoryPath,
19924
21180
  stdio: "pipe"
@@ -19934,7 +21190,7 @@ var GitHandoffTracker = class {
19934
21190
  child.on("error", reject);
19935
21191
  child.on("close", (code) => {
19936
21192
  if (code === 0) {
19937
- resolve7({ stdout, stderr });
21193
+ resolve8({ stdout, stderr });
19938
21194
  return;
19939
21195
  }
19940
21196
  reject(new Error(stderr || `git ${args2.join(" ")} failed with code ${code}`));
@@ -19946,7 +21202,7 @@ var GitHandoffTracker = class {
19946
21202
  }
19947
21203
  };
19948
21204
  function joinTempPrefix(checkpointId) {
19949
- return path14.join(tmpdir(), `posthog-code-handoff-${checkpointId}-`);
21205
+ return path15.join(tmpdir(), `posthog-code-handoff-${checkpointId}-`);
19950
21206
  }
19951
21207
  async function getCurrentBranchName(git) {
19952
21208
  try {
@@ -20034,10 +21290,10 @@ var HandoffCheckpointTracker = class {
20034
21290
  indexArtifactPath: uploads.index?.storagePath
20035
21291
  };
20036
21292
  } finally {
20037
- const tempDir = capture.headPack?.path ? dirname6(capture.headPack.path) : dirname6(capture.indexFile.path);
21293
+ const tempDir = capture.headPack?.path ? dirname7(capture.headPack.path) : dirname7(capture.indexFile.path);
20038
21294
  await this.removeIfPresent(capture.headPack?.path);
20039
21295
  await this.removeIfPresent(capture.indexFile.path);
20040
- await rm4(tempDir, { recursive: true, force: true }).catch(() => {
21296
+ await rm5(tempDir, { recursive: true, force: true }).catch(() => {
20041
21297
  });
20042
21298
  }
20043
21299
  }
@@ -20049,10 +21305,10 @@ var HandoffCheckpointTracker = class {
20049
21305
  }
20050
21306
  const gitTracker = this.createGitTracker();
20051
21307
  const tmpDir = await mkdtemp2(
20052
- join10(tmpdir2(), `posthog-code-handoff-${checkpoint.checkpointId}-`)
21308
+ join11(tmpdir2(), `posthog-code-handoff-${checkpoint.checkpointId}-`)
20053
21309
  );
20054
- const packPath = join10(tmpDir, `${checkpoint.checkpointId}.pack`);
20055
- const indexPath = join10(tmpDir, `${checkpoint.checkpointId}.index`);
21310
+ const packPath = join11(tmpDir, `${checkpoint.checkpointId}.pack`);
21311
+ const indexPath = join11(tmpDir, `${checkpoint.checkpointId}.index`);
20056
21312
  try {
20057
21313
  const downloads = await this.downloadArtifacts([
20058
21314
  {
@@ -20084,7 +21340,7 @@ var HandoffCheckpointTracker = class {
20084
21340
  } finally {
20085
21341
  await this.removeIfPresent(packPath);
20086
21342
  await this.removeIfPresent(indexPath);
20087
- await rm4(tmpDir, { recursive: true, force: true }).catch(() => {
21343
+ await rm5(tmpDir, { recursive: true, force: true }).catch(() => {
20088
21344
  });
20089
21345
  }
20090
21346
  }
@@ -20215,7 +21471,7 @@ var HandoffCheckpointTracker = class {
20215
21471
  if (!filePath) {
20216
21472
  return;
20217
21473
  }
20218
- await rm4(filePath, { force: true }).catch(() => {
21474
+ await rm5(filePath, { force: true }).catch(() => {
20219
21475
  });
20220
21476
  }
20221
21477
  };
@@ -20462,9 +21718,9 @@ function extractCreatedPrUrl(input) {
20462
21718
 
20463
21719
  // src/adapters/claude/session/jsonl-hydration.ts
20464
21720
  import { randomUUID as randomUUID3 } from "crypto";
20465
- import * as fs12 from "fs/promises";
20466
- import * as os7 from "os";
20467
- import * as path15 from "path";
21721
+ import * as fs13 from "fs/promises";
21722
+ import * as os8 from "os";
21723
+ import * as path16 from "path";
20468
21724
  var CHARS_PER_TOKEN = 4;
20469
21725
  var DEFAULT_MAX_TOKENS = 15e4;
20470
21726
  function estimateTurnTokens(turn) {
@@ -20771,9 +22027,9 @@ ${toolSummary}`);
20771
22027
  }
20772
22028
 
20773
22029
  // src/session-log-writer.ts
20774
- import fs13 from "fs";
22030
+ import fs14 from "fs";
20775
22031
  import fsp from "fs/promises";
20776
- import path16 from "path";
22032
+ import path17 from "path";
20777
22033
  var SessionLogWriter = class _SessionLogWriter {
20778
22034
  static FLUSH_DEBOUNCE_MS = 500;
20779
22035
  static FLUSH_MAX_INTERVAL_MS = 5e3;
@@ -20809,13 +22065,13 @@ var SessionLogWriter = class _SessionLogWriter {
20809
22065
  this.sessions.set(sessionId, { context, currentTurnMessages: [] });
20810
22066
  this.lastFlushAttemptTime.set(sessionId, Date.now());
20811
22067
  if (this.localCachePath) {
20812
- const sessionDir = path16.join(
22068
+ const sessionDir = path17.join(
20813
22069
  this.localCachePath,
20814
22070
  "sessions",
20815
22071
  context.runId
20816
22072
  );
20817
22073
  try {
20818
- fs13.mkdirSync(sessionDir, { recursive: true });
22074
+ fs14.mkdirSync(sessionDir, { recursive: true });
20819
22075
  } catch (error) {
20820
22076
  this.logger.warn("Failed to create local cache directory", {
20821
22077
  sessionDir,
@@ -21067,14 +22323,14 @@ var SessionLogWriter = class _SessionLogWriter {
21067
22323
  if (!this.localCachePath) return;
21068
22324
  const session = this.sessions.get(sessionId);
21069
22325
  if (!session) return;
21070
- const logPath = path16.join(
22326
+ const logPath = path17.join(
21071
22327
  this.localCachePath,
21072
22328
  "sessions",
21073
22329
  session.context.runId,
21074
22330
  "logs.ndjson"
21075
22331
  );
21076
22332
  try {
21077
- fs13.appendFileSync(logPath, `${JSON.stringify(entry)}
22333
+ fs14.appendFileSync(logPath, `${JSON.stringify(entry)}
21078
22334
  `);
21079
22335
  } catch (error) {
21080
22336
  this.logger.warn("Failed to write to local cache", {
@@ -21086,13 +22342,13 @@ var SessionLogWriter = class _SessionLogWriter {
21086
22342
  }
21087
22343
  }
21088
22344
  static async cleanupOldSessions(localCachePath) {
21089
- const sessionsDir = path16.join(localCachePath, "sessions");
22345
+ const sessionsDir = path17.join(localCachePath, "sessions");
21090
22346
  let deleted = 0;
21091
22347
  try {
21092
22348
  const entries = await fsp.readdir(sessionsDir);
21093
22349
  const now = Date.now();
21094
22350
  for (const entry of entries) {
21095
- const entryPath = path16.join(sessionsDir, entry);
22351
+ const entryPath = path17.join(sessionsDir, entry);
21096
22352
  try {
21097
22353
  const stats = await fsp.stat(entryPath);
21098
22354
  if (stats.isDirectory() && now - stats.birthtimeMs > _SessionLogWriter.SESSIONS_MAX_AGE_MS) {
@@ -21109,11 +22365,11 @@ var SessionLogWriter = class _SessionLogWriter {
21109
22365
  };
21110
22366
 
21111
22367
  // src/server/agentsh-runtime.ts
21112
- import { execFile as execFile2 } from "child_process";
22368
+ import { execFile as execFile5 } from "child_process";
21113
22369
  import { readFile as readFile5 } from "fs/promises";
21114
22370
  import { promisify as promisify2 } from "util";
21115
22371
  var AGENTSH_SESSION_ID_FILE = "/tmp/agentsh-session-id";
21116
- var execFileAsync2 = promisify2(execFile2);
22372
+ var execFileAsync2 = promisify2(execFile5);
21117
22373
  function errorMessage(error) {
21118
22374
  return error instanceof Error ? error.message : String(error);
21119
22375
  }
@@ -21130,7 +22386,7 @@ async function getAgentshVersion() {
21130
22386
  }
21131
22387
  async function resolveAgentshRuntimeInfo({
21132
22388
  sessionIdPath = AGENTSH_SESSION_ID_FILE,
21133
- readSessionId = async (path17) => readFile5(path17, "utf8"),
22389
+ readSessionId = async (path18) => readFile5(path18, "utf8"),
21134
22390
  getVersion = getAgentshVersion
21135
22391
  } = {}) {
21136
22392
  let sessionId;
@@ -21184,20 +22440,20 @@ function normalizeCloudPromptContent(content) {
21184
22440
 
21185
22441
  // src/server/jwt.ts
21186
22442
  import jwt from "jsonwebtoken";
21187
- import { z as z2 } from "zod";
22443
+ import { z as z3 } from "zod";
21188
22444
  var SANDBOX_CONNECTION_AUDIENCE = "posthog:sandbox_connection";
21189
- var userDataSchema = z2.object({
21190
- run_id: z2.string(),
21191
- task_id: z2.string(),
21192
- team_id: z2.number(),
21193
- user_id: z2.number(),
21194
- distinct_id: z2.string(),
21195
- mode: z2.enum(["interactive", "background"]).optional().default("interactive")
22445
+ var userDataSchema = z3.object({
22446
+ run_id: z3.string(),
22447
+ task_id: z3.string(),
22448
+ team_id: z3.number(),
22449
+ user_id: z3.number(),
22450
+ distinct_id: z3.string(),
22451
+ mode: z3.enum(["interactive", "background"]).optional().default("interactive")
21196
22452
  });
21197
22453
  var jwtPayloadSchema = userDataSchema.extend({
21198
- exp: z2.number(),
21199
- iat: z2.number().optional(),
21200
- aud: z2.string().optional()
22454
+ exp: z3.number(),
22455
+ iat: z3.number().optional(),
22456
+ aud: z3.string().optional()
21201
22457
  });
21202
22458
  var JwtValidationError = class extends Error {
21203
22459
  constructor(message, code) {
@@ -21235,49 +22491,49 @@ function validateJwt(token, publicKey) {
21235
22491
  }
21236
22492
 
21237
22493
  // src/server/schemas.ts
21238
- import { z as z3 } from "zod/v4";
21239
- var httpHeaderSchema = z3.object({
21240
- name: z3.string(),
21241
- value: z3.string()
22494
+ import { z as z4 } from "zod/v4";
22495
+ var httpHeaderSchema = z4.object({
22496
+ name: z4.string(),
22497
+ value: z4.string()
21242
22498
  });
21243
- var nullishString = z3.string().nullish().transform((value) => value ?? null);
21244
- var handoffLocalGitStateSchema = z3.object({
22499
+ var nullishString = z4.string().nullish().transform((value) => value ?? null);
22500
+ var handoffLocalGitStateSchema = z4.object({
21245
22501
  head: nullishString,
21246
22502
  branch: nullishString,
21247
22503
  upstreamHead: nullishString,
21248
22504
  upstreamRemote: nullishString,
21249
22505
  upstreamMergeRef: nullishString
21250
22506
  });
21251
- var remoteMcpServerSchema = z3.object({
21252
- type: z3.enum(["http", "sse"]),
21253
- name: z3.string().min(1, "MCP server name is required"),
21254
- url: z3.url({ error: "MCP server url must be a valid URL" }),
21255
- headers: z3.array(httpHeaderSchema).default([])
22507
+ var remoteMcpServerSchema = z4.object({
22508
+ type: z4.enum(["http", "sse"]),
22509
+ name: z4.string().min(1, "MCP server name is required"),
22510
+ url: z4.url({ error: "MCP server url must be a valid URL" }),
22511
+ headers: z4.array(httpHeaderSchema).default([])
21256
22512
  });
21257
- var mcpServersSchema = z3.array(remoteMcpServerSchema);
21258
- var claudeCodeConfigSchema = z3.object({
21259
- systemPrompt: z3.union([
21260
- z3.string(),
21261
- z3.object({
21262
- type: z3.literal("preset"),
21263
- preset: z3.literal("claude_code"),
21264
- append: z3.string().optional()
22513
+ var mcpServersSchema = z4.array(remoteMcpServerSchema);
22514
+ var claudeCodeConfigSchema = z4.object({
22515
+ systemPrompt: z4.union([
22516
+ z4.string(),
22517
+ z4.object({
22518
+ type: z4.literal("preset"),
22519
+ preset: z4.literal("claude_code"),
22520
+ append: z4.string().optional()
21265
22521
  })
21266
22522
  ]).optional(),
21267
- plugins: z3.array(z3.object({ type: z3.literal("local"), path: z3.string() })).optional()
22523
+ plugins: z4.array(z4.object({ type: z4.literal("local"), path: z4.string() })).optional()
21268
22524
  });
21269
- var jsonRpcRequestSchema = z3.object({
21270
- jsonrpc: z3.literal("2.0"),
21271
- method: z3.string(),
21272
- params: z3.record(z3.string(), z3.unknown()).optional(),
21273
- id: z3.union([z3.string(), z3.number()]).optional()
22525
+ var jsonRpcRequestSchema = z4.object({
22526
+ jsonrpc: z4.literal("2.0"),
22527
+ method: z4.string(),
22528
+ params: z4.record(z4.string(), z4.unknown()).optional(),
22529
+ id: z4.union([z4.string(), z4.number()]).optional()
21274
22530
  });
21275
- var userMessageParamsSchema = z3.object({
21276
- content: z3.union([
21277
- z3.string().min(1, "Content is required"),
21278
- z3.array(z3.record(z3.string(), z3.unknown())).min(1, "Content is required")
22531
+ var userMessageParamsSchema = z4.object({
22532
+ content: z4.union([
22533
+ z4.string().min(1, "Content is required"),
22534
+ z4.array(z4.record(z4.string(), z4.unknown())).min(1, "Content is required")
21279
22535
  ]).optional(),
21280
- artifacts: z3.array(z3.record(z3.string(), z3.unknown())).optional()
22536
+ artifacts: z4.array(z4.record(z4.string(), z4.unknown())).optional()
21281
22537
  }).refine(
21282
22538
  (params) => {
21283
22539
  const hasContent = typeof params.content === "string" ? params.content.trim().length > 0 : Array.isArray(params.content) && params.content.length > 0;
@@ -21286,27 +22542,27 @@ var userMessageParamsSchema = z3.object({
21286
22542
  },
21287
22543
  { error: "Either content or artifacts are required" }
21288
22544
  );
21289
- var permissionResponseParamsSchema = z3.object({
21290
- requestId: z3.string().min(1, "requestId is required"),
21291
- optionId: z3.string().min(1, "optionId is required"),
21292
- customInput: z3.string().optional(),
21293
- answers: z3.record(z3.string(), z3.string()).optional()
22545
+ var permissionResponseParamsSchema = z4.object({
22546
+ requestId: z4.string().min(1, "requestId is required"),
22547
+ optionId: z4.string().min(1, "optionId is required"),
22548
+ customInput: z4.string().optional(),
22549
+ answers: z4.record(z4.string(), z4.string()).optional()
21294
22550
  });
21295
- var setConfigOptionParamsSchema = z3.object({
21296
- configId: z3.string().min(1, "configId is required"),
21297
- value: z3.string().min(1, "value is required")
22551
+ var setConfigOptionParamsSchema = z4.object({
22552
+ configId: z4.string().min(1, "configId is required"),
22553
+ value: z4.string().min(1, "value is required")
21298
22554
  });
21299
- var refreshSessionParamsSchema = z3.object({
22555
+ var refreshSessionParamsSchema = z4.object({
21300
22556
  mcpServers: mcpServersSchema
21301
22557
  });
21302
- var closeParamsSchema = z3.object({
22558
+ var closeParamsSchema = z4.object({
21303
22559
  localGitState: handoffLocalGitStateSchema.optional()
21304
22560
  }).optional();
21305
22561
  var commandParamsSchemas = {
21306
22562
  user_message: userMessageParamsSchema,
21307
22563
  "posthog/user_message": userMessageParamsSchema,
21308
- cancel: z3.object({}).optional(),
21309
- "posthog/cancel": z3.object({}).optional(),
22564
+ cancel: z4.object({}).optional(),
22565
+ "posthog/cancel": z4.object({}).optional(),
21310
22566
  close: closeParamsSchema,
21311
22567
  "posthog/close": closeParamsSchema,
21312
22568
  permission_response: permissionResponseParamsSchema,
@@ -21330,7 +22586,7 @@ function validateCommandParams(method, params) {
21330
22586
  }
21331
22587
 
21332
22588
  // src/server/agent-server.ts
21333
- var agentErrorClassificationSchema = z4.enum([
22589
+ var agentErrorClassificationSchema = z5.enum([
21334
22590
  "upstream_stream_terminated",
21335
22591
  "upstream_connection_error",
21336
22592
  "upstream_provider_failure",
@@ -21342,8 +22598,8 @@ var upstreamProviderFailureClassifications = /* @__PURE__ */ new Set([
21342
22598
  "upstream_connection_error",
21343
22599
  "upstream_provider_failure"
21344
22600
  ]);
21345
- var errorWithClassificationSchema = z4.object({
21346
- data: z4.object({ classification: agentErrorClassificationSchema })
22601
+ var errorWithClassificationSchema = z5.object({
22602
+ data: z5.object({ classification: agentErrorClassificationSchema })
21347
22603
  });
21348
22604
  var SSE_KEEPALIVE_INTERVAL_MS = 25e3;
21349
22605
  var NdJsonTap = class {
@@ -21664,7 +22920,7 @@ var AgentServer = class {
21664
22920
  return app;
21665
22921
  }
21666
22922
  async start() {
21667
- await new Promise((resolve7) => {
22923
+ await new Promise((resolve8) => {
21668
22924
  this.server = serve(
21669
22925
  {
21670
22926
  fetch: this.app.fetch,
@@ -21674,7 +22930,7 @@ var AgentServer = class {
21674
22930
  this.logger.debug(
21675
22931
  `HTTP server listening on port ${this.config.port}`
21676
22932
  );
21677
- resolve7();
22933
+ resolve8();
21678
22934
  }
21679
22935
  );
21680
22936
  });
@@ -22000,6 +23256,7 @@ var AgentServer = class {
22000
23256
  _meta: {
22001
23257
  sessionId: payload.run_id,
22002
23258
  taskRunId: payload.run_id,
23259
+ taskId: payload.task_id,
22003
23260
  systemPrompt: sessionSystemPrompt,
22004
23261
  ...this.config.model && { model: this.config.model },
22005
23262
  allowedDomains: this.config.allowedDomains,
@@ -22393,15 +23650,15 @@ Continue from where you left off. The user is waiting for your response.`
22393
23650
  throw new Error(`Failed to download artifact ${artifact.name}`);
22394
23651
  }
22395
23652
  const safeName = this.getSafeArtifactName(artifact.name);
22396
- const artifactDir = join12(
23653
+ const artifactDir = join13(
22397
23654
  this.config.repositoryPath ?? "/tmp/workspace",
22398
23655
  ".posthog",
22399
23656
  "attachments",
22400
23657
  runId,
22401
23658
  artifact.id ?? safeName
22402
23659
  );
22403
- await mkdir4(artifactDir, { recursive: true });
22404
- const artifactPath = join12(artifactDir, safeName);
23660
+ await mkdir5(artifactDir, { recursive: true });
23661
+ const artifactPath = join13(artifactDir, safeName);
22405
23662
  await writeFile4(artifactPath, Buffer.from(data));
22406
23663
  return resourceLink(pathToFileURL(artifactPath).toString(), artifact.name, {
22407
23664
  ...artifact.content_type ? { mimeType: artifact.content_type } : {},
@@ -22409,7 +23666,7 @@ Continue from where you left off. The user is waiting for your response.`
22409
23666
  });
22410
23667
  }
22411
23668
  getSafeArtifactName(name2) {
22412
- const baseName = basename2(name2).trim();
23669
+ const baseName = basename3(name2).trim();
22413
23670
  const normalizedName = baseName.replace(/[^\w.-]/g, "_");
22414
23671
  return normalizedName.length > 0 ? normalizedName : "attachment";
22415
23672
  }
@@ -22483,24 +23740,21 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`;
22483
23740
  buildCloudSystemPrompt(prUrl) {
22484
23741
  const taskId = this.config.taskId;
22485
23742
  const shouldAutoCreatePr = this.shouldAutoPublishCloudChanges();
22486
- const attributionInstructions = `
22487
- ## Attribution
22488
- Do NOT use Claude Code's default attribution (no "Co-Authored-By" trailers, no "Generated with [Claude Code]" lines).
23743
+ const signedCommitInstructions = `
23744
+ ## Committing (signed commits required)
23745
+ Commits MUST be signed. \`git commit\` and \`git push\` are blocked in this environment.
23746
+ To commit: stage your changes with \`git add\`, then call the \`git_signed_commit\` tool (full
23747
+ name \`${SIGNED_COMMIT_QUALIFIED_TOOL_NAME}\`) with a \`message\` (and optional \`body\`/\`paths\`).
23748
+ It creates a GitHub-signed ("Verified") commit on the branch and keeps your local checkout in
23749
+ sync. To start a new branch, pass \`branch\` (prefixed with \`posthog-code/\`) \u2014 the tool creates
23750
+ it on the remote for you.
22489
23751
 
22490
- If you create a commit, add the following trailers to the commit message (after a blank line at the end):
23752
+ ## Attribution
23753
+ Do NOT add "Co-Authored-By" trailers or "Generated with [Claude Code]" lines to your
23754
+ commit messages. The \`git_signed_commit\` tool automatically appends the only trailers
23755
+ we want:
22491
23756
  Generated-By: PostHog Code
22492
- Task-Id: ${taskId}
22493
-
22494
- Example:
22495
- \`\`\`
22496
- git commit -m "$(cat <<'EOF'
22497
- fix: resolve login redirect loop
22498
-
22499
- Generated-By: PostHog Code
22500
- Task-Id: ${taskId}
22501
- EOF
22502
- )"
22503
- \`\`\``;
23757
+ Task-Id: ${taskId}`;
22504
23758
  if (prUrl) {
22505
23759
  if (!shouldAutoCreatePr) {
22506
23760
  return `
@@ -22513,7 +23767,7 @@ Do the requested work, but stop with local changes ready for review.
22513
23767
  Important:
22514
23768
  - Do NOT create new commits, push to the branch, or update the pull request unless the user explicitly asks.
22515
23769
  - Do NOT create a new branch or a new pull request.
22516
- ${attributionInstructions}
23770
+ ${signedCommitInstructions}
22517
23771
  `;
22518
23772
  }
22519
23773
  return `
@@ -22523,9 +23777,8 @@ This task already has an open pull request: ${prUrl}
22523
23777
 
22524
23778
  After completing the requested changes:
22525
23779
  1. Check out the existing PR branch with \`gh pr checkout ${prUrl}\`
22526
- 2. Stage and commit all changes with a clear commit message
22527
- 3. Push to the existing PR branch
22528
- 4. For every PR review comment or review thread you addressed, treat the thread as done only after BOTH of these:
23780
+ 2. Stage your changes with \`git add\`, then call the \`git_signed_commit\` tool with a clear \`message\` (do NOT use \`git commit\`/\`git push\` \u2014 they are blocked). This commits to the existing PR branch.
23781
+ 3. For every PR review comment or review thread you addressed, treat the thread as done only after BOTH of these:
22529
23782
  - Reply on the thread with a short note describing what changed (reference the commit SHA when useful) using \`gh api -X POST /repos/{owner}/{repo}/pulls/{n}/comments/{id}/replies -f body='...'\`.
22530
23783
  - Resolve the thread via the \`resolveReviewThread\` GraphQL mutation: \`gh api graphql -f query='mutation($id:ID!){resolveReviewThread(input:{threadId:$id}){thread{isResolved}}}' -f id="<thread-node-id>"\`.
22531
23784
  List unresolved threads first with \`gh api graphql -f query='{repository(owner:"<owner>",name:"<repo>"){pullRequest(number:<n>){reviewThreads(first:100){nodes{id isResolved comments(first:1){nodes{body}}}}}}}'\` so you can resolve each one you fixed.
@@ -22533,7 +23786,7 @@ After completing the requested changes:
22533
23786
  Important:
22534
23787
  - Do NOT create a new branch or a new pull request.
22535
23788
  - Do NOT push fixes for review comments without replying to and resolving each related thread.
22536
- ${attributionInstructions}
23789
+ ${signedCommitInstructions}
22537
23790
  `;
22538
23791
  }
22539
23792
  if (!this.config.repositoryPath) {
@@ -22544,7 +23797,7 @@ When the user asks for code changes:
22544
23797
  When the user explicitly asks to clone or work in a GitHub repository:
22545
23798
  - Clone the repository into /tmp/workspace/repos/<owner>/<repo> using \`gh repo clone <owner>/<repo> /tmp/workspace/repos/<owner>/<repo>\`
22546
23799
  - Work from inside that cloned repository for follow-up code changes
22547
- - If the user explicitly asks you to open or update a pull request, create a branch, commit the requested changes, push it, and open a draft pull request from inside the clone. Before opening the PR, check the cloned repo for a PR template at \`.github/pull_request_template.md\` (or variants; fall back to the org's \`.github\` repo via \`gh api\`) and use it as the body structure, and search for matching open issues with \`gh issue list --search\` to include \`Closes #<n>\` / \`Refs #<n>\` links.
23800
+ - If the user explicitly asks you to open or update a pull request, create a branch, stage your changes with \`git add\` and commit them with the \`git_signed_commit\` tool (do NOT use \`git commit\`/\`git push\` \u2014 they are blocked), and open a draft pull request from inside the clone. Before opening the PR, check the cloned repo for a PR template at \`.github/pull_request_template.md\` (or variants; fall back to the org's \`.github\` repo via \`gh api\`) and use it as the body structure, and search for matching open issues with \`gh issue list --search\` to include \`Closes #<n>\` / \`Refs #<n>\` links.
22548
23801
  - Do NOT create branches, commits, push changes, or open pull requests unless the user explicitly asks for that`;
22549
23802
  return `
22550
23803
  # Cloud Task Execution \u2014 No Repository Mode
@@ -22563,7 +23816,7 @@ ${publishInstructions}
22563
23816
 
22564
23817
  Important:
22565
23818
  - Prefer using MCP tools to answer questions with real data over giving generic advice.
22566
- ${attributionInstructions}
23819
+ ${signedCommitInstructions}
22567
23820
  `;
22568
23821
  }
22569
23822
  if (!shouldAutoCreatePr) {
@@ -22574,21 +23827,20 @@ Do the requested work, but stop with local changes ready for review.
22574
23827
 
22575
23828
  Important:
22576
23829
  - Do NOT create a branch, commit, push, or open a pull request unless the user explicitly asks.
22577
- ${attributionInstructions}
23830
+ ${signedCommitInstructions}
22578
23831
  `;
22579
23832
  }
22580
23833
  return `
22581
23834
  # Cloud Task Execution
22582
23835
 
22583
23836
  After completing the requested changes:
22584
- 1. Create a new branch prefixed with \`posthog-code/\` (e.g. \`posthog-code/fix-login-redirect\`) based on the work done
22585
- 2. Stage and commit all changes with a clear commit message
22586
- 3. Push the branch to origin
22587
- 4. Before opening the PR, prepare the body:
23837
+ 1. Pick a new branch name prefixed with \`posthog-code/\` (e.g. \`posthog-code/fix-login-redirect\`)
23838
+ 2. Stage your changes with \`git add\`, then call the \`git_signed_commit\` tool with \`branch\` set to that name and a clear \`message\` (do NOT use \`git commit\`/\`git push\` \u2014 they are blocked). The tool creates the branch on the remote and a signed commit on it.
23839
+ 3. Before opening the PR, prepare the body:
22588
23840
  - Check the repo for a PR template at \`.github/pull_request_template.md\` (also try \`.github/PULL_REQUEST_TEMPLATE.md\`, \`docs/pull_request_template.md\`, and root variants). If one exists, use its exact section headings as the PR body \u2014 do NOT fall back to a generic Summary/Test plan format.
22589
23841
  - If no repo-level template exists, check the org's \`.github\` repo via \`gh api /repos/<owner>/.github/contents/.github/pull_request_template.md\` (and other common paths) and use that as a fallback.
22590
23842
  - Search for matching open issues with \`gh issue list --state open --search '<keywords>'\` (derive keywords from the branch name, commits, and changed files; \`gh issue view <n>\` to confirm relevance). For every issue this PR would resolve, include a \`Closes #<n>\` line in the body so GitHub auto-links and auto-closes it on merge. For issues that are related but not fully resolved, use \`Refs #<n>\` instead.
22591
- 5. Create a draft pull request using \`gh pr create --draft${this.config.baseBranch ? ` --base ${this.config.baseBranch}` : ""}\` with a descriptive title and the body prepared above. Add the following footer at the end of the PR description:
23843
+ 4. Create a draft pull request using \`gh pr create --draft${this.config.baseBranch ? ` --base ${this.config.baseBranch}` : ""}\` with a descriptive title and the body prepared above. Add the following footer at the end of the PR description:
22592
23844
  \`\`\`
22593
23845
  ---
22594
23846
  *Created with [PostHog Code](https://posthog.com/code?ref=pr)*
@@ -22596,7 +23848,7 @@ After completing the requested changes:
22596
23848
 
22597
23849
  Important:
22598
23850
  - Always create the PR as a draft. Do not ask for confirmation.
22599
- ${attributionInstructions}
23851
+ ${signedCommitInstructions}
22600
23852
  `;
22601
23853
  }
22602
23854
  async getCurrentGitBranch() {
@@ -23052,8 +24304,8 @@ ${attributionInstructions}
23052
24304
  options: params.options,
23053
24305
  toolCall: params.toolCall
23054
24306
  });
23055
- return new Promise((resolve7) => {
23056
- this.pendingPermissions.set(requestId, { resolve: resolve7 });
24307
+ return new Promise((resolve8) => {
24308
+ this.pendingPermissions.set(requestId, { resolve: resolve8 });
23057
24309
  });
23058
24310
  }
23059
24311
  resolvePermission(requestId, optionId, customInput, answers) {
@@ -23075,4 +24327,17 @@ export {
23075
24327
  SSE_KEEPALIVE_INTERVAL_MS,
23076
24328
  UPSTREAM_PROVIDER_FAILURE_MESSAGE
23077
24329
  };
24330
+ /*! Bundled license information:
24331
+
24332
+ git-url-parse/lib/index.js:
24333
+ (*!
24334
+ * buildToken
24335
+ * Builds OAuth token prefix (helper function)
24336
+ *
24337
+ * @name buildToken
24338
+ * @function
24339
+ * @param {GitUrl} obj The parsed Git url object.
24340
+ * @return {String} token prefix
24341
+ *)
24342
+ */
23078
24343
  //# sourceMappingURL=agent-server.js.map