@pensar/apex 0.0.80 → 0.0.81-canary.bef8d82a

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 +263 -86
  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.bef8d82a",
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",
@@ -37017,9 +37017,9 @@ function saveSubagentData(session, data) {
37017
37017
  const filename = `${data.agentName}-${ts}.json`;
37018
37018
  writeFileSync2(join4(subagentsDir, filename), JSON.stringify(savedData, null, 2));
37019
37019
  }
37020
- function writeAgentManifest(session, entries) {
37020
+ function writeAgentManifest(session, entries2) {
37021
37021
  const manifestPath = join4(session.rootPath, MANIFEST_FILE);
37022
- writeFileSync2(manifestPath, JSON.stringify(entries, null, 2));
37022
+ writeFileSync2(manifestPath, JSON.stringify(entries2, null, 2));
37023
37023
  }
37024
37024
  function buildManifestEntries(targets) {
37025
37025
  return targets.map((t2, i) => ({
@@ -37032,8 +37032,8 @@ function buildManifestEntries(targets) {
37032
37032
  spawnedAt: new Date().toISOString()
37033
37033
  }));
37034
37034
  }
37035
- function finalizeManifest(session, entries, results) {
37036
- const finalManifest = entries.map((entry, i) => ({
37035
+ function finalizeManifest(session, entries2, results) {
37036
+ const finalManifest = entries2.map((entry, i) => ({
37037
37037
  ...entry,
37038
37038
  status: results[i] != null ? "completed" : "failed",
37039
37039
  completedAt: new Date().toISOString()
@@ -37612,9 +37612,9 @@ function assertNever(_x) {
37612
37612
  throw new Error;
37613
37613
  }
37614
37614
  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);
37615
+ function getEnumValues(entries2) {
37616
+ const numericValues = Object.values(entries2).filter((v2) => typeof v2 === "number");
37617
+ const values = Object.entries(entries2).filter(([k2, _2]) => numericValues.indexOf(+k2) === -1).map(([_2, v2]) => v2);
37618
37618
  return values;
37619
37619
  }
37620
37620
  function joinValues(array, separator = "|") {
@@ -46216,17 +46216,17 @@ function _set(Class2, valueType, params) {
46216
46216
  });
46217
46217
  }
46218
46218
  function _enum(Class2, values, params) {
46219
- const entries = Array.isArray(values) ? Object.fromEntries(values.map((v2) => [v2, v2])) : values;
46219
+ const entries2 = Array.isArray(values) ? Object.fromEntries(values.map((v2) => [v2, v2])) : values;
46220
46220
  return new Class2({
46221
46221
  type: "enum",
46222
- entries,
46222
+ entries: entries2,
46223
46223
  ...normalizeParams(params)
46224
46224
  });
46225
46225
  }
46226
- function _nativeEnum(Class2, entries, params) {
46226
+ function _nativeEnum(Class2, entries2, params) {
46227
46227
  return new Class2({
46228
46228
  type: "enum",
46229
- entries,
46229
+ entries: entries2,
46230
46230
  ...normalizeParams(params)
46231
46231
  });
46232
46232
  }
@@ -47850,17 +47850,17 @@ function set(valueType, params) {
47850
47850
  });
47851
47851
  }
47852
47852
  function _enum2(values, params) {
47853
- const entries = Array.isArray(values) ? Object.fromEntries(values.map((v2) => [v2, v2])) : values;
47853
+ const entries2 = Array.isArray(values) ? Object.fromEntries(values.map((v2) => [v2, v2])) : values;
47854
47854
  return new ZodEnum2({
47855
47855
  type: "enum",
47856
- entries,
47856
+ entries: entries2,
47857
47857
  ...exports_util.normalizeParams(params)
47858
47858
  });
47859
47859
  }
47860
- function nativeEnum(entries, params) {
47860
+ function nativeEnum(entries2, params) {
47861
47861
  return new ZodEnum2({
47862
47862
  type: "enum",
47863
- entries,
47863
+ entries: entries2,
47864
47864
  ...exports_util.normalizeParams(params)
47865
47865
  });
47866
47866
  }
@@ -53268,8 +53268,8 @@ var require_baggage_impl = __commonJS((exports) => {
53268
53268
  exports.BaggageImpl = undefined;
53269
53269
 
53270
53270
  class BaggageImpl {
53271
- constructor(entries) {
53272
- this._entries = entries ? new Map(entries) : new Map;
53271
+ constructor(entries2) {
53272
+ this._entries = entries2 ? new Map(entries2) : new Map;
53273
53273
  }
53274
53274
  getEntry(key) {
53275
53275
  const entry = this._entries.get(key);
@@ -53320,8 +53320,8 @@ var require_utils = __commonJS((exports) => {
53320
53320
  var baggage_impl_1 = require_baggage_impl();
53321
53321
  var symbol_1 = require_symbol();
53322
53322
  var diag = diag_1.DiagAPI.instance();
53323
- function createBaggage(entries = {}) {
53324
- return new baggage_impl_1.BaggageImpl(new Map(Object.entries(entries)));
53323
+ function createBaggage(entries2 = {}) {
53324
+ return new baggage_impl_1.BaggageImpl(new Map(Object.entries(entries2)));
53325
53325
  }
53326
53326
  exports.createBaggage = createBaggage;
53327
53327
  function baggageEntryMetadataFromString(str) {
@@ -103898,13 +103898,13 @@ async function listRecursive(dir, maxEntries) {
103898
103898
  const results = [];
103899
103899
  let total = 0;
103900
103900
  async function walk(current) {
103901
- let entries;
103901
+ let entries2;
103902
103902
  try {
103903
- entries = await readdir(current, { withFileTypes: true });
103903
+ entries2 = await readdir(current, { withFileTypes: true });
103904
103904
  } catch {
103905
103905
  return;
103906
103906
  }
103907
- for (const entry of entries) {
103907
+ for (const entry of entries2) {
103908
103908
  total++;
103909
103909
  const fullPath = join12(current, entry.name);
103910
103910
  if (entry.isDirectory()) {
@@ -103967,8 +103967,8 @@ Each directory entry is suffixed with "/" for easy identification.`,
103967
103967
  totalFound: total > MAX_RECURSIVE ? total : undefined
103968
103968
  };
103969
103969
  }
103970
- const entries = await readdir(dir, { withFileTypes: true });
103971
- const fullPaths = entries.map((e) => {
103970
+ const entries2 = await readdir(dir, { withFileTypes: true });
103971
+ const fullPaths = entries2.map((e) => {
103972
103972
  const name26 = join12(dir, e.name);
103973
103973
  return e.isDirectory() ? `${name26}/` : name26;
103974
103974
  });
@@ -103976,11 +103976,11 @@ Each directory entry is suffixed with "/" for easy identification.`,
103976
103976
  const relPaths = toRelative(dir, capped);
103977
103977
  return {
103978
103978
  success: true,
103979
- error: entries.length > MAX_NON_RECURSIVE ? `Showing ${MAX_NON_RECURSIVE} of ${entries.length} entries` : "",
103979
+ error: entries2.length > MAX_NON_RECURSIVE ? `Showing ${MAX_NON_RECURSIVE} of ${entries2.length} entries` : "",
103980
103980
  files: relPaths,
103981
103981
  directory: dir,
103982
103982
  count: relPaths.length,
103983
- totalFound: entries.length > MAX_NON_RECURSIVE ? entries.length : undefined
103983
+ totalFound: entries2.length > MAX_NON_RECURSIVE ? entries2.length : undefined
103984
103984
  };
103985
103985
  } catch (err) {
103986
103986
  return {
@@ -104982,6 +104982,13 @@ When to use delegate_to_auth_subagent vs authenticate_session:
104982
104982
  tokens = { ...stored.tokens };
104983
104983
  }
104984
104984
  }
104985
+ const subagentId = "auth-agent";
104986
+ const cbs = ctx4.subagentCallbacks;
104987
+ cbs?.onSubagentSpawn?.({
104988
+ subagentId,
104989
+ input: { target, reason },
104990
+ status: "pending"
104991
+ });
104985
104992
  console.log(`
104986
104993
  \uD83D\uDD10 Delegating to authentication subagent...`);
104987
104994
  console.log(` Target: ${target}`);
@@ -105033,6 +105040,12 @@ When to use delegate_to_auth_subagent vs authenticate_session:
105033
105040
  ctx4.session.credentialManager.addFromAuthCredentials(credentials);
105034
105041
  }
105035
105042
  const { runAuthenticationAgent: runAuthenticationAgent3 } = await Promise.resolve().then(() => (init_authentication(), exports_authentication));
105043
+ const subagentCallbacks = cbs ? {
105044
+ onTextDelta: (d2) => cbs.onTextDelta?.({ ...d2, subagentId }),
105045
+ onToolCall: (d2) => cbs.onToolCall?.({ ...d2, subagentId }),
105046
+ onToolResult: (d2) => cbs.onToolResult?.({ ...d2, subagentId }),
105047
+ onError: (e) => cbs.onError?.(e)
105048
+ } : undefined;
105036
105049
  const result = await runAuthenticationAgent3({
105037
105050
  target,
105038
105051
  session: ctx4.session,
@@ -105040,7 +105053,15 @@ When to use delegate_to_auth_subagent vs authenticate_session:
105040
105053
  model: ctx4.model,
105041
105054
  authConfig: ctx4.authConfig,
105042
105055
  abortSignal: ctx4.abortSignal,
105043
- callbacks: ctx4.callbacks
105056
+ callbacks: {
105057
+ ...ctx4.callbacks,
105058
+ subagentCallbacks
105059
+ }
105060
+ });
105061
+ cbs?.onSubagentComplete?.({
105062
+ subagentId,
105063
+ input: { target, reason },
105064
+ status: result.success ? "completed" : "failed"
105044
105065
  });
105045
105066
  if (result.success) {
105046
105067
  const sessionInfoPath = join16(ctx4.session.rootPath, "session-info.json");
@@ -105088,6 +105109,11 @@ To make authenticated requests, use the returned values:
105088
105109
  Auth data saved to: ${result.authDataPath}` : ""}` : `Authentication subagent failed. ${result.summary}${result.authBarrier ? ` Barrier: ${result.authBarrier.type} - ${result.authBarrier.details}` : ""}`
105089
105110
  };
105090
105111
  } catch (error40) {
105112
+ ctx4.subagentCallbacks?.onSubagentComplete?.({
105113
+ subagentId: "auth-agent",
105114
+ input: { target, reason },
105115
+ status: "failed"
105116
+ });
105091
105117
  const errorMessage = error40 instanceof Error ? error40.message : String(error40);
105092
105118
  return {
105093
105119
  success: false,
@@ -106170,6 +106196,11 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
106170
106196
  onToolResult: (d2) => cbs.onToolResult?.({ ...d2, subagentId }),
106171
106197
  onError: (e) => cbs.onError?.(e)
106172
106198
  } : undefined;
106199
+ cbs?.onSubagentSpawn?.({
106200
+ subagentId,
106201
+ input: { target, cwd },
106202
+ status: "pending"
106203
+ });
106173
106204
  if (cwd) {
106174
106205
  try {
106175
106206
  const { WhiteboxAttackSurfaceAgent: WhiteboxAttackSurfaceAgent2 } = await Promise.resolve().then(() => (init_agent2(), exports_agent));
@@ -106193,6 +106224,11 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
106193
106224
  })));
106194
106225
  console.log(`
106195
106226
  ✓ Whitebox attack surface complete: ${targets.length} targets from ${result.apps.length} apps`);
106227
+ cbs?.onSubagentComplete?.({
106228
+ subagentId,
106229
+ input: { target, cwd },
106230
+ status: "completed"
106231
+ });
106196
106232
  return {
106197
106233
  success: true,
106198
106234
  mode: "whitebox",
@@ -106204,6 +106240,11 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
106204
106240
  } catch (error40) {
106205
106241
  const errorMsg = error40 instanceof Error ? error40.message : String(error40);
106206
106242
  console.error(`✗ Whitebox attack surface agent failed: ${errorMsg}`);
106243
+ cbs?.onSubagentComplete?.({
106244
+ subagentId,
106245
+ input: { target, cwd },
106246
+ status: "failed"
106247
+ });
106207
106248
  return {
106208
106249
  success: false,
106209
106250
  targets: [],
@@ -106230,6 +106271,11 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
106230
106271
  const targetCount = result.targets.length;
106231
106272
  console.log(`
106232
106273
  ✓ Blackbox attack surface complete: ${targetCount} targets identified`);
106274
+ cbs?.onSubagentComplete?.({
106275
+ subagentId,
106276
+ input: { target },
106277
+ status: "completed"
106278
+ });
106233
106279
  return {
106234
106280
  success: true,
106235
106281
  mode: "blackbox",
@@ -106248,6 +106294,11 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
106248
106294
  } catch (error40) {
106249
106295
  const errorMsg = error40 instanceof Error ? error40.message : String(error40);
106250
106296
  console.error(`✗ Blackbox attack surface agent failed: ${errorMsg}`);
106297
+ cbs?.onSubagentComplete?.({
106298
+ subagentId,
106299
+ input: { target },
106300
+ status: "failed"
106301
+ });
106251
106302
  return {
106252
106303
  success: false,
106253
106304
  targets: [],
@@ -140780,9 +140831,9 @@ var require_html_to_text = __commonJS((exports) => {
140780
140831
  if (!dict || Object.keys(dict).length === 0) {
140781
140832
  return;
140782
140833
  }
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);
140834
+ const entries2 = Object.entries(dict).filter(([, v2]) => v2 !== false);
140835
+ const regex = new RegExp(entries2.map(([c]) => `(${unicodeEscape([...c][0])})`).join("|"), "g");
140836
+ const values = entries2.map(([, v2]) => v2);
140786
140837
  const replacer = (m2, ...cgs) => values[cgs.findIndex((cg) => cg)];
140787
140838
  return (str) => str.replace(regex, replacer);
140788
140839
  }
@@ -145295,7 +145346,7 @@ var require_common2 = __commonJS((exports, module2) => {
145295
145346
  var require_browser = __commonJS((exports, module2) => {
145296
145347
  exports.formatArgs = formatArgs;
145297
145348
  exports.save = save;
145298
- exports.load = load;
145349
+ exports.load = load2;
145299
145350
  exports.useColors = useColors;
145300
145351
  exports.storage = localstorage();
145301
145352
  exports.destroy = (() => {
@@ -145425,7 +145476,7 @@ var require_browser = __commonJS((exports, module2) => {
145425
145476
  }
145426
145477
  } catch (error40) {}
145427
145478
  }
145428
- function load() {
145479
+ function load2() {
145429
145480
  let r;
145430
145481
  try {
145431
145482
  r = exports.storage.getItem("debug") || exports.storage.getItem("DEBUG");
@@ -145459,7 +145510,7 @@ var require_node3 = __commonJS((exports, module2) => {
145459
145510
  exports.log = log2;
145460
145511
  exports.formatArgs = formatArgs;
145461
145512
  exports.save = save;
145462
- exports.load = load;
145513
+ exports.load = load2;
145463
145514
  exports.useColors = useColors;
145464
145515
  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
145516
  exports.colors = [6, 2, 3, 4, 5, 1];
@@ -145599,7 +145650,7 @@ var require_node3 = __commonJS((exports, module2) => {
145599
145650
  delete process.env.DEBUG;
145600
145651
  }
145601
145652
  }
145602
- function load() {
145653
+ function load2() {
145603
145654
  return process.env.DEBUG;
145604
145655
  }
145605
145656
  function init2(debug) {
@@ -161065,8 +161116,8 @@ var require_object_inspect = __commonJS((exports, module2) => {
161065
161116
  function weakCollectionOf(type) {
161066
161117
  return type + " { ? }";
161067
161118
  }
161068
- function collectionOf(type, size, entries, indent) {
161069
- var joinedEntries = indent ? indentedJoin(entries, indent) : $join.call(entries, ", ");
161119
+ function collectionOf(type, size, entries2, indent) {
161120
+ var joinedEntries = indent ? indentedJoin(entries2, indent) : $join.call(entries2, ", ");
161070
161121
  return type + " (" + size + ") {" + joinedEntries + "}";
161071
161122
  }
161072
161123
  function singleLineValues(xs) {
@@ -162375,9 +162426,9 @@ var require_stringify3 = __commonJS((exports, module2) => {
162375
162426
  }
162376
162427
  };
162377
162428
  var isArray = Array.isArray;
162378
- var push = Array.prototype.push;
162429
+ var push2 = Array.prototype.push;
162379
162430
  var pushToArray = function(arr, valueOrArray) {
162380
- push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
162431
+ push2.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
162381
162432
  };
162382
162433
  var toISO = Date.prototype.toISOString;
162383
162434
  var defaultFormat = formats["default"];
@@ -170227,9 +170278,9 @@ var require_caller = __commonJS((exports, module2) => {
170227
170278
  if (!Array.isArray(stack)) {
170228
170279
  return;
170229
170280
  }
170230
- const entries = stack.slice(2);
170281
+ const entries2 = stack.slice(2);
170231
170282
  const fileNames = [];
170232
- for (const entry of entries) {
170283
+ for (const entry of entries2) {
170233
170284
  if (!entry) {
170234
170285
  continue;
170235
170286
  }
@@ -183296,7 +183347,7 @@ var require_list = __commonJS((exports, module2) => {
183296
183347
  let listCommand = connection.capabilities.has("XLIST") && !connection.capabilities.has("SPECIAL-USE") ? "XLIST" : "LIST";
183297
183348
  let response;
183298
183349
  try {
183299
- let entries = [];
183350
+ let entries2 = [];
183300
183351
  let statusMap = new Map;
183301
183352
  let returnArgs = [];
183302
183353
  let statusQueryAttributes = [];
@@ -183382,7 +183433,7 @@ var require_list = __commonJS((exports, module2) => {
183382
183433
  if (specialUseFlag) {
183383
183434
  addSpecialUseMatch(entry, specialUseFlag, flagSource);
183384
183435
  }
183385
- entries.push(entry);
183436
+ entries2.push(entry);
183386
183437
  },
183387
183438
  STATUS: async (untagged) => {
183388
183439
  let statusPath = normalizePath(connection, decodePath(connection, untagged.attributes[0] && untagged.attributes[0].value || ""));
@@ -183427,13 +183478,13 @@ var require_list = __commonJS((exports, module2) => {
183427
183478
  let normalizedReference = normalizePath(connection, reference || "");
183428
183479
  await runList(normalizedReference, normalizePath(connection, mailbox || "", true));
183429
183480
  if (options.listOnly) {
183430
- return entries;
183481
+ return entries2;
183431
183482
  }
183432
183483
  if (normalizedReference && !specialUseMatches["\\Inbox"]) {
183433
183484
  await runList("", "INBOX");
183434
183485
  }
183435
183486
  if (options.statusQuery) {
183436
- for (let entry of entries) {
183487
+ for (let entry of entries2) {
183437
183488
  if (!entry.flags.has("\\Noselect") && !entry.flags.has("\\NonExistent")) {
183438
183489
  if (statusMap.has(entry.path)) {
183439
183490
  entry.status = statusMap.get(entry.path);
@@ -183469,7 +183520,7 @@ var require_list = __commonJS((exports, module2) => {
183469
183520
  entry.parentPath = entry.delimiter && entry.path ? entry.path.substr(0, entry.path.lastIndexOf(entry.delimiter)) : "";
183470
183521
  entry.parent = entry.delimiter ? entry.path.split(entry.delimiter) : [entry.path];
183471
183522
  entry.name = entry.parent.pop();
183472
- let existing = entries.find((existing2) => existing2.path === entry.path);
183523
+ let existing = entries2.find((existing2) => existing2.path === entry.path);
183473
183524
  if (existing) {
183474
183525
  existing.subscribed = true;
183475
183526
  entry.flags.forEach((flag) => existing.flags.add(flag));
@@ -183492,11 +183543,11 @@ var require_list = __commonJS((exports, module2) => {
183492
183543
  sortedEntries[0].entry.specialUseSource = sortedEntries[0].source;
183493
183544
  }
183494
183545
  }
183495
- let inboxEntry = entries.find((entry) => entry.specialUse === "\\Inbox");
183546
+ let inboxEntry = entries2.find((entry) => entry.specialUse === "\\Inbox");
183496
183547
  if (inboxEntry && !inboxEntry.subscribed) {
183497
183548
  inboxEntry.subscribed = true;
183498
183549
  }
183499
- return entries.sort((a, b2) => {
183550
+ return entries2.sort((a, b2) => {
183500
183551
  if (a.specialUse && !b2.specialUse) {
183501
183552
  return -1;
183502
183553
  }
@@ -186612,7 +186663,7 @@ var init_imap_flow = __esm(() => {
186612
186663
  return false;
186613
186664
  }
186614
186665
  let finished = false;
186615
- let push = false;
186666
+ let push2 = false;
186616
186667
  let rowQueue = [];
186617
186668
  let getNext = () => new Promise((resolve4, reject) => {
186618
186669
  let check2 = () => {
@@ -186627,8 +186678,8 @@ var init_imap_flow = __esm(() => {
186627
186678
  if (finished) {
186628
186679
  return resolve4(null);
186629
186680
  }
186630
- push = () => {
186631
- push = false;
186681
+ push2 = () => {
186682
+ push2 = false;
186632
186683
  check2();
186633
186684
  };
186634
186685
  };
@@ -186645,19 +186696,19 @@ var init_imap_flow = __esm(() => {
186645
186696
  next
186646
186697
  }
186647
186698
  });
186648
- if (typeof push === "function") {
186649
- push();
186699
+ if (typeof push2 === "function") {
186700
+ push2();
186650
186701
  }
186651
186702
  }
186652
186703
  }).then(() => {
186653
186704
  finished = true;
186654
- if (typeof push === "function") {
186655
- push();
186705
+ if (typeof push2 === "function") {
186706
+ push2();
186656
186707
  }
186657
186708
  }).catch((err) => {
186658
186709
  rowQueue.push({ err });
186659
- if (typeof push === "function") {
186660
- push();
186710
+ if (typeof push2 === "function") {
186711
+ push2();
186661
186712
  }
186662
186713
  });
186663
186714
  let res;
@@ -269903,6 +269954,7 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
269903
269954
  maxSuggestions = 10,
269904
269955
  enableCommands = false,
269905
269956
  onCommandExecute,
269957
+ commandHistory = [],
269906
269958
  showPromptIndicator = false
269907
269959
  }, ref) {
269908
269960
  const { colors: colors2 } = useTheme();
@@ -269910,6 +269962,11 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
269910
269962
  const { registerPromptRef } = useFocus();
269911
269963
  const textareaRef = import_react30.useRef(null);
269912
269964
  const [selectedSuggestionIndex, setSelectedSuggestionIndex] = import_react30.useState(-1);
269965
+ const [historyIndex, setHistoryIndex] = import_react30.useState(-1);
269966
+ const savedInputRef = import_react30.useRef("");
269967
+ const historyRef = import_react30.useRef(commandHistory);
269968
+ historyRef.current = commandHistory;
269969
+ const isNavigatingHistoryRef = import_react30.useRef(false);
269913
269970
  const selectedIndexRef = import_react30.useRef(selectedSuggestionIndex);
269914
269971
  const suggestionsRef = import_react30.useRef([]);
269915
269972
  const onCommandExecuteRef = import_react30.useRef(onCommandExecute);
@@ -269957,28 +270014,76 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
269957
270014
  return () => registerPromptRef(null);
269958
270015
  }, [registerPromptRef]);
269959
270016
  useKeyboard((key) => {
269960
- if (!focused || suggestions.length === 0)
270017
+ if (!focused)
269961
270018
  return;
269962
- if (key.name === "up") {
269963
- setSelectedSuggestionIndex((prev) => prev <= 0 ? suggestions.length - 1 : prev - 1);
270019
+ if (suggestions.length > 0) {
270020
+ if (key.name === "up") {
270021
+ setSelectedSuggestionIndex((prev) => prev <= 0 ? suggestions.length - 1 : prev - 1);
270022
+ return;
270023
+ }
270024
+ if (key.name === "down") {
270025
+ setSelectedSuggestionIndex((prev) => prev >= suggestions.length - 1 ? 0 : prev + 1);
270026
+ return;
270027
+ }
270028
+ if (key.name === "tab") {
270029
+ key.preventDefault?.();
270030
+ const currentSelectedIndex = selectedIndexRef.current;
270031
+ if (currentSelectedIndex >= 0 && currentSelectedIndex < suggestions.length) {
270032
+ const selected = suggestions[currentSelectedIndex];
270033
+ if (selected) {
270034
+ textareaRef.current?.setText(selected.value);
270035
+ setInputValue(selected.value);
270036
+ setSelectedSuggestionIndex(-1);
270037
+ textareaRef.current?.gotoLineEnd();
270038
+ }
270039
+ }
270040
+ return;
270041
+ }
269964
270042
  return;
269965
270043
  }
269966
- if (key.name === "down") {
269967
- setSelectedSuggestionIndex((prev) => prev >= suggestions.length - 1 ? 0 : prev + 1);
270044
+ const history = historyRef.current;
270045
+ if (history.length === 0)
270046
+ return;
270047
+ if (key.name === "up") {
270048
+ setHistoryIndex((prev) => {
270049
+ if (prev === -1) {
270050
+ savedInputRef.current = textareaRef.current?.plainText ?? "";
270051
+ }
270052
+ const next = Math.min(prev + 1, history.length - 1);
270053
+ const entry = history[history.length - 1 - next];
270054
+ if (entry !== undefined) {
270055
+ isNavigatingHistoryRef.current = true;
270056
+ textareaRef.current?.setText(entry);
270057
+ setInputValue(entry);
270058
+ isNavigatingHistoryRef.current = false;
270059
+ setTimeout(() => textareaRef.current?.gotoLineEnd(), 0);
270060
+ }
270061
+ return next;
270062
+ });
269968
270063
  return;
269969
270064
  }
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();
270065
+ if (key.name === "down") {
270066
+ setHistoryIndex((prev) => {
270067
+ if (prev <= 0) {
270068
+ const saved = savedInputRef.current;
270069
+ isNavigatingHistoryRef.current = true;
270070
+ textareaRef.current?.setText(saved);
270071
+ setInputValue(saved);
270072
+ isNavigatingHistoryRef.current = false;
270073
+ setTimeout(() => textareaRef.current?.gotoLineEnd(), 0);
270074
+ return -1;
269980
270075
  }
269981
- }
270076
+ const next = prev - 1;
270077
+ const entry = history[history.length - 1 - next];
270078
+ if (entry !== undefined) {
270079
+ isNavigatingHistoryRef.current = true;
270080
+ textareaRef.current?.setText(entry);
270081
+ setInputValue(entry);
270082
+ isNavigatingHistoryRef.current = false;
270083
+ setTimeout(() => textareaRef.current?.gotoLineEnd(), 0);
270084
+ }
270085
+ return next;
270086
+ });
269982
270087
  return;
269983
270088
  }
269984
270089
  });
@@ -270004,13 +270109,18 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
270004
270109
  setInputValue("");
270005
270110
  textareaRef.current?.setText("");
270006
270111
  setSelectedSuggestionIndex(-1);
270112
+ setHistoryIndex(-1);
270007
270113
  return;
270008
270114
  }
270115
+ setHistoryIndex(-1);
270009
270116
  onSubmitRef.current?.(valueToSubmit);
270010
270117
  };
270011
270118
  const handleContentChange = () => {
270012
270119
  const text = textareaRef.current?.plainText ?? "";
270013
270120
  setInputValue(text);
270121
+ if (historyIndex !== -1 && !isNavigatingHistoryRef.current) {
270122
+ setHistoryIndex(-1);
270123
+ }
270014
270124
  };
270015
270125
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
270016
270126
  flexDirection: "column",
@@ -270092,6 +270202,44 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
270092
270202
  }, undefined, true, undefined, this);
270093
270203
  });
270094
270204
 
270205
+ // src/core/history.ts
270206
+ var STORAGE_KEY = ["command-history"];
270207
+ var MAX_ENTRIES = 500;
270208
+ var entries = null;
270209
+ var loadPromise = null;
270210
+ async function ensureLoaded() {
270211
+ if (entries !== null)
270212
+ return entries;
270213
+ if (!loadPromise) {
270214
+ loadPromise = (async () => {
270215
+ try {
270216
+ const data = await read2(STORAGE_KEY);
270217
+ entries = Array.isArray(data) ? data : [];
270218
+ } catch {
270219
+ entries = [];
270220
+ }
270221
+ })();
270222
+ }
270223
+ await loadPromise;
270224
+ return entries;
270225
+ }
270226
+ async function load() {
270227
+ return ensureLoaded();
270228
+ }
270229
+ async function push(entry) {
270230
+ const history = await ensureLoaded();
270231
+ if (history[history.length - 1] === entry)
270232
+ return;
270233
+ history.push(entry);
270234
+ if (history.length > MAX_ENTRIES) {
270235
+ history.splice(0, history.length - MAX_ENTRIES);
270236
+ }
270237
+ write2(STORAGE_KEY, history).catch(() => {});
270238
+ }
270239
+ function getEntries() {
270240
+ return entries ?? [];
270241
+ }
270242
+
270095
270243
  // src/tui/components/chat/home-view.tsx
270096
270244
  function HomeView({ onNavigate, onStartSession }) {
270097
270245
  const { colors: colors2 } = useTheme();
@@ -270102,6 +270250,10 @@ function HomeView({ onNavigate, onStartSession }) {
270102
270250
  const { setInputValue } = useInput();
270103
270251
  const { promptRef } = useFocus();
270104
270252
  const [hintMessage, setHintMessage] = import_react32.useState(null);
270253
+ const [commandHistory, setCommandHistory] = import_react32.useState(getEntries);
270254
+ import_react32.useEffect(() => {
270255
+ load().then(setCommandHistory);
270256
+ }, []);
270105
270257
  const launchOperator = import_react32.useCallback((message, options) => {
270106
270258
  route.navigate({
270107
270259
  type: "operator",
@@ -270109,11 +270261,15 @@ function HomeView({ onNavigate, onStartSession }) {
270109
270261
  initialConfig: { requireApproval: options?.requireApproval ?? true }
270110
270262
  });
270111
270263
  }, [route]);
270264
+ const pushHistory = import_react32.useCallback((entry) => {
270265
+ push(entry).then(() => setCommandHistory([...getEntries()]));
270266
+ }, []);
270112
270267
  const handleSubmit = import_react32.useCallback((value) => {
270113
270268
  if (!value.trim())
270114
270269
  return;
270270
+ pushHistory(value.trim());
270115
270271
  launchOperator(value.trim());
270116
- }, [launchOperator]);
270272
+ }, [launchOperator, pushHistory]);
270117
270273
  import_react32.useEffect(() => {
270118
270274
  if (!hintMessage)
270119
270275
  return;
@@ -270121,7 +270277,9 @@ function HomeView({ onNavigate, onStartSession }) {
270121
270277
  return () => clearTimeout(timer);
270122
270278
  }, [hintMessage]);
270123
270279
  const handleCommandExecute = import_react32.useCallback(async (command) => {
270124
- const parts = command.trim().replace(/^\/+/, "").split(/\s+/);
270280
+ const trimmed = command.trim();
270281
+ pushHistory(trimmed);
270282
+ const parts = trimmed.replace(/^\/+/, "").split(/\s+/);
270125
270283
  const slug = parts[0]?.toLowerCase() ?? "";
270126
270284
  const args = parts.slice(1);
270127
270285
  const autopilot = args.includes("--autopilot");
@@ -270131,7 +270289,7 @@ function HomeView({ onNavigate, onStartSession }) {
270131
270289
  return;
270132
270290
  }
270133
270291
  await executeCommand(command);
270134
- }, [resolveSkillContent, launchOperator, executeCommand]);
270292
+ }, [resolveSkillContent, launchOperator, executeCommand, pushHistory]);
270135
270293
  const skillItems = skills.slice(0, 5).map((s) => ({
270136
270294
  cmd: `/${slugify(s.name)}`,
270137
270295
  desc: s.description || "skill"
@@ -270272,6 +270430,7 @@ function HomeView({ onNavigate, onStartSession }) {
270272
270430
  autocompleteOptions,
270273
270431
  enableCommands: true,
270274
270432
  onCommandExecute: handleCommandExecute,
270433
+ commandHistory,
270275
270434
  showPromptIndicator: true
270276
270435
  }, undefined, false, undefined, this),
270277
270436
  hintMessage && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
@@ -275044,7 +275203,6 @@ function KeybindingProvider({
275044
275203
  deps
275045
275204
  }) {
275046
275205
  const { promptRef, refocusPrompt } = useFocus();
275047
- const { isInputEmpty } = useInput();
275048
275206
  const { setExternalDialogOpen } = useDialog();
275049
275207
  const registry = createKeybindings({
275050
275208
  ...deps,
@@ -275060,7 +275218,9 @@ function KeybindingProvider({
275060
275218
  if (binding.combo.toLowerCase().startsWith("shift") || binding.combo.toLowerCase() === "?") {
275061
275219
  const textareaRef = promptRef.current?.getTextareaRef();
275062
275220
  const isInputFocused = textareaRef && !textareaRef.isDestroyed && textareaRef.focused;
275063
- if (!isInputFocused || !isInputEmpty) {
275221
+ const actualValue = promptRef.current?.getValue() ?? "";
275222
+ const isPromptEmpty = actualValue.trim().length === 0;
275223
+ if (!isInputFocused || !isPromptEmpty) {
275064
275224
  continue;
275065
275225
  }
275066
275226
  }
@@ -276620,7 +276780,11 @@ var TOOL_SUMMARY_MAP = {
276620
276780
  return `${method} ${url2}`;
276621
276781
  },
276622
276782
  crawl: (args) => `crawl ${args.url || args.target || ""}`,
276623
- execute_command: (args) => `$ ${args.command || ""}`,
276783
+ execute_command: (args) => {
276784
+ const cmd = String(args.command || "").split(`
276785
+ `)[0];
276786
+ return cmd.length > 80 ? `$ ${cmd.slice(0, 80)}…` : `$ ${cmd}`;
276787
+ },
276624
276788
  read_file: (args) => `read ${args.path || ""}`,
276625
276789
  Read: (args) => `read ${args.path || args.file_path || ""}`,
276626
276790
  write_file: (args) => `write ${args.path || ""}`,
@@ -276656,6 +276820,7 @@ var TOOL_SUMMARY_MAP = {
276656
276820
  const targets = args.targets;
276657
276821
  return `pentest swarm ×${targets?.length ?? "?"}`;
276658
276822
  },
276823
+ delegate_to_auth_subagent: (args) => `auth ${args.target || ""} — ${args.reason || ""}`,
276659
276824
  scratchpad: () => "note"
276660
276825
  };
276661
276826
  function getToolSummary(toolName, args) {
@@ -277367,7 +277532,8 @@ var TOOLS_WITH_LOG_WINDOW = new Set([
277367
277532
  "execute_command",
277368
277533
  "run_attack_surface",
277369
277534
  "spawn_coding_agent",
277370
- "spawn_pentest_swarm"
277535
+ "spawn_pentest_swarm",
277536
+ "delegate_to_auth_subagent"
277371
277537
  ]);
277372
277538
  var ToolRenderer = import_react68.memo(function ToolRenderer2({
277373
277539
  message,
@@ -277997,7 +278163,7 @@ function Pentest({ sessionId }) {
277997
278163
  const gridAvailableWidth = showOrchestratorPanel ? Math.floor((termWidth - 4) / 2) - 2 : termWidth - ORCHESTRATOR_PANEL_WIDTH - GRID_OUTER_PADDING;
277998
278164
  const gridColumns = Math.max(1, Math.floor((gridAvailableWidth + GRID_GAP) / (CARD_MIN_WIDTH + GRID_GAP)));
277999
278165
  import_react75.useEffect(() => {
278000
- async function load() {
278166
+ async function load2() {
278001
278167
  try {
278002
278168
  const s2 = await sessions.get(sessionId);
278003
278169
  if (!s2) {
@@ -278041,7 +278207,7 @@ function Pentest({ sessionId }) {
278041
278207
  setPhase("error");
278042
278208
  }
278043
278209
  }
278044
- load();
278210
+ load2();
278045
278211
  }, [sessionId]);
278046
278212
  import_react75.useEffect(() => {
278047
278213
  if (!session)
@@ -279640,7 +279806,8 @@ function NormalInputAreaInner({
279640
279806
  enableAutocomplete = false,
279641
279807
  autocompleteOptions = [],
279642
279808
  enableCommands = false,
279643
- onCommandExecute
279809
+ onCommandExecute,
279810
+ commandHistory = []
279644
279811
  }) {
279645
279812
  const { colors: colors2 } = useTheme();
279646
279813
  const { inputValue, setInputValue } = useInput();
@@ -279698,7 +279865,8 @@ function NormalInputAreaInner({
279698
279865
  enableAutocomplete,
279699
279866
  autocompleteOptions,
279700
279867
  enableCommands,
279701
- onCommandExecute
279868
+ onCommandExecute,
279869
+ commandHistory
279702
279870
  }, undefined, false, undefined, this)
279703
279871
  ]
279704
279872
  }, undefined, true, undefined, this),
@@ -279784,6 +279952,7 @@ function InputArea(props) {
279784
279952
  autocompleteOptions,
279785
279953
  enableCommands,
279786
279954
  onCommandExecute,
279955
+ commandHistory,
279787
279956
  ...normalProps
279788
279957
  } = props;
279789
279958
  if (pendingApproval) {
@@ -279806,6 +279975,7 @@ function InputArea(props) {
279806
279975
  autocompleteOptions,
279807
279976
  enableCommands,
279808
279977
  onCommandExecute,
279978
+ commandHistory,
279809
279979
  ...normalProps
279810
279980
  }, undefined, false, undefined, this)
279811
279981
  }, undefined, false, undefined, this);
@@ -279991,6 +280161,10 @@ function OperatorDashboard({
279991
280161
  const textRef = import_react80.useRef("");
279992
280162
  const conversationRef = import_react80.useRef([]);
279993
280163
  const [inputValue, setInputValue] = import_react80.useState("");
280164
+ const [commandHistory, setCommandHistory] = import_react80.useState(getEntries);
280165
+ import_react80.useEffect(() => {
280166
+ load().then(setCommandHistory);
280167
+ }, []);
279994
280168
  const [operatorState, setOperatorState] = import_react80.useState(() => createInitialOperatorState("manual", true));
279995
280169
  const approvalGateRef = import_react80.useRef(new ApprovalGate({ requireApproval: true }));
279996
280170
  const [pendingApprovals, setPendingApprovals] = import_react80.useState([]);
@@ -280365,8 +280539,10 @@ function OperatorDashboard({
280365
280539
  }
280366
280540
  if (status === "running")
280367
280541
  return;
280542
+ const trimmed = value.trim();
280543
+ push(trimmed).then(() => setCommandHistory([...getEntries()]));
280368
280544
  setInputValue("");
280369
- runAgent(value.trim());
280545
+ runAgent(trimmed);
280370
280546
  }, [status, runAgent]);
280371
280547
  const initialMessageSentRef = import_react80.useRef(false);
280372
280548
  const runAgentRef = import_react80.useRef(runAgent);
@@ -280686,7 +280862,8 @@ function OperatorDashboard({
280686
280862
  enableAutocomplete: true,
280687
280863
  autocompleteOptions,
280688
280864
  enableCommands: true,
280689
- onCommandExecute: handleCommandExecute
280865
+ onCommandExecute: handleCommandExecute,
280866
+ commandHistory
280690
280867
  }, undefined, false, undefined, this)
280691
280868
  ]
280692
280869
  }, undefined, true, undefined, this);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pensar/apex",
3
- "version": "0.0.80",
3
+ "version": "0.0.81-canary.bef8d82a",
4
4
  "description": "AI-powered penetration testing CLI tool with terminal UI",
5
5
  "module": "src/tui/index.tsx",
6
6
  "main": "build/index.js",