@pensar/apex 0.0.88 → 0.0.89-canary.4a30c15b

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 +722 -459
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -31971,7 +31971,7 @@ var package_default2;
31971
31971
  var init_package = __esm(() => {
31972
31972
  package_default2 = {
31973
31973
  name: "@pensar/apex",
31974
- version: "0.0.88",
31974
+ version: "0.0.89-canary.4a30c15b",
31975
31975
  description: "AI-powered penetration testing CLI tool with terminal UI",
31976
31976
  module: "src/tui/index.tsx",
31977
31977
  main: "build/index.js",
@@ -87849,6 +87849,28 @@ function createPensarModel(bedrockModelId, config2) {
87849
87849
  }
87850
87850
  return headers;
87851
87851
  }
87852
+ let cachedStreamUrl = null;
87853
+ async function getStreamUrl() {
87854
+ if (cachedStreamUrl)
87855
+ return cachedStreamUrl;
87856
+ try {
87857
+ const headers = await buildHeaders();
87858
+ const res = await fetch(`${config2.baseUrl}/bedrock/validate`, {
87859
+ headers
87860
+ });
87861
+ if (res.ok) {
87862
+ const data = await res.json();
87863
+ if (data.endpoints?.stream) {
87864
+ cachedStreamUrl = data.endpoints.stream;
87865
+ log(` Discovered stream URL: ${cachedStreamUrl}`);
87866
+ return cachedStreamUrl;
87867
+ }
87868
+ }
87869
+ } catch {}
87870
+ cachedStreamUrl = `${config2.baseUrl}/bedrock/invoke`;
87871
+ log(` Using fallback stream URL: ${cachedStreamUrl}`);
87872
+ return cachedStreamUrl;
87873
+ }
87852
87874
  const model = {
87853
87875
  specificationVersion: "v2",
87854
87876
  provider: "pensar",
@@ -87917,7 +87939,7 @@ function createPensarModel(bedrockModelId, config2) {
87917
87939
  },
87918
87940
  async doStream(options) {
87919
87941
  const body = convertToBedrockFormat(bedrockModelId, options);
87920
- const url2 = `${config2.baseUrl}/bedrock/stream`;
87942
+ const url2 = await getStreamUrl();
87921
87943
  log(`doStream → SSE streaming for ${bedrockModelId}`);
87922
87944
  log(` URL: ${url2}`);
87923
87945
  const headers = await buildHeaders();
@@ -87929,7 +87951,8 @@ function createPensarModel(bedrockModelId, config2) {
87929
87951
  signal: options.abortSignal,
87930
87952
  body: JSON.stringify({
87931
87953
  modelId: bedrockModelId,
87932
- body
87954
+ body,
87955
+ stream: true
87933
87956
  })
87934
87957
  });
87935
87958
  } catch (err) {
@@ -88441,7 +88464,8 @@ async function summarizeConversation(messages, opts, model) {
88441
88464
  const { text: summary, usage: summaryUsage } = await generateText({
88442
88465
  model,
88443
88466
  system: `You are a helpful assistant that summarizes conversations to pass to another agent. Review the conversation and system prompt at the end provided by the user.`,
88444
- messages: summarizedMessages
88467
+ messages: summarizedMessages,
88468
+ abortSignal: opts.abortSignal
88445
88469
  });
88446
88470
  if (opts.onStepFinish && summaryUsage) {
88447
88471
  opts.onStepFinish({
@@ -88719,7 +88743,8 @@ function streamResponse(opts) {
88719
88743
  "IMPORTANT: For enum fields like 'severity' or 'riskLevel', use ONLY the exact values from the enum (e.g., 'HIGH', 'CRITICAL', 'MEDIUM', 'LOW').",
88720
88744
  "Do not add prefixes, suffixes, or formatting characters like '>', '-', '!', etc."
88721
88745
  ].join(`
88722
- `)
88746
+ `),
88747
+ abortSignal
88723
88748
  });
88724
88749
  if (onStepFinish && repairUsage) {
88725
88750
  onStepFinish({
@@ -88787,6 +88812,7 @@ async function generateObjectResponse(opts) {
88787
88812
  maxTokens,
88788
88813
  temperature,
88789
88814
  authConfig,
88815
+ abortSignal,
88790
88816
  onTokenUsage
88791
88817
  } = opts;
88792
88818
  const providerModel = getProviderModel(model, authConfig);
@@ -88802,7 +88828,8 @@ async function generateObjectResponse(opts) {
88802
88828
  system,
88803
88829
  maxOutputTokens: maxTokens,
88804
88830
  temperature,
88805
- maxRetries: 0
88831
+ maxRetries: 0,
88832
+ abortSignal
88806
88833
  });
88807
88834
  if (onTokenUsage && usage) {
88808
88835
  onTokenUsage(usage.inputTokens ?? 0, usage.outputTokens ?? 0);
@@ -88849,7 +88876,7 @@ function generateRandomName() {
88849
88876
  return `${adj}-${noun}`;
88850
88877
  }
88851
88878
  async function generateSessionName(opts) {
88852
- const { targets, userMessage, model, authConfig } = opts;
88879
+ const { targets, userMessage, model, authConfig, abortSignal } = opts;
88853
88880
  const contextParts = [];
88854
88881
  if (targets.length > 0) {
88855
88882
  contextParts.push(`Target(s): ${targets.join(", ")}`);
@@ -88874,7 +88901,8 @@ async function generateSessionName(opts) {
88874
88901
  prompt,
88875
88902
  maxTokens: 50,
88876
88903
  temperature: 0.7,
88877
- authConfig
88904
+ authConfig,
88905
+ abortSignal
88878
88906
  });
88879
88907
  if (!result?.name)
88880
88908
  return null;
@@ -106937,7 +106965,7 @@ IMPORTANT: Always analyze results and adjust your approach based on findings.`,
106937
106965
  }
106938
106966
  if (ctx4.persistentShell) {
106939
106967
  try {
106940
- const result = await ctx4.persistentShell.execute(command, timeout, ctx4.onCommandOutput);
106968
+ const result = await ctx4.persistentShell.execute(command, timeout, ctx4.onCommandOutput, ctx4.abortSignal);
106941
106969
  const { text: stdout, file: outputFile } = maybeSaveFullOutput(result.stdout, ctx4);
106942
106970
  return {
106943
106971
  success: result.exitCode === 0,
@@ -107845,14 +107873,15 @@ var init_cvss = __esm(() => {
107845
107873
  });
107846
107874
 
107847
107875
  // src/core/agents/specialized/cvssScorer/index.ts
107848
- async function scoreFindingWithCVSS(input, model, authConfig) {
107876
+ async function scoreFindingWithCVSS(input, model, authConfig, abortSignal) {
107849
107877
  const prompt = buildScoringPrompt(input);
107850
107878
  const assessment = await generateObjectResponse({
107851
107879
  model,
107852
107880
  schema: CVSSMetricsOutputSchema,
107853
107881
  prompt,
107854
107882
  system: CVSS_SCORER_SYSTEM_PROMPT,
107855
- authConfig
107883
+ authConfig,
107884
+ abortSignal
107856
107885
  });
107857
107886
  const cvssResult = calculateCVSS4Score({
107858
107887
  ...assessment.metrics
@@ -108120,7 +108149,7 @@ FINDING STRUCTURE:
108120
108149
  remediation: input.remediation
108121
108150
  },
108122
108151
  agentMessages: []
108123
- }, ctx4.model, ctx4.authConfig);
108152
+ }, ctx4.model, ctx4.authConfig, ctx4.abortSignal);
108124
108153
  } catch (cvssError) {
108125
108154
  const msg = cvssError instanceof Error ? cvssError.message : String(cvssError);
108126
108155
  cvssWarning = `CVSS scoring failed (${msg}), using fallback severity.`;
@@ -111302,10 +111331,12 @@ class FindingsRegistry {
111302
111331
  findings = [];
111303
111332
  model;
111304
111333
  authConfig;
111334
+ abortSignal;
111305
111335
  mutex = Promise.resolve();
111306
111336
  constructor(opts) {
111307
111337
  this.model = opts?.model;
111308
111338
  this.authConfig = opts?.authConfig;
111339
+ this.abortSignal = opts?.abortSignal;
111309
111340
  }
111310
111341
  get size() {
111311
111342
  return this.findings.length;
@@ -111402,7 +111433,8 @@ class FindingsRegistry {
111402
111433
  schema: SemanticDedupResultSchema,
111403
111434
  prompt,
111404
111435
  system: SEMANTIC_DEDUP_SYSTEM,
111405
- authConfig: this.authConfig
111436
+ authConfig: this.authConfig,
111437
+ abortSignal: this.abortSignal
111406
111438
  });
111407
111439
  if (result.isDuplicate && result.matchedIndex != null) {
111408
111440
  const idx = result.matchedIndex - 1;
@@ -111526,7 +111558,8 @@ Pass every target you want tested — the swarm handles concurrency automaticall
111526
111558
  }
111527
111559
  const findingsRegistry = ctx4.findingsRegistry ?? FindingsRegistry.fromDirectory(ctx4.session.findingsPath, {
111528
111560
  model: ctx4.model,
111529
- authConfig: ctx4.authConfig
111561
+ authConfig: ctx4.authConfig,
111562
+ abortSignal: ctx4.abortSignal
111530
111563
  });
111531
111564
  const total = targets.length;
111532
111565
  console.log(`
@@ -193567,10 +193600,17 @@ class PersistentShell {
193567
193600
  this.spawn();
193568
193601
  }
193569
193602
  }
193570
- async execute(command, timeoutSeconds, onData) {
193603
+ async execute(command, timeoutSeconds, onData, abortSignal) {
193571
193604
  if (this.disposed) {
193572
193605
  return { stdout: "", stderr: "Shell has been disposed", exitCode: 1 };
193573
193606
  }
193607
+ if (abortSignal?.aborted) {
193608
+ return {
193609
+ stdout: "",
193610
+ stderr: "Command aborted",
193611
+ exitCode: 130
193612
+ };
193613
+ }
193574
193614
  this.ensureAlive();
193575
193615
  const proc = this.proc;
193576
193616
  if (!proc || !proc.stdin || !proc.stdout || !proc.stderr) {
@@ -193595,11 +193635,39 @@ class PersistentShell {
193595
193635
  this.pendingStderr = null;
193596
193636
  if (timeoutTimer)
193597
193637
  clearTimeout(timeoutTimer);
193638
+ if (abortCleanup)
193639
+ abortCleanup();
193598
193640
  proc.stdout.removeListener("data", onStdout);
193599
193641
  proc.stderr.removeListener("data", onStderr);
193642
+ proc.removeListener("close", onClose);
193600
193643
  resolve4(result);
193601
193644
  };
193602
193645
  this.pendingCancel = safeResolve;
193646
+ let abortCleanup;
193647
+ if (abortSignal) {
193648
+ const onAbort = () => {
193649
+ if (resolved)
193650
+ return;
193651
+ const pid = proc.pid;
193652
+ if (pid && process.platform !== "win32") {
193653
+ try {
193654
+ spawnSync("pkill", ["-TERM", "-P", pid.toString()], {
193655
+ stdio: "ignore"
193656
+ });
193657
+ } catch {}
193658
+ }
193659
+ setTimeout(() => {
193660
+ safeResolve({
193661
+ stdout: stdout || "(no output)",
193662
+ stderr: stderr ? stderr + `
193663
+ (aborted)` : "(aborted)",
193664
+ exitCode: 130
193665
+ });
193666
+ }, 500);
193667
+ };
193668
+ abortSignal.addEventListener("abort", onAbort, { once: true });
193669
+ abortCleanup = () => abortSignal.removeEventListener("abort", onAbort);
193670
+ }
193603
193671
  const onStdout = (data) => {
193604
193672
  const chunk = data.toString();
193605
193673
  if (onData && !chunk.includes(exitMarkerPrefix)) {
@@ -194504,6 +194572,35 @@ For \`http_request\`, pass these as the \`headers\` parameter.`, `For \`execute_
194504
194572
  The following vulnerabilities have already been documented. Do NOT re-test or re-document these — the system will automatically reject duplicates.
194505
194573
  ${existing}`;
194506
194574
  }
194575
+ let knowledgeBaseSection = "";
194576
+ const markerPath = join24(sessionRootPath, "scratchpad", ".knowledge-populated");
194577
+ if (existsSync23(markerPath)) {
194578
+ try {
194579
+ const count = parseInt(readFileSync9(markerPath, "utf-8").trim(), 10) || 0;
194580
+ if (count > 0) {
194581
+ knowledgeBaseSection = `
194582
+
194583
+ ## Project Knowledge Available
194584
+ There are ${count} project knowledge entries in the memory system from previous scans, user notes, and resolved issues. Before beginning your testing plan, call \`list_memories\` with tag \`"project-knowledge"\` to check for relevant context. Pay special attention to false positive patterns and technology context that may affect your testing.`;
194585
+ }
194586
+ } catch {}
194587
+ }
194588
+ if (!knowledgeBaseSection) {
194589
+ const knowledgePath = join24(sessionRootPath, "scratchpad", "knowledge-base.md");
194590
+ if (existsSync23(knowledgePath)) {
194591
+ try {
194592
+ const knowledgeContent = readFileSync9(knowledgePath, "utf-8").trim();
194593
+ if (knowledgeContent) {
194594
+ knowledgeBaseSection = `
194595
+
194596
+ ## Project Knowledge Base
194597
+ The following is accumulated knowledge about this project from previous scans, user notes, and resolved issues. Use this context to avoid false positives and make better testing decisions.
194598
+
194599
+ ${knowledgeContent}`;
194600
+ }
194601
+ } catch {}
194602
+ }
194603
+ }
194507
194604
  const outcomeSection = outcomeGuidance ? `
194508
194605
  ## Outcome Guidance
194509
194606
  ${outcomeGuidance}
@@ -194535,6 +194632,7 @@ Do NOT discover or enumerate other endpoints or services. Focus exclusively on t
194535
194632
  - **URL:** ${target}
194536
194633
  ${authSection}
194537
194634
  ${knownFindingsSection}
194635
+ ${knowledgeBaseSection}
194538
194636
 
194539
194637
  ## Objectives
194540
194638
  ${objectiveList}
@@ -194685,7 +194783,9 @@ var init_agent4 = __esm(() => {
194685
194783
  "email_list_inboxes",
194686
194784
  "email_list_messages",
194687
194785
  "email_search_messages",
194688
- "email_get_message"
194786
+ "email_get_message",
194787
+ "list_memories",
194788
+ "get_memory"
194689
194789
  ],
194690
194790
  responseSchema: PentestResponseSchema,
194691
194791
  resolveResult: () => {
@@ -195516,7 +195616,8 @@ async function runPentestWorkflow(input) {
195516
195616
  }
195517
195617
  const findingsRegistry = FindingsRegistry.fromDirectory(session.findingsPath, {
195518
195618
  model,
195519
- authConfig
195619
+ authConfig,
195620
+ abortSignal
195520
195621
  });
195521
195622
  await runPentestSwarm({
195522
195623
  targets: swarmTargets,
@@ -272247,7 +272348,7 @@ var useTerminalDimensions = () => {
272247
272348
  };
272248
272349
 
272249
272350
  // src/tui/index.tsx
272250
- var import_react86 = __toESM(require_react(), 1);
272351
+ var import_react88 = __toESM(require_react(), 1);
272251
272352
 
272252
272353
  // src/tui/components/footer.tsx
272253
272354
  import os6 from "os";
@@ -273336,6 +273437,7 @@ var commands = [
273336
273437
  const params = buildOperatorSessionConfig(flags);
273337
273438
  ctx3.navigate({
273338
273439
  type: "operator",
273440
+ nonce: Date.now(),
273339
273441
  initialConfig: {
273340
273442
  requireApproval: flags.requireApproval ?? true,
273341
273443
  target: flags.target
@@ -273396,6 +273498,14 @@ var commands = [
273396
273498
  ctx3.openSessionsDialog?.();
273397
273499
  }
273398
273500
  },
273501
+ {
273502
+ name: "new",
273503
+ description: "Start a new operator session",
273504
+ category: "Session",
273505
+ handler: async (args, ctx3) => {
273506
+ ctx3.navigate({ type: "operator", nonce: Date.now() });
273507
+ }
273508
+ },
273399
273509
  {
273400
273510
  name: "chat",
273401
273511
  aliases: ["c"],
@@ -273447,7 +273557,7 @@ var commands = [
273447
273557
  }
273448
273558
  return;
273449
273559
  }
273450
- ctx3.navigate({ type: "base", path: "theme" });
273560
+ ctx3.openThemeDialog?.();
273451
273561
  }
273452
273562
  },
273453
273563
  {
@@ -273476,10 +273586,7 @@ var commands = [
273476
273586
  description: "Connect to Pensar Console for managed inference",
273477
273587
  category: "General",
273478
273588
  handler: async (args, ctx3) => {
273479
- ctx3.navigate({
273480
- type: "base",
273481
- path: "auth"
273482
- });
273589
+ ctx3.openAuthDialog?.();
273483
273590
  }
273484
273591
  },
273485
273592
  {
@@ -273616,7 +273723,9 @@ function useCommand() {
273616
273723
  }
273617
273724
  function CommandProvider({
273618
273725
  children,
273619
- onOpenSessionsDialog
273726
+ onOpenSessionsDialog,
273727
+ onOpenThemeDialog,
273728
+ onOpenAuthDialog
273620
273729
  }) {
273621
273730
  const route = useRoute();
273622
273731
  const [skills, setSkills] = import_react17.useState([]);
@@ -273624,10 +273733,12 @@ function CommandProvider({
273624
273733
  const ctx4 = {
273625
273734
  route: route.data,
273626
273735
  navigate: route.navigate,
273627
- openSessionsDialog: onOpenSessionsDialog
273736
+ openSessionsDialog: onOpenSessionsDialog,
273737
+ openThemeDialog: onOpenThemeDialog,
273738
+ openAuthDialog: onOpenAuthDialog
273628
273739
  };
273629
273740
  return ctx4;
273630
- }, [route, onOpenSessionsDialog]);
273741
+ }, [route, onOpenSessionsDialog, onOpenThemeDialog, onOpenAuthDialog]);
273631
273742
  const refreshSkills = import_react17.useCallback(async () => {
273632
273743
  const loaded = await loadSkills();
273633
273744
  setSkills(loaded);
@@ -274866,6 +274977,12 @@ function shouldResetHistory(historyIndex, isNavigatingHistory) {
274866
274977
  }
274867
274978
 
274868
274979
  // src/tui/components/shared/prompt-input.tsx
274980
+ var chatKeyBindings = [
274981
+ { name: "return", action: "submit" },
274982
+ { name: "linefeed", action: "newline" },
274983
+ { name: "return", shift: true, action: "newline" },
274984
+ { name: "linefeed", shift: true, action: "newline" }
274985
+ ];
274869
274986
  var PromptInput = import_react29.forwardRef(function PromptInput2({
274870
274987
  width,
274871
274988
  minHeight = 1,
@@ -274885,7 +275002,8 @@ var PromptInput = import_react29.forwardRef(function PromptInput2({
274885
275002
  onCommandExecute,
274886
275003
  commandHistory = [],
274887
275004
  disableHistoryNavigation = false,
274888
- showPromptIndicator = false
275005
+ showPromptIndicator = false,
275006
+ autocompletePlacement = "below"
274889
275007
  }, ref) {
274890
275008
  const { colors: colors2 } = useTheme();
274891
275009
  const { inputValue, setInputValue } = useInput();
@@ -275035,9 +275153,38 @@ var PromptInput = import_react29.forwardRef(function PromptInput2({
275035
275153
  setHistoryIndex(-1);
275036
275154
  }
275037
275155
  };
275156
+ const suggestionsBox = suggestions.length > 0 && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
275157
+ flexDirection: "column",
275158
+ ...autocompletePlacement === "above" ? { marginBottom: 1 } : { marginTop: 1 },
275159
+ children: suggestions.map((suggestion, index) => {
275160
+ const isSelected = index === selectedSuggestionIndex;
275161
+ return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
275162
+ flexDirection: "row",
275163
+ gap: 1,
275164
+ children: [
275165
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
275166
+ fg: isSelected ? colors2.primary : colors2.textMuted,
275167
+ children: isSelected ? " ▸" : " "
275168
+ }, undefined, false, undefined, this),
275169
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
275170
+ fg: isSelected ? colors2.text : colors2.textMuted,
275171
+ children: suggestion.label
275172
+ }, undefined, false, undefined, this),
275173
+ suggestion.description && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
275174
+ fg: colors2.textMuted,
275175
+ children: [
275176
+ " ",
275177
+ suggestion.description
275178
+ ]
275179
+ }, undefined, true, undefined, this)
275180
+ ]
275181
+ }, suggestion.value, true, undefined, this);
275182
+ })
275183
+ }, undefined, false, undefined, this);
275038
275184
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
275039
275185
  flexDirection: "column",
275040
275186
  children: [
275187
+ autocompletePlacement === "above" && suggestionsBox,
275041
275188
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
275042
275189
  flexDirection: "row",
275043
275190
  children: [
@@ -275058,59 +275205,13 @@ var PromptInput = import_react29.forwardRef(function PromptInput2({
275058
275205
  backgroundColor,
275059
275206
  focusedBackgroundColor,
275060
275207
  cursorColor: cursorColor ?? colors2.textMuted,
275061
- keyBindings: [
275062
- {
275063
- action: "submit",
275064
- name: "return"
275065
- },
275066
- {
275067
- action: "submit",
275068
- name: "linefeed"
275069
- },
275070
- {
275071
- action: "newline",
275072
- shift: true,
275073
- name: "return"
275074
- },
275075
- {
275076
- action: "newline",
275077
- shift: true,
275078
- name: "linefeed"
275079
- }
275080
- ],
275208
+ keyBindings: chatKeyBindings,
275081
275209
  onContentChange: handleContentChange,
275082
275210
  onSubmit: handleSubmit
275083
275211
  }, undefined, false, undefined, this)
275084
275212
  ]
275085
275213
  }, undefined, true, undefined, this),
275086
- suggestions.length > 0 && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
275087
- flexDirection: "column",
275088
- marginTop: 1,
275089
- children: suggestions.map((suggestion, index) => {
275090
- const isSelected = index === selectedSuggestionIndex;
275091
- return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
275092
- flexDirection: "row",
275093
- gap: 1,
275094
- children: [
275095
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
275096
- fg: isSelected ? colors2.primary : colors2.textMuted,
275097
- children: isSelected ? " ▸" : " "
275098
- }, undefined, false, undefined, this),
275099
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
275100
- fg: isSelected ? colors2.text : colors2.textMuted,
275101
- children: suggestion.label
275102
- }, undefined, false, undefined, this),
275103
- suggestion.description && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
275104
- fg: colors2.textMuted,
275105
- children: [
275106
- " ",
275107
- suggestion.description
275108
- ]
275109
- }, undefined, true, undefined, this)
275110
- ]
275111
- }, suggestion.value, true, undefined, this);
275112
- })
275113
- }, undefined, false, undefined, this)
275214
+ autocompletePlacement === "below" && suggestionsBox
275114
275215
  ]
275115
275216
  }, undefined, true, undefined, this);
275116
275217
  });
@@ -275163,6 +275264,7 @@ function HomeView({ onNavigate, onStartSession }) {
275163
275264
  const { executeCommand, autocompleteOptions, resolveSkillContent, skills } = useCommand();
275164
275265
  const { setInputValue } = useInput();
275165
275266
  const { promptRef } = useFocus();
275267
+ const { externalDialogOpen, stack } = useDialog();
275166
275268
  const [hintMessage, setHintMessage] = import_react31.useState(null);
275167
275269
  const [commandHistory, setCommandHistory] = import_react31.useState(getEntries);
275168
275270
  import_react31.useEffect(() => {
@@ -275330,7 +275432,7 @@ function HomeView({ onNavigate, onStartSession }) {
275330
275432
  children: [
275331
275433
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(PromptInput, {
275332
275434
  ref: promptRef,
275333
- focused: true,
275435
+ focused: !externalDialogOpen && stack.length === 0,
275334
275436
  width: inputWidth - 4,
275335
275437
  minHeight: 1,
275336
275438
  maxHeight: 4,
@@ -278667,8 +278769,8 @@ function ModelsDisplay() {
278667
278769
  // src/tui/components/commands/auth-flow.tsx
278668
278770
  var import_react57 = __toESM(require_react(), 1);
278669
278771
  init_config2();
278670
- function AuthFlow() {
278671
- const route = useRoute();
278772
+ function AuthFlow({ onClose }) {
278773
+ const { colors: colors2 } = useTheme();
278672
278774
  const appConfig = useConfig();
278673
278775
  const isConnected = !!(appConfig.data.accessToken || appConfig.data.pensarAPIKey);
278674
278776
  const [step, setStep] = import_react57.useState(isConnected ? "success" : "start");
@@ -278685,7 +278787,7 @@ function AuthFlow() {
278685
278787
  const cancelledRef = import_react57.useRef(false);
278686
278788
  const connectedWorkspace = appConfig.data.workspaceSlug ? { name: appConfig.data.workspaceSlug, slug: appConfig.data.workspaceSlug } : null;
278687
278789
  const goHome = () => {
278688
- route.navigate({ type: "base", path: "home" });
278790
+ onClose();
278689
278791
  };
278690
278792
  const cleanup = () => {
278691
278793
  cancelledRef.current = true;
@@ -278937,6 +279039,7 @@ function AuthFlow() {
278937
279039
  goHome();
278938
279040
  };
278939
279041
  useKeyboard((key) => {
279042
+ key.preventDefault();
278940
279043
  if (key.name === "escape") {
278941
279044
  cleanup();
278942
279045
  goHome();
@@ -278979,326 +279082,330 @@ function AuthFlow() {
278979
279082
  }
278980
279083
  }
278981
279084
  });
278982
- return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
278983
- flexDirection: "column",
278984
- width: "100%",
278985
- maxWidth: 80,
278986
- alignItems: "flex-start",
278987
- padding: 1,
278988
- children: [
278989
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
278990
- marginBottom: 1,
278991
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
278992
- fg: "green",
278993
- children: "Pensar Console Managed Inference"
278994
- }, undefined, false, undefined, this)
278995
- }, undefined, false, undefined, this),
278996
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
278997
- marginBottom: 1,
278998
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
278999
- fg: "gray",
279000
- children: [
279001
- "Connect to Pensar Console for usage-based AI inference.",
279002
- `
279003
- `,
279004
- "No API keys needed — just a Pensar account with credits."
279005
- ]
279006
- }, undefined, true, undefined, this)
279007
- }, undefined, false, undefined, this),
279008
- step === "start" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279009
- flexDirection: "column",
279010
- gap: 1,
279011
- children: [
279012
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279013
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279014
- fg: "white",
279015
- children: [
279016
- "Press ",
279017
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279018
- fg: "green",
279019
- children: "[ENTER]"
279020
- }, undefined, false, undefined, this),
279021
- " to authorize via your browser."
279022
- ]
279023
- }, undefined, true, undefined, this)
279024
- }, undefined, false, undefined, this),
279025
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279026
- marginTop: 1,
279027
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279028
- fg: "gray",
279029
- children: [
279030
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279031
- fg: "green",
279032
- children: "[ENTER]"
279033
- }, undefined, false, undefined, this),
279034
- " Connect ·",
279035
- " ",
279036
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279037
- fg: "green",
279038
- children: "[ESC]"
279039
- }, undefined, false, undefined, this),
279040
- " Cancel"
279041
- ]
279042
- }, undefined, true, undefined, this)
279085
+ return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Dialog, {
279086
+ size: "large",
279087
+ onClose: goHome,
279088
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279089
+ flexDirection: "column",
279090
+ width: "100%",
279091
+ alignItems: "flex-start",
279092
+ padding: 1,
279093
+ children: [
279094
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279095
+ marginBottom: 1,
279096
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279097
+ fg: colors2.primary,
279098
+ children: "Pensar Console Managed Inference"
279043
279099
  }, undefined, false, undefined, this)
279044
- ]
279045
- }, undefined, true, undefined, this),
279046
- step === "requesting" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279047
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279048
- fg: "yellow",
279049
- children: "Starting authorization..."
279050
- }, undefined, false, undefined, this)
279051
- }, undefined, false, undefined, this),
279052
- step === "polling" && (deviceInfo || legacyDeviceInfo) && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279053
- flexDirection: "column",
279054
- gap: 1,
279055
- children: [
279056
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279057
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279058
- fg: "yellow",
279059
- children: "Waiting for browser authorization..."
279060
- }, undefined, false, undefined, this)
279061
- }, undefined, false, undefined, this),
279062
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279063
- marginTop: 1,
279064
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279065
- fg: "white",
279066
- children: [
279067
- "Your code:",
279068
- " ",
279069
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279070
- fg: "green",
279071
- children: deviceInfo?.user_code || legacyDeviceInfo?.userCode
279072
- }, undefined, false, undefined, this)
279073
- ]
279074
- }, undefined, true, undefined, this)
279075
- }, undefined, false, undefined, this),
279076
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279077
- marginTop: 1,
279078
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279079
- fg: "gray",
279080
- children: [
279081
- "If the browser didn't open, visit:",
279082
- `
279100
+ }, undefined, false, undefined, this),
279101
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279102
+ marginBottom: 1,
279103
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279104
+ fg: colors2.textMuted,
279105
+ children: [
279106
+ "Connect to Pensar Console for usage-based AI inference.",
279107
+ `
279083
279108
  `,
279084
- deviceInfo?.verification_uri_complete || legacyDeviceInfo?.verificationUriComplete
279085
- ]
279086
- }, undefined, true, undefined, this)
279087
- }, undefined, false, undefined, this),
279088
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279089
- marginTop: 1,
279090
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279091
- fg: "gray",
279092
- children: [
279093
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279094
- fg: "green",
279095
- children: "[ESC]"
279096
- }, undefined, false, undefined, this),
279097
- " Cancel"
279098
- ]
279099
- }, undefined, true, undefined, this)
279100
- }, undefined, false, undefined, this)
279101
- ]
279102
- }, undefined, true, undefined, this),
279103
- step === "select-workspace" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279104
- flexDirection: "column",
279105
- gap: 1,
279106
- children: [
279107
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279108
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279109
- fg: "white",
279110
- children: "Select a workspace:"
279111
- }, undefined, false, undefined, this)
279112
- }, undefined, false, undefined, this),
279113
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279114
- flexDirection: "column",
279115
- marginTop: 1,
279116
- children: workspaces.map((ws, i) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279109
+ "No API keys needed — just a Pensar account with credits."
279110
+ ]
279111
+ }, undefined, true, undefined, this)
279112
+ }, undefined, false, undefined, this),
279113
+ step === "start" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279114
+ flexDirection: "column",
279115
+ gap: 1,
279116
+ children: [
279117
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279117
279118
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279118
- fg: i === selectedIndex ? "green" : "gray",
279119
+ fg: colors2.text,
279119
279120
  children: [
279120
- i === selectedIndex ? " " : " ",
279121
- ws.name,
279121
+ "Press ",
279122
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279123
+ fg: colors2.primary,
279124
+ children: "[ENTER]"
279125
+ }, undefined, false, undefined, this),
279126
+ " to authorize via your browser."
279127
+ ]
279128
+ }, undefined, true, undefined, this)
279129
+ }, undefined, false, undefined, this),
279130
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279131
+ marginTop: 1,
279132
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279133
+ fg: colors2.textMuted,
279134
+ children: [
279135
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279136
+ fg: colors2.primary,
279137
+ children: "[ENTER]"
279138
+ }, undefined, false, undefined, this),
279139
+ " Connect ·",
279122
279140
  " ",
