@pensar/apex 0.0.80 → 0.0.81-canary.5a90bb41

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/build/index.js +1469 -830
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -31956,7 +31956,7 @@ var package_default2;
31956
31956
  var init_package = __esm(() => {
31957
31957
  package_default2 = {
31958
31958
  name: "@pensar/apex",
31959
- version: "0.0.80",
31959
+ version: "0.0.81-canary.5a90bb41",
31960
31960
  description: "AI-powered penetration testing CLI tool with terminal UI",
31961
31961
  module: "src/tui/index.tsx",
31962
31962
  main: "build/index.js",
@@ -36137,6 +36137,279 @@ var init_zod = __esm(() => {
36137
36137
  zod_default = exports_external;
36138
36138
  });
36139
36139
 
36140
+ // src/util/errors.ts
36141
+ var NamedError;
36142
+ var init_errors2 = __esm(() => {
36143
+ init_zod();
36144
+ NamedError = class NamedError extends Error {
36145
+ static create(name, data) {
36146
+ const schema2 = zod_default.object({
36147
+ name: zod_default.literal(name),
36148
+ data
36149
+ });
36150
+ const result = class extends NamedError {
36151
+ data;
36152
+ static Schema = schema2;
36153
+ name = name;
36154
+ constructor(data2, options) {
36155
+ super(name, options);
36156
+ this.data = data2;
36157
+ this.name = name;
36158
+ }
36159
+ static isInstance(input) {
36160
+ return typeof input === "object" && input !== null && "name" in input && input.name === name;
36161
+ }
36162
+ schema() {
36163
+ return schema2;
36164
+ }
36165
+ toObject() {
36166
+ return {
36167
+ name,
36168
+ data: this.data
36169
+ };
36170
+ }
36171
+ };
36172
+ Object.defineProperty(result, "name", { value: name });
36173
+ return result;
36174
+ }
36175
+ static Unknown = NamedError.create("UnknownError", zod_default.object({
36176
+ message: zod_default.string()
36177
+ }));
36178
+ };
36179
+ });
36180
+
36181
+ // src/util/lock.ts
36182
+ function getLock(key) {
36183
+ if (!locks.has(key)) {
36184
+ locks.set(key, {
36185
+ readers: 0,
36186
+ writer: false,
36187
+ waitingReaders: [],
36188
+ waitingWriters: []
36189
+ });
36190
+ }
36191
+ return locks.get(key);
36192
+ }
36193
+ function processQueue(key) {
36194
+ const lock = locks.get(key);
36195
+ if (!lock || lock.writer || lock.readers > 0)
36196
+ return;
36197
+ if (lock.waitingWriters.length > 0) {
36198
+ const nextWriter = lock.waitingWriters.shift();
36199
+ nextWriter();
36200
+ return;
36201
+ }
36202
+ while (lock.waitingReaders.length > 0) {
36203
+ const nextReader = lock.waitingReaders.shift();
36204
+ nextReader();
36205
+ }
36206
+ if (lock.readers === 0 && !lock.writer && lock.waitingReaders.length === 0 && lock.waitingWriters.length === 0) {
36207
+ locks.delete(key);
36208
+ }
36209
+ }
36210
+ async function read(key) {
36211
+ const lock = getLock(key);
36212
+ return new Promise((resolve3) => {
36213
+ if (!lock.writer && lock.waitingWriters.length === 0) {
36214
+ lock.readers++;
36215
+ resolve3({
36216
+ [Symbol.dispose]: () => {
36217
+ lock.readers--;
36218
+ processQueue(key);
36219
+ }
36220
+ });
36221
+ } else {
36222
+ lock.waitingReaders.push(() => {
36223
+ lock.readers++;
36224
+ resolve3({
36225
+ [Symbol.dispose]: () => {
36226
+ lock.readers--;
36227
+ processQueue(key);
36228
+ }
36229
+ });
36230
+ });
36231
+ }
36232
+ });
36233
+ }
36234
+ async function write(key) {
36235
+ const lock = getLock(key);
36236
+ return new Promise((resolve3) => {
36237
+ if (!lock.writer && lock.readers === 0) {
36238
+ lock.writer = true;
36239
+ resolve3({
36240
+ [Symbol.dispose]: () => {
36241
+ lock.writer = false;
36242
+ processQueue(key);
36243
+ }
36244
+ });
36245
+ } else {
36246
+ lock.waitingWriters.push(() => {
36247
+ lock.writer = true;
36248
+ resolve3({
36249
+ [Symbol.dispose]: () => {
36250
+ lock.writer = false;
36251
+ processQueue(key);
36252
+ }
36253
+ });
36254
+ });
36255
+ }
36256
+ });
36257
+ }
36258
+ var locks;
36259
+ var init_lock = __esm(() => {
36260
+ locks = new Map;
36261
+ });
36262
+
36263
+ // src/core/storage/index.ts
36264
+ import os3 from "os";
36265
+ import path3 from "path";
36266
+ import fs3 from "fs/promises";
36267
+ import { readdir } from "fs/promises";
36268
+ function getBaseDir() {
36269
+ return process.env.PENSAR_DATA_DIR ?? path3.join(os3.homedir(), ".pensar");
36270
+ }
36271
+ async function remove(key) {
36272
+ const dir = getBaseDir();
36273
+ const target = path3.join(dir, ...key) + ".json";
36274
+ return withErrorHandling(async () => {
36275
+ await fs3.unlink(target).catch(() => {});
36276
+ });
36277
+ }
36278
+ async function write2(key, content, ext) {
36279
+ const dir = getBaseDir();
36280
+ const target = path3.join(dir, ...key) + (ext ? ext : ".json");
36281
+ return withErrorHandling(async () => {
36282
+ let __stack = [];
36283
+ try {
36284
+ const _2 = __using(__stack, await write(target), 0);
36285
+ await fs3.mkdir(path3.dirname(target), { recursive: true });
36286
+ await fs3.writeFile(target, JSON.stringify(content, null, 2), "utf-8");
36287
+ } catch (_catch) {
36288
+ var _err = _catch, _hasErr = 1;
36289
+ } finally {
36290
+ __callDispose(__stack, _err, _hasErr);
36291
+ }
36292
+ });
36293
+ }
36294
+ async function createDir(key) {
36295
+ const dir = getBaseDir();
36296
+ const target = path3.join(dir, ...key);
36297
+ return withErrorHandling(async () => {
36298
+ let __stack = [];
36299
+ try {
36300
+ const _2 = __using(__stack, await write(target), 0);
36301
+ await fs3.mkdir(target, { recursive: true });
36302
+ } catch (_catch) {
36303
+ var _err = _catch, _hasErr = 1;
36304
+ } finally {
36305
+ __callDispose(__stack, _err, _hasErr);
36306
+ }
36307
+ });
36308
+ }
36309
+ async function writeRaw(key, content) {
36310
+ const dir = getBaseDir();
36311
+ const target = path3.join(dir, ...key);
36312
+ return withErrorHandling(async () => {
36313
+ let __stack = [];
36314
+ try {
36315
+ const _2 = __using(__stack, await write(target), 0);
36316
+ const parentDir = path3.dirname(target);
36317
+ await fs3.mkdir(parentDir, { recursive: true });
36318
+ await fs3.writeFile(target, content, "utf-8");
36319
+ } catch (_catch) {
36320
+ var _err = _catch, _hasErr = 1;
36321
+ } finally {
36322
+ __callDispose(__stack, _err, _hasErr);
36323
+ }
36324
+ });
36325
+ }
36326
+ async function read2(key, ext) {
36327
+ const dir = getBaseDir();
36328
+ const target = path3.join(dir, ...key) + (ext ? ext : ".json");
36329
+ return withErrorHandling(async () => {
36330
+ let __stack = [];
36331
+ try {
36332
+ const _2 = __using(__stack, await read(target), 0);
36333
+ const text = await fs3.readFile(target, "utf-8");
36334
+ const result = ext ? text : JSON.parse(text);
36335
+ return result;
36336
+ } catch (_catch) {
36337
+ var _err = _catch, _hasErr = 1;
36338
+ } finally {
36339
+ __callDispose(__stack, _err, _hasErr);
36340
+ }
36341
+ });
36342
+ }
36343
+ async function update2(key, fn, ext) {
36344
+ const dir = getBaseDir();
36345
+ const target = path3.join(dir, ...key) + (ext ? ext : ".json");
36346
+ return withErrorHandling(async () => {
36347
+ let __stack = [];
36348
+ try {
36349
+ const _2 = __using(__stack, await write(target), 0);
36350
+ const text = await fs3.readFile(target, "utf-8");
36351
+ const content = ext ? text : JSON.parse(text);
36352
+ fn(content);
36353
+ await fs3.writeFile(target, JSON.stringify(content, null, 2), "utf-8");
36354
+ return content;
36355
+ } catch (_catch) {
36356
+ var _err = _catch, _hasErr = 1;
36357
+ } finally {
36358
+ __callDispose(__stack, _err, _hasErr);
36359
+ }
36360
+ });
36361
+ }
36362
+ async function withErrorHandling(body) {
36363
+ return body().catch((e) => {
36364
+ if (!(e instanceof Error))
36365
+ throw e;
36366
+ const errnoExcpetion = e;
36367
+ if (errnoExcpetion.code === "ENOENT") {
36368
+ throw new NotFoundError({
36369
+ message: `Resource not found: ${errnoExcpetion.path}`
36370
+ });
36371
+ }
36372
+ throw e;
36373
+ });
36374
+ }
36375
+ async function listFilesRecursively(dir) {
36376
+ const entries = await readdir(dir, { withFileTypes: true });
36377
+ const files = [];
36378
+ for (const entry of entries) {
36379
+ const fullPath = path3.join(dir, entry.name);
36380
+ if (entry.isDirectory()) {
36381
+ files.push(...await listFilesRecursively(fullPath));
36382
+ } else {
36383
+ files.push(fullPath);
36384
+ }
36385
+ }
36386
+ return files;
36387
+ }
36388
+ async function list(prefix) {
36389
+ const dir = getBaseDir();
36390
+ const targetDir = path3.join(dir, ...prefix);
36391
+ try {
36392
+ const files = await listFilesRecursively(targetDir);
36393
+ const result = files.map((filePath) => {
36394
+ const relativePath = path3.relative(targetDir, filePath);
36395
+ return [...prefix, ...relativePath.slice(0, -5).split(path3.sep)];
36396
+ });
36397
+ result.sort();
36398
+ return result;
36399
+ } catch {
36400
+ return [];
36401
+ }
36402
+ }
36403
+ var NotFoundError;
36404
+ var init_storage = __esm(() => {
36405
+ init_zod();
36406
+ init_errors2();
36407
+ init_lock();
36408
+ NotFoundError = NamedError.create("NotFoundError", zod_default.object({
36409
+ message: zod_default.string()
36410
+ }));
36411
+ });
36412
+
36140
36413
  // src/core/credentials/manager.ts
36141
36414
  import { randomBytes as randomBytes2 } from "crypto";
36142
36415
  function generateCredentialId() {
@@ -36615,6 +36888,30 @@ var init_toolset = __esm(() => {
36615
36888
  detail: "Validate that testing is complete by checking coverage against the original scope and identifying any gaps.",
36616
36889
  category: "utility",
36617
36890
  defaultEnabled: true
36891
+ },
36892
+ {
36893
+ id: "add_memory",
36894
+ name: "Add Memory",
36895
+ description: "Save to memory",
36896
+ detail: "Save a piece of knowledge to persistent memory. Memories survive across sessions and can store reusable techniques, target notes, credential patterns, useful payloads, or any information worth remembering.",
36897
+ category: "utility",
36898
+ defaultEnabled: true
36899
+ },
36900
+ {
36901
+ id: "list_memories",
36902
+ name: "List Memories",
36903
+ description: "Browse saved memories",
36904
+ detail: "List all saved memories with optional tag filtering. Returns summaries sorted by most recent first. Use the returned id with Get Memory to retrieve full content.",
36905
+ category: "utility",
36906
+ defaultEnabled: true
36907
+ },
36908
+ {
36909
+ id: "get_memory",
36910
+ name: "Get Memory",
36911
+ description: "Retrieve a memory",
36912
+ detail: "Retrieve the full content of a saved memory by its id. Use List Memories first to discover available memory ids.",
36913
+ category: "utility",
36914
+ defaultEnabled: true
36618
36915
  }
36619
36916
  ];
36620
36917
  TOOLSETS = [
@@ -37017,9 +37314,9 @@ function saveSubagentData(session, data) {
37017
37314
  const filename = `${data.agentName}-${ts}.json`;
37018
37315
  writeFileSync2(join4(subagentsDir, filename), JSON.stringify(savedData, null, 2));
37019
37316
  }
37020
- function writeAgentManifest(session, entries) {
37317
+ function writeAgentManifest(session, entries2) {
37021
37318
  const manifestPath = join4(session.rootPath, MANIFEST_FILE);
37022
- writeFileSync2(manifestPath, JSON.stringify(entries, null, 2));
37319
+ writeFileSync2(manifestPath, JSON.stringify(entries2, null, 2));
37023
37320
  }
37024
37321
  function buildManifestEntries(targets) {
37025
37322
  return targets.map((t2, i) => ({
@@ -37032,8 +37329,8 @@ function buildManifestEntries(targets) {
37032
37329
  spawnedAt: new Date().toISOString()
37033
37330
  }));
37034
37331
  }
37035
- function finalizeManifest(session, entries, results) {
37036
- const finalManifest = entries.map((entry, i) => ({
37332
+ function finalizeManifest(session, entries2, results) {
37333
+ const finalManifest = entries2.map((entry, i) => ({
37037
37334
  ...entry,
37038
37335
  status: results[i] != null ? "completed" : "failed",
37039
37336
  completedAt: new Date().toISOString()
@@ -37612,9 +37909,9 @@ function assertNever(_x) {
37612
37909
  throw new Error;
37613
37910
  }
37614
37911
  function assert(_2) {}
37615
- function getEnumValues(entries) {
37616
- const numericValues = Object.values(entries).filter((v2) => typeof v2 === "number");
37617
- const values = Object.entries(entries).filter(([k2, _2]) => numericValues.indexOf(+k2) === -1).map(([_2, v2]) => v2);
37912
+ function getEnumValues(entries2) {
37913
+ const numericValues = Object.values(entries2).filter((v2) => typeof v2 === "number");
37914
+ const values = Object.entries(entries2).filter(([k2, _2]) => numericValues.indexOf(+k2) === -1).map(([_2, v2]) => v2);
37618
37915
  return values;
37619
37916
  }
37620
37917
  function joinValues(array, separator = "|") {
@@ -38208,7 +38505,7 @@ var initializer = (inst, def) => {
38208
38505
  enumerable: false
38209
38506
  });
38210
38507
  }, $ZodError, $ZodRealError;
38211
- var init_errors2 = __esm(() => {
38508
+ var init_errors3 = __esm(() => {
38212
38509
  init_core();
38213
38510
  init_util2();
38214
38511
  $ZodError = $constructor("$ZodError", initializer);
@@ -38261,7 +38558,7 @@ var _parse = (_Err) => (schema2, value, _ctx, _params) => {
38261
38558
  }, safeParseAsync;
38262
38559
  var init_parse = __esm(() => {
38263
38560
  init_core();
38264
- init_errors2();
38561
+ init_errors3();
38265
38562
  init_util2();
38266
38563
  parse2 = /* @__PURE__ */ _parse($ZodRealError);
38267
38564
  parseAsync = /* @__PURE__ */ _parseAsync($ZodRealError);
@@ -46216,17 +46513,17 @@ function _set(Class2, valueType, params) {
46216
46513
  });
46217
46514
  }
46218
46515
  function _enum(Class2, values, params) {
46219
- const entries = Array.isArray(values) ? Object.fromEntries(values.map((v2) => [v2, v2])) : values;
46516
+ const entries2 = Array.isArray(values) ? Object.fromEntries(values.map((v2) => [v2, v2])) : values;
46220
46517
  return new Class2({
46221
46518
  type: "enum",
46222
- entries,
46519
+ entries: entries2,
46223
46520
  ...normalizeParams(params)
46224
46521
  });
46225
46522
  }
46226
- function _nativeEnum(Class2, entries, params) {
46523
+ function _nativeEnum(Class2, entries2, params) {
46227
46524
  return new Class2({
46228
46525
  type: "enum",
46229
- entries,
46526
+ entries: entries2,
46230
46527
  ...normalizeParams(params)
46231
46528
  });
46232
46529
  }
@@ -47513,7 +47810,7 @@ var init_core2 = __esm(() => {
47513
47810
  init_json_schema();
47514
47811
  init_core();
47515
47812
  init_parse();
47516
- init_errors2();
47813
+ init_errors3();
47517
47814
  init_schemas2();
47518
47815
  init_checks();
47519
47816
  init_versions();
@@ -47598,7 +47895,7 @@ var initializer2 = (inst, issues) => {
47598
47895
  }
47599
47896
  });
47600
47897
  }, ZodError3, ZodRealError;
47601
- var init_errors3 = __esm(() => {
47898
+ var init_errors4 = __esm(() => {
47602
47899
  init_core2();
47603
47900
  init_core2();
47604
47901
  ZodError3 = $constructor("ZodError", initializer2);
@@ -47611,7 +47908,7 @@ var init_errors3 = __esm(() => {
47611
47908
  var parse4, parseAsync2, safeParse2, safeParseAsync2;
47612
47909
  var init_parse2 = __esm(() => {
47613
47910
  init_core2();
47614
- init_errors3();
47911
+ init_errors4();
47615
47912
  parse4 = /* @__PURE__ */ _parse(ZodRealError);
47616
47913
  parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
47617
47914
  safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
@@ -47850,17 +48147,17 @@ function set(valueType, params) {
47850
48147
  });
47851
48148
  }
47852
48149
  function _enum2(values, params) {
47853
- const entries = Array.isArray(values) ? Object.fromEntries(values.map((v2) => [v2, v2])) : values;
48150
+ const entries2 = Array.isArray(values) ? Object.fromEntries(values.map((v2) => [v2, v2])) : values;
47854
48151
  return new ZodEnum2({
47855
48152
  type: "enum",
47856
- entries,
48153
+ entries: entries2,
47857
48154
  ...exports_util.normalizeParams(params)
47858
48155
  });
47859
48156
  }
47860
- function nativeEnum(entries, params) {
48157
+ function nativeEnum(entries2, params) {
47861
48158
  return new ZodEnum2({
47862
48159
  type: "enum",
47863
- entries,
48160
+ entries: entries2,
47864
48161
  ...exports_util.normalizeParams(params)
47865
48162
  });
47866
48163
  }
@@ -48835,7 +49132,7 @@ var init_external2 = __esm(() => {
48835
49132
  init_coerce();
48836
49133
  init_schemas3();
48837
49134
  init_checks2();
48838
- init_errors3();
49135
+ init_errors4();
48839
49136
  init_parse2();
48840
49137
  init_compat();
48841
49138
  config2(en_default2());
@@ -53268,8 +53565,8 @@ var require_baggage_impl = __commonJS((exports) => {
53268
53565
  exports.BaggageImpl = undefined;
53269
53566
 
53270
53567
  class BaggageImpl {
53271
- constructor(entries) {
53272
- this._entries = entries ? new Map(entries) : new Map;
53568
+ constructor(entries2) {
53569
+ this._entries = entries2 ? new Map(entries2) : new Map;
53273
53570
  }
53274
53571
  getEntry(key) {
53275
53572
  const entry = this._entries.get(key);
@@ -53320,8 +53617,8 @@ var require_utils = __commonJS((exports) => {
53320
53617
  var baggage_impl_1 = require_baggage_impl();
53321
53618
  var symbol_1 = require_symbol();
53322
53619
  var diag = diag_1.DiagAPI.instance();
53323
- function createBaggage(entries = {}) {
53324
- return new baggage_impl_1.BaggageImpl(new Map(Object.entries(entries)));
53620
+ function createBaggage(entries2 = {}) {
53621
+ return new baggage_impl_1.BaggageImpl(new Map(Object.entries(entries2)));
53325
53622
  }
53326
53623
  exports.createBaggage = createBaggage;
53327
53624
  function baggageEntryMetadataFromString(str) {
@@ -99560,8 +99857,8 @@ var require_dist2 = __commonJS((exports, module2) => {
99560
99857
  return ajv;
99561
99858
  }
99562
99859
  const [formats, exportName] = opts.mode === "fast" ? [formats_1.fastFormats, fastName] : [formats_1.fullFormats, fullName];
99563
- const list2 = opts.formats || formats_1.formatNames;
99564
- addFormats(ajv, list2, formats, exportName);
99860
+ const list3 = opts.formats || formats_1.formatNames;
99861
+ addFormats(ajv, list3, formats, exportName);
99565
99862
  if (opts.keywords)
99566
99863
  (0, limit_1.default)(ajv);
99567
99864
  return ajv;
@@ -99573,11 +99870,11 @@ var require_dist2 = __commonJS((exports, module2) => {
99573
99870
  throw new Error(`Unknown format "${name26}"`);
99574
99871
  return f;
99575
99872
  };
99576
- function addFormats(ajv, list2, fs5, exportName) {
99873
+ function addFormats(ajv, list3, fs5, exportName) {
99577
99874
  var _a26;
99578
99875
  var _b16;
99579
99876
  (_a26 = (_b16 = ajv.opts.code).formats) !== null && _a26 !== undefined || (_b16.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`);
99580
- for (const f of list2)
99877
+ for (const f of list3)
99581
99878
  ajv.addFormat(f, fs5[f]);
99582
99879
  }
99583
99880
  module2.exports = exports = formatsPlugin;
@@ -103892,19 +104189,19 @@ var init_readFile = __esm(() => {
103892
104189
  });
103893
104190
 
103894
104191
  // src/core/agents/offSecAgent/tools/listFiles.ts
103895
- import { readdir, stat } from "fs/promises";
104192
+ import { readdir as readdir2, stat } from "fs/promises";
103896
104193
  import { join as join12, relative } from "path";
103897
104194
  async function listRecursive(dir, maxEntries) {
103898
104195
  const results = [];
103899
104196
  let total = 0;
103900
104197
  async function walk(current) {
103901
- let entries;
104198
+ let entries2;
103902
104199
  try {
103903
- entries = await readdir(current, { withFileTypes: true });
104200
+ entries2 = await readdir2(current, { withFileTypes: true });
103904
104201
  } catch {
103905
104202
  return;
103906
104203
  }
103907
- for (const entry of entries) {
104204
+ for (const entry of entries2) {
103908
104205
  total++;
103909
104206
  const fullPath = join12(current, entry.name);
103910
104207
  if (entry.isDirectory()) {
@@ -103967,8 +104264,8 @@ Each directory entry is suffixed with "/" for easy identification.`,
103967
104264
  totalFound: total > MAX_RECURSIVE ? total : undefined
103968
104265
  };
103969
104266
  }
103970
- const entries = await readdir(dir, { withFileTypes: true });
103971
- const fullPaths = entries.map((e) => {
104267
+ const entries2 = await readdir2(dir, { withFileTypes: true });
104268
+ const fullPaths = entries2.map((e) => {
103972
104269
  const name26 = join12(dir, e.name);
103973
104270
  return e.isDirectory() ? `${name26}/` : name26;
103974
104271
  });
@@ -103976,11 +104273,11 @@ Each directory entry is suffixed with "/" for easy identification.`,
103976
104273
  const relPaths = toRelative(dir, capped);
103977
104274
  return {
103978
104275
  success: true,
103979
- error: entries.length > MAX_NON_RECURSIVE ? `Showing ${MAX_NON_RECURSIVE} of ${entries.length} entries` : "",
104276
+ error: entries2.length > MAX_NON_RECURSIVE ? `Showing ${MAX_NON_RECURSIVE} of ${entries2.length} entries` : "",
103980
104277
  files: relPaths,
103981
104278
  directory: dir,
103982
104279
  count: relPaths.length,
103983
- totalFound: entries.length > MAX_NON_RECURSIVE ? entries.length : undefined
104280
+ totalFound: entries2.length > MAX_NON_RECURSIVE ? entries2.length : undefined
103984
104281
  };
103985
104282
  } catch (err) {
103986
104283
  return {
@@ -104982,6 +105279,13 @@ When to use delegate_to_auth_subagent vs authenticate_session:
104982
105279
  tokens = { ...stored.tokens };
104983
105280
  }
104984
105281
  }
105282
+ const subagentId = "auth-agent";
105283
+ const cbs = ctx4.subagentCallbacks;
105284
+ cbs?.onSubagentSpawn?.({
105285
+ subagentId,
105286
+ input: { target, reason },
105287
+ status: "pending"
105288
+ });
104985
105289
  console.log(`
104986
105290
  \uD83D\uDD10 Delegating to authentication subagent...`);
104987
105291
  console.log(` Target: ${target}`);
@@ -105033,6 +105337,12 @@ When to use delegate_to_auth_subagent vs authenticate_session:
105033
105337
  ctx4.session.credentialManager.addFromAuthCredentials(credentials);
105034
105338
  }
105035
105339
  const { runAuthenticationAgent: runAuthenticationAgent3 } = await Promise.resolve().then(() => (init_authentication(), exports_authentication));
105340
+ const subagentCallbacks = cbs ? {
105341
+ onTextDelta: (d2) => cbs.onTextDelta?.({ ...d2, subagentId }),
105342
+ onToolCall: (d2) => cbs.onToolCall?.({ ...d2, subagentId }),
105343
+ onToolResult: (d2) => cbs.onToolResult?.({ ...d2, subagentId }),
105344
+ onError: (e) => cbs.onError?.(e)
105345
+ } : undefined;
105036
105346
  const result = await runAuthenticationAgent3({
105037
105347
  target,
105038
105348
  session: ctx4.session,
@@ -105040,7 +105350,15 @@ When to use delegate_to_auth_subagent vs authenticate_session:
105040
105350
  model: ctx4.model,
105041
105351
  authConfig: ctx4.authConfig,
105042
105352
  abortSignal: ctx4.abortSignal,
105043
- callbacks: ctx4.callbacks
105353
+ callbacks: {
105354
+ ...ctx4.callbacks,
105355
+ subagentCallbacks
105356
+ }
105357
+ });
105358
+ cbs?.onSubagentComplete?.({
105359
+ subagentId,
105360
+ input: { target, reason },
105361
+ status: result.success ? "completed" : "failed"
105044
105362
  });
105045
105363
  if (result.success) {
105046
105364
  const sessionInfoPath = join16(ctx4.session.rootPath, "session-info.json");
@@ -105088,6 +105406,11 @@ To make authenticated requests, use the returned values:
105088
105406
  Auth data saved to: ${result.authDataPath}` : ""}` : `Authentication subagent failed. ${result.summary}${result.authBarrier ? ` Barrier: ${result.authBarrier.type} - ${result.authBarrier.details}` : ""}`
105089
105407
  };
105090
105408
  } catch (error40) {
105409
+ ctx4.subagentCallbacks?.onSubagentComplete?.({
105410
+ subagentId: "auth-agent",
105411
+ input: { target, reason },
105412
+ status: "failed"
105413
+ });
105091
105414
  const errorMessage = error40 instanceof Error ? error40.message : String(error40);
105092
105415
  return {
105093
105416
  success: false,
@@ -106170,6 +106493,11 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
106170
106493
  onToolResult: (d2) => cbs.onToolResult?.({ ...d2, subagentId }),
106171
106494
  onError: (e) => cbs.onError?.(e)
106172
106495
  } : undefined;
106496
+ cbs?.onSubagentSpawn?.({
106497
+ subagentId,
106498
+ input: { target, cwd },
106499
+ status: "pending"
106500
+ });
106173
106501
  if (cwd) {
106174
106502
  try {
106175
106503
  const { WhiteboxAttackSurfaceAgent: WhiteboxAttackSurfaceAgent2 } = await Promise.resolve().then(() => (init_agent2(), exports_agent));
@@ -106193,6 +106521,11 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
106193
106521
  })));
106194
106522
  console.log(`
106195
106523
  ✓ Whitebox attack surface complete: ${targets.length} targets from ${result.apps.length} apps`);
106524
+ cbs?.onSubagentComplete?.({
106525
+ subagentId,
106526
+ input: { target, cwd },
106527
+ status: "completed"
106528
+ });
106196
106529
  return {
106197
106530
  success: true,
106198
106531
  mode: "whitebox",
@@ -106204,6 +106537,11 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
106204
106537
  } catch (error40) {
106205
106538
  const errorMsg = error40 instanceof Error ? error40.message : String(error40);
106206
106539
  console.error(`✗ Whitebox attack surface agent failed: ${errorMsg}`);
106540
+ cbs?.onSubagentComplete?.({
106541
+ subagentId,
106542
+ input: { target, cwd },
106543
+ status: "failed"
106544
+ });
106207
106545
  return {
106208
106546
  success: false,
106209
106547
  targets: [],
@@ -106230,6 +106568,11 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
106230
106568
  const targetCount = result.targets.length;
106231
106569
  console.log(`
106232
106570
  ✓ Blackbox attack surface complete: ${targetCount} targets identified`);
106571
+ cbs?.onSubagentComplete?.({
106572
+ subagentId,
106573
+ input: { target },
106574
+ status: "completed"
106575
+ });
106233
106576
  return {
106234
106577
  success: true,
106235
106578
  mode: "blackbox",
@@ -106248,6 +106591,11 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
106248
106591
  } catch (error40) {
106249
106592
  const errorMsg = error40 instanceof Error ? error40.message : String(error40);
106250
106593
  console.error(`✗ Blackbox attack surface agent failed: ${errorMsg}`);
106594
+ cbs?.onSubagentComplete?.({
106595
+ subagentId,
106596
+ input: { target },
106597
+ status: "failed"
106598
+ });
106251
106599
  return {
106252
106600
  success: false,
106253
106601
  targets: [],
@@ -106878,6 +107226,215 @@ var init_provideComparisonResults = __esm(() => {
106878
107226
  init_zod();
106879
107227
  });
106880
107228
 
107229
+ // src/core/memory/index.ts
107230
+ function storageKey(category, id) {
107231
+ return [MEMORIES_PREFIX, category, id];
107232
+ }
107233
+ function slugify2(text2) {
107234
+ return text2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
107235
+ }
107236
+ function makeId(title) {
107237
+ const slug = slugify2(title);
107238
+ const ts = Date.now().toString(36);
107239
+ return slug ? `${slug}-${ts}` : ts;
107240
+ }
107241
+ function validateId(id) {
107242
+ if (id.includes("/") || id.includes("\\") || id.includes("..")) {
107243
+ throw new Error("Invalid memory id: contains path traversal characters");
107244
+ }
107245
+ }
107246
+ async function addMemory(input) {
107247
+ const category = input.category ?? "general";
107248
+ const id = makeId(input.title);
107249
+ const now2 = new Date().toISOString();
107250
+ const memory = {
107251
+ id,
107252
+ category,
107253
+ title: input.title,
107254
+ content: input.content,
107255
+ tags: input.tags ?? [],
107256
+ createdAt: now2,
107257
+ updatedAt: now2
107258
+ };
107259
+ await write2(storageKey(category, id), memory);
107260
+ return memory;
107261
+ }
107262
+ async function getMemory(category, id) {
107263
+ validateId(id);
107264
+ try {
107265
+ return await read2(storageKey(category, id));
107266
+ } catch (e) {
107267
+ if (e instanceof NotFoundError)
107268
+ return null;
107269
+ throw e;
107270
+ }
107271
+ }
107272
+ async function listMemories(opts) {
107273
+ const prefix = opts?.category ? [MEMORIES_PREFIX, opts.category] : [MEMORIES_PREFIX];
107274
+ const keys = await list(prefix);
107275
+ const summaries = [];
107276
+ for (const key of keys) {
107277
+ try {
107278
+ const memory = await read2(key);
107279
+ if (opts?.tag && !memory.tags.includes(opts.tag))
107280
+ continue;
107281
+ summaries.push({
107282
+ id: memory.id,
107283
+ category: memory.category,
107284
+ title: memory.title,
107285
+ tags: memory.tags,
107286
+ createdAt: memory.createdAt
107287
+ });
107288
+ } catch {}
107289
+ }
107290
+ summaries.sort((a, b2) => new Date(b2.createdAt).getTime() - new Date(a.createdAt).getTime());
107291
+ return summaries;
107292
+ }
107293
+ var MEMORY_CATEGORIES, MEMORIES_PREFIX = "memories";
107294
+ var init_memory = __esm(() => {
107295
+ init_storage();
107296
+ MEMORY_CATEGORIES = ["app", "framework", "general"];
107297
+ });
107298
+
107299
+ // src/core/agents/offSecAgent/tools/addMemory.ts
107300
+ function addMemory2(_ctx) {
107301
+ return tool({
107302
+ description: `Save a piece of knowledge to persistent memory.
107303
+
107304
+ Memories are stored across sessions in ~/.pensar/memories/ and survive restarts.
107305
+ They are organised into categories:
107306
+ - "app" — application-specific notes (e.g. target quirks, endpoints)
107307
+ - "framework" — framework-specific notes (e.g. Rails tricks, Django patterns)
107308
+ - "general" — catch-all (default when category is omitted)
107309
+
107310
+ Use this to record reusable techniques, target-specific notes, credential
107311
+ patterns, useful payloads, or any information worth remembering for future
107312
+ engagements.`,
107313
+ inputSchema: addMemoryInputSchema,
107314
+ execute: async ({
107315
+ title,
107316
+ content,
107317
+ category,
107318
+ tags
107319
+ }) => {
107320
+ try {
107321
+ const memory = await addMemory({ title, content, category, tags });
107322
+ return {
107323
+ success: true,
107324
+ error: "",
107325
+ id: memory.id,
107326
+ category: memory.category,
107327
+ title: memory.title
107328
+ };
107329
+ } catch (err) {
107330
+ return {
107331
+ success: false,
107332
+ error: err instanceof Error ? err.message : String(err)
107333
+ };
107334
+ }
107335
+ }
107336
+ });
107337
+ }
107338
+ var addMemoryInputSchema;
107339
+ var init_addMemory = __esm(() => {
107340
+ init_dist5();
107341
+ init_zod();
107342
+ init_memory();
107343
+ addMemoryInputSchema = exports_external.object({
107344
+ title: exports_external.string().describe("Short, descriptive title for the memory (used to generate id)"),
107345
+ content: exports_external.string().describe("Free-form text content to persist as a memory"),
107346
+ category: exports_external.enum(MEMORY_CATEGORIES).optional().describe('Storage category: "app" for application-specific knowledge, ' + '"framework" for framework-specific knowledge, or omit for the ' + '"general" catch-all'),
107347
+ tags: exports_external.array(exports_external.string()).optional().describe("Optional tags for categorisation and filtering"),
107348
+ toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing (e.g., 'Saving XSS payload pattern')")
107349
+ });
107350
+ });
107351
+
107352
+ // src/core/agents/offSecAgent/tools/listMemories.ts
107353
+ function listMemories2(_ctx) {
107354
+ return tool({
107355
+ description: `List saved memories, optionally filtered by category and/or tag.
107356
+
107357
+ Returns lightweight summaries (id, category, title, tags, createdAt) sorted by
107358
+ most recent first. Use the returned category + id with get_memory to retrieve
107359
+ full content.`,
107360
+ inputSchema: listMemoriesInputSchema,
107361
+ execute: async ({ category, tag }) => {
107362
+ try {
107363
+ const memories = await listMemories({ category, tag });
107364
+ return {
107365
+ success: true,
107366
+ error: "",
107367
+ memories,
107368
+ count: memories.length
107369
+ };
107370
+ } catch (err) {
107371
+ return {
107372
+ success: false,
107373
+ error: err instanceof Error ? err.message : String(err),
107374
+ memories: [],
107375
+ count: 0
107376
+ };
107377
+ }
107378
+ }
107379
+ });
107380
+ }
107381
+ var listMemoriesInputSchema;
107382
+ var init_listMemories = __esm(() => {
107383
+ init_dist5();
107384
+ init_zod();
107385
+ init_memory();
107386
+ listMemoriesInputSchema = exports_external.object({
107387
+ category: exports_external.enum(MEMORY_CATEGORIES).optional().describe('Filter by category: "app", "framework", or "general". ' + "Omit to list memories across all categories."),
107388
+ tag: exports_external.string().optional().describe("Optional tag to filter memories by (exact match)"),
107389
+ toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing (e.g., 'Listing stored recon notes')")
107390
+ });
107391
+ });
107392
+
107393
+ // src/core/agents/offSecAgent/tools/getMemory.ts
107394
+ function getMemory2(_ctx) {
107395
+ return tool({
107396
+ description: `Retrieve the full content of a memory by its category and id.
107397
+
107398
+ Use list_memories first to discover available memories, then call this tool
107399
+ with the category and id from that listing to fetch full content.`,
107400
+ inputSchema: getMemoryInputSchema,
107401
+ execute: async ({ category, id }) => {
107402
+ try {
107403
+ const memory = await getMemory(category, id);
107404
+ if (!memory) {
107405
+ return {
107406
+ success: false,
107407
+ error: `Memory not found: ${category}/${id}`,
107408
+ memory: null
107409
+ };
107410
+ }
107411
+ return {
107412
+ success: true,
107413
+ error: "",
107414
+ memory
107415
+ };
107416
+ } catch (err) {
107417
+ return {
107418
+ success: false,
107419
+ error: err instanceof Error ? err.message : String(err),
107420
+ memory: null
107421
+ };
107422
+ }
107423
+ }
107424
+ });
107425
+ }
107426
+ var getMemoryInputSchema;
107427
+ var init_getMemory = __esm(() => {
107428
+ init_dist5();
107429
+ init_zod();
107430
+ init_memory();
107431
+ getMemoryInputSchema = exports_external.object({
107432
+ category: exports_external.enum(MEMORY_CATEGORIES).describe('The memory category: "app", "framework", or "general" (returned by list_memories)'),
107433
+ id: exports_external.string().describe("The unique memory id (returned by list_memories)"),
107434
+ toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing (e.g., 'Retrieving SQL injection cheatsheet')")
107435
+ });
107436
+ });
107437
+
106881
107438
  // src/core/agents/offSecAgent/tools/email/listInboxes.ts
106882
107439
  function emailListInboxes(ctx4) {
106883
107440
  return tool({
@@ -129707,7 +130264,7 @@ var require_libmime = __commonJS((exports, module2) => {
129707
130264
  return response;
129708
130265
  }
129709
130266
  buildHeaderParam(key, data, maxLength, fromCharset) {
129710
- let list2 = [];
130267
+ let list3 = [];
129711
130268
  let encodedStr = typeof data === "string" ? data : this.decode(data, fromCharset);
129712
130269
  let encodedStrArr;
129713
130270
  let chr, ord;
@@ -129726,13 +130283,13 @@ var require_libmime = __commonJS((exports, module2) => {
129726
130283
  ];
129727
130284
  }
129728
130285
  encodedStr = encodedStr.replace(new RegExp(".{" + maxLength + "}", "g"), (str) => {
129729
- list2.push({
130286
+ list3.push({
129730
130287
  line: str
129731
130288
  });
129732
130289
  return "";
129733
130290
  });
129734
130291
  if (encodedStr) {
129735
- list2.push({
130292
+ list3.push({
129736
130293
  line: encodedStr
129737
130294
  });
129738
130295
  }
@@ -129763,7 +130320,7 @@ var require_libmime = __commonJS((exports, module2) => {
129763
130320
  chr = chr === " " ? chr : this.safeEncodeURIComponent(chr);
129764
130321
  if (chr !== encodedStr[i]) {
129765
130322
  if ((this.safeEncodeURIComponent(line) + chr).length >= maxLength) {
129766
- list2.push({
130323
+ list3.push({
129767
130324
  line,
129768
130325
  encoded: isEncoded
129769
130326
  });
@@ -129778,7 +130335,7 @@ var require_libmime = __commonJS((exports, module2) => {
129778
130335
  }
129779
130336
  }
129780
130337
  if ((line + chr).length >= maxLength) {
129781
- list2.push({
130338
+ list3.push({
129782
130339
  line,
129783
130340
  encoded: isEncoded
129784
130341
  });
@@ -129794,13 +130351,13 @@ var require_libmime = __commonJS((exports, module2) => {
129794
130351
  }
129795
130352
  }
129796
130353
  if (line) {
129797
- list2.push({
130354
+ list3.push({
129798
130355
  line,
129799
130356
  encoded: isEncoded
129800
130357
  });
129801
130358
  }
129802
130359
  }
129803
- return list2.map((item, i2) => ({
130360
+ return list3.map((item, i2) => ({
129804
130361
  key: key + "*" + i2 + (item.encoded ? "*" : ""),
129805
130362
  value: item.line
129806
130363
  }));
@@ -131165,7 +131722,7 @@ var require_addressparser = __commonJS((exports, module2) => {
131165
131722
  };
131166
131723
  }
131167
131724
  tokenize() {
131168
- let list2 = [];
131725
+ let list3 = [];
131169
131726
  for (let i = 0, len = this.str.length;i < len; i++) {
131170
131727
  let chr = this.str.charAt(i);
131171
131728
  let nextChr = i < len - 1 ? this.str.charAt(i + 1) : null;
@@ -131174,10 +131731,10 @@ var require_addressparser = __commonJS((exports, module2) => {
131174
131731
  this.list.forEach((node) => {
131175
131732
  node.value = (node.value || "").toString().trim();
131176
131733
  if (node.value) {
131177
- list2.push(node);
131734
+ list3.push(node);
131178
131735
  }
131179
131736
  });
131180
- return list2;
131737
+ return list3;
131181
131738
  }
131182
131739
  checkChar(chr, nextChr) {
131183
131740
  if (this.escaped) {} else if (chr === this.operatorExpecting) {
@@ -131258,8 +131815,8 @@ var require_addressparser = __commonJS((exports, module2) => {
131258
131815
  });
131259
131816
  if (options.flatten) {
131260
131817
  let addresses2 = [];
131261
- let walkAddressList = (list2) => {
131262
- list2.forEach((address2) => {
131818
+ let walkAddressList = (list3) => {
131819
+ list3.forEach((address2) => {
131263
131820
  if (address2.group) {
131264
131821
  return walkAddressList(address2.group);
131265
131822
  } else {
@@ -140602,30 +141159,30 @@ var require_html_to_text = __commonJS((exports) => {
140602
141159
  if (!(this._stackItem instanceof ListStackItem)) {
140603
141160
  throw new Error("Can't add a list item to something that is not a list! Check the formatter.");
140604
141161
  }
140605
- const list2 = this._stackItem;
140606
- const prefixLength = Math.max(prefix.length, list2.maxPrefixLength);
140607
- const maxLineLength = Math.max(20, list2.inlineTextBuilder.maxLineLength - prefixLength);
140608
- this._stackItem = new ListItemStackItem(this.options, list2, {
141162
+ const list3 = this._stackItem;
141163
+ const prefixLength = Math.max(prefix.length, list3.maxPrefixLength);
141164
+ const maxLineLength = Math.max(20, list3.inlineTextBuilder.maxLineLength - prefixLength);
141165
+ this._stackItem = new ListItemStackItem(this.options, list3, {
140609
141166
  prefix,
140610
141167
  maxLineLength,
140611
- leadingLineBreaks: list2.interRowLineBreaks
141168
+ leadingLineBreaks: list3.interRowLineBreaks
140612
141169
  });
140613
141170
  }
140614
141171
  closeListItem() {
140615
141172
  const listItem = this._popStackItem();
140616
- const list2 = listItem.next;
140617
- const prefixLength = Math.max(listItem.prefix.length, list2.maxPrefixLength);
141173
+ const list3 = listItem.next;
141174
+ const prefixLength = Math.max(listItem.prefix.length, list3.maxPrefixLength);
140618
141175
  const spacing = `
140619
141176
  ` + " ".repeat(prefixLength);
140620
- const prefix = list2.prefixAlign === "right" ? listItem.prefix.padStart(prefixLength) : listItem.prefix.padEnd(prefixLength);
141177
+ const prefix = list3.prefixAlign === "right" ? listItem.prefix.padStart(prefixLength) : listItem.prefix.padEnd(prefixLength);
140621
141178
  const text2 = prefix + getText(listItem).replace(/\n/g, spacing);
140622
- addText(list2, text2, listItem.leadingLineBreaks, Math.max(listItem.stashedLineBreaks, list2.interRowLineBreaks));
141179
+ addText(list3, text2, listItem.leadingLineBreaks, Math.max(listItem.stashedLineBreaks, list3.interRowLineBreaks));
140623
141180
  }
140624
141181
  closeList({ trailingLineBreaks = 2 } = {}) {
140625
- const list2 = this._popStackItem();
140626
- const text2 = getText(list2);
141182
+ const list3 = this._popStackItem();
141183
+ const text2 = getText(list3);
140627
141184
  if (text2) {
140628
- addText(this._stackItem, text2, list2.leadingLineBreaks, trailingLineBreaks);
141185
+ addText(this._stackItem, text2, list3.leadingLineBreaks, trailingLineBreaks);
140629
141186
  }
140630
141187
  }
140631
141188
  openTable() {
@@ -140780,9 +141337,9 @@ var require_html_to_text = __commonJS((exports) => {
140780
141337
  if (!dict || Object.keys(dict).length === 0) {
140781
141338
  return;
140782
141339
  }
140783
- const entries = Object.entries(dict).filter(([, v2]) => v2 !== false);
140784
- const regex = new RegExp(entries.map(([c]) => `(${unicodeEscape([...c][0])})`).join("|"), "g");
140785
- const values = entries.map(([, v2]) => v2);
141340
+ const entries2 = Object.entries(dict).filter(([, v2]) => v2 !== false);
141341
+ const regex = new RegExp(entries2.map(([c]) => `(${unicodeEscape([...c][0])})`).join("|"), "g");
141342
+ const values = entries2.map(([, v2]) => v2);
140786
141343
  const replacer = (m2, ...cgs) => values[cgs.findIndex((cg) => cg)];
140787
141344
  return (str) => str.replace(regex, replacer);
140788
141345
  }
@@ -141967,15 +142524,15 @@ var require_index_cjs2 = __commonJS((exports, module2) => {
141967
142524
  this.__last_index__ = m2.index + m2[0].length + len;
141968
142525
  return createMatch(this, 0);
141969
142526
  };
141970
- LinkifyIt.prototype.tlds = function tlds(list2, keepOld) {
141971
- list2 = Array.isArray(list2) ? list2 : [list2];
142527
+ LinkifyIt.prototype.tlds = function tlds(list3, keepOld) {
142528
+ list3 = Array.isArray(list3) ? list3 : [list3];
141972
142529
  if (!keepOld) {
141973
- this.__tlds__ = list2.slice();
142530
+ this.__tlds__ = list3.slice();
141974
142531
  this.__tlds_replaced__ = true;
141975
142532
  compile(this);
141976
142533
  return this;
141977
142534
  }
141978
- this.__tlds__ = this.__tlds__.concat(list2).sort().filter(function(el, idx, arr) {
142535
+ this.__tlds__ = this.__tlds__.concat(list3).sort().filter(function(el, idx, arr) {
141979
142536
  return el !== arr[idx - 1];
141980
142537
  }).reverse();
141981
142538
  compile(this);
@@ -145295,7 +145852,7 @@ var require_common2 = __commonJS((exports, module2) => {
145295
145852
  var require_browser = __commonJS((exports, module2) => {
145296
145853
  exports.formatArgs = formatArgs;
145297
145854
  exports.save = save;
145298
- exports.load = load;
145855
+ exports.load = load2;
145299
145856
  exports.useColors = useColors;
145300
145857
  exports.storage = localstorage();
145301
145858
  exports.destroy = (() => {
@@ -145425,7 +145982,7 @@ var require_browser = __commonJS((exports, module2) => {
145425
145982
  }
145426
145983
  } catch (error40) {}
145427
145984
  }
145428
- function load() {
145985
+ function load2() {
145429
145986
  let r;
145430
145987
  try {
145431
145988
  r = exports.storage.getItem("debug") || exports.storage.getItem("DEBUG");
@@ -145459,7 +146016,7 @@ var require_node3 = __commonJS((exports, module2) => {
145459
146016
  exports.log = log2;
145460
146017
  exports.formatArgs = formatArgs;
145461
146018
  exports.save = save;
145462
- exports.load = load;
146019
+ exports.load = load2;
145463
146020
  exports.useColors = useColors;
145464
146021
  exports.destroy = util4.deprecate(() => {}, "Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
145465
146022
  exports.colors = [6, 2, 3, 4, 5, 1];
@@ -145599,7 +146156,7 @@ var require_node3 = __commonJS((exports, module2) => {
145599
146156
  delete process.env.DEBUG;
145600
146157
  }
145601
146158
  }
145602
- function load() {
146159
+ function load2() {
145603
146160
  return process.env.DEBUG;
145604
146161
  }
145605
146162
  function init2(debug) {
@@ -161065,8 +161622,8 @@ var require_object_inspect = __commonJS((exports, module2) => {
161065
161622
  function weakCollectionOf(type) {
161066
161623
  return type + " { ? }";
161067
161624
  }
161068
- function collectionOf(type, size, entries, indent) {
161069
- var joinedEntries = indent ? indentedJoin(entries, indent) : $join.call(entries, ", ");
161625
+ function collectionOf(type, size, entries2, indent) {
161626
+ var joinedEntries = indent ? indentedJoin(entries2, indent) : $join.call(entries2, ", ");
161070
161627
  return type + " (" + size + ") {" + joinedEntries + "}";
161071
161628
  }
161072
161629
  function singleLineValues(xs) {
@@ -161148,15 +161705,15 @@ var require_object_inspect = __commonJS((exports, module2) => {
161148
161705
  var require_side_channel_list = __commonJS((exports, module2) => {
161149
161706
  var inspect = require_object_inspect();
161150
161707
  var $TypeError = require_type();
161151
- var listGetNode = function(list2, key, isDelete) {
161152
- var prev = list2;
161708
+ var listGetNode = function(list3, key, isDelete) {
161709
+ var prev = list3;
161153
161710
  var curr;
161154
161711
  for (;(curr = prev.next) != null; prev = curr) {
161155
161712
  if (curr.key === key) {
161156
161713
  prev.next = curr.next;
161157
161714
  if (!isDelete) {
161158
- curr.next = list2.next;
161159
- list2.next = curr;
161715
+ curr.next = list3.next;
161716
+ list3.next = curr;
161160
161717
  }
161161
161718
  return curr;
161162
161719
  }
@@ -162375,9 +162932,9 @@ var require_stringify3 = __commonJS((exports, module2) => {
162375
162932
  }
162376
162933
  };
162377
162934
  var isArray = Array.isArray;
162378
- var push = Array.prototype.push;
162935
+ var push2 = Array.prototype.push;
162379
162936
  var pushToArray = function(arr, valueOrArray) {
162380
- push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
162937
+ push2.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
162381
162938
  };
162382
162939
  var toISO = Date.prototype.toISOString;
162383
162940
  var defaultFormat = formats["default"];
@@ -170227,9 +170784,9 @@ var require_caller = __commonJS((exports, module2) => {
170227
170784
  if (!Array.isArray(stack)) {
170228
170785
  return;
170229
170786
  }
170230
- const entries = stack.slice(2);
170787
+ const entries2 = stack.slice(2);
170231
170788
  const fileNames = [];
170232
- for (const entry of entries) {
170789
+ for (const entry of entries2) {
170233
170790
  if (!entry) {
170234
170791
  continue;
170235
170792
  }
@@ -182143,10 +182700,10 @@ var require_tools2 = __commonJS((exports, module2) => {
182143
182700
  }
182144
182701
  return tools.normalizePath(connection, a) === tools.normalizePath(connection, b2);
182145
182702
  },
182146
- updateCapabilities(list2) {
182703
+ updateCapabilities(list3) {
182147
182704
  let map3 = new Map;
182148
- if (list2 && Array.isArray(list2)) {
182149
- list2.forEach((val) => {
182705
+ if (list3 && Array.isArray(list3)) {
182706
+ list3.forEach((val) => {
182150
182707
  if (typeof val.value !== "string") {
182151
182708
  return false;
182152
182709
  }
@@ -182435,8 +182992,8 @@ var require_tools2 = __commonJS((exports, module2) => {
182435
182992
  }
182436
182993
  return obj.value;
182437
182994
  };
182438
- let processAddresses = function(list2) {
182439
- return [].concat(list2 || []).map((addr) => {
182995
+ let processAddresses = function(list3) {
182996
+ return [].concat(list3 || []).map((addr) => {
182440
182997
  let address = (getStrValue(addr[2]) || "") + "@" + (getStrValue(addr[3]) || "");
182441
182998
  if (address === "@") {
182442
182999
  address = "";
@@ -182705,17 +183262,17 @@ var require_tools2 = __commonJS((exports, module2) => {
182705
183262
  if (first === second) {
182706
183263
  return first;
182707
183264
  }
182708
- let list2 = [];
183265
+ let list3 = [];
182709
183266
  if (first < second) {
182710
183267
  for (let i2 = first;i2 <= second; i2++) {
182711
- list2.push(i2);
183268
+ list3.push(i2);
182712
183269
  }
182713
183270
  } else {
182714
183271
  for (let i2 = first;i2 >= second; i2--) {
182715
- list2.push(i2);
183272
+ list3.push(i2);
182716
183273
  }
182717
183274
  }
182718
- return list2;
183275
+ return list3;
182719
183276
  });
182720
183277
  },
182721
183278
  getDecoder(charset) {
@@ -182725,22 +183282,22 @@ var require_tools2 = __commonJS((exports, module2) => {
182725
183282
  }
182726
183283
  return iconv.decodeStream(charset);
182727
183284
  },
182728
- packMessageRange(list2) {
182729
- if (!Array.isArray(list2)) {
182730
- list2 = [].concat(list2 || []);
183285
+ packMessageRange(list3) {
183286
+ if (!Array.isArray(list3)) {
183287
+ list3 = [].concat(list3 || []);
182731
183288
  }
182732
- if (!list2.length) {
183289
+ if (!list3.length) {
182733
183290
  return "";
182734
183291
  }
182735
- list2.sort((a, b2) => a - b2);
182736
- let last = list2[list2.length - 1];
183292
+ list3.sort((a, b2) => a - b2);
183293
+ let last = list3[list3.length - 1];
182737
183294
  let result = [[last]];
182738
- for (let i2 = list2.length - 2;i2 >= 0; i2--) {
182739
- if (list2[i2] === list2[i2 + 1] - 1) {
182740
- result[0].unshift(list2[i2]);
183295
+ for (let i2 = list3.length - 2;i2 >= 0; i2--) {
183296
+ if (list3[i2] === list3[i2 + 1] - 1) {
183297
+ result[0].unshift(list3[i2]);
182741
183298
  continue;
182742
183299
  }
182743
- result.unshift([list2[i2]]);
183300
+ result.unshift([list3[i2]]);
182744
183301
  }
182745
183302
  result = result.map((item) => {
182746
183303
  if (item.length === 1) {
@@ -183296,7 +183853,7 @@ var require_list = __commonJS((exports, module2) => {
183296
183853
  let listCommand = connection.capabilities.has("XLIST") && !connection.capabilities.has("SPECIAL-USE") ? "XLIST" : "LIST";
183297
183854
  let response;
183298
183855
  try {
183299
- let entries = [];
183856
+ let entries2 = [];
183300
183857
  let statusMap = new Map;
183301
183858
  let returnArgs = [];
183302
183859
  let statusQueryAttributes = [];
@@ -183382,7 +183939,7 @@ var require_list = __commonJS((exports, module2) => {
183382
183939
  if (specialUseFlag) {
183383
183940
  addSpecialUseMatch(entry, specialUseFlag, flagSource);
183384
183941
  }
183385
- entries.push(entry);
183942
+ entries2.push(entry);
183386
183943
  },
183387
183944
  STATUS: async (untagged) => {
183388
183945
  let statusPath = normalizePath(connection, decodePath(connection, untagged.attributes[0] && untagged.attributes[0].value || ""));
@@ -183427,13 +183984,13 @@ var require_list = __commonJS((exports, module2) => {
183427
183984
  let normalizedReference = normalizePath(connection, reference || "");
183428
183985
  await runList(normalizedReference, normalizePath(connection, mailbox || "", true));
183429
183986
  if (options.listOnly) {
183430
- return entries;
183987
+ return entries2;
183431
183988
  }
183432
183989
  if (normalizedReference && !specialUseMatches["\\Inbox"]) {
183433
183990
  await runList("", "INBOX");
183434
183991
  }
183435
183992
  if (options.statusQuery) {
183436
- for (let entry of entries) {
183993
+ for (let entry of entries2) {
183437
183994
  if (!entry.flags.has("\\Noselect") && !entry.flags.has("\\NonExistent")) {
183438
183995
  if (statusMap.has(entry.path)) {
183439
183996
  entry.status = statusMap.get(entry.path);
@@ -183469,7 +184026,7 @@ var require_list = __commonJS((exports, module2) => {
183469
184026
  entry.parentPath = entry.delimiter && entry.path ? entry.path.substr(0, entry.path.lastIndexOf(entry.delimiter)) : "";
183470
184027
  entry.parent = entry.delimiter ? entry.path.split(entry.delimiter) : [entry.path];
183471
184028
  entry.name = entry.parent.pop();
183472
- let existing = entries.find((existing2) => existing2.path === entry.path);
184029
+ let existing = entries2.find((existing2) => existing2.path === entry.path);
183473
184030
  if (existing) {
183474
184031
  existing.subscribed = true;
183475
184032
  entry.flags.forEach((flag) => existing.flags.add(flag));
@@ -183492,11 +184049,11 @@ var require_list = __commonJS((exports, module2) => {
183492
184049
  sortedEntries[0].entry.specialUseSource = sortedEntries[0].source;
183493
184050
  }
183494
184051
  }
183495
- let inboxEntry = entries.find((entry) => entry.specialUse === "\\Inbox");
184052
+ let inboxEntry = entries2.find((entry) => entry.specialUse === "\\Inbox");
183496
184053
  if (inboxEntry && !inboxEntry.subscribed) {
183497
184054
  inboxEntry.subscribed = true;
183498
184055
  }
183499
- return entries.sort((a, b2) => {
184056
+ return entries2.sort((a, b2) => {
183500
184057
  if (a.specialUse && !b2.specialUse) {
183501
184058
  return -1;
183502
184059
  }
@@ -184346,10 +184903,10 @@ var require_search_compiler = __commonJS((exports, module2) => {
184346
184903
  }
184347
184904
  break;
184348
184905
  }
184349
- let genOrTree = (list2) => {
184906
+ let genOrTree = (list3) => {
184350
184907
  let group = false;
184351
184908
  let groups = [];
184352
- list2.forEach((entry, i2) => {
184909
+ list3.forEach((entry, i2) => {
184353
184910
  if (i2 % 2 === 0) {
184354
184911
  group = [entry];
184355
184912
  } else {
@@ -184573,9 +185130,9 @@ var require_append = __commonJS((exports, module2) => {
184573
185130
  }
184574
185131
  }
184575
185132
  if (map3.seq && !map3.uid) {
184576
- let list2 = await connection.search({ seq: map3.seq }, { uid: true });
184577
- if (list2 && list2.length) {
184578
- map3.uid = list2[0];
185133
+ let list3 = await connection.search({ seq: map3.seq }, { uid: true });
185134
+ if (list3 && list3.length) {
185135
+ map3.uid = list3[0];
184579
185136
  }
184580
185137
  }
184581
185138
  return map3;
@@ -184628,8 +185185,8 @@ var require_status2 = __commonJS((exports, module2) => {
184628
185185
  untagged: {
184629
185186
  STATUS: async (untagged) => {
184630
185187
  let updateCurrent = connection.state === connection.states.SELECTED && path6 === connection.mailbox.path;
184631
- let list2 = untagged.attributes && Array.isArray(untagged.attributes[1]) ? untagged.attributes[1] : false;
184632
- if (!list2) {
185188
+ let list3 = untagged.attributes && Array.isArray(untagged.attributes[1]) ? untagged.attributes[1] : false;
185189
+ if (!list3) {
184633
185190
  return;
184634
185191
  }
184635
185192
  const STATUS_FIELD_MAP = {
@@ -184663,7 +185220,7 @@ var require_status2 = __commonJS((exports, module2) => {
184663
185220
  }
184664
185221
  };
184665
185222
  let key;
184666
- list2.forEach((entry, i2) => {
185223
+ list3.forEach((entry, i2) => {
184667
185224
  if (i2 % 2 === 0) {
184668
185225
  key = entry && typeof entry.value === "string" ? entry.value : false;
184669
185226
  return;
@@ -186612,7 +187169,7 @@ var init_imap_flow = __esm(() => {
186612
187169
  return false;
186613
187170
  }
186614
187171
  let finished = false;
186615
- let push = false;
187172
+ let push2 = false;
186616
187173
  let rowQueue = [];
186617
187174
  let getNext = () => new Promise((resolve4, reject) => {
186618
187175
  let check2 = () => {
@@ -186627,8 +187184,8 @@ var init_imap_flow = __esm(() => {
186627
187184
  if (finished) {
186628
187185
  return resolve4(null);
186629
187186
  }
186630
- push = () => {
186631
- push = false;
187187
+ push2 = () => {
187188
+ push2 = false;
186632
187189
  check2();
186633
187190
  };
186634
187191
  };
@@ -186645,19 +187202,19 @@ var init_imap_flow = __esm(() => {
186645
187202
  next
186646
187203
  }
186647
187204
  });
186648
- if (typeof push === "function") {
186649
- push();
187205
+ if (typeof push2 === "function") {
187206
+ push2();
186650
187207
  }
186651
187208
  }
186652
187209
  }).then(() => {
186653
187210
  finished = true;
186654
- if (typeof push === "function") {
186655
- push();
187211
+ if (typeof push2 === "function") {
187212
+ push2();
186656
187213
  }
186657
187214
  }).catch((err) => {
186658
187215
  rowQueue.push({ err });
186659
- if (typeof push === "function") {
186660
- push();
187216
+ if (typeof push2 === "function") {
187217
+ push2();
186661
187218
  }
186662
187219
  });
186663
187220
  let res;
@@ -188182,6 +188739,9 @@ function createAllTools(ctx4) {
188182
188739
  spawn_pentest_swarm: spawnPentestSwarm(ctx4),
188183
188740
  spawn_coding_agent: spawnCodingAgent(ctx4),
188184
188741
  provide_comparison_results: provideComparisonResults(ctx4),
188742
+ add_memory: addMemory2(ctx4),
188743
+ list_memories: listMemories2(ctx4),
188744
+ get_memory: getMemory2(ctx4),
188185
188745
  ...createEmailToolset(ctx4),
188186
188746
  email_list_inboxes: emailListInboxes(ctx4),
188187
188747
  email_list_messages: emailListMessages(ctx4),
@@ -188217,6 +188777,9 @@ var init_tools = __esm(() => {
188217
188777
  init_spawnPentestSwarm();
188218
188778
  init_spawnCodingAgent();
188219
188779
  init_provideComparisonResults();
188780
+ init_addMemory();
188781
+ init_listMemories();
188782
+ init_getMemory();
188220
188783
  init_email();
188221
188784
  init_browserTools();
188222
188785
  init_executeCommand();
@@ -188243,6 +188806,9 @@ var init_tools = __esm(() => {
188243
188806
  init_spawnPentestSwarm();
188244
188807
  init_spawnCodingAgent();
188245
188808
  init_provideComparisonResults();
188809
+ init_addMemory();
188810
+ init_listMemories();
188811
+ init_getMemory();
188246
188812
  init_email();
188247
188813
  init_listInboxes();
188248
188814
  init_listMessages();
@@ -188276,6 +188842,9 @@ var init_tools = __esm(() => {
188276
188842
  "spawn_pentest_swarm",
188277
188843
  "spawn_coding_agent",
188278
188844
  "provide_comparison_results",
188845
+ "add_memory",
188846
+ "list_memories",
188847
+ "get_memory",
188279
188848
  "email_list_inboxes",
188280
188849
  "email_list_messages",
188281
188850
  "email_get_message",
@@ -189402,6 +189971,82 @@ var init_agent4 = __esm(() => {
189402
189971
  };
189403
189972
  });
189404
189973
 
189974
+ // src/core/session/execution-metrics.ts
189975
+ import { existsSync as existsSync23, readFileSync as readFileSync10, writeFileSync as writeFileSync15 } from "fs";
189976
+ import { join as join24 } from "path";
189977
+ function toNonNegativeInteger(value) {
189978
+ const n = Number(value);
189979
+ return Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
189980
+ }
189981
+ function normalizeTokenUsage(value) {
189982
+ const inputTokens = toNonNegativeInteger(value?.inputTokens);
189983
+ const outputTokens = toNonNegativeInteger(value?.outputTokens);
189984
+ const derivedTotal = inputTokens + outputTokens;
189985
+ const explicitTotal = toNonNegativeInteger(value?.totalTokens);
189986
+ return {
189987
+ inputTokens,
189988
+ outputTokens,
189989
+ totalTokens: explicitTotal > 0 ? explicitTotal : derivedTotal
189990
+ };
189991
+ }
189992
+ function metricsPath(sessionRootPath) {
189993
+ return join24(sessionRootPath, EXECUTION_METRICS_FILENAME);
189994
+ }
189995
+ function sessionJsonPath(sessionRootPath) {
189996
+ return join24(sessionRootPath, "session.json");
189997
+ }
189998
+ function readExecutionMetrics(sessionRootPath) {
189999
+ const path6 = metricsPath(sessionRootPath);
190000
+ if (!existsSync23(path6))
190001
+ return null;
190002
+ try {
190003
+ const parsed = JSON.parse(readFileSync10(path6, "utf-8"));
190004
+ return {
190005
+ tokenUsage: normalizeTokenUsage(parsed.tokenUsage),
190006
+ runtime: typeof parsed.runtime === "string" ? parsed.runtime : undefined,
190007
+ updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : new Date().toISOString()
190008
+ };
190009
+ } catch {
190010
+ return null;
190011
+ }
190012
+ }
190013
+ function writeSessionJsonTokenTotals(sessionRootPath, tokenUsage) {
190014
+ const path6 = sessionJsonPath(sessionRootPath);
190015
+ if (!existsSync23(path6))
190016
+ return;
190017
+ try {
190018
+ const parsed = JSON.parse(readFileSync10(path6, "utf-8"));
190019
+ parsed.tokensIn = tokenUsage.inputTokens;
190020
+ parsed.tokensOut = tokenUsage.outputTokens;
190021
+ writeFileSync15(path6, JSON.stringify(parsed, null, 2));
190022
+ } catch {}
190023
+ }
190024
+ function writeExecutionMetrics(input) {
190025
+ const existing = readExecutionMetrics(input.sessionRootPath);
190026
+ const nextTokenUsage = input.tokenUsage ? normalizeTokenUsage(input.tokenUsage) : existing?.tokenUsage ?? {
190027
+ inputTokens: 0,
190028
+ outputTokens: 0,
190029
+ totalTokens: 0
190030
+ };
190031
+ const next = {
190032
+ tokenUsage: nextTokenUsage,
190033
+ runtime: input.runtime ?? existing?.runtime,
190034
+ updatedAt: new Date().toISOString()
190035
+ };
190036
+ writeFileSync15(metricsPath(input.sessionRootPath), JSON.stringify(next, null, 2), "utf-8");
190037
+ writeSessionJsonTokenTotals(input.sessionRootPath, next.tokenUsage);
190038
+ return next;
190039
+ }
190040
+ function formatDurationHmsFromMs(durationMs) {
190041
+ const totalSeconds = Math.max(0, Math.floor(durationMs / 1000));
190042
+ const hours = Math.floor(totalSeconds / 3600);
190043
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
190044
+ const seconds = totalSeconds % 60;
190045
+ return `${hours}h${minutes}m${seconds}s`;
190046
+ }
190047
+ var EXECUTION_METRICS_FILENAME = "execution-metrics.json";
190048
+ var init_execution_metrics = () => {};
190049
+
189405
190050
  // src/core/utils/concurrency.ts
189406
190051
  async function runWithBoundedConcurrency(items, concurrency, fn) {
189407
190052
  const results = new Array(items.length).fill(null);
@@ -189439,7 +190084,15 @@ async function runWithBoundedConcurrency(items, concurrency, fn) {
189439
190084
 
189440
190085
  // src/core/workflows/whiteboxAttackSurface.ts
189441
190086
  async function runWhiteboxAttackSurfaceWorkflow(input) {
189442
- const { codebasePath, model, session, authConfig, abortSignal, callbacks } = input;
190087
+ const {
190088
+ codebasePath,
190089
+ model,
190090
+ session,
190091
+ authConfig,
190092
+ abortSignal,
190093
+ callbacks,
190094
+ onStepFinish
190095
+ } = input;
189443
190096
  const appsAgent = new CodeAgent({
189444
190097
  codebasePath,
189445
190098
  objective: buildAppsDiscoveryObjective(codebasePath),
@@ -189449,6 +190102,7 @@ async function runWhiteboxAttackSurfaceWorkflow(input) {
189449
190102
  authConfig,
189450
190103
  abortSignal,
189451
190104
  callbacks,
190105
+ onStepFinish: (event) => onStepFinish?.(event),
189452
190106
  responseSchema: AppsDiscoveryResultSchema
189453
190107
  });
189454
190108
  const appsResult = await appsAgent.consume({
@@ -189492,6 +190146,7 @@ async function runWhiteboxAttackSurfaceWorkflow(input) {
189492
190146
  authConfig,
189493
190147
  abortSignal,
189494
190148
  callbacks,
190149
+ onStepFinish: (event) => onStepFinish?.(event),
189495
190150
  responseSchema: EndpointsDiscoveryResultSchema
189496
190151
  });
189497
190152
  try {
@@ -189756,8 +190411,18 @@ __export(exports_pentest, {
189756
190411
  runPentestSwarm: () => runPentestSwarm,
189757
190412
  DEFAULT_CONCURRENCY: () => DEFAULT_CONCURRENCY3
189758
190413
  });
189759
- import { existsSync as existsSync23, readdirSync as readdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync15 } from "fs";
189760
- import { join as join24 } from "path";
190414
+ import { existsSync as existsSync24, readdirSync as readdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync16 } from "fs";
190415
+ import { join as join25 } from "path";
190416
+ function addUsageTotals(totals, usage) {
190417
+ if (!usage)
190418
+ return;
190419
+ const inputTokens = usage.inputTokens ?? 0;
190420
+ const outputTokens = usage.outputTokens ?? 0;
190421
+ const totalTokens = usage.totalTokens ?? inputTokens + outputTokens;
190422
+ totals.inputTokens += inputTokens;
190423
+ totals.outputTokens += outputTokens;
190424
+ totals.totalTokens += totalTokens;
190425
+ }
189761
190426
  async function runPentestSwarm(input) {
189762
190427
  const {
189763
190428
  targets,
@@ -189768,17 +190433,19 @@ async function runPentestSwarm(input) {
189768
190433
  findingsRegistry,
189769
190434
  subagentCallbacks,
189770
190435
  onError,
189771
- concurrency = DEFAULT_CONCURRENCY3
190436
+ concurrency = DEFAULT_CONCURRENCY3,
190437
+ onStepFinish
189772
190438
  } = input;
189773
190439
  const manifestEntries = buildManifestEntries(targets);
189774
190440
  writeAgentManifest(session, manifestEntries);
189775
190441
  const results = await runWithBoundedConcurrency(targets, concurrency, async (target, index) => {
189776
190442
  const subagentId = `pentest-agent-${index + 1}`;
189777
190443
  let lastMessages = [];
189778
- const onStepFinish = (e2) => {
190444
+ const handleStepFinish = (e2) => {
189779
190445
  if (e2.response.messages) {
189780
190446
  lastMessages = e2.response.messages;
189781
190447
  }
190448
+ onStepFinish?.(e2);
189782
190449
  };
189783
190450
  const wrappedCallbacks = subagentCallbacks ? {
189784
190451
  onTextDelta: (d2) => subagentCallbacks.onTextDelta?.({ ...d2, subagentId }),
@@ -189800,7 +190467,7 @@ async function runPentestSwarm(input) {
189800
190467
  authConfig,
189801
190468
  abortSignal,
189802
190469
  findingsRegistry,
189803
- onStepFinish
190470
+ onStepFinish: handleStepFinish
189804
190471
  });
189805
190472
  const result = await agent.consume({
189806
190473
  onError: (e2) => onError?.(e2),
@@ -189842,74 +190509,98 @@ async function runPentestSwarm(input) {
189842
190509
  }
189843
190510
  async function runPentestWorkflow(input) {
189844
190511
  const { target, cwd, model, session, authConfig, abortSignal, callbacks } = input;
189845
- const mode = cwd ? "whitebox" : "blackbox";
189846
- let swarmTargets;
189847
- if (mode === "whitebox") {
189848
- swarmTargets = await runWhiteboxPhase({
189849
- codebasePath: cwd,
189850
- baseTarget: target,
190512
+ const startedAt = Date.now();
190513
+ const tokenUsageTotals = {
190514
+ inputTokens: 0,
190515
+ outputTokens: 0,
190516
+ totalTokens: 0
190517
+ };
190518
+ const onStepFinish = (event) => {
190519
+ addUsageTotals(tokenUsageTotals, event.usage);
190520
+ };
190521
+ try {
190522
+ const mode = cwd ? "whitebox" : "blackbox";
190523
+ let swarmTargets;
190524
+ if (mode === "whitebox") {
190525
+ swarmTargets = await runWhiteboxPhase({
190526
+ codebasePath: cwd,
190527
+ baseTarget: target,
190528
+ model,
190529
+ session,
190530
+ authConfig,
190531
+ abortSignal,
190532
+ callbacks,
190533
+ onStepFinish
190534
+ });
190535
+ } else {
190536
+ swarmTargets = await runBlackboxPhase({
190537
+ target,
190538
+ model,
190539
+ session,
190540
+ authConfig,
190541
+ abortSignal,
190542
+ callbacks,
190543
+ onStepFinish
190544
+ });
190545
+ }
190546
+ if (swarmTargets.length === 0) {
190547
+ const report2 = buildPentestReport([], {
190548
+ target,
190549
+ model,
190550
+ sessionId: session.id,
190551
+ mode
190552
+ });
190553
+ const mdPath2 = join25(session.rootPath, REPORT_FILENAME_MD);
190554
+ const jsonPath2 = join25(session.rootPath, REPORT_FILENAME_JSON);
190555
+ writeFileSync16(mdPath2, renderMarkdown(report2));
190556
+ writeFileSync16(jsonPath2, renderJson(report2));
190557
+ return {
190558
+ findings: [],
190559
+ findingsPath: session.findingsPath,
190560
+ pocsPath: session.pocsPath,
190561
+ reportPath: mdPath2
190562
+ };
190563
+ }
190564
+ const findingsRegistry = FindingsRegistry.fromDirectory(session.findingsPath, {
189851
190565
  model,
189852
- session,
189853
- authConfig,
189854
- abortSignal,
189855
- callbacks
190566
+ authConfig
189856
190567
  });
189857
- } else {
189858
- swarmTargets = await runBlackboxPhase({
189859
- target,
190568
+ await runPentestSwarm({
190569
+ targets: swarmTargets,
189860
190570
  model,
189861
190571
  session,
189862
190572
  authConfig,
189863
190573
  abortSignal,
189864
- callbacks
190574
+ findingsRegistry,
190575
+ subagentCallbacks: callbacks?.subagentCallbacks,
190576
+ onError: (e2) => callbacks?.onError?.(e2),
190577
+ onStepFinish
189865
190578
  });
189866
- }
189867
- if (swarmTargets.length === 0) {
189868
- const report2 = buildPentestReport([], {
190579
+ const findings = loadFindings2(session.findingsPath);
190580
+ const report = buildPentestReport(findings, {
189869
190581
  target,
189870
190582
  model,
189871
190583
  sessionId: session.id,
189872
190584
  mode
189873
190585
  });
189874
- const mdPath2 = join24(session.rootPath, REPORT_FILENAME_MD);
189875
- const jsonPath2 = join24(session.rootPath, REPORT_FILENAME_JSON);
189876
- writeFileSync15(mdPath2, renderMarkdown(report2));
189877
- writeFileSync15(jsonPath2, renderJson(report2));
190586
+ const mdPath = join25(session.rootPath, REPORT_FILENAME_MD);
190587
+ const jsonPath = join25(session.rootPath, REPORT_FILENAME_JSON);
190588
+ writeFileSync16(mdPath, renderMarkdown(report));
190589
+ writeFileSync16(jsonPath, renderJson(report));
189878
190590
  return {
189879
- findings: [],
190591
+ findings,
189880
190592
  findingsPath: session.findingsPath,
189881
190593
  pocsPath: session.pocsPath,
189882
- reportPath: mdPath2
190594
+ reportPath: mdPath
189883
190595
  };
190596
+ } finally {
190597
+ const runtime = formatDurationHmsFromMs(Date.now() - startedAt);
190598
+ writeExecutionMetrics({
190599
+ sessionRootPath: session.rootPath,
190600
+ tokenUsage: tokenUsageTotals,
190601
+ runtime
190602
+ });
189884
190603
  }
189885
- const findingsRegistry = FindingsRegistry.fromDirectory(session.findingsPath, { model, authConfig });
189886
- await runPentestSwarm({
189887
- targets: swarmTargets,
189888
- model,
189889
- session,
189890
- authConfig,
189891
- abortSignal,
189892
- findingsRegistry,
189893
- subagentCallbacks: callbacks?.subagentCallbacks,
189894
- onError: (e2) => callbacks?.onError?.(e2)
189895
- });
189896
- const findings = loadFindings2(session.findingsPath);
189897
- const report = buildPentestReport(findings, {
189898
- target,
189899
- model,
189900
- sessionId: session.id,
189901
- mode
189902
- });
189903
- const mdPath = join24(session.rootPath, REPORT_FILENAME_MD);
189904
- const jsonPath = join24(session.rootPath, REPORT_FILENAME_JSON);
189905
- writeFileSync15(mdPath, renderMarkdown(report));
189906
- writeFileSync15(jsonPath, renderJson(report));
189907
- return {
189908
- findings,
189909
- findingsPath: session.findingsPath,
189910
- pocsPath: session.pocsPath,
189911
- reportPath: mdPath
189912
- };
189913
190604
  }
189914
190605
  async function runWhiteboxPhase(opts) {
189915
190606
  const workflowInput = {
@@ -189918,7 +190609,8 @@ async function runWhiteboxPhase(opts) {
189918
190609
  session: opts.session,
189919
190610
  authConfig: opts.authConfig,
189920
190611
  abortSignal: opts.abortSignal,
189921
- callbacks: opts.callbacks
190612
+ callbacks: opts.callbacks,
190613
+ onStepFinish: opts.onStepFinish
189922
190614
  };
189923
190615
  const result = await runWhiteboxAttackSurfaceWorkflow(workflowInput);
189924
190616
  return result.apps.flatMap((app) => [...app.pages, ...app.apiEndpoints].map((ep) => ({
@@ -189939,6 +190631,7 @@ async function runBlackboxPhase(opts) {
189939
190631
  if (e2.response.messages) {
189940
190632
  lastMessages = e2.response.messages;
189941
190633
  }
190634
+ opts.onStepFinish?.(e2);
189942
190635
  }
189943
190636
  };
189944
190637
  const agent = new BlackboxAttackSurfaceAgent(agentInput);
@@ -189972,12 +190665,12 @@ async function runBlackboxPhase(opts) {
189972
190665
  }
189973
190666
  }
189974
190667
  function loadFindings2(findingsPath) {
189975
- if (!existsSync23(findingsPath)) {
190668
+ if (!existsSync24(findingsPath)) {
189976
190669
  return [];
189977
190670
  }
189978
190671
  return readdirSync5(findingsPath).filter((f3) => f3.endsWith(".json")).map((f3) => {
189979
190672
  try {
189980
- const content = readFileSync10(join24(findingsPath, f3), "utf-8");
190673
+ const content = readFileSync11(join25(findingsPath, f3), "utf-8");
189981
190674
  return JSON.parse(content);
189982
190675
  } catch {
189983
190676
  return null;
@@ -189991,6 +190684,7 @@ var init_pentest = __esm(() => {
189991
190684
  init_registry();
189992
190685
  init_report();
189993
190686
  init_persistence();
190687
+ init_execution_metrics();
189994
190688
  init_whiteboxAttackSurface();
189995
190689
  });
189996
190690
 
@@ -191049,13 +191743,13 @@ https://github.com/highlightjs/highlight.js/issues/2277`);
191049
191743
  return origin.returnEnd ? 0 : lexeme.length;
191050
191744
  }
191051
191745
  function processContinuations() {
191052
- const list2 = [];
191746
+ const list3 = [];
191053
191747
  for (let current = top;current !== language; current = current.parent) {
191054
191748
  if (current.scope) {
191055
- list2.unshift(current.scope);
191749
+ list3.unshift(current.scope);
191056
191750
  }
191057
191751
  }
191058
- list2.forEach((item) => emitter.openNode(item));
191752
+ list3.forEach((item) => emitter.openNode(item));
191059
191753
  }
191060
191754
  let lastMatch = {};
191061
191755
  function processLexeme(textBeforeMatch, match) {
@@ -196627,7 +197321,7 @@ var require_coffeescript = __commonJS((exports, module2) => {
196627
197321
  "function",
196628
197322
  "static"
196629
197323
  ];
196630
- const excluding = (list2) => (kw) => !list2.includes(kw);
197324
+ const excluding = (list3) => (kw) => !list3.includes(kw);
196631
197325
  const KEYWORDS$1 = {
196632
197326
  keyword: KEYWORDS.concat(COFFEE_KEYWORDS).filter(excluding(NOT_VALID_KEYWORDS)),
196633
197327
  literal: LITERALS.concat(COFFEE_LITERALS),
@@ -210081,8 +210775,8 @@ var require_javascript = __commonJS((exports, module2) => {
210081
210775
  match: /\b[A-Z][A-Z_0-9]+\b/,
210082
210776
  className: "variable.constant"
210083
210777
  };
210084
- function noneOf(list2) {
210085
- return regex.concat("(?!", list2.join("|"), ")");
210778
+ function noneOf(list3) {
210779
+ return regex.concat("(?!", list3.join("|"), ")");
210086
210780
  }
210087
210781
  const FUNCTION_CALL = {
210088
210782
  match: regex.concat(/\b/, noneOf([
@@ -232685,8 +233379,8 @@ var require_sql = __commonJS((exports, module2) => {
232685
233379
  relevance: 0,
232686
233380
  keywords: { built_in: FUNCTIONS }
232687
233381
  };
232688
- function kws_to_regex(list2) {
232689
- return regex.concat(/\b/, regex.either(...list2.map((kw) => {
233382
+ function kws_to_regex(list3) {
233383
+ return regex.concat(/\b/, regex.either(...list3.map((kw) => {
232690
233384
  return kw.replace(/\s+/, "\\s+");
232691
233385
  })), /\b/);
232692
233386
  }
@@ -232695,13 +233389,13 @@ var require_sql = __commonJS((exports, module2) => {
232695
233389
  match: kws_to_regex(COMBOS),
232696
233390
  relevance: 0
232697
233391
  };
232698
- function reduceRelevancy(list2, {
233392
+ function reduceRelevancy(list3, {
232699
233393
  exceptions,
232700
233394
  when
232701
233395
  } = {}) {
232702
233396
  const qualifyFn = when;
232703
233397
  exceptions = exceptions || [];
232704
- return list2.map((item) => {
233398
+ return list3.map((item) => {
232705
233399
  if (item.match(/\|\d+$/) || exceptions.includes(item)) {
232706
233400
  return item;
232707
233401
  } else if (qualifyFn(item)) {
@@ -236386,8 +237080,8 @@ var require_typescript = __commonJS((exports, module2) => {
236386
237080
  match: /\b[A-Z][A-Z_0-9]+\b/,
236387
237081
  className: "variable.constant"
236388
237082
  };
236389
- function noneOf(list2) {
236390
- return regex.concat("(?!", list2.join("|"), ")");
237083
+ function noneOf(list3) {
237084
+ return regex.concat("(?!", list3.join("|"), ")");
236391
237085
  }
236392
237086
  const FUNCTION_CALL = {
236393
237087
  match: regex.concat(/\b/, noneOf([
@@ -266598,7 +267292,7 @@ var useTerminalDimensions = () => {
266598
267292
  };
266599
267293
 
266600
267294
  // src/tui/index.tsx
266601
- var import_react87 = __toESM(require_react(), 1);
267295
+ var import_react86 = __toESM(require_react(), 1);
266602
267296
 
266603
267297
  // src/tui/components/footer.tsx
266604
267298
  import os6 from "os";
@@ -266766,239 +267460,7 @@ function create(prefix, descending2, timestamp) {
266766
267460
 
266767
267461
  // src/core/session/index.ts
266768
267462
  init_installation();
266769
-
266770
- // src/core/storage/index.ts
266771
- import os3 from "os";
266772
- import path3 from "path";
266773
- import fs3 from "fs/promises";
266774
- init_zod();
266775
-
266776
- // src/util/errors.ts
266777
- init_zod();
266778
-
266779
- class NamedError extends Error {
266780
- static create(name, data) {
266781
- const schema2 = zod_default.object({
266782
- name: zod_default.literal(name),
266783
- data
266784
- });
266785
- const result = class extends NamedError {
266786
- data;
266787
- static Schema = schema2;
266788
- name = name;
266789
- constructor(data2, options) {
266790
- super(name, options);
266791
- this.data = data2;
266792
- this.name = name;
266793
- }
266794
- static isInstance(input) {
266795
- return typeof input === "object" && input !== null && "name" in input && input.name === name;
266796
- }
266797
- schema() {
266798
- return schema2;
266799
- }
266800
- toObject() {
266801
- return {
266802
- name,
266803
- data: this.data
266804
- };
266805
- }
266806
- };
266807
- Object.defineProperty(result, "name", { value: name });
266808
- return result;
266809
- }
266810
- static Unknown = NamedError.create("UnknownError", zod_default.object({
266811
- message: zod_default.string()
266812
- }));
266813
- }
266814
-
266815
- // src/util/lock.ts
266816
- var locks = new Map;
266817
- function getLock(key) {
266818
- if (!locks.has(key)) {
266819
- locks.set(key, {
266820
- readers: 0,
266821
- writer: false,
266822
- waitingReaders: [],
266823
- waitingWriters: []
266824
- });
266825
- }
266826
- return locks.get(key);
266827
- }
266828
- function processQueue(key) {
266829
- const lock = locks.get(key);
266830
- if (!lock || lock.writer || lock.readers > 0)
266831
- return;
266832
- if (lock.waitingWriters.length > 0) {
266833
- const nextWriter = lock.waitingWriters.shift();
266834
- nextWriter();
266835
- return;
266836
- }
266837
- while (lock.waitingReaders.length > 0) {
266838
- const nextReader = lock.waitingReaders.shift();
266839
- nextReader();
266840
- }
266841
- if (lock.readers === 0 && !lock.writer && lock.waitingReaders.length === 0 && lock.waitingWriters.length === 0) {
266842
- locks.delete(key);
266843
- }
266844
- }
266845
- async function read(key) {
266846
- const lock = getLock(key);
266847
- return new Promise((resolve3) => {
266848
- if (!lock.writer && lock.waitingWriters.length === 0) {
266849
- lock.readers++;
266850
- resolve3({
266851
- [Symbol.dispose]: () => {
266852
- lock.readers--;
266853
- processQueue(key);
266854
- }
266855
- });
266856
- } else {
266857
- lock.waitingReaders.push(() => {
266858
- lock.readers++;
266859
- resolve3({
266860
- [Symbol.dispose]: () => {
266861
- lock.readers--;
266862
- processQueue(key);
266863
- }
266864
- });
266865
- });
266866
- }
266867
- });
266868
- }
266869
- async function write(key) {
266870
- const lock = getLock(key);
266871
- return new Promise((resolve3) => {
266872
- if (!lock.writer && lock.readers === 0) {
266873
- lock.writer = true;
266874
- resolve3({
266875
- [Symbol.dispose]: () => {
266876
- lock.writer = false;
266877
- processQueue(key);
266878
- }
266879
- });
266880
- } else {
266881
- lock.waitingWriters.push(() => {
266882
- lock.writer = true;
266883
- resolve3({
266884
- [Symbol.dispose]: () => {
266885
- lock.writer = false;
266886
- processQueue(key);
266887
- }
266888
- });
266889
- });
266890
- }
266891
- });
266892
- }
266893
-
266894
- // src/core/storage/index.ts
266895
- var NotFoundError = NamedError.create("NotFoundError", zod_default.object({
266896
- message: zod_default.string()
266897
- }));
266898
- async function remove(key) {
266899
- const dir = path3.join(os3.homedir(), ".pensar");
266900
- const target = path3.join(dir, ...key) + ".json";
266901
- return withErrorHandling(async () => {
266902
- await fs3.unlink(target).catch(() => {});
266903
- });
266904
- }
266905
- async function write2(key, content, ext) {
266906
- const dir = path3.join(os3.homedir(), ".pensar");
266907
- const target = path3.join(dir, ...key) + (ext ? ext : ".json");
266908
- return withErrorHandling(async () => {
266909
- let __stack = [];
266910
- try {
266911
- const _2 = __using(__stack, await write(target), 0);
266912
- await fs3.mkdir(path3.dirname(target), { recursive: true });
266913
- await fs3.writeFile(target, JSON.stringify(content, null, 2), "utf-8");
266914
- } catch (_catch) {
266915
- var _err = _catch, _hasErr = 1;
266916
- } finally {
266917
- __callDispose(__stack, _err, _hasErr);
266918
- }
266919
- });
266920
- }
266921
- async function createDir(key) {
266922
- const dir = path3.join(os3.homedir(), ".pensar");
266923
- const target = path3.join(dir, ...key);
266924
- return withErrorHandling(async () => {
266925
- let __stack = [];
266926
- try {
266927
- const _2 = __using(__stack, await write(target), 0);
266928
- await fs3.mkdir(target, { recursive: true });
266929
- } catch (_catch) {
266930
- var _err = _catch, _hasErr = 1;
266931
- } finally {
266932
- __callDispose(__stack, _err, _hasErr);
266933
- }
266934
- });
266935
- }
266936
- async function writeRaw(key, content) {
266937
- const dir = path3.join(os3.homedir(), ".pensar");
266938
- const target = path3.join(dir, ...key);
266939
- return withErrorHandling(async () => {
266940
- let __stack = [];
266941
- try {
266942
- const _2 = __using(__stack, await write(target), 0);
266943
- const parentDir = path3.dirname(target);
266944
- await fs3.mkdir(parentDir, { recursive: true });
266945
- await fs3.writeFile(target, content, "utf-8");
266946
- } catch (_catch) {
266947
- var _err = _catch, _hasErr = 1;
266948
- } finally {
266949
- __callDispose(__stack, _err, _hasErr);
266950
- }
266951
- });
266952
- }
266953
- async function read2(key, ext) {
266954
- const dir = path3.join(os3.homedir(), ".pensar");
266955
- const target = path3.join(dir, ...key) + (ext ? ext : ".json");
266956
- return withErrorHandling(async () => {
266957
- let __stack = [];
266958
- try {
266959
- const _2 = __using(__stack, await read(target), 0);
266960
- const text = await fs3.readFile(target, "utf-8");
266961
- const result = ext ? text : JSON.parse(text);
266962
- return result;
266963
- } catch (_catch) {
266964
- var _err = _catch, _hasErr = 1;
266965
- } finally {
266966
- __callDispose(__stack, _err, _hasErr);
266967
- }
266968
- });
266969
- }
266970
- async function update2(key, fn, ext) {
266971
- const dir = path3.join(os3.homedir(), ".pensar");
266972
- const target = path3.join(dir, ...key) + (ext ? ext : ".json");
266973
- return withErrorHandling(async () => {
266974
- let __stack = [];
266975
- try {
266976
- const _2 = __using(__stack, await write(target), 0);
266977
- const text = await fs3.readFile(target, "utf-8");
266978
- const content = ext ? text : JSON.parse(text);
266979
- fn(content);
266980
- await fs3.writeFile(target, JSON.stringify(content, null, 2), "utf-8");
266981
- return content;
266982
- } catch (_catch) {
266983
- var _err = _catch, _hasErr = 1;
266984
- } finally {
266985
- __callDispose(__stack, _err, _hasErr);
266986
- }
266987
- });
266988
- }
266989
- async function withErrorHandling(body) {
266990
- return body().catch((e) => {
266991
- if (!(e instanceof Error))
266992
- throw e;
266993
- const errnoExcpetion = e;
266994
- if (errnoExcpetion.code === "ENOENT") {
266995
- throw new NotFoundError({
266996
- message: `Resource not found: ${errnoExcpetion.path}`
266997
- });
266998
- }
266999
- throw e;
267000
- });
267001
- }
267463
+ init_storage();
267002
267464
 
267003
267465
  // src/core/services/rateLimiter/index.ts
267004
267466
  function sleep(ms) {
@@ -267293,7 +267755,7 @@ async function update3(id, editor) {
267293
267755
  console.info("updated session", result);
267294
267756
  return result;
267295
267757
  }
267296
- async function* list() {
267758
+ async function* list2() {
267297
267759
  const sessionsDir = getSessionsDir();
267298
267760
  let entries;
267299
267761
  try {
@@ -267428,7 +267890,7 @@ var sessions = {
267428
267890
  create: create2,
267429
267891
  get: get2,
267430
267892
  update: update3,
267431
- list,
267893
+ list: list2,
267432
267894
  remove: remove2,
267433
267895
  updateMessage,
267434
267896
  removeMessage,
@@ -267557,9 +268019,9 @@ function AgentProvider({ children }) {
267557
268019
  }
267558
268020
  const byProvider = new Map;
267559
268021
  for (const m2 of available) {
267560
- const list2 = byProvider.get(m2.provider) || [];
267561
- list2.push(m2);
267562
- byProvider.set(m2.provider, list2);
268022
+ const list3 = byProvider.get(m2.provider) || [];
268023
+ list3.push(m2);
268024
+ byProvider.set(m2.provider, list3);
267563
268025
  }
267564
268026
  let selectedModel = null;
267565
268027
  for (const provider of PROVIDER_PREFERENCE) {
@@ -267856,7 +268318,6 @@ function useInput() {
267856
268318
  }
267857
268319
 
267858
268320
  // src/tui/components/footer.tsx
267859
- var import_react17 = __toESM(require_react(), 1);
267860
268321
  function formatTokenCount(count) {
267861
268322
  if (count >= 1e6) {
267862
268323
  return `${(count / 1e6).toFixed(1)}M`;
@@ -267871,7 +268332,7 @@ function Footer({
267871
268332
  }) {
267872
268333
  cwd = "~" + cwd.split(os6.homedir()).pop() || "";
267873
268334
  const { colors: colors2 } = useTheme();
267874
- const { model, tokenUsage, hasExecuted, thinking, isExecuting } = useAgent();
268335
+ const { model, isExecuting } = useAgent();
267875
268336
  const session = useSession();
267876
268337
  const route = useRoute();
267877
268338
  const { isInputEmpty } = useInput();
@@ -267952,10 +268413,9 @@ function Footer({
267952
268413
  }
267953
268414
  function AgentStatus() {
267954
268415
  const { colors: colors2 } = useTheme();
267955
- const { tokenUsage, hasExecuted, thinking, isExecuting } = useAgent();
267956
- import_react17.useEffect(() => {
267957
- console.log(tokenUsage);
267958
- }, [tokenUsage]);
268416
+ const route = useRoute();
268417
+ const { tokenUsage, hasExecuted, thinking } = useAgent();
268418
+ const tokenLabel = route.data.type === "operator" ? `${formatTokenCount(tokenUsage.outputTokens)}↑ ${formatTokenCount(tokenUsage.inputTokens)}↓` : `↓${formatTokenCount(tokenUsage.inputTokens)} ↑${formatTokenCount(tokenUsage.outputTokens)} Σ${formatTokenCount(tokenUsage.totalTokens)}`;
267959
268419
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
267960
268420
  flexDirection: "row",
267961
268421
  gap: 1,
@@ -267968,7 +268428,7 @@ function AgentStatus() {
267968
268428
  }, undefined, false, undefined, this),
267969
268429
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
267970
268430
  fg: colors2.text,
267971
- children: `↓${formatTokenCount(tokenUsage.inputTokens)} ↑${formatTokenCount(tokenUsage.outputTokens)} Σ${formatTokenCount(tokenUsage.totalTokens)}`
268431
+ children: tokenLabel
267972
268432
  }, undefined, false, undefined, this)
267973
268433
  ]
267974
268434
  }, undefined, true, undefined, this),
@@ -267989,7 +268449,7 @@ function AgentStatus() {
267989
268449
  }
267990
268450
 
267991
268451
  // src/tui/context/command.tsx
267992
- var import_react18 = __toESM(require_react(), 1);
268452
+ var import_react17 = __toESM(require_react(), 1);
267993
268453
 
267994
268454
  // src/tui/command-router.ts
267995
268455
  class CommandRouter {
@@ -268751,9 +269211,9 @@ async function skillExists(slug) {
268751
269211
  }
268752
269212
 
268753
269213
  // src/tui/context/command.tsx
268754
- var CommandContext = import_react18.createContext(null);
269214
+ var CommandContext = import_react17.createContext(null);
268755
269215
  function useCommand() {
268756
- const context = import_react18.useContext(CommandContext);
269216
+ const context = import_react17.useContext(CommandContext);
268757
269217
  if (!context) {
268758
269218
  throw new Error("useCommand must be used within CommandProvider");
268759
269219
  }
@@ -268764,8 +269224,8 @@ function CommandProvider({
268764
269224
  onOpenSessionsDialog
268765
269225
  }) {
268766
269226
  const route = useRoute();
268767
- const [skills, setSkills] = import_react18.useState([]);
268768
- const ctx3 = import_react18.useMemo(() => {
269227
+ const [skills, setSkills] = import_react17.useState([]);
269228
+ const ctx3 = import_react17.useMemo(() => {
268769
269229
  const ctx4 = {
268770
269230
  route: route.data,
268771
269231
  navigate: route.navigate,
@@ -268773,33 +269233,33 @@ function CommandProvider({
268773
269233
  };
268774
269234
  return ctx4;
268775
269235
  }, [route, onOpenSessionsDialog]);
268776
- const refreshSkills = import_react18.useCallback(async () => {
269236
+ const refreshSkills = import_react17.useCallback(async () => {
268777
269237
  const loaded = await loadSkills();
268778
269238
  setSkills(loaded);
268779
269239
  }, []);
268780
- import_react18.useEffect(() => {
269240
+ import_react17.useEffect(() => {
268781
269241
  refreshSkills();
268782
269242
  }, [route.data]);
268783
- const router = import_react18.useMemo(() => {
269243
+ const router = import_react17.useMemo(() => {
268784
269244
  const router2 = new CommandRouter;
268785
269245
  for (const commandDef of commandRegistry) {
268786
269246
  router2.registerWithContext(commandDef, ctx3);
268787
269247
  }
268788
269248
  return router2;
268789
269249
  }, []);
268790
- const skillSlugMap = import_react18.useMemo(() => {
269250
+ const skillSlugMap = import_react17.useMemo(() => {
268791
269251
  const map = new Map;
268792
269252
  for (const skill of skills) {
268793
269253
  map.set(slugify(skill.name), skill);
268794
269254
  }
268795
269255
  return map;
268796
269256
  }, [skills]);
268797
- const resolveSkillContent = import_react18.useCallback((input) => {
269257
+ const resolveSkillContent = import_react17.useCallback((input) => {
268798
269258
  const trimmed = input.trim().replace(/^\/+/, "").toLowerCase();
268799
269259
  const skill = skillSlugMap.get(trimmed);
268800
269260
  return skill?.content ?? null;
268801
269261
  }, [skillSlugMap]);
268802
- const autocompleteOptions = import_react18.useMemo(() => {
269262
+ const autocompleteOptions = import_react17.useMemo(() => {
268803
269263
  const routerCommands = router.getAllCommands();
268804
269264
  const options = [];
268805
269265
  for (const cmd of routerCommands) {
@@ -268823,10 +269283,10 @@ function CommandProvider({
268823
269283
  }
268824
269284
  return options;
268825
269285
  }, [router, skills]);
268826
- const executeCommand = import_react18.useCallback(async (input) => {
269286
+ const executeCommand = import_react17.useCallback(async (input) => {
268827
269287
  return await router.execute(input, ctx3);
268828
269288
  }, [router, ctx3]);
268829
- const value = import_react18.useMemo(() => ({
269289
+ const value = import_react17.useMemo(() => ({
268830
269290
  router,
268831
269291
  autocompleteOptions,
268832
269292
  executeCommand,
@@ -268849,24 +269309,24 @@ function CommandProvider({
268849
269309
  }
268850
269310
 
268851
269311
  // src/tui/components/commands/sessions-display.tsx
268852
- var import_react23 = __toESM(require_react(), 1);
269312
+ var import_react22 = __toESM(require_react(), 1);
268853
269313
 
268854
269314
  // src/tui/context/focus.tsx
268855
- var import_react19 = __toESM(require_react(), 1);
268856
- var FocusContext = import_react19.createContext(undefined);
269315
+ var import_react18 = __toESM(require_react(), 1);
269316
+ var FocusContext = import_react18.createContext(undefined);
268857
269317
  function FocusProvider({ children }) {
268858
- const promptRef = import_react19.useRef(null);
268859
- const refocusPrompt = import_react19.useCallback(() => {
269318
+ const promptRef = import_react18.useRef(null);
269319
+ const refocusPrompt = import_react18.useCallback(() => {
268860
269320
  setTimeout(() => {
268861
269321
  promptRef.current?.focus();
268862
269322
  }, 1);
268863
269323
  }, []);
268864
- const focusPrompt = import_react19.useCallback(() => promptRef.current?.focus(), []);
268865
- const blurPrompt = import_react19.useCallback(() => promptRef.current?.blur(), []);
268866
- const resetPrompt = import_react19.useCallback(() => promptRef.current?.reset(), []);
268867
- const setPromptValue = import_react19.useCallback((value) => promptRef.current?.setValue(value), []);
268868
- const getPromptValue = import_react19.useCallback(() => promptRef.current?.getValue() ?? "", []);
268869
- const registerPromptRef = import_react19.useCallback((ref) => {
269324
+ const focusPrompt = import_react18.useCallback(() => promptRef.current?.focus(), []);
269325
+ const blurPrompt = import_react18.useCallback(() => promptRef.current?.blur(), []);
269326
+ const resetPrompt = import_react18.useCallback(() => promptRef.current?.reset(), []);
269327
+ const setPromptValue = import_react18.useCallback((value) => promptRef.current?.setValue(value), []);
269328
+ const getPromptValue = import_react18.useCallback(() => promptRef.current?.getValue() ?? "", []);
269329
+ const registerPromptRef = import_react18.useCallback((ref) => {
268870
269330
  promptRef.current = ref;
268871
269331
  }, []);
268872
269332
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(FocusContext.Provider, {
@@ -268884,7 +269344,7 @@ function FocusProvider({ children }) {
268884
269344
  }, undefined, false, undefined, this);
268885
269345
  }
268886
269346
  function useFocus() {
268887
- const context = import_react19.useContext(FocusContext);
269347
+ const context = import_react18.useContext(FocusContext);
268888
269348
  if (!context) {
268889
269349
  throw new Error("useFocus must be used within FocusProvider");
268890
269350
  }
@@ -268916,7 +269376,7 @@ function openSessionReport(sessionRootPath) {
268916
269376
  }
268917
269377
 
268918
269378
  // src/tui/context/dialog.tsx
268919
- var import_react21 = __toESM(require_react(), 1);
269379
+ var import_react20 = __toESM(require_react(), 1);
268920
269380
  function Dialog({ size = "medium", onClose, children }) {
268921
269381
  const dimensions = useTerminalDimensions();
268922
269382
  const renderer = useRenderer();
@@ -268953,14 +269413,14 @@ function Dialog({ size = "medium", onClose, children }) {
268953
269413
  }, undefined, false, undefined, this)
268954
269414
  }, undefined, false, undefined, this);
268955
269415
  }
268956
- var DialogContext = import_react21.createContext(null);
269416
+ var DialogContext = import_react20.createContext(null);
268957
269417
  function DialogProvider({ children }) {
268958
- const [stack, setStack] = import_react21.useState([]);
268959
- const [size, setSize] = import_react21.useState("medium");
268960
- const [externalDialogOpen, setExternalDialogOpen] = import_react21.useState(false);
269418
+ const [stack, setStack] = import_react20.useState([]);
269419
+ const [size, setSize] = import_react20.useState("medium");
269420
+ const [externalDialogOpen, setExternalDialogOpen] = import_react20.useState(false);
268961
269421
  const renderer = useRenderer();
268962
- const focusRef = import_react21.useRef(null);
268963
- const refocus = import_react21.useCallback(() => {
269422
+ const focusRef = import_react20.useRef(null);
269423
+ const refocus = import_react20.useCallback(() => {
268964
269424
  setTimeout(() => {
268965
269425
  const focus = focusRef.current;
268966
269426
  if (!focus)
@@ -268982,7 +269442,7 @@ function DialogProvider({ children }) {
268982
269442
  focus.focus();
268983
269443
  }, 1);
268984
269444
  }, [renderer]);
268985
- const clear = import_react21.useCallback(() => {
269445
+ const clear = import_react20.useCallback(() => {
268986
269446
  for (const item of stack) {
268987
269447
  if (item.onClose)
268988
269448
  item.onClose();
@@ -268991,7 +269451,7 @@ function DialogProvider({ children }) {
268991
269451
  setStack([]);
268992
269452
  refocus();
268993
269453
  }, [stack, refocus]);
268994
- const replace = import_react21.useCallback((element, onClose) => {
269454
+ const replace = import_react20.useCallback((element, onClose) => {
268995
269455
  if (stack.length === 0) {
268996
269456
  focusRef.current = renderer.currentFocusedRenderable;
268997
269457
  }
@@ -269036,7 +269496,7 @@ function DialogProvider({ children }) {
269036
269496
  }, undefined, true, undefined, this);
269037
269497
  }
269038
269498
  function useDialog() {
269039
- const value = import_react21.useContext(DialogContext);
269499
+ const value = import_react20.useContext(DialogContext);
269040
269500
  if (!value) {
269041
269501
  throw new Error("useDialog must be used within a DialogProvider");
269042
269502
  }
@@ -269044,10 +269504,10 @@ function useDialog() {
269044
269504
  }
269045
269505
 
269046
269506
  // src/tui/utils/scroll.ts
269047
- function scrollToIndex(scrollBox, index, list2, getId) {
269048
- if (!scrollBox || list2.length === 0)
269507
+ function scrollToIndex(scrollBox, index, list3, getId) {
269508
+ if (!scrollBox || list3.length === 0)
269049
269509
  return;
269050
- const item = list2[index];
269510
+ const item = list3[index];
269051
269511
  if (!item)
269052
269512
  return;
269053
269513
  const target = findChildById(scrollBox, getId(item));
@@ -269057,7 +269517,7 @@ function scrollToIndex(scrollBox, index, list2, getId) {
269057
269517
  scrollBox.scrollTo(0);
269058
269518
  return;
269059
269519
  }
269060
- if (index === list2.length - 1) {
269520
+ if (index === list3.length - 1) {
269061
269521
  scrollBox.scrollTo(Infinity);
269062
269522
  return;
269063
269523
  }
@@ -269099,7 +269559,7 @@ function findChildById(scrollBox, id) {
269099
269559
  }
269100
269560
 
269101
269561
  // src/tui/hooks/use-sessions-list.ts
269102
- var import_react22 = __toESM(require_react(), 1);
269562
+ var import_react21 = __toESM(require_react(), 1);
269103
269563
  import { existsSync as existsSync7, readdirSync } from "fs";
269104
269564
  import { join as join3 } from "path";
269105
269565
  init_report();
@@ -269116,10 +269576,10 @@ function checkHasReport(rootPath) {
269116
269576
  return existsSync7(join3(rootPath, REPORT_FILENAME_MD));
269117
269577
  }
269118
269578
  function useSessionsList() {
269119
- const [allSessions, setAllSessions] = import_react22.useState([]);
269120
- const [loading, setLoading] = import_react22.useState(true);
269121
- const [searchTerm, setSearchTerm] = import_react22.useState("");
269122
- const loadSessions = import_react22.useCallback(async () => {
269579
+ const [allSessions, setAllSessions] = import_react21.useState([]);
269580
+ const [loading, setLoading] = import_react21.useState(true);
269581
+ const [searchTerm, setSearchTerm] = import_react21.useState("");
269582
+ const loadSessions = import_react21.useCallback(async () => {
269123
269583
  setLoading(true);
269124
269584
  try {
269125
269585
  const enriched = [];
@@ -269142,10 +269602,10 @@ function useSessionsList() {
269142
269602
  setLoading(false);
269143
269603
  }
269144
269604
  }, []);
269145
- import_react22.useEffect(() => {
269605
+ import_react21.useEffect(() => {
269146
269606
  loadSessions();
269147
269607
  }, [loadSessions]);
269148
- const deleteSession = import_react22.useCallback(async (id) => {
269608
+ const deleteSession = import_react21.useCallback(async (id) => {
269149
269609
  await sessions.remove({ sessionId: id });
269150
269610
  await loadSessions();
269151
269611
  }, [loadSessions]);
@@ -269204,10 +269664,10 @@ function useSessionsList() {
269204
269664
  function SessionsDisplay({ onClose }) {
269205
269665
  const { colors: colors2 } = useTheme();
269206
269666
  const { refocusPrompt } = useFocus();
269207
- const [selectedIndex, setSelectedIndex] = import_react23.useState(0);
269208
- const [statusMessage, setStatusMessage] = import_react23.useState("");
269667
+ const [selectedIndex, setSelectedIndex] = import_react22.useState(0);
269668
+ const [statusMessage, setStatusMessage] = import_react22.useState("");
269209
269669
  const route = useRoute();
269210
- const scroll = import_react23.useRef(null);
269670
+ const scroll = import_react22.useRef(null);
269211
269671
  const {
269212
269672
  groupedSessions,
269213
269673
  visualOrderSessions,
@@ -269223,7 +269683,7 @@ function SessionsDisplay({ onClose }) {
269223
269683
  setTimeout(() => setStatusMessage(""), 2000);
269224
269684
  }
269225
269685
  }
269226
- import_react23.useEffect(() => {
269686
+ import_react22.useEffect(() => {
269227
269687
  if (visualOrderSessions.length > 0 && selectedIndex >= visualOrderSessions.length) {
269228
269688
  setSelectedIndex(visualOrderSessions.length - 1);
269229
269689
  } else if (visualOrderSessions.length === 0) {
@@ -269495,7 +269955,7 @@ function SessionsDisplay({ onClose }) {
269495
269955
  }
269496
269956
 
269497
269957
  // src/tui/components/commands/config-dialog.tsx
269498
- var import_react26 = __toESM(require_react(), 1);
269958
+ var import_react25 = __toESM(require_react(), 1);
269499
269959
 
269500
269960
  // src/tui/components/alert-dialog.tsx
269501
269961
  function AlertDialog({
@@ -269582,8 +270042,8 @@ function AlertDialog({
269582
270042
  init_config2();
269583
270043
  function ConfigDialog() {
269584
270044
  const route = useRoute();
269585
- const [open, setOpen] = import_react26.useState(false);
269586
- import_react26.useEffect(() => {
270045
+ const [open, setOpen] = import_react25.useState(false);
270046
+ import_react25.useEffect(() => {
269587
270047
  if (route.data.type === "base" && route.data.path === "config") {
269588
270048
  setOpen(true);
269589
270049
  } else {
@@ -269597,8 +270057,8 @@ function ConfigDialog() {
269597
270057
  path: "home"
269598
270058
  });
269599
270059
  };
269600
- const [appConfig, setAppConfig] = import_react26.useState(null);
269601
- import_react26.useEffect(() => {
270060
+ const [appConfig, setAppConfig] = import_react25.useState(null);
270061
+ import_react25.useEffect(() => {
269602
270062
  async function getConfig() {
269603
270063
  const _appConfig = await config.get();
269604
270064
  setAppConfig(_appConfig);
@@ -269668,15 +270128,15 @@ function ConfigForm({ appConfig }) {
269668
270128
  }
269669
270129
 
269670
270130
  // src/tui/components/chat/index.tsx
269671
- var import_react38 = __toESM(require_react(), 1);
270131
+ var import_react37 = __toESM(require_react(), 1);
269672
270132
 
269673
270133
  // src/tui/context/config.tsx
269674
270134
  init_config2();
269675
- var import_react27 = __toESM(require_react(), 1);
269676
- var ctx3 = import_react27.createContext(null);
270135
+ var import_react26 = __toESM(require_react(), 1);
270136
+ var ctx3 = import_react26.createContext(null);
269677
270137
  function ConfigProvider({ children, config: config2 }) {
269678
- const [appConfig, setAppConfig] = import_react27.useState(config2);
269679
- const value = import_react27.useMemo(() => ({
270138
+ const [appConfig, setAppConfig] = import_react26.useState(config2);
270139
+ const value = import_react26.useMemo(() => ({
269680
270140
  data: appConfig,
269681
270141
  update: async (newConfig) => {
269682
270142
  await config.update(newConfig);
@@ -269696,7 +270156,7 @@ function ConfigProvider({ children, config: config2 }) {
269696
270156
  }, undefined, false, undefined, this);
269697
270157
  }
269698
270158
  var useConfig = () => {
269699
- const config2 = import_react27.useContext(ctx3);
270159
+ const config2 = import_react26.useContext(ctx3);
269700
270160
  if (!config2) {
269701
270161
  throw new Error("useConfig must be called within a ConfigProvider");
269702
270162
  }
@@ -269704,10 +270164,10 @@ var useConfig = () => {
269704
270164
  };
269705
270165
 
269706
270166
  // src/tui/components/chat/home-view.tsx
269707
- var import_react32 = __toESM(require_react(), 1);
270167
+ var import_react31 = __toESM(require_react(), 1);
269708
270168
 
269709
270169
  // src/tui/components/chat/petri-animation.tsx
269710
- var import_react28 = __toESM(require_react(), 1);
270170
+ var import_react27 = __toESM(require_react(), 1);
269711
270171
 
269712
270172
  // src/tui/components/chat/lib/play-core/num.ts
269713
270173
  function clamp(x2, min, max) {
@@ -269803,8 +270263,8 @@ function stopGlobalTick2() {
269803
270263
  }
269804
270264
  }
269805
270265
  function useGlobalTick2() {
269806
- const [, setTick] = import_react28.useState(0);
269807
- import_react28.useEffect(() => {
270266
+ const [, setTick] = import_react27.useState(0);
270267
+ import_react27.useEffect(() => {
269808
270268
  const listener = () => setTick((t2) => t2 + 1);
269809
270269
  globalListeners2.add(listener);
269810
270270
  startGlobalTick2();
@@ -269832,16 +270292,16 @@ function PetriAnimation({
269832
270292
  const dimensions = useTerminalDimensions();
269833
270293
  const tick = useGlobalTick2();
269834
270294
  const { colors: colors2 } = useTheme();
269835
- const simulationRef = import_react28.useRef(null);
269836
- const [frame, setFrame] = import_react28.useState([]);
269837
- const gradientColors = import_react28.useMemo(() => generateGradient(colors2.primary, 9), [colors2.primary]);
269838
- const actualHeight = import_react28.useMemo(() => {
270295
+ const simulationRef = import_react27.useRef(null);
270296
+ const [frame, setFrame] = import_react27.useState([]);
270297
+ const gradientColors = import_react27.useMemo(() => generateGradient(colors2.primary, 9), [colors2.primary]);
270298
+ const actualHeight = import_react27.useMemo(() => {
269839
270299
  if (typeof height === "number" && height <= 1) {
269840
270300
  return Math.floor(dimensions.height * height);
269841
270301
  }
269842
270302
  return typeof height === "number" ? height : Math.floor(dimensions.height * 0.4);
269843
270303
  }, [height, dimensions.height]);
269844
- const actualWidth = import_react28.useMemo(() => {
270304
+ const actualWidth = import_react27.useMemo(() => {
269845
270305
  if (typeof width === "number" && width <= 1) {
269846
270306
  return Math.floor(dimensions.width * width);
269847
270307
  }
@@ -269850,7 +270310,7 @@ function PetriAnimation({
269850
270310
  }
269851
270311
  return typeof width === "number" ? width : dimensions.width;
269852
270312
  }, [width, dimensions.width]);
269853
- import_react28.useEffect(() => {
270313
+ import_react27.useEffect(() => {
269854
270314
  if (actualWidth <= 0 || actualHeight <= 0)
269855
270315
  return;
269856
270316
  if (!simulationRef.current) {
@@ -269859,7 +270319,7 @@ function PetriAnimation({
269859
270319
  simulationRef.current.resize(actualWidth, actualHeight);
269860
270320
  }
269861
270321
  }, [actualWidth, actualHeight]);
269862
- import_react28.useEffect(() => {
270322
+ import_react27.useEffect(() => {
269863
270323
  if (simulationRef.current) {
269864
270324
  simulationRef.current.step();
269865
270325
  setFrame(simulationRef.current.render());
@@ -269885,8 +270345,8 @@ function getRowColor(rowIdx, totalRows, gradient) {
269885
270345
  }
269886
270346
 
269887
270347
  // src/tui/components/shared/prompt-input.tsx
269888
- var import_react30 = __toESM(require_react(), 1);
269889
- var PromptInput = import_react30.forwardRef(function PromptInput2({
270348
+ var import_react29 = __toESM(require_react(), 1);
270349
+ var PromptInput = import_react29.forwardRef(function PromptInput2({
269890
270350
  width,
269891
270351
  minHeight = 1,
269892
270352
  maxHeight = 6,
@@ -269903,20 +270363,26 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
269903
270363
  maxSuggestions = 10,
269904
270364
  enableCommands = false,
269905
270365
  onCommandExecute,
270366
+ commandHistory = [],
269906
270367
  showPromptIndicator = false
269907
270368
  }, ref) {
269908
270369
  const { colors: colors2 } = useTheme();
269909
270370
  const { inputValue, setInputValue } = useInput();
269910
270371
  const { registerPromptRef } = useFocus();
269911
- const textareaRef = import_react30.useRef(null);
269912
- const [selectedSuggestionIndex, setSelectedSuggestionIndex] = import_react30.useState(-1);
269913
- const selectedIndexRef = import_react30.useRef(selectedSuggestionIndex);
269914
- const suggestionsRef = import_react30.useRef([]);
269915
- const onCommandExecuteRef = import_react30.useRef(onCommandExecute);
270372
+ const textareaRef = import_react29.useRef(null);
270373
+ const [selectedSuggestionIndex, setSelectedSuggestionIndex] = import_react29.useState(-1);
270374
+ const [historyIndex, setHistoryIndex] = import_react29.useState(-1);
270375
+ const savedInputRef = import_react29.useRef("");
270376
+ const historyRef = import_react29.useRef(commandHistory);
270377
+ historyRef.current = commandHistory;
270378
+ const isNavigatingHistoryRef = import_react29.useRef(false);
270379
+ const selectedIndexRef = import_react29.useRef(selectedSuggestionIndex);
270380
+ const suggestionsRef = import_react29.useRef([]);
270381
+ const onCommandExecuteRef = import_react29.useRef(onCommandExecute);
269916
270382
  onCommandExecuteRef.current = onCommandExecute;
269917
- const onSubmitRef = import_react30.useRef(onSubmit);
270383
+ const onSubmitRef = import_react29.useRef(onSubmit);
269918
270384
  onSubmitRef.current = onSubmit;
269919
- const suggestions = import_react30.useMemo(() => {
270385
+ const suggestions = import_react29.useMemo(() => {
269920
270386
  if (!enableAutocomplete || !autocompleteOptions || !inputValue)
269921
270387
  return [];
269922
270388
  const input = inputValue.toLowerCase().trim();
@@ -269924,16 +270390,16 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
269924
270390
  return [];
269925
270391
  return autocompleteOptions.filter((opt) => opt.value.toLowerCase().includes(input) || opt.label.toLowerCase().includes(input)).slice(0, maxSuggestions);
269926
270392
  }, [enableAutocomplete, autocompleteOptions, inputValue, maxSuggestions]);
269927
- import_react30.useEffect(() => {
270393
+ import_react29.useEffect(() => {
269928
270394
  suggestionsRef.current = suggestions;
269929
270395
  }, [suggestions]);
269930
- import_react30.useEffect(() => {
270396
+ import_react29.useEffect(() => {
269931
270397
  selectedIndexRef.current = selectedSuggestionIndex;
269932
270398
  }, [selectedSuggestionIndex]);
269933
- import_react30.useEffect(() => {
270399
+ import_react29.useEffect(() => {
269934
270400
  setSelectedSuggestionIndex(suggestions.length > 0 ? 0 : -1);
269935
270401
  }, [suggestions.length]);
269936
- const imperativeRef = import_react30.useRef({
270402
+ const imperativeRef = import_react29.useRef({
269937
270403
  focus: () => textareaRef.current?.focus(),
269938
270404
  blur: () => textareaRef.current?.blur(),
269939
270405
  reset: () => {
@@ -269948,37 +270414,85 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
269948
270414
  getValue: () => inputValue,
269949
270415
  getTextareaRef: () => textareaRef.current
269950
270416
  });
269951
- import_react30.useEffect(() => {
270417
+ import_react29.useEffect(() => {
269952
270418
  imperativeRef.current.getValue = () => inputValue;
269953
270419
  }, [inputValue]);
269954
- import_react30.useImperativeHandle(ref, () => imperativeRef.current, []);
269955
- import_react30.useEffect(() => {
270420
+ import_react29.useImperativeHandle(ref, () => imperativeRef.current, []);
270421
+ import_react29.useEffect(() => {
269956
270422
  registerPromptRef(imperativeRef.current);
269957
270423
  return () => registerPromptRef(null);
269958
270424
  }, [registerPromptRef]);
269959
270425
  useKeyboard((key) => {
269960
- if (!focused || suggestions.length === 0)
270426
+ if (!focused)
269961
270427
  return;
269962
- if (key.name === "up") {
269963
- setSelectedSuggestionIndex((prev) => prev <= 0 ? suggestions.length - 1 : prev - 1);
270428
+ if (suggestions.length > 0) {
270429
+ if (key.name === "up") {
270430
+ setSelectedSuggestionIndex((prev) => prev <= 0 ? suggestions.length - 1 : prev - 1);
270431
+ return;
270432
+ }
270433
+ if (key.name === "down") {
270434
+ setSelectedSuggestionIndex((prev) => prev >= suggestions.length - 1 ? 0 : prev + 1);
270435
+ return;
270436
+ }
270437
+ if (key.name === "tab") {
270438
+ key.preventDefault?.();
270439
+ const currentSelectedIndex = selectedIndexRef.current;
270440
+ if (currentSelectedIndex >= 0 && currentSelectedIndex < suggestions.length) {
270441
+ const selected = suggestions[currentSelectedIndex];
270442
+ if (selected) {
270443
+ textareaRef.current?.setText(selected.value);
270444
+ setInputValue(selected.value);
270445
+ setSelectedSuggestionIndex(-1);
270446
+ textareaRef.current?.gotoLineEnd();
270447
+ }
270448
+ }
270449
+ return;
270450
+ }
269964
270451
  return;
269965
270452
  }
269966
- if (key.name === "down") {
269967
- setSelectedSuggestionIndex((prev) => prev >= suggestions.length - 1 ? 0 : prev + 1);
270453
+ const history = historyRef.current;
270454
+ if (history.length === 0)
270455
+ return;
270456
+ if (key.name === "up") {
270457
+ setHistoryIndex((prev) => {
270458
+ if (prev === -1) {
270459
+ savedInputRef.current = textareaRef.current?.plainText ?? "";
270460
+ }
270461
+ const next = Math.min(prev + 1, history.length - 1);
270462
+ const entry = history[history.length - 1 - next];
270463
+ if (entry !== undefined) {
270464
+ isNavigatingHistoryRef.current = true;
270465
+ textareaRef.current?.setText(entry);
270466
+ setInputValue(entry);
270467
+ isNavigatingHistoryRef.current = false;
270468
+ setTimeout(() => textareaRef.current?.gotoLineEnd(), 0);
270469
+ }
270470
+ return next;
270471
+ });
269968
270472
  return;
269969
270473
  }
269970
- if (key.name === "tab") {
269971
- key.preventDefault?.();
269972
- const currentSelectedIndex = selectedIndexRef.current;
269973
- if (currentSelectedIndex >= 0 && currentSelectedIndex < suggestions.length) {
269974
- const selected = suggestions[currentSelectedIndex];
269975
- if (selected) {
269976
- textareaRef.current?.setText(selected.value);
269977
- setInputValue(selected.value);
269978
- setSelectedSuggestionIndex(-1);
269979
- textareaRef.current?.gotoLineEnd();
270474
+ if (key.name === "down") {
270475
+ setHistoryIndex((prev) => {
270476
+ if (prev <= 0) {
270477
+ const saved = savedInputRef.current;
270478
+ isNavigatingHistoryRef.current = true;
270479
+ textareaRef.current?.setText(saved);
270480
+ setInputValue(saved);
270481
+ isNavigatingHistoryRef.current = false;
270482
+ setTimeout(() => textareaRef.current?.gotoLineEnd(), 0);
270483
+ return -1;
269980
270484
  }
269981
- }
270485
+ const next = prev - 1;
270486
+ const entry = history[history.length - 1 - next];
270487
+ if (entry !== undefined) {
270488
+ isNavigatingHistoryRef.current = true;
270489
+ textareaRef.current?.setText(entry);
270490
+ setInputValue(entry);
270491
+ isNavigatingHistoryRef.current = false;
270492
+ setTimeout(() => textareaRef.current?.gotoLineEnd(), 0);
270493
+ }
270494
+ return next;
270495
+ });
269982
270496
  return;
269983
270497
  }
269984
270498
  });
@@ -270004,13 +270518,18 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
270004
270518
  setInputValue("");
270005
270519
  textareaRef.current?.setText("");
270006
270520
  setSelectedSuggestionIndex(-1);
270521
+ setHistoryIndex(-1);
270007
270522
  return;
270008
270523
  }
270524
+ setHistoryIndex(-1);
270009
270525
  onSubmitRef.current?.(valueToSubmit);
270010
270526
  };
270011
270527
  const handleContentChange = () => {
270012
270528
  const text = textareaRef.current?.plainText ?? "";
270013
270529
  setInputValue(text);
270530
+ if (historyIndex !== -1 && !isNavigatingHistoryRef.current) {
270531
+ setHistoryIndex(-1);
270532
+ }
270014
270533
  };
270015
270534
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
270016
270535
  flexDirection: "column",
@@ -270092,6 +270611,45 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
270092
270611
  }, undefined, true, undefined, this);
270093
270612
  });
270094
270613
 
270614
+ // src/core/history.ts
270615
+ init_storage();
270616
+ var STORAGE_KEY = ["command-history"];
270617
+ var MAX_ENTRIES = 500;
270618
+ var entries = null;
270619
+ var loadPromise = null;
270620
+ async function ensureLoaded() {
270621
+ if (entries !== null)
270622
+ return entries;
270623
+ if (!loadPromise) {
270624
+ loadPromise = (async () => {
270625
+ try {
270626
+ const data = await read2(STORAGE_KEY);
270627
+ entries = Array.isArray(data) ? data : [];
270628
+ } catch {
270629
+ entries = [];
270630
+ }
270631
+ })();
270632
+ }
270633
+ await loadPromise;
270634
+ return entries;
270635
+ }
270636
+ async function load() {
270637
+ return ensureLoaded();
270638
+ }
270639
+ async function push(entry) {
270640
+ const history = await ensureLoaded();
270641
+ if (history[history.length - 1] === entry)
270642
+ return;
270643
+ history.push(entry);
270644
+ if (history.length > MAX_ENTRIES) {
270645
+ history.splice(0, history.length - MAX_ENTRIES);
270646
+ }
270647
+ write2(STORAGE_KEY, history).catch(() => {});
270648
+ }
270649
+ function getEntries() {
270650
+ return entries ?? [];
270651
+ }
270652
+
270095
270653
  // src/tui/components/chat/home-view.tsx
270096
270654
  function HomeView({ onNavigate, onStartSession }) {
270097
270655
  const { colors: colors2 } = useTheme();
@@ -270101,27 +270659,37 @@ function HomeView({ onNavigate, onStartSession }) {
270101
270659
  const { executeCommand, autocompleteOptions, resolveSkillContent, skills } = useCommand();
270102
270660
  const { setInputValue } = useInput();
270103
270661
  const { promptRef } = useFocus();
270104
- const [hintMessage, setHintMessage] = import_react32.useState(null);
270105
- const launchOperator = import_react32.useCallback((message, options) => {
270662
+ const [hintMessage, setHintMessage] = import_react31.useState(null);
270663
+ const [commandHistory, setCommandHistory] = import_react31.useState(getEntries);
270664
+ import_react31.useEffect(() => {
270665
+ load().then(setCommandHistory);
270666
+ }, []);
270667
+ const launchOperator = import_react31.useCallback((message, options) => {
270106
270668
  route.navigate({
270107
270669
  type: "operator",
270108
270670
  initialMessage: message,
270109
270671
  initialConfig: { requireApproval: options?.requireApproval ?? true }
270110
270672
  });
270111
270673
  }, [route]);
270112
- const handleSubmit = import_react32.useCallback((value) => {
270674
+ const pushHistory = import_react31.useCallback((entry) => {
270675
+ push(entry).then(() => setCommandHistory([...getEntries()]));
270676
+ }, []);
270677
+ const handleSubmit = import_react31.useCallback((value) => {
270113
270678
  if (!value.trim())
270114
270679
  return;
270680
+ pushHistory(value.trim());
270115
270681
  launchOperator(value.trim());
270116
- }, [launchOperator]);
270117
- import_react32.useEffect(() => {
270682
+ }, [launchOperator, pushHistory]);
270683
+ import_react31.useEffect(() => {
270118
270684
  if (!hintMessage)
270119
270685
  return;
270120
270686
  const timer = setTimeout(() => setHintMessage(null), 3000);
270121
270687
  return () => clearTimeout(timer);
270122
270688
  }, [hintMessage]);
270123
- const handleCommandExecute = import_react32.useCallback(async (command) => {
270124
- const parts = command.trim().replace(/^\/+/, "").split(/\s+/);
270689
+ const handleCommandExecute = import_react31.useCallback(async (command) => {
270690
+ const trimmed = command.trim();
270691
+ pushHistory(trimmed);
270692
+ const parts = trimmed.replace(/^\/+/, "").split(/\s+/);
270125
270693
  const slug = parts[0]?.toLowerCase() ?? "";
270126
270694
  const args = parts.slice(1);
270127
270695
  const autopilot = args.includes("--autopilot");
@@ -270131,7 +270699,7 @@ function HomeView({ onNavigate, onStartSession }) {
270131
270699
  return;
270132
270700
  }
270133
270701
  await executeCommand(command);
270134
- }, [resolveSkillContent, launchOperator, executeCommand]);
270702
+ }, [resolveSkillContent, launchOperator, executeCommand, pushHistory]);
270135
270703
  const skillItems = skills.slice(0, 5).map((s) => ({
270136
270704
  cmd: `/${slugify(s.name)}`,
270137
270705
  desc: s.description || "skill"
@@ -270272,6 +270840,7 @@ function HomeView({ onNavigate, onStartSession }) {
270272
270840
  autocompleteOptions,
270273
270841
  enableCommands: true,
270274
270842
  onCommandExecute: handleCommandExecute,
270843
+ commandHistory,
270275
270844
  showPromptIndicator: true
270276
270845
  }, undefined, false, undefined, this),
270277
270846
  hintMessage && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
@@ -270333,10 +270902,10 @@ function HomeView({ onNavigate, onStartSession }) {
270333
270902
  }
270334
270903
 
270335
270904
  // src/tui/components/chat/config-view.tsx
270336
- var import_react36 = __toESM(require_react(), 1);
270905
+ var import_react35 = __toESM(require_react(), 1);
270337
270906
 
270338
270907
  // src/tui/components/model-picker/ModelPicker.tsx
270339
- var import_react34 = __toESM(require_react(), 1);
270908
+ var import_react33 = __toESM(require_react(), 1);
270340
270909
  var providerNames = {
270341
270910
  anthropic: "Claude",
270342
270911
  openai: "OpenAI",
@@ -270365,18 +270934,18 @@ function ModelPicker({
270365
270934
  isModelUserSelected = false
270366
270935
  }) {
270367
270936
  const { colors: colors2 } = useTheme();
270368
- const [availableModels, setAvailableModels] = import_react34.useState([]);
270369
- const [searchQuery, setSearchQuery] = import_react34.useState("");
270370
- const [expandedProviders, setExpandedProviders] = import_react34.useState(new Set(["anthropic"]));
270371
- const [focusedIndex, setFocusedIndex] = import_react34.useState(0);
270372
- const [localUrl, setLocalUrl] = import_react34.useState(config2?.localModelUrl ?? "");
270373
- const [localModelName, setLocalModelName] = import_react34.useState(config2?.localModelName ?? "");
270374
- const [editingLocalField, setEditingLocalField] = import_react34.useState(null);
270375
- import_react34.useEffect(() => {
270937
+ const [availableModels, setAvailableModels] = import_react33.useState([]);
270938
+ const [searchQuery, setSearchQuery] = import_react33.useState("");
270939
+ const [expandedProviders, setExpandedProviders] = import_react33.useState(new Set(["anthropic"]));
270940
+ const [focusedIndex, setFocusedIndex] = import_react33.useState(0);
270941
+ const [localUrl, setLocalUrl] = import_react33.useState(config2?.localModelUrl ?? "");
270942
+ const [localModelName, setLocalModelName] = import_react33.useState(config2?.localModelName ?? "");
270943
+ const [editingLocalField, setEditingLocalField] = import_react33.useState(null);
270944
+ import_react33.useEffect(() => {
270376
270945
  setLocalUrl(config2?.localModelUrl ?? "");
270377
270946
  setLocalModelName(config2?.localModelName ?? "");
270378
270947
  }, [config2?.localModelUrl, config2?.localModelName]);
270379
- import_react34.useEffect(() => {
270948
+ import_react33.useEffect(() => {
270380
270949
  if (config2) {
270381
270950
  const models = getAvailableModels(config2);
270382
270951
  setAvailableModels(models);
@@ -270388,7 +270957,7 @@ function ModelPicker({
270388
270957
  }
270389
270958
  }
270390
270959
  }, [config2, selectedModel.id]);
270391
- const groupedModels = import_react34.useMemo(() => {
270960
+ const groupedModels = import_react33.useMemo(() => {
270392
270961
  const groups = {};
270393
270962
  const query = searchQuery.toLowerCase().trim();
270394
270963
  for (const m2 of availableModels) {
@@ -270402,7 +270971,7 @@ function ModelPicker({
270402
270971
  }
270403
270972
  return groups;
270404
270973
  }, [availableModels, searchQuery]);
270405
- const navigationItems = import_react34.useMemo(() => {
270974
+ const navigationItems = import_react33.useMemo(() => {
270406
270975
  const items = [];
270407
270976
  for (const provider of providerOrder) {
270408
270977
  if (provider === "local") {
@@ -270431,16 +271000,16 @@ function ModelPicker({
270431
271000
  }
270432
271001
  return items;
270433
271002
  }, [groupedModels, expandedProviders]);
270434
- import_react34.useEffect(() => {
271003
+ import_react33.useEffect(() => {
270435
271004
  const idx = navigationItems.findIndex((item) => item.type === "model" && item.model.id === selectedModel.id);
270436
271005
  if (idx !== -1) {
270437
271006
  setFocusedIndex(idx);
270438
271007
  }
270439
271008
  }, [selectedModel.id, navigationItems]);
270440
- import_react34.useEffect(() => {
271009
+ import_react33.useEffect(() => {
270441
271010
  setFocusedIndex((prev) => Math.min(prev, Math.max(0, navigationItems.length - 1)));
270442
271011
  }, [navigationItems.length]);
270443
- const commitLocalConfig = import_react34.useCallback((url, modelName) => {
271012
+ const commitLocalConfig = import_react33.useCallback((url, modelName) => {
270444
271013
  if (!onConfigUpdate)
270445
271014
  return;
270446
271015
  const update4 = {
@@ -270449,11 +271018,11 @@ function ModelPicker({
270449
271018
  };
270450
271019
  onConfigUpdate(update4);
270451
271020
  }, [onConfigUpdate]);
270452
- const finishEditing = import_react34.useCallback(() => {
271021
+ const finishEditing = import_react33.useCallback(() => {
270453
271022
  setEditingLocalField(null);
270454
271023
  commitLocalConfig(localUrl, localModelName);
270455
271024
  }, [localUrl, localModelName, commitLocalConfig]);
270456
- const handleKeyboard = import_react34.useCallback((key) => {
271025
+ const handleKeyboard = import_react33.useCallback((key) => {
270457
271026
  if (!focused)
270458
271027
  return false;
270459
271028
  if (editingLocalField) {
@@ -270718,16 +271287,16 @@ function ModelPicker({
270718
271287
  // src/tui/components/chat/config-view.tsx
270719
271288
  function ConfigView({ config: config2, onBack, onStart }) {
270720
271289
  const { colors: colors2 } = useTheme();
270721
- const [targetUrl, setTargetUrl] = import_react36.useState("https://");
270722
- const [strictScope, setStrictScope] = import_react36.useState(true);
270723
- const [selectedModel, setSelectedModel] = import_react36.useState({
271290
+ const [targetUrl, setTargetUrl] = import_react35.useState("https://");
271291
+ const [strictScope, setStrictScope] = import_react35.useState(true);
271292
+ const [selectedModel, setSelectedModel] = import_react35.useState({
270724
271293
  id: "claude-sonnet-4-20250514",
270725
271294
  name: "Claude Sonnet 4",
270726
271295
  provider: "anthropic"
270727
271296
  });
270728
- const [isModelUserSelected, setIsModelUserSelected] = import_react36.useState(false);
270729
- const [focusedField, setFocusedField] = import_react36.useState("url");
270730
- import_react36.useEffect(() => {
271297
+ const [isModelUserSelected, setIsModelUserSelected] = import_react35.useState(false);
271298
+ const [focusedField, setFocusedField] = import_react35.useState("url");
271299
+ import_react35.useEffect(() => {
270731
271300
  if (config2) {
270732
271301
  const models = getAvailableModels(config2);
270733
271302
  if (models.length > 0 && !isModelUserSelected) {
@@ -270773,7 +271342,7 @@ function ConfigView({ config: config2, onBack, onStart }) {
270773
271342
  return;
270774
271343
  }
270775
271344
  });
270776
- const handleModelSelect = import_react36.useCallback((model) => {
271345
+ const handleModelSelect = import_react35.useCallback((model) => {
270777
271346
  setSelectedModel(model);
270778
271347
  setIsModelUserSelected(true);
270779
271348
  }, []);
@@ -270949,11 +271518,11 @@ function ChatApp({
270949
271518
  }) {
270950
271519
  const config2 = useConfig();
270951
271520
  const { model } = useAgent();
270952
- const [currentView, setCurrentView] = import_react38.useState(initialView);
270953
- const [activeSession, setActiveSession] = import_react38.useState(null);
270954
- const [sessionModel, setSessionModel] = import_react38.useState(model);
270955
- const [initialDirective, setInitialDirective] = import_react38.useState(undefined);
270956
- import_react38.useEffect(() => {
271521
+ const [currentView, setCurrentView] = import_react37.useState(initialView);
271522
+ const [activeSession, setActiveSession] = import_react37.useState(null);
271523
+ const [sessionModel, setSessionModel] = import_react37.useState(model);
271524
+ const [initialDirective, setInitialDirective] = import_react37.useState(undefined);
271525
+ import_react37.useEffect(() => {
270957
271526
  if (initialSessionId) {
270958
271527
  sessions.get(initialSessionId).then((session) => {
270959
271528
  if (session) {
@@ -270963,7 +271532,7 @@ function ChatApp({
270963
271532
  });
270964
271533
  }
270965
271534
  }, [initialSessionId]);
270966
- const handleNavigate = import_react38.useCallback((view, options) => {
271535
+ const handleNavigate = import_react37.useCallback((view, options) => {
270967
271536
  if (view === "chat" && options?.sessionId) {
270968
271537
  sessions.get(options.sessionId).then((session) => {
270969
271538
  if (session) {
@@ -270975,7 +271544,7 @@ function ChatApp({
270975
271544
  setCurrentView(view);
270976
271545
  }
270977
271546
  }, []);
270978
- const handleStartSession = import_react38.useCallback(async (directive) => {
271547
+ const handleStartSession = import_react37.useCallback(async (directive) => {
270979
271548
  const session = await sessions.create({
270980
271549
  name: `exploration-${Date.now()}`,
270981
271550
  targets: []
@@ -270984,7 +271553,7 @@ function ChatApp({
270984
271553
  setInitialDirective(directive);
270985
271554
  setCurrentView("chat");
270986
271555
  }, []);
270987
- const handleConfigSubmit = import_react38.useCallback(async (configData) => {
271556
+ const handleConfigSubmit = import_react37.useCallback(async (configData) => {
270988
271557
  const hostname = parseHostFromTarget(configData.targetUrl);
270989
271558
  const timestamp = new Date().toISOString().split("T")[0];
270990
271559
  const sessionName = `${hostname}-${timestamp}`;
@@ -271007,12 +271576,12 @@ function ChatApp({
271007
271576
  setSessionModel(configData.model);
271008
271577
  setCurrentView("chat");
271009
271578
  }, []);
271010
- const handleExitChat = import_react38.useCallback(() => {
271579
+ const handleExitChat = import_react37.useCallback(() => {
271011
271580
  setCurrentView("home");
271012
271581
  setActiveSession(null);
271013
271582
  setInitialDirective(undefined);
271014
271583
  }, []);
271015
- const handleBackFromConfig = import_react38.useCallback(() => {
271584
+ const handleBackFromConfig = import_react37.useCallback(() => {
271016
271585
  setCurrentView("home");
271017
271586
  }, []);
271018
271587
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
@@ -271044,7 +271613,7 @@ function parseHostFromTarget(target) {
271044
271613
  var chat_default = ChatApp;
271045
271614
 
271046
271615
  // src/tui/components/commands/operator-wizard.tsx
271047
- var import_react39 = __toESM(require_react(), 1);
271616
+ var import_react38 = __toESM(require_react(), 1);
271048
271617
  var providerOrder2 = ["anthropic", "openai", "openrouter", "bedrock"];
271049
271618
  function HITLWizard(props) {
271050
271619
  const { colors: colors2 } = useTheme();
@@ -271052,18 +271621,18 @@ function HITLWizard(props) {
271052
271621
  const route = useRoute();
271053
271622
  const config2 = useConfig();
271054
271623
  const { model, setModel, isModelUserSelected } = useAgent();
271055
- const [currentStep, setCurrentStep] = import_react39.useState("config");
271056
- const [state, setState] = import_react39.useState(() => ({
271624
+ const [currentStep, setCurrentStep] = import_react38.useState("config");
271625
+ const [state, setState] = import_react38.useState(() => ({
271057
271626
  name: initialName || generateRandomName(),
271058
271627
  target: initialTarget || "",
271059
271628
  requireApproval: initialRequireApproval ?? true
271060
271629
  }));
271061
- const [focusedField, setFocusedField] = import_react39.useState(0);
271062
- const [error, setError] = import_react39.useState(null);
271063
- const [availableModels, setAvailableModels] = import_react39.useState([]);
271064
- const [modelSearchQuery, setModelSearchQuery] = import_react39.useState("");
271065
- const [expandedProviders, setExpandedProviders] = import_react39.useState(new Set(["anthropic"]));
271066
- import_react39.useEffect(() => {
271630
+ const [focusedField, setFocusedField] = import_react38.useState(0);
271631
+ const [error, setError] = import_react38.useState(null);
271632
+ const [availableModels, setAvailableModels] = import_react38.useState([]);
271633
+ const [modelSearchQuery, setModelSearchQuery] = import_react38.useState("");
271634
+ const [expandedProviders, setExpandedProviders] = import_react38.useState(new Set(["anthropic"]));
271635
+ import_react38.useEffect(() => {
271067
271636
  if (config2.data) {
271068
271637
  const models = getAvailableModels(config2.data);
271069
271638
  setAvailableModels(models);
@@ -271083,7 +271652,7 @@ function HITLWizard(props) {
271083
271652
  }
271084
271653
  }
271085
271654
  }, [config2.data, model.id, initialModel]);
271086
- const groupedModels = import_react39.useMemo(() => {
271655
+ const groupedModels = import_react38.useMemo(() => {
271087
271656
  const groups = {};
271088
271657
  const query = modelSearchQuery.toLowerCase().trim();
271089
271658
  for (const m2 of availableModels) {
@@ -271096,7 +271665,7 @@ function HITLWizard(props) {
271096
271665
  }
271097
271666
  return groups;
271098
271667
  }, [availableModels, modelSearchQuery]);
271099
- const visibleModels = import_react39.useMemo(() => {
271668
+ const visibleModels = import_react38.useMemo(() => {
271100
271669
  const result = [];
271101
271670
  for (const provider of providerOrder2) {
271102
271671
  const models = groupedModels[provider];
@@ -271364,11 +271933,11 @@ function HITLWizard(props) {
271364
271933
  }
271365
271934
 
271366
271935
  // src/tui/components/commands/web-wizard.tsx
271367
- var import_react42 = __toESM(require_react(), 1);
271936
+ var import_react41 = __toESM(require_react(), 1);
271368
271937
 
271369
271938
  // src/tui/components/input.tsx
271370
- var import_react41 = __toESM(require_react(), 1);
271371
- var Input = import_react41.forwardRef(function Input2(opts, ref) {
271939
+ var import_react40 = __toESM(require_react(), 1);
271940
+ var Input = import_react40.forwardRef(function Input2(opts, ref) {
271372
271941
  const { colors: colors2 } = useTheme();
271373
271942
  const { label, focused = true, description, ...inputProps } = opts;
271374
271943
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
@@ -271422,10 +271991,10 @@ function WebWizard({
271422
271991
  const route = useRoute();
271423
271992
  const config2 = useConfig();
271424
271993
  const { model, setModel, isModelUserSelected } = useAgent();
271425
- const [availableModels, setAvailableModels] = import_react42.useState([]);
271426
- const [selectedModelIndex, setSelectedModelIndex] = import_react42.useState(0);
271427
- const [modelSearchQuery, setModelSearchQuery] = import_react42.useState("");
271428
- const [expandedProviders, setExpandedProviders] = import_react42.useState(new Set(["anthropic"]));
271994
+ const [availableModels, setAvailableModels] = import_react41.useState([]);
271995
+ const [selectedModelIndex, setSelectedModelIndex] = import_react41.useState(0);
271996
+ const [modelSearchQuery, setModelSearchQuery] = import_react41.useState("");
271997
+ const [expandedProviders, setExpandedProviders] = import_react41.useState(new Set(["anthropic"]));
271429
271998
  const providerNames2 = {
271430
271999
  anthropic: "Claude",
271431
272000
  openai: "OpenAI",
@@ -271433,7 +272002,7 @@ function WebWizard({
271433
272002
  bedrock: "Bedrock"
271434
272003
  };
271435
272004
  const providerOrder3 = ["anthropic", "openai", "openrouter", "bedrock"];
271436
- const groupedModels = import_react42.useMemo(() => {
272005
+ const groupedModels = import_react41.useMemo(() => {
271437
272006
  const groups = {};
271438
272007
  const query = modelSearchQuery.toLowerCase().trim();
271439
272008
  for (const m2 of availableModels) {
@@ -271447,7 +272016,7 @@ function WebWizard({
271447
272016
  }
271448
272017
  return groups;
271449
272018
  }, [availableModels, modelSearchQuery]);
271450
- const visibleModels = import_react42.useMemo(() => {
272019
+ const visibleModels = import_react41.useMemo(() => {
271451
272020
  const result = [];
271452
272021
  for (const provider of providerOrder3) {
271453
272022
  const models = groupedModels[provider];
@@ -271459,7 +272028,7 @@ function WebWizard({
271459
272028
  }
271460
272029
  return result;
271461
272030
  }, [groupedModels, expandedProviders]);
271462
- import_react42.useEffect(() => {
272031
+ import_react41.useEffect(() => {
271463
272032
  if (config2.data) {
271464
272033
  const models = getAvailableModels(config2.data);
271465
272034
  setAvailableModels(models);
@@ -271488,8 +272057,8 @@ function WebWizard({
271488
272057
  }
271489
272058
  }, [config2.data, model.id, initialModel]);
271490
272059
  const initialStep = initialTarget ? "configure" : "target";
271491
- const [currentStep, setCurrentStep] = import_react42.useState(initialStep);
271492
- const [state, setState] = import_react42.useState(() => ({
272060
+ const [currentStep, setCurrentStep] = import_react41.useState(initialStep);
272061
+ const [state, setState] = import_react41.useState(() => ({
271493
272062
  name: initialName || generateRandomName(),
271494
272063
  target: initialTarget || "",
271495
272064
  sourceCodeAccess: false,
@@ -271511,14 +272080,14 @@ function WebWizard({
271511
272080
  customHeaders: initialCustomHeaders || {}
271512
272081
  }
271513
272082
  }));
271514
- const [targetFocusedField, setTargetFocusedField] = import_react42.useState(0);
271515
- const [focusedSection, setFocusedSection] = import_react42.useState(0);
271516
- const [focusedField, setFocusedField] = import_react42.useState(0);
271517
- const [hostInput, setHostInput] = import_react42.useState("");
271518
- const [portInput, setPortInput] = import_react42.useState("");
271519
- const [headerNameInput, setHeaderNameInput] = import_react42.useState("");
271520
- const [headerValueInput, setHeaderValueInput] = import_react42.useState("");
271521
- const [error, setError] = import_react42.useState(null);
272083
+ const [targetFocusedField, setTargetFocusedField] = import_react41.useState(0);
272084
+ const [focusedSection, setFocusedSection] = import_react41.useState(0);
272085
+ const [focusedField, setFocusedField] = import_react41.useState(0);
272086
+ const [hostInput, setHostInput] = import_react41.useState("");
272087
+ const [portInput, setPortInput] = import_react41.useState("");
272088
+ const [headerNameInput, setHeaderNameInput] = import_react41.useState("");
272089
+ const [headerValueInput, setHeaderValueInput] = import_react41.useState("");
272090
+ const [error, setError] = import_react41.useState(null);
271522
272091
  async function createSessionAndNavigate() {
271523
272092
  if (!state.target.trim())
271524
272093
  return;
@@ -272465,10 +273034,10 @@ function WebWizard({
272465
273034
  }
272466
273035
 
272467
273036
  // src/tui/components/commands/provider-manager.tsx
272468
- var import_react48 = __toESM(require_react(), 1);
273037
+ var import_react47 = __toESM(require_react(), 1);
272469
273038
  init_config2();
272470
273039
  // src/tui/components/commands/provider-selection.tsx
272471
- var import_react45 = __toESM(require_react(), 1);
273040
+ var import_react44 = __toESM(require_react(), 1);
272472
273041
  function ProviderSelection({
272473
273042
  onProviderSelected,
272474
273043
  onClose
@@ -272476,7 +273045,7 @@ function ProviderSelection({
272476
273045
  const { colors: colors2 } = useTheme();
272477
273046
  const route = useRoute();
272478
273047
  const _config = useConfig();
272479
- const [highlightedIndex, setHighlightedIndex] = import_react45.useState(0);
273048
+ const [highlightedIndex, setHighlightedIndex] = import_react44.useState(0);
272480
273049
  const configuredProviders = getConfiguredProviders(_config.data);
272481
273050
  useKeyboard((key) => {
272482
273051
  if (key.name === "escape") {
@@ -272629,7 +273198,7 @@ function ProviderSelection({
272629
273198
  }
272630
273199
 
272631
273200
  // src/tui/components/commands/api-key-input.tsx
272632
- var import_react47 = __toESM(require_react(), 1);
273201
+ var import_react46 = __toESM(require_react(), 1);
272633
273202
  function APIKeyInput({
272634
273203
  provider,
272635
273204
  providerName,
@@ -272637,7 +273206,7 @@ function APIKeyInput({
272637
273206
  onCancel
272638
273207
  }) {
272639
273208
  const { colors: colors2 } = useTheme();
272640
- const [apiKey, setApiKey] = import_react47.useState("");
273209
+ const [apiKey, setApiKey] = import_react46.useState("");
272641
273210
  useKeyboard((key) => {
272642
273211
  if (key.name === "escape") {
272643
273212
  onCancel();
@@ -272753,8 +273322,8 @@ function APIKeyInput({
272753
273322
  function ProviderManager() {
272754
273323
  const route = useRoute();
272755
273324
  const _config = useConfig();
272756
- const [flowState, setFlowState] = import_react48.useState("selecting");
272757
- const [selectedProvider, setSelectedProvider] = import_react48.useState(null);
273325
+ const [flowState, setFlowState] = import_react47.useState("selecting");
273326
+ const [selectedProvider, setSelectedProvider] = import_react47.useState(null);
272758
273327
  const handleProviderSelected = (providerId) => {
272759
273328
  setSelectedProvider(providerId);
272760
273329
  setFlowState("inputting");
@@ -272818,7 +273387,7 @@ function ProviderManager() {
272818
273387
  init_config2();
272819
273388
 
272820
273389
  // src/tui/components/switch.tsx
272821
- var import_react49 = __toESM(require_react(), 1);
273390
+ var import_react48 = __toESM(require_react(), 1);
272822
273391
  var CaseSymbol = Symbol("Switch.Case");
272823
273392
  var DefaultSymbol = Symbol("Switch.Default");
272824
273393
  function CaseComponent({
@@ -272841,8 +273410,8 @@ function SwitchComponent({
272841
273410
  }) {
272842
273411
  let matchedChild = null;
272843
273412
  let defaultChild = null;
272844
- import_react49.default.Children.forEach(children, (child) => {
272845
- if (import_react49.default.isValidElement(child)) {
273413
+ import_react48.default.Children.forEach(children, (child) => {
273414
+ if (import_react48.default.isValidElement(child)) {
272846
273415
  if (child.type[CaseSymbol]) {
272847
273416
  const caseChild = child;
272848
273417
  if (caseChild.props.when === condition) {
@@ -272955,8 +273524,8 @@ function ResponsibleUseDisclosure({
272955
273524
  }
272956
273525
 
272957
273526
  // src/tui/context/toast.tsx
272958
- var import_react51 = __toESM(require_react(), 1);
272959
- var ToastContext = import_react51.createContext(null);
273527
+ var import_react50 = __toESM(require_react(), 1);
273528
+ var ToastContext = import_react50.createContext(null);
272960
273529
  var nextId = 0;
272961
273530
  var DEFAULT_DURATION = {
272962
273531
  default: 3000,
@@ -272964,24 +273533,24 @@ var DEFAULT_DURATION = {
272964
273533
  error: 5000
272965
273534
  };
272966
273535
  function ToastProvider({ children }) {
272967
- const [toasts, setToasts] = import_react51.useState([]);
272968
- const dismiss = import_react51.useCallback((id) => {
273536
+ const [toasts, setToasts] = import_react50.useState([]);
273537
+ const dismiss = import_react50.useCallback((id) => {
272969
273538
  setToasts((prev) => prev.filter((t2) => t2.id !== id));
272970
273539
  }, []);
272971
- const toast = import_react51.useCallback((message, variant = "default", duration) => {
273540
+ const toast = import_react50.useCallback((message, variant = "default", duration) => {
272972
273541
  const id = nextId++;
272973
273542
  const ms = duration ?? DEFAULT_DURATION[variant];
272974
273543
  setToasts((prev) => [...prev, { id, message, variant, duration: ms }]);
272975
273544
  setTimeout(() => dismiss(id), ms);
272976
273545
  }, [dismiss]);
272977
- const value = import_react51.useMemo(() => ({ toasts, toast, dismiss }), [toasts, toast, dismiss]);
273546
+ const value = import_react50.useMemo(() => ({ toasts, toast, dismiss }), [toasts, toast, dismiss]);
272978
273547
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastContext.Provider, {
272979
273548
  value,
272980
273549
  children
272981
273550
  }, undefined, false, undefined, this);
272982
273551
  }
272983
273552
  function useToast() {
272984
- const ctx4 = import_react51.useContext(ToastContext);
273553
+ const ctx4 = import_react50.useContext(ToastContext);
272985
273554
  if (!ctx4)
272986
273555
  throw new Error("useToast() must be used within <ToastProvider>");
272987
273556
  return ctx4;
@@ -273054,11 +273623,11 @@ function ToastContainer() {
273054
273623
  }
273055
273624
 
273056
273625
  // src/tui/components/error-boundary.tsx
273057
- var import_react53 = __toESM(require_react(), 1);
273626
+ var import_react52 = __toESM(require_react(), 1);
273058
273627
  var MAX_ERRORS = 3;
273059
273628
  var ERROR_WINDOW_MS = 5000;
273060
273629
 
273061
- class ErrorBoundaryInner extends import_react53.default.Component {
273630
+ class ErrorBoundaryInner extends import_react52.default.Component {
273062
273631
  state = {
273063
273632
  hasError: false,
273064
273633
  errorTimestamps: [],
@@ -273089,10 +273658,10 @@ class ErrorBoundaryInner extends import_react53.default.Component {
273089
273658
  }
273090
273659
  function ErrorBoundary2({ children }) {
273091
273660
  const { toast } = useToast();
273092
- const handleError = import_react53.useCallback((message) => {
273661
+ const handleError = import_react52.useCallback((message) => {
273093
273662
  toast(message, "error");
273094
273663
  }, [toast]);
273095
- return import_react53.default.createElement(ErrorBoundaryInner, { onError: handleError }, children);
273664
+ return import_react52.default.createElement(ErrorBoundaryInner, { onError: handleError }, children);
273096
273665
  }
273097
273666
 
273098
273667
  // src/tui/index.tsx
@@ -273203,16 +273772,16 @@ function ShortcutsDialog({
273203
273772
  }
273204
273773
 
273205
273774
  // src/tui/components/commands/help-dialog.tsx
273206
- var import_react55 = __toESM(require_react(), 1);
273775
+ var import_react54 = __toESM(require_react(), 1);
273207
273776
  function HelpDialog() {
273208
273777
  const { colors: colors2 } = useTheme();
273209
273778
  const { commands: commands2 } = useCommand();
273210
273779
  const route = useRoute();
273211
273780
  const dimensions = useTerminalDimensions();
273212
- const [selectedIndex, setSelectedIndex] = import_react55.useState(0);
273213
- const [showDetail, setShowDetail] = import_react55.useState(false);
273214
- const scrollboxRef = import_react55.useRef(null);
273215
- const commandsByCategory = import_react55.useMemo(() => {
273781
+ const [selectedIndex, setSelectedIndex] = import_react54.useState(0);
273782
+ const [showDetail, setShowDetail] = import_react54.useState(false);
273783
+ const scrollboxRef = import_react54.useRef(null);
273784
+ const commandsByCategory = import_react54.useMemo(() => {
273216
273785
  const grouped = {};
273217
273786
  for (const cmd of commands2) {
273218
273787
  const category = cmd.category || "Other";
@@ -273223,15 +273792,15 @@ function HelpDialog() {
273223
273792
  }
273224
273793
  return grouped;
273225
273794
  }, [commands2]);
273226
- const flatCommands = import_react55.useMemo(() => {
273795
+ const flatCommands = import_react54.useMemo(() => {
273227
273796
  return commands2;
273228
273797
  }, [commands2]);
273229
- import_react55.useEffect(() => {
273798
+ import_react54.useEffect(() => {
273230
273799
  if (selectedIndex >= flatCommands.length) {
273231
273800
  setSelectedIndex(Math.max(0, flatCommands.length - 1));
273232
273801
  }
273233
273802
  }, [flatCommands.length, selectedIndex]);
273234
- import_react55.useEffect(() => {
273803
+ import_react54.useEffect(() => {
273235
273804
  scrollToIndex(scrollboxRef.current, selectedIndex, flatCommands, (cmd) => cmd.name);
273236
273805
  }, [selectedIndex, flatCommands]);
273237
273806
  const handleClose = () => {
@@ -273666,24 +274235,24 @@ function ModelsDisplay() {
273666
274235
  }
273667
274236
 
273668
274237
  // src/tui/components/commands/auth-flow.tsx
273669
- var import_react58 = __toESM(require_react(), 1);
274238
+ var import_react57 = __toESM(require_react(), 1);
273670
274239
  init_config2();
273671
274240
  function AuthFlow() {
273672
274241
  const route = useRoute();
273673
274242
  const appConfig = useConfig();
273674
274243
  const isConnected = !!(appConfig.data.accessToken || appConfig.data.pensarAPIKey);
273675
- const [step, setStep] = import_react58.useState(isConnected ? "success" : "start");
273676
- const [error, setError] = import_react58.useState(null);
273677
- const [authMode, setAuthMode] = import_react58.useState(null);
273678
- const [deviceInfo, setDeviceInfo] = import_react58.useState(null);
273679
- const [legacyDeviceInfo, setLegacyDeviceInfo] = import_react58.useState(null);
273680
- const [workspaces, setWorkspaces] = import_react58.useState([]);
273681
- const [selectedWorkspace, setSelectedWorkspace] = import_react58.useState(null);
273682
- const [selectedIndex, setSelectedIndex] = import_react58.useState(0);
273683
- const [billingUrl, setBillingUrl] = import_react58.useState(null);
273684
- const [balance, setBalance] = import_react58.useState(null);
273685
- const pollingRef = import_react58.useRef(null);
273686
- const cancelledRef = import_react58.useRef(false);
274244
+ const [step, setStep] = import_react57.useState(isConnected ? "success" : "start");
274245
+ const [error, setError] = import_react57.useState(null);
274246
+ const [authMode, setAuthMode] = import_react57.useState(null);
274247
+ const [deviceInfo, setDeviceInfo] = import_react57.useState(null);
274248
+ const [legacyDeviceInfo, setLegacyDeviceInfo] = import_react57.useState(null);
274249
+ const [workspaces, setWorkspaces] = import_react57.useState([]);
274250
+ const [selectedWorkspace, setSelectedWorkspace] = import_react57.useState(null);
274251
+ const [selectedIndex, setSelectedIndex] = import_react57.useState(0);
274252
+ const [billingUrl, setBillingUrl] = import_react57.useState(null);
274253
+ const [balance, setBalance] = import_react57.useState(null);
274254
+ const pollingRef = import_react57.useRef(null);
274255
+ const cancelledRef = import_react57.useRef(false);
273687
274256
  const connectedWorkspace = appConfig.data.workspaceSlug ? { name: appConfig.data.workspaceSlug, slug: appConfig.data.workspaceSlug } : null;
273688
274257
  const goHome = () => {
273689
274258
  route.navigate({ type: "base", path: "home" });
@@ -273695,7 +274264,7 @@ function AuthFlow() {
273695
274264
  pollingRef.current = null;
273696
274265
  }
273697
274266
  };
273698
- import_react58.useEffect(() => {
274267
+ import_react57.useEffect(() => {
273699
274268
  return cleanup;
273700
274269
  }, []);
273701
274270
  const openUrl = (url) => {
@@ -274297,14 +274866,14 @@ function AuthFlow() {
274297
274866
  }
274298
274867
 
274299
274868
  // src/tui/components/commands/credits-flow.tsx
274300
- var import_react60 = __toESM(require_react(), 1);
274869
+ var import_react59 = __toESM(require_react(), 1);
274301
274870
  init_tokenRefresh();
274302
274871
  function CreditsFlow() {
274303
274872
  const route = useRoute();
274304
274873
  const appConfig = useConfig();
274305
- const [step, setStep] = import_react60.useState("loading");
274306
- const [credits, setCredits] = import_react60.useState(null);
274307
- const [error, setError] = import_react60.useState(null);
274874
+ const [step, setStep] = import_react59.useState("loading");
274875
+ const [credits, setCredits] = import_react59.useState(null);
274876
+ const [error, setError] = import_react59.useState(null);
274308
274877
  const creditsUrl = `${getPensarConsoleUrl()}/credits`;
274309
274878
  const goHome = () => {
274310
274879
  route.navigate({ type: "base", path: "home" });
@@ -274362,7 +274931,7 @@ function CreditsFlow() {
274362
274931
  setStep("display");
274363
274932
  }
274364
274933
  };
274365
- import_react60.useEffect(() => {
274934
+ import_react59.useEffect(() => {
274366
274935
  fetchBalance();
274367
274936
  }, []);
274368
274937
  useKeyboard((key) => {
@@ -274601,10 +275170,10 @@ function CreditsFlow() {
274601
275170
  }
274602
275171
 
274603
275172
  // src/tui/context/keybinding.tsx
274604
- var import_react66 = __toESM(require_react(), 1);
275173
+ var import_react65 = __toESM(require_react(), 1);
274605
275174
 
274606
275175
  // src/tui/keybindings/keybind.tsx
274607
- var import_react62 = __toESM(require_react(), 1);
275176
+ var import_react61 = __toESM(require_react(), 1);
274608
275177
 
274609
275178
  // src/tui/keybindings/actions.ts
274610
275179
  var movementActions = [
@@ -274856,7 +275425,7 @@ var allActions = [
274856
275425
  var actionsByKey = new Map(allActions.map((action) => [action.key, action]));
274857
275426
  var actionsById = new Map(allActions.map((action) => [action.id, action]));
274858
275427
  // src/tui/keybindings/keybind.tsx
274859
- var LeaderKeyContext = import_react62.createContext(null);
275428
+ var LeaderKeyContext = import_react61.createContext(null);
274860
275429
  // src/tui/keybindings/registry.ts
274861
275430
  function createKeybindings(deps) {
274862
275431
  const {
@@ -275038,13 +275607,12 @@ function matchesKeybind(pressed, combo) {
275038
275607
  }
275039
275608
 
275040
275609
  // src/tui/context/keybinding.tsx
275041
- var KeybindingContext = import_react66.createContext(undefined);
275610
+ var KeybindingContext = import_react65.createContext(undefined);
275042
275611
  function KeybindingProvider({
275043
275612
  children,
275044
275613
  deps
275045
275614
  }) {
275046
275615
  const { promptRef, refocusPrompt } = useFocus();
275047
- const { isInputEmpty } = useInput();
275048
275616
  const { setExternalDialogOpen } = useDialog();
275049
275617
  const registry = createKeybindings({
275050
275618
  ...deps,
@@ -275060,7 +275628,9 @@ function KeybindingProvider({
275060
275628
  if (binding.combo.toLowerCase().startsWith("shift") || binding.combo.toLowerCase() === "?") {
275061
275629
  const textareaRef = promptRef.current?.getTextareaRef();
275062
275630
  const isInputFocused = textareaRef && !textareaRef.isDestroyed && textareaRef.focused;
275063
- if (!isInputFocused || !isInputEmpty) {
275631
+ const actualValue = promptRef.current?.getValue() ?? "";
275632
+ const isPromptEmpty = actualValue.trim().length === 0;
275633
+ if (!isInputFocused || !isPromptEmpty) {
275064
275634
  continue;
275065
275635
  }
275066
275636
  }
@@ -275077,10 +275647,10 @@ function KeybindingProvider({
275077
275647
  }
275078
275648
 
275079
275649
  // src/tui/components/pentest/pentest.tsx
275080
- var import_react75 = __toESM(require_react(), 1);
275650
+ var import_react74 = __toESM(require_react(), 1);
275081
275651
  init_report();
275082
- import { existsSync as existsSync24, readdirSync as readdirSync6, readFileSync as readFileSync11 } from "fs";
275083
- import { join as join25 } from "path";
275652
+ import { existsSync as existsSync25, readdirSync as readdirSync6, readFileSync as readFileSync12 } from "fs";
275653
+ import { join as join26 } from "path";
275084
275654
 
275085
275655
  // src/core/session/loader.ts
275086
275656
  init_persistence();
@@ -275217,7 +275787,7 @@ Found ${findings.length} vulnerabilities`);
275217
275787
  init_utils2();
275218
275788
 
275219
275789
  // src/tui/components/agent-display.tsx
275220
- var import_react73 = __toESM(require_react(), 1);
275790
+ var import_react72 = __toESM(require_react(), 1);
275221
275791
 
275222
275792
  // node_modules/marked/lib/marked.esm.js
275223
275793
  function L2() {
@@ -276620,7 +277190,11 @@ var TOOL_SUMMARY_MAP = {
276620
277190
  return `${method} ${url2}`;
276621
277191
  },
276622
277192
  crawl: (args) => `crawl ${args.url || args.target || ""}`,
276623
- execute_command: (args) => `$ ${args.command || ""}`,
277193
+ execute_command: (args) => {
277194
+ const cmd = String(args.command || "").split(`
277195
+ `)[0];
277196
+ return cmd.length > 80 ? `$ ${cmd.slice(0, 80)}…` : `$ ${cmd}`;
277197
+ },
276624
277198
  read_file: (args) => `read ${args.path || ""}`,
276625
277199
  Read: (args) => `read ${args.path || args.file_path || ""}`,
276626
277200
  write_file: (args) => `write ${args.path || ""}`,
@@ -276656,6 +277230,7 @@ var TOOL_SUMMARY_MAP = {
276656
277230
  const targets = args.targets;
276657
277231
  return `pentest swarm ×${targets?.length ?? "?"}`;
276658
277232
  },
277233
+ delegate_to_auth_subagent: (args) => `auth ${args.target || ""} — ${args.reason || ""}`,
276659
277234
  scratchpad: () => "note"
276660
277235
  };
276661
277236
  function getToolSummary(toolName, args) {
@@ -277343,14 +277918,14 @@ ${preview}${suffix}` : preview + suffix || "POC passed",
277343
277918
  return null;
277344
277919
  }
277345
277920
  // src/tui/components/shared/ascii-spinner.tsx
277346
- var import_react67 = __toESM(require_react(), 1);
277921
+ var import_react66 = __toESM(require_react(), 1);
277347
277922
  var SPINNER_FRAMES = ["/", "-", "\\", "|"];
277348
277923
  var SPINNER_INTERVAL = 100;
277349
277924
  function AsciiSpinner({ label, fg: fg2 }) {
277350
277925
  const { colors: colors2 } = useTheme();
277351
277926
  const spinnerColor = fg2 ?? colors2.info;
277352
- const [frame, setFrame] = import_react67.useState(0);
277353
- import_react67.useEffect(() => {
277927
+ const [frame, setFrame] = import_react66.useState(0);
277928
+ import_react66.useEffect(() => {
277354
277929
  const interval = setInterval(() => {
277355
277930
  setFrame((f3) => (f3 + 1) % SPINNER_FRAMES.length);
277356
277931
  }, SPINNER_INTERVAL);
@@ -277362,20 +277937,21 @@ function AsciiSpinner({ label, fg: fg2 }) {
277362
277937
  }, undefined, false, undefined, this);
277363
277938
  }
277364
277939
  // src/tui/components/shared/tool-renderer.tsx
277365
- var import_react68 = __toESM(require_react(), 1);
277940
+ var import_react67 = __toESM(require_react(), 1);
277366
277941
  var TOOLS_WITH_LOG_WINDOW = new Set([
277367
277942
  "execute_command",
277368
277943
  "run_attack_surface",
277369
277944
  "spawn_coding_agent",
277370
- "spawn_pentest_swarm"
277945
+ "spawn_pentest_swarm",
277946
+ "delegate_to_auth_subagent"
277371
277947
  ]);
277372
- var ToolRenderer = import_react68.memo(function ToolRenderer2({
277948
+ var ToolRenderer = import_react67.memo(function ToolRenderer2({
277373
277949
  message,
277374
277950
  verbose = false,
277375
277951
  expandedLogs = false
277376
277952
  }) {
277377
277953
  const { colors: colors2 } = useTheme();
277378
- const [showOutput, setShowOutput] = import_react68.useState(false);
277954
+ const [showOutput, setShowOutput] = import_react67.useState(false);
277379
277955
  if (!isToolMessage(message)) {
277380
277956
  return null;
277381
277957
  }
@@ -277504,8 +278080,8 @@ var ToolRenderer = import_react68.memo(function ToolRenderer2({
277504
278080
  }, undefined, true, undefined, this);
277505
278081
  });
277506
278082
  // src/tui/components/shared/message-renderer.tsx
277507
- var import_react69 = __toESM(require_react(), 1);
277508
- var MessageRenderer = import_react69.memo(function MessageRenderer2({
278083
+ var import_react68 = __toESM(require_react(), 1);
278084
+ var MessageRenderer = import_react68.memo(function MessageRenderer2({
277509
278085
  message,
277510
278086
  isStreaming = false,
277511
278087
  verbose = false,
@@ -277515,7 +278091,7 @@ var MessageRenderer = import_react69.memo(function MessageRenderer2({
277515
278091
  }) {
277516
278092
  const { colors: colors2 } = useTheme();
277517
278093
  const content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
277518
- const displayContent = import_react69.useMemo(() => message.role === "assistant" ? markdownToStyledText(content, colors2) : content, [content, message.role, colors2]);
278094
+ const displayContent = import_react68.useMemo(() => message.role === "assistant" ? markdownToStyledText(content, colors2) : content, [content, message.role, colors2]);
277519
278095
  if (isToolMessage(message)) {
277520
278096
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToolRenderer, {
277521
278097
  message,
@@ -277627,9 +278203,9 @@ var MessageRenderer = import_react69.memo(function MessageRenderer2({
277627
278203
  }, undefined, false, undefined, this);
277628
278204
  });
277629
278205
  // src/tui/components/shared/approval-prompt.tsx
277630
- var import_react70 = __toESM(require_react(), 1);
278206
+ var import_react69 = __toESM(require_react(), 1);
277631
278207
  // src/tui/components/shared/message-reducer.ts
277632
- var import_react72 = __toESM(require_react(), 1);
278208
+ var import_react71 = __toESM(require_react(), 1);
277633
278209
  // src/tui/components/agent-display.tsx
277634
278210
  function getStableKey(item, contextId = "root") {
277635
278211
  if ("messages" in item) {
@@ -277705,11 +278281,11 @@ function AgentDisplay({
277705
278281
  ]
277706
278282
  }, undefined, true, undefined, this);
277707
278283
  }
277708
- var SubAgentDisplay = import_react73.memo(function SubAgentDisplay2({
278284
+ var SubAgentDisplay = import_react72.memo(function SubAgentDisplay2({
277709
278285
  subagent
277710
278286
  }) {
277711
278287
  const { colors: colors2 } = useTheme();
277712
- const [open, setOpen] = import_react73.useState(false);
278288
+ const [open, setOpen] = import_react72.useState(false);
277713
278289
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
277714
278290
  height: open ? 40 : "auto",
277715
278291
  onMouseDown: () => setOpen(!open),
@@ -277764,7 +278340,7 @@ var SubAgentDisplay = import_react73.memo(function SubAgentDisplay2({
277764
278340
  ]
277765
278341
  }, undefined, true, undefined, this);
277766
278342
  });
277767
- var AgentMessage = import_react73.memo(function AgentMessage2({
278343
+ var AgentMessage = import_react72.memo(function AgentMessage2({
277768
278344
  message
277769
278345
  }) {
277770
278346
  const { colors: colors2 } = useTheme();
@@ -277873,8 +278449,8 @@ var AgentMessage = import_react73.memo(function AgentMessage2({
277873
278449
  });
277874
278450
  function ToolDetails({ message }) {
277875
278451
  const { colors: colors2 } = useTheme();
277876
- const [showArgs, setShowArgs] = import_react73.useState(false);
277877
- const [showResult, setShowResult] = import_react73.useState(false);
278452
+ const [showArgs, setShowArgs] = import_react72.useState(false);
278453
+ const [showResult, setShowResult] = import_react72.useState(false);
277878
278454
  if (message.role !== "tool") {
277879
278455
  return null;
277880
278456
  }
@@ -277976,28 +278552,28 @@ function Pentest({ sessionId }) {
277976
278552
  const config3 = useConfig();
277977
278553
  const { model, setThinking, setIsExecuting, isExecuting } = useAgent();
277978
278554
  const { stack, externalDialogOpen } = useDialog();
277979
- const [session, setSession] = import_react75.useState(null);
277980
- const [error40, setError] = import_react75.useState(null);
277981
- const [phase, setPhase] = import_react75.useState("loading");
277982
- const [abortController, setAbortController] = import_react75.useState(null);
277983
- const [panelMessages, setPanelMessages] = import_react75.useState([]);
277984
- const panelTextRef = import_react75.useRef("");
277985
- const panelSourceRef = import_react75.useRef(null);
277986
- const [pentestAgents, setPentestAgents] = import_react75.useState({});
277987
- const pentestTextRefs = import_react75.useRef({});
277988
- const [assets, setAssets] = import_react75.useState([]);
277989
- const [viewMode, setViewMode] = import_react75.useState("overview");
277990
- const [selectedAgentId, setSelectedAgentId] = import_react75.useState(null);
277991
- const [focusedIndex, setFocusedIndex] = import_react75.useState(0);
277992
- const [showOrchestratorPanel, setShowOrchestratorPanel] = import_react75.useState(false);
277993
- const [startTime, setStartTime] = import_react75.useState(null);
277994
- const pentestAgentList = import_react75.useMemo(() => Object.values(pentestAgents).sort((a, b3) => a.createdAt.getTime() - b3.createdAt.getTime()), [pentestAgents]);
277995
- const selectedAgent = import_react75.useMemo(() => selectedAgentId ? pentestAgents[selectedAgentId] ?? null : null, [pentestAgents, selectedAgentId]);
278555
+ const [session, setSession] = import_react74.useState(null);
278556
+ const [error40, setError] = import_react74.useState(null);
278557
+ const [phase, setPhase] = import_react74.useState("loading");
278558
+ const [abortController, setAbortController] = import_react74.useState(null);
278559
+ const [panelMessages, setPanelMessages] = import_react74.useState([]);
278560
+ const panelTextRef = import_react74.useRef("");
278561
+ const panelSourceRef = import_react74.useRef(null);
278562
+ const [pentestAgents, setPentestAgents] = import_react74.useState({});
278563
+ const pentestTextRefs = import_react74.useRef({});
278564
+ const [assets, setAssets] = import_react74.useState([]);
278565
+ const [viewMode, setViewMode] = import_react74.useState("overview");
278566
+ const [selectedAgentId, setSelectedAgentId] = import_react74.useState(null);
278567
+ const [focusedIndex, setFocusedIndex] = import_react74.useState(0);
278568
+ const [showOrchestratorPanel, setShowOrchestratorPanel] = import_react74.useState(false);
278569
+ const [startTime, setStartTime] = import_react74.useState(null);
278570
+ const pentestAgentList = import_react74.useMemo(() => Object.values(pentestAgents).sort((a, b3) => a.createdAt.getTime() - b3.createdAt.getTime()), [pentestAgents]);
278571
+ const selectedAgent = import_react74.useMemo(() => selectedAgentId ? pentestAgents[selectedAgentId] ?? null : null, [pentestAgents, selectedAgentId]);
277996
278572
  const { width: termWidth } = useTerminalDimensions();
277997
278573
  const gridAvailableWidth = showOrchestratorPanel ? Math.floor((termWidth - 4) / 2) - 2 : termWidth - ORCHESTRATOR_PANEL_WIDTH - GRID_OUTER_PADDING;
277998
278574
  const gridColumns = Math.max(1, Math.floor((gridAvailableWidth + GRID_GAP) / (CARD_MIN_WIDTH + GRID_GAP)));
277999
- import_react75.useEffect(() => {
278000
- async function load() {
278575
+ import_react74.useEffect(() => {
278576
+ async function load2() {
278001
278577
  try {
278002
278578
  const s2 = await sessions.get(sessionId);
278003
278579
  if (!s2) {
@@ -278041,21 +278617,21 @@ function Pentest({ sessionId }) {
278041
278617
  setPhase("error");
278042
278618
  }
278043
278619
  }
278044
- load();
278620
+ load2();
278045
278621
  }, [sessionId]);
278046
- import_react75.useEffect(() => {
278622
+ import_react74.useEffect(() => {
278047
278623
  if (!session)
278048
278624
  return;
278049
- const assetsPath = join25(session.rootPath, "assets");
278625
+ const assetsPath = join26(session.rootPath, "assets");
278050
278626
  function readAssets() {
278051
- if (!existsSync24(assetsPath))
278627
+ if (!existsSync25(assetsPath))
278052
278628
  return;
278053
278629
  try {
278054
278630
  const files = readdirSync6(assetsPath).filter((f3) => f3.endsWith(".json"));
278055
278631
  const loaded = [];
278056
278632
  for (const file2 of files) {
278057
278633
  try {
278058
- const content = readFileSync11(join25(assetsPath, file2), "utf-8");
278634
+ const content = readFileSync12(join26(assetsPath, file2), "utf-8");
278059
278635
  loaded.push(JSON.parse(content));
278060
278636
  } catch {}
278061
278637
  }
@@ -278066,12 +278642,12 @@ function Pentest({ sessionId }) {
278066
278642
  const interval = setInterval(readAssets, 2000);
278067
278643
  return () => clearInterval(interval);
278068
278644
  }, [session]);
278069
- import_react75.useEffect(() => {
278645
+ import_react74.useEffect(() => {
278070
278646
  return () => {
278071
278647
  abortController?.abort();
278072
278648
  };
278073
278649
  }, [abortController]);
278074
- const ensurePentestAgent = import_react75.useCallback((subagentId) => {
278650
+ const ensurePentestAgent = import_react74.useCallback((subagentId) => {
278075
278651
  setPentestAgents((prev) => {
278076
278652
  if (prev[subagentId])
278077
278653
  return prev;
@@ -278088,7 +278664,7 @@ function Pentest({ sessionId }) {
278088
278664
  };
278089
278665
  });
278090
278666
  }, []);
278091
- const handleSubagentSpawn = import_react75.useCallback(({
278667
+ const handleSubagentSpawn = import_react74.useCallback(({
278092
278668
  subagentId,
278093
278669
  input
278094
278670
  }) => {
@@ -278108,7 +278684,7 @@ function Pentest({ sessionId }) {
278108
278684
  }
278109
278685
  }));
278110
278686
  }, []);
278111
- const handleSubagentComplete = import_react75.useCallback(({ subagentId, status }) => {
278687
+ const handleSubagentComplete = import_react74.useCallback(({ subagentId, status }) => {
278112
278688
  if (!subagentId.startsWith("pentest-agent-"))
278113
278689
  return;
278114
278690
  setPentestAgents((prev) => {
@@ -278121,7 +278697,7 @@ function Pentest({ sessionId }) {
278121
278697
  };
278122
278698
  });
278123
278699
  }, []);
278124
- const appendPanelText = import_react75.useCallback((source, text2) => {
278700
+ const appendPanelText = import_react74.useCallback((source, text2) => {
278125
278701
  if (panelSourceRef.current !== source) {
278126
278702
  panelTextRef.current = "";
278127
278703
  panelSourceRef.current = source;
@@ -278146,7 +278722,7 @@ function Pentest({ sessionId }) {
278146
278722
  ];
278147
278723
  });
278148
278724
  }, []);
278149
- const appendPentestText = import_react75.useCallback((subagentId, text2) => {
278725
+ const appendPentestText = import_react74.useCallback((subagentId, text2) => {
278150
278726
  ensurePentestAgent(subagentId);
278151
278727
  if (!pentestTextRefs.current[subagentId]) {
278152
278728
  pentestTextRefs.current[subagentId] = "";
@@ -278179,7 +278755,7 @@ function Pentest({ sessionId }) {
278179
278755
  };
278180
278756
  });
278181
278757
  }, [ensurePentestAgent]);
278182
- const addPanelToolCall = import_react75.useCallback((toolCallId, toolName, args) => {
278758
+ const addPanelToolCall = import_react74.useCallback((toolCallId, toolName, args) => {
278183
278759
  panelTextRef.current = "";
278184
278760
  panelSourceRef.current = null;
278185
278761
  const description = typeof args?.toolCallDescription === "string" ? args.toolCallDescription : toolName;
@@ -278198,7 +278774,7 @@ function Pentest({ sessionId }) {
278198
278774
  return [...prev, msg];
278199
278775
  });
278200
278776
  }, []);
278201
- const addPentestToolCall = import_react75.useCallback((subagentId, toolCallId, toolName, args) => {
278777
+ const addPentestToolCall = import_react74.useCallback((subagentId, toolCallId, toolName, args) => {
278202
278778
  pentestTextRefs.current[subagentId] = "";
278203
278779
  ensurePentestAgent(subagentId);
278204
278780
  const description = typeof args?.toolCallDescription === "string" ? args.toolCallDescription : toolName;
@@ -278243,12 +278819,12 @@ function Pentest({ sessionId }) {
278243
278819
  }
278244
278820
  ];
278245
278821
  };
278246
- const updatePanelToolResult = import_react75.useCallback((toolCallId, toolName, result) => {
278822
+ const updatePanelToolResult = import_react74.useCallback((toolCallId, toolName, result) => {
278247
278823
  panelTextRef.current = "";
278248
278824
  panelSourceRef.current = null;
278249
278825
  setPanelMessages((prev) => toolResultUpdater(prev, toolCallId, toolName, result));
278250
278826
  }, []);
278251
- const updatePentestToolResult = import_react75.useCallback((subagentId, toolCallId, toolName, result) => {
278827
+ const updatePentestToolResult = import_react74.useCallback((subagentId, toolCallId, toolName, result) => {
278252
278828
  pentestTextRefs.current[subagentId] = "";
278253
278829
  setPentestAgents((prev) => {
278254
278830
  const agent = prev[subagentId];
@@ -278263,7 +278839,7 @@ function Pentest({ sessionId }) {
278263
278839
  };
278264
278840
  });
278265
278841
  }, []);
278266
- const startPentest = import_react75.useCallback(async (s2) => {
278842
+ const startPentest = import_react74.useCallback(async (s2) => {
278267
278843
  setPhase("discovery");
278268
278844
  setStartTime(new Date);
278269
278845
  setIsExecuting(true);
@@ -278360,7 +278936,7 @@ function Pentest({ sessionId }) {
278360
278936
  handleSubagentSpawn,
278361
278937
  handleSubagentComplete
278362
278938
  ]);
278363
- import_react75.useEffect(() => {
278939
+ import_react74.useEffect(() => {
278364
278940
  if (phase === "completed") {
278365
278941
  setFocusedIndex(pentestAgentList.length);
278366
278942
  }
@@ -278423,7 +278999,7 @@ function Pentest({ sessionId }) {
278423
278999
  }
278424
279000
  }
278425
279001
  });
278426
- const openReport = import_react75.useCallback(() => {
279002
+ const openReport = import_react74.useCallback(() => {
278427
279003
  if (!session)
278428
279004
  return;
278429
279005
  const err = openSessionReport(session.rootPath);
@@ -278608,7 +279184,7 @@ function OrchestratorPanel({
278608
279184
  }) {
278609
279185
  const { colors: colors2 } = useTheme();
278610
279186
  const isRunning = phase !== "loading" && phase !== "completed" && phase !== "error";
278611
- const assetSummary = import_react75.useMemo(() => {
279187
+ const assetSummary = import_react74.useMemo(() => {
278612
279188
  const byType = {};
278613
279189
  for (const a of assets) {
278614
279190
  const key = a.assetType;
@@ -278851,13 +279427,13 @@ function AgentCardGrid({
278851
279427
  onSelectAgent
278852
279428
  }) {
278853
279429
  const { colors: colors2 } = useTheme();
278854
- const scrollRef = import_react75.useRef(null);
278855
- import_react75.useEffect(() => {
279430
+ const scrollRef = import_react74.useRef(null);
279431
+ import_react74.useEffect(() => {
278856
279432
  const agent = agents[focusedIndex];
278857
279433
  if (agent)
278858
279434
  scrollToChild(scrollRef.current, agent.id);
278859
279435
  }, [focusedIndex, agents]);
278860
- const rows = import_react75.useMemo(() => {
279436
+ const rows = import_react74.useMemo(() => {
278861
279437
  const result = [];
278862
279438
  for (let i2 = 0;i2 < agents.length; i2 += gridColumns) {
278863
279439
  result.push(agents.slice(i2, i2 + gridColumns));
@@ -278914,14 +279490,14 @@ function AgentCard({
278914
279490
  completed: colors2.primary,
278915
279491
  failed: colors2.error
278916
279492
  }[agent.status];
278917
- const lastActivity = import_react75.useMemo(() => {
279493
+ const lastActivity = import_react74.useMemo(() => {
278918
279494
  const last = agent.messages[agent.messages.length - 1];
278919
279495
  if (!last)
278920
279496
  return "Starting...";
278921
279497
  const text2 = typeof last.content === "string" ? last.content.replace(/\n/g, " ").trim() : "Working...";
278922
279498
  return text2.length > 50 ? text2.substring(0, 47) + "..." : text2;
278923
279499
  }, [agent.messages]);
278924
- const toolCalls = import_react75.useMemo(() => agent.messages.filter((m4) => m4.role === "tool").length, [agent.messages]);
279500
+ const toolCalls = import_react74.useMemo(() => agent.messages.filter((m4) => m4.role === "tool").length, [agent.messages]);
278925
279501
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
278926
279502
  id: agent.id,
278927
279503
  flexGrow: 1,
@@ -279109,8 +279685,8 @@ function MetricsBar({
279109
279685
  isExecuting
279110
279686
  }) {
279111
279687
  const { colors: colors2 } = useTheme();
279112
- const [now2, setNow] = import_react75.useState(Date.now());
279113
- import_react75.useEffect(() => {
279688
+ const [now2, setNow] = import_react74.useState(Date.now());
279689
+ import_react74.useEffect(() => {
279114
279690
  if (!isExecuting)
279115
279691
  return;
279116
279692
  const interval = setInterval(() => setNow(Date.now()), 1000);
@@ -279253,7 +279829,7 @@ function MetricsBar({
279253
279829
  }
279254
279830
 
279255
279831
  // src/tui/components/operator-dashboard/index.tsx
279256
- var import_react80 = __toESM(require_react(), 1);
279832
+ var import_react79 = __toESM(require_react(), 1);
279257
279833
 
279258
279834
  // src/core/api/offesecAgent.ts
279259
279835
  init_offensiveSecurityAgent();
@@ -279352,7 +279928,7 @@ function InlineApprovalPrompt2({ approval }) {
279352
279928
  }
279353
279929
 
279354
279930
  // src/tui/components/chat/loading-indicator.tsx
279355
- var import_react77 = __toESM(require_react(), 1);
279931
+ var import_react76 = __toESM(require_react(), 1);
279356
279932
  var SPINNER_FRAMES2 = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
279357
279933
  var SPINNER_INTERVAL2 = 80;
279358
279934
  var DOTS_FRAMES = ["", ".", "..", "..."];
@@ -279363,15 +279939,15 @@ function LoadingIndicator({
279363
279939
  toolName
279364
279940
  }) {
279365
279941
  const { colors: colors2 } = useTheme();
279366
- const [spinnerFrame, setSpinnerFrame] = import_react77.useState(0);
279367
- const [dotsFrame, setDotsFrame] = import_react77.useState(0);
279368
- import_react77.useEffect(() => {
279942
+ const [spinnerFrame, setSpinnerFrame] = import_react76.useState(0);
279943
+ const [dotsFrame, setDotsFrame] = import_react76.useState(0);
279944
+ import_react76.useEffect(() => {
279369
279945
  const interval = setInterval(() => {
279370
279946
  setSpinnerFrame((f3) => (f3 + 1) % SPINNER_FRAMES2.length);
279371
279947
  }, SPINNER_INTERVAL2);
279372
279948
  return () => clearInterval(interval);
279373
279949
  }, []);
279374
- import_react77.useEffect(() => {
279950
+ import_react76.useEffect(() => {
279375
279951
  const interval = setInterval(() => {
279376
279952
  setDotsFrame((f3) => (f3 + 1) % DOTS_FRAMES.length);
279377
279953
  }, DOTS_INTERVAL);
@@ -279625,7 +280201,7 @@ function MessageList({
279625
280201
  }
279626
280202
 
279627
280203
  // src/tui/components/chat/input-area.tsx
279628
- var import_react78 = __toESM(require_react(), 1);
280204
+ var import_react77 = __toESM(require_react(), 1);
279629
280205
  function NormalInputAreaInner({
279630
280206
  value,
279631
280207
  onChange,
@@ -279640,21 +280216,22 @@ function NormalInputAreaInner({
279640
280216
  enableAutocomplete = false,
279641
280217
  autocompleteOptions = [],
279642
280218
  enableCommands = false,
279643
- onCommandExecute
280219
+ onCommandExecute,
280220
+ commandHistory = []
279644
280221
  }) {
279645
280222
  const { colors: colors2 } = useTheme();
279646
280223
  const { inputValue, setInputValue } = useInput();
279647
- const promptRef = import_react78.useRef(null);
279648
- const isExternalUpdate = import_react78.useRef(false);
280224
+ const promptRef = import_react77.useRef(null);
280225
+ const isExternalUpdate = import_react77.useRef(false);
279649
280226
  const isDisabled = status === "running";
279650
- import_react78.useEffect(() => {
280227
+ import_react77.useEffect(() => {
279651
280228
  if (value !== inputValue) {
279652
280229
  isExternalUpdate.current = true;
279653
280230
  setInputValue(value);
279654
280231
  promptRef.current?.setValue(value);
279655
280232
  }
279656
280233
  }, [value]);
279657
- import_react78.useEffect(() => {
280234
+ import_react77.useEffect(() => {
279658
280235
  if (isExternalUpdate.current) {
279659
280236
  isExternalUpdate.current = false;
279660
280237
  return;
@@ -279698,7 +280275,8 @@ function NormalInputAreaInner({
279698
280275
  enableAutocomplete,
279699
280276
  autocompleteOptions,
279700
280277
  enableCommands,
279701
- onCommandExecute
280278
+ onCommandExecute,
280279
+ commandHistory
279702
280280
  }, undefined, false, undefined, this)
279703
280281
  ]
279704
280282
  }, undefined, true, undefined, this),
@@ -279784,6 +280362,7 @@ function InputArea(props) {
279784
280362
  autocompleteOptions,
279785
280363
  enableCommands,
279786
280364
  onCommandExecute,
280365
+ commandHistory,
279787
280366
  ...normalProps
279788
280367
  } = props;
279789
280368
  if (pendingApproval) {
@@ -279806,6 +280385,7 @@ function InputArea(props) {
279806
280385
  autocompleteOptions,
279807
280386
  enableCommands,
279808
280387
  onCommandExecute,
280388
+ commandHistory,
279809
280389
  ...normalProps
279810
280390
  }, undefined, false, undefined, this)
279811
280391
  }, undefined, false, undefined, this);
@@ -279820,7 +280400,7 @@ function ApprovalInputArea2({
279820
280400
  lastDeclineNote
279821
280401
  }) {
279822
280402
  const { colors: colors2 } = useTheme();
279823
- const [focusedElement, setFocusedElement] = import_react78.useState(0);
280403
+ const [focusedElement, setFocusedElement] = import_react77.useState(0);
279824
280404
  useKeyboard((key) => {
279825
280405
  if (key.name === "up") {
279826
280406
  setFocusedElement((prev) => Math.max(0, prev - 1));
@@ -279933,6 +280513,7 @@ function ApprovalInputArea2({
279933
280513
 
279934
280514
  // src/tui/components/operator-dashboard/index.tsx
279935
280515
  init_operator();
280516
+ init_execution_metrics();
279936
280517
  init_dist5();
279937
280518
 
279938
280519
  // src/tui/components/operator-dashboard/keyboard.ts
@@ -279948,8 +280529,8 @@ function shouldHandleOperatorCtrlC(key, status, inputValue) {
279948
280529
  }
279949
280530
 
279950
280531
  // src/tui/components/operator-dashboard/index.tsx
279951
- import { existsSync as existsSync25, readFileSync as readFileSync12 } from "fs";
279952
- import { join as join26 } from "path";
280532
+ import { existsSync as existsSync26, readFileSync as readFileSync13 } from "fs";
280533
+ import { join as join27 } from "path";
279953
280534
  function OperatorDashboard({
279954
280535
  sessionId,
279955
280536
  initialMessage,
@@ -279958,7 +280539,16 @@ function OperatorDashboard({
279958
280539
  const { colors: colors2 } = useTheme();
279959
280540
  const route = useRoute();
279960
280541
  const config3 = useConfig();
279961
- const { model, setModel, isModelUserSelected, setThinking, setIsExecuting } = useAgent();
280542
+ const {
280543
+ model,
280544
+ setModel,
280545
+ isModelUserSelected,
280546
+ setThinking,
280547
+ setIsExecuting,
280548
+ tokenUsage,
280549
+ addTokenUsage,
280550
+ resetTokenUsage
280551
+ } = useAgent();
279962
280552
  const {
279963
280553
  autocompleteOptions: allAutocompleteOptions,
279964
280554
  executeCommand: executeCommand2,
@@ -279972,32 +280562,40 @@ function OperatorDashboard({
279972
280562
  clear: clearDialog,
279973
280563
  setSize: setDialogSize
279974
280564
  } = useDialog();
279975
- const autocompleteOptions = import_react80.useMemo(() => {
280565
+ const autocompleteOptions = import_react79.useMemo(() => {
279976
280566
  const allowedCommands = new Set(["/create-skill", "/models"]);
279977
280567
  const skillSlugs = new Set(skills.map((s2) => `/${slugify(s2.name)}`));
279978
280568
  return allAutocompleteOptions.filter((opt) => allowedCommands.has(opt.value) || skillSlugs.has(opt.value));
279979
280569
  }, [allAutocompleteOptions, skills]);
279980
- const [session, setSession] = import_react80.useState(null);
279981
- const [loading, setLoading] = import_react80.useState(true);
279982
- const [error40, setError] = import_react80.useState(null);
279983
- const [status, setStatus] = import_react80.useState("idle");
279984
- const abortControllerRef = import_react80.useRef(null);
279985
- const generationRef = import_react80.useRef(0);
279986
- const cancelHandleRef = import_react80.useRef({
280570
+ const [session, setSession] = import_react79.useState(null);
280571
+ const [loading, setLoading] = import_react79.useState(true);
280572
+ const [error40, setError] = import_react79.useState(null);
280573
+ const [status, setStatus] = import_react79.useState("idle");
280574
+ const abortControllerRef = import_react79.useRef(null);
280575
+ const generationRef = import_react79.useRef(0);
280576
+ const cancelHandleRef = import_react79.useRef({
279987
280577
  cancel: () => false
279988
280578
  });
279989
- const commandCancelledRef = import_react80.useRef(false);
279990
- const [messages, setMessages] = import_react80.useState([]);
279991
- const textRef = import_react80.useRef("");
279992
- const conversationRef = import_react80.useRef([]);
279993
- const [inputValue, setInputValue] = import_react80.useState("");
279994
- const [operatorState, setOperatorState] = import_react80.useState(() => createInitialOperatorState("manual", true));
279995
- const approvalGateRef = import_react80.useRef(new ApprovalGate({ requireApproval: true }));
279996
- const [pendingApprovals, setPendingApprovals] = import_react80.useState([]);
279997
- const [lastApprovedAction, setLastApprovedAction] = import_react80.useState(null);
279998
- const [verboseMode, setVerboseMode] = import_react80.useState(false);
279999
- const [expandedLogs, setExpandedLogs] = import_react80.useState(false);
280000
- import_react80.useEffect(() => {
280579
+ const commandCancelledRef = import_react79.useRef(false);
280580
+ const [messages, setMessages] = import_react79.useState([]);
280581
+ const textRef = import_react79.useRef("");
280582
+ const conversationRef = import_react79.useRef([]);
280583
+ const [inputValue, setInputValue] = import_react79.useState("");
280584
+ const [commandHistory, setCommandHistory] = import_react79.useState(getEntries);
280585
+ import_react79.useEffect(() => {
280586
+ load().then(setCommandHistory);
280587
+ }, []);
280588
+ const [operatorState, setOperatorState] = import_react79.useState(() => createInitialOperatorState("manual", true));
280589
+ const approvalGateRef = import_react79.useRef(new ApprovalGate({ requireApproval: true }));
280590
+ const [pendingApprovals, setPendingApprovals] = import_react79.useState([]);
280591
+ const [lastApprovedAction, setLastApprovedAction] = import_react79.useState(null);
280592
+ const [verboseMode, setVerboseMode] = import_react79.useState(false);
280593
+ const [expandedLogs, setExpandedLogs] = import_react79.useState(false);
280594
+ const tokenUsageRef = import_react79.useRef(tokenUsage);
280595
+ import_react79.useEffect(() => {
280596
+ tokenUsageRef.current = tokenUsage;
280597
+ }, [tokenUsage]);
280598
+ import_react79.useEffect(() => {
280001
280599
  const gate = approvalGateRef.current;
280002
280600
  const onApprovalNeeded = () => {
280003
280601
  setPendingApprovals(gate.getPendingApprovals());
@@ -280019,7 +280617,7 @@ function OperatorDashboard({
280019
280617
  gate.off("approval-resolved", onApprovalResolved);
280020
280618
  };
280021
280619
  }, []);
280022
- import_react80.useEffect(() => {
280620
+ import_react79.useEffect(() => {
280023
280621
  async function loadSession() {
280024
280622
  try {
280025
280623
  let s2;
@@ -280092,7 +280690,25 @@ function OperatorDashboard({
280092
280690
  }
280093
280691
  loadSession();
280094
280692
  }, [sessionId]);
280095
- const appendText = import_react80.useCallback((text2) => {
280693
+ import_react79.useEffect(() => {
280694
+ if (!session)
280695
+ return;
280696
+ resetTokenUsage();
280697
+ tokenUsageRef.current = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
280698
+ const metrics = readExecutionMetrics(session.rootPath);
280699
+ const persisted = metrics?.tokenUsage;
280700
+ if (persisted && (persisted.inputTokens > 0 || persisted.outputTokens > 0)) {
280701
+ addTokenUsage(persisted.inputTokens, persisted.outputTokens);
280702
+ tokenUsageRef.current = persisted;
280703
+ }
280704
+ try {
280705
+ writeExecutionMetrics({
280706
+ sessionRootPath: session.rootPath,
280707
+ tokenUsage: tokenUsageRef.current
280708
+ });
280709
+ } catch {}
280710
+ }, [session, addTokenUsage, resetTokenUsage]);
280711
+ const appendText = import_react79.useCallback((text2) => {
280096
280712
  textRef.current += text2;
280097
280713
  const accumulated = textRef.current;
280098
280714
  setMessages((prev) => {
@@ -280108,7 +280724,7 @@ function OperatorDashboard({
280108
280724
  ];
280109
280725
  });
280110
280726
  }, []);
280111
- const addToolCall = import_react80.useCallback((toolCallId, toolName, args) => {
280727
+ const addToolCall = import_react79.useCallback((toolCallId, toolName, args) => {
280112
280728
  textRef.current = "";
280113
280729
  setMessages((prev) => [
280114
280730
  ...prev,
@@ -280123,7 +280739,7 @@ function OperatorDashboard({
280123
280739
  }
280124
280740
  ]);
280125
280741
  }, []);
280126
- const updateToolResult = import_react80.useCallback((toolCallId, _toolName, result) => {
280742
+ const updateToolResult = import_react79.useCallback((toolCallId, _toolName, result) => {
280127
280743
  textRef.current = "";
280128
280744
  setMessages((prev) => {
280129
280745
  const idx = prev.findIndex((m4) => isToolMessage(m4) && m4.toolCallId === toolCallId);
@@ -280134,10 +280750,10 @@ function OperatorDashboard({
280134
280750
  return updated;
280135
280751
  });
280136
280752
  }, []);
280137
- const cmdOutputBufRef = import_react80.useRef("");
280138
- const cmdFlushTimerRef = import_react80.useRef(null);
280753
+ const cmdOutputBufRef = import_react79.useRef("");
280754
+ const cmdFlushTimerRef = import_react79.useRef(null);
280139
280755
  const MAX_LOG_LINES = 200;
280140
- const flushCommandOutput = import_react80.useCallback(() => {
280756
+ const flushCommandOutput = import_react79.useCallback(() => {
280141
280757
  const buf = cmdOutputBufRef.current;
280142
280758
  if (!buf)
280143
280759
  return;
@@ -280167,7 +280783,7 @@ function OperatorDashboard({
280167
280783
  return updated;
280168
280784
  });
280169
280785
  }, []);
280170
- const onCommandOutput = import_react80.useCallback((data) => {
280786
+ const onCommandOutput = import_react79.useCallback((data) => {
280171
280787
  cmdOutputBufRef.current += data;
280172
280788
  if (!cmdFlushTimerRef.current) {
280173
280789
  cmdFlushTimerRef.current = setInterval(() => {
@@ -280175,7 +280791,7 @@ function OperatorDashboard({
280175
280791
  }, 150);
280176
280792
  }
280177
280793
  }, [flushCommandOutput]);
280178
- import_react80.useEffect(() => {
280794
+ import_react79.useEffect(() => {
280179
280795
  return () => {
280180
280796
  if (cmdFlushTimerRef.current) {
280181
280797
  clearInterval(cmdFlushTimerRef.current);
@@ -280183,7 +280799,7 @@ function OperatorDashboard({
280183
280799
  }
280184
280800
  };
280185
280801
  }, []);
280186
- const appendLogToActiveTool = import_react80.useCallback((line) => {
280802
+ const appendLogToActiveTool = import_react79.useCallback((line) => {
280187
280803
  setMessages((prev) => {
280188
280804
  const idx = prev.findLastIndex((m4) => isToolMessage(m4) && m4.status === "pending");
280189
280805
  if (idx === -1)
@@ -280198,13 +280814,13 @@ function OperatorDashboard({
280198
280814
  return updated;
280199
280815
  });
280200
280816
  }, []);
280201
- const handleApprove = import_react80.useCallback(() => {
280817
+ const handleApprove = import_react79.useCallback(() => {
280202
280818
  const pending = approvalGateRef.current.getPendingApprovals();
280203
280819
  if (pending.length > 0) {
280204
280820
  approvalGateRef.current.approve(pending[0].id);
280205
280821
  }
280206
280822
  }, []);
280207
- const handleAutoApprove = import_react80.useCallback(() => {
280823
+ const handleAutoApprove = import_react79.useCallback(() => {
280208
280824
  approvalGateRef.current.updateConfig({ requireApproval: false });
280209
280825
  setOperatorState((prev) => ({ ...prev, requireApproval: false }));
280210
280826
  const pending = approvalGateRef.current.getPendingApprovals();
@@ -280212,7 +280828,7 @@ function OperatorDashboard({
280212
280828
  approvalGateRef.current.approve(p.id);
280213
280829
  }
280214
280830
  }, []);
280215
- const runAgent = import_react80.useCallback(async (prompt) => {
280831
+ const runAgent = import_react79.useCallback(async (prompt) => {
280216
280832
  if (!session)
280217
280833
  return;
280218
280834
  if (abortControllerRef.current) {
@@ -280250,6 +280866,25 @@ function OperatorDashboard({
280250
280866
  authConfig: buildAuthConfig(config3.data),
280251
280867
  approvalGate: approvalGateRef.current,
280252
280868
  commandCancelHandle: cancelHandleRef.current,
280869
+ onStepFinish: (event) => {
280870
+ const inputTokens = event.usage?.inputTokens ?? 0;
280871
+ const outputTokens = event.usage?.outputTokens ?? 0;
280872
+ if (inputTokens <= 0 && outputTokens <= 0)
280873
+ return;
280874
+ const nextUsage = {
280875
+ inputTokens: tokenUsageRef.current.inputTokens + inputTokens,
280876
+ outputTokens: tokenUsageRef.current.outputTokens + outputTokens,
280877
+ totalTokens: tokenUsageRef.current.totalTokens + inputTokens + outputTokens
280878
+ };
280879
+ tokenUsageRef.current = nextUsage;
280880
+ addTokenUsage(inputTokens, outputTokens);
280881
+ try {
280882
+ writeExecutionMetrics({
280883
+ sessionRootPath: session.rootPath,
280884
+ tokenUsage: nextUsage
280885
+ });
280886
+ } catch {}
280887
+ },
280253
280888
  callbacks: {
280254
280889
  onTextDelta: (d3) => {
280255
280890
  setThinking(false);
@@ -280345,6 +280980,7 @@ function OperatorDashboard({
280345
280980
  model.id,
280346
280981
  config3.data,
280347
280982
  operatorState,
280983
+ addTokenUsage,
280348
280984
  appendText,
280349
280985
  addToolCall,
280350
280986
  updateToolResult,
@@ -280354,7 +280990,7 @@ function OperatorDashboard({
280354
280990
  setThinking,
280355
280991
  setIsExecuting
280356
280992
  ]);
280357
- const handleSubmit = import_react80.useCallback((value) => {
280993
+ const handleSubmit = import_react79.useCallback((value) => {
280358
280994
  if (!value.trim())
280359
280995
  return;
280360
280996
  const pending = approvalGateRef.current.getPendingApprovals();
@@ -280365,19 +281001,21 @@ function OperatorDashboard({
280365
281001
  }
280366
281002
  if (status === "running")
280367
281003
  return;
281004
+ const trimmed = value.trim();
281005
+ push(trimmed).then(() => setCommandHistory([...getEntries()]));
280368
281006
  setInputValue("");
280369
- runAgent(value.trim());
281007
+ runAgent(trimmed);
280370
281008
  }, [status, runAgent]);
280371
- const initialMessageSentRef = import_react80.useRef(false);
280372
- const runAgentRef = import_react80.useRef(runAgent);
281009
+ const initialMessageSentRef = import_react79.useRef(false);
281010
+ const runAgentRef = import_react79.useRef(runAgent);
280373
281011
  runAgentRef.current = runAgent;
280374
- import_react80.useEffect(() => {
281012
+ import_react79.useEffect(() => {
280375
281013
  if (!loading && session && initialMessage && !initialMessageSentRef.current) {
280376
281014
  initialMessageSentRef.current = true;
280377
281015
  runAgentRef.current(initialMessage);
280378
281016
  }
280379
281017
  }, [loading, session, initialMessage]);
280380
- const showModelPicker = import_react80.useCallback(() => {
281018
+ const showModelPicker = import_react79.useCallback(() => {
280381
281019
  setDialogSize("large");
280382
281020
  showDialog(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
280383
281021
  flexDirection: "column",
@@ -280439,7 +281077,7 @@ function OperatorDashboard({
280439
281077
  clearDialog,
280440
281078
  setDialogSize
280441
281079
  ]);
280442
- const handleCommandExecute = import_react80.useCallback(async (command) => {
281080
+ const handleCommandExecute = import_react79.useCallback(async (command) => {
280443
281081
  const commandLower = command.trim().replace(/^\/+/, "").toLowerCase();
280444
281082
  if (commandLower === "models" || commandLower === "model") {
280445
281083
  showModelPicker();
@@ -280458,7 +281096,7 @@ function OperatorDashboard({
280458
281096
  }
280459
281097
  await executeCommand2(command);
280460
281098
  }, [resolveSkillContent, handleSubmit, executeCommand2, showModelPicker]);
280461
- const handleAbort = import_react80.useCallback(() => {
281099
+ const handleAbort = import_react79.useCallback(() => {
280462
281100
  if (!abortControllerRef.current)
280463
281101
  return;
280464
281102
  if (!commandCancelledRef.current && cancelHandleRef.current.cancel()) {
@@ -280483,9 +281121,9 @@ function OperatorDashboard({
280483
281121
  approvalGateRef.current.denyAll();
280484
281122
  if (session) {
280485
281123
  try {
280486
- const messagesPath = join26(session.rootPath, "messages.json");
280487
- if (existsSync25(messagesPath)) {
280488
- const raw = JSON.parse(readFileSync12(messagesPath, "utf-8"));
281124
+ const messagesPath = join27(session.rootPath, "messages.json");
281125
+ if (existsSync26(messagesPath)) {
281126
+ const raw = JSON.parse(readFileSync13(messagesPath, "utf-8"));
280489
281127
  if (Array.isArray(raw) && raw.length > 0) {
280490
281128
  conversationRef.current = raw;
280491
281129
  }
@@ -280504,7 +281142,7 @@ function OperatorDashboard({
280504
281142
  ];
280505
281143
  });
280506
281144
  }, [session, setThinking, setIsExecuting]);
280507
- const toggleApproval = import_react80.useCallback(() => {
281145
+ const toggleApproval = import_react79.useCallback(() => {
280508
281146
  setOperatorState((prev) => {
280509
281147
  const newVal = !prev.requireApproval;
280510
281148
  approvalGateRef.current.updateConfig({ requireApproval: newVal });
@@ -280686,7 +281324,8 @@ function OperatorDashboard({
280686
281324
  enableAutocomplete: true,
280687
281325
  autocompleteOptions,
280688
281326
  enableCommands: true,
280689
- onCommandExecute: handleCommandExecute
281327
+ onCommandExecute: handleCommandExecute,
281328
+ commandHistory
280690
281329
  }, undefined, false, undefined, this)
280691
281330
  ]
280692
281331
  }, undefined, true, undefined, this);
@@ -280717,7 +281356,7 @@ Session paths:
280717
281356
  }
280718
281357
 
280719
281358
  // src/tui/components/commands/theme-picker.tsx
280720
- var import_react82 = __toESM(require_react(), 1);
281359
+ var import_react81 = __toESM(require_react(), 1);
280721
281360
  init_config2();
280722
281361
  function ThemePicker() {
280723
281362
  const dimensions = useTerminalDimensions();
@@ -280731,15 +281370,15 @@ function ThemePicker() {
280731
281370
  toggleMode,
280732
281371
  setMode
280733
281372
  } = useTheme();
280734
- const [selectedIndex, setSelectedIndex] = import_react82.useState(() => Math.max(0, availableThemes.indexOf(theme.name)));
280735
- const originalThemeRef = import_react82.useRef(theme.name);
280736
- const originalModeRef = import_react82.useRef(mode);
280737
- const handleClose = import_react82.useCallback(() => {
281373
+ const [selectedIndex, setSelectedIndex] = import_react81.useState(() => Math.max(0, availableThemes.indexOf(theme.name)));
281374
+ const originalThemeRef = import_react81.useRef(theme.name);
281375
+ const originalModeRef = import_react81.useRef(mode);
281376
+ const handleClose = import_react81.useCallback(() => {
280738
281377
  setTheme(originalThemeRef.current);
280739
281378
  setMode(originalModeRef.current);
280740
281379
  route.navigate({ type: "base", path: "home" });
280741
281380
  }, [setTheme, setMode, route]);
280742
- const handleConfirm = import_react82.useCallback(async () => {
281381
+ const handleConfirm = import_react81.useCallback(async () => {
280743
281382
  const currentThemeName = availableThemes[selectedIndex];
280744
281383
  if (currentThemeName) {
280745
281384
  await config.update({ theme: currentThemeName });
@@ -280882,16 +281521,16 @@ function ThemePicker() {
280882
281521
  }
280883
281522
 
280884
281523
  // src/tui/components/commands/create-skill-wizard.tsx
280885
- var import_react84 = __toESM(require_react(), 1);
281524
+ var import_react83 = __toESM(require_react(), 1);
280886
281525
  function CreateSkillWizard() {
280887
281526
  const { colors: colors2 } = useTheme();
280888
281527
  const route = useRoute();
280889
- const [step, setStep] = import_react84.useState("name");
280890
- const [name26, setName] = import_react84.useState("");
280891
- const [description, setDescription] = import_react84.useState("");
280892
- const [content, setContent] = import_react84.useState("");
280893
- const [error40, setError] = import_react84.useState(null);
280894
- const [confirmFocused, setConfirmFocused] = import_react84.useState(0);
281528
+ const [step, setStep] = import_react83.useState("name");
281529
+ const [name26, setName] = import_react83.useState("");
281530
+ const [description, setDescription] = import_react83.useState("");
281531
+ const [content, setContent] = import_react83.useState("");
281532
+ const [error40, setError] = import_react83.useState(null);
281533
+ const [confirmFocused, setConfirmFocused] = import_react83.useState(0);
280895
281534
  const slug = slugify(name26);
280896
281535
  async function handleSave() {
280897
281536
  if (!name26.trim() || !content.trim())
@@ -283768,13 +284407,13 @@ async function detectTerminalMode(timeoutMs = 1000) {
283768
284407
 
283769
284408
  // src/tui/index.tsx
283770
284409
  function App({ appConfig }) {
283771
- const [focusIndex, setFocusIndex] = import_react87.useState(0);
283772
- const [cwd, setCwd] = import_react87.useState(process.cwd());
283773
- const [ctrlCPressTime, setCtrlCPressTime] = import_react87.useState(null);
283774
- const [showExitWarning, setShowExitWarning] = import_react87.useState(false);
283775
- const [inputKey, setInputKey] = import_react87.useState(0);
283776
- const [showSessionsDialog, setShowSessionsDialog] = import_react87.useState(false);
283777
- const [showShortcutsDialog, setShowShortcutsDialog] = import_react87.useState(false);
284410
+ const [focusIndex, setFocusIndex] = import_react86.useState(0);
284411
+ const [cwd, setCwd] = import_react86.useState(process.cwd());
284412
+ const [ctrlCPressTime, setCtrlCPressTime] = import_react86.useState(null);
284413
+ const [showExitWarning, setShowExitWarning] = import_react86.useState(false);
284414
+ const [inputKey, setInputKey] = import_react86.useState(0);
284415
+ const [showSessionsDialog, setShowSessionsDialog] = import_react86.useState(false);
284416
+ const [showShortcutsDialog, setShowShortcutsDialog] = import_react86.useState(false);
283778
284417
  const navigableItems = ["command-input"];
283779
284418
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ConfigProvider, {
283780
284419
  config: appConfig,
@@ -283839,14 +284478,14 @@ function AppContent({
283839
284478
  const { toast } = useToast();
283840
284479
  const { refocusPrompt } = useFocus();
283841
284480
  const { setExternalDialogOpen } = useDialog();
283842
- import_react87.useEffect(() => {
284481
+ import_react86.useEffect(() => {
283843
284482
  checkForUpdate().then(({ updateAvailable, currentVersion, latestVersion }) => {
283844
284483
  if (!updateAvailable)
283845
284484
  return;
283846
284485
  toast(`Update available: v${currentVersion} → v${latestVersion}. Run: pensar upgrade`, "warn", 8000);
283847
284486
  });
283848
284487
  }, []);
283849
- import_react87.useEffect(() => {
284488
+ import_react86.useEffect(() => {
283850
284489
  if (route.data.type !== "base")
283851
284490
  return;
283852
284491
  if (!config3.data.responsibleUseAccepted && route.data.path !== "disclosure") {
@@ -283855,7 +284494,7 @@ function AppContent({
283855
284494
  route.navigate({ type: "base", path: "providers" });
283856
284495
  }
283857
284496
  }, [config3.data.responsibleUseAccepted, route.data]);
283858
- import_react87.useEffect(() => {
284497
+ import_react86.useEffect(() => {
283859
284498
  if (showExitWarning) {
283860
284499
  const timer = setTimeout(() => {
283861
284500
  setShowExitWarning(false);