@pensar/apex 0.0.103 → 0.0.104

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.
package/bin/pensar.js CHANGED
@@ -73,6 +73,26 @@ if (command === "benchmark") {
73
73
  process.argv = [process.argv[0], uninstallPath, ...args.slice(1)];
74
74
 
75
75
  await import(uninstallPath);
76
+ } else if (command === "projects") {
77
+ const p = join(__dirname, "..", "build", "projects.js");
78
+ process.argv = [process.argv[0], p, ...args.slice(1)];
79
+ await import(p);
80
+ } else if (command === "pentests") {
81
+ const p = join(__dirname, "..", "build", "pentests.js");
82
+ process.argv = [process.argv[0], p, ...args.slice(1)];
83
+ await import(p);
84
+ } else if (command === "issues") {
85
+ const p = join(__dirname, "..", "build", "issues.js");
86
+ process.argv = [process.argv[0], p, ...args.slice(1)];
87
+ await import(p);
88
+ } else if (command === "fixes") {
89
+ const p = join(__dirname, "..", "build", "fixes.js");
90
+ process.argv = [process.argv[0], p, ...args.slice(1)];
91
+ await import(p);
92
+ } else if (command === "logs") {
93
+ const p = join(__dirname, "..", "build", "logs.js");
94
+ process.argv = [process.argv[0], p, ...args.slice(1)];
95
+ await import(p);
76
96
  } else if (command === "upgrade" || command === "update") {
77
97
  const currentVersion = getCurrentVersion();
78
98
  console.log(`Current version: v${currentVersion}`);
@@ -109,6 +129,21 @@ if (command === "benchmark") {
109
129
  console.log(
110
130
  " pensar auth Connect to Pensar Console for managed inference"
111
131
  );
132
+ console.log(
133
+ " pensar projects List workspace projects"
134
+ );
135
+ console.log(
136
+ " pensar pentests List and manage pentests"
137
+ );
138
+ console.log(
139
+ " pensar issues List and manage security issues"
140
+ );
141
+ console.log(
142
+ " pensar fixes View security fixes"
143
+ );
144
+ console.log(
145
+ " pensar logs View agent execution logs"
146
+ );
112
147
  console.log();
113
148
  console.log("Options:");
114
149
  console.log(" -h, --help Show this help message");
@@ -226,6 +261,14 @@ if (command === "benchmark") {
226
261
  console.log(" pensar auth");
227
262
  console.log(" pensar auth status");
228
263
  console.log(" pensar auth logout");
264
+ console.log();
265
+ console.log("Console API:");
266
+ console.log(" pensar projects");
267
+ console.log(" pensar pentests <projectId>");
268
+ console.log(" pensar issues <projectId>");
269
+ console.log(" pensar issues get <issueId>");
270
+ console.log(" pensar fixes <issueId>");
271
+ console.log(" pensar logs <issueId>");
229
272
  } else if (args.length === 0) {
230
273
  // No command specified, run the TUI
231
274
  const appPath = join(__dirname, "..", "build", "index.js");
package/build/auth.js CHANGED
@@ -8,7 +8,7 @@ import fs from "fs/promises";
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "@pensar/apex",
11
- version: "0.0.103",
11
+ version: "0.0.104",
12
12
  description: "AI-powered penetration testing CLI tool with terminal UI",
13
13
  module: "src/tui/index.tsx",
14
14
  main: "build/index.js",
@@ -557,14 +557,31 @@ async function status() {
557
557
  console.log("\nRun `pensar auth login` to connect.");
558
558
  return;
559
559
  }
560
- console.log("\u2713 Connected to Pensar Console");
561
- if (appConfig.workspaceSlug) {
562
- console.log(` Workspace: ${appConfig.workspaceSlug}`);
560
+ if (!appConfig.accessToken && appConfig.pensarAPIKey && !appConfig.workspaceSlug) {
561
+ try {
562
+ const apiUrl = getPensarApiUrl();
563
+ const res = await fetch(`${apiUrl}/auth/validate`, {
564
+ headers: { Authorization: `Bearer ${appConfig.pensarAPIKey}` }
565
+ });
566
+ if (res.ok) {
567
+ const data = await res.json();
568
+ if (data.workspace) {
569
+ await config.update({
570
+ workspaceId: data.workspace.id,
571
+ workspaceSlug: data.workspace.slug
572
+ });
573
+ appConfig.workspaceId = data.workspace.id;
574
+ appConfig.workspaceSlug = data.workspace.slug;
575
+ }
576
+ }
577
+ } catch {}
563
578
  }
579
+ console.log("\u2713 Connected to Pensar Console");
580
+ console.log(` Workspace: ${appConfig.workspaceSlug ?? "not set"}`);
564
581
  if (appConfig.accessToken) {
565
- console.log(" Auth: WorkOS (modern)");
582
+ console.log(" Auth: WorkOS");
566
583
  } else {
567
- console.log(" Auth: API key (legacy)");
584
+ console.log(" Auth: API key");
568
585
  }
569
586
  }
570
587
  function showHelp() {
package/build/index.js CHANGED
@@ -31977,7 +31977,7 @@ var package_default2;
31977
31977
  var init_package = __esm(() => {
31978
31978
  package_default2 = {
31979
31979
  name: "@pensar/apex",
31980
- version: "0.0.103",
31980
+ version: "0.0.104",
31981
31981
  description: "AI-powered penetration testing CLI tool with terminal UI",
31982
31982
  module: "src/tui/index.tsx",
31983
31983
  main: "build/index.js",
@@ -273074,7 +273074,7 @@ var useTerminalDimensions = () => {
273074
273074
  };
273075
273075
 
273076
273076
  // src/tui/index.tsx
273077
- var import_react88 = __toESM(require_react(), 1);
273077
+ var import_react90 = __toESM(require_react(), 1);
273078
273078
 
273079
273079
  // src/tui/components/footer.tsx
273080
273080
  import os6 from "os";
@@ -281225,6 +281225,98 @@ var actionsByKey = new Map(allActions.map((action) => [action.key, action]));
281225
281225
  var actionsById = new Map(allActions.map((action) => [action.id, action]));
281226
281226
  // src/tui/keybindings/keybind.tsx
281227
281227
  var LeaderKeyContext = import_react62.createContext(null);
281228
+ // src/tui/terminal-focus.ts
281229
+ var bracketedFocusModeEnabled = false;
281230
+ function setupTerminalFocusHandling(renderer, options = {}) {
281231
+ const { onTerminalFocus, debug = false } = options;
281232
+ const log2 = (...args) => {
281233
+ if (debug)
281234
+ console.error("[TerminalFocus]", ...args);
281235
+ };
281236
+ const enableBracketedFocus = () => {
281237
+ if (process.stdout.isTTY) {
281238
+ process.stdout.write("\x1B[?1004h");
281239
+ bracketedFocusModeEnabled = true;
281240
+ log2("Enabled bracketed focus mode");
281241
+ }
281242
+ };
281243
+ const disableBracketedFocus = () => {
281244
+ if (process.stdout.isTTY && bracketedFocusModeEnabled) {
281245
+ process.stdout.write("\x1B[?1004l");
281246
+ bracketedFocusModeEnabled = false;
281247
+ log2("Disabled bracketed focus mode");
281248
+ }
281249
+ };
281250
+ const showCursor = () => {
281251
+ if (process.stdout.isTTY) {
281252
+ process.stdout.write("\x1B[?25h");
281253
+ log2("Showed cursor");
281254
+ }
281255
+ };
281256
+ const handleFocusIn = () => {
281257
+ log2("Terminal gained focus");
281258
+ showCursor();
281259
+ renderer.requestRender();
281260
+ if (onTerminalFocus) {
281261
+ setTimeout(() => {
281262
+ onTerminalFocus();
281263
+ log2("Re-focused prompt input");
281264
+ }, 10);
281265
+ }
281266
+ };
281267
+ const handleFocusOut = () => {
281268
+ log2("Terminal lost focus");
281269
+ };
281270
+ const handleSigCont = () => {
281271
+ log2("Received SIGCONT (terminal resumed)");
281272
+ showCursor();
281273
+ renderer.requestRender();
281274
+ if (onTerminalFocus) {
281275
+ setTimeout(() => {
281276
+ onTerminalFocus();
281277
+ log2("Re-focused prompt input after SIGCONT");
281278
+ }, 10);
281279
+ }
281280
+ };
281281
+ let stdinListenerActive = false;
281282
+ const handleStdinData = (data) => {
281283
+ const str = data.toString();
281284
+ if (str.includes("\x1B[I")) {
281285
+ handleFocusIn();
281286
+ }
281287
+ if (str.includes("\x1B[O")) {
281288
+ handleFocusOut();
281289
+ }
281290
+ };
281291
+ const setupListeners = () => {
281292
+ enableBracketedFocus();
281293
+ showCursor();
281294
+ process.on("SIGCONT", handleSigCont);
281295
+ if (process.stdin.isTTY && !stdinListenerActive) {
281296
+ process.stdin.on("data", handleStdinData);
281297
+ stdinListenerActive = true;
281298
+ log2("Set up stdin listener for bracketed focus events");
281299
+ }
281300
+ };
281301
+ const cleanup = () => {
281302
+ log2("Cleaning up terminal focus handling");
281303
+ disableBracketedFocus();
281304
+ process.off("SIGCONT", handleSigCont);
281305
+ if (stdinListenerActive) {
281306
+ process.stdin.off("data", handleStdinData);
281307
+ stdinListenerActive = false;
281308
+ }
281309
+ };
281310
+ setupListeners();
281311
+ return cleanup;
281312
+ }
281313
+ function cleanupTerminalFocusMode() {
281314
+ if (process.stdout.isTTY && bracketedFocusModeEnabled) {
281315
+ process.stdout.write("\x1B[?1004l");
281316
+ bracketedFocusModeEnabled = false;
281317
+ }
281318
+ }
281319
+
281228
281320
  // src/tui/keybindings/registry.ts
281229
281321
  function createKeybindings(deps) {
281230
281322
  const {
@@ -281253,6 +281345,7 @@ function createKeybindings(deps) {
281253
281345
  const now2 = Date.now();
281254
281346
  const lastPress = ctrlCPressTime;
281255
281347
  if (lastPress && now2 - lastPress < 1000) {
281348
+ cleanupTerminalFocusMode();
281256
281349
  renderer.destroy();
281257
281350
  process.exit(0);
281258
281351
  } else {
@@ -291109,74 +291202,92 @@ function setupAutoCopy(renderer, copyToClipboard) {
291109
291202
  });
291110
291203
  }
291111
291204
 
291205
+ // src/tui/components/terminal-focus-handler.tsx
291206
+ var import_react87 = __toESM(require_react(), 1);
291207
+ function TerminalFocusHandler() {
291208
+ const { refocusPrompt } = useFocus();
291209
+ const renderer = useRenderer();
291210
+ import_react87.useEffect(() => {
291211
+ const cleanup = setupTerminalFocusHandling(renderer, {
291212
+ onTerminalFocus: refocusPrompt,
291213
+ debug: false
291214
+ });
291215
+ return cleanup;
291216
+ }, [renderer, refocusPrompt]);
291217
+ return null;
291218
+ }
291219
+
291112
291220
  // src/tui/index.tsx
291113
291221
  function App({ appConfig }) {
291114
- const [focusIndex, setFocusIndex] = import_react88.useState(0);
291115
- const [cwd, setCwd] = import_react88.useState(process.cwd());
291116
- const [ctrlCPressTime, setCtrlCPressTime] = import_react88.useState(null);
291117
- const [showExitWarning, setShowExitWarning] = import_react88.useState(false);
291118
- const [inputKey, setInputKey] = import_react88.useState(0);
291119
- const [showSessionsDialog, setShowSessionsDialog] = import_react88.useState(false);
291120
- const [showShortcutsDialog, setShowShortcutsDialog] = import_react88.useState(false);
291121
- const [showThemeDialog, setShowThemeDialog] = import_react88.useState(false);
291122
- const [showAuthDialog, setShowAuthDialog] = import_react88.useState(false);
291123
- const [showPentestDialog, setShowPentestDialog] = import_react88.useState(false);
291124
- const [pendingPentestFlags, setPendingPentestFlags] = import_react88.useState(undefined);
291222
+ const [focusIndex, setFocusIndex] = import_react90.useState(0);
291223
+ const [cwd, setCwd] = import_react90.useState(process.cwd());
291224
+ const [ctrlCPressTime, setCtrlCPressTime] = import_react90.useState(null);
291225
+ const [showExitWarning, setShowExitWarning] = import_react90.useState(false);
291226
+ const [inputKey, setInputKey] = import_react90.useState(0);
291227
+ const [showSessionsDialog, setShowSessionsDialog] = import_react90.useState(false);
291228
+ const [showShortcutsDialog, setShowShortcutsDialog] = import_react90.useState(false);
291229
+ const [showThemeDialog, setShowThemeDialog] = import_react90.useState(false);
291230
+ const [showAuthDialog, setShowAuthDialog] = import_react90.useState(false);
291231
+ const [showPentestDialog, setShowPentestDialog] = import_react90.useState(false);
291232
+ const [pendingPentestFlags, setPendingPentestFlags] = import_react90.useState(undefined);
291125
291233
  const navigableItems = ["command-input"];
291126
291234
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ConfigProvider, {
291127
291235
  config: appConfig,
291128
291236
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(SessionProvider, {
291129
291237
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(RouteProvider, {
291130
291238
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(FocusProvider, {
291131
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(InputProvider, {
291132
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(DialogProvider, {
291133
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AgentProvider, {
291134
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(CommandProvider, {
291135
- onOpenSessionsDialog: () => setShowSessionsDialog(true),
291136
- onOpenThemeDialog: () => setShowThemeDialog(true),
291137
- onOpenAuthDialog: () => setShowAuthDialog(true),
291138
- onOpenPentestDialog: (flags) => {
291139
- setPendingPentestFlags(flags);
291140
- setShowPentestDialog(true);
291141
- },
291142
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(KeybindingProvider, {
291143
- deps: {
291144
- ctrlCPressTime,
291145
- setCtrlCPressTime,
291146
- setShowExitWarning,
291147
- setInputKey,
291148
- setShowSessionsDialog,
291149
- setShowShortcutsDialog,
291150
- setFocusIndex,
291151
- navigableItems
291239
+ children: [
291240
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(TerminalFocusHandler, {}, undefined, false, undefined, this),
291241
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(InputProvider, {
291242
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(DialogProvider, {
291243
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AgentProvider, {
291244
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(CommandProvider, {
291245
+ onOpenSessionsDialog: () => setShowSessionsDialog(true),
291246
+ onOpenThemeDialog: () => setShowThemeDialog(true),
291247
+ onOpenAuthDialog: () => setShowAuthDialog(true),
291248
+ onOpenPentestDialog: (flags) => {
291249
+ setPendingPentestFlags(flags);
291250
+ setShowPentestDialog(true);
291152
291251
  },
291153
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AppContent, {
291154
- focusIndex,
291155
- showSessionsDialog,
291156
- setShowSessionsDialog,
291157
- showShortcutsDialog,
291158
- setShowShortcutsDialog,
291159
- showThemeDialog,
291160
- setShowThemeDialog,
291161
- showAuthDialog,
291162
- setShowAuthDialog,
291163
- showPentestDialog,
291164
- setShowPentestDialog,
291165
- pendingPentestFlags,
291166
- setPendingPentestFlags,
291167
- cwd,
291168
- setCtrlCPressTime,
291169
- showExitWarning,
291170
- setShowExitWarning,
291171
- inputKey,
291172
- setInputKey
291252
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(KeybindingProvider, {
291253
+ deps: {
291254
+ ctrlCPressTime,
291255
+ setCtrlCPressTime,
291256
+ setShowExitWarning,
291257
+ setInputKey,
291258
+ setShowSessionsDialog,
291259
+ setShowShortcutsDialog,
291260
+ setFocusIndex,
291261
+ navigableItems
291262
+ },
291263
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AppContent, {
291264
+ focusIndex,
291265
+ showSessionsDialog,
291266
+ setShowSessionsDialog,
291267
+ showShortcutsDialog,
291268
+ setShowShortcutsDialog,
291269
+ showThemeDialog,
291270
+ setShowThemeDialog,
291271
+ showAuthDialog,
291272
+ setShowAuthDialog,
291273
+ showPentestDialog,
291274
+ setShowPentestDialog,
291275
+ pendingPentestFlags,
291276
+ setPendingPentestFlags,
291277
+ cwd,
291278
+ setCtrlCPressTime,
291279
+ showExitWarning,
291280
+ setShowExitWarning,
291281
+ inputKey,
291282
+ setInputKey
291283
+ }, undefined, false, undefined, this)
291173
291284
  }, undefined, false, undefined, this)
291174
291285
  }, undefined, false, undefined, this)
291175
291286
  }, undefined, false, undefined, this)
291176
291287
  }, undefined, false, undefined, this)
291177
291288
  }, undefined, false, undefined, this)
291178
- }, undefined, false, undefined, this)
291179
- }, undefined, false, undefined, this)
291289
+ ]
291290
+ }, undefined, true, undefined, this)
291180
291291
  }, undefined, false, undefined, this)
291181
291292
  }, undefined, false, undefined, this)
291182
291293
  }, undefined, false, undefined, this);
@@ -291208,14 +291319,14 @@ function AppContent({
291208
291319
  const { toast } = useToast();
291209
291320
  const { refocusPrompt } = useFocus();
291210
291321
  const { setExternalDialogOpen } = useDialog();
291211
- import_react88.useEffect(() => {
291322
+ import_react90.useEffect(() => {
291212
291323
  checkForUpdate().then(({ updateAvailable, currentVersion, latestVersion }) => {
291213
291324
  if (!updateAvailable)
291214
291325
  return;
291215
291326
  toast(`Update available: v${currentVersion} → v${latestVersion}. Run: pensar upgrade`, "warn", 8000);
291216
291327
  });
291217
291328
  }, []);
291218
- import_react88.useEffect(() => {
291329
+ import_react90.useEffect(() => {
291219
291330
  if (route.data.type !== "base")
291220
291331
  return;
291221
291332
  if (!config3.data.responsibleUseAccepted && route.data.path !== "disclosure") {
@@ -291224,12 +291335,12 @@ function AppContent({
291224
291335
  route.navigate({ type: "base", path: "providers" });
291225
291336
  }
291226
291337
  }, [config3.data.responsibleUseAccepted, route.data]);
291227
- import_react88.useEffect(() => {
291338
+ import_react90.useEffect(() => {
291228
291339
  if (showThemeDialog || showAuthDialog || showPentestDialog) {
291229
291340
  setExternalDialogOpen(true);
291230
291341
  }
291231
291342
  }, [showThemeDialog, showAuthDialog, showPentestDialog]);
291232
- import_react88.useEffect(() => {
291343
+ import_react90.useEffect(() => {
291233
291344
  if (showExitWarning) {
291234
291345
  const timer = setTimeout(() => {
291235
291346
  setShowExitWarning(false);
@@ -291461,18 +291572,21 @@ async function main2() {
291461
291572
  const { copyToClipboard } = createClipboardManager(renderer);
291462
291573
  setupAutoCopy(renderer, copyToClipboard);
291463
291574
  const cleanup = () => {
291575
+ cleanupTerminalFocusMode();
291464
291576
  renderer.destroy();
291465
291577
  process.exit(0);
291466
291578
  };
291467
291579
  process.on("SIGINT", cleanup);
291468
291580
  process.on("SIGTERM", cleanup);
291469
291581
  process.on("uncaughtException", (err) => {
291582
+ cleanupTerminalFocusMode();
291470
291583
  renderer.destroy();
291471
291584
  console.error("Uncaught exception:", err);
291472
291585
  writeErrorLog(err, "UNCAUGHT");
291473
291586
  process.exit(1);
291474
291587
  });
291475
291588
  process.on("unhandledRejection", (reason) => {
291589
+ cleanupTerminalFocusMode();
291476
291590
  renderer.destroy();
291477
291591
  console.error("Unhandled rejection:", reason);
291478
291592
  writeErrorLog(reason, "UNHANDLED_REJECTION");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pensar/apex",
3
- "version": "0.0.103",
3
+ "version": "0.0.104",
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",