279123
279141
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279124
- fg: "gray",
279125
- children: [
279126
- "(",
279127
- ws.slug,
279128
- ") — $",
279129
- ws.balance.toFixed(2)
279130
- ]
279131
- }, undefined, true, undefined, this)
279142
+ fg: colors2.primary,
279143
+ children: "[ESC]"
279144
+ }, undefined, false, undefined, this),
279145
+ " Cancel"
279132
279146
  ]
279133
279147
  }, undefined, true, undefined, this)
279134
- }, ws.id, false, undefined, this))
279135
- }, undefined, false, undefined, this),
279136
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279137
- marginTop: 1,
279138
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279139
- fg: "gray",
279140
- children: [
279141
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279142
- fg: "green",
279143
- children: "[↑/↓]"
279144
- }, undefined, false, undefined, this),
279145
- " Navigate ·",
279146
- " ",
279147
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279148
- fg: "green",
279149
- children: "[ENTER]"
279150
- }, undefined, false, undefined, this),
279151
- " Select ·",
279152
- " ",
279153
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279154
- fg: "green",
279155
- children: "[ESC]"
279156
- }, undefined, false, undefined, this),
279157
- " Cancel"
279158
- ]
279159
- }, undefined, true, undefined, this)
279148
+ }, undefined, false, undefined, this)
279149
+ ]
279150
+ }, undefined, true, undefined, this),
279151
+ step === "requesting" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279152
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279153
+ fg: colors2.warning,
279154
+ children: "Starting authorization..."
279160
279155
  }, undefined, false, undefined, this)
