oroute-cli 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/oroute.cjs +1066 -318
  2. package/package.json +1 -1
package/dist/oroute.cjs CHANGED
@@ -23388,7 +23388,7 @@ var require_pdf_worker = __commonJS({
23388
23388
  });
23389
23389
  }
23390
23390
  },
23391
- parse: function parse(_ref4) {
23391
+ parse: function parse2(_ref4) {
23392
23392
  var xref = _ref4.xref, isEvalSupported = _ref4.isEvalSupported, fn = _ref4.fn;
23393
23393
  var IR = this.getIR({
23394
23394
  xref,
@@ -25624,7 +25624,7 @@ var require_pdf_worker = __commonJS({
25624
25624
  return encodeURIComponent(c);
25625
25625
  }
25626
25626
  var EOF, ALPHA = /[a-zA-Z]/, ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
25627
- function parse(input, stateOverride, base) {
25627
+ function parse2(input, stateOverride, base) {
25628
25628
  function err(message) {
25629
25629
  errors.push(message);
25630
25630
  }
@@ -25986,7 +25986,7 @@ var require_pdf_worker = __commonJS({
25986
25986
  this._url = url;
25987
25987
  clear.call(this);
25988
25988
  var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, "");
25989
- parse.call(this, input, null, base);
25989
+ parse2.call(this, input, null, base);
25990
25990
  }
25991
25991
  JURL.prototype = {
25992
25992
  toString: function toString() {
@@ -26004,7 +26004,7 @@ var require_pdf_worker = __commonJS({
26004
26004
  },
26005
26005
  set href(value) {
26006
26006
  clear.call(this);
26007
- parse.call(this, value);
26007
+ parse2.call(this, value);
26008
26008
  },
26009
26009
  get protocol() {
26010
26010
  return this._scheme + ":";
@@ -26013,7 +26013,7 @@ var require_pdf_worker = __commonJS({
26013
26013
  if (this._isInvalid) {
26014
26014
  return;
26015
26015
  }
26016
- parse.call(this, value + ":", "scheme start");
26016
+ parse2.call(this, value + ":", "scheme start");
26017
26017
  },
26018
26018
  get host() {
26019
26019
  return this._isInvalid ? "" : this._port ? this._host + ":" + this._port : this._host;
@@ -26022,7 +26022,7 @@ var require_pdf_worker = __commonJS({
26022
26022
  if (this._isInvalid || !this._isRelative) {
26023
26023
  return;
26024
26024
  }
26025
- parse.call(this, value, "host");
26025
+ parse2.call(this, value, "host");
26026
26026
  },
26027
26027
  get hostname() {
26028
26028
  return this._host;
@@ -26031,7 +26031,7 @@ var require_pdf_worker = __commonJS({
26031
26031
  if (this._isInvalid || !this._isRelative) {
26032
26032
  return;
26033
26033
  }
26034
- parse.call(this, value, "hostname");
26034
+ parse2.call(this, value, "hostname");
26035
26035
  },
26036
26036
  get port() {
26037
26037
  return this._port;
@@ -26040,7 +26040,7 @@ var require_pdf_worker = __commonJS({
26040
26040
  if (this._isInvalid || !this._isRelative) {
26041
26041
  return;
26042
26042
  }
26043
- parse.call(this, value, "port");
26043
+ parse2.call(this, value, "port");
26044
26044
  },
26045
26045
  get pathname() {
26046
26046
  return this._isInvalid ? "" : this._isRelative ? "/" + this._path.join("/") : this._schemeData;
@@ -26050,7 +26050,7 @@ var require_pdf_worker = __commonJS({
26050
26050
  return;
26051
26051
  }
26052
26052
  this._path = [];
26053
- parse.call(this, value, "relative path start");
26053
+ parse2.call(this, value, "relative path start");
26054
26054
  },
26055
26055
  get search() {
26056
26056
  return this._isInvalid || !this._query || this._query === "?" ? "" : this._query;
@@ -26063,7 +26063,7 @@ var require_pdf_worker = __commonJS({
26063
26063
  if (value[0] === "?") {
26064
26064
  value = value.slice(1);
26065
26065
  }
26066
- parse.call(this, value, "query");
26066
+ parse2.call(this, value, "query");
26067
26067
  },
26068
26068
  get hash() {
26069
26069
  return this._isInvalid || !this._fragment || this._fragment === "#" ? "" : this._fragment;
@@ -26076,7 +26076,7 @@ var require_pdf_worker = __commonJS({
26076
26076
  if (value[0] === "#") {
26077
26077
  value = value.slice(1);
26078
26078
  }
26079
- parse.call(this, value, "fragment");
26079
+ parse2.call(this, value, "fragment");
26080
26080
  },
26081
26081
  get origin() {
26082
26082
  var host;
@@ -32121,7 +32121,7 @@ var require_pdf_worker = __commonJS({
32121
32121
  };
32122
32122
  }
32123
32123
  JpegImage2.prototype = {
32124
- parse: function parse(data) {
32124
+ parse: function parse2(data) {
32125
32125
  function readUint16() {
32126
32126
  var value = data[offset] << 8 | data[offset + 1];
32127
32127
  offset += 2;
@@ -37804,7 +37804,7 @@ var require_pdf_worker = __commonJS({
37804
37804
  args: [x1, y1, x2, y2, x3, y3]
37805
37805
  });
37806
37806
  }
37807
- function parse(code2) {
37807
+ function parse2(code2) {
37808
37808
  var i = 0;
37809
37809
  while (i < code2.length) {
37810
37810
  var stackClean = false;
@@ -37868,7 +37868,7 @@ var require_pdf_worker = __commonJS({
37868
37868
  n = stack.pop() + font.subrsBias;
37869
37869
  subrCode = font.subrs[n];
37870
37870
  if (subrCode) {
37871
- parse(subrCode);
37871
+ parse2(subrCode);
37872
37872
  }
37873
37873
  break;
37874
37874
  case 11:
@@ -38054,7 +38054,7 @@ var require_pdf_worker = __commonJS({
38054
38054
  n = stack.pop() + font.gsubrsBias;
38055
38055
  subrCode = font.gsubrs[n];
38056
38056
  if (subrCode) {
38057
- parse(subrCode);
38057
+ parse2(subrCode);
38058
38058
  }
38059
38059
  break;
38060
38060
  case 30:
@@ -38120,7 +38120,7 @@ var require_pdf_worker = __commonJS({
38120
38120
  }
38121
38121
  }
38122
38122
  }
38123
- parse(code);
38123
+ parse2(code);
38124
38124
  }
38125
38125
  var noop = "";
38126
38126
  function CompiledFont(fontMatrix) {
@@ -52673,7 +52673,7 @@ var require_pdf = __commonJS({
52673
52673
  return encodeURIComponent(c);
52674
52674
  }
52675
52675
  var EOF, ALPHA = /[a-zA-Z]/, ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
52676
- function parse(input, stateOverride, base) {
52676
+ function parse2(input, stateOverride, base) {
52677
52677
  function err(message) {
52678
52678
  errors.push(message);
52679
52679
  }
@@ -53035,7 +53035,7 @@ var require_pdf = __commonJS({
53035
53035
  this._url = url;
53036
53036
  clear.call(this);
53037
53037
  var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, "");
53038
- parse.call(this, input, null, base);
53038
+ parse2.call(this, input, null, base);
53039
53039
  }
53040
53040
  JURL.prototype = {
53041
53041
  toString: function toString() {
@@ -53053,7 +53053,7 @@ var require_pdf = __commonJS({
53053
53053
  },
53054
53054
  set href(value) {
53055
53055
  clear.call(this);
53056
- parse.call(this, value);
53056
+ parse2.call(this, value);
53057
53057
  },
53058
53058
  get protocol() {
53059
53059
  return this._scheme + ":";
@@ -53062,7 +53062,7 @@ var require_pdf = __commonJS({
53062
53062
  if (this._isInvalid) {
53063
53063
  return;
53064
53064
  }
53065
- parse.call(this, value + ":", "scheme start");
53065
+ parse2.call(this, value + ":", "scheme start");
53066
53066
  },
53067
53067
  get host() {
53068
53068
  return this._isInvalid ? "" : this._port ? this._host + ":" + this._port : this._host;
@@ -53071,7 +53071,7 @@ var require_pdf = __commonJS({
53071
53071
  if (this._isInvalid || !this._isRelative) {
53072
53072
  return;
53073
53073
  }
53074
- parse.call(this, value, "host");
53074
+ parse2.call(this, value, "host");
53075
53075
  },
53076
53076
  get hostname() {
53077
53077
  return this._host;
@@ -53080,7 +53080,7 @@ var require_pdf = __commonJS({
53080
53080
  if (this._isInvalid || !this._isRelative) {
53081
53081
  return;
53082
53082
  }
53083
- parse.call(this, value, "hostname");
53083
+ parse2.call(this, value, "hostname");
53084
53084
  },
53085
53085
  get port() {
53086
53086
  return this._port;
@@ -53089,7 +53089,7 @@ var require_pdf = __commonJS({
53089
53089
  if (this._isInvalid || !this._isRelative) {
53090
53090
  return;
53091
53091
  }
53092
- parse.call(this, value, "port");
53092
+ parse2.call(this, value, "port");
53093
53093
  },
53094
53094
  get pathname() {
53095
53095
  return this._isInvalid ? "" : this._isRelative ? "/" + this._path.join("/") : this._schemeData;
@@ -53099,7 +53099,7 @@ var require_pdf = __commonJS({
53099
53099
  return;
53100
53100
  }
53101
53101
  this._path = [];
53102
- parse.call(this, value, "relative path start");
53102
+ parse2.call(this, value, "relative path start");
53103
53103
  },
53104
53104
  get search() {
53105
53105
  return this._isInvalid || !this._query || this._query === "?" ? "" : this._query;
@@ -53112,7 +53112,7 @@ var require_pdf = __commonJS({
53112
53112
  if (value[0] === "?") {
53113
53113
  value = value.slice(1);
53114
53114
  }
53115
- parse.call(this, value, "query");
53115
+ parse2.call(this, value, "query");
53116
53116
  },
53117
53117
  get hash() {
53118
53118
  return this._isInvalid || !this._fragment || this._fragment === "#" ? "" : this._fragment;
@@ -53125,7 +53125,7 @@ var require_pdf = __commonJS({
53125
53125
  if (value[0] === "#") {
53126
53126
  value = value.slice(1);
53127
53127
  }
53128
- parse.call(this, value, "fragment");
53128
+ parse2.call(this, value, "fragment");
53129
53129
  },
53130
53130
  get origin() {
53131
53131
  var host;
@@ -61161,8 +61161,8 @@ var require_pdf = __commonJS({
61161
61161
  }
61162
61162
  }
61163
61163
  var fs20 = require("fs");
61164
- var http = require("http");
61165
- var https = require("https");
61164
+ var http2 = require("http");
61165
+ var https2 = require("https");
61166
61166
  var url = require("url");
61167
61167
  var PDFNodeStream = (function() {
61168
61168
  function PDFNodeStream2(options) {
@@ -61441,9 +61441,9 @@ var require_pdf = __commonJS({
61441
61441
  };
61442
61442
  _this5._request = null;
61443
61443
  if (_this5._url.protocol === "http:") {
61444
- _this5._request = http.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
61444
+ _this5._request = http2.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
61445
61445
  } else {
61446
- _this5._request = https.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
61446
+ _this5._request = https2.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
61447
61447
  }
61448
61448
  _this5._request.on("error", function(reason) {
61449
61449
  _this5._errored = true;
@@ -61471,11 +61471,11 @@ var require_pdf = __commonJS({
61471
61471
  _this6._httpHeaders["Range"] = "bytes=" + start + "-" + (end - 1);
61472
61472
  _this6._request = null;
61473
61473
  if (_this6._url.protocol === "http:") {
61474
- _this6._request = http.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
61474
+ _this6._request = http2.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
61475
61475
  _this6._setReadableStream(response);
61476
61476
  });
61477
61477
  } else {
61478
- _this6._request = https.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
61478
+ _this6._request = https2.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
61479
61479
  _this6._setReadableStream(response);
61480
61480
  });
61481
61481
  }
@@ -85592,7 +85592,7 @@ var require_pdf_worker2 = __commonJS({
85592
85592
  });
85593
85593
  }
85594
85594
  },
85595
- parse: function parse(_ref4) {
85595
+ parse: function parse2(_ref4) {
85596
85596
  var xref = _ref4.xref, isEvalSupported = _ref4.isEvalSupported, fn = _ref4.fn;
85597
85597
  var IR = this.getIR({
85598
85598
  xref,
@@ -87839,7 +87839,7 @@ var require_pdf_worker2 = __commonJS({
87839
87839
  return encodeURIComponent(c);
87840
87840
  }
87841
87841
  var EOF, ALPHA = /[a-zA-Z]/, ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
87842
- function parse(input, stateOverride, base) {
87842
+ function parse2(input, stateOverride, base) {
87843
87843
  function err(message) {
87844
87844
  errors.push(message);
87845
87845
  }
@@ -88201,7 +88201,7 @@ var require_pdf_worker2 = __commonJS({
88201
88201
  this._url = url;
88202
88202
  clear.call(this);
88203
88203
  var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, "");
88204
- parse.call(this, input, null, base);
88204
+ parse2.call(this, input, null, base);
88205
88205
  }
88206
88206
  JURL.prototype = {
88207
88207
  toString: function toString() {
@@ -88219,7 +88219,7 @@ var require_pdf_worker2 = __commonJS({
88219
88219
  },
88220
88220
  set href(value) {
88221
88221
  clear.call(this);
88222
- parse.call(this, value);
88222
+ parse2.call(this, value);
88223
88223
  },
88224
88224
  get protocol() {
88225
88225
  return this._scheme + ":";
@@ -88228,7 +88228,7 @@ var require_pdf_worker2 = __commonJS({
88228
88228
  if (this._isInvalid) {
88229
88229
  return;
88230
88230
  }
88231
- parse.call(this, value + ":", "scheme start");
88231
+ parse2.call(this, value + ":", "scheme start");
88232
88232
  },
88233
88233
  get host() {
88234
88234
  return this._isInvalid ? "" : this._port ? this._host + ":" + this._port : this._host;
@@ -88237,7 +88237,7 @@ var require_pdf_worker2 = __commonJS({
88237
88237
  if (this._isInvalid || !this._isRelative) {
88238
88238
  return;
88239
88239
  }
88240
- parse.call(this, value, "host");
88240
+ parse2.call(this, value, "host");
88241
88241
  },
88242
88242
  get hostname() {
88243
88243
  return this._host;
@@ -88246,7 +88246,7 @@ var require_pdf_worker2 = __commonJS({
88246
88246
  if (this._isInvalid || !this._isRelative) {
88247
88247
  return;
88248
88248
  }
88249
- parse.call(this, value, "hostname");
88249
+ parse2.call(this, value, "hostname");
88250
88250
  },
88251
88251
  get port() {
88252
88252
  return this._port;
@@ -88255,7 +88255,7 @@ var require_pdf_worker2 = __commonJS({
88255
88255
  if (this._isInvalid || !this._isRelative) {
88256
88256
  return;
88257
88257
  }
88258
- parse.call(this, value, "port");
88258
+ parse2.call(this, value, "port");
88259
88259
  },
88260
88260
  get pathname() {
88261
88261
  return this._isInvalid ? "" : this._isRelative ? "/" + this._path.join("/") : this._schemeData;
@@ -88265,7 +88265,7 @@ var require_pdf_worker2 = __commonJS({
88265
88265
  return;
88266
88266
  }
88267
88267
  this._path = [];
88268
- parse.call(this, value, "relative path start");
88268
+ parse2.call(this, value, "relative path start");
88269
88269
  },
88270
88270
  get search() {
88271
88271
  return this._isInvalid || !this._query || this._query === "?" ? "" : this._query;
@@ -88278,7 +88278,7 @@ var require_pdf_worker2 = __commonJS({
88278
88278
  if (value[0] === "?") {
88279
88279
  value = value.slice(1);
88280
88280
  }
88281
- parse.call(this, value, "query");
88281
+ parse2.call(this, value, "query");
88282
88282
  },
88283
88283
  get hash() {
88284
88284
  return this._isInvalid || !this._fragment || this._fragment === "#" ? "" : this._fragment;
@@ -88291,7 +88291,7 @@ var require_pdf_worker2 = __commonJS({
88291
88291
  if (value[0] === "#") {
88292
88292
  value = value.slice(1);
88293
88293
  }
88294
- parse.call(this, value, "fragment");
88294
+ parse2.call(this, value, "fragment");
88295
88295
  },
88296
88296
  get origin() {
88297
88297
  var host;
@@ -94329,7 +94329,7 @@ var require_pdf_worker2 = __commonJS({
94329
94329
  };
94330
94330
  }
94331
94331
  JpegImage2.prototype = {
94332
- parse: function parse(data) {
94332
+ parse: function parse2(data) {
94333
94333
  function readUint16() {
94334
94334
  var value = data[offset] << 8 | data[offset + 1];
94335
94335
  offset += 2;
@@ -100006,7 +100006,7 @@ var require_pdf_worker2 = __commonJS({
100006
100006
  args: [x1, y1, x2, y2, x3, y3]
100007
100007
  });
100008
100008
  }
100009
- function parse(code2) {
100009
+ function parse2(code2) {
100010
100010
  var i = 0;
100011
100011
  while (i < code2.length) {
100012
100012
  var stackClean = false;
@@ -100070,7 +100070,7 @@ var require_pdf_worker2 = __commonJS({
100070
100070
  n = stack.pop() + font.subrsBias;
100071
100071
  subrCode = font.subrs[n];
100072
100072
  if (subrCode) {
100073
- parse(subrCode);
100073
+ parse2(subrCode);
100074
100074
  }
100075
100075
  break;
100076
100076
  case 11:
@@ -100256,7 +100256,7 @@ var require_pdf_worker2 = __commonJS({
100256
100256
  n = stack.pop() + font.gsubrsBias;
100257
100257
  subrCode = font.gsubrs[n];
100258
100258
  if (subrCode) {
100259
- parse(subrCode);
100259
+ parse2(subrCode);
100260
100260
  }
100261
100261
  break;
100262
100262
  case 30:
@@ -100322,7 +100322,7 @@ var require_pdf_worker2 = __commonJS({
100322
100322
  }
100323
100323
  }
100324
100324
  }
100325
- parse(code);
100325
+ parse2(code);
100326
100326
  }
100327
100327
  var noop = "";
100328
100328
  function CompiledFont(fontMatrix) {
@@ -114992,7 +114992,7 @@ var require_pdf2 = __commonJS({
114992
114992
  return encodeURIComponent(c);
114993
114993
  }
114994
114994
  var EOF, ALPHA = /[a-zA-Z]/, ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
114995
- function parse(input, stateOverride, base) {
114995
+ function parse2(input, stateOverride, base) {
114996
114996
  function err(message) {
114997
114997
  errors.push(message);
114998
114998
  }
@@ -115354,7 +115354,7 @@ var require_pdf2 = __commonJS({
115354
115354
  this._url = url;
115355
115355
  clear.call(this);
115356
115356
  var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, "");
115357
- parse.call(this, input, null, base);
115357
+ parse2.call(this, input, null, base);
115358
115358
  }
115359
115359
  JURL.prototype = {
115360
115360
  toString: function toString() {
@@ -115372,7 +115372,7 @@ var require_pdf2 = __commonJS({
115372
115372
  },
115373
115373
  set href(value) {
115374
115374
  clear.call(this);
115375
- parse.call(this, value);
115375
+ parse2.call(this, value);
115376
115376
  },
115377
115377
  get protocol() {
115378
115378
  return this._scheme + ":";
@@ -115381,7 +115381,7 @@ var require_pdf2 = __commonJS({
115381
115381
  if (this._isInvalid) {
115382
115382
  return;
115383
115383
  }
115384
- parse.call(this, value + ":", "scheme start");
115384
+ parse2.call(this, value + ":", "scheme start");
115385
115385
  },
115386
115386
  get host() {
115387
115387
  return this._isInvalid ? "" : this._port ? this._host + ":" + this._port : this._host;
@@ -115390,7 +115390,7 @@ var require_pdf2 = __commonJS({
115390
115390
  if (this._isInvalid || !this._isRelative) {
115391
115391
  return;
115392
115392
  }
115393
- parse.call(this, value, "host");
115393
+ parse2.call(this, value, "host");
115394
115394
  },
115395
115395
  get hostname() {
115396
115396
  return this._host;
@@ -115399,7 +115399,7 @@ var require_pdf2 = __commonJS({
115399
115399
  if (this._isInvalid || !this._isRelative) {
115400
115400
  return;
115401
115401
  }
115402
- parse.call(this, value, "hostname");
115402
+ parse2.call(this, value, "hostname");
115403
115403
  },
115404
115404
  get port() {
115405
115405
  return this._port;
@@ -115408,7 +115408,7 @@ var require_pdf2 = __commonJS({
115408
115408
  if (this._isInvalid || !this._isRelative) {
115409
115409
  return;
115410
115410
  }
115411
- parse.call(this, value, "port");
115411
+ parse2.call(this, value, "port");
115412
115412
  },
115413
115413
  get pathname() {
115414
115414
  return this._isInvalid ? "" : this._isRelative ? "/" + this._path.join("/") : this._schemeData;
@@ -115418,7 +115418,7 @@ var require_pdf2 = __commonJS({
115418
115418
  return;
115419
115419
  }
115420
115420
  this._path = [];
115421
- parse.call(this, value, "relative path start");
115421
+ parse2.call(this, value, "relative path start");
115422
115422
  },
115423
115423
  get search() {
115424
115424
  return this._isInvalid || !this._query || this._query === "?" ? "" : this._query;
@@ -115431,7 +115431,7 @@ var require_pdf2 = __commonJS({
115431
115431
  if (value[0] === "?") {
115432
115432
  value = value.slice(1);
115433
115433
  }
115434
- parse.call(this, value, "query");
115434
+ parse2.call(this, value, "query");
115435
115435
  },
115436
115436
  get hash() {
115437
115437
  return this._isInvalid || !this._fragment || this._fragment === "#" ? "" : this._fragment;
@@ -115444,7 +115444,7 @@ var require_pdf2 = __commonJS({
115444
115444
  if (value[0] === "#") {
115445
115445
  value = value.slice(1);
115446
115446
  }
115447
- parse.call(this, value, "fragment");
115447
+ parse2.call(this, value, "fragment");
115448
115448
  },
115449
115449
  get origin() {
115450
115450
  var host;
@@ -122997,8 +122997,8 @@ var require_pdf2 = __commonJS({
122997
122997
  }
122998
122998
  }
122999
122999
  var fs20 = require("fs");
123000
- var http = require("http");
123001
- var https = require("https");
123000
+ var http2 = require("http");
123001
+ var https2 = require("https");
123002
123002
  var url = require("url");
123003
123003
  var PDFNodeStream = (function() {
123004
123004
  function PDFNodeStream2(options) {
@@ -123277,9 +123277,9 @@ var require_pdf2 = __commonJS({
123277
123277
  };
123278
123278
  _this5._request = null;
123279
123279
  if (_this5._url.protocol === "http:") {
123280
- _this5._request = http.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
123280
+ _this5._request = http2.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
123281
123281
  } else {
123282
- _this5._request = https.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
123282
+ _this5._request = https2.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
123283
123283
  }
123284
123284
  _this5._request.on("error", function(reason) {
123285
123285
  _this5._errored = true;
@@ -123307,11 +123307,11 @@ var require_pdf2 = __commonJS({
123307
123307
  _this6._httpHeaders["Range"] = "bytes=" + start + "-" + (end - 1);
123308
123308
  _this6._request = null;
123309
123309
  if (_this6._url.protocol === "http:") {
123310
- _this6._request = http.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
123310
+ _this6._request = http2.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
123311
123311
  _this6._setReadableStream(response);
123312
123312
  });
123313
123313
  } else {
123314
- _this6._request = https.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
123314
+ _this6._request = https2.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
123315
123315
  _this6._setReadableStream(response);
123316
123316
  });
123317
123317
  }
@@ -153463,7 +153463,7 @@ var require_pdf_worker3 = __commonJS({
153463
153463
  args: [x1, y1, x2, y2, x3, y3]
153464
153464
  });
153465
153465
  }
153466
- function parse(code2) {
153466
+ function parse2(code2) {
153467
153467
  var i = 0;
153468
153468
  while (i < code2.length) {
153469
153469
  var stackClean = false;
@@ -153527,7 +153527,7 @@ var require_pdf_worker3 = __commonJS({
153527
153527
  n = stack.pop() + font.subrsBias;
153528
153528
  subrCode = font.subrs[n];
153529
153529
  if (subrCode) {
153530
- parse(subrCode);
153530
+ parse2(subrCode);
153531
153531
  }
153532
153532
  break;
153533
153533
  case 11:
@@ -153713,7 +153713,7 @@ var require_pdf_worker3 = __commonJS({
153713
153713
  n = stack.pop() + font.gsubrsBias;
153714
153714
  subrCode = font.gsubrs[n];
153715
153715
  if (subrCode) {
153716
- parse(subrCode);
153716
+ parse2(subrCode);
153717
153717
  }
153718
153718
  break;
153719
153719
  case 30:
@@ -153779,7 +153779,7 @@ var require_pdf_worker3 = __commonJS({
153779
153779
  }
153780
153780
  }
153781
153781
  }
153782
- parse(code);
153782
+ parse2(code);
153783
153783
  }
153784
153784
  var noop = "";
153785
153785
  function CompiledFont(fontMatrix) {
@@ -158339,7 +158339,7 @@ var require_pdf_worker3 = __commonJS({
158339
158339
  };
158340
158340
  }
158341
158341
  JpegImage2.prototype = {
158342
- parse: function parse(data) {
158342
+ parse: function parse2(data) {
158343
158343
  function readUint16() {
158344
158344
  var value = data[offset] << 8 | data[offset + 1];
158345
158345
  offset += 2;
@@ -164488,7 +164488,7 @@ var require_pdf_worker3 = __commonJS({
164488
164488
  return encodeURIComponent(c);
164489
164489
  }
164490
164490
  var EOF, ALPHA = /[a-zA-Z]/, ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
164491
- function parse(input, stateOverride, base) {
164491
+ function parse2(input, stateOverride, base) {
164492
164492
  function err(message) {
164493
164493
  errors.push(message);
164494
164494
  }
@@ -164850,7 +164850,7 @@ var require_pdf_worker3 = __commonJS({
164850
164850
  this._url = url;
164851
164851
  clear.call(this);
164852
164852
  var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, "");
164853
- parse.call(this, input, null, base);
164853
+ parse2.call(this, input, null, base);
164854
164854
  }
164855
164855
  JURL.prototype = {
164856
164856
  toString: function toString() {
@@ -164868,7 +164868,7 @@ var require_pdf_worker3 = __commonJS({
164868
164868
  },
164869
164869
  set href(value) {
164870
164870
  clear.call(this);
164871
- parse.call(this, value);
164871
+ parse2.call(this, value);
164872
164872
  },
164873
164873
  get protocol() {
164874
164874
  return this._scheme + ":";
@@ -164877,7 +164877,7 @@ var require_pdf_worker3 = __commonJS({
164877
164877
  if (this._isInvalid) {
164878
164878
  return;
164879
164879
  }
164880
- parse.call(this, value + ":", "scheme start");
164880
+ parse2.call(this, value + ":", "scheme start");
164881
164881
  },
164882
164882
  get host() {
164883
164883
  return this._isInvalid ? "" : this._port ? this._host + ":" + this._port : this._host;
@@ -164886,7 +164886,7 @@ var require_pdf_worker3 = __commonJS({
164886
164886
  if (this._isInvalid || !this._isRelative) {
164887
164887
  return;
164888
164888
  }
164889
- parse.call(this, value, "host");
164889
+ parse2.call(this, value, "host");
164890
164890
  },
164891
164891
  get hostname() {
164892
164892
  return this._host;
@@ -164895,7 +164895,7 @@ var require_pdf_worker3 = __commonJS({
164895
164895
  if (this._isInvalid || !this._isRelative) {
164896
164896
  return;
164897
164897
  }
164898
- parse.call(this, value, "hostname");
164898
+ parse2.call(this, value, "hostname");
164899
164899
  },
164900
164900
  get port() {
164901
164901
  return this._port;
@@ -164904,7 +164904,7 @@ var require_pdf_worker3 = __commonJS({
164904
164904
  if (this._isInvalid || !this._isRelative) {
164905
164905
  return;
164906
164906
  }
164907
- parse.call(this, value, "port");
164907
+ parse2.call(this, value, "port");
164908
164908
  },
164909
164909
  get pathname() {
164910
164910
  return this._isInvalid ? "" : this._isRelative ? "/" + this._path.join("/") : this._schemeData;
@@ -164914,7 +164914,7 @@ var require_pdf_worker3 = __commonJS({
164914
164914
  return;
164915
164915
  }
164916
164916
  this._path = [];
164917
- parse.call(this, value, "relative path start");
164917
+ parse2.call(this, value, "relative path start");
164918
164918
  },
164919
164919
  get search() {
164920
164920
  return this._isInvalid || !this._query || this._query === "?" ? "" : this._query;
@@ -164927,7 +164927,7 @@ var require_pdf_worker3 = __commonJS({
164927
164927
  if (value[0] === "?") {
164928
164928
  value = value.slice(1);
164929
164929
  }
164930
- parse.call(this, value, "query");
164930
+ parse2.call(this, value, "query");
164931
164931
  },
164932
164932
  get hash() {
164933
164933
  return this._isInvalid || !this._fragment || this._fragment === "#" ? "" : this._fragment;
@@ -164940,7 +164940,7 @@ var require_pdf_worker3 = __commonJS({
164940
164940
  if (value[0] === "#") {
164941
164941
  value = value.slice(1);
164942
164942
  }
164943
- parse.call(this, value, "fragment");
164943
+ parse2.call(this, value, "fragment");
164944
164944
  },
164945
164945
  get origin() {
164946
164946
  var host;
@@ -178054,7 +178054,7 @@ var require_pdf3 = __commonJS({
178054
178054
  return encodeURIComponent(c);
178055
178055
  }
178056
178056
  var EOF, ALPHA = /[a-zA-Z]/, ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
178057
- function parse(input, stateOverride, base) {
178057
+ function parse2(input, stateOverride, base) {
178058
178058
  function err(message) {
178059
178059
  errors.push(message);
178060
178060
  }
@@ -178416,7 +178416,7 @@ var require_pdf3 = __commonJS({
178416
178416
  this._url = url;
178417
178417
  clear.call(this);
178418
178418
  var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, "");
178419
- parse.call(this, input, null, base);
178419
+ parse2.call(this, input, null, base);
178420
178420
  }
178421
178421
  JURL.prototype = {
178422
178422
  toString: function toString() {
@@ -178434,7 +178434,7 @@ var require_pdf3 = __commonJS({
178434
178434
  },
178435
178435
  set href(value) {
178436
178436
  clear.call(this);
178437
- parse.call(this, value);
178437
+ parse2.call(this, value);
178438
178438
  },
178439
178439
  get protocol() {
178440
178440
  return this._scheme + ":";
@@ -178443,7 +178443,7 @@ var require_pdf3 = __commonJS({
178443
178443
  if (this._isInvalid) {
178444
178444
  return;
178445
178445
  }
178446
- parse.call(this, value + ":", "scheme start");
178446
+ parse2.call(this, value + ":", "scheme start");
178447
178447
  },
178448
178448
  get host() {
178449
178449
  return this._isInvalid ? "" : this._port ? this._host + ":" + this._port : this._host;
@@ -178452,7 +178452,7 @@ var require_pdf3 = __commonJS({
178452
178452
  if (this._isInvalid || !this._isRelative) {
178453
178453
  return;
178454
178454
  }
178455
- parse.call(this, value, "host");
178455
+ parse2.call(this, value, "host");
178456
178456
  },
178457
178457
  get hostname() {
178458
178458
  return this._host;
@@ -178461,7 +178461,7 @@ var require_pdf3 = __commonJS({
178461
178461
  if (this._isInvalid || !this._isRelative) {
178462
178462
  return;
178463
178463
  }
178464
- parse.call(this, value, "hostname");
178464
+ parse2.call(this, value, "hostname");
178465
178465
  },
178466
178466
  get port() {
178467
178467
  return this._port;
@@ -178470,7 +178470,7 @@ var require_pdf3 = __commonJS({
178470
178470
  if (this._isInvalid || !this._isRelative) {
178471
178471
  return;
178472
178472
  }
178473
- parse.call(this, value, "port");
178473
+ parse2.call(this, value, "port");
178474
178474
  },
178475
178475
  get pathname() {
178476
178476
  return this._isInvalid ? "" : this._isRelative ? "/" + this._path.join("/") : this._schemeData;
@@ -178480,7 +178480,7 @@ var require_pdf3 = __commonJS({
178480
178480
  return;
178481
178481
  }
178482
178482
  this._path = [];
178483
- parse.call(this, value, "relative path start");
178483
+ parse2.call(this, value, "relative path start");
178484
178484
  },
178485
178485
  get search() {
178486
178486
  return this._isInvalid || !this._query || this._query === "?" ? "" : this._query;
@@ -178493,7 +178493,7 @@ var require_pdf3 = __commonJS({
178493
178493
  if (value[0] === "?") {
178494
178494
  value = value.slice(1);
178495
178495
  }
178496
- parse.call(this, value, "query");
178496
+ parse2.call(this, value, "query");
178497
178497
  },
178498
178498
  get hash() {
178499
178499
  return this._isInvalid || !this._fragment || this._fragment === "#" ? "" : this._fragment;
@@ -178506,7 +178506,7 @@ var require_pdf3 = __commonJS({
178506
178506
  if (value[0] === "#") {
178507
178507
  value = value.slice(1);
178508
178508
  }
178509
- parse.call(this, value, "fragment");
178509
+ parse2.call(this, value, "fragment");
178510
178510
  },
178511
178511
  get origin() {
178512
178512
  var host;
@@ -180268,7 +180268,7 @@ var require_pdf_worker4 = __commonJS({
180268
180268
  return encodeURIComponent(c);
180269
180269
  }
180270
180270
  var EOF, ALPHA = /[a-zA-Z]/, ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
180271
- function parse(input, stateOverride, base) {
180271
+ function parse2(input, stateOverride, base) {
180272
180272
  function err(message) {
180273
180273
  errors.push(message);
180274
180274
  }
@@ -180630,7 +180630,7 @@ var require_pdf_worker4 = __commonJS({
180630
180630
  this._url = url;
180631
180631
  clear.call(this);
180632
180632
  var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, "");
180633
- parse.call(this, input, null, base);
180633
+ parse2.call(this, input, null, base);
180634
180634
  }
180635
180635
  JURL.prototype = {
180636
180636
  toString: function toString() {
@@ -180648,7 +180648,7 @@ var require_pdf_worker4 = __commonJS({
180648
180648
  },
180649
180649
  set href(value) {
180650
180650
  clear.call(this);
180651
- parse.call(this, value);
180651
+ parse2.call(this, value);
180652
180652
  },
180653
180653
  get protocol() {
180654
180654
  return this._scheme + ":";
@@ -180657,7 +180657,7 @@ var require_pdf_worker4 = __commonJS({
180657
180657
  if (this._isInvalid) {
180658
180658
  return;
180659
180659
  }
180660
- parse.call(this, value + ":", "scheme start");
180660
+ parse2.call(this, value + ":", "scheme start");
180661
180661
  },
180662
180662
  get host() {
180663
180663
  return this._isInvalid ? "" : this._port ? this._host + ":" + this._port : this._host;
@@ -180666,7 +180666,7 @@ var require_pdf_worker4 = __commonJS({
180666
180666
  if (this._isInvalid || !this._isRelative) {
180667
180667
  return;
180668
180668
  }
180669
- parse.call(this, value, "host");
180669
+ parse2.call(this, value, "host");
180670
180670
  },
180671
180671
  get hostname() {
180672
180672
  return this._host;
@@ -180675,7 +180675,7 @@ var require_pdf_worker4 = __commonJS({
180675
180675
  if (this._isInvalid || !this._isRelative) {
180676
180676
  return;
180677
180677
  }
180678
- parse.call(this, value, "hostname");
180678
+ parse2.call(this, value, "hostname");
180679
180679
  },
180680
180680
  get port() {
180681
180681
  return this._port;
@@ -180684,7 +180684,7 @@ var require_pdf_worker4 = __commonJS({
180684
180684
  if (this._isInvalid || !this._isRelative) {
180685
180685
  return;
180686
180686
  }
180687
- parse.call(this, value, "port");
180687
+ parse2.call(this, value, "port");
180688
180688
  },
180689
180689
  get pathname() {
180690
180690
  return this._isInvalid ? "" : this._isRelative ? "/" + this._path.join("/") : this._schemeData;
@@ -180694,7 +180694,7 @@ var require_pdf_worker4 = __commonJS({
180694
180694
  return;
180695
180695
  }
180696
180696
  this._path = [];
180697
- parse.call(this, value, "relative path start");
180697
+ parse2.call(this, value, "relative path start");
180698
180698
  },
180699
180699
  get search() {
180700
180700
  return this._isInvalid || !this._query || this._query === "?" ? "" : this._query;
@@ -180707,7 +180707,7 @@ var require_pdf_worker4 = __commonJS({
180707
180707
  if (value[0] === "?") {
180708
180708
  value = value.slice(1);
180709
180709
  }
180710
- parse.call(this, value, "query");
180710
+ parse2.call(this, value, "query");
180711
180711
  },
180712
180712
  get hash() {
180713
180713
  return this._isInvalid || !this._fragment || this._fragment === "#" ? "" : this._fragment;
@@ -180720,7 +180720,7 @@ var require_pdf_worker4 = __commonJS({
180720
180720
  if (value[0] === "#") {
180721
180721
  value = value.slice(1);
180722
180722
  }
180723
- parse.call(this, value, "fragment");
180723
+ parse2.call(this, value, "fragment");
180724
180724
  },
180725
180725
  get origin() {
180726
180726
  var host;
@@ -194299,7 +194299,7 @@ var require_pdf_worker4 = __commonJS({
194299
194299
  };
194300
194300
  }
194301
194301
  JpegImage2.prototype = {
194302
- parse: function parse(data) {
194302
+ parse: function parse2(data) {
194303
194303
  var _ref = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}, _ref$dnlScanLines = _ref.dnlScanLines, dnlScanLines = _ref$dnlScanLines === void 0 ? null : _ref$dnlScanLines;
194304
194304
  function readUint16() {
194305
194305
  var value = data[offset] << 8 | data[offset + 1];
@@ -215210,7 +215210,7 @@ var require_pdf_worker4 = __commonJS({
215210
215210
  args: [x1, y1, x2, y2, x3, y3]
215211
215211
  });
215212
215212
  }
215213
- function parse(code2) {
215213
+ function parse2(code2) {
215214
215214
  var i = 0;
215215
215215
  while (i < code2.length) {
215216
215216
  var stackClean = false;
@@ -215292,7 +215292,7 @@ var require_pdf_worker4 = __commonJS({
215292
215292
  subrCode = font.subrs[n + font.subrsBias];
215293
215293
  }
215294
215294
  if (subrCode) {
215295
- parse(subrCode);
215295
+ parse2(subrCode);
215296
215296
  }
215297
215297
  break;
215298
215298
  case 11:
@@ -215478,7 +215478,7 @@ var require_pdf_worker4 = __commonJS({
215478
215478
  n = stack.pop() + font.gsubrsBias;
215479
215479
  subrCode = font.gsubrs[n];
215480
215480
  if (subrCode) {
215481
- parse(subrCode);
215481
+ parse2(subrCode);
215482
215482
  }
215483
215483
  break;
215484
215484
  case 30:
@@ -215544,7 +215544,7 @@ var require_pdf_worker4 = __commonJS({
215544
215544
  }
215545
215545
  }
215546
215546
  }
215547
- parse(code);
215547
+ parse2(code);
215548
215548
  }
215549
215549
  var noop = "";
215550
215550
  function CompiledFont(fontMatrix) {
@@ -220336,7 +220336,7 @@ var require_pdf_worker4 = __commonJS({
220336
220336
  });
220337
220337
  }
220338
220338
  },
220339
- parse: function parse(_ref4) {
220339
+ parse: function parse2(_ref4) {
220340
220340
  var xref = _ref4.xref, isEvalSupported = _ref4.isEvalSupported, fn = _ref4.fn;
220341
220341
  var IR = this.getIR({
220342
220342
  xref,
@@ -223650,7 +223650,7 @@ var require_pdf4 = __commonJS({
223650
223650
  return encodeURIComponent(c);
223651
223651
  }
223652
223652
  var EOF, ALPHA = /[a-zA-Z]/, ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
223653
- function parse(input, stateOverride, base) {
223653
+ function parse2(input, stateOverride, base) {
223654
223654
  function err(message) {
223655
223655
  errors.push(message);
223656
223656
  }
@@ -224012,7 +224012,7 @@ var require_pdf4 = __commonJS({
224012
224012
  this._url = url;
224013
224013
  clear.call(this);
224014
224014
  var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, "");
224015
- parse.call(this, input, null, base);
224015
+ parse2.call(this, input, null, base);
224016
224016
  }
224017
224017
  JURL.prototype = {
224018
224018
  toString: function toString() {
@@ -224030,7 +224030,7 @@ var require_pdf4 = __commonJS({
224030
224030
  },
224031
224031
  set href(value) {
224032
224032
  clear.call(this);
224033
- parse.call(this, value);
224033
+ parse2.call(this, value);
224034
224034
  },
224035
224035
  get protocol() {
224036
224036
  return this._scheme + ":";
@@ -224039,7 +224039,7 @@ var require_pdf4 = __commonJS({
224039
224039
  if (this._isInvalid) {
224040
224040
  return;
224041
224041
  }
224042
- parse.call(this, value + ":", "scheme start");
224042
+ parse2.call(this, value + ":", "scheme start");
224043
224043
  },
224044
224044
  get host() {
224045
224045
  return this._isInvalid ? "" : this._port ? this._host + ":" + this._port : this._host;
@@ -224048,7 +224048,7 @@ var require_pdf4 = __commonJS({
224048
224048
  if (this._isInvalid || !this._isRelative) {
224049
224049
  return;
224050
224050
  }
224051
- parse.call(this, value, "host");
224051
+ parse2.call(this, value, "host");
224052
224052
  },
224053
224053
  get hostname() {
224054
224054
  return this._host;
@@ -224057,7 +224057,7 @@ var require_pdf4 = __commonJS({
224057
224057
  if (this._isInvalid || !this._isRelative) {
224058
224058
  return;
224059
224059
  }
224060
- parse.call(this, value, "hostname");
224060
+ parse2.call(this, value, "hostname");
224061
224061
  },
224062
224062
  get port() {
224063
224063
  return this._port;
@@ -224066,7 +224066,7 @@ var require_pdf4 = __commonJS({
224066
224066
  if (this._isInvalid || !this._isRelative) {
224067
224067
  return;
224068
224068
  }
224069
- parse.call(this, value, "port");
224069
+ parse2.call(this, value, "port");
224070
224070
  },
224071
224071
  get pathname() {
224072
224072
  return this._isInvalid ? "" : this._isRelative ? "/" + this._path.join("/") : this._schemeData;
@@ -224076,7 +224076,7 @@ var require_pdf4 = __commonJS({
224076
224076
  return;
224077
224077
  }
224078
224078
  this._path = [];
224079
- parse.call(this, value, "relative path start");
224079
+ parse2.call(this, value, "relative path start");
224080
224080
  },
224081
224081
  get search() {
224082
224082
  return this._isInvalid || !this._query || this._query === "?" ? "" : this._query;
@@ -224089,7 +224089,7 @@ var require_pdf4 = __commonJS({
224089
224089
  if (value[0] === "?") {
224090
224090
  value = value.slice(1);
224091
224091
  }
224092
- parse.call(this, value, "query");
224092
+ parse2.call(this, value, "query");
224093
224093
  },
224094
224094
  get hash() {
224095
224095
  return this._isInvalid || !this._fragment || this._fragment === "#" ? "" : this._fragment;
@@ -224102,7 +224102,7 @@ var require_pdf4 = __commonJS({
224102
224102
  if (value[0] === "#") {
224103
224103
  value = value.slice(1);
224104
224104
  }
224105
- parse.call(this, value, "fragment");
224105
+ parse2.call(this, value, "fragment");
224106
224106
  },
224107
224107
  get origin() {
224108
224108
  var host;
@@ -238007,8 +238007,8 @@ var require_pdf4 = __commonJS({
238007
238007
  }
238008
238008
  }
238009
238009
  var fs20 = require("fs");
238010
- var http = require("http");
238011
- var https = require("https");
238010
+ var http2 = require("http");
238011
+ var https2 = require("https");
238012
238012
  var url = require("url");
238013
238013
  var fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
238014
238014
  function parseUrl(sourceUrl) {
@@ -238308,9 +238308,9 @@ var require_pdf4 = __commonJS({
238308
238308
  };
238309
238309
  _this5._request = null;
238310
238310
  if (_this5._url.protocol === "http:") {
238311
- _this5._request = http.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
238311
+ _this5._request = http2.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
238312
238312
  } else {
238313
- _this5._request = https.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
238313
+ _this5._request = https2.request(createRequestOptions(_this5._url, stream.httpHeaders), handleResponse);
238314
238314
  }
238315
238315
  _this5._request.on("error", function(reason) {
238316
238316
  _this5._errored = true;
@@ -238338,11 +238338,11 @@ var require_pdf4 = __commonJS({
238338
238338
  _this6._httpHeaders["Range"] = "bytes=" + start + "-" + (end - 1);
238339
238339
  _this6._request = null;
238340
238340
  if (_this6._url.protocol === "http:") {
238341
- _this6._request = http.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
238341
+ _this6._request = http2.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
238342
238342
  _this6._setReadableStream(response);
238343
238343
  });
238344
238344
  } else {
238345
- _this6._request = https.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
238345
+ _this6._request = https2.request(createRequestOptions(_this6._url, _this6._httpHeaders), function(response) {
238346
238346
  _this6._setReadableStream(response);
238347
238347
  });
238348
238348
  }
@@ -239659,6 +239659,8 @@ var os9 = __toESM(require("node:os"), 1);
239659
239659
  var os7 = __toESM(require("node:os"), 1);
239660
239660
  var fs17 = __toESM(require("node:fs"), 1);
239661
239661
  var path16 = __toESM(require("node:path"), 1);
239662
+ var http = __toESM(require("node:http"), 1);
239663
+ var https = __toESM(require("node:https"), 1);
239662
239664
  var readline2 = __toESM(require("node:readline"), 1);
239663
239665
 
239664
239666
  // src/tools/readFile.ts
@@ -239865,6 +239867,39 @@ var readFileDefinition = {
239865
239867
  // src/tools/writeFile.ts
239866
239868
  var fs3 = __toESM(require("node:fs"), 1);
239867
239869
  var path3 = __toESM(require("node:path"), 1);
239870
+ var SECRET_PATTERNS = [
239871
+ [/\bsk-[a-zA-Z0-9]{20,}/g, "OpenAI API key (sk-...)"],
239872
+ [/\bor-[a-zA-Z0-9]{20,}/g, "O'Route API key (or-...)"],
239873
+ [/\bAKIA[A-Z0-9]{12,}/g, "AWS Access Key (AKIA...)"],
239874
+ [/password\s*[=:]\s*["'][^"']{4,}["']/gi, "Hardcoded password"],
239875
+ [/secret\s*[=:]\s*["'][^"']{4,}["']/gi, "Hardcoded secret"],
239876
+ [/token\s*[=:]\s*["'][^"']{8,}["']/gi, "Hardcoded token"],
239877
+ [/\bghp_[a-zA-Z0-9]{30,}/g, "GitHub personal access token"],
239878
+ [/\bglpat-[a-zA-Z0-9\-]{20,}/g, "GitLab personal access token"],
239879
+ [/\bxox[bprs]-[a-zA-Z0-9\-]{10,}/g, "Slack token"],
239880
+ [/-----BEGIN (?:RSA )?PRIVATE KEY-----/g, "Private key"]
239881
+ ];
239882
+ function scanForSecrets(content) {
239883
+ const warnings = [];
239884
+ for (const [pattern, label] of SECRET_PATTERNS) {
239885
+ pattern.lastIndex = 0;
239886
+ if (pattern.test(content)) {
239887
+ warnings.push(label);
239888
+ }
239889
+ }
239890
+ return warnings;
239891
+ }
239892
+ function checkWritePermission(dirPath) {
239893
+ try {
239894
+ fs3.accessSync(dirPath, fs3.constants.W_OK);
239895
+ } catch {
239896
+ throw new Error(
239897
+ `No write permission on directory: ${dirPath}
239898
+ Check permissions with: ls -la "${path3.dirname(dirPath)}"
239899
+ Fix with: chmod u+w "${dirPath}"`
239900
+ );
239901
+ }
239902
+ }
239868
239903
  function writeFileTool(input, cwd) {
239869
239904
  const resolved = smartResolve(input.path, cwd);
239870
239905
  const isNew = !fs3.existsSync(resolved);
@@ -239872,9 +239907,22 @@ function writeFileTool(input, cwd) {
239872
239907
  if (!fs3.existsSync(dir)) {
239873
239908
  fs3.mkdirSync(dir, { recursive: true });
239874
239909
  }
239910
+ checkWritePermission(dir);
239911
+ if (!isNew) {
239912
+ checkWritePermission(path3.dirname(resolved));
239913
+ try {
239914
+ fs3.accessSync(resolved, fs3.constants.W_OK);
239915
+ } catch {
239916
+ throw new Error(
239917
+ `No write permission on file: ${resolved}
239918
+ Fix with: chmod u+w "${resolved}"`
239919
+ );
239920
+ }
239921
+ }
239922
+ const secretWarnings = scanForSecrets(input.content);
239875
239923
  fs3.writeFileSync(resolved, input.content, "utf-8");
239876
239924
  const stat = fs3.statSync(resolved);
239877
- return { success: true, bytesWritten: stat.size, isNew };
239925
+ return { success: true, bytesWritten: stat.size, isNew, secretWarnings };
239878
239926
  }
239879
239927
  function generateDiff(filePath, newContent, cwd) {
239880
239928
  const resolved = smartResolve(filePath, cwd);
@@ -240523,8 +240571,12 @@ function diffFilesTool(input, cwd) {
240523
240571
  const pathB = smartResolve(input.file_b, cwd);
240524
240572
  if (!fs9.existsSync(pathA)) throw new Error(`File not found: ${pathA}`);
240525
240573
  if (!fs9.existsSync(pathB)) throw new Error(`File not found: ${pathB}`);
240526
- const linesA = fs9.readFileSync(pathA, "utf-8").split("\n");
240527
- const linesB = fs9.readFileSync(pathB, "utf-8").split("\n");
240574
+ let linesA = fs9.readFileSync(pathA, "utf-8").split("\n");
240575
+ let linesB = fs9.readFileSync(pathB, "utf-8").split("\n");
240576
+ if (input.ignoreWhitespace) {
240577
+ linesA = linesA.map((l) => l.trim());
240578
+ linesB = linesB.map((l) => l.trim());
240579
+ }
240528
240580
  const result = [];
240529
240581
  result.push(`--- ${input.file_a}`);
240530
240582
  result.push(`+++ ${input.file_b}`);
@@ -240584,20 +240636,82 @@ function diffFilesTool(input, cwd) {
240584
240636
 
240585
240637
  // src/ui.ts
240586
240638
  var readline = __toESM(require("node:readline"), 1);
240639
+ var colorScheme = process.env["OROUTE_COLOR_SCHEME"] ?? "default";
240640
+ var THEME_PRESETS = {
240641
+ default: {
240642
+ green: "\x1B[32m",
240643
+ cyan: "\x1B[36m",
240644
+ yellow: "\x1B[33m",
240645
+ red: "\x1B[31m",
240646
+ magenta: "\x1B[35m",
240647
+ blue: "\x1B[34m",
240648
+ gray: "\x1B[90m",
240649
+ white: "\x1B[97m"
240650
+ },
240651
+ nord: {
240652
+ green: "\x1B[38;2;163;190;140m",
240653
+ // #A3BE8C
240654
+ cyan: "\x1B[38;2;136;192;208m",
240655
+ // #88C0D0
240656
+ yellow: "\x1B[38;2;235;203;139m",
240657
+ // #EBCB8B
240658
+ red: "\x1B[38;2;191;97;106m",
240659
+ // #BF616A
240660
+ magenta: "\x1B[38;2;180;142;173m",
240661
+ // #B48EAD
240662
+ blue: "\x1B[38;2;129;161;193m",
240663
+ // #81A1C1
240664
+ gray: "\x1B[38;2;76;86;106m",
240665
+ // #4C566A
240666
+ white: "\x1B[38;2;236;239;244m"
240667
+ // #ECEFF4
240668
+ },
240669
+ dracula: {
240670
+ green: "\x1B[38;2;80;250;123m",
240671
+ // #50FA7B
240672
+ cyan: "\x1B[38;2;139;233;253m",
240673
+ // #8BE9FD
240674
+ yellow: "\x1B[38;2;241;250;140m",
240675
+ // #F1FA8C
240676
+ red: "\x1B[38;2;255;85;85m",
240677
+ // #FF5555
240678
+ magenta: "\x1B[38;2;255;121;198m",
240679
+ // #FF79C6
240680
+ blue: "\x1B[38;2;189;147;249m",
240681
+ // #BD93F9
240682
+ gray: "\x1B[38;2;98;114;164m",
240683
+ // #6272A4
240684
+ white: "\x1B[38;2;248;248;242m"
240685
+ // #F8F8F2
240686
+ }
240687
+ };
240688
+ var theme = THEME_PRESETS[colorScheme] ?? THEME_PRESETS.default;
240587
240689
  var isLightTheme = process.env["OROUTE_THEME"] === "light";
240588
- var GREEN = isLightTheme ? "\x1B[32m" : "\x1B[32m";
240589
- var GRAY = isLightTheme ? "\x1B[37m" : "\x1B[90m";
240690
+ var GREEN = isLightTheme ? "\x1B[32m" : theme.green;
240691
+ var GRAY = isLightTheme ? "\x1B[37m" : theme.gray;
240590
240692
  var BOLD = "\x1B[1m";
240591
240693
  var DIM = "\x1B[2m";
240592
240694
  var RESET = "\x1B[0m";
240593
- var CYAN = isLightTheme ? "\x1B[36m" : "\x1B[36m";
240594
- var YELLOW = isLightTheme ? "\x1B[33m" : "\x1B[33m";
240595
- var WHITE = isLightTheme ? "\x1B[30m" : "\x1B[97m";
240596
- var RED = "\x1B[31m";
240597
- var MAGENTA = "\x1B[35m";
240598
- var BLUE = isLightTheme ? "\x1B[34m" : "\x1B[34m";
240695
+ var CYAN = isLightTheme ? "\x1B[36m" : theme.cyan;
240696
+ var YELLOW = isLightTheme ? "\x1B[33m" : theme.yellow;
240697
+ var WHITE = isLightTheme ? "\x1B[30m" : theme.white;
240698
+ var RED = isLightTheme ? "\x1B[31m" : theme.red;
240699
+ var MAGENTA = isLightTheme ? "\x1B[35m" : theme.magenta;
240700
+ var BLUE = isLightTheme ? "\x1B[34m" : theme.blue;
240599
240701
  var BG_YELLOW = "\x1B[43m";
240600
240702
  var BLACK = "\x1B[30m";
240703
+ var LOG_LEVEL_PRIORITY = {
240704
+ error: 0,
240705
+ warn: 1,
240706
+ info: 2,
240707
+ debug: 3,
240708
+ trace: 4
240709
+ };
240710
+ var currentLogLevel = (() => {
240711
+ const env = (process.env["OROUTE_LOG_LEVEL"] ?? "info").toLowerCase();
240712
+ if (env in LOG_LEVEL_PRIORITY) return env;
240713
+ return "info";
240714
+ })();
240601
240715
  var TOOL_COLORS = {
240602
240716
  read_file: CYAN,
240603
240717
  write_file: YELLOW,
@@ -240924,42 +241038,14 @@ function extractPackageJson(filePath) {
240924
241038
  return "";
240925
241039
  }
240926
241040
  }
240927
- function getGitBranch(cwd) {
240928
- try {
240929
- return (0, import_node_child_process2.execSync)("git rev-parse --abbrev-ref HEAD 2>/dev/null", { cwd, encoding: "utf-8" }).trim() || void 0;
240930
- } catch {
240931
- return void 0;
240932
- }
240933
- }
240934
- function getGitStatusSummary(cwd) {
240935
- try {
240936
- const isGit = (0, import_node_child_process2.execSync)("git rev-parse --is-inside-work-tree 2>/dev/null", { cwd, encoding: "utf-8" }).trim();
240937
- if (isGit !== "true") return void 0;
240938
- const status = (0, import_node_child_process2.execSync)("git status --short 2>/dev/null", { cwd, encoding: "utf-8" }).trim();
240939
- if (!status) return "clean";
240940
- const lines = status.split("\n");
240941
- const modified = lines.filter((l) => l.startsWith(" M") || l.startsWith("M ")).length;
240942
- const added = lines.filter((l) => l.startsWith("A ") || l.startsWith("??")).length;
240943
- const deleted = lines.filter((l) => l.startsWith(" D") || l.startsWith("D ")).length;
240944
- const parts = [];
240945
- if (modified > 0) parts.push(`${modified} modified`);
240946
- if (added > 0) parts.push(`${added} untracked/added`);
240947
- if (deleted > 0) parts.push(`${deleted} deleted`);
240948
- return parts.join(", ") || "clean";
240949
- } catch {
240950
- return void 0;
240951
- }
240952
- }
240953
241041
  function loadProjectContext(cwd) {
240954
241042
  const contextFiles = [];
240955
- const candidates = [
241043
+ const essentialCandidates = [
240956
241044
  { name: "CLAUDE.md", loader: () => safeReadFile(path9.join(cwd, "CLAUDE.md")) },
240957
- { name: ".claude/CLAUDE.md", loader: () => safeReadFile(path9.join(cwd, ".claude", "CLAUDE.md")) },
240958
- { name: ".oroute.md", loader: () => safeReadFile(path9.join(cwd, ".oroute.md")) },
240959
241045
  { name: "package.json", loader: () => extractPackageJson(path9.join(cwd, "package.json")) }
240960
241046
  ];
240961
241047
  let totalChars = 0;
240962
- for (const c of candidates) {
241048
+ for (const c of essentialCandidates) {
240963
241049
  if (totalChars >= MAX_CONTEXT_CHARS) break;
240964
241050
  const content = c.loader();
240965
241051
  if (!content) continue;
@@ -240968,9 +241054,7 @@ function loadProjectContext(cwd) {
240968
241054
  contextFiles.push({ name: c.name, content: trimmed });
240969
241055
  totalChars += trimmed.length;
240970
241056
  }
240971
- const gitBranch = getGitBranch(cwd);
240972
- const gitStatus = getGitStatusSummary(cwd);
240973
- return { files: contextFiles, gitBranch, gitStatus };
241057
+ return { files: contextFiles, gitBranch: void 0, gitStatus: void 0 };
240974
241058
  }
240975
241059
  function buildContextString(ctx) {
240976
241060
  const parts = [];
@@ -241105,7 +241189,7 @@ ${summaryParts.join("\n")}`
241105
241189
  }
241106
241190
 
241107
241191
  // src/streaming.ts
241108
- async function parseSSEStream(response, onTextDelta) {
241192
+ async function parseSSEStream(response, onTextDelta, onTokenUpdate) {
241109
241193
  const contentBlocks = [];
241110
241194
  let stopReason = null;
241111
241195
  let usage = { input_tokens: 0, output_tokens: 0 };
@@ -241138,6 +241222,7 @@ async function parseSSEStream(response, onTextDelta) {
241138
241222
  },
241139
241223
  setUsage: (u) => {
241140
241224
  usage = u;
241225
+ if (onTokenUpdate) onTokenUpdate(u);
241141
241226
  },
241142
241227
  setModel: (m) => {
241143
241228
  model = m;
@@ -241215,7 +241300,9 @@ function processSSEEvent(evt, contentBlocks, onTextDelta, cb) {
241215
241300
  if (block.type === "text") {
241216
241301
  block.text = (block.text ?? "") + text;
241217
241302
  }
241218
- onTextDelta(text);
241303
+ for (const char of text) {
241304
+ onTextDelta(char);
241305
+ }
241219
241306
  } else if (delta["type"] === "input_json_delta") {
241220
241307
  const partial = delta["partial_json"];
241221
241308
  if (block.type === "tool_use") {
@@ -241368,6 +241455,15 @@ function printCostSummary(stats) {
241368
241455
  }
241369
241456
  console.log();
241370
241457
  }
241458
+ function isBudgetExceeded(stats, maxCostPerSession) {
241459
+ if (maxCostPerSession <= 0) return false;
241460
+ return estimateCost(stats) >= maxCostPerSession;
241461
+ }
241462
+ function printBudgetWarning(stats, maxCostPerSession) {
241463
+ const cost = estimateCost(stats);
241464
+ console.log(`${YELLOW} \u26A0 Session cost ($${cost.toFixed(4)}) has reached the budget limit ($${maxCostPerSession.toFixed(4)}).${RESET}`);
241465
+ console.log(`${GRAY} Set maxCost in .oroute/config.json to adjust, or type "continue" to proceed.${RESET}`);
241466
+ }
241371
241467
  function printExitSummary(stats) {
241372
241468
  if (stats.requests === 0) return;
241373
241469
  const cost = estimateCost(stats);
@@ -241380,6 +241476,26 @@ var fs12 = __toESM(require("node:fs"), 1);
241380
241476
  var path11 = __toESM(require("node:path"), 1);
241381
241477
  var os3 = __toESM(require("node:os"), 1);
241382
241478
  var SESSIONS_DIR = path11.join(os3.homedir(), ".oroute", "sessions");
241479
+ var SESSION_CACHE_MAX = 3;
241480
+ var sessionCache = /* @__PURE__ */ new Map();
241481
+ function cacheSession(id, session) {
241482
+ sessionCache.delete(id);
241483
+ sessionCache.set(id, session);
241484
+ if (sessionCache.size > SESSION_CACHE_MAX) {
241485
+ const oldestKey = sessionCache.keys().next().value;
241486
+ if (oldestKey !== void 0) {
241487
+ sessionCache.delete(oldestKey);
241488
+ }
241489
+ }
241490
+ }
241491
+ function getCachedSession(id) {
241492
+ const session = sessionCache.get(id);
241493
+ if (session) {
241494
+ sessionCache.delete(id);
241495
+ sessionCache.set(id, session);
241496
+ }
241497
+ return session;
241498
+ }
241383
241499
  function ensureSessionsDir() {
241384
241500
  if (!fs12.existsSync(SESSIONS_DIR)) {
241385
241501
  fs12.mkdirSync(SESSIONS_DIR, { recursive: true });
@@ -241432,19 +241548,28 @@ function listSessions(limit = 10) {
241432
241548
  }
241433
241549
  function loadSession(id) {
241434
241550
  ensureSessionsDir();
241551
+ const cached = getCachedSession(id);
241552
+ if (cached) return cached;
241435
241553
  const exactPath = path11.join(SESSIONS_DIR, `${id}.json`);
241436
241554
  if (fs12.existsSync(exactPath)) {
241437
241555
  try {
241438
- return JSON.parse(fs12.readFileSync(exactPath, "utf-8"));
241556
+ const session = JSON.parse(fs12.readFileSync(exactPath, "utf-8"));
241557
+ cacheSession(id, session);
241558
+ return session;
241439
241559
  } catch {
241440
241560
  return null;
241441
241561
  }
241442
241562
  }
241443
241563
  const files = fs12.readdirSync(SESSIONS_DIR).filter((f) => f.endsWith(".json") && f.startsWith(id)).sort().reverse();
241444
241564
  if (files.length === 0) return null;
241565
+ const resolvedId = files[0].replace(".json", "");
241566
+ const cachedPartial = getCachedSession(resolvedId);
241567
+ if (cachedPartial) return cachedPartial;
241445
241568
  const filePath = path11.join(SESSIONS_DIR, files[0]);
241446
241569
  try {
241447
- return JSON.parse(fs12.readFileSync(filePath, "utf-8"));
241570
+ const session = JSON.parse(fs12.readFileSync(filePath, "utf-8"));
241571
+ cacheSession(resolvedId, session);
241572
+ return session;
241448
241573
  } catch {
241449
241574
  return null;
241450
241575
  }
@@ -241695,6 +241820,7 @@ function getActiveTasks() {
241695
241820
  var import_meta = {};
241696
241821
  var debugMode = false;
241697
241822
  var dryRunMode = false;
241823
+ var skipConfirmations = false;
241698
241824
  var lastAiResponse = "";
241699
241825
  var undoStack = [];
241700
241826
  function isDryRun() {
@@ -241779,6 +241905,9 @@ var ALL_COMMANDS = [
241779
241905
  "/undo",
241780
241906
  "/next-task",
241781
241907
  "/dry-run",
241908
+ "/estimate-cost",
241909
+ "/skip-confirmation",
241910
+ "/yes",
241782
241911
  // Conversion / Info
241783
241912
  "/docx",
241784
241913
  "/xlsx",
@@ -241799,7 +241928,20 @@ var ALL_COMMANDS = [
241799
241928
  "/btw",
241800
241929
  "/batch",
241801
241930
  "/color",
241802
- "/terminal"
241931
+ "/terminal",
241932
+ // New features (11-17)
241933
+ "/explain",
241934
+ "/refs",
241935
+ "/resolve",
241936
+ "/stash",
241937
+ "/changelog",
241938
+ // Navigation & Search (41, 43)
241939
+ "/goto",
241940
+ "/find",
241941
+ // Code analysis (Features 7, 8, 10)
241942
+ "/test-gen",
241943
+ "/dead-code",
241944
+ "/deps"
241803
241945
  ];
241804
241946
  var COMMAND_DESCRIPTIONS = {
241805
241947
  "/help": "Show all available commands",
@@ -241884,7 +242026,17 @@ var COMMAND_DESCRIPTIONS = {
241884
242026
  "/btw": "Quick side question",
241885
242027
  "/batch": "Batch operations",
241886
242028
  "/color": "Terminal color palette",
241887
- "/terminal": "Terminal settings info"
242029
+ "/terminal": "Terminal settings info",
242030
+ "/explain": "Explain code at file:line using AI",
242031
+ "/refs": "Find all references of a symbol across project",
242032
+ "/resolve": "Detect and AI-resolve merge conflicts",
242033
+ "/stash": "Git stash management (save/pop/list)",
242034
+ "/changelog": "Generate CHANGELOG.md from git log",
242035
+ "/goto": "Navigate to type/function/class definition",
242036
+ "/find": "Semantic code search using AI",
242037
+ "/test-gen": "Generate tests for current file context",
242038
+ "/dead-code": "Detect unused imports/exports",
242039
+ "/deps": "Show dependency graph for a file"
241888
242040
  };
241889
242041
  var KNOWN_COMMANDS = new Set(ALL_COMMANDS);
241890
242042
  function shell(cmd, cwd) {
@@ -242066,20 +242218,36 @@ function handleSlashCommand(input, ctx) {
242066
242218
  console.log();
242067
242219
  return "handled";
242068
242220
  case "/pr":
242069
- console.log(`${CYAN} Creating pull request...${RESET}`);
242070
- shellPrint('gh pr create --web 2>/dev/null || echo " Install GitHub CLI: brew install gh"', ctx.cwd);
242221
+ handlePr(arg, ctx);
242071
242222
  return "handled";
242072
242223
  case "/pull":
242073
242224
  console.log(`${CYAN} Pulling latest changes...${RESET}`);
242074
242225
  shellPrint("git pull", ctx.cwd);
242075
242226
  return "handled";
242076
242227
  case "/push":
242077
- console.log(`${CYAN} Pushing to remote...${RESET}`);
242078
- shellPrint("git push", ctx.cwd);
242228
+ handlePush(ctx);
242079
242229
  return "handled";
242080
242230
  case "/commit":
242081
242231
  handleCommit(arg, ctx);
242082
242232
  return "handled";
242233
+ case "/stash":
242234
+ handleStash(arg, ctx);
242235
+ return "handled";
242236
+ case "/changelog":
242237
+ handleChangelog(ctx);
242238
+ return "handled";
242239
+ case "/resolve":
242240
+ handleResolveConflicts(ctx);
242241
+ return "handled";
242242
+ // -----------------------------------------------------------------------
242243
+ // Navigation & Search (41, 43)
242244
+ // -----------------------------------------------------------------------
242245
+ case "/goto":
242246
+ handleGoto(arg, ctx);
242247
+ return "handled";
242248
+ case "/find":
242249
+ handleFind(arg, ctx);
242250
+ return "handled";
242083
242251
  // -----------------------------------------------------------------------
242084
242252
  // File / Code commands
242085
242253
  // -----------------------------------------------------------------------
@@ -242099,6 +242267,12 @@ function handleSlashCommand(input, ctx) {
242099
242267
  console.log();
242100
242268
  }
242101
242269
  return "handled";
242270
+ case "/explain":
242271
+ handleExplain(arg, ctx);
242272
+ return "handled";
242273
+ case "/refs":
242274
+ handleRefs(arg, ctx);
242275
+ return "handled";
242102
242276
  case "/open":
242103
242277
  if (!arg) {
242104
242278
  console.log(`${YELLOW} Usage: /open <file|url> (opens in system default app)${RESET}`);
@@ -242258,6 +242432,26 @@ function handleSlashCommand(input, ctx) {
242258
242432
  '"\uB2E4\uC74C \uC791\uC5C5" or "Pending Tasks\uC5D0\uC11C \uB2E4\uC74C \uAC70 \uC9C4\uD589\uD574\uC918"'
242259
242433
  );
242260
242434
  return "handled";
242435
+ case "/estimate-cost": {
242436
+ const tokenCount = ctx.messages.reduce((sum, m) => {
242437
+ const text = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
242438
+ return sum + Math.ceil(text.length / 4);
242439
+ }, 0);
242440
+ const estInputCost = tokenCount / 1e6 * 3;
242441
+ const estOutputCost = 2e3 / 1e6 * 15;
242442
+ console.log(`${CYAN} Estimated cost for next request:${RESET}`);
242443
+ console.log(`${GRAY} Context: ~${tokenCount.toLocaleString()} tokens${RESET}`);
242444
+ console.log(`${GRAY} Input: ~$${estInputCost.toFixed(4)} (Sonnet rate)${RESET}`);
242445
+ console.log(`${GRAY} Output: ~$${estOutputCost.toFixed(4)} (est. 2K tokens)${RESET}`);
242446
+ console.log(`${GRAY} Total: ~$${(estInputCost + estOutputCost).toFixed(4)}${RESET}`);
242447
+ console.log(`${GRAY} (Auto-routing may select cheaper model)${RESET}`);
242448
+ return "handled";
242449
+ }
242450
+ case "/skip-confirmation":
242451
+ case "/yes":
242452
+ skipConfirmations = !skipConfirmations;
242453
+ console.log(`${skipConfirmations ? YELLOW : GREEN} Confirmations: ${skipConfirmations ? "SKIPPED (auto-yes)" : "ENABLED (will ask before writes)"}${RESET}`);
242454
+ return "handled";
242261
242455
  // -----------------------------------------------------------------------
242262
242456
  // Conversion / Info — natural language hints
242263
242457
  // -----------------------------------------------------------------------
@@ -242353,6 +242547,18 @@ function handleSlashCommand(input, ctx) {
242353
242547
  );
242354
242548
  return "handled";
242355
242549
  // -----------------------------------------------------------------------
242550
+ // Code analysis (Features 7, 8, 10)
242551
+ // -----------------------------------------------------------------------
242552
+ case "/test-gen":
242553
+ handleTestGen(arg, ctx);
242554
+ return "handled";
242555
+ case "/dead-code":
242556
+ handleDeadCode(arg, ctx);
242557
+ return "handled";
242558
+ case "/deps":
242559
+ handleDeps(arg, ctx);
242560
+ return "handled";
242561
+ // -----------------------------------------------------------------------
242356
242562
  // Misc
242357
242563
  // -----------------------------------------------------------------------
242358
242564
  case "/btw":
@@ -242637,6 +242843,204 @@ function handleUndo() {
242637
242843
  console.log(`${RED} Failed to undo: ${err instanceof Error ? err.message : String(err)}${RESET}`);
242638
242844
  }
242639
242845
  }
242846
+ function handleExplain(arg, ctx) {
242847
+ if (!arg) {
242848
+ console.log(`${YELLOW} Usage: /explain <file:line> (e.g. /explain src/agent.ts:42)${RESET}`);
242849
+ return;
242850
+ }
242851
+ const match = arg.match(/^(.+?):(\d+)$/);
242852
+ if (!match) {
242853
+ console.log(`${YELLOW} Usage: /explain <file:line> (e.g. /explain src/agent.ts:42)${RESET}`);
242854
+ return;
242855
+ }
242856
+ const filePath = path14.resolve(ctx.cwd, match[1]);
242857
+ const lineNum = parseInt(match[2], 10);
242858
+ if (!fs15.existsSync(filePath)) {
242859
+ console.log(`${RED} File not found: ${filePath}${RESET}`);
242860
+ return;
242861
+ }
242862
+ try {
242863
+ const fileLines = fs15.readFileSync(filePath, "utf-8").split("\n");
242864
+ const start = Math.max(0, lineNum - 10);
242865
+ const end = Math.min(fileLines.length, lineNum + 10);
242866
+ const snippet = fileLines.slice(start, end).map((l, i) => {
242867
+ const num = start + i + 1;
242868
+ const marker = num === lineNum ? ">>>" : " ";
242869
+ return `${marker} ${String(num).padStart(4)} | ${l}`;
242870
+ }).join("\n");
242871
+ console.log();
242872
+ console.log(`${WHITE} ${match[1]}:${lineNum}${RESET}`);
242873
+ console.log(`${GRAY}${"\u2500".repeat(50)}${RESET}`);
242874
+ console.log(snippet);
242875
+ console.log(`${GRAY}${"\u2500".repeat(50)}${RESET}`);
242876
+ console.log();
242877
+ const prompt = `Please explain this code step by step. File: ${match[1]}, around line ${lineNum}:
242878
+
242879
+ \`\`\`
242880
+ ${snippet}
242881
+ \`\`\``;
242882
+ ctx.messages.push({ role: "user", content: prompt });
242883
+ ctx.setMessages(ctx.messages);
242884
+ console.log(`${GRAY} Asking AI to explain...${RESET}`);
242885
+ } catch (err) {
242886
+ console.log(`${RED} Failed to read: ${err instanceof Error ? err.message : String(err)}${RESET}`);
242887
+ }
242888
+ }
242889
+ function handleRefs(arg, ctx) {
242890
+ if (!arg) {
242891
+ console.log(`${YELLOW} Usage: /refs <symbol> (e.g. /refs handleSlashCommand)${RESET}`);
242892
+ return;
242893
+ }
242894
+ console.log(`${CYAN} Searching for "${arg}" across project...${RESET}`);
242895
+ console.log();
242896
+ const escaped = arg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
242897
+ const output = shell(`grep -rn --color=never "${escaped}" . --include='*.ts' --include='*.tsx' --include='*.js' --include='*.jsx' --include='*.py' --include='*.go' --include='*.rs' --include='*.java' --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist --exclude-dir=.next 2>/dev/null | head -50`, ctx.cwd);
242898
+ if (!output || output.includes("Command failed")) {
242899
+ console.log(`${GRAY} No references found for "${arg}".${RESET}`);
242900
+ } else {
242901
+ const resultLines = output.split("\n");
242902
+ console.log(`${WHITE} Found ${resultLines.length} reference(s):${RESET}`);
242903
+ console.log();
242904
+ for (const line of resultLines) console.log(` ${line}`);
242905
+ }
242906
+ console.log();
242907
+ }
242908
+ function handlePr(_arg, ctx) {
242909
+ const ghCheck = shell("which gh 2>/dev/null", ctx.cwd);
242910
+ if (!ghCheck || ghCheck.includes("Command failed")) {
242911
+ console.log(`${YELLOW} GitHub CLI not found. Install: brew install gh${RESET}`);
242912
+ return;
242913
+ }
242914
+ console.log(`${CYAN} Preparing pull request...${RESET}`);
242915
+ console.log();
242916
+ const branch = shell("git rev-parse --abbrev-ref HEAD", ctx.cwd);
242917
+ if (!branch || branch === "HEAD") {
242918
+ console.log(`${RED} Not on a branch. Cannot create PR.${RESET}`);
242919
+ return;
242920
+ }
242921
+ const recentCommits = shell("git log --oneline -5 2>/dev/null", ctx.cwd);
242922
+ const firstCommitLine = recentCommits.split("\n")[0] ?? "";
242923
+ const suggestedTitle = firstCommitLine.replace(/^[a-f0-9]+ /, "");
242924
+ const mainBranch = shell('git remote show origin 2>/dev/null | grep "HEAD branch" | sed "s/.*: //"', ctx.cwd) || "main";
242925
+ const diffStat = shell(`git diff ${mainBranch}...HEAD --stat 2>/dev/null`, ctx.cwd);
242926
+ const commitCount = shell(`git rev-list --count ${mainBranch}..HEAD 2>/dev/null`, ctx.cwd);
242927
+ console.log(`${WHITE} Branch: ${branch}${RESET}`);
242928
+ console.log(`${WHITE} Base: ${mainBranch}${RESET}`);
242929
+ console.log(`${WHITE} Commits: ${commitCount || "?"}${RESET}`);
242930
+ if (diffStat) console.log(`${GRAY}${diffStat}${RESET}`);
242931
+ console.log();
242932
+ console.log(`${WHITE} Suggested title: ${suggestedTitle}${RESET}`);
242933
+ console.log(`${WHITE} Recent commits:${RESET}`);
242934
+ console.log(`${GRAY}${recentCommits}${RESET}`);
242935
+ console.log();
242936
+ const safeTitle = suggestedTitle.replace(/"/g, '\\"');
242937
+ const safeDiff = (diffStat || "").replace(/\n/g, "\\n").replace(/"/g, '\\"');
242938
+ shellPrint(`gh pr create --title "${safeTitle}" --body "## Changes\\n${safeDiff}\\n\\nCommits: ${commitCount || "?"}" --web 2>/dev/null || echo " Failed to create PR. Run: gh auth login"`, ctx.cwd);
242939
+ console.log();
242940
+ }
242941
+ function handleResolveConflicts(ctx) {
242942
+ console.log(`${CYAN} Scanning for merge conflicts...${RESET}`);
242943
+ const output = shell('grep -rn "<<<<<<< " . --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" --include="*.json" --include="*.md" --exclude-dir=node_modules --exclude-dir=.git 2>/dev/null | head -20', ctx.cwd);
242944
+ if (!output || output.includes("Command failed")) {
242945
+ console.log(`${GREEN} No merge conflicts found.${RESET}`);
242946
+ console.log();
242947
+ return;
242948
+ }
242949
+ const resultLines = output.split("\n").filter(Boolean);
242950
+ const files = [...new Set(resultLines.map((l) => l.split(":")[0]))];
242951
+ console.log(`${YELLOW} Found conflicts in ${files.length} file(s):${RESET}`);
242952
+ console.log();
242953
+ for (const file of files) console.log(`${RED} \u2716 ${file}${RESET}`);
242954
+ console.log();
242955
+ const prompt = `I have merge conflicts in these files:
242956
+ ${files.map((f) => `- ${f}`).join("\n")}
242957
+
242958
+ Please read each conflicted file, understand both sides of the conflict (between <<<<<<< and >>>>>>>) and suggest the best resolution. For each file, use edit_file to resolve the conflict by removing the conflict markers and keeping the correct code.`;
242959
+ ctx.messages.push({ role: "user", content: prompt });
242960
+ ctx.setMessages(ctx.messages);
242961
+ console.log(`${GRAY} Asking AI to resolve conflicts...${RESET}`);
242962
+ }
242963
+ function handleStash(arg, ctx) {
242964
+ const stashParts = arg.trim().split(/\s+/);
242965
+ const sub = stashParts[0] ?? "";
242966
+ const stashMsg = stashParts.slice(1).join(" ");
242967
+ switch (sub) {
242968
+ case "":
242969
+ case "save": {
242970
+ console.log(`${CYAN} Stashing changes...${RESET}`);
242971
+ const cmd = stashMsg ? `git stash push -m "${stashMsg.replace(/"/g, '\\"')}"` : "git stash push";
242972
+ shellPrint(cmd, ctx.cwd);
242973
+ break;
242974
+ }
242975
+ case "pop":
242976
+ console.log(`${CYAN} Applying latest stash...${RESET}`);
242977
+ shellPrint("git stash pop", ctx.cwd);
242978
+ break;
242979
+ case "list":
242980
+ console.log(`${BOLD} Git Stash List${RESET}`);
242981
+ console.log(`${GRAY} ${"\u2500".repeat(40)}${RESET}`);
242982
+ shellPrint("git stash list", ctx.cwd);
242983
+ break;
242984
+ case "drop":
242985
+ console.log(`${CYAN} Dropping latest stash...${RESET}`);
242986
+ shellPrint("git stash drop", ctx.cwd);
242987
+ break;
242988
+ case "show":
242989
+ shellPrint("git stash show -p", ctx.cwd);
242990
+ break;
242991
+ default:
242992
+ console.log(`${YELLOW} Usage: /stash [save|pop|list|drop|show] [message]${RESET}`);
242993
+ }
242994
+ console.log();
242995
+ }
242996
+ function handlePush(ctx) {
242997
+ const branch = shell("git rev-parse --abbrev-ref HEAD", ctx.cwd);
242998
+ if (["main", "master", "production", "prod"].includes(branch)) {
242999
+ console.log(`${RED} \u26A0 WARNING: You are on the '${branch}' branch!${RESET}`);
243000
+ console.log(`${YELLOW} Direct pushes to ${branch} are discouraged.${RESET}`);
243001
+ console.log(`${GRAY} Consider creating a feature branch and a pull request instead.${RESET}`);
243002
+ console.log(`${GRAY} Pushing anyway...${RESET}`);
243003
+ }
243004
+ console.log(`${CYAN} Pushing to remote...${RESET}`);
243005
+ shellPrint("git push", ctx.cwd);
243006
+ }
243007
+ function handleChangelog(ctx) {
243008
+ console.log(`${CYAN} Generating changelog...${RESET}`);
243009
+ console.log();
243010
+ const log = shell("git log --oneline -20 2>/dev/null", ctx.cwd);
243011
+ if (!log || log.includes("Command failed")) {
243012
+ console.log(`${YELLOW} No git history found.${RESET}`);
243013
+ return;
243014
+ }
243015
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
243016
+ const logLines = log.split("\n").filter(Boolean);
243017
+ const categories = {};
243018
+ for (const line of logLines) {
243019
+ const commitMsg = line.replace(/^[a-f0-9]+ /, "");
243020
+ const typeMatch = commitMsg.match(/^(feat|fix|refactor|docs|test|chore|perf|ci|style|build)(\(.*?\))?:\s*/);
243021
+ const type = typeMatch ? typeMatch[1] : "other";
243022
+ const msg = typeMatch ? commitMsg.replace(typeMatch[0], "") : commitMsg;
243023
+ if (!categories[type]) categories[type] = [];
243024
+ categories[type].push(msg);
243025
+ }
243026
+ const typeLabels = { feat: "Features", fix: "Bug Fixes", refactor: "Refactoring", docs: "Documentation", test: "Tests", perf: "Performance", chore: "Chores", other: "Other" };
243027
+ const changelogEntryLines = [`## [Unreleased] - ${today}`, ""];
243028
+ for (const [type, msgs] of Object.entries(categories)) {
243029
+ changelogEntryLines.push(`### ${typeLabels[type] ?? type}`);
243030
+ for (const msg of msgs) changelogEntryLines.push(`- ${msg}`);
243031
+ changelogEntryLines.push("");
243032
+ }
243033
+ const changelog = changelogEntryLines.join("\n");
243034
+ console.log(changelog);
243035
+ const changelogPath = path14.join(ctx.cwd, "CHANGELOG.md");
243036
+ const existing = fs15.existsSync(changelogPath) ? fs15.readFileSync(changelogPath, "utf-8") : "";
243037
+ const header = existing.startsWith("# Changelog") ? "" : "# Changelog\n\n";
243038
+ const newContent = existing ? existing.replace(/(# Changelog\n\n?)/, `$1${changelog}
243039
+ `) : `${header}${changelog}`;
243040
+ fs15.writeFileSync(changelogPath, newContent, "utf-8");
243041
+ console.log(`${GREEN} Updated: ${changelogPath}${RESET}`);
243042
+ console.log();
243043
+ }
242640
243044
  function printHelp() {
242641
243045
  console.log();
242642
243046
  console.log(`${BOLD} O'Route CLI Commands${RESET}`);
@@ -242712,6 +243116,9 @@ function printHelp() {
242712
243116
  console.log(`${GREEN} /seo${RESET} SEO analysis`);
242713
243117
  console.log(`${GREEN} /security${RESET} Security audit`);
242714
243118
  console.log(`${GREEN} /deploy-audit${RESET} Deployment readiness check`);
243119
+ console.log(`${GREEN} /test-gen [file]${RESET} Generate tests for a file`);
243120
+ console.log(`${GREEN} /dead-code [scope]${RESET} Detect unused imports/exports`);
243121
+ console.log(`${GREEN} /deps <file>${RESET} Show dependency graph for a file`);
242715
243122
  console.log();
242716
243123
  console.log(`${BOLD} Sub-agents & Plugins${RESET}`);
242717
243124
  console.log(`${GRAY} ${"\u2500".repeat(50)}${RESET}`);
@@ -242870,12 +243277,30 @@ function printTools() {
242870
243277
  function printKeybindings() {
242871
243278
  console.log();
242872
243279
  console.log(`${BOLD} Keyboard Shortcuts${RESET}`);
242873
- console.log(`${GRAY} ${"\u2500".repeat(40)}${RESET}`);
242874
- console.log(`${WHITE} Ctrl+C${RESET} Cancel current input / interrupt`);
242875
- console.log(`${WHITE} Ctrl+D${RESET} Exit CLI`);
242876
- console.log(`${WHITE} Up/Down${RESET} Navigate input history`);
242877
- console.log(`${WHITE} Tab${RESET} Autocomplete slash commands`);
242878
- console.log(`${WHITE} """${RESET} Toggle multi-line input mode`);
243280
+ console.log(`${GRAY} ${"\u2500".repeat(50)}${RESET}`);
243281
+ console.log();
243282
+ console.log(`${BOLD} Navigation${RESET}`);
243283
+ console.log(`${GREEN} Ctrl+C${RESET} Cancel current input / interrupt streaming`);
243284
+ console.log(`${GREEN} Ctrl+D${RESET} Exit CLI (end of input)`);
243285
+ console.log(`${GREEN} Ctrl+L${RESET} Clear terminal screen`);
243286
+ console.log();
243287
+ console.log(`${BOLD} History${RESET}`);
243288
+ console.log(`${GREEN} Up Arrow${RESET} Previous command from history`);
243289
+ console.log(`${GREEN} Down Arrow${RESET} Next command from history`);
243290
+ console.log(`${GREEN} Ctrl+R${RESET} Reverse search history (shell)`);
243291
+ console.log();
243292
+ console.log(`${BOLD} Editing${RESET}`);
243293
+ console.log(`${GREEN} Tab${RESET} Autocomplete slash commands`);
243294
+ console.log(`${GREEN} Ctrl+A${RESET} Move cursor to start of line`);
243295
+ console.log(`${GREEN} Ctrl+E${RESET} Move cursor to end of line`);
243296
+ console.log(`${GREEN} Ctrl+W${RESET} Delete word before cursor`);
243297
+ console.log(`${GREEN} Ctrl+U${RESET} Delete from cursor to start of line`);
243298
+ console.log(`${GREEN} Ctrl+K${RESET} Delete from cursor to end of line`);
243299
+ console.log();
243300
+ console.log(`${BOLD} Input Modes${RESET}`);
243301
+ console.log(`${GREEN} """${RESET} Toggle multi-line input mode`);
243302
+ console.log(`${GREEN} !<cmd>${RESET} Execute shell command directly`);
243303
+ console.log(`${GREEN} /<command>${RESET} Run a slash command`);
242879
243304
  console.log();
242880
243305
  }
242881
243306
  function printColorPalette() {
@@ -242969,6 +243394,126 @@ function handleExport(arg, ctx) {
242969
243394
  }
242970
243395
  console.log();
242971
243396
  }
243397
+ function handleGoto(symbol, ctx) {
243398
+ if (!symbol) {
243399
+ console.log(`${YELLOW} Usage: /goto <symbol> (e.g. /goto UserService, /goto handleLogin)${RESET}`);
243400
+ return;
243401
+ }
243402
+ console.log(`${CYAN} Searching for definition of "${symbol}"...${RESET}`);
243403
+ const escapedSymbol = symbol.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
243404
+ const pattern = `export.*(function|class|type|interface|const|enum)\\s+${escapedSymbol}`;
243405
+ const output = shell(
243406
+ `grep -rn --include='*.ts' --include='*.tsx' --include='*.js' --include='*.jsx' -E "${pattern}" . 2>/dev/null | head -20`,
243407
+ ctx.cwd
243408
+ );
243409
+ if (!output || output.startsWith("Command failed")) {
243410
+ console.log(`${GRAY} No exported definition found for "${symbol}". Trying broader search...${RESET}`);
243411
+ const broadOutput = shell(
243412
+ `grep -rn --include='*.ts' --include='*.tsx' --include='*.js' --include='*.jsx' -E "(function|class|type|interface|const|enum)\\s+${escapedSymbol}" . 2>/dev/null | head -20`,
243413
+ ctx.cwd
243414
+ );
243415
+ if (!broadOutput || broadOutput.startsWith("Command failed")) {
243416
+ console.log(`${YELLOW} No definition found for "${symbol}".${RESET}`);
243417
+ } else {
243418
+ console.log();
243419
+ console.log(broadOutput);
243420
+ }
243421
+ } else {
243422
+ console.log();
243423
+ console.log(output);
243424
+ }
243425
+ console.log();
243426
+ }
243427
+ function handleFind(description, ctx) {
243428
+ if (!description) {
243429
+ console.log(`${YELLOW} Usage: /find <description> (e.g. /find "function that validates email")${RESET}`);
243430
+ return;
243431
+ }
243432
+ const prompt = `Search this project's codebase to find code that matches this description: "${description}". Use search_files and glob tools to locate relevant files, then read the matching sections. Show the file path, line number, and a brief snippet for each match.`;
243433
+ ctx.messages.push({ role: "user", content: prompt });
243434
+ console.log(`${CYAN} Asking AI to find: "${description}"${RESET}`);
243435
+ console.log(`${GRAY} (AI will use tools to search the codebase)${RESET}`);
243436
+ console.log();
243437
+ }
243438
+ function handleTestGen(arg, ctx) {
243439
+ const target = arg || "the most recently discussed file";
243440
+ const prompt = `Generate comprehensive unit tests for ${target}. Follow these steps:
243441
+ 1. Read the target file(s) using read_file
243442
+ 2. Analyze all exported functions, classes, and key logic
243443
+ 3. Write test cases covering: happy path, edge cases, error handling, boundary conditions
243444
+ 4. Use the project's existing test framework (detect from package.json \u2014 jest, vitest, mocha, etc.)
243445
+ 5. If no test framework is detected, use Node.js built-in test runner
243446
+ 6. Write the tests to a corresponding test file (e.g., foo.ts \u2192 foo.test.ts)
243447
+ 7. Include at minimum: 1 test per exported function, 1 edge case per function, 1 error case per function
243448
+
243449
+ Output the complete test file content.`;
243450
+ ctx.messages.push({ role: "user", content: prompt });
243451
+ console.log(`${CYAN} Generating tests for: ${target}${RESET}`);
243452
+ console.log(`${GRAY} (AI will read the file and create tests)${RESET}`);
243453
+ console.log();
243454
+ }
243455
+ function handleDeadCode(arg, ctx) {
243456
+ const scope = arg || ".";
243457
+ const prompt = `Analyze the codebase at "${scope}" for dead code. Follow these steps:
243458
+ 1. Use glob to find all TypeScript/JavaScript source files in the scope
243459
+ 2. For each file, identify all exports (functions, classes, types, constants)
243460
+ 3. Use search_files to check if each export is imported/used elsewhere in the project
243461
+ 4. Report:
243462
+ - Unused exports (exported but never imported)
243463
+ - Unused imports (imported but never referenced in the file)
243464
+ - Unreachable code (code after return/throw statements)
243465
+ - Unused variables/parameters (if obvious)
243466
+
243467
+ Format the results as a list grouped by file, showing the symbol name, type, and line number.
243468
+ Mark severity: HIGH (unused export), MEDIUM (unused import), LOW (unused variable).`;
243469
+ ctx.messages.push({ role: "user", content: prompt });
243470
+ console.log(`${CYAN} Analyzing dead code in: ${scope}${RESET}`);
243471
+ console.log(`${GRAY} (AI will scan imports/exports across the project)${RESET}`);
243472
+ console.log();
243473
+ }
243474
+ function handleDeps(arg, ctx) {
243475
+ if (!arg) {
243476
+ console.log(`${YELLOW} Usage: /deps <file> (e.g. /deps src/agent.ts)${RESET}`);
243477
+ console.log(`${GRAY} Shows all files that import the given file (reverse dependencies).${RESET}`);
243478
+ return;
243479
+ }
243480
+ const basename6 = path14.basename(arg).replace(/\.(ts|tsx|js|jsx)$/, "");
243481
+ const searchPatterns = [
243482
+ `from.*['"].*${basename6}['"]`,
243483
+ `require.*['"].*${basename6}['"]`
243484
+ ];
243485
+ console.log(`${BOLD} Dependency Graph: ${arg}${RESET}`);
243486
+ console.log(`${GRAY} ${"\u2500".repeat(40)}${RESET}`);
243487
+ console.log();
243488
+ console.log(`${WHITE} Files that import "${basename6}":${RESET}`);
243489
+ let totalFound = 0;
243490
+ for (const pattern of searchPatterns) {
243491
+ try {
243492
+ const result = shell(
243493
+ `grep -rn --include='*.ts' --include='*.tsx' --include='*.js' --include='*.jsx' "${pattern}" . 2>/dev/null | grep -v node_modules | grep -v '.d.ts'`,
243494
+ ctx.cwd
243495
+ );
243496
+ if (result && !result.startsWith("Command failed")) {
243497
+ const lines = result.split("\n").filter(Boolean);
243498
+ for (const line of lines) {
243499
+ const [filePart] = line.split(":");
243500
+ if (filePart && !filePart.includes(arg)) {
243501
+ console.log(`${GREEN} ${line}${RESET}`);
243502
+ totalFound++;
243503
+ }
243504
+ }
243505
+ }
243506
+ } catch {
243507
+ }
243508
+ }
243509
+ if (totalFound === 0) {
243510
+ console.log(`${GRAY} No files import "${basename6}" in this project.${RESET}`);
243511
+ } else {
243512
+ console.log();
243513
+ console.log(`${GRAY} Found ${totalFound} reference(s).${RESET}`);
243514
+ }
243515
+ console.log();
243516
+ }
242972
243517
 
242973
243518
  // src/hooks.ts
242974
243519
  var fs16 = __toESM(require("node:fs"), 1);
@@ -243053,6 +243598,8 @@ function substituteEnvVars(command, env) {
243053
243598
 
243054
243599
  // src/agent.ts
243055
243600
  init_mcpLoader();
243601
+ var keepAliveHttpAgent = new http.Agent({ keepAlive: true });
243602
+ var keepAliveHttpsAgent = new https.Agent({ keepAlive: true });
243056
243603
  var TOOL_DEFINITIONS = [
243057
243604
  readFileDefinition,
243058
243605
  writeFileDefinition,
@@ -243071,20 +243618,56 @@ var PARALLEL_SAFE_TOOLS = /* @__PURE__ */ new Set([
243071
243618
  "read_image"
243072
243619
  ]);
243073
243620
  var MAX_TOOL_RESULT_CHARS = 4e3;
243074
- var MIN_API_DELAY_MS = 500;
243621
+ var MODEL_DELAYS = {
243622
+ opus: 2e3,
243623
+ sonnet: 1e3,
243624
+ haiku: 300,
243625
+ mini: 300
243626
+ };
243627
+ var DEFAULT_API_DELAY_MS = 500;
243628
+ function getModelDelay(model) {
243629
+ const lower = model.toLowerCase();
243630
+ for (const [key, delay] of Object.entries(MODEL_DELAYS)) {
243631
+ if (lower.includes(key)) return delay;
243632
+ }
243633
+ return DEFAULT_API_DELAY_MS;
243634
+ }
243075
243635
  var lastApiCallTime = 0;
243076
- function appendAuditLog(toolName, filePath) {
243636
+ var turnRollbackBuffer = /* @__PURE__ */ new Map();
243637
+ function appendAuditLog(toolName, filePath, extra) {
243077
243638
  try {
243078
243639
  const auditDir = path16.join(os7.homedir(), ".oroute");
243079
243640
  if (!fs17.existsSync(auditDir)) fs17.mkdirSync(auditDir, { recursive: true });
243080
243641
  const logPath = path16.join(auditDir, "audit.log");
243081
243642
  const ts = (/* @__PURE__ */ new Date()).toISOString();
243082
- const entry = `${ts} tool=${toolName} path=${filePath ?? "-"}
243083
- `;
243084
- fs17.appendFileSync(logPath, entry);
243643
+ let entry = `${ts} tool=${toolName} path=${filePath ?? "-"}`;
243644
+ if (extra?.command) entry += ` cmd=${extra.command}`;
243645
+ if (extra?.escalation) entry += ` escalation=${extra.escalation}`;
243646
+ if (extra?.affectedFiles && extra.affectedFiles.length > 0) entry += ` affected=${extra.affectedFiles.join(",")}`;
243647
+ fs17.appendFileSync(logPath, entry + "\n");
243085
243648
  } catch {
243086
243649
  }
243087
243650
  }
243651
+ function detectCommandEscalation(command) {
243652
+ const modifyingPatterns = [
243653
+ [/\bgit\s+(add|commit|reset|checkout|merge|rebase|push|rm)\b/, "git-modify"],
243654
+ [/\bnpm\s+(install|uninstall|update|publish|init)\b/, "npm-modify"],
243655
+ [/\bpnpm\s+(add|remove|install|update|publish)\b/, "pnpm-modify"],
243656
+ [/\byarn\s+(add|remove|install|upgrade|publish)\b/, "yarn-modify"],
243657
+ [/\brm\s/, "file-delete"],
243658
+ [/\bmv\s/, "file-move"],
243659
+ [/\bcp\s/, "file-copy"],
243660
+ [/\bchmod\s/, "permission-change"],
243661
+ [/\bchown\s/, "ownership-change"],
243662
+ [/\bmkdir\s/, "directory-create"]
243663
+ ];
243664
+ for (const [pattern, reason] of modifyingPatterns) {
243665
+ if (pattern.test(command)) {
243666
+ return { escalation: reason, reason: `Command matches modifying pattern: ${reason}` };
243667
+ }
243668
+ }
243669
+ return null;
243670
+ }
243088
243671
  function maskDebugSecrets(text) {
243089
243672
  return text.replace(/\b(or|sk|key)-[a-zA-Z0-9]{10,}/g, "$1-****").replace(/Bearer\s+[a-zA-Z0-9._\-]{10,}/gi, "Bearer ****").replace(/(API_KEY|SECRET|TOKEN|PASSWORD)\s*[=:]\s*["']?[^\s"']{5,}/gi, "$1=****");
243090
243673
  }
@@ -243263,7 +243846,21 @@ ${contextSection}${memorySection}
243263
243846
  - Never output API keys, tokens, passwords, or secrets
243264
243847
  - Never execute curl/wget piped to sh
243265
243848
  - Validate that file paths don't escape the project directory
243266
- - Flag potential security issues in code you review`;
243849
+ - Flag potential security issues in code you review
243850
+
243851
+ ## Auto Import Management
243852
+ - When you create new functions, types, or constants that are used in other files, automatically add the necessary import statements to those files.
243853
+ - When you rename or move exports, update all import references across the project.
243854
+ - Before adding an import, verify the export exists in the source file.
243855
+ - Use the project's existing import style (named vs default, relative vs alias paths).
243856
+
243857
+ ## Syntax Error Context (Feature 42)
243858
+ - When you encounter a syntax error, automatically read 20 lines before and after the error line to understand the full context before attempting a fix.
243859
+ - Use read_file with offset=(errorLine - 20) and limit=41 to get surrounding context.
243860
+
243861
+ ## Refactoring Suggestions (Feature 44)
243862
+ - When you notice repeated code patterns (3+ similar blocks), proactively suggest extracting them into a shared function.
243863
+ - Mention the duplication, propose a function signature, and ask if the user wants you to refactor.`;
243267
243864
  }
243268
243865
  function truncateResult(result) {
243269
243866
  if (result.length <= MAX_TOOL_RESULT_CHARS) return result;
@@ -243274,123 +243871,186 @@ function truncateResult(result) {
243274
243871
  ... (${totalLines - keptLines} lines, ${omittedChars} chars truncated \u2014 showing ${keptLines}/${totalLines} lines)`;
243275
243872
  }
243276
243873
  async function executeTool(tool, cwd, config) {
243874
+ if (config.toolBlacklist && config.toolBlacklist.includes(tool.name)) {
243875
+ const msg = `Tool "${tool.name}" is blacklisted in config. Skipping.`;
243876
+ console.log(`${YELLOW} ${msg}${RESET}`);
243877
+ return JSON.stringify({ error: msg });
243878
+ }
243277
243879
  const confirmWrite = config.skipConfirmations ? false : config.confirmBeforeWrite !== false;
243278
243880
  const confirmExec = config.skipConfirmations ? false : config.confirmBeforeExecute !== false;
243881
+ const toolStart = performance.now();
243279
243882
  try {
243280
- switch (tool.name) {
243281
- case "read_file": {
243282
- const input = tool.input;
243283
- printToolUse("read_file", input.path);
243284
- const result = await readFileTool(input, cwd);
243285
- printToolResult(result.content);
243286
- return truncateResult(JSON.stringify({ content: result.content, lines: result.lines, size: result.size }));
243883
+ const result = await executeToolInner(tool, cwd, confirmWrite, confirmExec, config);
243884
+ const elapsed = performance.now() - toolStart;
243885
+ if (elapsed > 100) {
243886
+ console.log(`${DIM} (${tool.name} took ${elapsed.toFixed(0)}ms)${RESET}`);
243887
+ }
243888
+ return result;
243889
+ } catch (err) {
243890
+ const elapsed = performance.now() - toolStart;
243891
+ const msg = err instanceof Error ? err.message : String(err);
243892
+ printError(`${tool.name}: ${msg}`);
243893
+ if (elapsed > 100) {
243894
+ console.log(`${DIM} (failed after ${elapsed.toFixed(0)}ms)${RESET}`);
243895
+ }
243896
+ if (turnRollbackBuffer.size > 0) {
243897
+ console.log(`${YELLOW} Tool failed. ${turnRollbackBuffer.size} file(s) can be rolled back.${RESET}`);
243898
+ for (const [filePath] of turnRollbackBuffer) {
243899
+ console.log(`${GRAY} - ${filePath}${RESET}`);
243287
243900
  }
243288
- case "write_file": {
243289
- const input = tool.input;
243290
- printToolUse("write_file", input.path);
243291
- const diff = generateDiff(input.path, input.content, cwd);
243292
- console.log(`${GRAY}${diff}${RESET}`);
243293
- if (isDryRun()) {
243294
- console.log(`${YELLOW} [DRY-RUN] Would write ${input.content.length} chars to ${input.path}${RESET}`);
243295
- return JSON.stringify({ success: true, note: "dry-run \u2014 not written" });
243901
+ for (const [filePath, content] of turnRollbackBuffer) {
243902
+ try {
243903
+ fs17.writeFileSync(filePath, content, "utf-8");
243904
+ console.log(`${GREEN} Rolled back: ${filePath}${RESET}`);
243905
+ } catch {
243296
243906
  }
243297
- if (confirmWrite) {
243298
- const ok = await confirm(`Write to ${input.path}?`);
243299
- if (!ok) return JSON.stringify({ success: false, reason: "User declined" });
243907
+ }
243908
+ turnRollbackBuffer.clear();
243909
+ }
243910
+ return JSON.stringify({ error: msg });
243911
+ }
243912
+ }
243913
+ async function executeToolInner(tool, cwd, confirmWrite, confirmExec, config) {
243914
+ switch (tool.name) {
243915
+ case "read_file": {
243916
+ const input = tool.input;
243917
+ printToolUse("read_file", input.path);
243918
+ const result = await readFileTool(input, cwd);
243919
+ printToolResult(result.content);
243920
+ return truncateResult(JSON.stringify({ content: result.content, lines: result.lines, size: result.size }));
243921
+ }
243922
+ case "write_file": {
243923
+ const input = tool.input;
243924
+ printToolUse("write_file", input.path);
243925
+ const resolvedForRollback = path16.resolve(cwd, input.path);
243926
+ if (fs17.existsSync(resolvedForRollback) && !turnRollbackBuffer.has(resolvedForRollback)) {
243927
+ try {
243928
+ turnRollbackBuffer.set(resolvedForRollback, fs17.readFileSync(resolvedForRollback, "utf-8"));
243929
+ } catch {
243300
243930
  }
243301
- const result = writeFileTool(input, cwd);
243302
- printSuccess(`Written ${result.bytesWritten} bytes${result.isNew ? " (new file)" : ""}`);
243303
- return JSON.stringify(result);
243304
243931
  }
243305
- case "list_directory": {
243306
- const input = tool.input;
243307
- printToolUse("list_directory", input.path);
243308
- const tree = listDirectoryTool(input, cwd);
243309
- printToolResult(tree);
243310
- return truncateResult(tree);
243932
+ const resolved = path16.resolve(cwd, input.path);
243933
+ const dangerPaths = ["/etc", "/usr", "/bin", "/sbin", "/System", "/Windows", "node_modules"];
243934
+ if (dangerPaths.some((d) => resolved.startsWith(d) || resolved.includes("node_modules"))) {
243935
+ console.log(`${RED} \u26A0 WARNING: Writing to system/protected path: ${resolved}${RESET}`);
243311
243936
  }
243312
- case "search_files": {
243313
- const input = tool.input;
243314
- printToolUse("search_files", `"${input.pattern}" in ${input.path}`);
243315
- const output = searchFilesTool(input, cwd);
243316
- const formatted = output.results.map((r) => `${r.file}:${r.line}: ${r.content}`).join("\n");
243317
- const meta = output.hasMore ? `
243318
- (${output.totalFound}+ total matches, showing ${output.offset + 1}-${output.offset + output.results.length}. Use offset=${output.offset + output.limit} for more.)` : "";
243319
- printToolResult((formatted || "No matches found.") + meta);
243320
- return truncateResult(JSON.stringify(output));
243937
+ if (resolved.includes(".env")) {
243938
+ console.log(`${YELLOW} \u26A0 Modifying .env file \u2014 secrets may be affected${RESET}`);
243321
243939
  }
243322
- case "execute_command": {
243323
- const input = tool.input;
243324
- printToolUse("execute_command", input.command);
243325
- if (config.planMode || isDryRun()) {
243326
- const tag = config.planMode ? "PLAN MODE" : "DRY-RUN";
243327
- console.log(`${YELLOW} [${tag}] Would execute: ${input.command}${RESET}`);
243328
- return JSON.stringify({ stdout: `[${tag.toLowerCase()} \u2014 not executed]`, stderr: "", exitCode: 0 });
243329
- }
243330
- if (confirmExec) {
243331
- const ok = await confirm(`Execute: ${input.command}`);
243332
- if (!ok) return JSON.stringify({ stdout: "", stderr: "User declined", exitCode: -1 });
243333
- }
243334
- const result = executeCommandTool(input, cwd);
243335
- if (result.stdout) printToolResult(result.stdout);
243336
- if (result.stderr) console.log(`${RED}${result.stderr}${RESET}`);
243337
- if (result.exitCode === 0) printSuccess("Command completed");
243338
- else console.log(`${YELLOW} Exit code: ${result.exitCode}${RESET}`);
243339
- return truncateResult(JSON.stringify(result));
243940
+ const diff = generateDiff(input.path, input.content, cwd);
243941
+ console.log(`${GRAY}${diff}${RESET}`);
243942
+ if (isDryRun()) {
243943
+ console.log(`${YELLOW} [DRY-RUN] Would write ${input.content.length} chars to ${input.path}${RESET}`);
243944
+ return JSON.stringify({ success: true, note: "dry-run \u2014 not written" });
243340
243945
  }
243341
- case "edit_file": {
243342
- const input = tool.input;
243343
- printToolUse("edit_file", input.path);
243344
- const diff = generateEditDiff(input);
243345
- console.log(`${GRAY}${diff}${RESET}`);
243346
- if (config.planMode || isDryRun()) {
243347
- const tag = config.planMode ? "PLAN MODE" : "DRY-RUN";
243348
- console.log(`${YELLOW} [${tag}] Would edit: ${input.path}${RESET}`);
243349
- return JSON.stringify({ success: true, note: `${tag.toLowerCase()} \u2014 not executed` });
243350
- }
243351
- if (confirmWrite) {
243352
- const ok = await confirm(`Edit ${input.path}?`);
243353
- if (!ok) return JSON.stringify({ success: false, reason: "User declined" });
243946
+ const secretWarnings = scanForSecrets(input.content);
243947
+ if (secretWarnings.length > 0) {
243948
+ console.log(`${RED} WARNING: Potential secrets detected in file content:${RESET}`);
243949
+ for (const warning of secretWarnings) {
243950
+ console.log(`${YELLOW} - ${warning}${RESET}`);
243354
243951
  }
243355
- const result = editFileTool(input, cwd);
243356
- printSuccess("Edit applied");
243357
- return JSON.stringify(result);
243952
+ const secretOk = await confirm("File contains potential secrets. Write anyway?");
243953
+ if (!secretOk) return JSON.stringify({ success: false, reason: "User declined \u2014 secrets detected" });
243358
243954
  }
243359
- case "glob": {
243360
- const input = tool.input;
243361
- printToolUse("glob", input.pattern);
243362
- const results = globTool(input, cwd);
243363
- const formatted = results.join("\n");
243364
- printToolResult(formatted || "No matches found.");
243365
- return truncateResult(JSON.stringify({ matches: results, count: results.length }));
243955
+ if (confirmWrite && secretWarnings.length === 0) {
243956
+ const ok = await confirm(`Write to ${input.path}?`);
243957
+ if (!ok) return JSON.stringify({ success: false, reason: "User declined" });
243366
243958
  }
243367
- case "read_image": {
243368
- const input = tool.input;
243369
- printToolUse("read_image", input.path);
243370
- const result = readImageTool(input, cwd);
243371
- printSuccess(`Read image: ${result.media_type}, ${(result.size / 1024).toFixed(1)}KB`);
243372
- return JSON.stringify(result);
243959
+ const result = writeFileTool(input, cwd);
243960
+ printSuccess(`Written ${result.bytesWritten} bytes${result.isNew ? " (new file)" : ""}`);
243961
+ return JSON.stringify(result);
243962
+ }
243963
+ case "list_directory": {
243964
+ const input = tool.input;
243965
+ printToolUse("list_directory", input.path);
243966
+ const tree = listDirectoryTool(input, cwd);
243967
+ printToolResult(tree);
243968
+ return truncateResult(tree);
243969
+ }
243970
+ case "search_files": {
243971
+ const input = tool.input;
243972
+ printToolUse("search_files", `"${input.pattern}" in ${input.path}`);
243973
+ const output = searchFilesTool(input, cwd);
243974
+ const formatted = output.results.map((r) => `${r.file}:${r.line}: ${r.content}`).join("\n");
243975
+ const meta = output.hasMore ? `
243976
+ (${output.totalFound}+ total matches, showing ${output.offset + 1}-${output.offset + output.results.length}. Use offset=${output.offset + output.limit} for more.)` : "";
243977
+ printToolResult((formatted || "No matches found.") + meta);
243978
+ return truncateResult(JSON.stringify(output));
243979
+ }
243980
+ case "execute_command": {
243981
+ const input = tool.input;
243982
+ printToolUse("execute_command", input.command);
243983
+ if (config.planMode || isDryRun()) {
243984
+ const tag = config.planMode ? "PLAN MODE" : "DRY-RUN";
243985
+ console.log(`${YELLOW} [${tag}] Would execute: ${input.command}${RESET}`);
243986
+ return JSON.stringify({ stdout: `[${tag.toLowerCase()} \u2014 not executed]`, stderr: "", exitCode: 0 });
243373
243987
  }
243374
- case "diff_files": {
243375
- const input = tool.input;
243376
- printToolUse("diff_files", `${input.file_a} \u2194 ${input.file_b}`);
243377
- const result = diffFilesTool(input, cwd);
243378
- const coloredLines = result.split("\n").map((line) => {
243379
- if (line.startsWith("+")) return `${GREEN}${line}${RESET}`;
243380
- if (line.startsWith("-")) return `${RED}${line}${RESET}`;
243381
- if (line.startsWith("@")) return `${CYAN}${line}${RESET}`;
243382
- return line;
243383
- });
243384
- printToolResult(coloredLines.join("\n"));
243385
- return truncateResult(result);
243988
+ if (confirmExec) {
243989
+ const ok = await confirm(`Execute: ${input.command}`);
243990
+ if (!ok) return JSON.stringify({ stdout: "", stderr: "User declined", exitCode: -1 });
243386
243991
  }
243387
- default:
243388
- return JSON.stringify({ error: `Unknown tool: ${tool.name}` });
243992
+ const result = executeCommandTool(input, cwd);
243993
+ if (result.stdout) printToolResult(result.stdout);
243994
+ if (result.stderr) console.log(`${RED}${result.stderr}${RESET}`);
243995
+ if (result.exitCode === 0) printSuccess("Command completed");
243996
+ else console.log(`${YELLOW} Exit code: ${result.exitCode}${RESET}`);
243997
+ return truncateResult(JSON.stringify(result));
243389
243998
  }
243390
- } catch (err) {
243391
- const msg = err instanceof Error ? err.message : String(err);
243392
- printError(msg);
243393
- return JSON.stringify({ error: msg });
243999
+ case "edit_file": {
244000
+ const input = tool.input;
244001
+ printToolUse("edit_file", input.path);
244002
+ const editResolved = path16.resolve(cwd, input.path);
244003
+ if (fs17.existsSync(editResolved) && !turnRollbackBuffer.has(editResolved)) {
244004
+ try {
244005
+ turnRollbackBuffer.set(editResolved, fs17.readFileSync(editResolved, "utf-8"));
244006
+ } catch {
244007
+ }
244008
+ }
244009
+ const diff = generateEditDiff(input);
244010
+ console.log(`${GRAY}${diff}${RESET}`);
244011
+ if (config.planMode || isDryRun()) {
244012
+ const tag = config.planMode ? "PLAN MODE" : "DRY-RUN";
244013
+ console.log(`${YELLOW} [${tag}] Would edit: ${input.path}${RESET}`);
244014
+ return JSON.stringify({ success: true, note: `${tag.toLowerCase()} \u2014 not executed` });
244015
+ }
244016
+ if (confirmWrite) {
244017
+ const ok = await confirm(`Edit ${input.path}?`);
244018
+ if (!ok) return JSON.stringify({ success: false, reason: "User declined" });
244019
+ }
244020
+ const result = editFileTool(input, cwd);
244021
+ printSuccess("Edit applied");
244022
+ return JSON.stringify(result);
244023
+ }
244024
+ case "glob": {
244025
+ const input = tool.input;
244026
+ printToolUse("glob", input.pattern);
244027
+ const results = globTool(input, cwd);
244028
+ const formatted = results.join("\n");
244029
+ printToolResult(formatted || "No matches found.");
244030
+ return truncateResult(JSON.stringify({ matches: results, count: results.length }));
244031
+ }
244032
+ case "read_image": {
244033
+ const input = tool.input;
244034
+ printToolUse("read_image", input.path);
244035
+ const result = readImageTool(input, cwd);
244036
+ printSuccess(`Read image: ${result.media_type}, ${(result.size / 1024).toFixed(1)}KB`);
244037
+ return JSON.stringify(result);
244038
+ }
244039
+ case "diff_files": {
244040
+ const input = tool.input;
244041
+ printToolUse("diff_files", `${input.file_a} \u2194 ${input.file_b}`);
244042
+ const result = diffFilesTool(input, cwd);
244043
+ const coloredLines = result.split("\n").map((line) => {
244044
+ if (line.startsWith("+")) return `${GREEN}${line}${RESET}`;
244045
+ if (line.startsWith("-")) return `${RED}${line}${RESET}`;
244046
+ if (line.startsWith("@")) return `${CYAN}${line}${RESET}`;
244047
+ return line;
244048
+ });
244049
+ printToolResult(coloredLines.join("\n"));
244050
+ return truncateResult(result);
244051
+ }
244052
+ default:
244053
+ return JSON.stringify({ error: `Unknown tool: ${tool.name}` });
243394
244054
  }
243395
244055
  }
243396
244056
  async function executeToolWithHooks(tool, cwd, config, hooks) {
@@ -243401,7 +244061,12 @@ async function executeToolWithHooks(tool, cwd, config, hooks) {
243401
244061
  const result = await executeTool(tool, cwd, config);
243402
244062
  runHooks("PostToolUse", hooks, tool.name, tool.input, cwd);
243403
244063
  const toolFilePath = tool.input["path"] ?? tool.input["file_path"] ?? null;
243404
- appendAuditLog(tool.name, toolFilePath);
244064
+ const command = tool.input["command"];
244065
+ const escalation = command ? detectCommandEscalation(command) : null;
244066
+ appendAuditLog(tool.name, toolFilePath, {
244067
+ command: command ?? void 0,
244068
+ escalation: escalation?.escalation
244069
+ });
243405
244070
  if ((tool.name === "write_file" || tool.name === "edit_file") && toolFilePath) {
243406
244071
  checkTypesAfterEdit(toolFilePath, cwd);
243407
244072
  }
@@ -243745,6 +244410,7 @@ ${mcpSummary}
243745
244410
  if (estimated > 5e4) {
243746
244411
  console.log(`${YELLOW} \u26A0 Context ~${Math.round(estimated / 1e3)}K tokens. Consider /compact to reduce.${RESET}`);
243747
244412
  }
244413
+ turnRollbackBuffer.clear();
243748
244414
  let continueLoop = true;
243749
244415
  let retryCount = 0;
243750
244416
  const maxRetries = 3;
@@ -243755,6 +244421,7 @@ ${mcpSummary}
243755
244421
  const MAX_DUPLICATE_STREAK = 3;
243756
244422
  const toolNameCounts = /* @__PURE__ */ new Map();
243757
244423
  const turnStartTime = Date.now();
244424
+ const userTurnStart = Date.now();
243758
244425
  const TURN_TIMEOUT_MS = 5 * 60 * 1e3;
243759
244426
  while (continueLoop) {
243760
244427
  if (Date.now() - turnStartTime > TURN_TIMEOUT_MS) {
@@ -243773,10 +244440,11 @@ ${mcpSummary}
243773
244440
  }
243774
244441
  const spinner = createSpinner("Thinking...");
243775
244442
  try {
244443
+ const modelDelay = getModelDelay(model);
243776
244444
  const now = Date.now();
243777
244445
  const elapsed = now - lastApiCallTime;
243778
- if (elapsed < MIN_API_DELAY_MS && lastApiCallTime > 0) {
243779
- await new Promise((r) => setTimeout(r, MIN_API_DELAY_MS - elapsed));
244446
+ if (elapsed < modelDelay && lastApiCallTime > 0) {
244447
+ await new Promise((r) => setTimeout(r, modelDelay - elapsed));
243780
244448
  }
243781
244449
  lastApiCallTime = Date.now();
243782
244450
  const abortCtrl = new AbortController();
@@ -243850,16 +244518,20 @@ ${headers.join("\n")}${RESET}
243850
244518
  }
243851
244519
  if (res.status === 429 && retryCount < maxRetries) {
243852
244520
  retryCount++;
243853
- const waitSec = retryCount * 3;
244521
+ const baseDelay = 3e3;
244522
+ const delay = Math.min(baseDelay * Math.pow(2, retryCount - 1) + Math.random() * 1e3, 3e4);
244523
+ const waitSec = (delay / 1e3).toFixed(1);
243854
244524
  console.log(`${YELLOW} Rate limited. Retrying in ${waitSec}s... (${retryCount}/${maxRetries})${RESET}`);
243855
- await new Promise((r) => setTimeout(r, waitSec * 1e3));
244525
+ await new Promise((r) => setTimeout(r, delay));
243856
244526
  continue;
243857
244527
  }
243858
244528
  if (res.status >= 500 && retryCount < maxRetries) {
243859
244529
  retryCount++;
243860
- const waitSec = retryCount * 2;
244530
+ const baseDelay = 2e3;
244531
+ const delay = Math.min(baseDelay * Math.pow(2, retryCount - 1) + Math.random() * 1e3, 3e4);
244532
+ const waitSec = (delay / 1e3).toFixed(1);
243861
244533
  console.log(`${YELLOW} Server error (${res.status}). Retrying in ${waitSec}s... (${retryCount}/${maxRetries})${RESET}`);
243862
- await new Promise((r) => setTimeout(r, waitSec * 1e3));
244534
+ await new Promise((r) => setTimeout(r, delay));
243863
244535
  continue;
243864
244536
  }
243865
244537
  printError(errMsg);
@@ -243870,14 +244542,23 @@ ${headers.join("\n")}${RESET}
243870
244542
  retryCount = 0;
243871
244543
  if (isSSEResponse(res)) {
243872
244544
  let firstText = true;
244545
+ let runningTokens = { input_tokens: 0, output_tokens: 0 };
244546
+ const onTokenUpdate = (tokens) => {
244547
+ runningTokens = tokens;
244548
+ };
243873
244549
  const streamResult = await parseSSEStream(res, (text) => {
243874
244550
  if (firstText) {
243875
244551
  console.log();
243876
244552
  firstText = false;
243877
244553
  }
243878
244554
  process.stdout.write(text);
243879
- });
244555
+ }, onTokenUpdate);
243880
244556
  if (!firstText) {
244557
+ if (runningTokens.input_tokens > 0 || runningTokens.output_tokens > 0) {
244558
+ const total = runningTokens.input_tokens + runningTokens.output_tokens;
244559
+ process.stdout.write(`
244560
+ ${DIM} [tokens: ${total.toLocaleString()}]${RESET}`);
244561
+ }
243881
244562
  console.log();
243882
244563
  }
243883
244564
  sessionStats = updateStats(
@@ -243890,6 +244571,11 @@ ${headers.join("\n")}${RESET}
243890
244571
  const turnCost = estimateCost({ ...sessionStats, inputTokens: u.input_tokens, outputTokens: u.output_tokens, requests: 1, providerCounts: {} });
243891
244572
  console.log(`${DIM} tokens: ${u.input_tokens} in + ${u.output_tokens} out = ${u.input_tokens + u.output_tokens} \xB7 ~$${turnCost.toFixed(4)}${RESET}`);
243892
244573
  }
244574
+ if (config.maxCostPerSession && config.maxCostPerSession > 0) {
244575
+ if (isBudgetExceeded(sessionStats, config.maxCostPerSession)) {
244576
+ printBudgetWarning(sessionStats, config.maxCostPerSession);
244577
+ }
244578
+ }
243893
244579
  const contentBlocksForHistory = [];
243894
244580
  const toolBlocks = [];
243895
244581
  for (const block of streamResult.contentBlocks) {
@@ -243936,6 +244622,9 @@ ${headers.join("\n")}${RESET}
243936
244622
  const toolResults = await executeToolsParallel(toolBlocks, cwd, config, hooks);
243937
244623
  messages.push({ role: "user", content: toolResults });
243938
244624
  } else {
244625
+ if (Date.now() - userTurnStart > 1e4) {
244626
+ process.stdout.write("\x07");
244627
+ }
243939
244628
  const meta = streamResult.routingMetadata;
243940
244629
  if (meta && streamResult.usage) {
243941
244630
  console.log(`${DIM} - ${meta.provider} \xB7 L${meta.taskComplexity} \xB7 ${meta.totalLatencyMs?.toFixed(0) ?? "?"}ms \xB7 ${streamResult.usage.input_tokens}+${streamResult.usage.output_tokens} tokens${RESET}`);
@@ -244104,7 +244793,7 @@ var GRAY4 = "\x1B[90m";
244104
244793
  var BOLD2 = "\x1B[1m";
244105
244794
  var DIM2 = "\x1B[2m";
244106
244795
  var RESET2 = "\x1B[0m";
244107
- var YELLOW3 = "\x1B[33m";
244796
+ var YELLOW2 = "\x1B[33m";
244108
244797
  var WHITE2 = "\x1B[37m";
244109
244798
  var VERSION = "0.2.0";
244110
244799
  var CONFIG_DIR = path18.join(os9.homedir(), ".oroute");
@@ -244174,6 +244863,21 @@ var LOGO = `${GREEN2}${BOLD2}
244174
244863
  | |_| | | _ < (_) | |_| | || __/
244175
244864
  \\___/ |_| \\_\\___/ \\__,_|\\__\\___|${RESET2}
244176
244865
  `;
244866
+ function checkApiKeyAge(config) {
244867
+ if (!config.apiKeyCreatedAt) return;
244868
+ try {
244869
+ const createdAt = new Date(config.apiKeyCreatedAt);
244870
+ const now = /* @__PURE__ */ new Date();
244871
+ const ageMs = now.getTime() - createdAt.getTime();
244872
+ const ageDays = Math.floor(ageMs / (1e3 * 60 * 60 * 24));
244873
+ if (ageDays > 90) {
244874
+ console.log(`${YELLOW2} WARNING: Your API key is ${ageDays} days old. Consider rotating it for security.${RESET2}`);
244875
+ console.log(`${GRAY4} Rotate at: https://oroute.itshin.com/api-keys${RESET2}`);
244876
+ console.log();
244877
+ }
244878
+ } catch {
244879
+ }
244880
+ }
244177
244881
  function loadConfig() {
244178
244882
  try {
244179
244883
  if (fs19.existsSync(CONFIG_FILE)) {
@@ -244183,6 +244887,22 @@ function loadConfig() {
244183
244887
  }
244184
244888
  return {};
244185
244889
  }
244890
+ function loadProjectConfig() {
244891
+ try {
244892
+ const projectConfigPath = path18.join(process.cwd(), ".oroute", "config.json");
244893
+ if (fs19.existsSync(projectConfigPath)) {
244894
+ const raw = JSON.parse(fs19.readFileSync(projectConfigPath, "utf-8"));
244895
+ const result = {};
244896
+ if (raw.model) result.model = raw.model;
244897
+ if (raw.apiUrl) result.apiUrl = raw.apiUrl;
244898
+ if (raw.maxCost !== void 0) result.maxCost = Number(raw.maxCost);
244899
+ if (Array.isArray(raw.toolBlacklist)) result.toolBlacklist = raw.toolBlacklist;
244900
+ return result;
244901
+ }
244902
+ } catch {
244903
+ }
244904
+ return {};
244905
+ }
244186
244906
  function saveConfig(config) {
244187
244907
  if (!fs19.existsSync(CONFIG_DIR)) {
244188
244908
  fs19.mkdirSync(CONFIG_DIR, { recursive: true });
@@ -244216,8 +244936,9 @@ function parseArgs(args) {
244216
244936
  let targetPath;
244217
244937
  let prompt;
244218
244938
  let debug = false;
244219
- let skipConfirmations = false;
244939
+ let skipConfirmations2 = false;
244220
244940
  let planMode = false;
244941
+ let profile = false;
244221
244942
  for (let i = 0; i < args.length; i++) {
244222
244943
  const arg = args[i];
244223
244944
  if (arg === "--debug") {
@@ -244225,13 +244946,17 @@ function parseArgs(args) {
244225
244946
  continue;
244226
244947
  }
244227
244948
  if (arg === "--yes" || arg === "-y") {
244228
- skipConfirmations = true;
244949
+ skipConfirmations2 = true;
244229
244950
  continue;
244230
244951
  }
244231
244952
  if (arg === "--plan") {
244232
244953
  planMode = true;
244233
244954
  continue;
244234
244955
  }
244956
+ if (arg === "--profile") {
244957
+ profile = true;
244958
+ continue;
244959
+ }
244235
244960
  if (arg === "-p" && args[i + 1]) {
244236
244961
  prompt = args[++i];
244237
244962
  continue;
@@ -244243,7 +244968,7 @@ function parseArgs(args) {
244243
244968
  if (arg.startsWith("-")) continue;
244244
244969
  targetPath = arg;
244245
244970
  }
244246
- return { command, path: targetPath, prompt, debug, skipConfirmations, planMode };
244971
+ return { command, path: targetPath, prompt, debug, skipConfirmations: skipConfirmations2, planMode, profile };
244247
244972
  }
244248
244973
  async function promptInput(prompt) {
244249
244974
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
@@ -244257,7 +244982,7 @@ async function promptInput(prompt) {
244257
244982
  async function loginWithApiKey(config) {
244258
244983
  const key = await promptInput(`${GREEN2}\u203A${RESET2} Enter your O'Route API Key (or-...): `);
244259
244984
  if (!key.startsWith("or-")) {
244260
- console.log(`${YELLOW3} Invalid key format. O'Route keys start with "or-"${RESET2}`);
244985
+ console.log(`${YELLOW2} Invalid key format. O'Route keys start with "or-"${RESET2}`);
244261
244986
  return;
244262
244987
  }
244263
244988
  const apiUrl = config.apiUrl ?? DEFAULT_API_URL;
@@ -244268,19 +244993,21 @@ async function loginWithApiKey(config) {
244268
244993
  signal: AbortSignal.timeout(5e3)
244269
244994
  });
244270
244995
  config.apiKey = key;
244996
+ config.apiKeyCreatedAt = (/* @__PURE__ */ new Date()).toISOString();
244271
244997
  saveConfig(config);
244272
244998
  if (res.ok) {
244273
244999
  console.log(`${GREEN2} \u2713 API Key verified and saved!${RESET2}`);
244274
245000
  } else {
244275
- console.log(`${YELLOW3} Key saved (server returned ${res.status}).${RESET2}`);
245001
+ console.log(`${YELLOW2} Key saved (server returned ${res.status}).${RESET2}`);
244276
245002
  }
244277
245003
  console.log();
244278
245004
  await chat(config);
244279
245005
  return;
244280
245006
  } catch {
244281
245007
  config.apiKey = key;
245008
+ config.apiKeyCreatedAt = (/* @__PURE__ */ new Date()).toISOString();
244282
245009
  saveConfig(config);
244283
- console.log(`${YELLOW3} Saved (server offline). Starting chat...${RESET2}`);
245010
+ console.log(`${YELLOW2} Saved (server offline). Starting chat...${RESET2}`);
244284
245011
  console.log();
244285
245012
  await chat(config);
244286
245013
  }
@@ -244314,6 +245041,7 @@ async function loginWithGoogle(config) {
244314
245041
  const pollData = await pollRes.json();
244315
245042
  if (pollData.status === "approved" && pollData.apiKey) {
244316
245043
  config.apiKey = pollData.apiKey;
245044
+ config.apiKeyCreatedAt = (/* @__PURE__ */ new Date()).toISOString();
244317
245045
  saveConfig(config);
244318
245046
  console.log(`
244319
245047
  ${GREEN2} \u2713 Logged in!${RESET2} ${GRAY4}(${pollData.email})${RESET2}`);
@@ -244323,20 +245051,20 @@ ${GREEN2} \u2713 Logged in!${RESET2} ${GRAY4}(${pollData.email})${RESET2}`);
244323
245051
  return;
244324
245052
  }
244325
245053
  if (pollData.status === "expired") {
244326
- console.log(`${YELLOW3} \uC778\uC99D \uCF54\uB4DC\uAC00 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.${RESET2}`);
245054
+ console.log(`${YELLOW2} \uC778\uC99D \uCF54\uB4DC\uAC00 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.${RESET2}`);
244327
245055
  return;
244328
245056
  }
244329
245057
  process.stdout.write(`\r${GRAY4} \uB300\uAE30 \uC911${"\xB7".repeat(i % 3 + 1).padEnd(3)}${RESET2}`);
244330
245058
  }
244331
245059
  console.log(`
244332
- ${YELLOW3} \uC2DC\uAC04 \uCD08\uACFC. \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.${RESET2}`);
245060
+ ${YELLOW2} \uC2DC\uAC04 \uCD08\uACFC. \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.${RESET2}`);
244333
245061
  } catch (err) {
244334
- console.log(`${YELLOW3} \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. API Key\uB85C \uB85C\uADF8\uC778\uD558\uC138\uC694 (\uC635\uC158 1).${RESET2}`);
245062
+ console.log(`${YELLOW2} \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. API Key\uB85C \uB85C\uADF8\uC778\uD558\uC138\uC694 (\uC635\uC158 1).${RESET2}`);
244335
245063
  }
244336
245064
  }
244337
245065
  async function chat(config) {
244338
245066
  if (!config.apiKey) {
244339
- console.log(`${YELLOW3} No API Key configured. Run option 1 first.${RESET2}`);
245067
+ console.log(`${YELLOW2} No API Key configured. Run option 1 first.${RESET2}`);
244340
245068
  return;
244341
245069
  }
244342
245070
  const apiUrl = config.apiUrl ?? DEFAULT_API_URL;
@@ -244368,7 +245096,7 @@ async function chat(config) {
244368
245096
  if (!res.ok) {
244369
245097
  const errBody = await res.json().catch(() => ({ error: { message: `HTTP ${res.status}` } }));
244370
245098
  const errMsg = typeof errBody.error === "string" ? errBody.error : errBody.error?.message ?? `HTTP ${res.status}`;
244371
- console.log(`${YELLOW3} Error: ${errMsg}${RESET2}`);
245099
+ console.log(`${YELLOW2} Error: ${errMsg}${RESET2}`);
244372
245100
  messages.pop();
244373
245101
  continue;
244374
245102
  }
@@ -244382,7 +245110,7 @@ async function chat(config) {
244382
245110
  console.log();
244383
245111
  messages.push({ role: "assistant", content: text });
244384
245112
  } catch (err) {
244385
- console.log(`${YELLOW3} Request failed: ${err instanceof Error ? err.message : "unknown"}${RESET2}`);
245113
+ console.log(`${YELLOW2} Request failed: ${err instanceof Error ? err.message : "unknown"}${RESET2}`);
244386
245114
  messages.pop();
244387
245115
  }
244388
245116
  }
@@ -244398,7 +245126,7 @@ async function checkStatus(config) {
244398
245126
  console.log(`${GRAY4} Key: ${config.apiKey ? config.apiKey.slice(0, 11) + "..." : "not set"}${RESET2}`);
244399
245127
  console.log(`${GRAY4} Model: ${config.model ?? "auto"}${RESET2}`);
244400
245128
  } catch {
244401
- console.log(`${YELLOW3} \u2717 Server unreachable at ${apiUrl}${RESET2}`);
245129
+ console.log(`${YELLOW2} \u2717 Server unreachable at ${apiUrl}${RESET2}`);
244402
245130
  }
244403
245131
  }
244404
245132
  async function settings(config) {
@@ -244433,32 +245161,52 @@ async function settings(config) {
244433
245161
  }
244434
245162
  }
244435
245163
  async function main() {
245164
+ const startupStart = performance.now();
244436
245165
  const rawArgs = process.argv.slice(2);
245166
+ const parseStart = performance.now();
244437
245167
  const config = loadConfig();
244438
245168
  const parsed = parseArgs(rawArgs);
245169
+ const configLoadMs = performance.now() - parseStart;
245170
+ checkApiKeyAge(config);
245171
+ const updateStart = performance.now();
244439
245172
  checkForUpdates(VERSION);
245173
+ const updateMs = performance.now() - updateStart;
244440
245174
  if (parsed.debug) {
244441
245175
  console.log(`${GRAY4} Debug mode: config=${JSON.stringify(config)}${RESET2}`);
244442
245176
  }
244443
245177
  if (parsed.path) {
244444
245178
  const resolved = path18.resolve(process.cwd(), parsed.path);
244445
245179
  if (!fs19.existsSync(resolved)) {
244446
- console.log(`${YELLOW3} \uB514\uB809\uD1A0\uB9AC\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${resolved}${RESET2}`);
245180
+ console.log(`${YELLOW2} \uB514\uB809\uD1A0\uB9AC\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${resolved}${RESET2}`);
244447
245181
  process.exit(1);
244448
245182
  }
244449
245183
  const stat = fs19.statSync(resolved);
244450
245184
  if (!stat.isDirectory()) {
244451
- console.log(`${YELLOW3} \uB514\uB809\uD1A0\uB9AC\uAC00 \uC544\uB2D9\uB2C8\uB2E4: ${resolved}${RESET2}`);
245185
+ console.log(`${YELLOW2} \uB514\uB809\uD1A0\uB9AC\uAC00 \uC544\uB2D9\uB2C8\uB2E4: ${resolved}${RESET2}`);
244452
245186
  process.exit(1);
244453
245187
  }
244454
245188
  process.chdir(resolved);
244455
245189
  }
245190
+ const projectConfig = loadProjectConfig();
245191
+ const mergedConfig = { ...config, ...projectConfig };
244456
245192
  const agentConfig = {
244457
- ...config,
245193
+ ...mergedConfig,
244458
245194
  skipConfirmations: parsed.skipConfirmations,
244459
245195
  planMode: parsed.planMode,
244460
- debug: parsed.debug
245196
+ debug: parsed.debug,
245197
+ maxCostPerSession: mergedConfig.maxCost,
245198
+ toolBlacklist: mergedConfig.toolBlacklist
244461
245199
  };
245200
+ if (parsed.profile) {
245201
+ const totalMs = performance.now() - startupStart;
245202
+ console.log(`${BOLD2} Startup Profile${RESET2}`);
245203
+ console.log(`${GRAY4} ${"\u2500".repeat(40)}${RESET2}`);
245204
+ console.log(`${WHITE2} Config load: ${configLoadMs.toFixed(1)}ms${RESET2}`);
245205
+ console.log(`${WHITE2} Update check: ${updateMs.toFixed(1)}ms${RESET2}`);
245206
+ console.log(`${WHITE2} Total startup: ${totalMs.toFixed(1)}ms${RESET2}`);
245207
+ console.log(`${GRAY4} (context, MCP, history are loaded in agent loop)${RESET2}`);
245208
+ console.log();
245209
+ }
244462
245210
  if (parsed.command === "login") {
244463
245211
  printWelcome();
244464
245212
  await loginWithApiKey(config);
@@ -244474,7 +245222,7 @@ async function main() {
244474
245222
  }
244475
245223
  if (parsed.prompt) {
244476
245224
  if (!config.apiKey) {
244477
- console.log(`${YELLOW3}No API Key. Run: oroute login${RESET2}`);
245225
+ console.log(`${YELLOW2}No API Key. Run: oroute login${RESET2}`);
244478
245226
  process.exit(1);
244479
245227
  }
244480
245228
  const apiUrl = config.apiUrl ?? DEFAULT_API_URL;
@@ -244489,7 +245237,7 @@ async function main() {
244489
245237
  console.log(data.content[0]?.text ?? "");
244490
245238
  } catch (err) {
244491
245239
  const msg = err instanceof Error ? err.message : String(err);
244492
- console.log(`${YELLOW3} Error: ${msg}${RESET2}`);
245240
+ console.log(`${YELLOW2} Error: ${msg}${RESET2}`);
244493
245241
  }
244494
245242
  return;
244495
245243
  }
@@ -244523,14 +245271,14 @@ async function main() {
244523
245271
  console.log(`${GRAY4} Bye!${RESET2}`);
244524
245272
  process.exit(0);
244525
245273
  default:
244526
- console.log(`${YELLOW3} Unknown option: ${choice}${RESET2}`);
245274
+ console.log(`${YELLOW2} Unknown option: ${choice}${RESET2}`);
244527
245275
  }
244528
245276
  console.log();
244529
245277
  }
244530
245278
  }
244531
245279
  main().catch((err) => {
244532
245280
  const msg = err instanceof Error ? err.message : String(err);
244533
- console.error(`${YELLOW3} Error: ${msg}${RESET2}`);
245281
+ console.error(`${YELLOW2} Error: ${msg}${RESET2}`);
244534
245282
  process.exit(1);
244535
245283
  });
244536
245284
  //# sourceMappingURL=oroute.cjs.map