@probelabs/probe 0.6.0-rc225 → 0.6.0-rc227

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 (30) hide show
  1. package/bin/binaries/probe-v0.6.0-rc227-aarch64-apple-darwin.tar.gz +0 -0
  2. package/bin/binaries/probe-v0.6.0-rc227-aarch64-unknown-linux-musl.tar.gz +0 -0
  3. package/bin/binaries/probe-v0.6.0-rc227-x86_64-apple-darwin.tar.gz +0 -0
  4. package/bin/binaries/probe-v0.6.0-rc227-x86_64-pc-windows-msvc.zip +0 -0
  5. package/bin/binaries/probe-v0.6.0-rc227-x86_64-unknown-linux-musl.tar.gz +0 -0
  6. package/build/agent/ProbeAgent.d.ts +24 -0
  7. package/build/agent/ProbeAgent.js +310 -141
  8. package/build/agent/engines/enhanced-claude-code.js +72 -3
  9. package/build/agent/index.js +386 -129
  10. package/build/tools/analyzeAll.js +6 -1
  11. package/build/tools/bash.js +18 -3
  12. package/build/tools/edit.js +19 -10
  13. package/build/tools/vercel.js +17 -7
  14. package/build/utils/path-validation.js +148 -1
  15. package/cjs/agent/ProbeAgent.cjs +683 -389
  16. package/cjs/index.cjs +680 -389
  17. package/package.json +1 -1
  18. package/src/agent/ProbeAgent.d.ts +24 -0
  19. package/src/agent/ProbeAgent.js +310 -141
  20. package/src/agent/engines/enhanced-claude-code.js +72 -3
  21. package/src/tools/analyzeAll.js +6 -1
  22. package/src/tools/bash.js +18 -3
  23. package/src/tools/edit.js +19 -10
  24. package/src/tools/vercel.js +17 -7
  25. package/src/utils/path-validation.js +148 -1
  26. package/bin/binaries/probe-v0.6.0-rc225-aarch64-apple-darwin.tar.gz +0 -0
  27. package/bin/binaries/probe-v0.6.0-rc225-aarch64-unknown-linux-musl.tar.gz +0 -0
  28. package/bin/binaries/probe-v0.6.0-rc225-x86_64-apple-darwin.tar.gz +0 -0
  29. package/bin/binaries/probe-v0.6.0-rc225-x86_64-pc-windows-msvc.zip +0 -0
  30. package/bin/binaries/probe-v0.6.0-rc225-x86_64-unknown-linux-musl.tar.gz +0 -0
package/cjs/index.cjs CHANGED
@@ -1645,6 +1645,25 @@ var init_error_types = __esm({
1645
1645
  });
1646
1646
 
1647
1647
  // src/utils/path-validation.js
1648
+ function safeRealpath(inputPath) {
1649
+ try {
1650
+ return (0, import_fs3.realpathSync)(inputPath);
1651
+ } catch (error2) {
1652
+ const normalized = import_path4.default.normalize(inputPath);
1653
+ const parts = normalized.split(import_path4.default.sep);
1654
+ for (let i5 = parts.length - 1; i5 >= 0; i5--) {
1655
+ const ancestorPath = parts.slice(0, i5).join(import_path4.default.sep) || import_path4.default.sep;
1656
+ try {
1657
+ const resolvedAncestor = (0, import_fs3.realpathSync)(ancestorPath);
1658
+ const remainingParts = parts.slice(i5);
1659
+ return import_path4.default.join(resolvedAncestor, ...remainingParts);
1660
+ } catch (ancestorError) {
1661
+ continue;
1662
+ }
1663
+ }
1664
+ return normalized;
1665
+ }
1666
+ }
1648
1667
  async function validateCwdPath(inputPath, defaultPath = process.cwd()) {
1649
1668
  const targetPath = inputPath || defaultPath;
1650
1669
  const normalizedPath = import_path4.default.normalize(import_path4.default.resolve(targetPath));
@@ -1677,6 +1696,53 @@ async function validateCwdPath(inputPath, defaultPath = process.cwd()) {
1677
1696
  }
1678
1697
  return normalizedPath;
1679
1698
  }
1699
+ function getCommonPrefix(folders) {
1700
+ if (!folders || folders.length === 0) {
1701
+ return process.cwd();
1702
+ }
1703
+ if (folders.length === 1) {
1704
+ return safeRealpath(folders[0]);
1705
+ }
1706
+ const normalized = folders.map((f5) => safeRealpath(f5));
1707
+ const segments = normalized.map((f5) => f5.split(import_path4.default.sep));
1708
+ const minLen = Math.min(...segments.map((s5) => s5.length));
1709
+ const commonSegments = [];
1710
+ for (let i5 = 0; i5 < minLen; i5++) {
1711
+ const segment = segments[0][i5];
1712
+ if (segments.every((s5) => s5[i5] === segment)) {
1713
+ commonSegments.push(segment);
1714
+ } else {
1715
+ break;
1716
+ }
1717
+ }
1718
+ if (commonSegments.length === 0) {
1719
+ return normalized[0];
1720
+ }
1721
+ if (commonSegments.length === 1 && /^[a-zA-Z]:$/.test(commonSegments[0])) {
1722
+ return normalized[0];
1723
+ }
1724
+ if (commonSegments.length === 1 && commonSegments[0] === "") {
1725
+ return normalized[0];
1726
+ }
1727
+ return commonSegments.join(import_path4.default.sep);
1728
+ }
1729
+ function toRelativePath(absolutePath, workspaceRoot) {
1730
+ if (!absolutePath || !workspaceRoot) {
1731
+ return absolutePath;
1732
+ }
1733
+ let normalized = safeRealpath(absolutePath);
1734
+ let normalizedRoot = safeRealpath(workspaceRoot);
1735
+ while (normalizedRoot.length > 1 && normalizedRoot.endsWith(import_path4.default.sep)) {
1736
+ normalizedRoot = normalizedRoot.slice(0, -1);
1737
+ }
1738
+ if (normalized === normalizedRoot) {
1739
+ return ".";
1740
+ }
1741
+ if (normalized.startsWith(normalizedRoot + import_path4.default.sep)) {
1742
+ return import_path4.default.relative(normalizedRoot, normalized);
1743
+ }
1744
+ return absolutePath;
1745
+ }
1680
1746
  var import_path4, import_fs3;