279161
- ]
279162
- }, undefined, true, undefined, this),
279163
- step === "checking-billing" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279164
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279165
- fg: "yellow",
279156
+ }, undefined, false, undefined, this),
279157
+ step === "polling" && (deviceInfo || legacyDeviceInfo) && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279158
+ flexDirection: "column",
279159
+ gap: 1,
279166
279160
  children: [
279167
- "Checking billing for ",
279168
- selectedWorkspace?.name,
279169
- "..."
279170
- ]
279171
- }, undefined, true, undefined, this)
279172
- }, undefined, false, undefined, this),
279173
- step === "success" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279174
- flexDirection: "column",
279175
- gap: 1,
279176
- children: [
279177
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279178
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279179
- fg: "green",
279180
- children: "Connected to Pensar Console"
279181
- }, undefined, false, undefined, this)
279182
- }, undefined, false, undefined, this),
279183
- (selectedWorkspace || connectedWorkspace) && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279184
- flexDirection: "column",
279185
- children: [
279186
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279187
- fg: "white",
279161
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279162
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279163
+ fg: colors2.warning,
279164
+ children: "Waiting for browser authorization..."
279165
+ }, undefined, false, undefined, this)
279166
+ }, undefined, false, undefined, this),
279167
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279168
+ marginTop: 1,
279169
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279170
+ fg: colors2.text,
279171
+ children: [
279172
+ "Your code:",
279173
+ " ",
279174
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279175
+ fg: colors2.primary,
279176
+ children: deviceInfo?.user_code || legacyDeviceInfo?.userCode
279177
+ }, undefined, false, undefined, this)
279178
+ ]
279179
+ }, undefined, true, undefined, this)
279180
+ }, undefined, false, undefined, this),
279181
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279182
+ marginTop: 1,
279183
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279184
+ fg: colors2.textMuted,
279188
279185
  children: [
279189
- "Workspace: ",
279190
- selectedWorkspace?.name || connectedWorkspace?.name
279186
+ "If the browser didn't open, visit:",
279187
+ `
279188
+ `,
279189
+ deviceInfo?.verification_uri_complete || legacyDeviceInfo?.verificationUriComplete
279191
279190
  ]
