@pensar/apex 0.0.90 → 0.0.91-canary.53063f8d

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 +673 -533
  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.90",
31974
+ version: "0.0.91-canary.53063f8d",
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",
@@ -89342,10 +89342,21 @@ var init_session = __esm(() => {
89342
89342
  };
89343
89343
  });
89344
89344
 
89345
+ // src/lib/cwe/types.ts
89346
+ var CweEntrySchema;
89347
+ var init_types2 = __esm(() => {
89348
+ init_zod();
89349
+ CweEntrySchema = exports_external.object({
89350
+ id: exports_external.string().regex(/^CWE-\d+$/, "Must be CWE-<number> format"),
89351
+ reasoning: exports_external.string().describe("Why this CWE applies to the observed vulnerability")
89352
+ });
89353
+ });
89354
+
89345
89355
  // src/core/report/schemas.ts
89346
89356
  var PentestReportFindingSchema, PentestReportSchema, REPORT_VERSION = "1.0";
89347
89357
  var init_schemas3 = __esm(() => {
89348
89358
  init_zod();
89359
+ init_types2();
89349
89360
  PentestReportFindingSchema = exports_external.object({
89350
89361
  title: exports_external.string(),
89351
89362
  severity: exports_external.enum(["CRITICAL", "HIGH", "MEDIUM", "LOW"]),
@@ -89355,7 +89366,8 @@ var init_schemas3 = __esm(() => {
89355
89366
  endpoint: exports_external.string(),
89356
89367
  pocPath: exports_external.string(),
89357
89368
  remediation: exports_external.string(),
89358
- references: exports_external.string().optional()
89369
+ references: exports_external.string().optional(),
89370
+ cwes: exports_external.array(CweEntrySchema).optional()
89359
89371
  });
89360
89372
  PentestReportSchema = exports_external.object({
89361
89373
  version: exports_external.string().regex(/^1\.\d+$/),
@@ -89469,6 +89481,12 @@ function renderFinding(finding, metadata) {
89469
89481
  finding.evidence,
89470
89482
  "```",
89471
89483
  "",
89484
+ ...finding.cwes?.length ? [
89485
+ "## CWE Classification",
89486
+ "",
89487
+ ...finding.cwes.map((cwe) => `- **${cwe.id}** — ${cwe.reasoning}`),
89488
+ ""
89489
+ ] : [],
89472
89490
  "## POC",
89473
89491
  "",
89474
89492
  `Path: \`${finding.pocPath}\``,
@@ -89508,44 +89526,22 @@ import {
89508
89526
  readdirSync as readdirSync2
89509
89527
  } from "fs";
89510
89528
  import { join as join4 } from "path";
89511
- function mapToSavedMessage(msg) {
89512
- const m2 = msg;
89513
- if (typeof m2.content === "string") {
89514
- return { role: m2.role, content: m2.content };
89515
- }
89516
- if (Array.isArray(m2.content)) {
89517
- const mapped = m2.content.map((part) => {
89518
- if (part.type === "tool-call") {
89519
- return {
89520
- type: "tool-call",
89521
- toolCallId: part.toolCallId,
89522
- toolName: part.toolName,
89523
- input: part.args ?? part.input
89524
- };
89525
- }
89526
- if (part.type === "tool-result") {
89527
- return {
89528
- type: "tool-result",
89529
- toolCallId: part.toolCallId,
89530
- toolName: part.toolName,
89531
- output: part.result ?? part.output
89532
- };
89533
- }
89534
- return {
89535
- type: "text",
89536
- text: part.text ?? ""
89537
- };
89538
- });
89539
- return { role: m2.role, content: mapped };
89529
+ function loadSubagentMessages(session, agentName) {
89530
+ const filePath = join4(session.rootPath, SUBAGENTS_DIR, `${agentName}.json`);
89531
+ if (!existsSync8(filePath))
89532
+ return [];
89533
+ try {
89534
+ const data = JSON.parse(readFileSync3(filePath, "utf-8"));
89535
+ return data.messages;
89536
+ } catch {
89537
+ return [];
89540
89538
  }
89541
- return { role: m2.role, content: String(m2.content) };
89542
89539
  }
89543
89540
  function saveSubagentData(session, data) {
89544
89541
  const subagentsDir = join4(session.rootPath, SUBAGENTS_DIR);
89545
89542
  mkdirSync2(subagentsDir, { recursive: true });
89546
89543
  let toolCallCount = 0;
89547
89544
  let stepCount = 0;
89548
- const savedMessages = [];
89549
89545
  for (const msg of data.messages) {
89550
89546
  if (msg.role === "assistant") {
89551
89547
  stepCount++;
@@ -89556,12 +89552,10 @@ function saveSubagentData(session, data) {
89556
89552
  }
89557
89553
  }
89558
89554
  }
89559
- savedMessages.push(mapToSavedMessage(msg));
89560
89555
  }
89561
- const now2 = new Date;
89562
89556
  const savedData = {
89563
89557
  agentName: data.agentName,
89564
- timestamp: now2.toISOString(),
89558
+ timestamp: new Date().toISOString(),
89565
89559
  target: data.target,
89566
89560
  objective: data.objective,
89567
89561
  vulnerabilityClass: data.vulnerabilityClass,
@@ -89570,16 +89564,24 @@ function saveSubagentData(session, data) {
89570
89564
  findingsCount: data.findingsCount ?? 0,
89571
89565
  status: data.status,
89572
89566
  error: data.error,
89573
- messages: savedMessages
89567
+ messages: data.messages
89574
89568
  };
89575
- const ts = now2.toISOString().replace(/[:.]/g, "-");
89576
- const filename = `${data.agentName}-${ts}.json`;
89577
- writeFileSync2(join4(subagentsDir, filename), JSON.stringify(savedData, null, 2));
89569
+ writeFileSync2(join4(subagentsDir, `${data.agentName}.json`), JSON.stringify(savedData, null, 2));
89578
89570
  }
89579
89571
  function writeAgentManifest(session, entries2) {
89580
89572
  const manifestPath = join4(session.rootPath, MANIFEST_FILE);
89581
89573
  writeFileSync2(manifestPath, JSON.stringify(entries2, null, 2));
89582
89574
  }
89575
+ function readAgentManifest(session) {
89576
+ const manifestPath = join4(session.rootPath, MANIFEST_FILE);
89577
+ if (!existsSync8(manifestPath))
89578
+ return [];
89579
+ try {
89580
+ return JSON.parse(readFileSync3(manifestPath, "utf-8"));
89581
+ } catch {
89582
+ return [];
89583
+ }
89584
+ }
89583
89585
  function buildManifestEntries(targets) {
89584
89586
  return targets.map((t2, i) => ({
89585
89587
  id: `pentest-agent-${i + 1}`,
@@ -89592,18 +89594,31 @@ function buildManifestEntries(targets) {
89592
89594
  }));
89593
89595
  }
89594
89596
  function finalizeManifest(session, entries2, results) {
89595
- const finalManifest = entries2.map((entry, i) => ({
89596
- ...entry,
89597
- status: results[i] != null ? "completed" : "failed",
89598
- completedAt: new Date().toISOString()
89599
- }));
89597
+ const finalManifest = entries2.map((entry, i) => {
89598
+ if (entry.status === "completed")
89599
+ return entry;
89600
+ return {
89601
+ ...entry,
89602
+ status: results[i] != null ? "completed" : "failed",
89603
+ completedAt: new Date().toISOString()
89604
+ };
89605
+ });
89600
89606
  writeAgentManifest(session, finalManifest);
89601
89607
  }
89608
+ function updateManifestEntryStatus(session, agentId, status) {
89609
+ const manifest = readAgentManifest(session);
89610
+ const updated = manifest.map((e) => e.id === agentId ? { ...e, status, completedAt: new Date().toISOString() } : e);
89611
+ writeAgentManifest(session, updated);
89612
+ }
89613
+ function getCompletedAgentIds(session) {
89614
+ const manifest = readAgentManifest(session);
89615
+ return new Set(manifest.filter((e) => e.id.startsWith("pentest-agent-") && e.status === "completed").map((e) => e.id));
89616
+ }
89602
89617
  function parseSubagentFilename(filename) {
89603
89618
  if (filename.startsWith("attack-surface-agent")) {
89604
89619
  return { agentType: "attack-surface", name: "Attack Surface Discovery" };
89605
89620
  }
89606
- const pentestMatch = filename.match(/^pentest-agent-(\d+)-/);
89621
+ const pentestMatch = filename.match(/^pentest-agent-(\d+)/);
89607
89622
  if (pentestMatch) {
89608
89623
  return {
89609
89624
  agentType: "pentest",
@@ -89655,7 +89670,8 @@ function convertMessagesToUI(messages, baseTime) {
89655
89670
  createdAt
89656
89671
  });
89657
89672
  } else if (part.type === "tool-call") {
89658
- const toolDescription = typeof part.input?.toolCallDescription === "string" ? part.input.toolCallDescription : part.toolName || "tool";
89673
+ const input = part.input;
89674
+ const toolDescription = typeof input?.toolCallDescription === "string" ? input.toolCallDescription : part.toolName || "tool";
89659
89675
  const result = part.toolCallId ? toolResults.get(part.toolCallId) : undefined;
89660
89676
  uiMessages.push({
89661
89677
  role: "tool",
@@ -89663,7 +89679,7 @@ function convertMessagesToUI(messages, baseTime) {
89663
89679
  createdAt,
89664
89680
  toolCallId: part.toolCallId,
89665
89681
  toolName: part.toolName,
89666
- args: part.input,
89682
+ args: input,
89667
89683
  result,
89668
89684
  status: "completed"
89669
89685
  });
@@ -89674,8 +89690,7 @@ function convertMessagesToUI(messages, baseTime) {
89674
89690
  return uiMessages;
89675
89691
  }
89676
89692
  function convertModelMessagesToUI(messages) {
89677
- const saved = messages.map((m2) => mapToSavedMessage(m2));
89678
- return convertMessagesToUI(saved, new Date);
89693
+ return convertMessagesToUI(messages, new Date);
89679
89694
  }
89680
89695
  function loadSubagents(rootPath) {
89681
89696
  const subagentsPath = join4(rootPath, SUBAGENTS_DIR);
@@ -89683,11 +89698,7 @@ function loadSubagents(rootPath) {
89683
89698
  const agentNameIndex = new Map;
89684
89699
  if (existsSync8(subagentsPath)) {
89685
89700
  const files = readdirSync2(subagentsPath).filter((f) => f.endsWith(".json"));
89686
- files.sort((a, b2) => {
89687
- const timeA = a.match(/\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}/)?.[0] || "";
89688
- const timeB = b2.match(/\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}/)?.[0] || "";
89689
- return timeA.localeCompare(timeB);
89690
- });
89701
+ files.sort();
89691
89702
  for (const file2 of files) {
89692
89703
  if (file2.startsWith("orchestrator-"))
89693
89704
  continue;
@@ -89711,9 +89722,9 @@ function loadSubagents(rootPath) {
89711
89722
  }
89712
89723
  break;
89713
89724
  }
89714
- const idx = subagents.length;
89725
+ agentNameIndex.set(data.agentName, subagents.length);
89715
89726
  subagents.push({
89716
- id: `loaded-${file2.replace(".json", "")}`,
89727
+ id: data.agentName,
89717
89728
  name: data.agentName === "attack-surface-agent" ? "Attack Surface Discovery" : name26,
89718
89729
  type: agentType,
89719
89730
  target: data.target || "Unknown",
@@ -89721,7 +89732,6 @@ function loadSubagents(rootPath) {
89721
89732
  createdAt: timestamp,
89722
89733
  status
89723
89734
  });
89724
- agentNameIndex.set(data.agentName, idx);
89725
89735
  } catch (e) {
89726
89736
  console.error(`Failed to load subagent file ${file2}:`, e);
89727
89737
  }
@@ -89769,6 +89779,116 @@ function loadSubagents(rootPath) {
89769
89779
  var SUBAGENTS_DIR = "subagents", MANIFEST_FILE = "agent-manifest.json";
89770
89780
  var init_persistence = () => {};
89771
89781
 
89782
+ // src/core/session/loader.ts
89783
+ import { join as join5 } from "path";
89784
+ import { existsSync as existsSync9, readFileSync as readFileSync4 } from "fs";
89785
+ function loadAttackSurfaceResults(rootPath) {
89786
+ const resultsPath = join5(rootPath, "attack-surface-results.json");
89787
+ if (!existsSync9(resultsPath)) {
89788
+ return null;
89789
+ }
89790
+ try {
89791
+ return JSON.parse(readFileSync4(resultsPath, "utf-8"));
89792
+ } catch (e) {
89793
+ console.error("Failed to load attack surface results:", e);
89794
+ return null;
89795
+ }
89796
+ }
89797
+ function hasReport(rootPath) {
89798
+ const reportPath = join5(rootPath, REPORT_FILENAME_MD);
89799
+ return existsSync9(reportPath);
89800
+ }
89801
+ function createDiscoveryFromLogs(rootPath, session) {
89802
+ const logPath = join5(rootPath, "logs", "streamlined-pentest.log");
89803
+ if (!existsSync9(logPath)) {
89804
+ return null;
89805
+ }
89806
+ try {
89807
+ const logContent = readFileSync4(logPath, "utf-8");
89808
+ const lines = logContent.split(`
89809
+ `).filter(Boolean);
89810
+ const messages = [];
89811
+ for (const line of lines) {
89812
+ const match = line.match(/^(\d{4}-\d{2}-\d{2}T[\d:.]+Z) - \[(\w+)\] (.+)$/);
89813
+ if (!match)
89814
+ continue;
89815
+ const [, timestamp, _level, content] = match;
89816
+ const createdAt = new Date(timestamp);
89817
+ if (content.startsWith("[Tool]")) {
89818
+ const toolMatch = content.match(/\[Tool\] (\w+): (.+)/);
89819
+ if (toolMatch) {
89820
+ messages.push({
89821
+ role: "tool",
89822
+ content: `✓ ${toolMatch[2]}`,
89823
+ createdAt,
89824
+ toolName: toolMatch[1],
89825
+ status: "completed"
89826
+ });
89827
+ }
89828
+ } else if (content.startsWith("[Step")) {
89829
+ const stepMatch = content.match(/\[Step \d+\] (.+)/);
89830
+ if (stepMatch) {
89831
+ messages.push({
89832
+ role: "assistant",
89833
+ content: stepMatch[1],
89834
+ createdAt
89835
+ });
89836
+ }
89837
+ }
89838
+ }
89839
+ if (messages.length === 0) {
89840
+ return null;
89841
+ }
89842
+ return {
89843
+ id: "discovery-from-logs",
89844
+ name: "Attack Surface Discovery",
89845
+ type: "attack-surface",
89846
+ target: session.targets[0] || "Unknown",
89847
+ messages,
89848
+ createdAt: new Date(session.time.created),
89849
+ status: "completed"
89850
+ };
89851
+ } catch (e) {
89852
+ console.error("Failed to parse logs:", e);
89853
+ return null;
89854
+ }
89855
+ }
89856
+ async function loadSessionState(session) {
89857
+ const rootPath = session.rootPath;
89858
+ let subagents = loadSubagents(rootPath);
89859
+ const hasAttackSurfaceAgent = subagents.some((s) => s.type === "attack-surface");
89860
+ if (!hasAttackSurfaceAgent) {
89861
+ const discoveryAgent = createDiscoveryFromLogs(rootPath, session);
89862
+ if (discoveryAgent) {
89863
+ subagents = [discoveryAgent, ...subagents];
89864
+ }
89865
+ }
89866
+ const attackSurfaceResults = loadAttackSurfaceResults(rootPath);
89867
+ const hasReportFile = hasReport(rootPath);
89868
+ const hasDiscoverySubagent = subagents.some((s) => s.type === "attack-surface");
89869
+ const interruptedDuringDiscovery = !attackSurfaceResults && !hasReportFile && hasDiscoverySubagent;
89870
+ if (interruptedDuringDiscovery) {
89871
+ for (let i = 0;i < subagents.length; i++) {
89872
+ if (subagents[i].type === "attack-surface" && subagents[i].status === "completed") {
89873
+ subagents[i] = { ...subagents[i], status: "paused" };
89874
+ }
89875
+ }
89876
+ }
89877
+ const isComplete = hasReportFile;
89878
+ return {
89879
+ session,
89880
+ subagents,
89881
+ attackSurfaceResults,
89882
+ isComplete,
89883
+ hasReport: hasReportFile,
89884
+ interruptedDuringDiscovery
89885
+ };
89886
+ }
89887
+ var init_loader = __esm(() => {
89888
+ init_persistence();
89889
+ init_report();
89890
+ });
89891
+
89772
89892
  // src/core/agents/specialized/attackSurface/prompts.ts
89773
89893
  var SYSTEM = `You are an autonomous attack surface analysis agent. Your mission is to comprehensively map the attack surface of a target and produce a structured report of all discovered assets and pentest objectives.
89774
89894
 
@@ -90220,7 +90340,7 @@ function loadAttackSurfaceResults2(resultsPath) {
90220
90340
  const data = readFileSync6(resultsPath, "utf-8");
90221
90341
  return JSON.parse(data);
90222
90342
  }
90223
- var init_types2 = () => {};
90343
+ var init_types3 = () => {};
90224
90344
 
90225
90345
  // src/core/ai/index.ts
90226
90346
  var init_ai2 = __esm(() => {
@@ -90333,7 +90453,7 @@ var init_zod_compat = __esm(() => {
90333
90453
 
90334
90454
  // node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
90335
90455
  var LATEST_PROTOCOL_VERSION = "2025-11-25", SUPPORTED_PROTOCOL_VERSIONS, RELATED_TASK_META_KEY = "io.modelcontextprotocol/related-task", JSONRPC_VERSION = "2.0", AssertObjectSchema, ProgressTokenSchema, CursorSchema, TaskCreationParamsSchema, TaskMetadataSchema, RelatedTaskMetadataSchema, RequestMetaSchema, BaseRequestParamsSchema, TaskAugmentedRequestParamsSchema, isTaskAugmentedRequestParams = (value) => TaskAugmentedRequestParamsSchema.safeParse(value).success, RequestSchema, NotificationsParamsSchema, NotificationSchema, ResultSchema, RequestIdSchema, JSONRPCRequestSchema, isJSONRPCRequest = (value) => JSONRPCRequestSchema.safeParse(value).success, JSONRPCNotificationSchema, isJSONRPCNotification = (value) => JSONRPCNotificationSchema.safeParse(value).success, JSONRPCResultResponseSchema, isJSONRPCResultResponse = (value) => JSONRPCResultResponseSchema.safeParse(value).success, ErrorCode, JSONRPCErrorResponseSchema, isJSONRPCErrorResponse = (value) => JSONRPCErrorResponseSchema.safeParse(value).success, JSONRPCMessageSchema, JSONRPCResponseSchema, EmptyResultSchema, CancelledNotificationParamsSchema, CancelledNotificationSchema, IconSchema, IconsSchema, BaseMetadataSchema, ImplementationSchema, FormElicitationCapabilitySchema, ElicitationCapabilitySchema, ClientTasksCapabilitySchema, ServerTasksCapabilitySchema, ClientCapabilitiesSchema, InitializeRequestParamsSchema, InitializeRequestSchema, ServerCapabilitiesSchema, InitializeResultSchema, InitializedNotificationSchema, PingRequestSchema, ProgressSchema, ProgressNotificationParamsSchema, ProgressNotificationSchema, PaginatedRequestParamsSchema, PaginatedRequestSchema, PaginatedResultSchema, TaskStatusSchema, TaskSchema, CreateTaskResultSchema, TaskStatusNotificationParamsSchema, TaskStatusNotificationSchema, GetTaskRequestSchema, GetTaskResultSchema, GetTaskPayloadRequestSchema, GetTaskPayloadResultSchema, ListTasksRequestSchema, ListTasksResultSchema, CancelTaskRequestSchema, CancelTaskResultSchema, ResourceContentsSchema, TextResourceContentsSchema, Base64Schema, BlobResourceContentsSchema, RoleSchema, AnnotationsSchema, ResourceSchema, ResourceTemplateSchema, ListResourcesRequestSchema, ListResourcesResultSchema, ListResourceTemplatesRequestSchema, ListResourceTemplatesResultSchema, ResourceRequestParamsSchema, ReadResourceRequestParamsSchema, ReadResourceRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, SubscribeRequestParamsSchema, SubscribeRequestSchema, UnsubscribeRequestParamsSchema, UnsubscribeRequestSchema, ResourceUpdatedNotificationParamsSchema, ResourceUpdatedNotificationSchema, PromptArgumentSchema, PromptSchema, ListPromptsRequestSchema, ListPromptsResultSchema, GetPromptRequestParamsSchema, GetPromptRequestSchema, TextContentSchema, ImageContentSchema, AudioContentSchema, ToolUseContentSchema, EmbeddedResourceSchema, ResourceLinkSchema, ContentBlockSchema, PromptMessageSchema, GetPromptResultSchema, PromptListChangedNotificationSchema, ToolAnnotationsSchema, ToolExecutionSchema, ToolSchema, ListToolsRequestSchema, ListToolsResultSchema, CallToolResultSchema, CompatibilityCallToolResultSchema, CallToolRequestParamsSchema, CallToolRequestSchema, ToolListChangedNotificationSchema, ListChangedOptionsBaseSchema, LoggingLevelSchema, SetLevelRequestParamsSchema, SetLevelRequestSchema, LoggingMessageNotificationParamsSchema, LoggingMessageNotificationSchema, ModelHintSchema, ModelPreferencesSchema, ToolChoiceSchema, ToolResultContentSchema, SamplingContentSchema, SamplingMessageContentBlockSchema, SamplingMessageSchema, CreateMessageRequestParamsSchema, CreateMessageRequestSchema, CreateMessageResultSchema, CreateMessageResultWithToolsSchema, BooleanSchemaSchema, StringSchemaSchema, NumberSchemaSchema, UntitledSingleSelectEnumSchemaSchema, TitledSingleSelectEnumSchemaSchema, LegacyTitledEnumSchemaSchema, SingleSelectEnumSchemaSchema, UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema, MultiSelectEnumSchemaSchema, EnumSchemaSchema, PrimitiveSchemaDefinitionSchema, ElicitRequestFormParamsSchema, ElicitRequestURLParamsSchema, ElicitRequestParamsSchema, ElicitRequestSchema, ElicitationCompleteNotificationParamsSchema, ElicitationCompleteNotificationSchema, ElicitResultSchema, ResourceTemplateReferenceSchema, PromptReferenceSchema, CompleteRequestParamsSchema, CompleteRequestSchema, CompleteResultSchema, RootSchema, ListRootsRequestSchema, ListRootsResultSchema, RootsListChangedNotificationSchema, ClientRequestSchema, ClientNotificationSchema, ClientResultSchema, ServerRequestSchema, ServerNotificationSchema, ServerResultSchema, McpError, UrlElicitationRequiredError;
90336
- var init_types3 = __esm(() => {
90456
+ var init_types4 = __esm(() => {
90337
90457
  init_v4();
90338
90458
  SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, "2025-06-18", "2025-03-26", "2024-11-05", "2024-10-07"];
90339
90459
  AssertObjectSchema = custom2((v2) => v2 !== null && (typeof v2 === "object" || typeof v2 === "function"));
@@ -92234,7 +92354,7 @@ function mergeCapabilities(base, additional) {
92234
92354
  var DEFAULT_REQUEST_TIMEOUT_MSEC = 60000;
92235
92355
  var init_protocol = __esm(() => {
92236
92356
  init_zod_compat();
92237
- init_types3();
92357
+ init_types4();
92238
92358
  init_zod_json_schema_compat();
92239
92359
  });
92240
92360
 
@@ -104284,7 +104404,7 @@ class ExperimentalClientTasks {
104284
104404
  }
104285
104405
  }
104286
104406
  var init_client = __esm(() => {
104287
- init_types3();
104407
+ init_types4();
104288
104408
  });
104289
104409
 
104290
104410
  // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
@@ -104367,7 +104487,7 @@ function getSupportedElicitationModes(capabilities) {
104367
104487
  var Client;
104368
104488
  var init_client2 = __esm(() => {
104369
104489
  init_protocol();
104370
- init_types3();
104490
+ init_types4();
104371
104491
  init_ajv_provider();
104372
104492
  init_zod_compat();
104373
104493
  init_client();
@@ -105282,7 +105402,7 @@ function serializeMessage(message) {
105282
105402
  `;
105283
105403
  }
105284
105404
  var init_stdio = __esm(() => {
105285
- init_types3();
105405
+ init_types4();
105286
105406
  });
105287
105407
 
105288
105408
  // node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js
@@ -105634,9 +105754,10 @@ class PlaywrightMcpSession {
105634
105754
  }
105635
105755
  function createBrowserTools(targetUrl, evidenceDir, mode = "pentest", logger, abortSignal, headless) {
105636
105756
  const session = new PlaywrightMcpSession(headless ?? defaultHeadless);
105637
- abortSignal?.addEventListener("abort", () => {
105638
- session.disconnect().catch(() => {});
105639
- });
105757
+ if (abortSignal) {
105758
+ const onAbort = () => session.disconnect().catch(() => {});
105759
+ abortSignal.addEventListener("abort", onAbort, { once: true });
105760
+ }
105640
105761
  if (!existsSync11(evidenceDir)) {
105641
105762
  mkdirSync3(evidenceDir, { recursive: true });
105642
105763
  }
@@ -107192,7 +107313,7 @@ function getSeverityFromScore(score) {
107192
107313
  return "HIGH";
107193
107314
  return "CRITICAL";
107194
107315
  }
107195
- var init_types4 = () => {};
107316
+ var init_types5 = () => {};
107196
107317
 
107197
107318
  // src/lib/cvss/macrovector-scores.ts
107198
107319
  var MACROVECTOR_LOOKUP, METRIC_LEVELS, MAX_SEVERITY, STEP = 0.1, EPSILON;
@@ -107766,7 +107887,7 @@ function getScoreType(metrics) {
107766
107887
  }
107767
107888
  var BASE_METRICS, THREAT_METRICS, ENVIRONMENTAL_METRICS, SUPPLEMENTAL_METRICS;
107768
107889
  var init_calculator = __esm(() => {
107769
- init_types4();
107890
+ init_types5();
107770
107891
  init_macrovector_scores();
107771
107892
  BASE_METRICS = [
107772
107893
  "AV",
@@ -107803,7 +107924,7 @@ var init_calculator = __esm(() => {
107803
107924
 
107804
107925
  // src/lib/cvss/index.ts
107805
107926
  var init_cvss = __esm(() => {
107806
- init_types4();
107927
+ init_types5();
107807
107928
  init_calculator();
107808
107929
  init_macrovector_scores();
107809
107930
  });
@@ -107828,7 +107949,8 @@ async function scoreFindingWithCVSS(input, model, authConfig, abortSignal) {
107828
107949
  vectorString: cvssResult.vectorString,
107829
107950
  metrics: cvssResult.metrics,
107830
107951
  scoreType: cvssResult.scoreType,
107831
- reasoning: assessment.reasoning
107952
+ reasoning: assessment.reasoning,
107953
+ cwes: assessment.cwes
107832
107954
  };
107833
107955
  }
107834
107956
  function truncateField(value, limit) {
@@ -108012,11 +108134,45 @@ var CVSSMetricsOutputSchema, CVSS_SCORER_SYSTEM_PROMPT = `You are a CVSS 4.0 sco
108012
108134
  6. Assess impact on both the vulnerable system AND potential subsequent systems
108013
108135
  7. Since a POC exists and confirmed the vulnerability, E should typically be 'A'
108014
108136
 
108015
- Always provide brief reasoning explaining your key decisions.`, MAX_EVIDENCE_CHARS = 1e4, MAX_DESCRIPTION_CHARS = 3000, MAX_IMPACT_CHARS = 2000;
108137
+ Always provide brief reasoning explaining your key decisions.
108138
+
108139
+ ## CWE Assignment Guidelines
108140
+
108141
+ In addition to CVSS metrics, assign one or more CWE identifiers to the finding. For each CWE, provide a brief reasoning explaining why it applies.
108142
+
108143
+ ### Common CWE Mappings
108144
+
108145
+ | Vulnerability Class | Primary CWE | Related CWEs |
108146
+ |---------------------|------------|--------------|
108147
+ | SQL Injection | CWE-89 | CWE-564 (Hibernate), CWE-943 (NoSQL) |
108148
+ | Cross-Site Scripting (XSS) | CWE-79 | CWE-80 (Basic XSS), CWE-87 (Alt XSS) |
108149
+ | Command/OS Injection | CWE-78 | CWE-77 (Command Injection) |
108150
+ | Code Injection / RCE | CWE-94 | CWE-95 (Eval Injection), CWE-96 (Static Code Injection) |
108151
+ | IDOR / Access Control | CWE-639 | CWE-284 (Improper Access Control), CWE-862 (Missing AuthZ) |
108152
+ | SSRF | CWE-918 | — |
108153
+ | Path Traversal / LFI | CWE-22 | CWE-23 (Relative Path), CWE-36 (Absolute Path) |
108154
+ | XXE | CWE-611 | CWE-776 (Recursive Entity) |
108155
+ | SSTI | CWE-1336 | CWE-94 (Code Injection) |
108156
+ | CSRF | CWE-352 | — |
108157
+ | Deserialization | CWE-502 | — |
108158
+ | Open Redirect | CWE-601 | — |
108159
+ | Information Disclosure | CWE-200 | CWE-209 (Error Messages), CWE-532 (Log Files) |
108160
+ | Authentication Bypass | CWE-287 | CWE-306 (Missing Auth) |
108161
+ | Cryptographic Issues | CWE-327 | CWE-328 (Weak Hash), CWE-330 (Insufficient Randomness) |
108162
+
108163
+ ### CWE Assignment Rules
108164
+
108165
+ 1. Assign the **most specific applicable CWE(s)** — prefer CWE-89 (SQL Injection) over CWE-74 (generic Injection).
108166
+ 2. Use the standard \`CWE-<number>\` format (e.g., CWE-89, not "CWE 89" or "89").
108167
+ 3. Assign **1-3 CWEs** per finding. Multiple CWEs are appropriate when the vulnerability spans categories (e.g., an IDOR that also leaks PII: CWE-639 + CWE-200).
108168
+ 4. Order CWEs by relevance — the primary weakness first.
108169
+ 5. When the vulnerability class is provided, use it as a strong hint but verify against the evidence.
108170
+ 6. For each CWE, provide a specific reasoning explaining why it applies to *this* finding — not a generic definition of the CWE.`, MAX_EVIDENCE_CHARS = 1e4, MAX_DESCRIPTION_CHARS = 3000, MAX_IMPACT_CHARS = 2000;
108016
108171
  var init_cvssScorer = __esm(() => {
108017
108172
  init_zod();
108018
108173
  init_ai2();
108019
108174
  init_cvss();
108175
+ init_types2();
108020
108176
  CVSSMetricsOutputSchema = exports_external.object({
108021
108177
  metrics: exports_external.object({
108022
108178
  AV: exports_external.enum(["N", "A", "L", "P"]).describe("Attack Vector: N=Network (remotely exploitable), A=Adjacent network, L=Local access required, P=Physical access required"),
@@ -108032,7 +108188,8 @@ var init_cvssScorer = __esm(() => {
108032
108188
  SA: exports_external.enum(["H", "L", "N"]).describe("Availability Impact on Subsequent Systems: H=High, L=Low, N=None"),
108033
108189
  E: exports_external.enum(["A", "P", "U"]).describe("Exploit Maturity: A=Attacked (working exploit exists), P=POC available, U=Unreported")
108034
108190
  }),
108035
- reasoning: exports_external.string().describe("Brief explanation (2-3 sentences) of the key factors that influenced the metric choices")
108191
+ reasoning: exports_external.string().describe("Brief explanation (2-3 sentences) of the key factors that influenced the metric choices"),
108192
+ cwes: exports_external.array(CweEntrySchema).describe("CWE classifications for this vulnerability, most specific first")
108036
108193
  });
108037
108194
  });
108038
108195
 
@@ -108057,7 +108214,8 @@ FINDING STRUCTURE:
108057
108214
  - Impact: Business and technical consequences if exploited
108058
108215
  - Evidence: Commands run, responses received, proof of exploitation
108059
108216
  - Remediation: Specific, actionable steps to fix
108060
- - References: CVE, CWE, OWASP, or security advisories`,
108217
+ - References: CVE, CWE, OWASP, or security advisories
108218
+ - Vulnerability Class: The class of vulnerability (e.g., sqli, xss, command-injection) — improves CWE accuracy`,
108061
108219
  inputSchema: documentVulnerabilityInputSchema,
108062
108220
  execute: async (input) => {
108063
108221
  try {
@@ -108082,7 +108240,8 @@ FINDING STRUCTURE:
108082
108240
  impact: input.impact,
108083
108241
  evidence: evidenceForPrompt,
108084
108242
  endpoint: input.endpoint,
108085
- remediation: input.remediation
108243
+ remediation: input.remediation,
108244
+ vulnerabilityClass: input.vulnerabilityClass
108086
108245
  },
108087
108246
  agentMessages: []
108088
108247
  }, ctx4.model, ctx4.authConfig, ctx4.abortSignal);
@@ -108115,6 +108274,7 @@ FINDING STRUCTURE:
108115
108274
  sessionId: session.id,
108116
108275
  target: session.targets[0],
108117
108276
  ...evidenceFilePath && { evidenceFile: evidenceFilePath },
108277
+ cwes: cvssResult.cwes,
108118
108278
  cvss: {
108119
108279
  score: cvssResult.score,
108120
108280
  severity: cvssResult.severity,
@@ -108144,6 +108304,10 @@ FINDING STRUCTURE:
108144
108304
  **Score Type:** ${cvssResult.scoreType}
108145
108305
 
108146
108306
  **Reasoning:** ${cvssResult.reasoning}`;
108307
+ const cweSection = cvssResult.cwes?.length ? `## CWE Classification
108308
+
108309
+ ${cvssResult.cwes.map((cwe) => `- **${cwe.id}** — ${cwe.reasoning}`).join(`
108310
+ `)}` : "";
108147
108311
  const evidenceSection = evidenceFilePath ? `## Evidence
108148
108312
 
108149
108313
  \`\`\`
@@ -108175,7 +108339,9 @@ ${finding.impact}
108175
108339
 
108176
108340
  ${cvssSection}
108177
108341
 
108178
- ${evidenceSection}
108342
+ ${cweSection ? `${cweSection}
108343
+
108344
+ ` : ""}${evidenceSection}
108179
108345
 
108180
108346
  ## POC
108181
108347
 
@@ -108195,7 +108361,8 @@ ${finding.references}` : ""}
108195
108361
  `;
108196
108362
  writeFileSync7(mdPath, markdown);
108197
108363
  const summaryPath = join11(session.rootPath, "findings-summary.md");
108198
- const summaryEntry = `- [${finding.severity}] (CVSS ${cvssResult.score}) ${finding.title} - \`findings/${mdFilename}\`
108364
+ const cweTag = cvssResult.cwes?.length ? ` (${cvssResult.cwes.map((c) => c.id).join(", ")})` : "";
108365
+ const summaryEntry = `- [${finding.severity}] (CVSS ${cvssResult.score})${cweTag} ${finding.title} - \`findings/${mdFilename}\`
108199
108366
  `;
108200
108367
  try {
108201
108368
  appendFileSync2(summaryPath, summaryEntry);
@@ -108248,6 +108415,7 @@ var init_documentFinding = __esm(() => {
108248
108415
  pocPath: exports_external.string().describe("Relative path to the POC script (e.g., pocs/poc_sqli.sh)"),
108249
108416
  remediation: exports_external.string().describe("Steps to fix the issue"),
108250
108417
  references: exports_external.string().optional().describe("CVE, CWE, or related references"),
108418
+ vulnerabilityClass: exports_external.string().optional().describe("The class of vulnerability (e.g., sqli, xss, command-injection, idor, ssrf, path-traversal, crypto, cve)"),
108251
108419
  toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing (e.g., 'Documenting SQL injection finding')")
108252
108420
  });
108253
108421
  FALLBACK_CVSS = {
@@ -108269,7 +108437,8 @@ var init_documentFinding = __esm(() => {
108269
108437
  E: "A"
108270
108438
  },
108271
108439
  scoreType: "CVSS-BT",
108272
- reasoning: "CVSS scoring unavailable — using conservative MEDIUM default."
108440
+ reasoning: "CVSS scoring unavailable — using conservative MEDIUM default.",
108441
+ cwes: []
108273
108442
  };
108274
108443
  });
108275
108444
 
@@ -108451,9 +108620,17 @@ function runScript(runner, scriptPath, timeout, abortSignal) {
108451
108620
  let stderr = "";
108452
108621
  let killed = false;
108453
108622
  let resolved = false;
108623
+ let abortCleanup;
108624
+ if (abortSignal) {
108625
+ const handler = () => killProcess();
108626
+ abortSignal.addEventListener("abort", handler, { once: true });
108627
+ abortCleanup = () => abortSignal.removeEventListener("abort", handler);
108628
+ }
108454
108629
  const safeResolve = (result) => {
108455
108630
  if (!resolved) {
108456
108631
  resolved = true;
108632
+ clearTimeout(timeoutTimer);
108633
+ abortCleanup?.();
108457
108634
  resolve4(result);
108458
108635
  }
108459
108636
  };
@@ -108487,18 +108664,11 @@ function runScript(runner, scriptPath, timeout, abortSignal) {
108487
108664
  stderr += data.toString();
108488
108665
  });
108489
108666
  child.on("close", (code) => {
108490
- clearTimeout(timeoutTimer);
108491
108667
  safeResolve({ stdout, stderr, exitCode: code ?? 1 });
108492
108668
  });
108493
108669
  child.on("error", (err) => {
108494
- clearTimeout(timeoutTimer);
108495
108670
  safeResolve({ stdout, stderr, exitCode: 1 });
108496
108671
  });
108497
- if (abortSignal) {
108498
- const handler = () => killProcess();
108499
- abortSignal.addEventListener("abort", handler, { once: true });
108500
- child.on("close", () => abortSignal.removeEventListener("abort", handler));
108501
- }
108502
108672
  });
108503
108673
  }
108504
108674
  var MAX_POC_ATTEMPTS = 3, createPocInputSchema;
@@ -108733,6 +108903,23 @@ search with flags or a more specific directory if results are truncated.`,
108733
108903
  });
108734
108904
  let stdout = "";
108735
108905
  let stderr = "";
108906
+ let resolved = false;
108907
+ let abortCleanup;
108908
+ if (ctx4.abortSignal) {
108909
+ const abortHandler = () => child.kill("SIGTERM");
108910
+ ctx4.abortSignal.addEventListener("abort", abortHandler, {
108911
+ once: true
108912
+ });
108913
+ abortCleanup = () => ctx4.abortSignal.removeEventListener("abort", abortHandler);
108914
+ }
108915
+ const safeResolve = (result) => {
108916
+ if (resolved)
108917
+ return;
108918
+ resolved = true;
108919
+ clearTimeout(timeout);
108920
+ abortCleanup?.();
108921
+ resolve4(result);
108922
+ };
108736
108923
  const timeout = setTimeout(() => {
108737
108924
  child.kill("SIGTERM");
108738
108925
  }, 30000);
@@ -108743,7 +108930,6 @@ search with flags or a more specific directory if results are truncated.`,
108743
108930
  stderr += data.toString();
108744
108931
  });
108745
108932
  child.on("close", (code) => {
108746
- clearTimeout(timeout);
108747
108933
  const noMatch = code === 1 && stderr === "";
108748
108934
  const matchCount = stdout ? stdout.trimEnd().split(`
108749
108935
  `).length : 0;
@@ -108751,7 +108937,7 @@ search with flags or a more specific directory if results are truncated.`,
108751
108937
  const output = truncated ? `${stdout.substring(0, 50000)}
108752
108938
 
108753
108939
  (truncated — narrow your search)` : stdout || "(no matches)";
108754
- resolve4({
108940
+ safeResolve({
108755
108941
  success: code === 0 || noMatch,
108756
108942
  error: noMatch || code === 0 ? "" : stderr || `Exit code: ${code}`,
108757
108943
  output,
@@ -108760,8 +108946,7 @@ search with flags or a more specific directory if results are truncated.`,
108760
108946
  });
108761
108947
  });
108762
108948
  child.on("error", (err) => {
108763
- clearTimeout(timeout);
108764
- resolve4({
108949
+ safeResolve({
108765
108950
  success: false,
108766
108951
  error: err.message,
108767
108952
  output: "",
@@ -108769,15 +108954,6 @@ search with flags or a more specific directory if results are truncated.`,
108769
108954
  command
108770
108955
  });
108771
108956
  });
108772
- if (ctx4.abortSignal) {
108773
- const abortHandler = () => child.kill("SIGTERM");
108774
- ctx4.abortSignal.addEventListener("abort", abortHandler, {
108775
- once: true
108776
- });
108777
- child.on("close", () => {
108778
- ctx4.abortSignal.removeEventListener("abort", abortHandler);
108779
- });
108780
- }
108781
108957
  });
108782
108958
  }
108783
108959
  });
@@ -110904,7 +111080,7 @@ For each app you identified, spawn a coding agent with a detailed objective. The
110904
111080
 
110905
111081
  // src/core/agents/specialized/whiteboxAttackSurface/types.ts
110906
111082
  var RiskScoreBreakdownSchema, RiskScoreSchema, EndpointSchema, AppSchema, WhiteboxAttackSurfaceResultSchema;
110907
- var init_types5 = __esm(() => {
111083
+ var init_types6 = __esm(() => {
110908
111084
  init_zod();
110909
111085
  RiskScoreBreakdownSchema = exports_external.object({
110910
111086
  exposure: exports_external.number().min(0).max(3).describe("Exposure Level (0-3): 3=Public no auth, 2=Standard user login, 1=Privileged/admin access, 0=Private/internal-only"),
@@ -110978,7 +111154,7 @@ var init_agent2 = __esm(() => {
110978
111154
  init_dist5();
110979
111155
  init_dist5();
110980
111156
  init_offensiveSecurityAgent();
110981
- init_types5();
111157
+ init_types6();
110982
111158
  WhiteboxAttackSurfaceAgent = class WhiteboxAttackSurfaceAgent extends OffensiveSecurityAgent {
110983
111159
  constructor(opts) {
110984
111160
  const {
@@ -193873,7 +194049,7 @@ function createInitialOperatorState(initialMode = "manual", requireApproval = tr
193873
194049
  };
193874
194050
  }
193875
194051
  var OPERATOR_STAGES, OperatorSettingsObject2;
193876
- var init_types6 = __esm(() => {
194052
+ var init_types7 = __esm(() => {
193877
194053
  init_zod();
193878
194054
  OPERATOR_STAGES = {
193879
194055
  setup: {
@@ -194071,11 +194247,11 @@ var init_approvalGate = __esm(() => {
194071
194247
 
194072
194248
  // src/core/operator/stageManager.ts
194073
194249
  var init_stageManager = __esm(() => {
194074
- init_types6();
194250
+ init_types7();
194075
194251
  });
194076
194252
  // src/core/operator/index.ts
194077
194253
  var init_operator = __esm(() => {
194078
- init_types6();
194254
+ init_types7();
194079
194255
  init_toolClassifier();
194080
194256
  init_approvalGate();
194081
194257
  init_stageManager();
@@ -194125,6 +194301,7 @@ var init_offensiveSecurityAgent = __esm(() => {
194125
194301
  resolveResult;
194126
194302
  subagentId;
194127
194303
  persistentShell;
194304
+ abortSignal;
194128
194305
  _session;
194129
194306
  static async create(input) {
194130
194307
  let session = input.session;
@@ -194146,6 +194323,7 @@ var init_offensiveSecurityAgent = __esm(() => {
194146
194323
  constructor(input) {
194147
194324
  this._session = input.session;
194148
194325
  this.subagentId = input.subagentId;
194326
+ this.abortSignal = input.abortSignal;
194149
194327
  if (!input.sandbox) {
194150
194328
  this.persistentShell = new PersistentShell({
194151
194329
  cwd: input.session.rootPath
@@ -194309,6 +194487,9 @@ var init_offensiveSecurityAgent = __esm(() => {
194309
194487
  }
194310
194488
  }
194311
194489
  this.persistentShell?.dispose();
194490
+ if (this.abortSignal?.aborted) {
194491
+ throw new DOMException("Agent aborted by user", "AbortError");
194492
+ }
194312
194493
  if (this.resolveResult) {
194313
194494
  return this.resolveResult(this.streamResult);
194314
194495
  }
@@ -194392,7 +194573,7 @@ var BlackboxAttackSurfaceAgent;
194392
194573
  var init_blackboxAgent = __esm(() => {
194393
194574
  init_dist5();
194394
194575
  init_utils2();
194395
- init_types2();
194576
+ init_types3();
194396
194577
  init_offensiveSecurityAgent();
194397
194578
  BlackboxAttackSurfaceAgent = class BlackboxAttackSurfaceAgent extends OffensiveSecurityAgent {
194398
194579
  constructor(opts) {
@@ -194417,6 +194598,7 @@ var init_blackboxAgent = __esm(() => {
194417
194598
  onStepFinish,
194418
194599
  abortSignal,
194419
194600
  attackSurfaceRegistry,
194601
+ messages: opts.messages,
194420
194602
  activeTools: [
194421
194603
  "execute_command",
194422
194604
  "document_asset",
@@ -194692,7 +194874,8 @@ var init_agent4 = __esm(() => {
194692
194874
  onStepFinish,
194693
194875
  abortSignal,
194694
194876
  sandbox,
194695
- findingsRegistry
194877
+ findingsRegistry,
194878
+ messages
194696
194879
  } = opts;
194697
194880
  super({
194698
194881
  system: buildSystemPrompt(session),
@@ -194705,6 +194888,7 @@ var init_agent4 = __esm(() => {
194705
194888
  abortSignal,
194706
194889
  sandbox,
194707
194890
  findingsRegistry,
194891
+ messages,
194708
194892
  activeTools: [
194709
194893
  "execute_command",
194710
194894
  "http_request",
@@ -194814,7 +194998,7 @@ var EXECUTION_METRICS_FILENAME = "execution-metrics.json";
194814
194998
  var init_execution_metrics = () => {};
194815
194999
 
194816
195000
  // src/core/utils/concurrency.ts
194817
- async function runWithBoundedConcurrency(items, concurrency, fn) {
195001
+ async function runWithBoundedConcurrency(items, concurrency, fn, abortSignal) {
194818
195002
  const results = new Array(items.length).fill(null);
194819
195003
  let nextIdx = 0;
194820
195004
  let completed = 0;
@@ -194825,11 +195009,11 @@ async function runWithBoundedConcurrency(items, concurrency, fn) {
194825
195009
  }
194826
195010
  let active = 0;
194827
195011
  function next() {
194828
- if (completed === items.length) {
195012
+ if (completed >= nextIdx && (nextIdx === items.length || abortSignal?.aborted)) {
194829
195013
  resolve4();
194830
195014
  return;
194831
195015
  }
194832
- while (active < concurrency && nextIdx < items.length) {
195016
+ while (active < concurrency && nextIdx < items.length && !abortSignal?.aborted) {
194833
195017
  const idx = nextIdx++;
194834
195018
  active++;
194835
195019
  fn(items[idx], idx).then((r2) => {
@@ -195369,7 +195553,7 @@ When your objective includes structured output, call \`response\` with your fina
195369
195553
  var init_whiteboxAttackSurface = __esm(() => {
195370
195554
  init_zod();
195371
195555
  init_agent3();
195372
- init_types5();
195556
+ init_types6();
195373
195557
  init_riskScoring();
195374
195558
  AppInfoSchema = exports_external.object({
195375
195559
  name: exports_external.string().describe("Application or service name"),
@@ -195419,10 +195603,21 @@ async function runPentestSwarm(input) {
195419
195603
  concurrency = DEFAULT_CONCURRENCY4,
195420
195604
  onStepFinish
195421
195605
  } = input;
195422
- const manifestEntries = buildManifestEntries(targets);
195606
+ const completedIds = getCompletedAgentIds(session);
195607
+ const existingManifest = readAgentManifest(session);
195608
+ const freshEntries = buildManifestEntries(targets);
195609
+ const manifestEntries = freshEntries.map((fresh) => {
195610
+ const existing = existingManifest.find((e2) => e2.id === fresh.id);
195611
+ if (existing && existing.status === "completed")
195612
+ return existing;
195613
+ return fresh;
195614
+ });
195423
195615
  writeAgentManifest(session, manifestEntries);
195424
195616
  const results = await runWithBoundedConcurrency(targets, concurrency, async (target, index) => {
195425
195617
  const subagentId = `pentest-agent-${index + 1}`;
195618
+ if (completedIds.has(subagentId))
195619
+ return null;
195620
+ const previousMessages = loadSubagentMessages(session, subagentId);
195426
195621
  let lastMessages = [];
195427
195622
  const handleStepFinish = (e2) => {
195428
195623
  if (e2.response.messages) {
@@ -195456,7 +195651,8 @@ async function runPentestSwarm(input) {
195456
195651
  authConfig,
195457
195652
  abortSignal,
195458
195653
  findingsRegistry,
195459
- onStepFinish: handleStepFinish
195654
+ onStepFinish: handleStepFinish,
195655
+ messages: previousMessages.length > 0 ? previousMessages : undefined
195460
195656
  });
195461
195657
  const result = await agent.consume({
195462
195658
  onError: (e2) => onError?.(e2),
@@ -195468,8 +195664,9 @@ async function runPentestSwarm(input) {
195468
195664
  objective: target.objectives.join("; "),
195469
195665
  status: "completed",
195470
195666
  findingsCount: result.findings.length,
195471
- messages: lastMessages
195667
+ messages: [...previousMessages, ...lastMessages]
195472
195668
  });
195669
+ updateManifestEntryStatus(session, subagentId, "completed");
195473
195670
  subagentCallbacks?.onSubagentComplete?.({
195474
195671
  subagentId,
195475
195672
  input: { target: target.target, objectives: target.objectives },
@@ -195483,8 +195680,9 @@ async function runPentestSwarm(input) {
195483
195680
  objective: target.objectives.join("; "),
195484
195681
  status: "failed",
195485
195682
  error: error40 instanceof Error ? error40.message : String(error40),
195486
- messages: lastMessages
195683
+ messages: [...previousMessages, ...lastMessages]
195487
195684
  });
195685
+ updateManifestEntryStatus(session, subagentId, "failed");
195488
195686
  subagentCallbacks?.onSubagentComplete?.({
195489
195687
  subagentId,
195490
195688
  input: { target: target.target, objectives: target.objectives },
@@ -195492,7 +195690,7 @@ async function runPentestSwarm(input) {
195492
195690
  });
195493
195691
  throw error40;
195494
195692
  }
195495
- });
195693
+ }, abortSignal);
195496
195694
  finalizeManifest(session, manifestEntries, results);
195497
195695
  return results;
195498
195696
  }
@@ -195510,7 +195708,13 @@ async function runPentestWorkflow(input) {
195510
195708
  try {
195511
195709
  const mode = cwd ? "whitebox" : "blackbox";
195512
195710
  let swarmTargets;
195513
- if (mode === "whitebox") {
195711
+ const existingResults = loadAttackSurfaceResults(session.rootPath);
195712
+ if (existingResults?.targets && existingResults.targets.length > 0) {
195713
+ swarmTargets = existingResults.targets.map((t3) => ({
195714
+ target: t3.target,
195715
+ objectives: [t3.objective]
195716
+ }));
195717
+ } else if (mode === "whitebox") {
195514
195718
  swarmTargets = await runWhiteboxPhase({
195515
195719
  codebasePath: cwd,
195516
195720
  baseTarget: target,
@@ -195532,6 +195736,9 @@ async function runPentestWorkflow(input) {
195532
195736
  onStepFinish
195533
195737
  });
195534
195738
  }
195739
+ if (abortSignal?.aborted) {
195740
+ throw new DOMException("Pentest aborted by user", "AbortError");
195741
+ }
195535
195742
  if (swarmTargets.length === 0) {
195536
195743
  const report2 = buildPentestReport([], {
195537
195744
  target,
@@ -195555,17 +195762,23 @@ async function runPentestWorkflow(input) {
195555
195762
  authConfig,
195556
195763
  abortSignal
195557
195764
  });
195558
- await runPentestSwarm({
195559
- targets: swarmTargets,
195560
- model,
195561
- session,
195562
- authConfig,
195563
- abortSignal,
195564
- findingsRegistry,
195565
- subagentCallbacks: callbacks?.subagentCallbacks,
195566
- onError: (e2) => callbacks?.onError?.(e2),
195567
- onStepFinish
195568
- });
195765
+ const completedCount = getCompletedAgentIds(session).size;
195766
+ if (completedCount < swarmTargets.length) {
195767
+ await runPentestSwarm({
195768
+ targets: swarmTargets,
195769
+ model,
195770
+ session,
195771
+ authConfig,
195772
+ abortSignal,
195773
+ findingsRegistry,
195774
+ subagentCallbacks: callbacks?.subagentCallbacks,
195775
+ onError: (e2) => callbacks?.onError?.(e2),
195776
+ onStepFinish
195777
+ });
195778
+ }
195779
+ if (abortSignal?.aborted) {
195780
+ throw new DOMException("Pentest aborted by user", "AbortError");
195781
+ }
195569
195782
  const findings = loadFindings2(session.findingsPath);
195570
195783
  const report = buildPentestReport(findings, {
195571
195784
  target,
@@ -195677,6 +195890,7 @@ var init_pentest = __esm(() => {
195677
195890
  init_report();
195678
195891
  init_persistence();
195679
195892
  init_execution_metrics();
195893
+ init_loader();
195680
195894
  init_whiteboxAttackSurface();
195681
195895
  });
195682
195896
 
@@ -272284,7 +272498,7 @@ var useTerminalDimensions = () => {
272284
272498
  };
272285
272499
 
272286
272500
  // src/tui/index.tsx
272287
- var import_react89 = __toESM(require_react(), 1);
272501
+ var import_react87 = __toESM(require_react(), 1);
272288
272502
 
272289
272503
  // src/tui/components/footer.tsx
272290
272504
  import os6 from "os";
@@ -273755,7 +273969,7 @@ function CommandProvider({
273755
273969
  }
273756
273970
 
273757
273971
  // src/tui/components/commands/sessions-display.tsx
273758
- var import_react22 = __toESM(require_react(), 1);
273972
+ var import_react24 = __toESM(require_react(), 1);
273759
273973
 
273760
273974
  // src/tui/context/focus.tsx
273761
273975
  var import_react18 = __toESM(require_react(), 1);
@@ -273824,10 +274038,29 @@ function openSessionReport(sessionRootPath) {
273824
274038
  }
273825
274039
  }
273826
274040
 
274041
+ // src/tui/context/dimensions.tsx
274042
+ var import_react19 = __toESM(require_react(), 1);
274043
+ var DimensionsContext = import_react19.createContext(null);
274044
+ function TerminalDimensionsProvider({
274045
+ children
274046
+ }) {
274047
+ const dimensions = useTerminalDimensions();
274048
+ return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(DimensionsContext.Provider, {
274049
+ value: dimensions,
274050
+ children
274051
+ }, undefined, false, undefined, this);
274052
+ }
274053
+ function useDimensions() {
274054
+ const ctx3 = import_react19.useContext(DimensionsContext);
274055
+ if (!ctx3)
274056
+ throw new Error("useDimensions() must be used within <TerminalDimensionsProvider>");
274057
+ return ctx3;
274058
+ }
274059
+
273827
274060
  // src/tui/context/dialog.tsx
273828
- var import_react20 = __toESM(require_react(), 1);
274061
+ var import_react22 = __toESM(require_react(), 1);
273829
274062
  function Dialog({ size = "medium", onClose, children }) {
273830
- const dimensions = useTerminalDimensions();
274063
+ const dimensions = useDimensions();
273831
274064
  const renderer = useRenderer();
273832
274065
  const { colors: themeColors } = useTheme();
273833
274066
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
@@ -273862,14 +274095,14 @@ function Dialog({ size = "medium", onClose, children }) {
273862
274095
  }, undefined, false, undefined, this)
273863
274096
  }, undefined, false, undefined, this);
273864
274097
  }
273865
- var DialogContext = import_react20.createContext(null);
274098
+ var DialogContext = import_react22.createContext(null);
273866
274099
  function DialogProvider({ children }) {
273867
- const [stack, setStack] = import_react20.useState([]);
273868
- const [size, setSize] = import_react20.useState("medium");
273869
- const [externalDialogOpen, setExternalDialogOpen] = import_react20.useState(false);
274100
+ const [stack, setStack] = import_react22.useState([]);
274101
+ const [size, setSize] = import_react22.useState("medium");
274102
+ const [externalDialogOpen, setExternalDialogOpen] = import_react22.useState(false);
273870
274103
  const renderer = useRenderer();
273871
- const focusRef = import_react20.useRef(null);
273872
- const refocus = import_react20.useCallback(() => {
274104
+ const focusRef = import_react22.useRef(null);
274105
+ const refocus = import_react22.useCallback(() => {
273873
274106
  setTimeout(() => {
273874
274107
  const focus = focusRef.current;
273875
274108
  if (!focus)
@@ -273891,7 +274124,7 @@ function DialogProvider({ children }) {
273891
274124
  focus.focus();
273892
274125
  }, 1);
273893
274126
  }, [renderer]);
273894
- const clear = import_react20.useCallback(() => {
274127
+ const clear = import_react22.useCallback(() => {
273895
274128
  for (const item of stack) {
273896
274129
  if (item.onClose)
273897
274130
  item.onClose();
@@ -273900,7 +274133,7 @@ function DialogProvider({ children }) {
273900
274133
  setStack([]);
273901
274134
  refocus();
273902
274135
  }, [stack, refocus]);
273903
- const replace = import_react20.useCallback((element, onClose) => {
274136
+ const replace = import_react22.useCallback((element, onClose) => {
273904
274137
  if (stack.length === 0) {
273905
274138
  focusRef.current = renderer.currentFocusedRenderable;
273906
274139
  }
@@ -273945,7 +274178,7 @@ function DialogProvider({ children }) {
273945
274178
  }, undefined, true, undefined, this);
273946
274179
  }
273947
274180
  function useDialog() {
273948
- const value = import_react20.useContext(DialogContext);
274181
+ const value = import_react22.useContext(DialogContext);
273949
274182
  if (!value) {
273950
274183
  throw new Error("useDialog must be used within a DialogProvider");
273951
274184
  }
@@ -274010,7 +274243,7 @@ function findChildById(scrollBox, id) {
274010
274243
  // src/tui/hooks/use-sessions-list.ts
274011
274244
  init_session();
274012
274245
  init_report();
274013
- var import_react21 = __toESM(require_react(), 1);
274246
+ var import_react23 = __toESM(require_react(), 1);
274014
274247
  import { existsSync as existsSync7, readdirSync } from "fs";
274015
274248
  import { join as join3 } from "path";
274016
274249
  function countFindings(findingsPath) {
@@ -274026,10 +274259,10 @@ function checkHasReport(rootPath) {
274026
274259
  return existsSync7(join3(rootPath, REPORT_FILENAME_MD));
274027
274260
  }
274028
274261
  function useSessionsList() {
274029
- const [allSessions, setAllSessions] = import_react21.useState([]);
274030
- const [loading, setLoading] = import_react21.useState(true);
274031
- const [searchTerm, setSearchTerm] = import_react21.useState("");
274032
- const loadSessions = import_react21.useCallback(async () => {
274262
+ const [allSessions, setAllSessions] = import_react23.useState([]);
274263
+ const [loading, setLoading] = import_react23.useState(true);
274264
+ const [searchTerm, setSearchTerm] = import_react23.useState("");
274265
+ const loadSessions = import_react23.useCallback(async () => {
274033
274266
  setLoading(true);
274034
274267
  try {
274035
274268
  const enriched = [];
@@ -274052,10 +274285,10 @@ function useSessionsList() {
274052
274285
  setLoading(false);
274053
274286
  }
274054
274287
  }, []);
274055
- import_react21.useEffect(() => {
274288
+ import_react23.useEffect(() => {
274056
274289
  loadSessions();
274057
274290
  }, [loadSessions]);
274058
- const deleteSession = import_react21.useCallback(async (id) => {
274291
+ const deleteSession = import_react23.useCallback(async (id) => {
274059
274292
  await sessions.remove({ sessionId: id });
274060
274293
  await loadSessions();
274061
274294
  }, [loadSessions]);
@@ -274114,10 +274347,10 @@ function useSessionsList() {
274114
274347
  function SessionsDisplay({ onClose }) {
274115
274348
  const { colors: colors2 } = useTheme();
274116
274349
  const { refocusPrompt } = useFocus();
274117
- const [selectedIndex, setSelectedIndex] = import_react22.useState(0);
274118
- const [statusMessage, setStatusMessage] = import_react22.useState("");
274350
+ const [selectedIndex, setSelectedIndex] = import_react24.useState(0);
274351
+ const [statusMessage, setStatusMessage] = import_react24.useState("");
274119
274352
  const route = useRoute();
274120
- const scroll = import_react22.useRef(null);
274353
+ const scroll = import_react24.useRef(null);
274121
274354
  const {
274122
274355
  groupedSessions,
274123
274356
  visualOrderSessions,
@@ -274133,7 +274366,7 @@ function SessionsDisplay({ onClose }) {
274133
274366
  setTimeout(() => setStatusMessage(""), 2000);
274134
274367
  }
274135
274368
  }
274136
- import_react22.useEffect(() => {
274369
+ import_react24.useEffect(() => {
274137
274370
  if (visualOrderSessions.length > 0 && selectedIndex >= visualOrderSessions.length) {
274138
274371
  setSelectedIndex(visualOrderSessions.length - 1);
274139
274372
  } else if (visualOrderSessions.length === 0) {
@@ -274169,7 +274402,7 @@ function SessionsDisplay({ onClose }) {
274169
274402
  setTimeout(() => setStatusMessage(""), 2000);
274170
274403
  return;
274171
274404
  }
274172
- const isOperator = currentSelection.config?.mode === "operator" || currentSelection.hasOperatorState;
274405
+ const isOperator = currentSelection.config?.mode === "operator" || !currentSelection.config?.mode && currentSelection.hasOperatorState;
274173
274406
  refocusPrompt();
274174
274407
  onClose();
274175
274408
  route.navigate({
@@ -274215,6 +274448,11 @@ function SessionsDisplay({ onClose }) {
274215
274448
  const currentSelection = visualOrderSessions[selectedIndex];
274216
274449
  if (!currentSelection)
274217
274450
  return;
274451
+ if (!currentSelection.hasReport) {
274452
+ setStatusMessage("No report available");
274453
+ setTimeout(() => setStatusMessage(""), 2000);
274454
+ return;
274455
+ }
274218
274456
  openReport(currentSelection.id);
274219
274457
  return;
274220
274458
  }
@@ -274318,6 +274556,7 @@ function SessionsDisplay({ onClose }) {
274318
274556
  });
274319
274557
  const mode = session.config?.mode || "auto";
274320
274558
  const modeBadge = mode === "operator" ? "[operator]" : "[auto]";
274559
+ const statusBadge = session.hasReport ? "✓" : "…";
274321
274560
  const findingsText = session.findingsCount > 0 ? `${session.findingsCount} finding${session.findingsCount > 1 ? "s" : ""}` : "";
274322
274561
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
274323
274562
  id: session.id,
@@ -274342,6 +274581,10 @@ function SessionsDisplay({ onClose }) {
274342
274581
  fg: isSelected ? colors2.text : colors2.textMuted,
274343
274582
  children: session.name
274344
274583
  }, undefined, false, undefined, this),
274584
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
274585
+ fg: session.hasReport ? colors2.primary : colors2.textMuted,
274586
+ children: statusBadge
274587
+ }, undefined, false, undefined, this),
274345
274588
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
274346
274589
  fg: mode === "operator" ? colors2.primary : colors2.textMuted,
274347
274590
  children: modeBadge
@@ -274405,7 +274648,7 @@ function SessionsDisplay({ onClose }) {
274405
274648
  }
274406
274649
 
274407
274650
  // src/tui/components/commands/config-dialog.tsx
274408
- var import_react25 = __toESM(require_react(), 1);
274651
+ var import_react27 = __toESM(require_react(), 1);
274409
274652
 
274410
274653
  // src/tui/components/alert-dialog.tsx
274411
274654
  function AlertDialog({
@@ -274418,7 +274661,7 @@ function AlertDialog({
274418
274661
  size = "medium"
274419
274662
  }) {
274420
274663
  const { colors: colors2 } = useTheme();
274421
- const dimensions = useTerminalDimensions();
274664
+ const dimensions = useDimensions();
274422
274665
  const renderer = useRenderer();
274423
274666
  useKeyboard((key) => {
274424
274667
  if (!open)
@@ -274492,8 +274735,8 @@ function AlertDialog({
274492
274735
  init_config2();
274493
274736
  function ConfigDialog() {
274494
274737
  const route = useRoute();
274495
- const [open, setOpen] = import_react25.useState(false);
274496
- import_react25.useEffect(() => {
274738
+ const [open, setOpen] = import_react27.useState(false);
274739
+ import_react27.useEffect(() => {
274497
274740
  if (route.data.type === "base" && route.data.path === "config") {
274498
274741
  setOpen(true);
274499
274742
  } else {
@@ -274507,8 +274750,8 @@ function ConfigDialog() {
274507
274750
  path: "home"
274508
274751
  });
274509
274752
  };
274510
- const [appConfig, setAppConfig] = import_react25.useState(null);
274511
- import_react25.useEffect(() => {
274753
+ const [appConfig, setAppConfig] = import_react27.useState(null);
274754
+ import_react27.useEffect(() => {
274512
274755
  async function getConfig() {
274513
274756
  const _appConfig = await config2.get();
274514
274757
  setAppConfig(_appConfig);
@@ -274583,11 +274826,11 @@ var import_react38 = __toESM(require_react(), 1);
274583
274826
 
274584
274827
  // src/tui/context/config.tsx
274585
274828
  init_config2();
274586
- var import_react26 = __toESM(require_react(), 1);
274587
- var ctx3 = import_react26.createContext(null);
274829
+ var import_react28 = __toESM(require_react(), 1);
274830
+ var ctx3 = import_react28.createContext(null);
274588
274831
  function ConfigProvider({ children, config: config3 }) {
274589
- const [appConfig, setAppConfig] = import_react26.useState(config3);
274590
- const value = import_react26.useMemo(() => ({
274832
+ const [appConfig, setAppConfig] = import_react28.useState(config3);
274833
+ const value = import_react28.useMemo(() => ({
274591
274834
  data: appConfig,
274592
274835
  update: async (newConfig) => {
274593
274836
  await config2.update(newConfig);
@@ -274607,7 +274850,7 @@ function ConfigProvider({ children, config: config3 }) {
274607
274850
  }, undefined, false, undefined, this);
274608
274851
  }
274609
274852
  var useConfig = () => {
274610
- const config3 = import_react26.useContext(ctx3);
274853
+ const config3 = import_react28.useContext(ctx3);
274611
274854
  if (!config3) {
274612
274855
  throw new Error("useConfig must be called within a ConfigProvider");
274613
274856
  }
@@ -274615,10 +274858,10 @@ var useConfig = () => {
274615
274858
  };
274616
274859
 
274617
274860
  // src/tui/components/chat/home-view.tsx
274618
- var import_react32 = __toESM(require_react(), 1);
274861
+ var import_react33 = __toESM(require_react(), 1);
274619
274862
 
274620
274863
  // src/tui/components/chat/petri-animation.tsx
274621
- var import_react27 = __toESM(require_react(), 1);
274864
+ var import_react29 = __toESM(require_react(), 1);
274622
274865
 
274623
274866
  // src/tui/components/chat/lib/play-core/num.ts
274624
274867
  function clamp(x2, min, max) {
@@ -274714,8 +274957,8 @@ function stopGlobalTick2() {
274714
274957
  }
274715
274958
  }
274716
274959
  function useGlobalTick2() {
274717
- const [, setTick] = import_react27.useState(0);
274718
- import_react27.useEffect(() => {
274960
+ const [, setTick] = import_react29.useState(0);
274961
+ import_react29.useEffect(() => {
274719
274962
  const listener = () => setTick((t2) => t2 + 1);
274720
274963
  globalListeners2.add(listener);
274721
274964
  startGlobalTick2();
@@ -274740,19 +274983,19 @@ function PetriAnimation({
274740
274983
  height = 0.4,
274741
274984
  width = "100%"
274742
274985
  }) {
274743
- const dimensions = useTerminalDimensions();
274986
+ const dimensions = useDimensions();
274744
274987
  const tick = useGlobalTick2();
274745
274988
  const { colors: colors2 } = useTheme();
274746
- const simulationRef = import_react27.useRef(null);
274747
- const [frame, setFrame] = import_react27.useState([]);
274748
- const gradientColors = import_react27.useMemo(() => generateGradient(colors2.primary, 9), [colors2.primary]);
274749
- const actualHeight = import_react27.useMemo(() => {
274989
+ const simulationRef = import_react29.useRef(null);
274990
+ const [frame, setFrame] = import_react29.useState([]);
274991
+ const gradientColors = import_react29.useMemo(() => generateGradient(colors2.primary, 9), [colors2.primary]);
274992
+ const actualHeight = import_react29.useMemo(() => {
274750
274993
  if (typeof height === "number" && height <= 1) {
274751
274994
  return Math.floor(dimensions.height * height);
274752
274995
  }
274753
274996
  return typeof height === "number" ? height : Math.floor(dimensions.height * 0.4);
274754
274997
  }, [height, dimensions.height]);
274755
- const actualWidth = import_react27.useMemo(() => {
274998
+ const actualWidth = import_react29.useMemo(() => {
274756
274999
  if (typeof width === "number" && width <= 1) {
274757
275000
  return Math.floor(dimensions.width * width);
274758
275001
  }
@@ -274761,7 +275004,7 @@ function PetriAnimation({
274761
275004
  }
274762
275005
  return typeof width === "number" ? width : dimensions.width;
274763
275006
  }, [width, dimensions.width]);
274764
- import_react27.useEffect(() => {
275007
+ import_react29.useEffect(() => {
274765
275008
  if (actualWidth <= 0 || actualHeight <= 0)
274766
275009
  return;
274767
275010
  if (!simulationRef.current) {
@@ -274770,7 +275013,7 @@ function PetriAnimation({
274770
275013
  simulationRef.current.resize(actualWidth, actualHeight);
274771
275014
  }
274772
275015
  }, [actualWidth, actualHeight]);
274773
- import_react27.useEffect(() => {
275016
+ import_react29.useEffect(() => {
274774
275017
  if (simulationRef.current) {
274775
275018
  simulationRef.current.step();
274776
275019
  setFrame(simulationRef.current.render());
@@ -274796,7 +275039,7 @@ function getRowColor(rowIdx, totalRows, gradient) {
274796
275039
  }
274797
275040
 
274798
275041
  // src/tui/components/shared/prompt-input.tsx
274799
- var import_react30 = __toESM(require_react(), 1);
275042
+ var import_react31 = __toESM(require_react(), 1);
274800
275043
 
274801
275044
  // src/tui/components/shared/prompt-input-logic.ts
274802
275045
  function filterSuggestions(inputValue, options, maxSuggestions) {
@@ -274917,13 +275160,13 @@ function shouldResetHistory(historyIndex, isNavigatingHistory) {
274917
275160
  }
274918
275161
 
274919
275162
  // src/tui/components/shared/use-paste-extmarks.ts
274920
- var import_react29 = __toESM(require_react(), 1);
275163
+ var import_react30 = __toESM(require_react(), 1);
274921
275164
  var LARGE_PASTE_MIN_LINES = 5;
274922
275165
  var LARGE_PASTE_MIN_CHARS = 500;
274923
275166
  function usePasteExtmarks(textareaRef) {
274924
- const countRef = import_react29.useRef(0);
274925
- const typeIdRef = import_react29.useRef(-1);
274926
- const dataRef = import_react29.useRef(new Map);
275167
+ const countRef = import_react30.useRef(0);
275168
+ const typeIdRef = import_react30.useRef(-1);
275169
+ const dataRef = import_react30.useRef(new Map);
274927
275170
  const clearPaste = () => {
274928
275171
  textareaRef.current?.extmarks.clear();
274929
275172
  countRef.current = 0;
@@ -274993,7 +275236,7 @@ var chatKeyBindings = [
274993
275236
  { name: "return", shift: true, action: "newline" },
274994
275237
  { name: "linefeed", shift: true, action: "newline" }
274995
275238
  ];
274996
- var PromptInput = import_react30.forwardRef(function PromptInput2({
275239
+ var PromptInput = import_react31.forwardRef(function PromptInput2({
274997
275240
  width,
274998
275241
  minHeight = 1,
274999
275242
  maxHeight = 6,
@@ -275018,31 +275261,31 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
275018
275261
  const { colors: colors2 } = useTheme();
275019
275262
  const { inputValue, setInputValue } = useInput();
275020
275263
  const { registerPromptRef } = useFocus();
275021
- const textareaRef = import_react30.useRef(null);
275022
- const [selectedSuggestionIndex, setSelectedSuggestionIndex] = import_react30.useState(-1);
275023
- const [historyIndex, setHistoryIndex] = import_react30.useState(-1);
275024
- const savedInputRef = import_react30.useRef("");
275025
- const historyRef = import_react30.useRef(commandHistory);
275264
+ const textareaRef = import_react31.useRef(null);
275265
+ const [selectedSuggestionIndex, setSelectedSuggestionIndex] = import_react31.useState(-1);
275266
+ const [historyIndex, setHistoryIndex] = import_react31.useState(-1);
275267
+ const savedInputRef = import_react31.useRef("");
275268
+ const historyRef = import_react31.useRef(commandHistory);
275026
275269
  historyRef.current = commandHistory;
275027
- const isNavigatingHistoryRef = import_react30.useRef(false);
275028
- const selectedIndexRef = import_react30.useRef(selectedSuggestionIndex);
275029
- const suggestionsRef = import_react30.useRef([]);
275030
- const onCommandExecuteRef = import_react30.useRef(onCommandExecute);
275270
+ const isNavigatingHistoryRef = import_react31.useRef(false);
275271
+ const selectedIndexRef = import_react31.useRef(selectedSuggestionIndex);
275272
+ const suggestionsRef = import_react31.useRef([]);
275273
+ const onCommandExecuteRef = import_react31.useRef(onCommandExecute);
275031
275274
  onCommandExecuteRef.current = onCommandExecute;
275032
- const onSubmitRef = import_react30.useRef(onSubmit);
275275
+ const onSubmitRef = import_react31.useRef(onSubmit);
275033
275276
  onSubmitRef.current = onSubmit;
275034
275277
  const { handlePaste, resolveText, clearPaste } = usePasteExtmarks(textareaRef);
275035
- const suggestions = import_react30.useMemo(() => enableAutocomplete ? filterSuggestions(inputValue, autocompleteOptions, maxSuggestions) : [], [enableAutocomplete, autocompleteOptions, inputValue, maxSuggestions]);
275036
- import_react30.useEffect(() => {
275278
+ const suggestions = import_react31.useMemo(() => enableAutocomplete ? filterSuggestions(inputValue, autocompleteOptions, maxSuggestions) : [], [enableAutocomplete, autocompleteOptions, inputValue, maxSuggestions]);
275279
+ import_react31.useEffect(() => {
275037
275280
  suggestionsRef.current = suggestions;
275038
275281
  }, [suggestions]);
275039
- import_react30.useEffect(() => {
275282
+ import_react31.useEffect(() => {
275040
275283
  selectedIndexRef.current = selectedSuggestionIndex;
275041
275284
  }, [selectedSuggestionIndex]);
275042
- import_react30.useEffect(() => {
275285
+ import_react31.useEffect(() => {
275043
275286
  setSelectedSuggestionIndex(suggestions.length > 0 ? 0 : -1);
275044
275287
  }, [suggestions.length]);
275045
- const imperativeRef = import_react30.useRef({
275288
+ const imperativeRef = import_react31.useRef({
275046
275289
  focus: () => textareaRef.current?.focus(),
275047
275290
  blur: () => textareaRef.current?.blur(),
275048
275291
  reset: () => {
@@ -275059,11 +275302,11 @@ var PromptInput = import_react30.forwardRef(function PromptInput2({
275059
275302
  getValue: () => inputValue,
275060
275303
  getTextareaRef: () => textareaRef.current
275061
275304
  });
275062
- import_react30.useEffect(() => {
275305
+ import_react31.useEffect(() => {
275063
275306
  imperativeRef.current.getValue = () => inputValue;
275064
275307
  }, [inputValue]);
275065
- import_react30.useImperativeHandle(ref, () => imperativeRef.current, []);
275066
- import_react30.useEffect(() => {
275308
+ import_react31.useImperativeHandle(ref, () => imperativeRef.current, []);
275309
+ import_react31.useEffect(() => {
275067
275310
  registerPromptRef(imperativeRef.current);
275068
275311
  return () => registerPromptRef(null);
275069
275312
  }, [registerPromptRef]);
@@ -275279,41 +275522,41 @@ function getEntries() {
275279
275522
  // src/tui/components/chat/home-view.tsx
275280
275523
  function HomeView({ onNavigate, onStartSession }) {
275281
275524
  const { colors: colors2 } = useTheme();
275282
- const dimensions = useTerminalDimensions();
275525
+ const dimensions = useDimensions();
275283
275526
  const config3 = useConfig();
275284
275527
  const route = useRoute();
275285
275528
  const { executeCommand, autocompleteOptions, resolveSkillContent, skills } = useCommand();
275286
275529
  const { setInputValue } = useInput();
275287
275530
  const { promptRef } = useFocus();
275288
275531
  const { externalDialogOpen, stack } = useDialog();
275289
- const [hintMessage, setHintMessage] = import_react32.useState(null);
275290
- const [commandHistory, setCommandHistory] = import_react32.useState(getEntries);
275291
- import_react32.useEffect(() => {
275532
+ const [hintMessage, setHintMessage] = import_react33.useState(null);
275533
+ const [commandHistory, setCommandHistory] = import_react33.useState(getEntries);
275534
+ import_react33.useEffect(() => {
275292
275535
  load().then(setCommandHistory);
275293
275536
  }, []);
275294
- const launchOperator = import_react32.useCallback((message, options) => {
275537
+ const launchOperator = import_react33.useCallback((message, options) => {
275295
275538
  route.navigate({
275296
275539
  type: "operator",
275297
275540
  initialMessage: message,
275298
275541
  initialConfig: { requireApproval: options?.requireApproval ?? true }
275299
275542
  });
275300
275543
  }, [route]);
275301
- const pushHistory = import_react32.useCallback((entry) => {
275544
+ const pushHistory = import_react33.useCallback((entry) => {
275302
275545
  push(entry).then(() => setCommandHistory([...getEntries()]));
275303
275546
  }, []);
275304
- const handleSubmit = import_react32.useCallback((value) => {
275547
+ const handleSubmit = import_react33.useCallback((value) => {
275305
275548
  if (!value.trim())
275306
275549
  return;
275307
275550
  pushHistory(value.trim());
275308
275551
  launchOperator(value.trim());
275309
275552
  }, [launchOperator, pushHistory]);
275310
- import_react32.useEffect(() => {
275553
+ import_react33.useEffect(() => {
275311
275554
  if (!hintMessage)
275312
275555
  return;
275313
275556
  const timer = setTimeout(() => setHintMessage(null), 3000);
275314
275557
  return () => clearTimeout(timer);
275315
275558
  }, [hintMessage]);
275316
- const handleCommandExecute = import_react32.useCallback(async (command) => {
275559
+ const handleCommandExecute = import_react33.useCallback(async (command) => {
275317
275560
  const trimmed = command.trim();
275318
275561
  pushHistory(trimmed);
275319
275562
  const parts = trimmed.replace(/^\/+/, "").split(/\s+/);
@@ -278177,7 +278420,7 @@ function ToastItem({
278177
278420
  }
278178
278421
  function ToastContainer() {
278179
278422
  const { toasts, dismiss } = useToast();
278180
- const dims = useTerminalDimensions();
278423
+ const dims = useDimensions();
278181
278424
  if (toasts.length === 0)
278182
278425
  return null;
278183
278426
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
@@ -278198,11 +278441,11 @@ function ToastContainer() {
278198
278441
  }
278199
278442
 
278200
278443
  // src/tui/components/error-boundary.tsx
278201
- var import_react53 = __toESM(require_react(), 1);
278444
+ var import_react52 = __toESM(require_react(), 1);
278202
278445
  var MAX_ERRORS = 3;
278203
278446
  var ERROR_WINDOW_MS = 5000;
278204
278447
 
278205
- class ErrorBoundaryInner extends import_react53.default.Component {
278448
+ class ErrorBoundaryInner extends import_react52.default.Component {
278206
278449
  state = {
278207
278450
  hasError: false,
278208
278451
  errorTimestamps: [],
@@ -278233,10 +278476,10 @@ class ErrorBoundaryInner extends import_react53.default.Component {
278233
278476
  }
278234
278477
  function ErrorBoundary2({ children }) {
278235
278478
  const { toast } = useToast();
278236
- const handleError = import_react53.useCallback((message) => {
278479
+ const handleError = import_react52.useCallback((message) => {
278237
278480
  toast(message, "error");
278238
278481
  }, [toast]);
278239
- return import_react53.default.createElement(ErrorBoundaryInner, { onError: handleError }, children);
278482
+ return import_react52.default.createElement(ErrorBoundaryInner, { onError: handleError }, children);
278240
278483
  }
278241
278484
 
278242
278485
  // src/tui/index.tsx
@@ -278347,16 +278590,16 @@ function ShortcutsDialog({
278347
278590
  }
278348
278591
 
278349
278592
  // src/tui/components/commands/help-dialog.tsx
278350
- var import_react55 = __toESM(require_react(), 1);
278593
+ var import_react54 = __toESM(require_react(), 1);
278351
278594
  function HelpDialog() {
278352
278595
  const { colors: colors2 } = useTheme();
278353
278596
  const { commands: commands2 } = useCommand();
278354
278597
  const route = useRoute();
278355
- const dimensions = useTerminalDimensions();
278356
- const [selectedIndex, setSelectedIndex] = import_react55.useState(0);
278357
- const [showDetail, setShowDetail] = import_react55.useState(false);
278358
- const scrollboxRef = import_react55.useRef(null);
278359
- const commandsByCategory = import_react55.useMemo(() => {
278598
+ const dimensions = useDimensions();
278599
+ const [selectedIndex, setSelectedIndex] = import_react54.useState(0);
278600
+ const [showDetail, setShowDetail] = import_react54.useState(false);
278601
+ const scrollboxRef = import_react54.useRef(null);
278602
+ const commandsByCategory = import_react54.useMemo(() => {
278360
278603
  const grouped = {};
278361
278604
  for (const cmd of commands2) {
278362
278605
  const category = cmd.category || "Other";
@@ -278367,15 +278610,15 @@ function HelpDialog() {
278367
278610
  }
278368
278611
  return grouped;
278369
278612
  }, [commands2]);
278370
- const flatCommands = import_react55.useMemo(() => {
278613
+ const flatCommands = import_react54.useMemo(() => {
278371
278614
  return commands2;
278372
278615
  }, [commands2]);
278373
- import_react55.useEffect(() => {
278616
+ import_react54.useEffect(() => {
278374
278617
  if (selectedIndex >= flatCommands.length) {
278375
278618
  setSelectedIndex(Math.max(0, flatCommands.length - 1));
278376
278619
  }
278377
278620
  }, [flatCommands.length, selectedIndex]);
278378
- import_react55.useEffect(() => {
278621
+ import_react54.useEffect(() => {
278379
278622
  scrollToIndex(scrollboxRef.current, selectedIndex, flatCommands, (cmd) => cmd.name);
278380
278623
  }, [selectedIndex, flatCommands]);
278381
278624
  const handleClose = () => {
@@ -278810,24 +279053,24 @@ function ModelsDisplay() {
278810
279053
  }
278811
279054
 
278812
279055
  // src/tui/components/commands/auth-flow.tsx
278813
- var import_react58 = __toESM(require_react(), 1);
279056
+ var import_react57 = __toESM(require_react(), 1);
278814
279057
  init_config2();
278815
279058
  function AuthFlow({ onClose }) {
278816
279059
  const { colors: colors2 } = useTheme();
278817
279060
  const appConfig = useConfig();
278818
279061
  const isConnected = !!(appConfig.data.accessToken || appConfig.data.pensarAPIKey);
278819
- const [step, setStep] = import_react58.useState(isConnected ? "success" : "start");
278820
- const [error40, setError] = import_react58.useState(null);
278821
- const [authMode, setAuthMode] = import_react58.useState(null);
278822
- const [deviceInfo, setDeviceInfo] = import_react58.useState(null);
278823
- const [legacyDeviceInfo, setLegacyDeviceInfo] = import_react58.useState(null);
278824
- const [workspaces, setWorkspaces] = import_react58.useState([]);
278825
- const [selectedWorkspace, setSelectedWorkspace] = import_react58.useState(null);
278826
- const [selectedIndex, setSelectedIndex] = import_react58.useState(0);
278827
- const [billingUrl, setBillingUrl] = import_react58.useState(null);
278828
- const [balance, setBalance] = import_react58.useState(null);
278829
- const pollingRef = import_react58.useRef(null);
278830
- const cancelledRef = import_react58.useRef(false);
279062
+ const [step, setStep] = import_react57.useState(isConnected ? "success" : "start");
279063
+ const [error40, setError] = import_react57.useState(null);
279064
+ const [authMode, setAuthMode] = import_react57.useState(null);
279065
+ const [deviceInfo, setDeviceInfo] = import_react57.useState(null);
279066
+ const [legacyDeviceInfo, setLegacyDeviceInfo] = import_react57.useState(null);
279067
+ const [workspaces, setWorkspaces] = import_react57.useState([]);
279068
+ const [selectedWorkspace, setSelectedWorkspace] = import_react57.useState(null);
279069
+ const [selectedIndex, setSelectedIndex] = import_react57.useState(0);
279070
+ const [billingUrl, setBillingUrl] = import_react57.useState(null);
279071
+ const [balance, setBalance] = import_react57.useState(null);
279072
+ const pollingRef = import_react57.useRef(null);
279073
+ const cancelledRef = import_react57.useRef(false);
278831
279074
  const connectedWorkspace = appConfig.data.workspaceSlug ? { name: appConfig.data.workspaceSlug, slug: appConfig.data.workspaceSlug } : null;
278832
279075
  const goHome = () => {
278833
279076
  onClose();
@@ -278839,7 +279082,7 @@ function AuthFlow({ onClose }) {
278839
279082
  pollingRef.current = null;
278840
279083
  }
278841
279084
  };
278842
- import_react58.useEffect(() => {
279085
+ import_react57.useEffect(() => {
278843
279086
  return cleanup;
278844
279087
  }, []);
278845
279088
  const openUrl = (url2) => {
@@ -279472,14 +279715,14 @@ function AuthFlow({ onClose }) {
279472
279715
  }
279473
279716
 
279474
279717
  // src/tui/components/commands/credits-flow.tsx
279475
- var import_react60 = __toESM(require_react(), 1);
279718
+ var import_react59 = __toESM(require_react(), 1);
279476
279719
  init_tokenRefresh();
279477
279720
  function CreditsFlow({ onOpenAuthDialog }) {
279478
279721
  const route = useRoute();
279479
279722
  const appConfig = useConfig();
279480
- const [step, setStep] = import_react60.useState("loading");
279481
- const [credits, setCredits] = import_react60.useState(null);
279482
- const [error40, setError] = import_react60.useState(null);
279723
+ const [step, setStep] = import_react59.useState("loading");
279724
+ const [credits, setCredits] = import_react59.useState(null);
279725
+ const [error40, setError] = import_react59.useState(null);
279483
279726
  const creditsUrl = `${getPensarConsoleUrl()}/credits`;
279484
279727
  const goHome = () => {
279485
279728
  route.navigate({ type: "base", path: "home" });
@@ -279537,7 +279780,7 @@ function CreditsFlow({ onOpenAuthDialog }) {
279537
279780
  setStep("display");
279538
279781
  }
279539
279782
  };
279540
- import_react60.useEffect(() => {
279783
+ import_react59.useEffect(() => {
279541
279784
  fetchBalance();
279542
279785
  }, []);
279543
279786
  useKeyboard((key) => {
@@ -279776,10 +280019,10 @@ function CreditsFlow({ onOpenAuthDialog }) {
279776
280019
  }
279777
280020
 
279778
280021
  // src/tui/context/keybinding.tsx
279779
- var import_react66 = __toESM(require_react(), 1);
280022
+ var import_react65 = __toESM(require_react(), 1);
279780
280023
 
279781
280024
  // src/tui/keybindings/keybind.tsx
279782
- var import_react62 = __toESM(require_react(), 1);
280025
+ var import_react61 = __toESM(require_react(), 1);
279783
280026
 
279784
280027
  // src/tui/keybindings/actions.ts
279785
280028
  var movementActions = [
@@ -280031,7 +280274,7 @@ var allActions = [
280031
280274
  var actionsByKey = new Map(allActions.map((action) => [action.key, action]));
280032
280275
  var actionsById = new Map(allActions.map((action) => [action.id, action]));
280033
280276
  // src/tui/keybindings/keybind.tsx
280034
- var LeaderKeyContext = import_react62.createContext(null);
280277
+ var LeaderKeyContext = import_react61.createContext(null);
280035
280278
  // src/tui/keybindings/registry.ts
280036
280279
  function createKeybindings(deps) {
280037
280280
  const {
@@ -280212,7 +280455,7 @@ function matchesKeybind(pressed, combo) {
280212
280455
  }
280213
280456
 
280214
280457
  // src/tui/context/keybinding.tsx
280215
- var KeybindingContext = import_react66.createContext(undefined);
280458
+ var KeybindingContext = import_react65.createContext(undefined);
280216
280459
  function KeybindingProvider({
280217
280460
  children,
280218
280461
  deps
@@ -280252,121 +280495,12 @@ function KeybindingProvider({
280252
280495
  }
280253
280496
 
280254
280497
  // src/tui/components/pentest/pentest.tsx
280255
- var import_react75 = __toESM(require_react(), 1);
280498
+ var import_react73 = __toESM(require_react(), 1);
280256
280499
  init_report();
280257
280500
  import { existsSync as existsSync26, readdirSync as readdirSync6, readFileSync as readFileSync12 } from "fs";
280258
280501
  import { join as join27 } from "path";
280259
280502
  init_session();
280260
-
280261
- // src/core/session/loader.ts
280262
- init_persistence();
280263
- init_report();
280264
- import { join as join5 } from "path";
280265
- import { existsSync as existsSync9, readFileSync as readFileSync4 } from "fs";
280266
- function loadAttackSurfaceResults(rootPath) {
280267
- const resultsPath = join5(rootPath, "attack-surface-results.json");
280268
- if (!existsSync9(resultsPath)) {
280269
- return null;
280270
- }
280271
- try {
280272
- return JSON.parse(readFileSync4(resultsPath, "utf-8"));
280273
- } catch (e) {
280274
- console.error("Failed to load attack surface results:", e);
280275
- return null;
280276
- }
280277
- }
280278
- function hasReport(rootPath) {
280279
- const reportPath = join5(rootPath, REPORT_FILENAME_MD);
280280
- return existsSync9(reportPath);
280281
- }
280282
- function createDiscoveryFromLogs(rootPath, session) {
280283
- const logPath = join5(rootPath, "logs", "streamlined-pentest.log");
280284
- if (!existsSync9(logPath)) {
280285
- return null;
280286
- }
280287
- try {
280288
- const logContent = readFileSync4(logPath, "utf-8");
280289
- const lines = logContent.split(`
280290
- `).filter(Boolean);
280291
- const messages = [];
280292
- for (const line of lines) {
280293
- const match = line.match(/^(\d{4}-\d{2}-\d{2}T[\d:.]+Z) - \[(\w+)\] (.+)$/);
280294
- if (!match)
280295
- continue;
280296
- const [, timestamp, _level, content] = match;
280297
- const createdAt = new Date(timestamp);
280298
- if (content.startsWith("[Tool]")) {
280299
- const toolMatch = content.match(/\[Tool\] (\w+): (.+)/);
280300
- if (toolMatch) {
280301
- messages.push({
280302
- role: "tool",
280303
- content: `✓ ${toolMatch[2]}`,
280304
- createdAt,
280305
- toolName: toolMatch[1],
280306
- status: "completed"
280307
- });
280308
- }
280309
- } else if (content.startsWith("[Step")) {
280310
- const stepMatch = content.match(/\[Step \d+\] (.+)/);
280311
- if (stepMatch) {
280312
- messages.push({
280313
- role: "assistant",
280314
- content: stepMatch[1],
280315
- createdAt
280316
- });
280317
- }
280318
- }
280319
- }
280320
- if (messages.length === 0) {
280321
- return null;
280322
- }
280323
- return {
280324
- id: "discovery-from-logs",
280325
- name: "Attack Surface Discovery",
280326
- type: "attack-surface",
280327
- target: session.targets[0] || "Unknown",
280328
- messages,
280329
- createdAt: new Date(session.time.created),
280330
- status: "completed"
280331
- };
280332
- } catch (e) {
280333
- console.error("Failed to parse logs:", e);
280334
- return null;
280335
- }
280336
- }
280337
- async function loadSessionState(session) {
280338
- const rootPath = session.rootPath;
280339
- let subagents = loadSubagents(rootPath);
280340
- const hasAttackSurfaceAgent = subagents.some((s) => s.type === "attack-surface");
280341
- if (!hasAttackSurfaceAgent) {
280342
- const discoveryAgent = createDiscoveryFromLogs(rootPath, session);
280343
- if (discoveryAgent) {
280344
- subagents = [discoveryAgent, ...subagents];
280345
- }
280346
- }
280347
- const attackSurfaceResults = loadAttackSurfaceResults(rootPath);
280348
- const hasReportFile = hasReport(rootPath);
280349
- const hasDiscoverySubagent = subagents.some((s) => s.type === "attack-surface");
280350
- const interruptedDuringDiscovery = !attackSurfaceResults && !hasReportFile && hasDiscoverySubagent;
280351
- if (interruptedDuringDiscovery) {
280352
- for (let i = 0;i < subagents.length; i++) {
280353
- if (subagents[i].type === "attack-surface" && subagents[i].status === "completed") {
280354
- subagents[i] = { ...subagents[i], status: "paused" };
280355
- }
280356
- }
280357
- }
280358
- const pentestSubagents = subagents.filter((s) => s.type === "pentest");
280359
- const allPentestDone = pentestSubagents.length > 0 && pentestSubagents.every((s) => s.status === "completed" || s.status === "failed");
280360
- const isComplete = hasReportFile || attackSurfaceResults?.summary?.analysisComplete === true && allPentestDone;
280361
- return {
280362
- session,
280363
- subagents,
280364
- attackSurfaceResults,
280365
- isComplete,
280366
- hasReport: hasReportFile,
280367
- interruptedDuringDiscovery
280368
- };
280369
- }
280503
+ init_loader();
280370
280504
 
280371
280505
  // src/core/api/blackboxPentest.ts
280372
280506
  init_pentest();
@@ -280393,7 +280527,7 @@ Found ${findings.length} vulnerabilities`);
280393
280527
  init_utils();
280394
280528
 
280395
280529
  // src/tui/components/agent-display.tsx
280396
- var import_react73 = __toESM(require_react(), 1);
280530
+ var import_react72 = __toESM(require_react(), 1);
280397
280531
 
280398
280532
  // node_modules/marked/lib/marked.esm.js
280399
280533
  function L2() {
@@ -282725,14 +282859,14 @@ ${preview}${suffix}` : preview + suffix || "POC passed",
282725
282859
  return null;
282726
282860
  }
282727
282861
  // src/tui/components/shared/ascii-spinner.tsx
282728
- var import_react67 = __toESM(require_react(), 1);
282862
+ var import_react66 = __toESM(require_react(), 1);
282729
282863
  var SPINNER_FRAMES = ["/", "-", "\\", "|"];
282730
282864
  var SPINNER_INTERVAL = 100;
282731
282865
  function AsciiSpinner({ label, fg: fg2 }) {
282732
282866
  const { colors: colors2 } = useTheme();
282733
282867
  const spinnerColor = fg2 ?? colors2.info;
282734
- const [frame, setFrame] = import_react67.useState(0);
282735
- import_react67.useEffect(() => {
282868
+ const [frame, setFrame] = import_react66.useState(0);
282869
+ import_react66.useEffect(() => {
282736
282870
  const interval = setInterval(() => {
282737
282871
  setFrame((f3) => (f3 + 1) % SPINNER_FRAMES.length);
282738
282872
  }, SPINNER_INTERVAL);
@@ -282744,7 +282878,7 @@ function AsciiSpinner({ label, fg: fg2 }) {
282744
282878
  }, undefined, false, undefined, this);
282745
282879
  }
282746
282880
  // src/tui/components/shared/tool-renderer.tsx
282747
- var import_react68 = __toESM(require_react(), 1);
282881
+ var import_react67 = __toESM(require_react(), 1);
282748
282882
  var TOOLS_WITH_LOG_WINDOW = new Set([
282749
282883
  "execute_command",
282750
282884
  "run_attack_surface",
@@ -282757,13 +282891,13 @@ var TOOLS_WITH_LOG_WINDOW = new Set([
282757
282891
  "document_vulnerability"
282758
282892
  ]);
282759
282893
  var DEFAULT_SUBAGENT_LOG_LINES = 5;
282760
- var ToolRenderer = import_react68.memo(function ToolRenderer2({
282894
+ var ToolRenderer = import_react67.memo(function ToolRenderer2({
282761
282895
  message,
282762
282896
  verbose = false,
282763
282897
  expandedLogs = false
282764
282898
  }) {
282765
282899
  const { colors: colors2 } = useTheme();
282766
- const [showOutput, setShowOutput] = import_react68.useState(false);
282900
+ const [showOutput, setShowOutput] = import_react67.useState(false);
282767
282901
  if (!isToolMessage(message)) {
282768
282902
  return null;
282769
282903
  }
@@ -282903,7 +283037,7 @@ var ToolRenderer = import_react68.memo(function ToolRenderer2({
282903
283037
  ]
282904
283038
  }, undefined, true, undefined, this);
282905
283039
  });
282906
- var SubagentLogWindow = import_react68.memo(function SubagentLogWindow2({
283040
+ var SubagentLogWindow = import_react67.memo(function SubagentLogWindow2({
282907
283041
  subagentId,
282908
283042
  entry,
282909
283043
  expandedLogs
@@ -282960,8 +283094,8 @@ var SubagentLogWindow = import_react68.memo(function SubagentLogWindow2({
282960
283094
  }, undefined, true, undefined, this);
282961
283095
  });
282962
283096
  // src/tui/components/shared/message-renderer.tsx
282963
- var import_react69 = __toESM(require_react(), 1);
282964
- var MessageRenderer = import_react69.memo(function MessageRenderer2({
283097
+ var import_react68 = __toESM(require_react(), 1);
283098
+ var MessageRenderer = import_react68.memo(function MessageRenderer2({
282965
283099
  message,
282966
283100
  isStreaming = false,
282967
283101
  verbose = false,
@@ -282971,7 +283105,7 @@ var MessageRenderer = import_react69.memo(function MessageRenderer2({
282971
283105
  }) {
282972
283106
  const { colors: colors2 } = useTheme();
282973
283107
  const content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
282974
- const displayContent = import_react69.useMemo(() => message.role === "assistant" ? markdownToStyledText(content, colors2) : content, [content, message.role, colors2]);
283108
+ const displayContent = import_react68.useMemo(() => message.role === "assistant" ? markdownToStyledText(content, colors2) : content, [content, message.role, colors2]);
282975
283109
  if (isToolMessage(message)) {
282976
283110
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToolRenderer, {
282977
283111
  message,
@@ -283083,9 +283217,9 @@ var MessageRenderer = import_react69.memo(function MessageRenderer2({
283083
283217
  }, undefined, false, undefined, this);
283084
283218
  });
283085
283219
  // src/tui/components/shared/approval-prompt.tsx
283086
- var import_react70 = __toESM(require_react(), 1);
283220
+ var import_react69 = __toESM(require_react(), 1);
283087
283221
  // src/tui/components/shared/message-reducer.ts
283088
- var import_react72 = __toESM(require_react(), 1);
283222
+ var import_react71 = __toESM(require_react(), 1);
283089
283223
  // src/tui/components/agent-display.tsx
283090
283224
  function getStableKey(item, contextId = "root") {
283091
283225
  if ("messages" in item) {
@@ -283161,11 +283295,11 @@ function AgentDisplay({
283161
283295
  ]
283162
283296
  }, undefined, true, undefined, this);
283163
283297
  }
283164
- var SubAgentDisplay = import_react73.memo(function SubAgentDisplay2({
283298
+ var SubAgentDisplay = import_react72.memo(function SubAgentDisplay2({
283165
283299
  subagent
283166
283300
  }) {
283167
283301
  const { colors: colors2 } = useTheme();
283168
- const [open, setOpen] = import_react73.useState(false);
283302
+ const [open, setOpen] = import_react72.useState(false);
283169
283303
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
283170
283304
  height: open ? 40 : "auto",
283171
283305
  onMouseDown: () => setOpen(!open),
@@ -283220,11 +283354,11 @@ var SubAgentDisplay = import_react73.memo(function SubAgentDisplay2({
283220
283354
  ]
283221
283355
  }, undefined, true, undefined, this);
283222
283356
  });
283223
- var AgentMessage = import_react73.memo(function AgentMessage2({
283357
+ var AgentMessage = import_react72.memo(function AgentMessage2({
283224
283358
  message
283225
283359
  }) {
283226
283360
  const { colors: colors2 } = useTheme();
283227
- const dimensions = useTerminalDimensions();
283361
+ const dimensions = useDimensions();
283228
283362
  let content = "";
283229
283363
  if (typeof message.content === "string") {
283230
283364
  content = message.content;
@@ -283329,8 +283463,8 @@ var AgentMessage = import_react73.memo(function AgentMessage2({
283329
283463
  });
283330
283464
  function ToolDetails({ message }) {
283331
283465
  const { colors: colors2 } = useTheme();
283332
- const [showArgs, setShowArgs] = import_react73.useState(false);
283333
- const [showResult, setShowResult] = import_react73.useState(false);
283466
+ const [showArgs, setShowArgs] = import_react72.useState(false);
283467
+ const [showResult, setShowResult] = import_react72.useState(false);
283334
283468
  if (message.role !== "tool") {
283335
283469
  return null;
283336
283470
  }
@@ -283436,27 +283570,27 @@ function Pentest({
283436
283570
  const config3 = useConfig();
283437
283571
  const { model, setThinking, setIsExecuting, isExecuting } = useAgent();
283438
283572
  const { stack, externalDialogOpen } = useDialog();
283439
- const [session, setSession] = import_react75.useState(null);
283440
- const [error40, setError] = import_react75.useState(null);
283441
- const [phase, setPhase] = import_react75.useState("loading");
283442
- const [abortController, setAbortController] = import_react75.useState(null);
283443
- const [panelMessages, setPanelMessages] = import_react75.useState([]);
283444
- const panelTextRef = import_react75.useRef("");
283445
- const panelSourceRef = import_react75.useRef(null);
283446
- const [pentestAgents, setPentestAgents] = import_react75.useState({});
283447
- const pentestTextRefs = import_react75.useRef({});
283448
- const [assets, setAssets] = import_react75.useState([]);
283449
- const [viewMode, setViewMode] = import_react75.useState("overview");
283450
- const [selectedAgentId, setSelectedAgentId] = import_react75.useState(null);
283451
- const [focusedIndex, setFocusedIndex] = import_react75.useState(0);
283452
- const [showOrchestratorPanel, setShowOrchestratorPanel] = import_react75.useState(false);
283453
- const [startTime, setStartTime] = import_react75.useState(null);
283454
- const pentestAgentList = import_react75.useMemo(() => Object.values(pentestAgents).sort((a, b3) => a.createdAt.getTime() - b3.createdAt.getTime()), [pentestAgents]);
283455
- const selectedAgent = import_react75.useMemo(() => selectedAgentId ? pentestAgents[selectedAgentId] ?? null : null, [pentestAgents, selectedAgentId]);
283456
- const { width: termWidth } = useTerminalDimensions();
283573
+ const [session, setSession] = import_react73.useState(null);
283574
+ const [error40, setError] = import_react73.useState(null);
283575
+ const [phase, setPhase] = import_react73.useState("loading");
283576
+ const [abortController, setAbortController] = import_react73.useState(null);
283577
+ const [panelMessages, setPanelMessages] = import_react73.useState([]);
283578
+ const panelTextRef = import_react73.useRef("");
283579
+ const panelSourceRef = import_react73.useRef(null);
283580
+ const [pentestAgents, setPentestAgents] = import_react73.useState({});
283581
+ const pentestTextRefs = import_react73.useRef({});
283582
+ const [assets, setAssets] = import_react73.useState([]);
283583
+ const [viewMode, setViewMode] = import_react73.useState("overview");
283584
+ const [selectedAgentId, setSelectedAgentId] = import_react73.useState(null);
283585
+ const [focusedIndex, setFocusedIndex] = import_react73.useState(0);
283586
+ const [showOrchestratorPanel, setShowOrchestratorPanel] = import_react73.useState(false);
283587
+ const [startTime, setStartTime] = import_react73.useState(null);
283588
+ const pentestAgentList = import_react73.useMemo(() => Object.values(pentestAgents).sort((a, b3) => a.createdAt.getTime() - b3.createdAt.getTime()), [pentestAgents]);
283589
+ const selectedAgent = import_react73.useMemo(() => selectedAgentId ? pentestAgents[selectedAgentId] ?? null : null, [pentestAgents, selectedAgentId]);
283590
+ const { width: termWidth } = useDimensions();
283457
283591
  const gridAvailableWidth = showOrchestratorPanel ? Math.floor((termWidth - 4) / 2) - 2 : termWidth - ORCHESTRATOR_PANEL_WIDTH - GRID_OUTER_PADDING;
283458
283592
  const gridColumns = Math.max(1, Math.floor((gridAvailableWidth + GRID_GAP) / (CARD_MIN_WIDTH + GRID_GAP)));
283459
- import_react75.useEffect(() => {
283593
+ import_react73.useEffect(() => {
283460
283594
  async function load2() {
283461
283595
  try {
283462
283596
  let s2;
@@ -283502,6 +283636,9 @@ function Pentest({
283502
283636
  if (attackSurfaceAgents.some((sa) => sa.messages.length > 0)) {
283503
283637
  setShowOrchestratorPanel(true);
283504
283638
  }
283639
+ if (state.attackSurfaceResults?.summary?.analysisComplete) {
283640
+ setPhase("pentesting");
283641
+ }
283505
283642
  startPentest(s2);
283506
283643
  }
283507
283644
  } else {
@@ -283514,7 +283651,7 @@ function Pentest({
283514
283651
  }
283515
283652
  load2();
283516
283653
  }, [sessionId]);
283517
- import_react75.useEffect(() => {
283654
+ import_react73.useEffect(() => {
283518
283655
  if (!session)
283519
283656
  return;
283520
283657
  const assetsPath = join27(session.rootPath, "assets");
@@ -283537,12 +283674,12 @@ function Pentest({
283537
283674
  const interval = setInterval(readAssets, 2000);
283538
283675
  return () => clearInterval(interval);
283539
283676
  }, [session]);
283540
- import_react75.useEffect(() => {
283677
+ import_react73.useEffect(() => {
283541
283678
  return () => {
283542
283679
  abortController?.abort();
283543
283680
  };
283544
283681
  }, [abortController]);
283545
- const ensurePentestAgent = import_react75.useCallback((subagentId) => {
283682
+ const ensurePentestAgent = import_react73.useCallback((subagentId) => {
283546
283683
  setPentestAgents((prev) => {
283547
283684
  if (prev[subagentId])
283548
283685
  return prev;
@@ -283559,7 +283696,7 @@ function Pentest({
283559
283696
  };
283560
283697
  });
283561
283698
  }, []);
283562
- const handleSubagentSpawn = import_react75.useCallback(({
283699
+ const handleSubagentSpawn = import_react73.useCallback(({
283563
283700
  subagentId,
283564
283701
  input
283565
283702
  }) => {
@@ -283579,7 +283716,7 @@ function Pentest({
283579
283716
  }
283580
283717
  }));
283581
283718
  }, []);
283582
- const handleSubagentComplete = import_react75.useCallback(({ subagentId, status }) => {
283719
+ const handleSubagentComplete = import_react73.useCallback(({ subagentId, status }) => {
283583
283720
  if (!subagentId.startsWith("pentest-agent-"))
283584
283721
  return;
283585
283722
  setPentestAgents((prev) => {
@@ -283592,7 +283729,7 @@ function Pentest({
283592
283729
  };
283593
283730
  });
283594
283731
  }, []);
283595
- const appendPanelText = import_react75.useCallback((source, text2) => {
283732
+ const appendPanelText = import_react73.useCallback((source, text2) => {
283596
283733
  if (panelSourceRef.current !== source) {
283597
283734
  panelTextRef.current = "";
283598
283735
  panelSourceRef.current = source;
@@ -283617,7 +283754,7 @@ function Pentest({
283617
283754
  ];
283618
283755
  });
283619
283756
  }, []);
283620
- const appendPentestText = import_react75.useCallback((subagentId, text2) => {
283757
+ const appendPentestText = import_react73.useCallback((subagentId, text2) => {
283621
283758
  ensurePentestAgent(subagentId);
283622
283759
  if (!pentestTextRefs.current[subagentId]) {
283623
283760
  pentestTextRefs.current[subagentId] = "";
@@ -283650,8 +283787,8 @@ function Pentest({
283650
283787
  };
283651
283788
  });
283652
283789
  }, [ensurePentestAgent]);
283653
- const toolArgsDeltaRef = import_react75.useRef(new Map);
283654
- const addPanelStreamingToolCall = import_react75.useCallback((toolCallId, toolName) => {
283790
+ const toolArgsDeltaRef = import_react73.useRef(new Map);
283791
+ const addPanelStreamingToolCall = import_react73.useCallback((toolCallId, toolName) => {
283655
283792
  panelTextRef.current = "";
283656
283793
  panelSourceRef.current = null;
283657
283794
  toolArgsDeltaRef.current.set(toolCallId, "");
@@ -283670,7 +283807,7 @@ function Pentest({
283670
283807
  return [...prev, msg];
283671
283808
  });
283672
283809
  }, []);
283673
- const appendPanelToolCallDelta = import_react75.useCallback((toolCallId, argsTextDelta) => {
283810
+ const appendPanelToolCallDelta = import_react73.useCallback((toolCallId, argsTextDelta) => {
283674
283811
  const prev = toolArgsDeltaRef.current.get(toolCallId) ?? "";
283675
283812
  const accumulated = prev + argsTextDelta;
283676
283813
  toolArgsDeltaRef.current.set(toolCallId, accumulated);
@@ -283693,7 +283830,7 @@ function Pentest({
283693
283830
  return updated;
283694
283831
  });
283695
283832
  }, []);
283696
- const addPanelToolCall = import_react75.useCallback((toolCallId, toolName, args) => {
283833
+ const addPanelToolCall = import_react73.useCallback((toolCallId, toolName, args) => {
283697
283834
  panelTextRef.current = "";
283698
283835
  panelSourceRef.current = null;
283699
283836
  toolArgsDeltaRef.current.delete(toolCallId);
@@ -283725,7 +283862,7 @@ function Pentest({
283725
283862
  ];
283726
283863
  });
283727
283864
  }, []);
283728
- const addPentestStreamingToolCall = import_react75.useCallback((subagentId, toolCallId, toolName) => {
283865
+ const addPentestStreamingToolCall = import_react73.useCallback((subagentId, toolCallId, toolName) => {
283729
283866
  pentestTextRefs.current[subagentId] = "";
283730
283867
  ensurePentestAgent(subagentId);
283731
283868
  toolArgsDeltaRef.current.set(toolCallId, "");
@@ -283750,7 +283887,7 @@ function Pentest({
283750
283887
  };
283751
283888
  });
283752
283889
  }, [ensurePentestAgent]);
283753
- const appendPentestToolCallDelta = import_react75.useCallback((subagentId, toolCallId, argsTextDelta) => {
283890
+ const appendPentestToolCallDelta = import_react73.useCallback((subagentId, toolCallId, argsTextDelta) => {
283754
283891
  const prev = toolArgsDeltaRef.current.get(toolCallId) ?? "";
283755
283892
  const accumulated = prev + argsTextDelta;
283756
283893
  toolArgsDeltaRef.current.set(toolCallId, accumulated);
@@ -283776,7 +283913,7 @@ function Pentest({
283776
283913
  return { ...agents, [subagentId]: { ...agent, messages: updatedMsgs } };
283777
283914
  });
283778
283915
  }, []);
283779
- const addPentestToolCall = import_react75.useCallback((subagentId, toolCallId, toolName, args) => {
283916
+ const addPentestToolCall = import_react73.useCallback((subagentId, toolCallId, toolName, args) => {
283780
283917
  pentestTextRefs.current[subagentId] = "";
283781
283918
  ensurePentestAgent(subagentId);
283782
283919
  toolArgsDeltaRef.current.delete(toolCallId);
@@ -283837,12 +283974,12 @@ function Pentest({
283837
283974
  }
283838
283975
  ];
283839
283976
  };
283840
- const updatePanelToolResult = import_react75.useCallback((toolCallId, toolName, result) => {
283977
+ const updatePanelToolResult = import_react73.useCallback((toolCallId, toolName, result) => {
283841
283978
  panelTextRef.current = "";
283842
283979
  panelSourceRef.current = null;
283843
283980
  setPanelMessages((prev) => toolResultUpdater(prev, toolCallId, toolName, result));
283844
283981
  }, []);
283845
- const updatePentestToolResult = import_react75.useCallback((subagentId, toolCallId, toolName, result) => {
283982
+ const updatePentestToolResult = import_react73.useCallback((subagentId, toolCallId, toolName, result) => {
283846
283983
  pentestTextRefs.current[subagentId] = "";
283847
283984
  setPentestAgents((prev) => {
283848
283985
  const agent = prev[subagentId];
@@ -283857,11 +283994,12 @@ function Pentest({
283857
283994
  };
283858
283995
  });
283859
283996
  }, []);
283860
- const startPentest = import_react75.useCallback(async (s2) => {
283861
- setPhase("discovery");
283997
+ const startPentest = import_react73.useCallback(async (s2) => {
283998
+ setPhase((prev) => prev === "pentesting" || prev === "reporting" ? prev : "discovery");
283862
283999
  setStartTime(new Date);
283863
284000
  setIsExecuting(true);
283864
- setThinking(true);
284001
+ const discoveryDone = existsSync26(join27(s2.rootPath, "attack-surface-results.json"));
284002
+ setThinking(!discoveryDone);
283865
284003
  const controller = new AbortController;
283866
284004
  setAbortController(controller);
283867
284005
  try {
@@ -283984,7 +284122,7 @@ function Pentest({
283984
284122
  handleSubagentSpawn,
283985
284123
  handleSubagentComplete
283986
284124
  ]);
283987
- import_react75.useEffect(() => {
284125
+ import_react73.useEffect(() => {
283988
284126
  if (phase === "completed") {
283989
284127
  setFocusedIndex(pentestAgentList.length);
283990
284128
  }
@@ -284047,7 +284185,7 @@ function Pentest({
284047
284185
  }
284048
284186
  }
284049
284187
  });
284050
- const openReport = import_react75.useCallback(() => {
284188
+ const openReport = import_react73.useCallback(() => {
284051
284189
  if (!session)
284052
284190
  return;
284053
284191
  const err = openSessionReport(session.rootPath);
@@ -284232,7 +284370,7 @@ function OrchestratorPanel({
284232
284370
  }) {
284233
284371
  const { colors: colors2 } = useTheme();
284234
284372
  const isRunning = phase !== "loading" && phase !== "completed" && phase !== "error";
284235
- const assetSummary = import_react75.useMemo(() => {
284373
+ const assetSummary = import_react73.useMemo(() => {
284236
284374
  const byType = {};
284237
284375
  for (const a of assets) {
284238
284376
  const key = a.assetType;
@@ -284475,13 +284613,13 @@ function AgentCardGrid({
284475
284613
  onSelectAgent
284476
284614
  }) {
284477
284615
  const { colors: colors2 } = useTheme();
284478
- const scrollRef = import_react75.useRef(null);
284479
- import_react75.useEffect(() => {
284616
+ const scrollRef = import_react73.useRef(null);
284617
+ import_react73.useEffect(() => {
284480
284618
  const agent = agents[focusedIndex];
284481
284619
  if (agent)
284482
284620
  scrollToChild(scrollRef.current, agent.id);
284483
284621
  }, [focusedIndex, agents]);
284484
- const rows = import_react75.useMemo(() => {
284622
+ const rows = import_react73.useMemo(() => {
284485
284623
  const result = [];
284486
284624
  for (let i2 = 0;i2 < agents.length; i2 += gridColumns) {
284487
284625
  result.push(agents.slice(i2, i2 + gridColumns));
@@ -284538,14 +284676,14 @@ function AgentCard({
284538
284676
  completed: colors2.primary,
284539
284677
  failed: colors2.error
284540
284678
  }[agent.status];
284541
- const lastActivity = import_react75.useMemo(() => {
284679
+ const lastActivity = import_react73.useMemo(() => {
284542
284680
  const last = agent.messages[agent.messages.length - 1];
284543
284681
  if (!last)
284544
284682
  return "Starting...";
284545
284683
  const text2 = typeof last.content === "string" ? last.content.replace(/\n/g, " ").trim() : "Working...";
284546
284684
  return text2.length > 50 ? text2.substring(0, 47) + "..." : text2;
284547
284685
  }, [agent.messages]);
284548
- const toolCalls = import_react75.useMemo(() => agent.messages.filter((m4) => m4.role === "tool").length, [agent.messages]);
284686
+ const toolCalls = import_react73.useMemo(() => agent.messages.filter((m4) => m4.role === "tool").length, [agent.messages]);
284549
284687
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
284550
284688
  id: agent.id,
284551
284689
  flexGrow: 1,
@@ -284733,8 +284871,8 @@ function MetricsBar({
284733
284871
  isExecuting
284734
284872
  }) {
284735
284873
  const { colors: colors2 } = useTheme();
284736
- const [now2, setNow] = import_react75.useState(Date.now());
284737
- import_react75.useEffect(() => {
284874
+ const [now2, setNow] = import_react73.useState(Date.now());
284875
+ import_react73.useEffect(() => {
284738
284876
  if (!isExecuting)
284739
284877
  return;
284740
284878
  const interval = setInterval(() => setNow(Date.now()), 1000);
@@ -284877,7 +285015,7 @@ function MetricsBar({
284877
285015
  }
284878
285016
 
284879
285017
  // src/tui/components/operator-dashboard/index.tsx
284880
- var import_react80 = __toESM(require_react(), 1);
285018
+ var import_react78 = __toESM(require_react(), 1);
284881
285019
  init_session();
284882
285020
 
284883
285021
  // src/core/api/offesecAgent.ts
@@ -284980,7 +285118,7 @@ function InlineApprovalPrompt2({ approval }) {
284980
285118
  }
284981
285119
 
284982
285120
  // src/tui/components/chat/loading-indicator.tsx
284983
- var import_react77 = __toESM(require_react(), 1);
285121
+ var import_react75 = __toESM(require_react(), 1);
284984
285122
  var SPINNER_FRAMES2 = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
284985
285123
  var SPINNER_INTERVAL2 = 80;
284986
285124
  var DOTS_FRAMES = ["", ".", "..", "..."];
@@ -284991,15 +285129,15 @@ function LoadingIndicator({
284991
285129
  toolName
284992
285130
  }) {
284993
285131
  const { colors: colors2 } = useTheme();
284994
- const [spinnerFrame, setSpinnerFrame] = import_react77.useState(0);
284995
- const [dotsFrame, setDotsFrame] = import_react77.useState(0);
284996
- import_react77.useEffect(() => {
285132
+ const [spinnerFrame, setSpinnerFrame] = import_react75.useState(0);
285133
+ const [dotsFrame, setDotsFrame] = import_react75.useState(0);
285134
+ import_react75.useEffect(() => {
284997
285135
  const interval = setInterval(() => {
284998
285136
  setSpinnerFrame((f3) => (f3 + 1) % SPINNER_FRAMES2.length);
284999
285137
  }, SPINNER_INTERVAL2);
285000
285138
  return () => clearInterval(interval);
285001
285139
  }, []);
285002
- import_react77.useEffect(() => {
285140
+ import_react75.useEffect(() => {
285003
285141
  const interval = setInterval(() => {
285004
285142
  setDotsFrame((f3) => (f3 + 1) % DOTS_FRAMES.length);
285005
285143
  }, DOTS_INTERVAL);
@@ -285253,7 +285391,7 @@ function MessageList({
285253
285391
  }
285254
285392
 
285255
285393
  // src/tui/components/chat/input-area.tsx
285256
- var import_react78 = __toESM(require_react(), 1);
285394
+ var import_react76 = __toESM(require_react(), 1);
285257
285395
  function NormalInputAreaInner({
285258
285396
  value,
285259
285397
  onChange,
@@ -285275,10 +285413,10 @@ function NormalInputAreaInner({
285275
285413
  }) {
285276
285414
  const { colors: colors2, theme, mode: colorMode } = useTheme();
285277
285415
  const { inputValue, setInputValue } = useInput();
285278
- const promptRef = import_react78.useRef(null);
285279
- const isExternalUpdate = import_react78.useRef(false);
285280
- const prevValueRef = import_react78.useRef(value);
285281
- import_react78.useEffect(() => {
285416
+ const promptRef = import_react76.useRef(null);
285417
+ const isExternalUpdate = import_react76.useRef(false);
285418
+ const prevValueRef = import_react76.useRef(value);
285419
+ import_react76.useEffect(() => {
285282
285420
  const prevValue = prevValueRef.current;
285283
285421
  prevValueRef.current = value;
285284
285422
  if (value !== prevValue && value !== inputValue) {
@@ -285287,7 +285425,7 @@ function NormalInputAreaInner({
285287
285425
  promptRef.current?.setValue(value);
285288
285426
  }
285289
285427
  }, [value, inputValue, setInputValue]);
285290
- import_react78.useEffect(() => {
285428
+ import_react76.useEffect(() => {
285291
285429
  if (isExternalUpdate.current) {
285292
285430
  isExternalUpdate.current = false;
285293
285431
  return;
@@ -285462,7 +285600,7 @@ function ApprovalInputArea2({
285462
285600
  lastDeclineNote
285463
285601
  }) {
285464
285602
  const { colors: colors2 } = useTheme();
285465
- const [focusedElement, setFocusedElement] = import_react78.useState(0);
285603
+ const [focusedElement, setFocusedElement] = import_react76.useState(0);
285466
285604
  useKeyboard((key) => {
285467
285605
  if (key.name === "up") {
285468
285606
  setFocusedElement((prev) => Math.max(0, prev - 1));
@@ -285789,29 +285927,29 @@ function OperatorDashboard({
285789
285927
  clear: clearDialog,
285790
285928
  setSize: setDialogSize
285791
285929
  } = useDialog();
285792
- const autocompleteOptions = import_react80.useMemo(() => {
285930
+ const autocompleteOptions = import_react78.useMemo(() => {
285793
285931
  const skillSlugs = new Set(skills.map((s2) => `/${slugify(s2.name)}`));
285794
285932
  return filterOperatorAutocomplete(allAutocompleteOptions, skillSlugs);
285795
285933
  }, [allAutocompleteOptions, skills]);
285796
- const [session, setSession] = import_react80.useState(null);
285797
- const [loading, setLoading] = import_react80.useState(true);
285798
- const [error40, setError] = import_react80.useState(null);
285799
- const pendingNameRef = import_react80.useRef(null);
285800
- const [status, setStatus] = import_react80.useState("idle");
285801
- const abortControllerRef = import_react80.useRef(null);
285802
- const generationRef = import_react80.useRef(0);
285803
- const cancelHandleRef = import_react80.useRef({
285934
+ const [session, setSession] = import_react78.useState(null);
285935
+ const [loading, setLoading] = import_react78.useState(true);
285936
+ const [error40, setError] = import_react78.useState(null);
285937
+ const pendingNameRef = import_react78.useRef(null);
285938
+ const [status, setStatus] = import_react78.useState("idle");
285939
+ const abortControllerRef = import_react78.useRef(null);
285940
+ const generationRef = import_react78.useRef(0);
285941
+ const cancelHandleRef = import_react78.useRef({
285804
285942
  cancel: () => false
285805
285943
  });
285806
- const commandCancelledRef = import_react80.useRef(false);
285807
- const [messages, setMessages] = import_react80.useState([]);
285808
- const textRef = import_react80.useRef("");
285809
- const conversationRef = import_react80.useRef([]);
285810
- const [inputValue, setInputValue] = import_react80.useState("");
285811
- const [queuedMessages, setQueuedMessages] = import_react80.useState([]);
285812
- const [selectedQueueIndex, setSelectedQueueIndex] = import_react80.useState(-1);
285813
- const queuedMessagesRef = import_react80.useRef([]);
285814
- import_react80.useEffect(() => {
285944
+ const commandCancelledRef = import_react78.useRef(false);
285945
+ const [messages, setMessages] = import_react78.useState([]);
285946
+ const textRef = import_react78.useRef("");
285947
+ const conversationRef = import_react78.useRef([]);
285948
+ const [inputValue, setInputValue] = import_react78.useState("");
285949
+ const [queuedMessages, setQueuedMessages] = import_react78.useState([]);
285950
+ const [selectedQueueIndex, setSelectedQueueIndex] = import_react78.useState(-1);
285951
+ const queuedMessagesRef = import_react78.useRef([]);
285952
+ import_react78.useEffect(() => {
285815
285953
  queuedMessagesRef.current = queuedMessages;
285816
285954
  if (queuedMessages.length === 0) {
285817
285955
  setSelectedQueueIndex(-1);
@@ -285819,17 +285957,17 @@ function OperatorDashboard({
285819
285957
  setSelectedQueueIndex(queuedMessages.length - 1);
285820
285958
  }
285821
285959
  }, [queuedMessages, selectedQueueIndex]);
285822
- const [operatorState, setOperatorState] = import_react80.useState(() => createInitialOperatorState("manual", true));
285823
- const approvalGateRef = import_react80.useRef(new ApprovalGate({ requireApproval: true }));
285824
- const [pendingApprovals, setPendingApprovals] = import_react80.useState([]);
285825
- const [lastApprovedAction, setLastApprovedAction] = import_react80.useState(null);
285826
- const [verboseMode, setVerboseMode] = import_react80.useState(false);
285827
- const [expandedLogs, setExpandedLogs] = import_react80.useState(false);
285828
- const tokenUsageRef = import_react80.useRef(tokenUsage);
285829
- import_react80.useEffect(() => {
285960
+ const [operatorState, setOperatorState] = import_react78.useState(() => createInitialOperatorState("manual", true));
285961
+ const approvalGateRef = import_react78.useRef(new ApprovalGate({ requireApproval: true }));
285962
+ const [pendingApprovals, setPendingApprovals] = import_react78.useState([]);
285963
+ const [lastApprovedAction, setLastApprovedAction] = import_react78.useState(null);
285964
+ const [verboseMode, setVerboseMode] = import_react78.useState(false);
285965
+ const [expandedLogs, setExpandedLogs] = import_react78.useState(false);
285966
+ const tokenUsageRef = import_react78.useRef(tokenUsage);
285967
+ import_react78.useEffect(() => {
285830
285968
  tokenUsageRef.current = tokenUsage;
285831
285969
  }, [tokenUsage]);
285832
- import_react80.useEffect(() => {
285970
+ import_react78.useEffect(() => {
285833
285971
  const gate = approvalGateRef.current;
285834
285972
  const onApprovalNeeded = () => {
285835
285973
  setPendingApprovals(gate.getPendingApprovals());
@@ -285851,7 +285989,7 @@ function OperatorDashboard({
285851
285989
  gate.off("approval-resolved", onApprovalResolved);
285852
285990
  };
285853
285991
  }, []);
285854
- import_react80.useEffect(() => {
285992
+ import_react78.useEffect(() => {
285855
285993
  async function loadSession() {
285856
285994
  try {
285857
285995
  if (sessionId) {
@@ -285908,10 +286046,10 @@ function OperatorDashboard({
285908
286046
  }
285909
286047
  loadSession();
285910
286048
  }, [sessionId]);
285911
- import_react80.useEffect(() => {
286049
+ import_react78.useEffect(() => {
285912
286050
  return () => setSessionCwd(null);
285913
286051
  }, [setSessionCwd]);
285914
- import_react80.useEffect(() => {
286052
+ import_react78.useEffect(() => {
285915
286053
  if (!session)
285916
286054
  return;
285917
286055
  resetTokenUsage();
@@ -285929,7 +286067,7 @@ function OperatorDashboard({
285929
286067
  });
285930
286068
  } catch {}
285931
286069
  }, [session, addTokenUsage, resetTokenUsage]);
285932
- const appendText = import_react80.useCallback((text2) => {
286070
+ const appendText = import_react78.useCallback((text2) => {
285933
286071
  textRef.current += text2;
285934
286072
  const accumulated = textRef.current;
285935
286073
  setMessages((prev) => {
@@ -285945,8 +286083,8 @@ function OperatorDashboard({
285945
286083
  ];
285946
286084
  });
285947
286085
  }, []);
285948
- const toolArgsDeltaRef = import_react80.useRef(new Map);
285949
- const addStreamingToolCall = import_react80.useCallback((toolCallId, toolName) => {
286086
+ const toolArgsDeltaRef = import_react78.useRef(new Map);
286087
+ const addStreamingToolCall = import_react78.useCallback((toolCallId, toolName) => {
285950
286088
  textRef.current = "";
285951
286089
  toolArgsDeltaRef.current.set(toolCallId, {
285952
286090
  toolName,
@@ -285965,7 +286103,7 @@ function OperatorDashboard({
285965
286103
  }
285966
286104
  ]);
285967
286105
  }, []);
285968
- const appendToolCallDelta = import_react80.useCallback((toolCallId, argsTextDelta) => {
286106
+ const appendToolCallDelta = import_react78.useCallback((toolCallId, argsTextDelta) => {
285969
286107
  const entry = toolArgsDeltaRef.current.get(toolCallId);
285970
286108
  const accumulated = (entry?.accumulated ?? "") + argsTextDelta;
285971
286109
  toolArgsDeltaRef.current.set(toolCallId, {
@@ -285987,7 +286125,7 @@ function OperatorDashboard({
285987
286125
  return updated;
285988
286126
  });
285989
286127
  }, []);
285990
- const addToolCall = import_react80.useCallback((toolCallId, toolName, args) => {
286128
+ const addToolCall = import_react78.useCallback((toolCallId, toolName, args) => {
285991
286129
  textRef.current = "";
285992
286130
  toolArgsDeltaRef.current.delete(toolCallId);
285993
286131
  setMessages((prev) => {
@@ -286016,7 +286154,7 @@ function OperatorDashboard({
286016
286154
  ];
286017
286155
  });
286018
286156
  }, []);
286019
- const updateToolResult = import_react80.useCallback((toolCallId, _toolName, result) => {
286157
+ const updateToolResult = import_react78.useCallback((toolCallId, _toolName, result) => {
286020
286158
  textRef.current = "";
286021
286159
  setMessages((prev) => {
286022
286160
  const idx = prev.findIndex((m4) => isToolMessage(m4) && m4.toolCallId === toolCallId);
@@ -286027,10 +286165,10 @@ function OperatorDashboard({
286027
286165
  return updated;
286028
286166
  });
286029
286167
  }, []);
286030
- const cmdOutputBufRef = import_react80.useRef("");
286031
- const cmdFlushTimerRef = import_react80.useRef(null);
286168
+ const cmdOutputBufRef = import_react78.useRef("");
286169
+ const cmdFlushTimerRef = import_react78.useRef(null);
286032
286170
  const MAX_LOG_LINES = 200;
286033
- const flushCommandOutput = import_react80.useCallback(() => {
286171
+ const flushCommandOutput = import_react78.useCallback(() => {
286034
286172
  const buf = cmdOutputBufRef.current;
286035
286173
  if (!buf)
286036
286174
  return;
@@ -286060,7 +286198,7 @@ function OperatorDashboard({
286060
286198
  return updated;
286061
286199
  });
286062
286200
  }, []);
286063
- const onCommandOutput = import_react80.useCallback((data) => {
286201
+ const onCommandOutput = import_react78.useCallback((data) => {
286064
286202
  cmdOutputBufRef.current += data;
286065
286203
  if (!cmdFlushTimerRef.current) {
286066
286204
  cmdFlushTimerRef.current = setInterval(() => {
@@ -286068,7 +286206,7 @@ function OperatorDashboard({
286068
286206
  }, 150);
286069
286207
  }
286070
286208
  }, [flushCommandOutput]);
286071
- import_react80.useEffect(() => {
286209
+ import_react78.useEffect(() => {
286072
286210
  return () => {
286073
286211
  if (cmdFlushTimerRef.current) {
286074
286212
  clearInterval(cmdFlushTimerRef.current);
@@ -286076,7 +286214,7 @@ function OperatorDashboard({
286076
286214
  }
286077
286215
  };
286078
286216
  }, []);
286079
- const appendLogToActiveTool = import_react80.useCallback((line) => {
286217
+ const appendLogToActiveTool = import_react78.useCallback((line) => {
286080
286218
  setMessages((prev) => {
286081
286219
  const idx = prev.findLastIndex((m4) => isToolMessage(m4) && (m4.status === "pending" || m4.status === "streaming"));
286082
286220
  if (idx === -1)
@@ -286091,7 +286229,7 @@ function OperatorDashboard({
286091
286229
  return updated;
286092
286230
  });
286093
286231
  }, []);
286094
- const initSubagent = import_react80.useCallback((subagentId, name26) => {
286232
+ const initSubagent = import_react78.useCallback((subagentId, name26) => {
286095
286233
  setMessages((prev) => {
286096
286234
  const idx = prev.findLastIndex((m4) => isToolMessage(m4) && (m4.status === "pending" || m4.status === "streaming"));
286097
286235
  if (idx === -1)
@@ -286106,7 +286244,7 @@ function OperatorDashboard({
286106
286244
  return updated;
286107
286245
  });
286108
286246
  }, []);
286109
- const completeSubagent = import_react80.useCallback((subagentId, status2) => {
286247
+ const completeSubagent = import_react78.useCallback((subagentId, status2) => {
286110
286248
  setMessages((prev) => {
286111
286249
  const idx = prev.findLastIndex((m4) => isToolMessage(m4) && (m4.status === "pending" || m4.status === "streaming"));
286112
286250
  if (idx === -1)
@@ -286124,7 +286262,7 @@ function OperatorDashboard({
286124
286262
  return updated;
286125
286263
  });
286126
286264
  }, []);
286127
- const appendLogToSubagent = import_react80.useCallback((subagentId, line) => {
286265
+ const appendLogToSubagent = import_react78.useCallback((subagentId, line) => {
286128
286266
  setMessages((prev) => {
286129
286267
  const idx = prev.findLastIndex((m4) => isToolMessage(m4) && (m4.status === "pending" || m4.status === "streaming"));
286130
286268
  if (idx === -1)
@@ -286146,13 +286284,13 @@ function OperatorDashboard({
286146
286284
  return updated;
286147
286285
  });
286148
286286
  }, []);
286149
- const handleApprove = import_react80.useCallback(() => {
286287
+ const handleApprove = import_react78.useCallback(() => {
286150
286288
  const pending = approvalGateRef.current.getPendingApprovals();
286151
286289
  if (pending.length > 0) {
286152
286290
  approvalGateRef.current.approve(pending[0].id);
286153
286291
  }
286154
286292
  }, []);
286155
- const handleAutoApprove = import_react80.useCallback(() => {
286293
+ const handleAutoApprove = import_react78.useCallback(() => {
286156
286294
  approvalGateRef.current.updateConfig({ requireApproval: false });
286157
286295
  setOperatorState((prev) => ({ ...prev, requireApproval: false }));
286158
286296
  const pending = approvalGateRef.current.getPendingApprovals();
@@ -286160,7 +286298,7 @@ function OperatorDashboard({
286160
286298
  approvalGateRef.current.approve(p.id);
286161
286299
  }
286162
286300
  }, []);
286163
- const runAgent = import_react80.useCallback(async (prompt) => {
286301
+ const runAgent = import_react78.useCallback(async (prompt) => {
286164
286302
  if (abortControllerRef.current) {
286165
286303
  abortControllerRef.current.abort();
286166
286304
  abortControllerRef.current = null;
@@ -286374,7 +286512,7 @@ function OperatorDashboard({
286374
286512
  setThinking,
286375
286513
  setIsExecuting
286376
286514
  ]);
286377
- const handleSubmit = import_react80.useCallback((value) => {
286515
+ const handleSubmit = import_react78.useCallback((value) => {
286378
286516
  const pending = approvalGateRef.current.getPendingApprovals();
286379
286517
  const result = resolveSubmit(value, status, pending.length > 0);
286380
286518
  if (result.denyPending) {
@@ -286392,16 +286530,16 @@ function OperatorDashboard({
286392
286530
  setInputValue("");
286393
286531
  runAgent(result.prompt);
286394
286532
  }, [status, runAgent]);
286395
- const initialMessageSentRef = import_react80.useRef(false);
286396
- const runAgentRef = import_react80.useRef(runAgent);
286533
+ const initialMessageSentRef = import_react78.useRef(false);
286534
+ const runAgentRef = import_react78.useRef(runAgent);
286397
286535
  runAgentRef.current = runAgent;
286398
- import_react80.useEffect(() => {
286536
+ import_react78.useEffect(() => {
286399
286537
  if (!loading && initialMessage && !initialMessageSentRef.current) {
286400
286538
  initialMessageSentRef.current = true;
286401
286539
  runAgentRef.current(initialMessage);
286402
286540
  }
286403
286541
  }, [loading, initialMessage]);
286404
- import_react80.useEffect(() => {
286542
+ import_react78.useEffect(() => {
286405
286543
  if (status !== "idle")
286406
286544
  return;
286407
286545
  const queue = queuedMessagesRef.current;
@@ -286412,7 +286550,7 @@ function OperatorDashboard({
286412
286550
  setSelectedQueueIndex(-1);
286413
286551
  runAgentRef.current(next);
286414
286552
  }, [status]);
286415
- const showModelPicker = import_react80.useCallback(() => {
286553
+ const showModelPicker = import_react78.useCallback(() => {
286416
286554
  setDialogSize("large");
286417
286555
  showDialog(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
286418
286556
  flexDirection: "column",
@@ -286474,7 +286612,7 @@ function OperatorDashboard({
286474
286612
  clearDialog,
286475
286613
  setDialogSize
286476
286614
  ]);
286477
- const handleCommandExecute = import_react80.useCallback(async (command) => {
286615
+ const handleCommandExecute = import_react78.useCallback(async (command) => {
286478
286616
  const action = routeCommand(command, resolveSkillContent);
286479
286617
  switch (action.type) {
286480
286618
  case "show-models":
@@ -286492,7 +286630,7 @@ function OperatorDashboard({
286492
286630
  return;
286493
286631
  }
286494
286632
  }, [resolveSkillContent, handleSubmit, executeCommand2, showModelPicker]);
286495
- const handleAbort = import_react80.useCallback(() => {
286633
+ const handleAbort = import_react78.useCallback(() => {
286496
286634
  if (!abortControllerRef.current)
286497
286635
  return;
286498
286636
  const action = resolveAbortAction(commandCancelledRef.current, () => cancelHandleRef.current.cancel());
@@ -286542,7 +286680,7 @@ function OperatorDashboard({
286542
286680
  ];
286543
286681
  });
286544
286682
  }, [session, setThinking, setIsExecuting]);
286545
- const toggleApproval = import_react80.useCallback(() => {
286683
+ const toggleApproval = import_react78.useCallback(() => {
286546
286684
  setOperatorState((prev) => {
286547
286685
  const newVal = !prev.requireApproval;
286548
286686
  approvalGateRef.current.updateConfig({ requireApproval: newVal });
@@ -286776,10 +286914,10 @@ function OperatorDashboard({
286776
286914
  }
286777
286915
 
286778
286916
  // src/tui/components/commands/theme-picker.tsx
286779
- var import_react82 = __toESM(require_react(), 1);
286917
+ var import_react80 = __toESM(require_react(), 1);
286780
286918
  init_config2();
286781
286919
  function ThemePicker({ onClose }) {
286782
- const dimensions = useTerminalDimensions();
286920
+ const dimensions = useDimensions();
286783
286921
  const {
286784
286922
  colors: colors2,
286785
286923
  theme,
@@ -286789,15 +286927,15 @@ function ThemePicker({ onClose }) {
286789
286927
  toggleMode,
286790
286928
  setMode
286791
286929
  } = useTheme();
286792
- const [selectedIndex, setSelectedIndex] = import_react82.useState(() => Math.max(0, availableThemes.indexOf(theme.name)));
286793
- const originalThemeRef = import_react82.useRef(theme.name);
286794
- const originalModeRef = import_react82.useRef(mode);
286795
- const handleClose = import_react82.useCallback(() => {
286930
+ const [selectedIndex, setSelectedIndex] = import_react80.useState(() => Math.max(0, availableThemes.indexOf(theme.name)));
286931
+ const originalThemeRef = import_react80.useRef(theme.name);
286932
+ const originalModeRef = import_react80.useRef(mode);
286933
+ const handleClose = import_react80.useCallback(() => {
286796
286934
  setTheme(originalThemeRef.current);
286797
286935
  setMode(originalModeRef.current);
286798
286936
  onClose();
286799
286937
  }, [setTheme, setMode, onClose]);
286800
- const handleConfirm = import_react82.useCallback(async () => {
286938
+ const handleConfirm = import_react80.useCallback(async () => {
286801
286939
  const currentThemeName = availableThemes[selectedIndex];
286802
286940
  if (currentThemeName) {
286803
286941
  await config2.update({ theme: currentThemeName });
@@ -286926,16 +287064,16 @@ function ThemePicker({ onClose }) {
286926
287064
  }
286927
287065
 
286928
287066
  // src/tui/components/commands/create-skill-wizard.tsx
286929
- var import_react84 = __toESM(require_react(), 1);
287067
+ var import_react82 = __toESM(require_react(), 1);
286930
287068
  function CreateSkillWizard() {
286931
287069
  const { colors: colors2 } = useTheme();
286932
287070
  const route = useRoute();
286933
- const [step, setStep] = import_react84.useState("name");
286934
- const [name26, setName] = import_react84.useState("");
286935
- const [description, setDescription] = import_react84.useState("");
286936
- const [content, setContent] = import_react84.useState("");
286937
- const [error40, setError] = import_react84.useState(null);
286938
- const [confirmFocused, setConfirmFocused] = import_react84.useState(0);
287071
+ const [step, setStep] = import_react82.useState("name");
287072
+ const [name26, setName] = import_react82.useState("");
287073
+ const [description, setDescription] = import_react82.useState("");
287074
+ const [content, setContent] = import_react82.useState("");
287075
+ const [error40, setError] = import_react82.useState(null);
287076
+ const [confirmFocused, setConfirmFocused] = import_react82.useState(0);
286939
287077
  const slug = slugify(name26);
286940
287078
  async function handleSave() {
286941
287079
  if (!name26.trim() || !content.trim())
@@ -289811,7 +289949,7 @@ async function detectTerminalMode(timeoutMs = 1000) {
289811
289949
  }
289812
289950
 
289813
289951
  // src/tui/console-theme.ts
289814
- var import_react86 = __toESM(require_react(), 1);
289952
+ var import_react84 = __toESM(require_react(), 1);
289815
289953
  var withAlpha = (rgba, a) => RGBA.fromValues(rgba.r, rgba.g, rgba.b, a);
289816
289954
  var overlayThemeRef = {
289817
289955
  current: null
@@ -289834,7 +289972,7 @@ function buildConsoleOptions(themeColors) {
289834
289972
  function ConsoleThemeSync() {
289835
289973
  const { colors: colors2 } = useTheme();
289836
289974
  const renderer = useRenderer();
289837
- import_react86.useEffect(() => {
289975
+ import_react84.useEffect(() => {
289838
289976
  overlayThemeRef.current = colors2;
289839
289977
  const c = renderer.console;
289840
289978
  c.backgroundColor = withAlpha(colors2.backgroundPanel, 0.85);
@@ -289922,17 +290060,17 @@ function setupAutoCopy(renderer, copyToClipboard) {
289922
290060
 
289923
290061
  // src/tui/index.tsx
289924
290062
  function App({ appConfig }) {
289925
- const [focusIndex, setFocusIndex] = import_react89.useState(0);
289926
- const [cwd, setCwd] = import_react89.useState(process.cwd());
289927
- const [ctrlCPressTime, setCtrlCPressTime] = import_react89.useState(null);
289928
- const [showExitWarning, setShowExitWarning] = import_react89.useState(false);
289929
- const [inputKey, setInputKey] = import_react89.useState(0);
289930
- const [showSessionsDialog, setShowSessionsDialog] = import_react89.useState(false);
289931
- const [showShortcutsDialog, setShowShortcutsDialog] = import_react89.useState(false);
289932
- const [showThemeDialog, setShowThemeDialog] = import_react89.useState(false);
289933
- const [showAuthDialog, setShowAuthDialog] = import_react89.useState(false);
289934
- const [showPentestDialog, setShowPentestDialog] = import_react89.useState(false);
289935
- const [pendingPentestFlags, setPendingPentestFlags] = import_react89.useState(undefined);
290063
+ const [focusIndex, setFocusIndex] = import_react87.useState(0);
290064
+ const [cwd, setCwd] = import_react87.useState(process.cwd());
290065
+ const [ctrlCPressTime, setCtrlCPressTime] = import_react87.useState(null);
290066
+ const [showExitWarning, setShowExitWarning] = import_react87.useState(false);
290067
+ const [inputKey, setInputKey] = import_react87.useState(0);
290068
+ const [showSessionsDialog, setShowSessionsDialog] = import_react87.useState(false);
290069
+ const [showShortcutsDialog, setShowShortcutsDialog] = import_react87.useState(false);
290070
+ const [showThemeDialog, setShowThemeDialog] = import_react87.useState(false);
290071
+ const [showAuthDialog, setShowAuthDialog] = import_react87.useState(false);
290072
+ const [showPentestDialog, setShowPentestDialog] = import_react87.useState(false);
290073
+ const [pendingPentestFlags, setPendingPentestFlags] = import_react87.useState(undefined);
289936
290074
  const navigableItems = ["command-input"];
289937
290075
  return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ConfigProvider, {
289938
290076
  config: appConfig,
@@ -290019,14 +290157,14 @@ function AppContent({
290019
290157
  const { toast } = useToast();
290020
290158
  const { refocusPrompt } = useFocus();
290021
290159
  const { setExternalDialogOpen } = useDialog();
290022
- import_react89.useEffect(() => {
290160
+ import_react87.useEffect(() => {
290023
290161
  checkForUpdate().then(({ updateAvailable, currentVersion, latestVersion }) => {
290024
290162
  if (!updateAvailable)
290025
290163
  return;
290026
290164
  toast(`Update available: v${currentVersion} → v${latestVersion}. Run: pensar upgrade`, "warn", 8000);
290027
290165
  });
290028
290166
  }, []);
290029
- import_react89.useEffect(() => {
290167
+ import_react87.useEffect(() => {
290030
290168
  if (route.data.type !== "base")
290031
290169
  return;
290032
290170
  if (!config3.data.responsibleUseAccepted && route.data.path !== "disclosure") {
@@ -290035,12 +290173,12 @@ function AppContent({
290035
290173
  route.navigate({ type: "base", path: "providers" });
290036
290174
  }
290037
290175
  }, [config3.data.responsibleUseAccepted, route.data]);
290038
- import_react89.useEffect(() => {
290176
+ import_react87.useEffect(() => {
290039
290177
  if (showThemeDialog || showAuthDialog || showPentestDialog) {
290040
290178
  setExternalDialogOpen(true);
290041
290179
  }
290042
290180
  }, [showThemeDialog, showAuthDialog, showPentestDialog]);
290043
- import_react89.useEffect(() => {
290181
+ import_react87.useEffect(() => {
290044
290182
  if (showExitWarning) {
290045
290183
  const timer = setTimeout(() => {
290046
290184
  setShowExitWarning(false);
@@ -290294,16 +290432,18 @@ async function main2() {
290294
290432
  initialMode: mode,
290295
290433
  children: [
290296
290434
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ConsoleThemeSync, {}, undefined, false, undefined, this),
290297
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastProvider, {
290298
- children: [
290299
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ErrorBoundary2, {
290300
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(App, {
290301
- appConfig
290302
- }, undefined, false, undefined, this)
290303
- }, undefined, false, undefined, this),
290304
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastContainer, {}, undefined, false, undefined, this)
290305
- ]
290306
- }, undefined, true, undefined, this)
290435
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(TerminalDimensionsProvider, {
290436
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastProvider, {
290437
+ children: [
290438
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ErrorBoundary2, {
290439
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(App, {
290440
+ appConfig
290441
+ }, undefined, false, undefined, this)
290442
+ }, undefined, false, undefined, this),
290443
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastContainer, {}, undefined, false, undefined, this)
290444
+ ]
290445
+ }, undefined, true, undefined, this)
290446
+ }, undefined, false, undefined, this)
290307
290447
  ]
290308
290448
  }, undefined, true, undefined, this));
290309
290449
  }