1681
1747
  var init_path_validation = __esm({
1682
1748
  "src/utils/path-validation.js"() {
@@ -16013,8 +16079,45 @@ var require_dist_cjs29 = __commonJS({
16013
16079
  }
16014
16080
  });
16015
16081
 
16016
- // node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer/dist-cjs/index.js
16082
+ // node_modules/@aws-sdk/util-format-url/dist-cjs/index.js
16017
16083
  var require_dist_cjs30 = __commonJS({
16084
+ "node_modules/@aws-sdk/util-format-url/dist-cjs/index.js"(exports2) {
16085
+ "use strict";
16086
+ var querystringBuilder = require_dist_cjs14();
16087
+ function formatUrl(request) {
16088
+ const { port, query: query2 } = request;
16089
+ let { protocol, path: path9, hostname } = request;
16090
+ if (protocol && protocol.slice(-1) !== ":") {
16091
+ protocol += ":";
16092
+ }
16093
+ if (port) {
16094
+ hostname += `:${port}`;
16095
+ }
16096
+ if (path9 && path9.charAt(0) !== "/") {
16097
+ path9 = `/${path9}`;
16098
+ }
16099
+ let queryString = query2 ? querystringBuilder.buildQueryString(query2) : "";
16100
+ if (queryString && queryString[0] !== "?") {
16101
+ queryString = `?${queryString}`;
16102
+ }
16103
+ let auth = "";
16104
+ if (request.username != null || request.password != null) {
16105
+ const username = request.username ?? "";
16106
+ const password = request.password ?? "";
16107
+ auth = `${username}:${password}@`;
16108
+ }
16109
+ let fragment = "";
16110
+ if (request.fragment) {
16111
+ fragment = `#${request.fragment}`;
16112
+ }
16113
+ return `${protocol}//${auth}${hostname}${path9}${queryString}${fragment}`;
16114
+ }
16115
+ exports2.formatUrl = formatUrl;
16116
+ }
16117
+ });
16118
+
16119
+ // node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer/dist-cjs/index.js
16120
+ var require_dist_cjs31 = __commonJS({
16018
16121
  "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer/dist-cjs/index.js"(exports2, module2) {
16019
16122
  var __defProp2 = Object.defineProperty;
16020
16123
  var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
@@ -16044,7 +16147,7 @@ var require_dist_cjs30 = __commonJS({
16044
16147
  });
16045
16148
 
16046
16149
  // node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from/dist-cjs/index.js
16047
- var require_dist_cjs31 = __commonJS({
16150
+ var require_dist_cjs32 = __commonJS({
16048
16151
  "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from/dist-cjs/index.js"(exports2, module2) {
16049
16152
  var __defProp2 = Object.defineProperty;
16050
16153
  var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
@@ -16070,7 +16173,7 @@ var require_dist_cjs31 = __commonJS({
16070
16173
  fromString: () => fromString
16071
16174
  });
16072
16175
  module2.exports = __toCommonJS2(src_exports);
16073
- var import_is_array_buffer = require_dist_cjs30();
16176
+ var import_is_array_buffer = require_dist_cjs31();
16074
16177
  var import_buffer = require("buffer");
16075
16178
  var fromArrayBuffer = /* @__PURE__ */ __name((input, offset = 0, length = input.byteLength - offset) => {
16076
16179
  if (!(0, import_is_array_buffer.isArrayBuffer)(input)) {
@@ -16088,7 +16191,7 @@ var require_dist_cjs31 = __commonJS({
16088
16191
  });
16089
16192
 
16090
16193
  // node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8/dist-cjs/index.js
16091
- var require_dist_cjs32 = __commonJS({
16194
+ var require_dist_cjs33 = __commonJS({
16092
16195
  "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8/dist-cjs/index.js"(exports2, module2) {
16093
16196
  var __defProp2 = Object.defineProperty;
16094
16197
  var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
@@ -16115,7 +16218,7 @@ var require_dist_cjs32 = __commonJS({
16115
16218
  toUtf8: () => toUtf811
16116
16219
  });
16117
16220
  module2.exports = __toCommonJS2(src_exports);
16118
- var import_util_buffer_from = require_dist_cjs31();
16221
+ var import_util_buffer_from = require_dist_cjs32();
16119
16222
  var fromUtf88 = /* @__PURE__ */ __name((input) => {
16120
16223
  const buf = (0, import_util_buffer_from.fromString)(input, "utf8");
16121
16224
  return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength / Uint8Array.BYTES_PER_ELEMENT);
@@ -16147,7 +16250,7 @@ var require_convertToBuffer = __commonJS({
16147
16250
  "use strict";
16148
16251
  Object.defineProperty(exports2, "__esModule", { value: true });
16149
16252
  exports2.convertToBuffer = void 0;
16150
- var util_utf8_1 = require_dist_cjs32();
16253
+ var util_utf8_1 = require_dist_cjs33();
16151
16254
  var fromUtf88 = typeof Buffer !== "undefined" && Buffer.from ? function(input) {
16152
16255
  return Buffer.from(input, "utf8");
16153
16256
  } : util_utf8_1.fromUtf8;
@@ -16594,7 +16697,7 @@ var require_main3 = __commonJS({
16594
16697
  });
16595
16698
 
16596
16699
  // node_modules/@smithy/eventstream-codec/dist-cjs/index.js
16597
- var require_dist_cjs33 = __commonJS({
16700
+ var require_dist_cjs34 = __commonJS({
16598
16701
  "node_modules/@smithy/eventstream-codec/dist-cjs/index.js"(exports2) {
16599
16702
  "use strict";
16600
16703
  var crc32 = require_main3();
@@ -16977,48 +17080,11 @@ var require_dist_cjs33 = __commonJS({
16977
17080
  }
16978
17081
  });
16979
17082
 
16980
- // node_modules/@aws-sdk/util-format-url/dist-cjs/index.js
16981
- var require_dist_cjs34 = __commonJS({
16982
- "node_modules/@aws-sdk/util-format-url/dist-cjs/index.js"(exports2) {
16983
- "use strict";
16984
- var querystringBuilder = require_dist_cjs14();
16985
- function formatUrl(request) {
16986
- const { port, query: query2 } = request;
16987
- let { protocol, path: path9, hostname } = request;
16988
- if (protocol && protocol.slice(-1) !== ":") {
16989
- protocol += ":";
16990
- }
16991
- if (port) {
16992
- hostname += `:${port}`;
16993
- }
16994
- if (path9 && path9.charAt(0) !== "/") {
16995
- path9 = `/${path9}`;
16996
- }
16997
- let queryString = query2 ? querystringBuilder.buildQueryString(query2) : "";
16998
- if (queryString && queryString[0] !== "?") {
16999
- queryString = `?${queryString}`;
17000
- }
17001
- let auth = "";
17002
- if (request.username != null || request.password != null) {
17003
- const username = request.username ?? "";
17004
- const password = request.password ?? "";
17005
- auth = `${username}:${password}@`;
17006
- }
17007
- let fragment = "";
17008
- if (request.fragment) {
17009
- fragment = `#${request.fragment}`;
17010
- }
17011
- return `${protocol}//${auth}${hostname}${path9}${queryString}${fragment}`;
17012
- }
17013
- exports2.formatUrl = formatUrl;
17014
- }
17015
- });
17016
-
17017
17083
  // node_modules/@smithy/eventstream-serde-universal/dist-cjs/index.js
17018
17084
  var require_dist_cjs35 = __commonJS({
17019
17085
  "node_modules/@smithy/eventstream-serde-universal/dist-cjs/index.js"(exports2) {
17020
17086
  "use strict";
17021
- var eventstreamCodec = require_dist_cjs33();
17087
+ var eventstreamCodec = require_dist_cjs34();
17022
17088
  function getChunkedStream(source) {
17023
17089
  let currentMessageTotalLength = 0;
17024
17090
  let currentMessagePendingLength = 0;
@@ -17203,183 +17269,20 @@ var require_dist_cjs36 = __commonJS({
17203
17269
  var require_dist_cjs37 = __commonJS({
17204
17270
  "node_modules/@aws-sdk/middleware-websocket/dist-cjs/index.js"(exports2) {
17205
17271
  "use strict";
17206
- var eventstreamCodec = require_dist_cjs33();
17207
- var utilHexEncoding = require_dist_cjs17();
17208
- var protocolHttp = require_dist_cjs2();
17209
- var utilFormatUrl = require_dist_cjs34();
17272
+ var utilFormatUrl = require_dist_cjs30();
17210
17273
  var eventstreamSerdeBrowser = require_dist_cjs36();
17211
17274
  var fetchHttpHandler = require_dist_cjs16();
17212
- var getEventSigningTransformStream = (initialSignature, messageSigner, eventStreamCodec, systemClockOffsetProvider) => {
17213
- let priorSignature = initialSignature;
17214
- const transformer = {
17215
- start() {
17216
- },
17217
- async transform(chunk, controller) {
17218
- try {
17219
- const now = new Date(Date.now() + await systemClockOffsetProvider());
17220
- const dateHeader = {
17221
- ":date": { type: "timestamp", value: now }
17222
- };
17223
- const signedMessage = await messageSigner.sign({
17224
- message: {
17225
- body: chunk,
17226
- headers: dateHeader
17227
- },
17228
- priorSignature
17229
- }, {
17230
- signingDate: now
17231
- });
17232
- priorSignature = signedMessage.signature;
17233
- const serializedSigned = eventStreamCodec.encode({
17234
- headers: {
17235
- ...dateHeader,
17236
- ":chunk-signature": {
17237
- type: "binary",
17238
- value: utilHexEncoding.fromHex(signedMessage.signature)
17239
- }
17240
- },
17241
- body: chunk
17242
- });
17243
- controller.enqueue(serializedSigned);
17244
- } catch (error2) {
17245
- controller.error(error2);
17246
- }
17247
- }
17248
- };
17249
- return new TransformStream({ ...transformer });
17250
- };
17251
- var EventStreamPayloadHandler = class {
17252
- messageSigner;
17253
- eventStreamCodec;
17254
- systemClockOffsetProvider;
17255
- constructor(options) {
17256
- this.messageSigner = options.messageSigner;
17257
- this.eventStreamCodec = new eventstreamCodec.EventStreamCodec(options.utf8Encoder, options.utf8Decoder);
17258
- this.systemClockOffsetProvider = async () => options.systemClockOffset ?? 0;
17259
- }
17260
- async handle(next, args, context = {}) {
17261
- const request = args.request;
17262
- const { body: payload2, headers, query: query2 } = request;
17263
- if (!(payload2 instanceof ReadableStream)) {
17264
- throw new Error("Eventstream payload must be a ReadableStream.");
17265
- }
17266
- const placeHolderStream = new TransformStream();
17267
- request.body = placeHolderStream.readable;
17268
- const match2 = (headers?.authorization ?? "").match(/Signature=(\w+)$/);
17269
- const priorSignature = (match2 ?? [])[1] ?? (query2 && query2["X-Amz-Signature"]) ?? "";
17270
- const signingStream = getEventSigningTransformStream(priorSignature, await this.messageSigner(), this.eventStreamCodec, this.systemClockOffsetProvider);
17271
- payload2.pipeThrough(signingStream).pipeThrough(placeHolderStream);
17272
- let result;
17273
- try {
17274
- result = await next(args);
17275
- } catch (e5) {
17276
- const p5 = payload2.cancel?.();
17277
- if (p5 instanceof Promise) {
17278
- p5.catch(() => {
17279
- });
17280
- }
17281
- throw e5;
17282
- }
17283
- return result;
17284
- }
17285
- };
17286
- var eventStreamPayloadHandlerProvider = (options) => new EventStreamPayloadHandler(options);
17287
- var injectSessionIdMiddleware = () => (next) => async (args) => {
17288
- const requestParams = {
17289
- ...args.input
17290
- };
17291
- const response = await next(args);
17292
- const output = response.output;
17293
- if (requestParams.SessionId && output.SessionId == null) {
17294
- output.SessionId = requestParams.SessionId;
17295
- }
17296
- return response;
17297
- };
17298
- var injectSessionIdMiddlewareOptions = {
17299
- step: "initialize",
17300
- name: "injectSessionIdMiddleware",
17301
- tags: ["WEBSOCKET", "EVENT_STREAM"],
17302
- override: true
17303
- };
17304
- var websocketEndpointMiddleware = (config, options) => (next) => (args) => {
17305
- const { request } = args;
17306
- if (protocolHttp.HttpRequest.isInstance(request) && config.requestHandler.metadata?.handlerProtocol?.toLowerCase().includes("websocket")) {
17307
- request.protocol = "wss:";
17308
- request.method = "GET";
17309
- request.path = `${request.path}-websocket`;
17310
- const { headers } = request;
17311
- delete headers["content-type"];
17312
- delete headers["x-amz-content-sha256"];
17313
- for (const name14 of Object.keys(headers)) {
17314
- if (name14.indexOf(options.headerPrefix) === 0) {
17315
- const chunkedName = name14.replace(options.headerPrefix, "");
17316
- request.query[chunkedName] = headers[name14];
17317
- }
17318
- }
17319
- if (headers["x-amz-user-agent"]) {
17320
- request.query["user-agent"] = headers["x-amz-user-agent"];
17321
- }
17322
- request.headers = { host: headers.host ?? request.hostname };
17323
- }
17324
- return next(args);
17325
- };
17326
- var websocketEndpointMiddlewareOptions = {
17327
- name: "websocketEndpointMiddleware",
17328
- tags: ["WEBSOCKET", "EVENT_STREAM"],
17329
- relation: "after",
17330
- toMiddleware: "eventStreamHeaderMiddleware",
17331
- override: true
17332
- };
17333
- var getWebSocketPlugin = (config, options) => ({
17334
- applyToStack: (clientStack) => {
17335
- clientStack.addRelativeTo(websocketEndpointMiddleware(config, options), websocketEndpointMiddlewareOptions);
17336
- clientStack.add(injectSessionIdMiddleware(), injectSessionIdMiddlewareOptions);
17337
- }
17338
- });
17275
+ var protocolHttp = require_dist_cjs2();
17276
+ var utilBase64 = require_dist_cjs12();
17277
+ var eventstreamCodec = require_dist_cjs34();
17278
+ var utilHexEncoding = require_dist_cjs17();
17339
17279
  var isWebSocketRequest = (request) => request.protocol === "ws:" || request.protocol === "wss:";
17340
- var WebsocketSignatureV4 = class {
17341
- signer;
17342
- constructor(options) {
17343
- this.signer = options.signer;
17344
- }
17345
- presign(originalRequest, options = {}) {
17346
- return this.signer.presign(originalRequest, options);
17347
- }
17348
- async sign(toSign, options) {
17349
- if (protocolHttp.HttpRequest.isInstance(toSign) && isWebSocketRequest(toSign)) {
17350
- const signedRequest = await this.signer.presign({ ...toSign, body: "" }, {
17351
- ...options,
17352
- expiresIn: 60,
17353
- unsignableHeaders: new Set(Object.keys(toSign.headers).filter((header) => header !== "host"))
17354
- });
17355
- return {
17356
- ...signedRequest,
17357
- body: toSign.body
17358
- };
17359
- } else {
17360
- return this.signer.sign(toSign, options);
17361
- }
17362
- }
17363
- };
17364
- var resolveWebSocketConfig = (input) => {
17365
- const { signer } = input;
17366
- return Object.assign(input, {
17367
- signer: async (authScheme) => {
17368
- const signerObj = await signer(authScheme);
17369
- if (validateSigner(signerObj)) {
17370
- return new WebsocketSignatureV4({ signer: signerObj });
17371
- }
17372
- throw new Error("Expected WebsocketSignatureV4 signer, please check the client constructor.");
17373
- }
17374
- });
17375
- };
17376
- var validateSigner = (signer) => !!signer;
17377
- var DEFAULT_WS_CONNECTION_TIMEOUT_MS = 2e3;
17280
+ var DEFAULT_WS_CONNECTION_TIMEOUT_MS = 3e3;
17378
17281
  var WebSocketFetchHandler = class _WebSocketFetchHandler {
17379
17282
  metadata = {
17380
17283
  handlerProtocol: "websocket/h1.1"
17381
17284
  };
17382
- config;
17285
+ config = {};
17383
17286
  configPromise;
17384
17287
  httpHandler;
17385
17288
  sockets = {};
@@ -17391,12 +17294,19 @@ var require_dist_cjs37 = __commonJS({
17391
17294
  }
17392
17295
  constructor(options, httpHandler = new fetchHttpHandler.FetchHttpHandler()) {
17393
17296
  this.httpHandler = httpHandler;
17297
+ const setConfig = (opts) => {
17298
+ this.config = {
17299
+ ...opts ?? {}
17300
+ };
17301
+ return this.config;
17302
+ };
17394
17303
  if (typeof options === "function") {
17395
17304
  this.config = {};
17396
- this.configPromise = options().then((opts) => this.config = opts ?? {});
17305
+ this.configPromise = options().then((opts) => {
17306
+ return setConfig(opts);
17307
+ });
17397
17308
  } else {
17398
- this.config = options ?? {};
17399
- this.configPromise = Promise.resolve(this.config);
17309
+ this.configPromise = Promise.resolve(setConfig(options));
17400
17310
  }
17401
17311
  }
17402
17312
  destroy() {
@@ -17408,17 +17318,20 @@ var require_dist_cjs37 = __commonJS({
17408
17318
  }
17409
17319
  }
17410
17320
  async handle(request) {
17321
+ this.config = await this.configPromise;
17322
+ const { logger: logger2 } = this.config;
17411
17323
  if (!isWebSocketRequest(request)) {
17324
+ logger2?.debug?.(`@aws-sdk - ws fetching ${request.protocol}${request.hostname}${request.path}`);
17412
17325
  return this.httpHandler.handle(request);
17413
17326
  }
17414
17327
  const url = utilFormatUrl.formatUrl(request);
17328
+ logger2?.debug?.(`@aws-sdk - ws connecting ${url.split("?")[0]}`);
17415
17329
  const socket = new WebSocket(url);
17416
17330
  if (!this.sockets[url]) {
17417
17331
  this.sockets[url] = [];
17418
17332
  }
17419
17333
  this.sockets[url].push(socket);
17420
17334
  socket.binaryType = "arraybuffer";
17421
- this.config = await this.configPromise;
17422
17335
  const { connectionTimeout = DEFAULT_WS_CONNECTION_TIMEOUT_MS } = this.config;
17423
17336
  await this.waitForReady(socket, connectionTimeout);
17424
17337
  const { body } = request;
@@ -17450,7 +17363,8 @@ var require_dist_cjs37 = __commonJS({
17450
17363
  this.removeNotUsableSockets(socket.url);
17451
17364
  reject2({
17452
17365
  $metadata: {
17453
- httpStatusCode: 500
17366
+ httpStatusCode: 500,
17367
+ websocketSynthetic500Error: true
17454
17368
  }
17455
17369
  });
17456
17370
  }, connectionTimeout);
@@ -17461,42 +17375,57 @@ var require_dist_cjs37 = __commonJS({
17461
17375
  });
17462
17376
  }
17463
17377
  connect(socket, data2) {
17464
- let streamError = void 0;
17465
- let socketErrorOccurred = false;
17466
- let reject2 = () => {
17467
- };
17468
- let resolve7 = () => {
17378
+ const messageQueue = [];
17379
+ let pendingResolve = null;
17380
+ let pendingReject = null;
17381
+ const push = (item) => {
17382
+ if (pendingResolve) {
17383
+ if (item.error) {
17384
+ pendingReject(item.error);
17385
+ } else {
17386
+ pendingResolve({ done: item.done, value: item.value });
17387
+ }
17388
+ pendingResolve = null;
17389
+ pendingReject = null;
17390
+ } else {
17391
+ messageQueue.push(item);
17392
+ }
17469
17393
  };
17470
17394
  socket.onmessage = (event) => {
17471
- resolve7({
17472
- done: false,
17473
- value: new Uint8Array(event.data)
17474
- });
17395
+ const { data: data3 } = event;
17396
+ if (typeof data3 === "string") {
17397
+ push({
17398
+ done: false,
17399
+ value: utilBase64.fromBase64(data3)
17400
+ });
17401
+ } else {
17402
+ push({
17403
+ done: false,
17404
+ value: new Uint8Array(data3)
17405
+ });
17406
+ }
17475
17407
  };
17476
- socket.onerror = (error2) => {
17477
- socketErrorOccurred = true;
17408
+ socket.onerror = (event) => {
17478
17409
  socket.close();
17479
- reject2(error2);
17410
+ push({ done: true, error: event });
17480
17411
  };
17481
17412
  socket.onclose = () => {
17482
17413
  this.removeNotUsableSockets(socket.url);
17483
- if (socketErrorOccurred)
17484
- return;
17485
- if (streamError) {
17486
- reject2(streamError);
17487
- } else {
17488
- resolve7({
17489
- done: true,
17490
- value: void 0
17491
- });
17492
- }
17414
+ push({ done: true });
17493
17415
  };
17494
17416
  const outputStream = {
17495
17417
  [Symbol.asyncIterator]: () => ({
17496
- next: () => {
17497
- return new Promise((_resolve, _reject) => {
17498
- resolve7 = _resolve;
17499
- reject2 = _reject;
17418
+ async next() {
17419
+ if (messageQueue.length > 0) {
17420
+ const item = messageQueue.shift();
17421
+ if (item.error) {
17422
+ throw item.error;
17423
+ }
17424
+ return { done: item.done, value: item.value };
17425
+ }
17426
+ return new Promise((resolve7, reject2) => {
17427
+ pendingResolve = resolve7;
17428
+ pendingReject = reject2;
17500
17429
  });
17501
17430
  }
17502
17431
  })
@@ -17511,7 +17440,10 @@ var require_dist_cjs37 = __commonJS({
17511
17440
  }
17512
17441
  }
17513
17442
  } catch (err) {
17514
- streamError = err;
17443
+ push({
17444
+ done: true,
17445
+ error: err
17446
+ });
17515
17447
  } finally {
17516
17448
  socket.close(1e3);
17517
17449
  }
@@ -17535,6 +17467,174 @@ var require_dist_cjs37 = __commonJS({
17535
17467
  };
17536
17468
  var toReadableStream = (asyncIterable) => typeof ReadableStream === "function" ? eventstreamSerdeBrowser.iterableToReadableStream(asyncIterable) : asyncIterable;
17537
17469
  var isReadableStream = (payload2) => typeof ReadableStream === "function" && payload2 instanceof ReadableStream;
17470
+ var websocketEndpointMiddleware = (config, options) => (next) => (args) => {
17471
+ const { request } = args;
17472
+ if (protocolHttp.HttpRequest.isInstance(request) && config.requestHandler.metadata?.handlerProtocol?.toLowerCase().includes("websocket")) {
17473
+ request.protocol = "wss:";
17474
+ request.method = "GET";
17475
+ request.path = `${request.path}-websocket`;
17476
+ const { headers } = request;
17477
+ delete headers["content-type"];
17478
+ delete headers["x-amz-content-sha256"];
17479
+ for (const name14 of Object.keys(headers)) {
17480
+ if (name14.indexOf(options.headerPrefix) === 0) {
17481
+ const chunkedName = name14.replace(options.headerPrefix, "");
17482
+ request.query[chunkedName] = headers[name14];
17483
+ }
17484
+ }
17485
+ if (headers["x-amz-user-agent"]) {
17486
+ request.query["user-agent"] = headers["x-amz-user-agent"];
17487
+ }
17488
+ request.headers = { host: headers.host ?? request.hostname };
17489
+ }
17490
+ return next(args);
17491
+ };
17492
+ var websocketEndpointMiddlewareOptions = {
17493
+ name: "websocketEndpointMiddleware",
17494
+ tags: ["WEBSOCKET", "EVENT_STREAM"],
17495
+ relation: "after",
17496
+ toMiddleware: "eventStreamHeaderMiddleware",
17497
+ override: true
17498
+ };
17499
+ var injectSessionIdMiddleware = () => (next) => async (args) => {
17500
+ const requestParams = {
17501
+ ...args.input
17502
+ };
17503
+ const response = await next(args);
17504
+ const output = response.output;
17505
+ if (requestParams.SessionId && output.SessionId == null) {
17506
+ output.SessionId = requestParams.SessionId;
17507
+ }
17508
+ return response;
17509
+ };
17510
+ var injectSessionIdMiddlewareOptions = {
17511
+ step: "initialize",
17512
+ name: "injectSessionIdMiddleware",
17513
+ tags: ["WEBSOCKET", "EVENT_STREAM"],
17514
+ override: true
17515
+ };
17516
+ var getWebSocketPlugin = (config, options) => ({
17517
+ applyToStack: (clientStack) => {
17518
+ clientStack.addRelativeTo(websocketEndpointMiddleware(config, options), websocketEndpointMiddlewareOptions);
17519
+ clientStack.add(injectSessionIdMiddleware(), injectSessionIdMiddlewareOptions);
17520
+ }
17521
+ });
17522
+ var WebsocketSignatureV4 = class {
17523
+ signer;
17524
+ constructor(options) {
17525
+ this.signer = options.signer;
17526
+ }
17527
+ presign(originalRequest, options = {}) {
17528
+ return this.signer.presign(originalRequest, options);
17529
+ }
17530
+ async sign(toSign, options) {
17531
+ if (protocolHttp.HttpRequest.isInstance(toSign) && isWebSocketRequest(toSign)) {
17532
+ const signedRequest = await this.signer.presign({ ...toSign, body: "" }, {
17533
+ ...options,
17534
+ expiresIn: 60,
17535
+ unsignableHeaders: new Set(Object.keys(toSign.headers).filter((header) => header !== "host"))
17536
+ });
17537
+ return {
17538
+ ...signedRequest,
17539
+ body: toSign.body
17540
+ };
17541
+ } else {
17542
+ return this.signer.sign(toSign, options);
17543
+ }
17544
+ }
17545
+ signMessage(message, args) {
17546
+ return this.signer.signMessage(message, args);
17547
+ }
17548
+ };
17549
+ var resolveWebSocketConfig = (input) => {
17550
+ const { signer } = input;
17551
+ return Object.assign(input, {
17552
+ signer: async (authScheme) => {
17553
+ const signerObj = await signer(authScheme);
17554
+ if (validateSigner(signerObj)) {
17555
+ return new WebsocketSignatureV4({ signer: signerObj });
17556
+ }
17557
+ throw new Error("Expected WebsocketSignatureV4 signer, please check the client constructor.");
17558
+ }
17559
+ });
17560
+ };
17561
+ var validateSigner = (signer) => !!signer;
17562
+ var EventSigningTransformStream = class extends TransformStream {
17563
+ constructor(initialSignature, messageSigner, eventStreamCodec, systemClockOffsetProvider) {
17564
+ let priorSignature = initialSignature;
17565
+ super({
17566
+ start() {
17567
+ },
17568
+ async transform(chunk, controller) {
17569
+ try {
17570
+ const now = new Date(Date.now() + await systemClockOffsetProvider());
17571
+ const dateHeader = {
17572
+ ":date": { type: "timestamp", value: now }
17573
+ };
17574
+ const signedMessage = await messageSigner.sign({
17575
+ message: {
17576
+ body: chunk,
17577
+ headers: dateHeader
17578
+ },
17579
+ priorSignature
17580
+ }, {
17581
+ signingDate: now
17582
+ });
17583
+ priorSignature = signedMessage.signature;
17584
+ const serializedSigned = eventStreamCodec.encode({
17585
+ headers: {
17586
+ ...dateHeader,
17587
+ ":chunk-signature": {
17588
+ type: "binary",
17589
+ value: utilHexEncoding.fromHex(signedMessage.signature)
17590
+ }
17591
+ },
17592
+ body: chunk
17593
+ });
17594
+ controller.enqueue(serializedSigned);
17595
+ } catch (error2) {
17596
+ controller.error(error2);
17597
+ }
17598
+ }
17599
+ });
17600
+ }
17601
+ };
17602
+ var EventStreamPayloadHandler = class {
17603
+ messageSigner;
17604
+ eventStreamCodec;
17605
+ systemClockOffsetProvider;
17606
+ constructor(options) {
17607
+ this.messageSigner = options.messageSigner;
17608
+ this.eventStreamCodec = new eventstreamCodec.EventStreamCodec(options.utf8Encoder, options.utf8Decoder);
17609
+ this.systemClockOffsetProvider = async () => options.systemClockOffset ?? 0;
17610
+ }
17611
+ async handle(next, args, context = {}) {
17612
+ const request = args.request;
17613
+ const { body: payload2, headers, query: query2 } = request;
17614
+ if (!(payload2 instanceof ReadableStream)) {
17615
+ throw new Error("Eventstream payload must be a ReadableStream.");
17616
+ }
17617
+ const placeHolderStream = new TransformStream();
17618
+ request.body = placeHolderStream.readable;
17619
+ const match2 = (headers?.authorization ?? "").match(/Signature=(\w+)$/);
17620
+ const priorSignature = (match2 ?? [])[1] ?? (query2 && query2["X-Amz-Signature"]) ?? "";
17621
+ const signingStream = new EventSigningTransformStream(priorSignature, await this.messageSigner(), this.eventStreamCodec, this.systemClockOffsetProvider);
17622
+ payload2.pipeThrough(signingStream).pipeThrough(placeHolderStream);
17623
+ let result;
17624
+ try {
17625
+ result = await next(args);
17626
+ } catch (e5) {
17627
+ const p5 = payload2.cancel?.();
17628
+ if (p5 instanceof Promise) {
17629
+ p5.catch(() => {
17630
+ });
17631
+ }
17632
+ throw e5;
17633
+ }
17634
+ return result;
17635
+ }
17636
+ };
17637
+ var eventStreamPayloadHandlerProvider = (options) => new EventStreamPayloadHandler(options);
17538
17638
  exports2.WebSocketFetchHandler = WebSocketFetchHandler;
17539
17639
  exports2.eventStreamPayloadHandlerProvider = eventStreamPayloadHandlerProvider;
17540
17640
  exports2.getWebSocketPlugin = getWebSocketPlugin;
@@ -19182,7 +19282,7 @@ var require_package2 = __commonJS({
19182
19282
  module2.exports = {
19183
19283
  name: "@aws-sdk/client-bedrock-runtime",
19184
19284
  description: "AWS SDK for JavaScript Bedrock Runtime Client for Node.js, Browser and React Native",
19185
- version: "3.983.0",
19285
+ version: "3.984.0",
19186
19286
  scripts: {
19187
19287
  build: "concurrently 'yarn:build:types' 'yarn:build:es' && yarn build:cjs",
19188
19288
  "build:cjs": "node ../../scripts/compilation/inline client-bedrock-runtime",
@@ -19204,17 +19304,17 @@ var require_package2 = __commonJS({
19204
19304
  "@aws-crypto/sha256-js": "5.2.0",
19205
19305
  "@aws-sdk/core": "^3.973.6",
19206
19306
  "@aws-sdk/credential-provider-node": "^3.972.5",
19207
- "@aws-sdk/eventstream-handler-node": "^3.972.4",
19307
+ "@aws-sdk/eventstream-handler-node": "^3.972.5",
19208
19308
  "@aws-sdk/middleware-eventstream": "^3.972.3",
19209
19309
  "@aws-sdk/middleware-host-header": "^3.972.3",
19210
19310
  "@aws-sdk/middleware-logger": "^3.972.3",
19211
19311
  "@aws-sdk/middleware-recursion-detection": "^3.972.3",
19212
19312
  "@aws-sdk/middleware-user-agent": "^3.972.6",
19213
- "@aws-sdk/middleware-websocket": "^3.972.4",
19313
+ "@aws-sdk/middleware-websocket": "^3.972.5",
19214
19314
  "@aws-sdk/region-config-resolver": "^3.972.3",
19215
- "@aws-sdk/token-providers": "3.983.0",
19315
+ "@aws-sdk/token-providers": "3.984.0",
19216
19316
  "@aws-sdk/types": "^3.973.1",
19217
- "@aws-sdk/util-endpoints": "3.983.0",
19317
+ "@aws-sdk/util-endpoints": "3.984.0",
19218
19318
  "@aws-sdk/util-user-agent-browser": "^3.972.3",
19219
19319
  "@aws-sdk/util-user-agent-node": "^3.972.4",
19220
19320
  "@smithy/config-resolver": "^4.4.6",
@@ -25526,9 +25626,9 @@ var require_dist_cjs65 = __commonJS({
25526
25626
  var require_dist_cjs66 = __commonJS({
25527
25627
  "node_modules/@aws-sdk/eventstream-handler-node/dist-cjs/index.js"(exports2) {
25528
25628
  "use strict";
25529
- var eventstreamCodec = require_dist_cjs33();
25530
- var stream2 = require("stream");
25531
- var EventSigningStream = class extends stream2.Transform {
25629
+ var eventstreamCodec = require_dist_cjs34();
25630
+ var node_stream = require("node:stream");
25631
+ var EventSigningTransformStream = class extends node_stream.Transform {
25532
25632
  priorSignature;
25533
25633
  messageSigner;
25534
25634
  eventStreamCodec;
@@ -25594,16 +25694,16 @@ var require_dist_cjs66 = __commonJS({
25594
25694
  async handle(next, args, context = {}) {
25595
25695
  const request = args.request;
25596
25696
  const { body: payload2, query: query2 } = request;
25597
- if (!(payload2 instanceof stream2.Readable)) {
25697
+ if (!(payload2 instanceof node_stream.Readable)) {
25598
25698
  throw new Error("Eventstream payload must be a Readable stream.");
25599
25699
  }
25600
25700
  const payloadStream = payload2;
25601
- request.body = new stream2.PassThrough({
25701
+ request.body = new node_stream.PassThrough({
25602
25702
  objectMode: true
25603
25703
  });
25604
25704
  const match2 = request.headers?.authorization?.match(/Signature=([\w]+)$/);
25605
25705
  const priorSignature = match2?.[1] ?? query2?.["X-Amz-Signature"] ?? "";
25606
- const signingStream = new EventSigningStream({
25706
+ const signingStream = new EventSigningTransformStream({
25607
25707
  priorSignature,
25608
25708
  eventStreamCodec: this.eventStreamCodec,
25609
25709
  messageSigner: await this.messageSigner(),
@@ -25612,7 +25712,7 @@ var require_dist_cjs66 = __commonJS({
25612
25712
  let resolvePipeline;
25613
25713
  const pipelineError = new Promise((resolve7, reject2) => {
25614
25714
  resolvePipeline = () => resolve7(void 0);
25615
- stream2.pipeline(payloadStream, signingStream, request.body, (err) => {
25715
+ node_stream.pipeline(payloadStream, signingStream, request.body, (err) => {
25616
25716
  if (err) {
25617
25717
  reject2(new Error(`Pipeline error in @aws-sdk/eventstream-handler-node: ${err.message}`, { cause: err }));
25618
25718
  }
@@ -25717,7 +25817,7 @@ var init_package2 = __esm({
25717
25817
  "node_modules/@aws-sdk/token-providers/node_modules/@aws-sdk/nested-clients/package.json"() {
25718
25818
  package_default2 = {
25719
25819
  name: "@aws-sdk/nested-clients",
25720
- version: "3.983.0",
25820
+ version: "3.984.0",
25721
25821
  description: "Nested clients for AWS SDK packages.",
25722
25822
  main: "./dist-cjs/index.js",
25723
25823
  module: "./dist-es/index.js",
@@ -25753,7 +25853,7 @@ var init_package2 = __esm({
25753
25853
  "@aws-sdk/middleware-user-agent": "^3.972.6",
25754
25854
  "@aws-sdk/region-config-resolver": "^3.972.3",
25755
25855
  "@aws-sdk/types": "^3.973.1",
25756
- "@aws-sdk/util-endpoints": "3.983.0",
25856
+ "@aws-sdk/util-endpoints": "3.984.0",
25757
25857
  "@aws-sdk/util-user-agent-browser": "^3.972.3",
25758
25858
  "@aws-sdk/util-user-agent-node": "^3.972.4",
25759
25859
  "@smithy/config-resolver": "^4.4.6",
@@ -37304,21 +37404,24 @@ var init_zod = __esm({
37304
37404
  // src/tools/edit.js
37305
37405
  function isPathAllowed(filePath, allowedFolders) {
37306
37406
  if (!allowedFolders || allowedFolders.length === 0) {
37307
- const resolvedPath3 = (0, import_path5.resolve)(filePath);
37308
- const cwd = (0, import_path5.resolve)(process.cwd());
37407
+ const resolvedPath3 = safeRealpath(filePath);
37408
+ const cwd = safeRealpath(process.cwd());
37309
37409
  return resolvedPath3 === cwd || resolvedPath3.startsWith(cwd + import_path5.sep);
37310
37410
  }
37311
- const resolvedPath2 = (0, import_path5.resolve)(filePath);
37411
+ const resolvedPath2 = safeRealpath(filePath);
37312
37412
  return allowedFolders.some((folder) => {
37313
- const allowedPath = (0, import_path5.resolve)(folder);
37413
+ const allowedPath = safeRealpath(folder);
37314
37414
  return resolvedPath2 === allowedPath || resolvedPath2.startsWith(allowedPath + import_path5.sep);
37315
37415
  });
37316
37416
  }
37317
37417
  function parseFileToolOptions(options = {}) {
37418
+ const allowedFolders = options.allowedFolders || [];
37318
37419
  return {
37319
37420
  debug: options.debug || false,
37320
- allowedFolders: options.allowedFolders || [],
37321
- cwd: options.cwd
37421
+ allowedFolders,
37422
+ cwd: options.cwd,
37423
+ // Consistent fallback chain: workspaceRoot > cwd > allowedFolders[0] > process.cwd()
37424
+ workspaceRoot: options.workspaceRoot || options.cwd || allowedFolders.length > 0 && allowedFolders[0] || process.cwd()
37322
37425
  };
37323
37426
  }
37324
37427
  var import_ai, import_fs4, import_path5, import_fs5, editTool, createTool, editSchema, createSchema, editDescription, createDescription, editToolDefinition, createToolDefinition;
@@ -37329,8 +37432,9 @@ var init_edit = __esm({
37329
37432
  import_fs4 = require("fs");
37330
37433
  import_path5 = require("path");
37331
37434
  import_fs5 = require("fs");
37435
+ init_path_validation();
37332
37436
  editTool = (options = {}) => {
37333
- const { debug, allowedFolders, cwd } = parseFileToolOptions(options);
37437
+ const { debug, allowedFolders, cwd, workspaceRoot } = parseFileToolOptions(options);
37334
37438
  return (0, import_ai.tool)({
37335
37439
  name: "edit",
37336
37440
  description: `Edit files using exact string replacement (Claude Code style).
@@ -37386,7 +37490,8 @@ Important:
37386
37490
  console.error(`[Edit] Attempting to edit file: ${resolvedPath2}`);
37387
37491
  }
37388
37492
  if (!isPathAllowed(resolvedPath2, allowedFolders)) {
37389
- return `Error editing file: Permission denied - ${file_path} is outside allowed directories`;
37493
+ const relativePath = toRelativePath(resolvedPath2, workspaceRoot);
37494
+ return `Error editing file: Permission denied - ${relativePath} is outside allowed directories`;
37390
37495
  }
37391
37496
  if (!(0, import_fs5.existsSync)(resolvedPath2)) {
37392
37497
  return `Error editing file: File not found - ${file_path}`;
@@ -37422,7 +37527,7 @@ Important:
37422
37527
  });
37423
37528
  };
37424
37529
  createTool = (options = {}) => {
37425
- const { debug, allowedFolders, cwd } = parseFileToolOptions(options);
37530
+ const { debug, allowedFolders, cwd, workspaceRoot } = parseFileToolOptions(options);
37426
37531
  return (0, import_ai.tool)({
37427
37532
  name: "create",
37428
37533
  description: `Create new files with specified content.
@@ -37470,7 +37575,8 @@ Important:
37470
37575
  console.error(`[Create] Attempting to create file: ${resolvedPath2}`);
37471
37576
  }
37472
37577
  if (!isPathAllowed(resolvedPath2, allowedFolders)) {
37473
- return `Error creating file: Permission denied - ${file_path} is outside allowed directories`;
37578
+ const relativePath = toRelativePath(resolvedPath2, workspaceRoot);
37579
+ return `Error creating file: Permission denied - ${relativePath} is outside allowed directories`;
37474
37580
  }
37475
37581
  if ((0, import_fs5.existsSync)(resolvedPath2) && !overwrite) {
37476
37582
  return `Error creating file: File already exists - ${file_path}. Use overwrite: true to replace it.`;
@@ -43309,7 +43415,7 @@ var init_esm3 = __esm({
43309
43415
  });
43310
43416
 
43311
43417
  // node_modules/path-scurry/dist/esm/index.js
43312
- var import_node_path, import_node_url, import_fs6, actualFS, import_promises, realpathSync, defaultFS, fsFromOption, uncDriveRegexp, uncToDrive, eitherSep, UNKNOWN, IFIFO, IFCHR, IFDIR, IFBLK, IFREG, IFLNK, IFSOCK, IFMT, IFMT_UNKNOWN, READDIR_CALLED, LSTAT_CALLED, ENOTDIR, ENOENT, ENOREADLINK, ENOREALPATH, ENOCHILD, TYPEMASK, entToType, normalizeCache, normalize, normalizeNocaseCache, normalizeNocase, ResolveCache, ChildrenCache, setAsCwd, PathBase, PathWin32, PathPosix, PathScurryBase, PathScurryWin32, PathScurryPosix, PathScurryDarwin, Path, PathScurry;
43418
+ var import_node_path, import_node_url, import_fs6, actualFS, import_promises, realpathSync2, defaultFS, fsFromOption, uncDriveRegexp, uncToDrive, eitherSep, UNKNOWN, IFIFO, IFCHR, IFDIR, IFBLK, IFREG, IFLNK, IFSOCK, IFMT, IFMT_UNKNOWN, READDIR_CALLED, LSTAT_CALLED, ENOTDIR, ENOENT, ENOREADLINK, ENOREALPATH, ENOCHILD, TYPEMASK, entToType, normalizeCache, normalize, normalizeNocaseCache, normalizeNocase, ResolveCache, ChildrenCache, setAsCwd, PathBase, PathWin32, PathPosix, PathScurryBase, PathScurryWin32, PathScurryPosix, PathScurryDarwin, Path, PathScurry;
43313
43419
  var init_esm4 = __esm({
43314
43420
  "node_modules/path-scurry/dist/esm/index.js"() {
43315
43421
  init_esm2();
@@ -43319,13 +43425,13 @@ var init_esm4 = __esm({
43319
43425
  actualFS = __toESM(require("node:fs"), 1);
43320
43426
  import_promises = require("node:fs/promises");
43321
43427
  init_esm3();
43322
- realpathSync = import_fs6.realpathSync.native;
43428
+ realpathSync2 = import_fs6.realpathSync.native;
43323
43429
  defaultFS = {
43324
43430
  lstatSync: import_fs6.lstatSync,
43325
43431
  readdir: import_fs6.readdir,
43326
43432
  readdirSync: import_fs6.readdirSync,
43327
43433
  readlinkSync: import_fs6.readlinkSync,
43328
- realpathSync,
43434
+ realpathSync: realpathSync2,
43329
43435
  promises: {
43330
43436
  lstat: import_promises.lstat,
43331
43437
  readdir: import_promises.readdir,
@@ -95059,7 +95165,7 @@ __export(enhanced_claude_code_exports, {
95059
95165
  createEnhancedClaudeCLIEngine: () => createEnhancedClaudeCLIEngine
95060
95166
  });
95061
95167
  async function createEnhancedClaudeCLIEngine(options = {}) {
95062
- const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools } = options;
95168
+ const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools, timeout = 12e4 } = options;
95063
95169
  const session = new Session(
95064
95170
  sessionId || (0, import_crypto6.randomBytes)(8).toString("hex"),
95065
95171
  debug
@@ -95158,6 +95264,30 @@ ${opts.schema}`;
95158
95264
  stdio: ["ignore", "pipe", "pipe"]
95159
95265
  // Ignore stdin since echo handles it
95160
95266
  });
95267
+ let killed = false;
95268
+ let timeoutHandle;
95269
+ let sigkillHandle;
95270
+ if (timeout > 0) {
95271
+ timeoutHandle = setTimeout(() => {
95272
+ if (!killed) {
95273
+ killed = true;
95274
+ processEnded = true;
95275
+ proc2.kill("SIGTERM");
95276
+ if (debug) {
95277
+ console.log(`[DEBUG] Process timed out after ${timeout}ms, sending SIGTERM`);
95278
+ }
95279
+ sigkillHandle = setTimeout(() => {
95280
+ if (proc2.exitCode === null) {
95281
+ proc2.kill("SIGKILL");
95282
+ if (debug) {
95283
+ console.log("[DEBUG] Process did not exit, sending SIGKILL");
95284
+ }
95285
+ }
95286
+ }, 5e3);
95287
+ emitter.emit("error", new Error(`Claude CLI process timed out after ${timeout}ms`));
95288
+ }
95289
+ }, timeout);
95290
+ }
95161
95291
  proc2.stdout.on("data", (data2) => {
95162
95292
  buffer += data2.toString();
95163
95293
  processJsonBuffer(buffer, emitter, session, debug, toolCollector);
@@ -95174,10 +95304,20 @@ ${opts.schema}`;
95174
95304
  }
95175
95305
  });
95176
95306
  proc2.on("close", (code) => {
95307
+ if (timeoutHandle) {
95308
+ clearTimeout(timeoutHandle);
95309
+ }
95310
+ if (sigkillHandle) {
95311
+ clearTimeout(sigkillHandle);
95312
+ }
95177
95313
  processEnded = true;
95178
95314
  if (code !== 0 && debug) {
95179
95315
  console.log(`[DEBUG] Process exited with code ${code}`);
95180
95316
  }
95317
+ if (killed) {
95318
+ emitter.emit("end");
95319
+ return;
95320
+ }
95181
95321
  if (buffer.trim()) {
95182
95322
  processJsonBuffer(buffer, emitter, session, debug, toolCollector);
95183
95323
  }
@@ -95193,6 +95333,13 @@ ${opts.schema}`;
95193
95333
  emitter.emit("end");
95194
95334
  });
95195
95335
  proc2.on("error", (error2) => {
95336
+ if (timeoutHandle) {
95337
+ clearTimeout(timeoutHandle);
95338
+ }
95339
+ if (sigkillHandle) {
95340
+ clearTimeout(sigkillHandle);
95341
+ }
95342
+ processEnded = true;
95196
95343
  emitter.emit("error", error2);
95197
95344
  });
95198
95345
  const messageQueue = [];
@@ -95238,7 +95385,22 @@ ${opts.schema}`;
95238
95385
  \u{1F527} Using ${msg.name}: ${JSON.stringify(msg.input)}
95239
95386
  `
95240
95387
  };
95241
- const result = await executeProbleTool(agent, msg.name, msg.input);
95388
+ const toolTimeout = 3e4;
95389
+ let toolTimeoutId;
95390
+ const timeoutPromise = new Promise((_, reject2) => {
95391
+ toolTimeoutId = setTimeout(() => reject2(new Error(`Tool ${msg.name} timed out after ${toolTimeout}ms`)), toolTimeout);
95392
+ });
95393
+ let result;
95394
+ try {
95395
+ result = await Promise.race([
95396
+ executeProbleTool(agent, msg.name, msg.input),
95397
+ timeoutPromise
95398
+ ]);
95399
+ } catch (error2) {
95400
+ result = `Tool error: ${error2.message}`;
95401
+ } finally {
95402
+ clearTimeout(toolTimeoutId);
95403
+ }
95242
95404
  yield { type: "text", content: `${result}
95243
95405
  ` };
95244
95406
  } else if (msg.type === "toolBatch") {
@@ -95814,6 +95976,9 @@ var init_enhanced_vercel = __esm({
95814
95976
  // src/agent/ProbeAgent.js
95815
95977
  var ProbeAgent_exports = {};
95816
95978
  __export(ProbeAgent_exports, {
95979
+ ENGINE_ACTIVITY_TIMEOUT_DEFAULT: () => ENGINE_ACTIVITY_TIMEOUT_DEFAULT,
95980
+ ENGINE_ACTIVITY_TIMEOUT_MAX: () => ENGINE_ACTIVITY_TIMEOUT_MAX,
95981
+ ENGINE_ACTIVITY_TIMEOUT_MIN: () => ENGINE_ACTIVITY_TIMEOUT_MIN,
95817
95982
  ProbeAgent: () => ProbeAgent
95818
95983
  });
95819
95984
  function extractWrappedToolName(wrappedToolError) {
@@ -95837,7 +96002,7 @@ Your content here
95837
96002
 
95838
96003
  Do NOT wrap in other tags like <api_call>, <tool_name>, <function>, etc.`;
95839
96004
  }
95840
- var import_dotenv, import_anthropic2, import_openai2, import_google2, import_ai3, import_crypto8, import_events4, import_fs11, import_promises6, import_path13, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
96005
+ var import_dotenv, import_anthropic2, import_openai2, import_google2, import_ai3, import_crypto8, import_events4, import_fs11, import_promises6, import_path13, ENGINE_ACTIVITY_TIMEOUT_DEFAULT, ENGINE_ACTIVITY_TIMEOUT_MIN, ENGINE_ACTIVITY_TIMEOUT_MAX, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
95841
96006
  var init_ProbeAgent = __esm({
95842
96007
  "src/agent/ProbeAgent.js"() {
95843
96008
  "use strict";
@@ -95872,10 +96037,14 @@ var init_ProbeAgent = __esm({
95872
96037
  init_FallbackManager();
95873
96038
  init_contextCompactor();
95874
96039
  init_error_types();
96040
+ init_path_validation();
95875
96041
  init_outputTruncator();
95876
96042
  init_delegate();
95877
96043
  init_tasks();
95878
96044
  import_dotenv.default.config();
96045
+ ENGINE_ACTIVITY_TIMEOUT_DEFAULT = 18e4;
96046
+ ENGINE_ACTIVITY_TIMEOUT_MIN = 5e3;
96047
+ ENGINE_ACTIVITY_TIMEOUT_MAX = 6e5;
95879
96048
  MAX_TOOL_ITERATIONS = (() => {
95880
96049
  const val = parseInt(process.env.MAX_TOOL_ITERATIONS || "30", 10);
95881
96050
  if (isNaN(val) || val < 1 || val > 200) {
@@ -95934,6 +96103,8 @@ var init_ProbeAgent = __esm({
95934
96103
  * @param {number} [options.fallback.maxTotalAttempts=10] - Maximum total attempts across all providers
95935
96104
  * @param {string} [options.completionPrompt] - Custom prompt to run after attempt_completion for validation/review (runs before mermaid/JSON validation)
95936
96105
  * @param {number} [options.maxOutputTokens] - Maximum tokens for tool output before truncation (default: 20000, can also be set via PROBE_MAX_OUTPUT_TOKENS env var)
96106
+ * @param {number} [options.requestTimeout] - Timeout in ms for AI requests (default: 120000 or REQUEST_TIMEOUT env var). Used to abort hung requests.
96107
+ * @param {number} [options.maxOperationTimeout] - Maximum timeout in ms for the entire operation including all retries and fallbacks (default: 300000 or MAX_OPERATION_TIMEOUT env var). This is the absolute maximum time for streamTextWithRetryAndFallback.
95937
96108
  */
95938
96109
  constructor(options = {}) {
95939
96110
  this.sessionId = options.sessionId || (0, import_crypto8.randomUUID)();
@@ -95989,7 +96160,8 @@ var init_ProbeAgent = __esm({
95989
96160
  } else {
95990
96161
  this.allowedFolders = [process.cwd()];
95991
96162
  }
95992
- this.cwd = options.cwd || null;
96163
+ this.workspaceRoot = getCommonPrefix(this.allowedFolders);
96164
+ this.cwd = options.cwd || this.workspaceRoot;
95993
96165
  this.clientApiProvider = options.provider || null;
95994
96166
  this.clientApiModel = options.model || null;
95995
96167
  this.clientApiKey = null;
@@ -96001,6 +96173,8 @@ var init_ProbeAgent = __esm({
96001
96173
  console.log(`[DEBUG] Maximum tool iterations configured: ${MAX_TOOL_ITERATIONS}`);
96002
96174
  console.log(`[DEBUG] Allow Edit (implement tool): ${this.allowEdit}`);
96003
96175
  console.log(`[DEBUG] Search delegation enabled: ${this.searchDelegate}`);
96176
+ console.log(`[DEBUG] Workspace root: ${this.workspaceRoot}`);
96177
+ console.log(`[DEBUG] Working directory (cwd): ${this.cwd}`);
96004
96178
  }
96005
96179
  this.initializeTools();
96006
96180
  this.history = [];
@@ -96016,6 +96190,32 @@ var init_ProbeAgent = __esm({
96016
96190
  this.enableTasks = !!options.enableTasks;
96017
96191
  this.taskManager = null;
96018
96192
  this.delegationManager = new DelegationManager();
96193
+ this.requestTimeout = options.requestTimeout ?? (() => {
96194
+ if (process.env.REQUEST_TIMEOUT) {
96195
+ const parsed = parseInt(process.env.REQUEST_TIMEOUT, 10);
96196
+ if (isNaN(parsed) || parsed < 1e3 || parsed > 36e5) {
96197
+ return 12e4;
96198
+ }
96199
+ return parsed;
96200
+ }
96201
+ return 12e4;
96202
+ })();
96203
+ if (this.debug) {
96204
+ console.log(`[DEBUG] Request timeout: ${this.requestTimeout}ms`);
96205
+ }
96206
+ this.maxOperationTimeout = options.maxOperationTimeout ?? (() => {
96207
+ if (process.env.MAX_OPERATION_TIMEOUT) {
96208
+ const parsed = parseInt(process.env.MAX_OPERATION_TIMEOUT, 10);
96209
+ if (isNaN(parsed) || parsed < 1e3 || parsed > 72e5) {
96210
+ return 3e5;
96211
+ }
96212
+ return parsed;
96213
+ }
96214
+ return 3e5;
96215
+ })();
96216
+ if (this.debug) {
96217
+ console.log(`[DEBUG] Max operation timeout: ${this.maxOperationTimeout}ms`);
96218
+ }
96019
96219
  this.retryConfig = options.retry || {};
96020
96220
  this.retryManager = null;
96021
96221
  this.fallbackConfig = options.fallback || null;
@@ -96348,8 +96548,9 @@ var init_ProbeAgent = __esm({
96348
96548
  const configOptions = {
96349
96549
  sessionId: this.sessionId,
96350
96550
  debug: this.debug,
96351
- // Use explicit cwd if set, otherwise fall back to first allowed folder
96352
- cwd: this.cwd || (this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd()),
96551
+ // Use cwd (which defaults to workspaceRoot in constructor)
96552
+ cwd: this.cwd,
96553
+ workspaceRoot: this.workspaceRoot,
96353
96554
  allowedFolders: this.allowedFolders,
96354
96555
  outline: this.outline,
96355
96556
  searchDelegate: this.searchDelegate,
@@ -96634,88 +96835,98 @@ var init_ProbeAgent = __esm({
96634
96835
  }
96635
96836
  }
96636
96837
  /**
96637
- * Execute streamText with retry and fallback support
96638
- * @param {Object} options - streamText options
96639
- * @returns {Promise<Object>} - streamText result
96838
+ * Create a streamText-compatible result from an engine stream with timeout handling
96839
+ * @param {AsyncGenerator} engineStream - The engine's query result
96840
+ * @param {AbortSignal} abortSignal - Signal for aborting the operation
96841
+ * @param {number} requestTimeout - Per-request timeout in ms
96842
+ * @param {Object} timeoutState - Object with timeoutId property (mutable for cleanup)
96843
+ * @returns {Object} - streamText-compatible result with textStream
96640
96844
  * @private
96641
96845
  */
96642
- async streamTextWithRetryAndFallback(options) {
96643
- if (this.clientApiProvider === "claude-code" || process.env.USE_CLAUDE_CODE === "true") {
96846
+ _createEngineTextStreamResult(engineStream, abortSignal, requestTimeout, timeoutState) {
96847
+ const activityTimeout = (() => {
96848
+ const parsed = parseInt(process.env.ENGINE_ACTIVITY_TIMEOUT, 10);
96849
+ return isNaN(parsed) || parsed < ENGINE_ACTIVITY_TIMEOUT_MIN || parsed > ENGINE_ACTIVITY_TIMEOUT_MAX ? ENGINE_ACTIVITY_TIMEOUT_DEFAULT : parsed;
96850
+ })();
96851
+ const startTime = Date.now();
96852
+ async function* createTextStream() {
96853
+ let lastActivity = Date.now();
96644
96854
  try {
96645
- const engine = await this.getEngine();
96646
- if (engine && engine.query) {
96647
- const userMessages = options.messages.filter(
96648
- (m5) => m5.role === "user" && !m5.content.includes("WARNING: You have reached the maximum tool iterations limit")
96649
- );
96650
- const lastUserMessage = userMessages[userMessages.length - 1];
96651
- const prompt = lastUserMessage ? lastUserMessage.content : "";
96652
- const engineOptions = {
96653
- maxTokens: options.maxTokens,
96654
- temperature: options.temperature,
96655
- messages: options.messages,
96656
- systemPrompt: options.messages.find((m5) => m5.role === "system")?.content
96657
- };
96658
- const engineStream = engine.query(prompt, engineOptions);
96659
- async function* createTextStream() {
96660
- for await (const message of engineStream) {
96661
- if (message.type === "text" && message.content) {
96662
- yield message.content;
96663
- } else if (typeof message === "string") {
96664
- yield message;
96665
- }
96666
- }
96855
+ for await (const message of engineStream) {
96856
+ if (abortSignal.aborted) {
96857
+ const abortError = new Error("Operation aborted");
96858
+ abortError.name = "AbortError";
96859
+ throw abortError;
96667
96860
  }
96668
- return {
96669
- textStream: createTextStream(),
96670
- usage: Promise.resolve({})
96671
- // Engine should handle its own usage tracking
96672
- // Add other streamText-compatible properties as needed
96673
- };
96674
- }
96675
- } catch (error2) {
96676
- if (this.debug) {
96677
- console.log(`[DEBUG] Failed to use Claude Code engine, falling back to Vercel:`, error2.message);
96678
- }
96679
- }
96680
- }
96681
- if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
96682
- try {
96683
- const engine = await this.getEngine();
96684
- if (engine && engine.query) {
96685
- const userMessages = options.messages.filter(
96686
- (m5) => m5.role === "user" && !m5.content.includes("WARNING: You have reached the maximum tool iterations limit")
96687
- );
96688
- const lastUserMessage = userMessages[userMessages.length - 1];
96689
- const prompt = lastUserMessage ? lastUserMessage.content : "";
96690
- const engineOptions = {
96691
- maxTokens: options.maxTokens,
96692
- temperature: options.temperature,
96693
- messages: options.messages,
96694
- systemPrompt: options.messages.find((m5) => m5.role === "system")?.content
96695
- };
96696
- const engineStream = engine.query(prompt, engineOptions);
96697
- async function* createTextStream() {
96698
- for await (const message of engineStream) {
96699
- if (message.type === "text" && message.content) {
96700
- yield message.content;
96701
- } else if (typeof message === "string") {
96702
- yield message;
96703
- }
96704
- }
96861
+ const now = Date.now();
96862
+ if (now - lastActivity > activityTimeout) {
96863
+ throw new Error(`Engine stream timeout - no activity for ${activityTimeout}ms`);
96864
+ }
96865
+ if (requestTimeout > 0 && now - startTime > requestTimeout) {
96866
+ throw new Error(`Engine stream timeout - request exceeded ${requestTimeout}ms`);
96867
+ }
96868
+ lastActivity = now;
96869
+ if (message.type === "text" && message.content) {
96870
+ yield message.content;
96871
+ } else if (typeof message === "string") {
96872
+ yield message;
96705
96873
  }
96706
- return {
96707
- textStream: createTextStream(),
96708
- usage: Promise.resolve({})
96709
- // Engine should handle its own usage tracking
96710
- // Add other streamText-compatible properties as needed
96711
- };
96712
96874
  }
96713
- } catch (error2) {
96714
- if (this.debug) {
96715
- console.log(`[DEBUG] Failed to use Codex engine, falling back to Vercel:`, error2.message);
96875
+ } finally {
96876
+ if (timeoutState.timeoutId) {
96877
+ clearTimeout(timeoutState.timeoutId);
96878
+ timeoutState.timeoutId = null;
96716
96879
  }
96717
96880
  }
96718
96881
  }
96882
+ return {
96883
+ textStream: createTextStream(),
96884
+ usage: Promise.resolve({})
96885
+ // Engine should handle its own usage tracking
96886
+ // Add other streamText-compatible properties as needed
96887
+ };
96888
+ }
96889
+ /**
96890
+ * Try to use an engine (claude-code or codex) for streaming
96891
+ * @param {Object} options - streamText options
96892
+ * @param {AbortController} controller - Abort controller for the operation
96893
+ * @param {Object} timeoutState - Mutable timeout state for cleanup
96894
+ * @returns {Promise<Object|null>} - Stream result or null if engine unavailable
96895
+ * @private
96896
+ */
96897
+ async _tryEngineStreamPath(options, controller, timeoutState) {
96898
+ const engine = await this.getEngine();
96899
+ if (!engine || !engine.query) {
96900
+ return null;
96901
+ }
96902
+ const userMessages = options.messages.filter(
96903
+ (m5) => m5.role === "user" && !m5.content.includes("WARNING: You have reached the maximum tool iterations limit")
96904
+ );
96905
+ const lastUserMessage = userMessages[userMessages.length - 1];
96906
+ const prompt = lastUserMessage ? lastUserMessage.content : "";
96907
+ const engineOptions = {
96908
+ maxTokens: options.maxTokens,
96909
+ temperature: options.temperature,
96910
+ messages: options.messages,
96911
+ systemPrompt: options.messages.find((m5) => m5.role === "system")?.content,
96912
+ abortSignal: controller.signal
96913
+ };
96914
+ const engineStream = engine.query(prompt, engineOptions);
96915
+ return this._createEngineTextStreamResult(
96916
+ engineStream,
96917
+ controller.signal,
96918
+ this.requestTimeout,
96919
+ timeoutState
96920
+ );
96921
+ }
96922
+ /**
96923
+ * Execute streamText with Vercel AI SDK using retry/fallback logic
96924
+ * @param {Object} options - streamText options
96925
+ * @param {AbortController} controller - Abort controller for the operation
96926
+ * @returns {Promise<Object>} - Stream result
96927
+ * @private
96928
+ */
96929
+ async _executeWithVercelProvider(options, controller) {
96719
96930
  if (!this.retryManager) {
96720
96931
  this.retryManager = new RetryManager({
96721
96932
  maxRetries: this.retryConfig.maxRetries ?? 3,
@@ -96728,10 +96939,11 @@ var init_ProbeAgent = __esm({
96728
96939
  }
96729
96940
  if (!this.fallbackManager) {
96730
96941
  return await this.retryManager.executeWithRetry(
96731
- () => (0, import_ai3.streamText)(options),
96942
+ () => (0, import_ai3.streamText)({ ...options, abortSignal: controller.signal }),
96732
96943
  {
96733
96944
  provider: this.apiType,
96734
- model: this.model
96945
+ model: this.model,
96946
+ signal: controller.signal
96735
96947
  }
96736
96948
  );
96737
96949
  }
@@ -96739,7 +96951,8 @@ var init_ProbeAgent = __esm({
96739
96951
  async (provider, model, config) => {
96740
96952
  const fallbackOptions = {
96741
96953
  ...options,
96742
- model: provider(model)
96954
+ model: provider(model),
96955
+ abortSignal: controller.signal
96743
96956
  };
96744
96957
  const providerRetryManager = new RetryManager({
96745
96958
  maxRetries: config.maxRetries ?? this.retryConfig.maxRetries ?? 3,
@@ -96753,12 +96966,54 @@ var init_ProbeAgent = __esm({
96753
96966
  () => (0, import_ai3.streamText)(fallbackOptions),
96754
96967
  {
96755
96968
  provider: config.provider,
96756
- model
96969
+ model,
96970
+ signal: controller.signal
96757
96971
  }
96758
96972
  );
96759
96973
  }
96760
96974
  );
96761
96975
  }
96976
+ /**
96977
+ * Execute streamText with retry and fallback support
96978
+ * @param {Object} options - streamText options
96979
+ * @returns {Promise<Object>} - streamText result
96980
+ * @private
96981
+ */
96982
+ async streamTextWithRetryAndFallback(options) {
96983
+ const controller = new AbortController();
96984
+ const timeoutState = { timeoutId: null };
96985
+ if (this.maxOperationTimeout && this.maxOperationTimeout > 0) {
96986
+ timeoutState.timeoutId = setTimeout(() => {
96987
+ controller.abort();
96988
+ if (this.debug) {
96989
+ console.log(`[DEBUG] Operation timed out after ${this.maxOperationTimeout}ms (max operation timeout)`);
96990
+ }
96991
+ }, this.maxOperationTimeout);
96992
+ }
96993
+ try {
96994
+ const useClaudeCode = this.clientApiProvider === "claude-code" || process.env.USE_CLAUDE_CODE === "true";
96995
+ const useCodex = this.clientApiProvider === "codex" || process.env.USE_CODEX === "true";
96996
+ if (useClaudeCode || useCodex) {
96997
+ try {
96998
+ const result = await this._tryEngineStreamPath(options, controller, timeoutState);
96999
+ if (result) {
97000
+ return result;
97001
+ }
97002
+ } catch (error2) {
97003
+ if (this.debug) {
97004
+ const engineType = useClaudeCode ? "Claude Code" : "Codex";
97005
+ console.log(`[DEBUG] Failed to use ${engineType} engine, falling back to Vercel:`, error2.message);
97006
+ }
97007
+ }
97008
+ }
97009
+ return await this._executeWithVercelProvider(options, controller);
97010
+ } finally {
97011
+ if (timeoutState.timeoutId) {
97012
+ clearTimeout(timeoutState.timeoutId);
97013
+ timeoutState.timeoutId = null;
97014
+ }
97015
+ }
97016
+ }
96762
97017
  /**
96763
97018
  * Initialize Anthropic model
96764
97019
  */
@@ -97036,16 +97291,16 @@ var init_ProbeAgent = __esm({
97036
97291
  let absolutePath;
97037
97292
  let isPathAllowed2 = false;
97038
97293
  if ((0, import_path13.isAbsolute)(imagePath)) {
97039
- absolutePath = (0, import_path13.normalize)((0, import_path13.resolve)(imagePath));
97294
+ absolutePath = safeRealpath((0, import_path13.resolve)(imagePath));
97040
97295
  isPathAllowed2 = allowedDirs.some((dir) => {
97041
- const normalizedDir = (0, import_path13.normalize)((0, import_path13.resolve)(dir));
97042
- return absolutePath === normalizedDir || absolutePath.startsWith(normalizedDir + import_path13.sep);
97296
+ const resolvedDir = safeRealpath(dir);
97297
+ return absolutePath === resolvedDir || absolutePath.startsWith(resolvedDir + import_path13.sep);
97043
97298
  });
97044
97299
  } else {
97045
97300
  for (const dir of allowedDirs) {
97046
- const normalizedDir = (0, import_path13.normalize)((0, import_path13.resolve)(dir));
97047
- const resolvedPath2 = (0, import_path13.normalize)((0, import_path13.resolve)(dir, imagePath));
97048
- if (resolvedPath2 === normalizedDir || resolvedPath2.startsWith(normalizedDir + import_path13.sep)) {
97301
+ const resolvedDir = safeRealpath(dir);
97302
+ const resolvedPath2 = safeRealpath((0, import_path13.resolve)(dir, imagePath));
97303
+ if (resolvedPath2 === resolvedDir || resolvedPath2.startsWith(resolvedDir + import_path13.sep)) {
97049
97304
  absolutePath = resolvedPath2;
97050
97305
  isPathAllowed2 = true;
97051
97306
  break;
@@ -97228,7 +97483,7 @@ var init_ProbeAgent = __esm({
97228
97483
  if (this._architectureContextLoaded) {
97229
97484
  return this.architectureContext;
97230
97485
  }
97231
- const rootDirectory = this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd();
97486
+ const rootDirectory = this.workspaceRoot || (this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd());
97232
97487
  const configuredName = typeof this.architectureFileName === "string" ? this.architectureFileName.trim() : "";
97233
97488
  const hasConfiguredName = !!configuredName;
97234
97489
  let guidanceCandidates = [];
@@ -97365,6 +97620,9 @@ ${this.architectureContext.content}
97365
97620
  `;
97366
97621
  }
97367
97622
  _getSkillsRepoRoot() {
97623
+ if (this.workspaceRoot) {
97624
+ return (0, import_path13.resolve)(this.workspaceRoot);
97625
+ }
97368
97626
  if (this.allowedFolders && this.allowedFolders.length > 0) {
97369
97627
  return (0, import_path13.resolve)(this.allowedFolders[0]);
97370
97628
  }
@@ -97432,7 +97690,7 @@ Workspace: ${this.allowedFolders.join(", ")}`;
97432
97690
 
97433
97691
  # Repository Structure
97434
97692
  `;
97435
- systemPrompt += `You are working with a repository located at: ${this.allowedFolders[0]}
97693
+ systemPrompt += `You are working with a repository located at: ${this.workspaceRoot}
97436
97694
 
97437
97695
  `;
97438
97696
  systemPrompt += `Here's an overview of the repository structure (showing up to 100 most relevant files):
@@ -97485,7 +97743,7 @@ Workspace: ${this.allowedFolders.join(", ")}`;
97485
97743
 
97486
97744
  # Repository Structure
97487
97745
  `;
97488
- systemPrompt += `You are working with a repository located at: ${this.allowedFolders[0]}
97746
+ systemPrompt += `You are working with a repository located at: ${this.workspaceRoot}
97489
97747
 
97490
97748
  `;
97491
97749
  systemPrompt += `Here's an overview of the repository structure (showing up to 100 most relevant files):
@@ -97784,21 +98042,34 @@ For MCP tools, use JSON format within the params tag, e.g.:
97784
98042
  `;
97785
98043
  }
97786
98044
  }
97787
- const searchDirectory = this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd();
98045
+ const searchDirectory = this.workspaceRoot;
97788
98046
  if (this.debug) {
97789
- console.log(`[DEBUG] Generating file list for base directory: ${searchDirectory}...`);
98047
+ console.log(`[DEBUG] Generating file list for workspace root: ${searchDirectory}...`);
98048
+ }
98049
+ const relativeWorkspaces = this.allowedFolders.map((f5) => {
98050
+ const rel = toRelativePath(f5, this.workspaceRoot);
98051
+ if (rel && rel !== "." && !rel.startsWith(".") && !rel.startsWith("/")) {
98052
+ return "./" + rel;
98053
+ }
98054
+ return rel;
98055
+ }).filter((f5) => f5 && f5 !== ".");
98056
+ let workspaceDesc;
98057
+ if (relativeWorkspaces.length === 0) {
98058
+ workspaceDesc = ". (current directory)";
98059
+ } else {
98060
+ workspaceDesc = relativeWorkspaces.join(", ");
97790
98061
  }
97791
98062
  try {
97792
98063
  const files = await listFilesByLevel({
97793
98064
  directory: searchDirectory,
97794
98065
  maxFiles: 100,
97795
98066
  respectGitignore: !process.env.PROBE_NO_GITIGNORE || process.env.PROBE_NO_GITIGNORE === "",
97796
- cwd: process.cwd()
98067
+ cwd: this.workspaceRoot
97797
98068
  });
97798
98069
  systemMessage += `
97799
98070
  # Repository Structure
97800
98071
 
97801
- You are working with a repository located at: ${searchDirectory}
98072
+ You are working with a workspace. Available paths: ${workspaceDesc}
97802
98073
 
97803
98074
  Here's an overview of the repository structure (showing up to 100 most relevant files):
97804
98075
 
@@ -97814,15 +98085,22 @@ ${files}
97814
98085
  systemMessage += `
97815
98086
  # Repository Structure
97816
98087
 
97817
- You are working with a repository located at: ${searchDirectory}
98088
+ You are working with a workspace. Available paths: ${workspaceDesc}
97818
98089
 
97819
98090
  `;
97820
98091
  }
97821
98092
  await this.loadArchitectureContext();
97822
98093
  systemMessage += this.getArchitectureSection();
97823
98094
  if (this.allowedFolders.length > 0) {
98095
+ const relativeAllowed = this.allowedFolders.map((f5) => {
98096
+ const rel = toRelativePath(f5, this.workspaceRoot);
98097
+ if (rel && rel !== "." && !rel.startsWith(".") && !rel.startsWith("/")) {
98098
+ return "./" + rel;
98099
+ }
98100
+ return rel;
98101
+ });
97824
98102
  systemMessage += `
97825
- **Important**: For security reasons, you can only search within these allowed folders: ${this.allowedFolders.join(", ")}
98103
+ **Important**: For security reasons, you can only access these paths: ${relativeAllowed.join(", ")}
97826
98104
 
97827
98105
  `;
97828
98106
  }
@@ -98336,6 +98614,7 @@ You are working with a repository located at: ${searchDirectory}
98336
98614
  console.error(`[DEBUG] ========================================
98337
98615
  `);
98338
98616
  }
98617
+ currentMessages.push({ role: "assistant", content: assistantResponseContent });
98339
98618
  currentMessages.push({ role: "user", content: `<tool_result>
98340
98619
  ${toolResultContent}
98341
98620
  </tool_result>` });
@@ -98356,17 +98635,18 @@ ${toolResultContent}
98356
98635
  `);
98357
98636
  }
98358
98637
  const errorXml = formatErrorForAI(error2);
98638
+ currentMessages.push({ role: "assistant", content: assistantResponseContent });
98359
98639
  currentMessages.push({ role: "user", content: `<tool_result>
98360
98640
  ${errorXml}
98361
98641
  </tool_result>` });
98362
98642
  }
98363
98643
  } else if (this.toolImplementations[toolName]) {
98364
98644
  try {
98365
- let resolvedWorkingDirectory = this.cwd || this.allowedFolders && this.allowedFolders[0] || process.cwd();
98645
+ let resolvedWorkingDirectory = this.workspaceRoot || this.cwd || this.allowedFolders && this.allowedFolders[0] || process.cwd();
98366
98646
  if (params.workingDirectory) {
98367
- const requestedDir = (0, import_path13.isAbsolute)(params.workingDirectory) ? (0, import_path13.resolve)(params.workingDirectory) : (0, import_path13.resolve)(resolvedWorkingDirectory, params.workingDirectory);
98647
+ const requestedDir = safeRealpath((0, import_path13.isAbsolute)(params.workingDirectory) ? (0, import_path13.resolve)(params.workingDirectory) : (0, import_path13.resolve)(resolvedWorkingDirectory, params.workingDirectory));
98368
98648
  const isWithinAllowed = !this.allowedFolders || this.allowedFolders.length === 0 || this.allowedFolders.some((folder) => {
98369
- const resolvedFolder = (0, import_path13.resolve)(folder);
98649
+ const resolvedFolder = safeRealpath(folder);
98370
98650
  return requestedDir === resolvedFolder || requestedDir.startsWith(resolvedFolder + import_path13.sep);
98371
98651
  });
98372
98652
  if (isWithinAllowed) {
@@ -98835,7 +99115,7 @@ Convert your previous response content into actual JSON data that follows this s
98835
99115
  }
98836
99116
  const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
98837
99117
  debug: this.debug,
98838
- path: this.allowedFolders[0],
99118
+ path: this.workspaceRoot || this.allowedFolders[0],
98839
99119
  provider: this.clientApiProvider,
98840
99120
  model: this.model,
98841
99121
  tracer: this.tracer
@@ -98908,7 +99188,7 @@ Convert your previous response content into actual JSON data that follows this s
98908
99188
  }
98909
99189
  const { JsonFixingAgent: JsonFixingAgent2 } = await Promise.resolve().then(() => (init_schemaUtils(), schemaUtils_exports));
98910
99190
  const jsonFixer = new JsonFixingAgent2({
98911
- path: this.allowedFolders[0],
99191
+ path: this.workspaceRoot || this.allowedFolders[0],
98912
99192
  provider: this.clientApiProvider,
98913
99193
  model: this.model,
98914
99194
  debug: this.debug,
@@ -98977,7 +99257,7 @@ Convert your previous response content into actual JSON data that follows this s
98977
99257
  }
98978
99258
  const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
98979
99259
  debug: this.debug,
98980
- path: this.allowedFolders[0],
99260
+ path: this.workspaceRoot || this.allowedFolders[0],
98981
99261
  provider: this.clientApiProvider,
98982
99262
  model: this.model,
98983
99263
  tracer: this.tracer
@@ -99109,7 +99389,7 @@ Convert your previous response content into actual JSON data that follows this s
99109
99389
  }
99110
99390
  const finalMermaidValidation = await validateAndFixMermaidResponse(finalResult, {
99111
99391
  debug: this.debug,
99112
- path: this.allowedFolders[0],
99392
+ path: this.workspaceRoot || this.allowedFolders[0],
99113
99393
  provider: this.clientApiProvider,
99114
99394
  model: this.model,
99115
99395
  tracer: this.tracer
@@ -99259,8 +99539,7 @@ Convert your previous response content into actual JSON data that follows this s
99259
99539
  allowEdit: this.allowEdit,
99260
99540
  enableDelegate: this.enableDelegate,
99261
99541
  architectureFileName: this.architectureFileName,
99262
- path: this.allowedFolders[0],
99263
- // Use first allowed folder as primary path
99542
+ // Pass allowedFolders which will recompute workspaceRoot correctly
99264
99543
  allowedFolders: [...this.allowedFolders],
99265
99544
  cwd: this.cwd,
99266
99545
  // Preserve explicit working directory
@@ -100223,6 +100502,7 @@ async function analyzeAll(options) {
100223
100502
  sessionId,
100224
100503
  debug = false,
100225
100504
  cwd,
100505
+ workspaceRoot,
100226
100506
  allowedFolders,
100227
100507
  provider,
100228
100508
  model,
@@ -100235,10 +100515,11 @@ async function analyzeAll(options) {
100235
100515
  if (!question) {
100236
100516
  throw new Error('The "question" parameter is required.');
100237
100517
  }
100518
+ const effectiveWorkspaceRoot = workspaceRoot || cwd || allowedFolders?.[0] || path9;
100238
100519
  const delegateOptions = {
100239
100520
  debug,
100240
100521
  sessionId,
100241
- path: allowedFolders?.[0] || cwd || path9,
100522
+ path: effectiveWorkspaceRoot,
100242
100523
  allowedFolders,
100243
100524
  provider,
100244
100525
  model,
@@ -100700,7 +100981,7 @@ var init_vercel = __esm({
100700
100981
  });
100701
100982
  };
100702
100983
  delegateTool = (options = {}) => {
100703
- const { debug = false, timeout = 300, cwd, allowedFolders, enableBash = false, bashConfig, architectureFileName, enableMcp = false, mcpConfig = null, mcpConfigPath = null, delegationManager = null } = options;
100984
+ const { debug = false, timeout = 300, cwd, allowedFolders, workspaceRoot, enableBash = false, bashConfig, architectureFileName, enableMcp = false, mcpConfig = null, mcpConfigPath = null, delegationManager = null } = options;
100704
100985
  return (0, import_ai4.tool)({
100705
100986
  name: "delegate",
100706
100987
  description: delegateDescription,
@@ -100733,8 +101014,8 @@ var init_vercel = __esm({
100733
101014
  if (searchDelegate !== void 0 && typeof searchDelegate !== "boolean") {
100734
101015
  throw new TypeError("searchDelegate must be a boolean if provided");
100735
101016
  }
100736
- const workspaceRoot = allowedFolders && allowedFolders[0];
100737
- const effectivePath = path9 || workspaceRoot || cwd;
101017
+ const effectiveWorkspaceRoot = workspaceRoot || allowedFolders && allowedFolders[0];
101018
+ const effectivePath = path9 || effectiveWorkspaceRoot || cwd;
100738
101019
  if (debug) {
100739
101020
  console.error(`Executing delegate with task: "${task.substring(0, 100)}${task.length > 100 ? "..." : ""}"`);
100740
101021
  if (parentSessionId) {
@@ -100771,7 +101052,7 @@ var init_vercel = __esm({
100771
101052
  });
100772
101053
  };
100773
101054
  analyzeAllTool = (options = {}) => {
100774
- const { sessionId, debug = false, delegationManager = null } = options;
101055
+ const { sessionId, debug = false, delegationManager = null, workspaceRoot } = options;
100775
101056
  return (0, import_ai4.tool)({
100776
101057
  name: "analyze_all",
100777
101058
  description: analyzeAllDescription,
@@ -100790,12 +101071,14 @@ var init_vercel = __esm({
100790
101071
  console.error(`[analyze_all] Question: ${question}`);
100791
101072
  console.error(`[analyze_all] Path: ${searchPath}`);
100792
101073
  }
101074
+ const effectiveWorkspaceRoot = workspaceRoot || options.cwd || options.allowedFolders && options.allowedFolders[0];
100793
101075
  const result = await analyzeAll({
100794
101076
  question,
100795
101077
  path: searchPath,
100796
101078
  sessionId,
100797
101079
  debug,
100798
101080
  cwd: options.cwd,
101081
+ workspaceRoot: effectiveWorkspaceRoot,
100799
101082
  allowedFolders: options.allowedFolders,
100800
101083
  provider: options.provider,
100801
101084
  model: options.model,
@@ -102272,14 +102555,17 @@ var init_bash = __esm({
102272
102555
  import_path15 = require("path");
102273
102556
  init_bashPermissions();
102274
102557
  init_bashExecutor();
102558
+ init_path_validation();
102275
102559
  bashTool = (options = {}) => {
102276
102560
  const {
102277
102561
  bashConfig = {},
102278
102562
  debug = false,
102279
102563
  cwd,
102280
102564
  allowedFolders = [],
102565
+ workspaceRoot: providedWorkspaceRoot,
102281
102566
  tracer = null
102282
102567
  } = options;
102568
+ const workspaceRoot = providedWorkspaceRoot || cwd || allowedFolders.length > 0 && allowedFolders[0] || process.cwd();
102283
102569
  const permissionChecker = new BashPermissionChecker({
102284
102570
  allow: bashConfig.allow,
102285
102571
  deny: bashConfig.deny,
@@ -102295,6 +102581,9 @@ var init_bash = __esm({
102295
102581
  if (cwd) {
102296
102582
  return cwd;
102297
102583
  }
102584
+ if (workspaceRoot) {
102585
+ return workspaceRoot;
102586
+ }
102298
102587
  if (allowedFolders && allowedFolders.length > 0) {
102299
102588
  return allowedFolders[0];
102300
102589
  }
@@ -102382,13 +102671,15 @@ For code exploration, try these safe alternatives:
102382
102671
  const defaultDir = getDefaultWorkingDirectory();
102383
102672
  const workingDir = workingDirectory ? (0, import_path15.isAbsolute)(workingDirectory) ? (0, import_path15.resolve)(workingDirectory) : (0, import_path15.resolve)(defaultDir, workingDirectory) : defaultDir;
102384
102673
  if (allowedFolders && allowedFolders.length > 0) {
102385
- const resolvedWorkingDir = (0, import_path15.resolve)(workingDir);
102674
+ const resolvedWorkingDir = safeRealpath(workingDir);
102386
102675
  const isAllowed = allowedFolders.some((folder) => {
102387
- const resolvedFolder = (0, import_path15.resolve)(folder);
102676
+ const resolvedFolder = safeRealpath(folder);
102388
102677
  return resolvedWorkingDir === resolvedFolder || resolvedWorkingDir.startsWith(resolvedFolder + import_path15.sep);
102389
102678
  });
102390
102679
  if (!isAllowed) {
102391
- return `Error: Working directory "${workingDir}" is not within allowed folders: ${allowedFolders.join(", ")}`;
102680
+ const relativeDir = toRelativePath(workingDir, workspaceRoot);
102681
+ const relativeAllowed = allowedFolders.map((f5) => toRelativePath(f5, workspaceRoot));
102682
+ return `Error: Working directory "${relativeDir}" is not within allowed folders: ${relativeAllowed.join(", ")}`;
102392
102683
  }
102393
102684
  }
102394
102685
  const executionOptions = {