279192
- }, undefined, true, undefined, this),
279193
- balance !== null && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279194
- fg: "white",
279191
+ }, undefined, true, undefined, this)
279192
+ }, undefined, false, undefined, this),
279193
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279194
+ marginTop: 1,
279195
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279196
+ fg: colors2.textMuted,
279195
279197
  children: [
279196
- "Credits:",
279198
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279199
+ fg: colors2.primary,
279200
+ children: "[ESC]"
279201
+ }, undefined, false, undefined, this),
279202
+ " Cancel"
279203
+ ]
279204
+ }, undefined, true, undefined, this)
279205
+ }, undefined, false, undefined, this)
279206
+ ]
279207
+ }, undefined, true, undefined, this),
279208
+ step === "select-workspace" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279209
+ flexDirection: "column",
279210
+ gap: 1,
279211
+ children: [
279212
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279213
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279214
+ fg: colors2.text,
279215
+ children: "Select a workspace:"
279216
+ }, undefined, false, undefined, this)
279217
+ }, undefined, false, undefined, this),
279218
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279219
+ flexDirection: "column",
279220
+ marginTop: 1,
279221
+ children: workspaces.map((ws, i) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279222
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279223
+ fg: i === selectedIndex ? colors2.primary : colors2.textMuted,
279224
+ children: [
279225
+ i === selectedIndex ? "▸ " : " ",
279226
+ ws.name,
279227
+ " ",
279228
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279229
+ fg: colors2.textMuted,
279230
+ children: [
279231
+ "(",
279232
+ ws.slug,
279233
+ ") — $",
279234
+ ws.balance.toFixed(2)
279235
+ ]
279236
+ }, undefined, true, undefined, this)
279237
+ ]
279238
+ }, undefined, true, undefined, this)
279239
+ }, ws.id, false, undefined, this))
279240
+ }, undefined, false, undefined, this),
279241
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279242
+ marginTop: 1,
279243
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279244
+ fg: colors2.textMuted,
279245
+ children: [
279246
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279247
+ fg: colors2.primary,
279248
+ children: "[↑/↓]"
279249
+ }, undefined, false, undefined, this),
279250
+ " Navigate ·",
279197
279251
  " ",
279198
279252
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279199
- fg: hasLowBalance ? "yellow" : "white",
279200
- children: [
279201
- "$",
279202
- balance.toFixed(2)
279203
- ]
279204
- }, undefined, true, undefined, this)
279253
+ fg: colors2.primary,
279254
+ children: "[ENTER]"
279255
+ }, undefined, false, undefined, this),
279256
+ " Select ·",
279257
+ " ",
279258
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279259
+ fg: colors2.primary,
279260
+ children: "[ESC]"
279261
+ }, undefined, false, undefined, this),
279262
+ " Cancel"
279205
279263
  ]
279206
279264
  }, undefined, true, undefined, this)
279265
+ }, undefined, false, undefined, this)
279266
+ ]
279267
+ }, undefined, true, undefined, this),
279268
+ step === "checking-billing" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279269
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279270
+ fg: colors2.warning,
279271
+ children: [
279272
+ "Checking billing for ",
279273
+ selectedWorkspace?.name,
279274
+ "..."
279207
279275
  ]
279208
- }, undefined, true, undefined, this),
279209
- (hasLowBalance || billingUrl) && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279210
- marginTop: 1,
279211
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279212
- fg: "yellow",
279276
+ }, undefined, true, undefined, this)
279277
+ }, undefined, false, undefined, this),
279278
+ step === "success" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279279
+ flexDirection: "column",
279280
+ gap: 1,
279281
+ children: [
279282
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279283
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279284
+ fg: colors2.success,
279285
+ children: "Connected to Pensar Console"
279286
+ }, undefined, false, undefined, this)
279287
+ }, undefined, false, undefined, this),
279288
+ (selectedWorkspace || connectedWorkspace) && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279289
+ flexDirection: "column",
279213
279290
  children: [
279214
- billingUrl ? "Your workspace needs credits to use Apex CLI." : "Your credit balance is very low. We recommend at least $30 to run",
279215
- `
279216
- `,
279217
- billingUrl ? "Press ENTER to open billing and add credits." : "pentests without interruptions. Press ENTER to open billing."
279291
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279292
+ fg: colors2.text,
279293
+ children: [
279294
+ "Workspace:",
279295
+ " ",
279296
+ selectedWorkspace?.name || connectedWorkspace?.name
279297
+ ]
279298
+ }, undefined, true, undefined, this),
279299
+ balance !== null && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279300
+ fg: colors2.text,
279301
+ children: [
279302
+ "Credits:",
279303
+ " ",
279304
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279305
+ fg: hasLowBalance ? colors2.warning : colors2.text,
279306
+ children: [
279307
+ "$",
279308
+ balance.toFixed(2)
279309
+ ]
279310
+ }, undefined, true, undefined, this)
279311
+ ]
279312
+ }, undefined, true, undefined, this)
279218
279313
  ]
279219
- }, undefined, true, undefined, this)
279220
- }, undefined, false, undefined, this),
279221
- !selectedWorkspace && !connectedWorkspace && appConfig.data.pensarAPIKey && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279222
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279223
- fg: "gray",
279224
- children: "Already connected (legacy key saved in config)"
279225
- }, undefined, false, undefined, this)
279226
- }, undefined, false, undefined, this),
279227
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279228
- marginTop: 1,
279229
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279230
- fg: "gray",
279231
- children: "Pensar models are now available in the model selector."
279314
+ }, undefined, true, undefined, this),
279315
+ (hasLowBalance || billingUrl) && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279316
+ marginTop: 1,
279317
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279318
+ fg: colors2.warning,
279319
+ children: [
279320
+ billingUrl ? "Your workspace needs credits to use Apex CLI." : "Your credit balance is very low. We recommend at least $30 to run",
279321
+ `
279322
+ `,
279323
+ billingUrl ? "Press ENTER to open billing and add credits." : "pentests without interruptions. Press ENTER to open billing."
279324
+ ]
279325
+ }, undefined, true, undefined, this)
279326
+ }, undefined, false, undefined, this),
279327
+ !selectedWorkspace && !connectedWorkspace && appConfig.data.pensarAPIKey && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279328
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279329
+ fg: colors2.textMuted,
279330
+ children: "Already connected (legacy key saved in config)"
279331
+ }, undefined, false, undefined, this)
279332
+ }, undefined, false, undefined, this),
279333
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279334
+ marginTop: 1,
279335
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279336
+ fg: colors2.textMuted,
279337
+ children: "Pensar models are now available in the model selector."
279338
+ }, undefined, false, undefined, this)
279339
+ }, undefined, false, undefined, this),
279340
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279341
+ marginTop: 1,
279342
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279343
+ fg: colors2.textMuted,
279344
+ children: [
279345
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279346
+ fg: colors2.primary,
279347
+ children: "[ENTER]"
279348
+ }, undefined, false, undefined, this),
279349
+ " ",
279350
+ hasLowBalance || billingUrl ? "Open billing" : "Done",
279351
+ " ·",
279352
+ " ",
279353
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279354
+ fg: colors2.error,
279355
+ children: "[D]"
279356
+ }, undefined, false, undefined, this),
279357
+ " Disconnect ·",
279358
+ " ",
279359
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279360
+ fg: colors2.primary,
279361
+ children: "[ESC]"
279362
+ }, undefined, false, undefined, this),
279363
+ " Back"
279364
+ ]
279365
+ }, undefined, true, undefined, this)
279232
279366
  }, undefined, false, undefined, this)
279233
- }, undefined, false, undefined, this),
279234
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279235
- marginTop: 1,
279236
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279237
- fg: "gray",
279238
- children: [
279239
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279240
- fg: "green",
279241
- children: "[ENTER]"
279242
- }, undefined, false, undefined, this),
279243
- " ",
279244
- hasLowBalance || billingUrl ? "Open billing" : "Done",
279245
- " ·",
279246
- " ",
279247
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279248
- fg: "red",
279249
- children: "[D]"
279250
- }, undefined, false, undefined, this),
279251
- " Disconnect ·",
279252
- " ",
279253
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279254
- fg: "green",
279255
- children: "[ESC]"
279256
- }, undefined, false, undefined, this),
279257
- " Back"
279258
- ]
279259
- }, undefined, true, undefined, this)
279260
- }, undefined, false, undefined, this)
279261
- ]
279262
- }, undefined, true, undefined, this),
279263
- step === "error" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279264
- flexDirection: "column",
279265
- gap: 1,
279266
- children: [
279267
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279268
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279269
- fg: "red",
279270
- children: error40
279367
+ ]
279368
+ }, undefined, true, undefined, this),
279369
+ step === "error" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279370
+ flexDirection: "column",
279371
+ gap: 1,
279372
+ children: [
279373
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279374
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279375
+ fg: colors2.error,
279376
+ children: error40
279377
+ }, undefined, false, undefined, this)
279378
+ }, undefined, false, undefined, this),
279379
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279380
+ marginTop: 1,
279381
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279382
+ fg: colors2.textMuted,
279383
+ children: [
279384
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279385
+ fg: colors2.primary,
279386
+ children: "[ENTER]"
279387
+ }, undefined, false, undefined, this),
279388
+ " Try again ·",
279389
+ " ",
279390
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279391
+ fg: colors2.primary,
279392
+ children: "[ESC]"
279393
+ }, undefined, false, undefined, this),
279394
+ " Cancel"
279395
+ ]
279396
+ }, undefined, true, undefined, this)
279271
279397
  }, undefined, false, undefined, this)
279272
- }, undefined, false, undefined, this),
279273
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
279274
- marginTop: 1,
279275
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
279276
- fg: "gray",
279277
- children: [
279278
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279279
- fg: "green",
279280
- children: "[ENTER]"
279281
- }, undefined, false, undefined, this),
279282
- " Try again ·",
279283
- " ",
279284
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
279285
- fg: "green",
279286
- children: "[ESC]"
279287
- }, undefined, false, undefined, this),
279288
- " Cancel"
279289
- ]
279290
- }, undefined, true, undefined, this)
279291
- }, undefined, false, undefined, this)
279292
- ]
279293
- }, undefined, true, undefined, this)
279294
- ]
279295
- }, undefined, true, undefined, this);
279398
+ ]
279399
+ }, undefined, true, undefined, this)
279400
+ ]
279401
+ }, undefined, true, undefined, this)
279402
+ }, undefined, false, undefined, this);
279296
279403
  }
279297
279404
 
279298
279405
  // src/tui/components/commands/credits-flow.tsx
279299
279406
  var import_react59 = __toESM(require_react(), 1);
279300
279407
  init_tokenRefresh();
279301
- function CreditsFlow() {
279408
+ function CreditsFlow({ onOpenAuthDialog }) {
279302
279409
  const route = useRoute();
279303
279410
  const appConfig = useConfig();
279304
279411
  const [step, setStep] = import_react59.useState("loading");
@@ -279371,7 +279478,7 @@ function CreditsFlow() {
279371
279478
  }
279372
279479
  if (step === "no-auth") {
279373
279480
  if (key.name === "return") {
279374
- route.navigate({ type: "base", path: "auth" });
279481
+ onOpenAuthDialog?.();
279375
279482
  }
279376
279483
  }
279377
279484
  if (step === "display") {
@@ -285095,19 +285202,23 @@ function NormalInputAreaInner({
285095
285202
  enableCommands = false,
285096
285203
  onCommandExecute,
285097
285204
  commandHistory = [],
285098
- disableHistoryNavigation = false
285205
+ disableHistoryNavigation = false,
285206
+ autocompletePlacement = "below"
285099
285207
  }) {
285100
- const { colors: colors2 } = useTheme();
285208
+ const { colors: colors2, theme, mode: colorMode } = useTheme();
285101
285209
  const { inputValue, setInputValue } = useInput();
285102
285210
  const promptRef = import_react77.useRef(null);
285103
285211
  const isExternalUpdate = import_react77.useRef(false);
285212
+ const prevValueRef = import_react77.useRef(value);
285104
285213
  import_react77.useEffect(() => {
285105
- if (value !== inputValue) {
285214
+ const prevValue = prevValueRef.current;
285215
+ prevValueRef.current = value;
285216
+ if (value !== prevValue && value !== inputValue) {
285106
285217
  isExternalUpdate.current = true;
285107
285218
  setInputValue(value);
285108
285219
  promptRef.current?.setValue(value);
285109
285220
  }
285110
- }, [value]);
285221
+ }, [value, inputValue, setInputValue]);
285111
285222
  import_react77.useEffect(() => {
285112
285223
  if (isExternalUpdate.current) {
285113
285224
  isExternalUpdate.current = false;
@@ -285116,7 +285227,7 @@ function NormalInputAreaInner({
285116
285227
  if (inputValue !== value) {
285117
285228
  onChange(inputValue);
285118
285229
  }
285119
- }, [inputValue]);
285230
+ }, [inputValue, value, onChange]);
285120
285231
  const handleSubmit = (val) => {
285121
285232
  if (val.trim()) {
285122
285233
  onSubmit(val.trim());
@@ -285154,8 +285265,9 @@ function NormalInputAreaInner({
285154
285265
  enableCommands,
285155
285266
  onCommandExecute,
285156
285267
  commandHistory,
285157
- disableHistoryNavigation
285158
- }, undefined, false, undefined, this)
285268
+ disableHistoryNavigation,
285269
+ autocompletePlacement
285270
+ }, `${theme.name}-${colorMode}`, false, undefined, this)
285159
285271
  ]
285160
285272
  }, undefined, true, undefined, this),
285161
285273
  mode === "operator" && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
@@ -285242,6 +285354,7 @@ function InputArea(props) {
285242
285354
  onCommandExecute,
285243
285355
  commandHistory,
285244
285356
  disableHistoryNavigation,
285357
+ autocompletePlacement,
285245
285358
  ...normalProps
285246
285359
  } = props;
285247
285360
  if (pendingApproval) {
@@ -285266,6 +285379,7 @@ function InputArea(props) {
285266
285379
  onCommandExecute,
285267
285380
  commandHistory,
285268
285381
  disableHistoryNavigation,
285382
+ autocompletePlacement,
285269
285383
  ...normalProps
285270
285384
  }, undefined, false, undefined, this)
285271
285385
  }, undefined, false, undefined, this);
@@ -285398,7 +285512,15 @@ init_dist5();
285398
285512
 
285399
285513
  // src/tui/components/operator-dashboard/logic.ts
285400
285514
  function filterOperatorAutocomplete(allOptions, skillSlugs) {
285401
- const allowedCommands = new Set(["/create-skill", "/models"]);
285515
+ const allowedCommands = new Set([
285516
+ "/create-skill",
285517
+ "/models",
285518
+ "/auth",
285519
+ "/themes",
285520
+ "/new",
285521
+ "/operator",
285522
+ "/pentest"
285523
+ ]);
285402
285524
  return allOptions.filter((opt) => allowedCommands.has(opt.value) || skillSlugs.has(opt.value));
285403
285525
  }
285404
285526
  function resolveSubmit(value, status, hasPendingApprovals) {
@@ -286576,6 +286698,7 @@ function OperatorDashboard({
286576
286698
  onAutoApprove: handleAutoApprove,
286577
286699
  enableAutocomplete: true,
286578
286700
  autocompleteOptions,
286701
+ autocompletePlacement: "above",
286579
286702
  enableCommands: true,
286580
286703
  onCommandExecute: handleCommandExecute,
286581
286704
  disableHistoryNavigation: status === "running" && queuedMessages.length > 0
@@ -286587,9 +286710,8 @@ function OperatorDashboard({
286587
286710
  // src/tui/components/commands/theme-picker.tsx
286588
286711
  var import_react81 = __toESM(require_react(), 1);
286589
286712
  init_config2();
286590
- function ThemePicker() {
286713
+ function ThemePicker({ onClose }) {
286591
286714
  const dimensions = useTerminalDimensions();
286592
- const route = useRoute();
286593
286715
  const {
286594
286716
  colors: colors2,
286595
286717
  theme,
@@ -286605,16 +286727,17 @@ function ThemePicker() {
286605
286727
  const handleClose = import_react81.useCallback(() => {
286606
286728
  setTheme(originalThemeRef.current);
286607
286729
  setMode(originalModeRef.current);
286608
- route.navigate({ type: "base", path: "home" });
286609
- }, [setTheme, setMode, route]);
286730
+ onClose();
286731
+ }, [setTheme, setMode, onClose]);
286610
286732
  const handleConfirm = import_react81.useCallback(async () => {
286611
286733
  const currentThemeName = availableThemes[selectedIndex];
286612
286734
  if (currentThemeName) {
286613
286735
  await config2.update({ theme: currentThemeName });
286614
286736
  }
286615
- route.navigate({ type: "base", path: "home" });
286616
- }, [availableThemes, selectedIndex, route]);
286737
+ onClose();
286738
+ }, [availableThemes, selectedIndex, onClose]);
286617
286739
  useKeyboard((evt) => {
286740
+ evt.preventDefault();
286618
286741
  if (evt.name === "escape") {
286619
286742
  handleClose();
286620
286743
  return;
@@ -286653,27 +286776,16 @@ function ThemePicker() {
286653
286776
  const listHeight = panelHeight - 5;
286654
286777
  const scrollOffset = Math.max(0, Math.min(selectedIndex - Math.floor(listHeight / 2), availableThemes.length - listHeight));
286655
286778
  const visibleThemes = availableThemes.slice(scrollOffset, scrollOffset + listHeight);
286656
- return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
286657
- width: dimensions.width,
286658
- height: dimensions.height,
286659
- alignItems: "center",
286660
- justifyContent: "center",
286661
- position: "absolute",
286662
- left: 0,
286663
- top: 0,
286664
- backgroundColor: colors2.background,
286779
+ return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Dialog, {
286780
+ size: "large",
286781
+ onClose: handleClose,
286665
286782
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
286666
- width: panelWidth,
286667
- height: panelHeight,
286668
- backgroundColor: colors2.backgroundPanel,
286669
- borderColor: colors2.border,
286670
- borderStyle: "single",
286783
+ width: "100%",
286671
286784
  flexDirection: "column",
286785
+ padding: 1,
286672
286786
  children: [
286673
286787
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
286674
286788
  width: "100%",
286675
- paddingLeft: 1,
286676
- paddingRight: 1,
286677
286789
  flexDirection: "row",
286678
286790
  justifyContent: "space-between",
286679
286791
  children: [
@@ -286701,8 +286813,6 @@ function ThemePicker() {
286701
286813
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
286702
286814
  flexDirection: "column",
286703
286815
  flexGrow: 1,
286704
- paddingLeft: 1,
286705
- paddingRight: 1,
286706
286816
  children: visibleThemes.map((themeName) => {
286707
286817
  const actualIndex = availableThemes.indexOf(themeName);
286708
286818
  const isSelected = actualIndex === selectedIndex;
@@ -286736,8 +286846,6 @@ function ThemePicker() {
286736
286846
  }, undefined, false, undefined, this),
286737
286847
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
286738
286848
  width: "100%",
286739
- paddingLeft: 1,
286740
- paddingRight: 1,
286741
286849
  flexDirection: "row",
286742
286850
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
286743
286851
  fg: colors2.textMuted,
@@ -287290,7 +287398,7 @@ var apex = {
287290
287398
  },
287291
287399
  backgroundOverlay: {
287292
287400
  dark: RGBA.fromInts(0, 0, 0, 200),
287293
- light: RGBA.fromInts(255, 255, 255, 200)
287401
+ light: RGBA.fromInts(0, 0, 0, 180)
287294
287402
  },
287295
287403
  backgroundSelected: {
287296
287404
  dark: RGBA.fromInts(40, 40, 60, 255),
@@ -287419,7 +287527,7 @@ var ayu = {
287419
287527
  },
287420
287528
  backgroundOverlay: {
287421
287529
  dark: RGBA.fromInts(0, 0, 0, 200),
287422
- light: RGBA.fromInts(255, 255, 255, 200)
287530
+ light: RGBA.fromInts(0, 0, 0, 180)
287423
287531
  },
287424
287532
  backgroundSelected: {
287425
287533
  dark: RGBA.fromHex("#1a1f29"),
@@ -287548,7 +287656,7 @@ var catppuccin = {
287548
287656
  },
287549
287657
  backgroundOverlay: {
287550
287658
  dark: RGBA.fromInts(0, 0, 0, 200),
287551
- light: RGBA.fromInts(255, 255, 255, 200)
287659
+ light: RGBA.fromInts(0, 0, 0, 180)
287552
287660
  },
287553
287661
  backgroundSelected: {
287554
287662
  dark: RGBA.fromHex("#45475a"),
@@ -287677,7 +287785,7 @@ var dracula = {
287677
287785
  },
287678
287786
  backgroundOverlay: {
287679
287787
  dark: RGBA.fromInts(0, 0, 0, 200),
287680
- light: RGBA.fromInts(255, 255, 255, 200)
287788
+ light: RGBA.fromInts(0, 0, 0, 180)
287681
287789
  },
287682
287790
  backgroundSelected: {
287683
287791
  dark: RGBA.fromHex("#44475a"),
@@ -287806,7 +287914,7 @@ var everforest = {
287806
287914
  },
287807
287915
  backgroundOverlay: {
287808
287916
  dark: RGBA.fromInts(0, 0, 0, 200),
287809
- light: RGBA.fromInts(255, 255, 255, 200)
287917
+ light: RGBA.fromInts(0, 0, 0, 180)
287810
287918
  },
287811
287919
  backgroundSelected: {
287812
287920
  dark: RGBA.fromHex("#3d484d"),
@@ -287935,7 +288043,7 @@ var flexoki = {
287935
288043
  },
287936
288044
  backgroundOverlay: {
287937
288045
  dark: RGBA.fromInts(0, 0, 0, 200),
287938
- light: RGBA.fromInts(255, 255, 255, 200)
288046
+ light: RGBA.fromInts(0, 0, 0, 180)
287939
288047
  },
287940
288048
  backgroundSelected: {
287941
288049
  dark: RGBA.fromHex("#343331"),
@@ -288064,7 +288172,7 @@ var github = {
288064
288172
  },
288065
288173
  backgroundOverlay: {
288066
288174
  dark: RGBA.fromInts(0, 0, 0, 200),
288067
- light: RGBA.fromInts(255, 255, 255, 200)
288175
+ light: RGBA.fromInts(0, 0, 0, 180)
288068
288176
  },
288069
288177
  backgroundSelected: {
288070
288178
  dark: RGBA.fromHex("#1f2937"),
@@ -288193,7 +288301,7 @@ var gruvbox = {
288193
288301
  },
288194
288302
  backgroundOverlay: {
288195
288303
  dark: RGBA.fromInts(0, 0, 0, 200),
288196
- light: RGBA.fromInts(255, 255, 255, 200)
288304
+ light: RGBA.fromInts(0, 0, 0, 180)
288197
288305
  },
288198
288306
  backgroundSelected: {
288199
288307
  dark: RGBA.fromHex("#504945"),
@@ -288322,7 +288430,7 @@ var kanagawa = {
288322
288430
  },
288323
288431
  backgroundOverlay: {
288324
288432
  dark: RGBA.fromInts(0, 0, 0, 200),
288325
- light: RGBA.fromInts(255, 255, 255, 200)
288433
+ light: RGBA.fromInts(0, 0, 0, 180)
288326
288434
  },
288327
288435
  backgroundSelected: {
288328
288436
  dark: RGBA.fromHex("#2d4f67"),
@@ -288451,7 +288559,7 @@ var material = {
288451
288559
  },
288452
288560
  backgroundOverlay: {
288453
288561
  dark: RGBA.fromInts(0, 0, 0, 200),
288454
- light: RGBA.fromInts(255, 255, 255, 200)
288562
+ light: RGBA.fromInts(0, 0, 0, 180)
288455
288563
  },
288456
288564
  backgroundSelected: {
288457
288565
  dark: RGBA.fromHex("#364850"),
@@ -288580,7 +288688,7 @@ var monokai = {
288580
288688
  },
288581
288689
  backgroundOverlay: {
288582
288690
  dark: RGBA.fromInts(0, 0, 0, 200),
288583
- light: RGBA.fromInts(255, 255, 255, 200)
288691
+ light: RGBA.fromInts(0, 0, 0, 180)
288584
288692
  },
288585
288693
  backgroundSelected: {
288586
288694
  dark: RGBA.fromHex("#4a474c"),
@@ -288709,7 +288817,7 @@ var nightfox = {
288709
288817
  },
288710
288818
  backgroundOverlay: {
288711
288819
  dark: RGBA.fromInts(0, 0, 0, 200),
288712
- light: RGBA.fromInts(255, 255, 255, 200)
288820
+ light: RGBA.fromInts(0, 0, 0, 180)
288713
288821
  },
288714
288822
  backgroundSelected: {
288715
288823
  dark: RGBA.fromHex("#2b3b51"),
@@ -288838,7 +288946,7 @@ var nord = {
288838
288946
  },
288839
288947
  backgroundOverlay: {
288840
288948
  dark: RGBA.fromInts(0, 0, 0, 200),
288841
- light: RGBA.fromInts(255, 255, 255, 200)
288949
+ light: RGBA.fromInts(0, 0, 0, 180)
288842
288950
  },
288843
288951
  backgroundSelected: {
288844
288952
  dark: RGBA.fromHex("#434c5e"),
@@ -288967,7 +289075,7 @@ var oneDark = {
288967
289075
  },
288968
289076
  backgroundOverlay: {
288969
289077
  dark: RGBA.fromInts(0, 0, 0, 200),
288970
- light: RGBA.fromInts(255, 255, 255, 200)
289078
+ light: RGBA.fromInts(0, 0, 0, 180)
288971
289079
  },
288972
289080
  backgroundSelected: {
288973
289081
  dark: RGBA.fromHex("#3e4451"),
@@ -289096,7 +289204,7 @@ var rosePine = {
289096
289204
  },
289097
289205
  backgroundOverlay: {
289098
289206
  dark: RGBA.fromInts(0, 0, 0, 200),
289099
- light: RGBA.fromInts(255, 255, 255, 200)
289207
+ light: RGBA.fromInts(0, 0, 0, 180)
289100
289208
  },
289101
289209
  backgroundSelected: {
289102
289210
  dark: RGBA.fromHex("#2a283e"),
@@ -289225,7 +289333,7 @@ var solarized = {
289225
289333
  },
289226
289334
  backgroundOverlay: {
289227
289335
  dark: RGBA.fromInts(0, 0, 0, 200),
289228
- light: RGBA.fromInts(255, 255, 255, 200)
289336
+ light: RGBA.fromInts(0, 0, 0, 180)
289229
289337
  },
289230
289338
  backgroundSelected: {
289231
289339
  dark: RGBA.fromHex("#0a4a5c"),
@@ -289354,7 +289462,7 @@ var tokyonight = {
289354
289462
  },
289355
289463
  backgroundOverlay: {
289356
289464
  dark: RGBA.fromInts(0, 0, 0, 200),
289357
- light: RGBA.fromInts(255, 255, 255, 200)
289465
+ light: RGBA.fromInts(0, 0, 0, 180)
289358
289466
  },
289359
289467
  backgroundSelected: {
289360
289468
  dark: RGBA.fromHex("#283457"),
@@ -289483,7 +289591,7 @@ var vesper = {
289483
289591
  },
289484
289592
  backgroundOverlay: {
289485
289593
  dark: RGBA.fromInts(0, 0, 0, 200),
289486
- light: RGBA.fromInts(255, 255, 255, 200)
289594
+ light: RGBA.fromInts(0, 0, 0, 180)
289487
289595
  },
289488
289596
  backgroundSelected: {
289489
289597
  dark: RGBA.fromHex("#232323"),
@@ -289634,15 +289742,127 @@ async function detectTerminalMode(timeoutMs = 1000) {
289634
289742
  });
289635
289743
  }
289636
289744
 
289745
+ // src/tui/console-theme.ts
289746
+ var import_react85 = __toESM(require_react(), 1);
289747
+ var withAlpha = (rgba, a) => RGBA.fromValues(rgba.r, rgba.g, rgba.b, a);
289748
+ var overlayThemeRef = {
289749
+ current: null
289750
+ };
289751
+ function buildConsoleOptions(themeColors) {
289752
+ return {
289753
+ backgroundColor: withAlpha(themeColors.backgroundPanel, 0.85),
289754
+ titleBarColor: withAlpha(themeColors.backgroundElement, 0.9),
289755
+ titleBarTextColor: themeColors.text,
289756
+ colorDefault: themeColors.textMuted,
289757
+ colorInfo: themeColors.info,
289758
+ colorWarn: themeColors.warning,
289759
+ colorError: themeColors.error,
289760
+ colorDebug: themeColors.textMuted,
289761
+ selectionColor: withAlpha(themeColors.primary, 0.35),
289762
+ cursorColor: themeColors.primary,
289763
+ copyButtonColor: themeColors.primary
289764
+ };
289765
+ }
289766
+ function ConsoleThemeSync() {
289767
+ const { colors: colors2 } = useTheme();
289768
+ const renderer = useRenderer();
289769
+ import_react85.useEffect(() => {
289770
+ overlayThemeRef.current = colors2;
289771
+ const c = renderer.console;
289772
+ c.backgroundColor = withAlpha(colors2.backgroundPanel, 0.85);
289773
+ c._rgbaTitleBar = withAlpha(colors2.backgroundElement, 0.9);
289774
+ c._rgbaTitleBarText = colors2.text;
289775
+ c._rgbaDefault = colors2.textMuted;
289776
+ c._rgbaInfo = colors2.info;
289777
+ c._rgbaWarn = colors2.warning;
289778
+ c._rgbaError = colors2.error;
289779
+ c._rgbaDebug = colors2.textMuted;
289780
+ c._rgbaSelection = withAlpha(colors2.primary, 0.35);
289781
+ c._rgbaCursor = colors2.primary;
289782
+ c._rgbaCopyButton = colors2.primary;
289783
+ c.markNeedsRerender();
289784
+ }, [colors2]);
289785
+ return null;
289786
+ }
289787
+
289788
+ // src/tui/clipboard.ts
289789
+ function createClipboardManager(renderer) {
289790
+ let clipboardNotifExpiry = 0;
289791
+ const copyToClipboard = (text2) => {
289792
+ renderer.copyToClipboardOSC52(text2);
289793
+ try {
289794
+ const proc = Bun.spawn(process.platform === "darwin" ? ["pbcopy"] : ["xclip", "-selection", "clipboard"], { stdin: "pipe" });
289795
+ proc.stdin.write(text2);
289796
+ proc.stdin.end();
289797
+ } catch {}
289798
+ clipboardNotifExpiry = Date.now() + 2000;
289799
+ renderer.requestRender();
289800
+ setTimeout(() => renderer.requestRender(), 2010);
289801
+ };
289802
+ const notifLabel = "Copied to clipboard";
289803
+ const notifPadX = 1;
289804
+ const notifBoxWidth = 1 + notifPadX + notifLabel.length + notifPadX + 1;
289805
+ const notifBoxHeight = 3;
289806
+ const notifMargin = 1;
289807
+ renderer.addPostProcessFn((buffer) => {
289808
+ if (Date.now() < clipboardNotifExpiry && overlayThemeRef.current) {
289809
+ const c = overlayThemeRef.current;
289810
+ const x4 = buffer.width - notifBoxWidth - notifMargin;
289811
+ const y3 = notifMargin;
289812
+ buffer.fillRect(x4, y3, notifBoxWidth, notifBoxHeight, c.backgroundElement);
289813
+ buffer.drawBox({
289814
+ x: x4,
289815
+ y: y3,
289816
+ width: notifBoxWidth,
289817
+ height: notifBoxHeight,
289818
+ border: true,
289819
+ borderColor: c.border,
289820
+ backgroundColor: c.backgroundElement,
289821
+ shouldFill: false
289822
+ });
289823
+ buffer.drawText(notifLabel, x4 + 1 + notifPadX, y3 + 1, c.text, c.backgroundElement);
289824
+ }
289825
+ });
289826
+ renderer.console.onCopySelection = copyToClipboard;
289827
+ return { copyToClipboard };
289828
+ }
289829
+
289830
+ // src/tui/auto-copy.ts
289831
+ function setupAutoCopy(renderer, copyToClipboard) {
289832
+ renderer.console.getCopyButtonLabel = () => "Select to copy";
289833
+ const originalHandleMouse = renderer.console.handleMouse.bind(renderer.console);
289834
+ renderer.console.handleMouse = (event) => {
289835
+ const result = originalHandleMouse(event);
289836
+ if (event.type === "up") {
289837
+ const c = renderer.console;
289838
+ if (typeof c.hasSelection === "function" && c.hasSelection()) {
289839
+ c.triggerCopy();
289840
+ }
289841
+ }
289842
+ return result;
289843
+ };
289844
+ renderer.on("selection", (selection) => {
289845
+ if (selection && !selection.isDragging) {
289846
+ const text2 = selection.getSelectedText();
289847
+ if (text2) {
289848
+ copyToClipboard(text2);
289849
+ }
289850
+ process.nextTick(() => renderer.clearSelection());
289851
+ }
289852
+ });
289853
+ }
289854
+
289637
289855
  // src/tui/index.tsx
289638
289856
  function App({ appConfig }) {
289639
- const [focusIndex, setFocusIndex] = import_react86.useState(0);
289640
- const [cwd, setCwd] = import_react86.useState(process.cwd());
289641
- const [ctrlCPressTime, setCtrlCPressTime] = import_react86.useState(null);
289642
- const [showExitWarning, setShowExitWarning] = import_react86.useState(false);
289643
- const [inputKey, setInputKey] = import_react86.useState(0);
289644
- const [showSessionsDialog, setShowSessionsDialog] = import_react86.useState(false);
289645
- const [showShortcutsDialog, setShowShortcutsDialog] = import_react86.useState(false);
289857
+ const [focusIndex, setFocusIndex] = import_react88.useState(0);
289858
+ const [cwd, setCwd] = import_react88.useState(process.cwd());
289859
+ const [ctrlCPressTime, setCtrlCPressTime] = import_react88.useState(null);
289860
+ const [showExitWarning, setShowExitWarning] = import_react88.useState(false);
289861
+ const [inputKey, setInputKey] = import_react88.useState(0);
289862
+ const [showSessionsDialog, setShowSessionsDialog] = import_react88.useState(false);
289863
+ const [showShortcutsDialog, setShowShortcutsDialog] = import_react88.useState(false);
289864
+ const [showThemeDialog, setShowThemeDialog] = import_react88.useState(false);
289865
+ const [showAuthDialog, setShowAuthDialog] = import_react88.useState(false);
289646
289866
  const navigableItems = ["command-input"];
289647
289867
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ConfigProvider, {
289648
289868
  config: appConfig,
@@ -289654,6 +289874,8 @@ function App({ appConfig }) {
289654
289874
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AgentProvider, {
289655
289875
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(CommandProvider, {
289656
289876
  onOpenSessionsDialog: () => setShowSessionsDialog(true),
289877
+ onOpenThemeDialog: () => setShowThemeDialog(true),
289878
+ onOpenAuthDialog: () => setShowAuthDialog(true),
289657
289879
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(KeybindingProvider, {
289658
289880
  deps: {
289659
289881
  ctrlCPressTime,
@@ -289671,6 +289893,10 @@ function App({ appConfig }) {
289671
289893
  setShowSessionsDialog,
289672
289894
  showShortcutsDialog,
289673
289895
  setShowShortcutsDialog,
289896
+ showThemeDialog,
289897
+ setShowThemeDialog,
289898
+ showAuthDialog,
289899
+ setShowAuthDialog,
289674
289900
  cwd,
289675
289901
  setCtrlCPressTime,
289676
289902
  showExitWarning,
@@ -289694,6 +289920,10 @@ function AppContent({
289694
289920
  setShowSessionsDialog,
289695
289921
  showShortcutsDialog,
289696
289922
  setShowShortcutsDialog,
289923
+ showThemeDialog,
289924
+ setShowThemeDialog,
289925
+ showAuthDialog,
289926
+ setShowAuthDialog,
289697
289927
  cwd,
289698
289928
  setCtrlCPressTime,
289699
289929
  showExitWarning,
@@ -289707,14 +289937,14 @@ function AppContent({
289707
289937
  const { toast } = useToast();
289708
289938
  const { refocusPrompt } = useFocus();
289709
289939
  const { setExternalDialogOpen } = useDialog();
289710
- import_react86.useEffect(() => {
289940
+ import_react88.useEffect(() => {
289711
289941
  checkForUpdate().then(({ updateAvailable, currentVersion, latestVersion }) => {
289712
289942
  if (!updateAvailable)
289713
289943
  return;
289714
289944
  toast(`Update available: v${currentVersion} → v${latestVersion}. Run: pensar upgrade`, "warn", 8000);
289715
289945
  });
289716
289946
  }, []);
289717
- import_react86.useEffect(() => {
289947
+ import_react88.useEffect(() => {
289718
289948
  if (route.data.type !== "base")
289719
289949
  return;
289720
289950
  if (!config3.data.responsibleUseAccepted && route.data.path !== "disclosure") {
@@ -289723,7 +289953,12 @@ function AppContent({
289723
289953
  route.navigate({ type: "base", path: "providers" });
289724
289954
  }
289725
289955
  }, [config3.data.responsibleUseAccepted, route.data]);
289726
- import_react86.useEffect(() => {
289956
+ import_react88.useEffect(() => {
289957
+ if (showThemeDialog || showAuthDialog) {
289958
+ setExternalDialogOpen(true);
289959
+ }
289960
+ }, [showThemeDialog, showAuthDialog]);
289961
+ import_react88.useEffect(() => {
289727
289962
  if (showExitWarning) {
289728
289963
  const timer = setTimeout(() => {
289729
289964
  setShowExitWarning(false);
@@ -289745,6 +289980,22 @@ function AppContent({
289745
289980
  setInputKey((prev) => prev + 1);
289746
289981
  refocusPrompt();
289747
289982
  };
289983
+ const handleCloseThemeDialog = () => {
289984
+ setShowThemeDialog(false);
289985
+ setTimeout(() => {
289986
+ setExternalDialogOpen(false);
289987
+ }, 0);
289988
+ setInputKey((prev) => prev + 1);
289989
+ refocusPrompt();
289990
+ };
289991
+ const handleCloseAuthDialog = () => {
289992
+ setShowAuthDialog(false);
289993
+ setTimeout(() => {
289994
+ setExternalDialogOpen(false);
289995
+ }, 0);
289996
+ setInputKey((prev) => prev + 1);
289997
+ refocusPrompt();
289998
+ };
289748
289999
  const isHomeRoute = route.data.type === "base" && route.data.path === "home";
289749
290000
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
289750
290001
  flexDirection: "column",
@@ -289757,7 +290008,8 @@ function AppContent({
289757
290008
  children: [
289758
290009
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(CommandDisplay, {
289759
290010
  focusIndex,
289760
- inputKey
290011
+ inputKey,
290012
+ onOpenAuthDialog: () => setShowAuthDialog(true)
289761
290013
  }, undefined, false, undefined, this),
289762
290014
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Footer, {
289763
290015
  cwd,
@@ -289769,6 +290021,12 @@ function AppContent({
289769
290021
  showShortcutsDialog && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ShortcutsDialog, {
289770
290022
  open: showShortcutsDialog,
289771
290023
  onClose: handleCloseShortcutsDialog
290024
+ }, undefined, false, undefined, this),
290025
+ showThemeDialog && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ThemePicker, {
290026
+ onClose: handleCloseThemeDialog
290027
+ }, undefined, false, undefined, this),
290028
+ showAuthDialog && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AuthFlow, {
290029
+ onClose: handleCloseAuthDialog
289772
290030
  }, undefined, false, undefined, this)
289773
290031
  ]
289774
290032
  }, undefined, true, undefined, this);
@@ -289776,7 +290034,8 @@ function AppContent({
289776
290034
  var RouteSwitch = createSwitch();
289777
290035
  function CommandDisplay({
289778
290036
  focusIndex,
289779
- inputKey
290037
+ inputKey,
290038
+ onOpenAuthDialog
289780
290039
  }) {
289781
290040
  const route = useRoute();
289782
290041
  const config3 = useConfig();
@@ -289853,10 +290112,6 @@ function CommandDisplay({
289853
290112
  when: "providers",
289854
290113
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ProviderManager, {}, undefined, false, undefined, this)
289855
290114
  }, undefined, false, undefined, this),
289856
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(RouteSwitch.Case, {
289857
- when: "theme",
289858
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ThemePicker, {}, undefined, false, undefined, this)
289859
- }, undefined, false, undefined, this),
289860
290115
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(RouteSwitch.Case, {
289861
290116
  when: "help",
289862
290117
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(HelpDialog, {}, undefined, false, undefined, this)
@@ -289865,13 +290120,11 @@ function CommandDisplay({
289865
290120
  when: "models",
289866
290121
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ModelsDisplay, {}, undefined, false, undefined, this)
289867
290122
  }, undefined, false, undefined, this),
289868
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(RouteSwitch.Case, {
289869
- when: "auth",
289870
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AuthFlow, {}, undefined, false, undefined, this)
289871
- }, undefined, false, undefined, this),
289872
290123
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(RouteSwitch.Case, {
289873
290124
  when: "credits",
289874
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(CreditsFlow, {}, undefined, false, undefined, this)
290125
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(CreditsFlow, {
290126
+ onOpenAuthDialog
290127
+ }, undefined, false, undefined, this)
289875
290128
  }, undefined, false, undefined, this),
289876
290129
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(RouteSwitch.Case, {
289877
290130
  when: "create-skill",
@@ -289886,7 +290139,7 @@ function CommandDisplay({
289886
290139
  sessionId: route.data.sessionId,
289887
290140
  initialMessage: route.data.initialMessage,
289888
290141
  initialConfig: route.data.initialConfig
289889
- }, undefined, false, undefined, this);
290142
+ }, route.data.sessionId ?? route.data.nonce ?? "new", false, undefined, this);
289890
290143
  }
289891
290144
  if (route.data.type === "pentest") {
289892
290145
  if (route.data.openAsOperator) {
@@ -289912,7 +290165,14 @@ async function main2() {
289912
290165
  } else {
289913
290166
  mode = await detectTerminalMode();
289914
290167
  }
289915
- const renderer = await createCliRenderer({ exitOnCtrlC: false });
290168
+ const themeColors = resolveThemeColors(getTheme(themeName), mode);
290169
+ overlayThemeRef.current = themeColors;
290170
+ const renderer = await createCliRenderer({
290171
+ exitOnCtrlC: false,
290172
+ consoleOptions: buildConsoleOptions(themeColors)
290173
+ });
290174
+ const { copyToClipboard } = createClipboardManager(renderer);
290175
+ setupAutoCopy(renderer, copyToClipboard);
289916
290176
  const cleanup = () => {
289917
290177
  renderer.destroy();
289918
290178
  process.exit(0);
@@ -289934,16 +290194,19 @@ async function main2() {
289934
290194
  createRoot(renderer).render(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ThemeProvider, {
289935
290195
  initialTheme: themeName,
289936
290196
  initialMode: mode,
289937
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastProvider, {
289938
- children: [
289939
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ErrorBoundary2, {
289940
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(App, {
289941
- appConfig
289942
- }, undefined, false, undefined, this)
289943
- }, undefined, false, undefined, this),
289944
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastContainer, {}, undefined, false, undefined, this)
289945
- ]
289946
- }, undefined, true, undefined, this)
289947
- }, undefined, false, undefined, this));
290197
+ children: [
290198
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ConsoleThemeSync, {}, undefined, false, undefined, this),
290199
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastProvider, {
290200
+ children: [
290201
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ErrorBoundary2, {
290202
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(App, {
290203
+ appConfig
290204
+ }, undefined, false, undefined, this)
290205
+ }, undefined, false, undefined, this),
290206
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastContainer, {}, undefined, false, undefined, this)
290207
+ ]
290208
+ }, undefined, true, undefined, this)
290209
+ ]
290210
+ }, undefined, true, undefined, this));
289948
290211
  }
289949
290212
  main2();