@pensar/apex 2.0.0-canary.241920ad → 2.0.0

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 (55) hide show
  1. package/README.md +0 -20
  2. package/build/agent-84enr6xn.js +22 -0
  3. package/build/{agent-7866ka7b.js → agent-x1tnsg7n.js} +10 -7
  4. package/build/{agent-aj7jpehp.js → agent-z8043nrm.js} +12 -9
  5. package/build/{apps-hse35c2d.js → apps-gdze0s68.js} +18 -15
  6. package/build/{auth-15rkvgam.js → auth-24ca1qwx.js} +19 -16
  7. package/build/authentication-0k43jay4.js +22 -0
  8. package/build/blackboxAgent-76tnwwg7.js +22 -0
  9. package/build/{blackboxPentest-vmtnnp5d.js → blackboxPentest-xwc031xm.js} +16 -13
  10. package/build/{cli-23xtyah8.js → cli-0v9x0eby.js} +1 -1
  11. package/build/cli-1yavz2pb.js +17 -0
  12. package/build/{cli-6gge86w5.js → cli-31cara07.js} +6 -8
  13. package/build/cli-3knnkdps.js +666 -0
  14. package/build/{cli-cbw2rmv7.js → cli-5fr9k6m4.js} +35 -58
  15. package/build/{cli-78s9w64j.js → cli-948dk60p.js} +1 -1
  16. package/build/{cli-k1vsv3qh.js → cli-a20jcpmp.js} +1 -1
  17. package/build/{cli-0svsmc2c.js → cli-cb5va0cs.js} +1 -10
  18. package/build/{cli-rtbry75t.js → cli-h6nw89zf.js} +1 -1
  19. package/build/{cli-5h1kv0v4.js → cli-h825qzmd.js} +53 -1492
  20. package/build/{cli-gtepvg8s.js → cli-k8mvghe1.js} +921 -444
  21. package/build/{cli-4dpc999m.js → cli-mswm4k81.js} +1 -11
  22. package/build/{cli-zyk3xsth.js → cli-ntd42071.js} +1 -1
  23. package/build/{cli-mb837pv4.js → cli-pkdjamer.js} +5 -15
  24. package/build/cli-s1nckt4k.js +20 -0
  25. package/build/{cli-4ez6yssj.js → cli-sw5swz40.js} +3 -3
  26. package/build/{cli-ft17f9nh.js → cli-wdmqkshz.js} +2 -2
  27. package/build/{cli-demg7sj2.js → cli-zpvmaxem.js} +2 -2
  28. package/build/{cli-r0s5br0a.js → cli-zvq4gy61.js} +6 -13
  29. package/build/cli.js +45 -105
  30. package/build/{config-bb6q79q0.js → config-cmq1cxz3.js} +3 -3
  31. package/build/{doctor-tkz0a0g4.js → doctor-2bkpddws.js} +1 -8
  32. package/build/{fixes-krvbkbey.js → fixes-a4qscvkx.js} +18 -15
  33. package/build/{index-pamhzcx3.js → index-0fnbx38r.js} +14 -20
  34. package/build/{index-ah3cm7hf.js → index-2a1x5nnv.js} +3 -3
  35. package/build/{index-v4sz6cee.js → index-48pjf9d2.js} +124 -76
  36. package/build/{index-tknvj68q.js → index-54ep0ery.js} +12 -9
  37. package/build/{index-wsp4kqtm.js → index-aymt8k9w.js} +2 -2
  38. package/build/{index-a9ea9c1q.js → index-hfhkjj2g.js} +11 -8
  39. package/build/{index-4gk224ac.js → index-s17r2akv.js} +4 -4
  40. package/build/{issues-m2me70rs.js → issues-5pnrspt7.js} +18 -15
  41. package/build/{logs-rxf1a0be.js → logs-1mfm901x.js} +18 -15
  42. package/build/{offesecAgent-hmxcpch7.js → offesecAgent-mrbyc93d.js} +11 -8
  43. package/build/pentest-wy4eeagc.js +31 -0
  44. package/build/{pentests-201vfsn6.js → pentests-htmtq66d.js} +18 -15
  45. package/build/{targetedPentest-85b1dndy.js → targetedPentest-cpbd87rc.js} +12 -9
  46. package/build/threatModel-9n56z6a6.js +29 -0
  47. package/build/{uninstall-qa8jvrj1.js → uninstall-6y9dkgyt.js} +1 -1
  48. package/build/{upload-p58nxxvf.js → upload-7wtbr768.js} +1 -8
  49. package/build/{utils-hsde107p.js → utils-trqnyj77.js} +8 -6
  50. package/package.json +1 -1
  51. package/build/agent-mjyx1amj.js +0 -19
  52. package/build/authentication-b8p1afqq.js +0 -19
  53. package/build/blackboxAgent-z1h2cgyg.js +0 -19
  54. package/build/pentest-r6hfzf8n.js +0 -28
  55. package/build/threatModel-hbpz15y7.js +0 -26
@@ -4,7 +4,7 @@ import {
4
4
  init_auth,
5
5
  init_constants,
6
6
  signGatewayRequest
7
- } from "./cli-78s9w64j.js";
7
+ } from "./cli-948dk60p.js";
8
8
  import {
9
9
  AISDKError,
10
10
  APICallError,
@@ -32,7 +32,6 @@ import {
32
32
  delay,
33
33
  executeTool,
34
34
  exports_external,
35
- exports_external1 as exports_external2,
36
35
  gateway,
37
36
  getErrorMessage,
38
37
  getErrorMessage1 as getErrorMessage2,
@@ -43,7 +42,6 @@ import {
43
42
  init_stream,
44
43
  init_v3,
45
44
  init_v4,
46
- init_zod,
47
45
  isAbortError,
48
46
  isUrlSupported,
49
47
  lazySchema,
@@ -57,24 +55,17 @@ import {
57
55
  validateDownloadUrl,
58
56
  validateTypes,
59
57
  withUserAgentSuffix,
60
- zodSchema,
61
- zod_default
58
+ zodSchema
62
59
  } from "./cli-e6rgwtpb.js";
63
60
  import {
64
61
  config,
65
62
  init_config
66
- } from "./cli-rtbry75t.js";
63
+ } from "./cli-h6nw89zf.js";
67
64
  import {
68
- getCurrentVersion,
69
- init_installation
70
- } from "./cli-k1vsv3qh.js";
71
- import {
72
- __callDispose,
73
65
  __commonJS,
74
66
  __esm,
75
67
  __require,
76
- __toESM,
77
- __using
68
+ __toESM
78
69
  } from "./cli-8rxa073f.js";
79
70
 
80
71
  // node_modules/ai/dist/index.mjs
@@ -8785,20 +8776,6 @@ var init_models = __esm(() => {
8785
8776
  ];
8786
8777
  });
8787
8778
 
8788
- // src/core/util/lazyLogger.ts
8789
- function scopedLogger(factory) {
8790
- let instance;
8791
- const get = () => instance ??= factory();
8792
- return new Proxy({}, {
8793
- get(_target, prop) {
8794
- const inst = get();
8795
- const value = inst[prop];
8796
- return typeof value === "function" ? value.bind(inst) : value;
8797
- }
8798
- });
8799
- }
8800
- var init_lazyLogger = () => {};
8801
-
8802
8779
  // node_modules/@ai-sdk/provider-utils/dist/index.mjs
8803
8780
  function combineHeaders(...headers) {
8804
8781
  return headers.reduce((combinedHeaders, currentHeaders) => ({
@@ -42457,7 +42434,7 @@ function wrapStreamWithErrorHandler(originalStream, messagesContainer, opts, mod
42457
42434
  if (!isCtxError && isStreamIdleTimeoutError(error) && idleResumeCount < MAX_IDLE_RESUME_RETRIES && messagesContainer.current.length > 0) {
42458
42435
  const nextIdleCount = idleResumeCount + 1;
42459
42436
  if (!silent) {
42460
- log.warn(`Stream stalled (attempt ${nextIdleCount}/${MAX_IDLE_RESUME_RETRIES}), resuming with ${messagesContainer.current.length} messages: ${errorMessage}`);
42437
+ console.warn(`Stream stalled (attempt ${nextIdleCount}/${MAX_IDLE_RESUME_RETRIES}), resuming with ${messagesContainer.current.length} messages: ${errorMessage}`);
42461
42438
  }
42462
42439
  const retriedStream = streamResponse({
42463
42440
  ...opts,
@@ -42473,7 +42450,7 @@ function wrapStreamWithErrorHandler(originalStream, messagesContainer, opts, mod
42473
42450
  const nextRetryCount = rateLimitRetryCount + 1;
42474
42451
  const delayMs = Math.min(1000 * nextRetryCount, 30000);
42475
42452
  if (!silent) {
42476
- log.warn(`Rate limit error (attempt ${nextRetryCount}/${MAX_RATE_LIMIT_RETRIES}), waiting ${delayMs}ms: ${errorMessage}`);
42453
+ console.warn(`Rate limit error (attempt ${nextRetryCount}/${MAX_RATE_LIMIT_RETRIES}), waiting ${delayMs}ms: ${errorMessage}`);
42477
42454
  }
42478
42455
  await new Promise((resolve4) => setTimeout(resolve4, delayMs));
42479
42456
  const retriedStream = streamResponse({
@@ -42505,7 +42482,7 @@ function wrapStreamWithErrorHandler(originalStream, messagesContainer, opts, mod
42505
42482
  let postReactiveDepth = opts._restartDepth ?? 0;
42506
42483
  if (fitted.fitsBudget && fitted.modified) {
42507
42484
  if (!silent) {
42508
- log.warn(`Context length error — Layer 1+2 reduced to ~${fitted.estimatedInputTokens} tokens, retrying`);
42485
+ console.warn(`Context length error — Layer 1+2 reduced to ~${fitted.estimatedInputTokens} tokens, retrying`);
42509
42486
  }
42510
42487
  try {
42511
42488
  const retried = streamResponse({
@@ -42527,7 +42504,7 @@ function wrapStreamWithErrorHandler(originalStream, messagesContainer, opts, mod
42527
42504
  }
42528
42505
  const messagesForSummary = messagesContainer.current;
42529
42506
  if (!silent) {
42530
- log.warn(`Context length error — summarizing ${messagesForSummary.length} messages`);
42507
+ console.warn(`Context length error — summarizing ${messagesForSummary.length} messages`);
42531
42508
  }
42532
42509
  try {
42533
42510
  const summarizationStream = createSummarizationStream(messagesForSummary, { ...opts, _restartDepth: postReactiveDepth }, model);
@@ -42540,7 +42517,7 @@ function wrapStreamWithErrorHandler(originalStream, messagesContainer, opts, mod
42540
42517
  }
42541
42518
  if (!silent) {
42542
42519
  const sumMsg = summarizeError instanceof Error ? summarizeError.message : String(summarizeError);
42543
- log.warn(`Layer 3 summarization failed (${sumMsg}). Falling back to minimal-context restart.`);
42520
+ console.error(`Layer 3 summarization failed (${sumMsg}). Falling back to minimal-context restart.`);
42544
42521
  }
42545
42522
  opts.onSummarized?.("");
42546
42523
  const minimalPrompt = typeof opts.prompt === "string" && opts.prompt.length > 0 ? opts.prompt.slice(0, 4000) : MINIMAL_RESTART_PROMPT;
@@ -42556,9 +42533,7 @@ function wrapStreamWithErrorHandler(originalStream, messagesContainer, opts, mod
42556
42533
  }
42557
42534
  } else {
42558
42535
  if (!silent) {
42559
- log.error("Non-recoverable stream error, re-throwing", {
42560
- error: errorMessage
42561
- });
42536
+ console.error("Non-recoverable stream error, re-throwing:", errorMessage);
42562
42537
  }
42563
42538
  throw error;
42564
42539
  }
@@ -42645,13 +42620,13 @@ function streamResponse(opts) {
42645
42620
  fittedMessages = fitted.messages;
42646
42621
  proactiveFitFailed = !fitted.fitsBudget;
42647
42622
  if (fitted.modified && !silent) {
42648
- log.warn(`Proactive context fit: compacted messages to ~${fitted.estimatedInputTokens} tokens (fits=${fitted.fitsBudget})`);
42623
+ console.warn(`Proactive context fit: compacted messages to ~${fitted.estimatedInputTokens} tokens (fits=${fitted.fitsBudget})`);
42649
42624
  }
42650
42625
  }
42651
42626
  const messagesContainer = { current: fittedMessages || [] };
42652
42627
  if (proactiveFitFailed && fittedMessages) {
42653
42628
  if (!silent) {
42654
- log.warn(`Proactive context fit returned fitsBudget=false on ${fittedMessages.length} messages — escalating to summarization before send`);
42629
+ console.warn(`Proactive context fit returned fitsBudget=false on ${fittedMessages.length} messages — escalating to summarization before send`);
42655
42630
  }
42656
42631
  return wrapStreamWithErrorHandler(createSummarizationStream(fittedMessages, opts, providerModel), messagesContainer, opts, providerModel, silent);
42657
42632
  }
@@ -42744,17 +42719,16 @@ function streamResponse(opts) {
42744
42719
  }) => {
42745
42720
  try {
42746
42721
  if (!silent) {
42747
- log.debug(`Repairing tool call: ${toolCall.toolName}`, {
42748
- error: error.message || String(error)
42749
- });
42722
+ console.log(`\uD83D\uDD27 Repairing tool call: ${toolCall.toolName}`);
42723
+ console.log(` Error: ${error.message || error}`);
42750
42724
  if (error.message && (error.message.includes("severity") || error.message.includes("riskLevel"))) {
42751
- log.debug("Enum validation error tool call repair will normalize the value");
42725
+ console.log(` Note: This appears to be an enum validation error. Tool call repair will normalize the value.`);
42752
42726
  }
42753
42727
  }
42754
42728
  const tool6 = tools2[toolCall.toolName];
42755
42729
  if (!tool6 || !tool6.inputSchema) {
42756
42730
  if (!silent) {
42757
- log.warn(`Cannot repair tool call: ${toolCall.toolName} not found or has no schema`);
42731
+ console.error(`Cannot repair tool call: ${toolCall.toolName} not found or has no schema`);
42758
42732
  }
42759
42733
  return null;
42760
42734
  }
@@ -42818,16 +42792,14 @@ function streamResponse(opts) {
42818
42792
  }
42819
42793
  if (repairedArgs === undefined || repairedArgs === null) {
42820
42794
  if (!silent) {
42821
- log.warn(`Tool call repair for "${toolCall.toolName}" produced no valid output`);
42795
+ console.error(`Tool call repair for "${toolCall.toolName}" produced no valid output`);
42822
42796
  }
42823
42797
  return null;
42824
42798
  }
42825
42799
  return { ...toolCall, input: JSON.stringify(repairedArgs) };
42826
42800
  } catch (repairError) {
42827
42801
  if (!silent) {
42828
- log.warn("Error repairing tool call", {
42829
- error: String(repairError)
42830
- });
42802
+ console.error("Error repairing tool call:", repairError instanceof Error ? repairError.message : String(repairError));
42831
42803
  }
42832
42804
  return null;
42833
42805
  }
@@ -42840,14 +42812,12 @@ function streamResponse(opts) {
42840
42812
  const outerErrorMessage = error instanceof Error ? error.message : String(error);
42841
42813
  if (isContextLengthError) {
42842
42814
  if (!silent) {
42843
- log.warn(`Context length error, summarizing ${messagesContainer.current.length} messages`, { error: outerErrorMessage });
42815
+ console.warn(`Context length error, summarizing ${messagesContainer.current.length} messages: `, outerErrorMessage);
42844
42816
  }
42845
42817
  return wrapStreamWithErrorHandler(createSummarizationStream(messagesContainer.current, opts, providerModel), messagesContainer, opts, providerModel, silent);
42846
42818
  }
42847
42819
  if (!silent) {
42848
- log.error("Non-context length error, re-throwing", {
42849
- error: outerErrorMessage
42850
- });
42820
+ console.error("Non-context length error, re-throwing", outerErrorMessage);
42851
42821
  }
42852
42822
  throw error;
42853
42823
  }
@@ -42920,17 +42890,14 @@ async function generateObjectResponse(opts) {
42920
42890
  }
42921
42891
  throw lastError;
42922
42892
  }
42923
- var log, DEFAULT_OPENAI_REASONING_EFFORT = "medium", OPENAI_REASONING_MODEL_IDS, _usageCallback = null, MAX_RATE_LIMIT_RETRIES = 20, MAX_IDLE_RESUME_RETRIES = 3, STREAM_IDLE_TIMEOUT_MS, StreamIdleTimeoutError, MAX_OBJECT_RATE_LIMIT_RETRIES = 8, ContextLengthError, ContextLengthExhaustedError, MAX_RESTART_DEPTH = 3, MAX_TOOL_INPUT_CHARS = 8000, MAX_SCHEMA_CHARS = 6000, MINIMAL_RESTART_PROMPT = "Continue the previous task. Earlier context was discarded due to repeated context-length errors.";
42893
+ var DEFAULT_OPENAI_REASONING_EFFORT = "medium", OPENAI_REASONING_MODEL_IDS, _usageCallback = null, MAX_RATE_LIMIT_RETRIES = 20, MAX_IDLE_RESUME_RETRIES = 3, STREAM_IDLE_TIMEOUT_MS, StreamIdleTimeoutError, MAX_OBJECT_RATE_LIMIT_RETRIES = 8, ContextLengthError, ContextLengthExhaustedError, MAX_RESTART_DEPTH = 3, MAX_TOOL_INPUT_CHARS = 8000, MAX_SCHEMA_CHARS = 6000, MINIMAL_RESTART_PROMPT = "Continue the previous task. Earlier context was discarded due to repeated context-length errors.";
42924
42894
  var init_ai = __esm(() => {
42925
42895
  init_dist4();
42926
- init_structured();
42927
42896
  init_observability();
42928
- init_lazyLogger();
42929
42897
  init_caching();
42930
42898
  init_contextManagement();
42931
42899
  init_models();
42932
42900
  init_utils();
42933
- log = scopedLogger(() => createLogger("ai"));
42934
42901
  OPENAI_REASONING_MODEL_IDS = new Set([
42935
42902
  "gpt-5",
42936
42903
  "gpt-5-2025-08-07",
@@ -42970,1407 +42937,6 @@ var init_ai = __esm(() => {
42970
42937
  };
42971
42938
  });
42972
42939
 
42973
- // src/core/ai/index.ts
42974
- var init_ai2 = __esm(() => {
42975
- init_ai();
42976
- init_models();
42977
- init_utils();
42978
- });
42979
-
42980
- // src/util/name.ts
42981
- function generateRandomName() {
42982
- const adj = adjectives[Math.floor(Math.random() * adjectives.length)] ?? "swift";
42983
- const noun = nouns[Math.floor(Math.random() * nouns.length)] ?? "falcon";
42984
- return `${adj}-${noun}`;
42985
- }
42986
- async function generateSessionName(opts) {
42987
- const { targets, userMessage, model, authConfig, abortSignal } = opts;
42988
- const contextParts = [];
42989
- if (targets.length > 0) {
42990
- contextParts.push(`Target(s): ${targets.join(", ")}`);
42991
- }
42992
- if (userMessage) {
42993
- contextParts.push(`User objective: ${userMessage}`);
42994
- }
42995
- if (contextParts.length === 0)
42996
- return null;
42997
- const prompt = [
42998
- "Generate a short, descriptive name for a penetration testing session.",
42999
- "The name should be 2-4 lowercase words separated by hyphens.",
43000
- "It should capture the key aspect of the target or task — e.g. 'acme-api-pentest', 'login-auth-bypass', 'ecommerce-checkout-test'.",
43001
- "",
43002
- ...contextParts
43003
- ].join(`
43004
- `);
43005
- try {
43006
- const result = await generateObjectResponse({
43007
- model,
43008
- schema: sessionNameSchema,
43009
- prompt,
43010
- maxTokens: 50,
43011
- temperature: 0.7,
43012
- authConfig,
43013
- abortSignal
43014
- });
43015
- if (!result?.name)
43016
- return null;
43017
- const name29 = result.name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 50);
43018
- return name29 || null;
43019
- } catch {
43020
- return null;
43021
- }
43022
- }
43023
- var adjectives, nouns, sessionNameSchema;
43024
- var init_name = __esm(() => {
43025
- init_zod();
43026
- init_ai2();
43027
- adjectives = [
43028
- "swift",
43029
- "bright",
43030
- "calm",
43031
- "bold",
43032
- "keen",
43033
- "noble",
43034
- "quick",
43035
- "sharp",
43036
- "vivid",
43037
- "warm",
43038
- "agile",
43039
- "brave",
43040
- "clever",
43041
- "daring",
43042
- "eager",
43043
- "fierce",
43044
- "gentle",
43045
- "humble",
43046
- "jolly",
43047
- "lively",
43048
- "merry",
43049
- "nimble",
43050
- "proud",
43051
- "quiet",
43052
- "rapid",
43053
- "serene",
43054
- "sturdy",
43055
- "tender",
43056
- "valiant",
43057
- "witty",
43058
- "zealous"
43059
- ];
43060
- nouns = [
43061
- "falcon",
43062
- "wolf",
43063
- "hawk",
43064
- "bear",
43065
- "lion",
43066
- "tiger",
43067
- "eagle",
43068
- "raven",
43069
- "phoenix",
43070
- "dragon",
43071
- "panther",
43072
- "cobra",
43073
- "viper",
43074
- "shark",
43075
- "orca",
43076
- "mantis",
43077
- "spider",
43078
- "scorpion",
43079
- "hydra",
43080
- "griffin",
43081
- "sphinx",
43082
- "kraken",
43083
- "cipher",
43084
- "nexus",
43085
- "prism",
43086
- "vector",
43087
- "matrix",
43088
- "pulse",
43089
- "surge",
43090
- "flux"
43091
- ];
43092
- sessionNameSchema = exports_external2.object({
43093
- name: exports_external2.string().describe("A short, descriptive session name (2-4 words, lowercase, hyphenated)")
43094
- });
43095
- });
43096
-
43097
- // src/core/credentials/manager.ts
43098
- import { randomBytes } from "crypto";
43099
- function generateCredentialId() {
43100
- return `cred_${randomBytes(8).toString("hex")}`;
43101
- }
43102
- function inferType(cred) {
43103
- const hasPwd = !!cred.password;
43104
- const hasApiKey = !!cred.apiKey;
43105
- const hasBearer = !!cred.tokens?.bearerToken;
43106
- const hasHeaders = !!cred.tokens?.customHeaders && Object.keys(cred.tokens.customHeaders).length > 0;
43107
- const hasCookies = !!cred.tokens?.cookies;
43108
- const count = (hasPwd ? 1 : 0) + (hasApiKey ? 1 : 0) + (hasBearer ? 1 : 0) + (hasHeaders ? 1 : 0) + (hasCookies ? 1 : 0);
43109
- if (count > 1)
43110
- return "composite";
43111
- if (hasPwd)
43112
- return "username-password";
43113
- if (hasApiKey)
43114
- return "api-key";
43115
- if (hasBearer)
43116
- return "bearer-token";
43117
- if (hasHeaders)
43118
- return "custom-headers";
43119
- if (hasCookies)
43120
- return "cookies";
43121
- return "username-password";
43122
- }
43123
- function toReference(stored) {
43124
- const ref = {
43125
- id: stored.id,
43126
- type: stored.type
43127
- };
43128
- if (stored.label)
43129
- ref.label = stored.label;
43130
- if (stored.role)
43131
- ref.role = stored.role;
43132
- if (stored.username)
43133
- ref.username = stored.username;
43134
- if (stored.loginUrl)
43135
- ref.loginUrl = stored.loginUrl;
43136
- if (stored.tokens?.customHeaders) {
43137
- ref.customHeaderKeys = Object.keys(stored.tokens.customHeaders);
43138
- }
43139
- const ctx = stored.metadata?.context;
43140
- if (typeof ctx === "string" && ctx)
43141
- ref.context = ctx;
43142
- return ref;
43143
- }
43144
-
43145
- class CredentialManager {
43146
- store = new Map;
43147
- findDuplicate(candidate) {
43148
- for (const [id, existing] of this.store) {
43149
- if (existing.username === candidate.username && existing.password === candidate.password && existing.apiKey === candidate.apiKey && existing.loginUrl === candidate.loginUrl && existing.tokens?.bearerToken === candidate.tokens?.bearerToken && existing.tokens?.cookies === candidate.tokens?.cookies && existing.tokens?.sessionToken === candidate.tokens?.sessionToken && JSON.stringify(existing.tokens?.customHeaders) === JSON.stringify(candidate.tokens?.customHeaders)) {
43150
- return id;
43151
- }
43152
- }
43153
- return;
43154
- }
43155
- add(input) {
43156
- const id = input.id ?? generateCredentialId();
43157
- const type = input.type ?? inferType(input);
43158
- const stored = { ...input, id, type };
43159
- this.store.set(id, stored);
43160
- return id;
43161
- }
43162
- addFromAuthCredentials(creds, extra) {
43163
- const candidate = {
43164
- username: creds.username,
43165
- password: creds.password,
43166
- apiKey: creds.apiKey,
43167
- loginUrl: creds.loginUrl,
43168
- additionalFields: creds.additionalFields,
43169
- tokens: creds.tokens,
43170
- label: extra?.label,
43171
- role: extra?.role ?? creds.role,
43172
- metadata: creds.context ? { context: creds.context } : undefined
43173
- };
43174
- const existingId = this.findDuplicate(candidate);
43175
- if (existingId)
43176
- return existingId;
43177
- return this.add(candidate);
43178
- }
43179
- resolve(credentialId) {
43180
- return this.store.get(credentialId);
43181
- }
43182
- getReference(credentialId) {
43183
- const stored = this.store.get(credentialId);
43184
- if (!stored)
43185
- return;
43186
- return toReference(stored);
43187
- }
43188
- listReferences() {
43189
- return Array.from(this.store.values()).map(toReference);
43190
- }
43191
- listCredentialsWithHeaders() {
43192
- const out = [];
43193
- for (const stored of this.store.values()) {
43194
- const headers = stored.tokens?.customHeaders;
43195
- if (headers && Object.keys(headers).length > 0) {
43196
- out.push({ tokens: { customHeaders: { ...headers } } });
43197
- }
43198
- }
43199
- return out;
43200
- }
43201
- remove(credentialId) {
43202
- return this.store.delete(credentialId);
43203
- }
43204
- get size() {
43205
- return this.store.size;
43206
- }
43207
- clear() {
43208
- this.store.clear();
43209
- }
43210
- toAuthCredentials(credentialId) {
43211
- const stored = this.resolve(credentialId);
43212
- if (!stored)
43213
- return;
43214
- const result = {};
43215
- if (stored.username)
43216
- result.username = stored.username;
43217
- if (stored.password)
43218
- result.password = stored.password;
43219
- if (stored.apiKey)
43220
- result.apiKey = stored.apiKey;
43221
- if (stored.loginUrl)
43222
- result.loginUrl = stored.loginUrl;
43223
- if (stored.additionalFields)
43224
- result.additionalFields = stored.additionalFields;
43225
- if (stored.tokens)
43226
- result.tokens = { ...stored.tokens };
43227
- return result;
43228
- }
43229
- formatForPrompt() {
43230
- const refs = this.listReferences();
43231
- if (refs.length === 0)
43232
- return "";
43233
- const lines = refs.map((ref) => {
43234
- const parts = [`- Credential ID: ${ref.id}`];
43235
- if (ref.label)
43236
- parts.push(` Label: ${ref.label}`);
43237
- parts.push(` Type: ${ref.type}`);
43238
- if (ref.role)
43239
- parts.push(` Role: ${ref.role}`);
43240
- if (ref.username)
43241
- parts.push(` Username: ${ref.username}`);
43242
- if (ref.loginUrl)
43243
- parts.push(` Login URL: ${ref.loginUrl}`);
43244
- if (ref.customHeaderKeys?.length) {
43245
- parts.push(` Header keys: ${ref.customHeaderKeys.join(", ")}`);
43246
- }
43247
- if (ref.context)
43248
- parts.push(` Context: ${ref.context}`);
43249
- return parts.join(`
43250
- `);
43251
- });
43252
- return `<available_credentials>
43253
- The following credentials are available. To use a credential, pass its ID to the appropriate tool.
43254
- Do NOT ask the user for passwords or secrets — they are resolved automatically from the credential ID.
43255
-
43256
- ${lines.join(`
43257
-
43258
- `)}
43259
- </available_credentials>`;
43260
- }
43261
- }
43262
- var init_manager = () => {};
43263
-
43264
- // src/core/credentials/index.ts
43265
- var init_credentials = __esm(() => {
43266
- init_manager();
43267
- });
43268
-
43269
- // src/core/id/id.ts
43270
- import { randomBytes as randomBytes2 } from "crypto";
43271
- function schema(prefix) {
43272
- return zod_default.string().startsWith(prefixes[prefix]);
43273
- }
43274
- function descending(prefix, given) {
43275
- return generateID(prefix, true, given);
43276
- }
43277
- function generateID(prefix, descending2, given) {
43278
- if (!given) {
43279
- return create(prefix, descending2);
43280
- }
43281
- if (!given.startsWith(prefixes[prefix])) {
43282
- throw new Error(`ID ${given} does not start with ${prefixes[prefix]}`);
43283
- }
43284
- return given;
43285
- }
43286
- function randomBase62(length) {
43287
- const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
43288
- let result = "";
43289
- const bytes = randomBytes2(length);
43290
- for (let i = 0;i < length; i++) {
43291
- result += chars[bytes[i] % 62];
43292
- }
43293
- return result;
43294
- }
43295
- function create(prefix, descending2, timestamp) {
43296
- const currentTimestamp = timestamp ?? Date.now();
43297
- if (currentTimestamp !== lastTimestamp) {
43298
- lastTimestamp = currentTimestamp;
43299
- counter = 0;
43300
- }
43301
- counter++;
43302
- let now2 = BigInt(currentTimestamp) * BigInt(4096) + BigInt(counter);
43303
- now2 = descending2 ? ~now2 : now2;
43304
- const timeBytes = Buffer.alloc(6);
43305
- for (let i = 0;i < 6; i++) {
43306
- timeBytes[i] = Number(now2 >> BigInt(40 - 8 * i) & BigInt(255));
43307
- }
43308
- return prefixes[prefix] + "_" + timeBytes.toString("hex") + randomBase62(LENGTH - 12);
43309
- }
43310
- var prefixes, LENGTH = 26, lastTimestamp = 0, counter = 0;
43311
- var init_id = __esm(() => {
43312
- init_zod();
43313
- prefixes = {
43314
- session: "ses",
43315
- message: "msg",
43316
- permission: "per",
43317
- user: "usr",
43318
- part: "prt"
43319
- };
43320
- });
43321
-
43322
- // src/core/services/rateLimiter/index.ts
43323
- function sleep(ms) {
43324
- return new Promise((resolve4) => setTimeout(resolve4, ms));
43325
- }
43326
-
43327
- class RateLimiter {
43328
- tokens;
43329
- lastRefillTime;
43330
- rps;
43331
- bucketSize;
43332
- msPerToken;
43333
- queue;
43334
- constructor(config2) {
43335
- this.rps = config2?.requestsPerSecond;
43336
- this.bucketSize = this.rps ? 1 : 0;
43337
- this.tokens = this.bucketSize;
43338
- this.lastRefillTime = performance.now();
43339
- this.msPerToken = this.rps ? 1000 / this.rps : undefined;
43340
- this.queue = Promise.resolve();
43341
- }
43342
- async acquireSlot() {
43343
- if (!this.rps || !this.msPerToken)
43344
- return;
43345
- const previousPromise = this.queue;
43346
- let resolveCurrentRequest;
43347
- this.queue = new Promise((resolve4) => {
43348
- resolveCurrentRequest = resolve4;
43349
- });
43350
- await previousPromise;
43351
- try {
43352
- const now2 = performance.now();
43353
- this.refill(now2);
43354
- if (this.tokens < 1) {
43355
- const waitTime = (1 - this.tokens) * this.msPerToken;
43356
- await sleep(waitTime);
43357
- const nowAfterSleep = performance.now();
43358
- this.refill(nowAfterSleep);
43359
- }
43360
- this.tokens -= 1;
43361
- } finally {
43362
- resolveCurrentRequest();
43363
- }
43364
- }
43365
- refill(now2) {
43366
- if (this.tokens >= this.bucketSize) {
43367
- this.lastRefillTime = now2;
43368
- return;
43369
- }
43370
- const elapsed = now2 - this.lastRefillTime;
43371
- const tokensToAdd = elapsed / this.msPerToken;
43372
- this.tokens = Math.min(this.bucketSize, this.tokens + tokensToAdd);
43373
- this.lastRefillTime = now2;
43374
- }
43375
- isEnabled() {
43376
- return this.rps !== undefined;
43377
- }
43378
- }
43379
- var init_rateLimiter = () => {};
43380
-
43381
- // src/util/errors.ts
43382
- var NamedError;
43383
- var init_errors = __esm(() => {
43384
- init_zod();
43385
- NamedError = class NamedError extends Error {
43386
- static create(name29, data) {
43387
- const schema2 = zod_default.object({
43388
- name: zod_default.literal(name29),
43389
- data
43390
- });
43391
- const result = class extends NamedError {
43392
- data;
43393
- static Schema = schema2;
43394
- name = name29;
43395
- constructor(data2, options) {
43396
- super(name29, options);
43397
- this.data = data2;
43398
- this.name = name29;
43399
- }
43400
- static isInstance(input) {
43401
- return typeof input === "object" && input !== null && "name" in input && input.name === name29;
43402
- }
43403
- schema() {
43404
- return schema2;
43405
- }
43406
- toObject() {
43407
- return {
43408
- name: name29,
43409
- data: this.data
43410
- };
43411
- }
43412
- };
43413
- Object.defineProperty(result, "name", { value: name29 });
43414
- return result;
43415
- }
43416
- static Unknown = NamedError.create("UnknownError", zod_default.object({
43417
- message: zod_default.string()
43418
- }));
43419
- };
43420
- });
43421
-
43422
- // src/util/lock.ts
43423
- function getLock(key) {
43424
- let lock = locks.get(key);
43425
- if (!lock) {
43426
- lock = {
43427
- readers: 0,
43428
- writer: false,
43429
- waitingReaders: [],
43430
- waitingWriters: []
43431
- };
43432
- locks.set(key, lock);
43433
- }
43434
- return lock;
43435
- }
43436
- function processQueue(key) {
43437
- const lock = locks.get(key);
43438
- if (!lock || lock.writer || lock.readers > 0)
43439
- return;
43440
- if (lock.waitingWriters.length > 0) {
43441
- const nextWriter = lock.waitingWriters.shift();
43442
- nextWriter?.();
43443
- return;
43444
- }
43445
- while (lock.waitingReaders.length > 0) {
43446
- const nextReader = lock.waitingReaders.shift();
43447
- nextReader?.();
43448
- }
43449
- if (lock.readers === 0 && !lock.writer && lock.waitingReaders.length === 0 && lock.waitingWriters.length === 0) {
43450
- locks.delete(key);
43451
- }
43452
- }
43453
- async function read(key) {
43454
- const lock = getLock(key);
43455
- return new Promise((resolve4) => {
43456
- if (!lock.writer && lock.waitingWriters.length === 0) {
43457
- lock.readers++;
43458
- resolve4({
43459
- [Symbol.dispose]: () => {
43460
- lock.readers--;
43461
- processQueue(key);
43462
- }
43463
- });
43464
- } else {
43465
- lock.waitingReaders.push(() => {
43466
- lock.readers++;
43467
- resolve4({
43468
- [Symbol.dispose]: () => {
43469
- lock.readers--;
43470
- processQueue(key);
43471
- }
43472
- });
43473
- });
43474
- }
43475
- });
43476
- }
43477
- async function write(key) {
43478
- const lock = getLock(key);
43479
- return new Promise((resolve4) => {
43480
- if (!lock.writer && lock.readers === 0) {
43481
- lock.writer = true;
43482
- resolve4({
43483
- [Symbol.dispose]: () => {
43484
- lock.writer = false;
43485
- processQueue(key);
43486
- }
43487
- });
43488
- } else {
43489
- lock.waitingWriters.push(() => {
43490
- lock.writer = true;
43491
- resolve4({
43492
- [Symbol.dispose]: () => {
43493
- lock.writer = false;
43494
- processQueue(key);
43495
- }
43496
- });
43497
- });
43498
- }
43499
- });
43500
- }
43501
- var locks;
43502
- var init_lock = __esm(() => {
43503
- locks = new Map;
43504
- });
43505
-
43506
- // src/core/storage/index.ts
43507
- import fs, { readdir } from "fs/promises";
43508
- import os from "os";
43509
- import path from "path";
43510
- function getBaseDir() {
43511
- return process.env.PENSAR_DATA_DIR ?? path.join(os.homedir(), ".pensar");
43512
- }
43513
- async function write2(key, content, ext) {
43514
- const dir = getBaseDir();
43515
- const target = path.join(dir, ...key) + (ext ? ext : ".json");
43516
- return withErrorHandling(async () => {
43517
- let __stack = [];
43518
- try {
43519
- const _ = __using(__stack, await write(target), 0);
43520
- await fs.mkdir(path.dirname(target), { recursive: true });
43521
- await fs.writeFile(target, JSON.stringify(content, null, 2), "utf-8");
43522
- } catch (_catch) {
43523
- var _err = _catch, _hasErr = 1;
43524
- } finally {
43525
- __callDispose(__stack, _err, _hasErr);
43526
- }
43527
- });
43528
- }
43529
- async function createDir(key) {
43530
- const dir = getBaseDir();
43531
- const target = path.join(dir, ...key);
43532
- return withErrorHandling(async () => {
43533
- let __stack = [];
43534
- try {
43535
- const _ = __using(__stack, await write(target), 0);
43536
- await fs.mkdir(target, { recursive: true });
43537
- } catch (_catch) {
43538
- var _err = _catch, _hasErr = 1;
43539
- } finally {
43540
- __callDispose(__stack, _err, _hasErr);
43541
- }
43542
- });
43543
- }
43544
- async function writeRaw(key, content) {
43545
- const dir = getBaseDir();
43546
- const target = path.join(dir, ...key);
43547
- return withErrorHandling(async () => {
43548
- let __stack = [];
43549
- try {
43550
- const _ = __using(__stack, await write(target), 0);
43551
- const parentDir = path.dirname(target);
43552
- await fs.mkdir(parentDir, { recursive: true });
43553
- await fs.writeFile(target, content, "utf-8");
43554
- } catch (_catch) {
43555
- var _err = _catch, _hasErr = 1;
43556
- } finally {
43557
- __callDispose(__stack, _err, _hasErr);
43558
- }
43559
- });
43560
- }
43561
- async function read2(key, ext) {
43562
- const dir = getBaseDir();
43563
- const target = path.join(dir, ...key) + (ext ? ext : ".json");
43564
- return withErrorHandling(async () => {
43565
- let __stack = [];
43566
- try {
43567
- const _ = __using(__stack, await read(target), 0);
43568
- const text2 = await fs.readFile(target, "utf-8");
43569
- const result = ext ? text2 : JSON.parse(text2);
43570
- return result;
43571
- } catch (_catch) {
43572
- var _err = _catch, _hasErr = 1;
43573
- } finally {
43574
- __callDispose(__stack, _err, _hasErr);
43575
- }
43576
- });
43577
- }
43578
- async function update(key, fn, ext) {
43579
- const dir = getBaseDir();
43580
- const target = path.join(dir, ...key) + (ext ? ext : ".json");
43581
- return withErrorHandling(async () => {
43582
- let __stack = [];
43583
- try {
43584
- const _ = __using(__stack, await write(target), 0);
43585
- const text2 = await fs.readFile(target, "utf-8");
43586
- const content = ext ? text2 : JSON.parse(text2);
43587
- fn(content);
43588
- await fs.writeFile(target, JSON.stringify(content, null, 2), "utf-8");
43589
- return content;
43590
- } catch (_catch) {
43591
- var _err = _catch, _hasErr = 1;
43592
- } finally {
43593
- __callDispose(__stack, _err, _hasErr);
43594
- }
43595
- });
43596
- }
43597
- async function withErrorHandling(body) {
43598
- return body().catch((e) => {
43599
- if (!(e instanceof Error))
43600
- throw e;
43601
- const errnoExcpetion = e;
43602
- if (errnoExcpetion.code === "ENOENT") {
43603
- throw new NotFoundError({
43604
- message: `Resource not found: ${errnoExcpetion.path}`
43605
- });
43606
- }
43607
- throw e;
43608
- });
43609
- }
43610
- async function listFilesRecursively(dir) {
43611
- const entries = await readdir(dir, { withFileTypes: true });
43612
- const files = [];
43613
- for (const entry of entries) {
43614
- const fullPath = path.join(dir, entry.name);
43615
- if (entry.isDirectory()) {
43616
- files.push(...await listFilesRecursively(fullPath));
43617
- } else {
43618
- files.push(fullPath);
43619
- }
43620
- }
43621
- return files;
43622
- }
43623
- async function list(prefix) {
43624
- const dir = getBaseDir();
43625
- const targetDir = path.join(dir, ...prefix);
43626
- try {
43627
- const files = await listFilesRecursively(targetDir);
43628
- const result = files.map((filePath) => {
43629
- const relativePath = path.relative(targetDir, filePath);
43630
- return [...prefix, ...relativePath.slice(0, -5).split(path.sep)];
43631
- });
43632
- result.sort();
43633
- return result;
43634
- } catch {
43635
- return [];
43636
- }
43637
- }
43638
- var NotFoundError;
43639
- var init_storage = __esm(() => {
43640
- init_zod();
43641
- init_errors();
43642
- init_lock();
43643
- NotFoundError = NamedError.create("NotFoundError", zod_default.object({
43644
- message: zod_default.string()
43645
- }));
43646
- });
43647
-
43648
- // src/core/toolset/index.ts
43649
- var ToolsetStateSchema;
43650
- var init_toolset = __esm(() => {
43651
- init_zod();
43652
- ToolsetStateSchema = exports_external2.object({
43653
- baseToolsetId: exports_external2.string(),
43654
- enabledTools: exports_external2.record(exports_external2.string(), exports_external2.boolean()),
43655
- lastModified: exports_external2.number()
43656
- });
43657
- });
43658
-
43659
- // src/core/session/index.ts
43660
- import { existsSync, readFileSync } from "fs";
43661
- import os2 from "os";
43662
- import path2 from "path";
43663
- function resolveSmtpConfig(explicit) {
43664
- if (explicit)
43665
- return explicit;
43666
- const fromAddress = process.env.OUTBOUND_EMAIL;
43667
- const resendKey = process.env.RESEND_API_KEY;
43668
- if (resendKey) {
43669
- return {
43670
- host: "smtp.resend.com",
43671
- port: 465,
43672
- username: "resend",
43673
- password: resendKey,
43674
- tls: true,
43675
- fromAddress
43676
- };
43677
- }
43678
- const host = process.env.SMTP_HOST;
43679
- const port = process.env.SMTP_PORT;
43680
- const username = process.env.SMTP_USERNAME;
43681
- const password = process.env.SMTP_PASSWORD;
43682
- if (host && port && username && password) {
43683
- return {
43684
- host,
43685
- port: parseInt(port, 10),
43686
- username,
43687
- password,
43688
- tls: process.env.SMTP_TLS !== "false",
43689
- fromAddress
43690
- };
43691
- }
43692
- return;
43693
- }
43694
- function getPensarDir() {
43695
- return path2.join(os2.homedir(), ".pensar");
43696
- }
43697
- function getSessionsDir() {
43698
- return path2.join(getPensarDir(), "sessions");
43699
- }
43700
- function getSessionRoot(id) {
43701
- return path2.join(getSessionsDir(), id);
43702
- }
43703
- async function createSessionDirs(input) {
43704
- const { session } = input;
43705
- await createDir(["sessions", session.id]);
43706
- await createDir(["sessions", session.id, "findings"]);
43707
- await createDir(["sessions", session.id, "scratchpad"]);
43708
- await createDir(["sessions", session.id, "logs"]);
43709
- await createDir(["sessions", session.id, "pocs"]);
43710
- const startTime = new Date().toISOString();
43711
- const readme = generateSessionReadme(session);
43712
- await writeRaw(["sessions", session.id, "README.md"], readme);
43713
- console.info("created session", session.id);
43714
- }
43715
- function generateSessionReadme(session) {
43716
- return `# Penetration Test Session
43717
-
43718
- **Session ID:** ${session.id}
43719
- **Target:** ${session.targets}
43720
- **Objective:** ${session.config?.outcomeGuidance}
43721
- **Started:** ${session.time.created}
43722
-
43723
- ## Directory Structure
43724
-
43725
- - \`findings/\` - Security findings and vulnerabilities
43726
- - \`scratchpad/\` - Notes and temporary data during testing
43727
- - \`logs/\` - Execution logs and command outputs
43728
- - \`pocs/\` - Proof-of-concept exploit scripts
43729
- - \`session.json\` - Session metadata
43730
-
43731
- ## Findings
43732
-
43733
- Security findings will be documented in the \`findings/\` directory as individual files.
43734
-
43735
- ## Status
43736
-
43737
- Testing in progress...
43738
- `;
43739
- }
43740
- function normalizeDeprecatedHeaders(config2) {
43741
- if (!config2)
43742
- return config2;
43743
- if (config2.offensiveHeaders == null) {
43744
- const { offensiveHeaders: _drop, ...rest2 } = config2;
43745
- return rest2;
43746
- }
43747
- const { offensiveHeaders, ...rest } = config2;
43748
- const restWithHeaders = rest;
43749
- if (restWithHeaders.headers !== undefined) {
43750
- return restWithHeaders;
43751
- }
43752
- const oh = offensiveHeaders;
43753
- if (oh.mode === "none") {
43754
- return { ...restWithHeaders, headers: {} };
43755
- }
43756
- let headers = {};
43757
- if (oh.mode === "default")
43758
- headers = { ...DEFAULT_HEADER_RECORD };
43759
- if (oh.headers)
43760
- headers = { ...headers, ...oh.headers };
43761
- return { ...restWithHeaders, headers };
43762
- }
43763
- function migrateLegacySessionData(input) {
43764
- if (!input || typeof input !== "object")
43765
- return input;
43766
- const root = input;
43767
- const config2 = root.config;
43768
- if (!config2 || typeof config2 !== "object")
43769
- return input;
43770
- const cfg = config2;
43771
- if (!("offensiveHeaders" in cfg))
43772
- return input;
43773
- return { ...root, config: normalizeDeprecatedHeaders(cfg) };
43774
- }
43775
- async function create2(input) {
43776
- const name29 = input.name ?? generateRandomName();
43777
- const normalizedConfig = normalizeDeprecatedHeaders(input.config);
43778
- const id = `${input.prefix ? input.prefix : ""}` + descending("session", input.id);
43779
- const rootPath = getSessionRoot(id);
43780
- const findingsPath = path2.join(rootPath, "findings");
43781
- const scratchpadPath = path2.join(rootPath, "scratchpad");
43782
- const logsPath = path2.join(rootPath, "logs");
43783
- const pocsPath = path2.join(rootPath, "pocs");
43784
- const rateLimiter = new RateLimiter({
43785
- requestsPerSecond: normalizedConfig?.requestsPerSecond
43786
- });
43787
- let credentialManager;
43788
- if (normalizedConfig?.authCredentials) {
43789
- credentialManager = new CredentialManager;
43790
- const creds = Array.isArray(normalizedConfig.authCredentials) ? normalizedConfig.authCredentials : [normalizedConfig.authCredentials];
43791
- for (const cred of creds) {
43792
- credentialManager.addFromAuthCredentials(cred);
43793
- }
43794
- }
43795
- const smtpConfig = resolveSmtpConfig(normalizedConfig?.smtpConfig);
43796
- let snapshotHeaders;
43797
- if (normalizedConfig?.headers !== undefined) {
43798
- snapshotHeaders = { ...normalizedConfig.headers };
43799
- } else {
43800
- const { config: appConfig } = await import("./index-ah3cm7hf.js");
43801
- const cfg = await appConfig.get();
43802
- snapshotHeaders = cfg.defaultHeaders ? { ...cfg.defaultHeaders } : { ...DEFAULT_HEADER_RECORD };
43803
- }
43804
- const result = {
43805
- id,
43806
- version: getCurrentVersion(),
43807
- targets: input.targets,
43808
- name: name29,
43809
- time: {
43810
- created: Date.now(),
43811
- updated: Date.now()
43812
- },
43813
- config: {
43814
- ...normalizedConfig,
43815
- mode: normalizedConfig?.mode || "auto",
43816
- headers: snapshotHeaders,
43817
- outcomeGuidance: normalizedConfig?.outcomeGuidance || (normalizedConfig?.exfilMode ? EXFIL_OUTCOME_GUIDANCE : DEFAULT_OUTCOME_GUIDANCE),
43818
- smtpConfig
43819
- },
43820
- _rateLimiter: rateLimiter,
43821
- credentialManager,
43822
- rootPath,
43823
- logsPath,
43824
- pocsPath,
43825
- scratchpadPath,
43826
- findingsPath
43827
- };
43828
- const { _rateLimiter, credentialManager: _cm, ...sessionData } = result;
43829
- await createSessionDirs({ session: result });
43830
- await write2(["sessions", result.id, "session"], sessionData);
43831
- if (!input.name && input.model) {
43832
- generateSessionName({
43833
- targets: input.targets,
43834
- userMessage: input.userMessage,
43835
- model: input.model,
43836
- authConfig: input.authConfig
43837
- }).then((aiName) => {
43838
- if (aiName) {
43839
- result.name = aiName;
43840
- update2(result.id, (s) => {
43841
- s.name = aiName;
43842
- }).catch(() => {});
43843
- input.onNameGenerated?.(aiName);
43844
- }
43845
- });
43846
- }
43847
- return result;
43848
- }
43849
- async function update2(id, editor) {
43850
- const result = await update(["sessions", id, "session"], (draft) => {
43851
- editor(draft);
43852
- draft.time.updated = Date.now();
43853
- });
43854
- return result;
43855
- }
43856
- async function* list2() {
43857
- const sessionsDir = getSessionsDir();
43858
- let entries;
43859
- try {
43860
- entries = await import("fs/promises").then((fsp) => fsp.readdir(sessionsDir, { withFileTypes: true }));
43861
- } catch {
43862
- return;
43863
- }
43864
- for (const entry of entries) {
43865
- if (!entry.isDirectory())
43866
- continue;
43867
- try {
43868
- yield await read2([
43869
- "sessions",
43870
- entry.name,
43871
- "session"
43872
- ]);
43873
- } catch {}
43874
- }
43875
- }
43876
- async function loadOperatorState(sessionId) {
43877
- try {
43878
- const session = await get(sessionId);
43879
- const statePath = path2.join(session.rootPath, "messages.json");
43880
- if (!existsSync(statePath))
43881
- return null;
43882
- const data = readFileSync(statePath, "utf-8");
43883
- const parsed = JSON.parse(data);
43884
- if (Array.isArray(parsed)) {
43885
- return {
43886
- mode: session.config?.operatorSettings?.initialMode ?? "manual",
43887
- requireApproval: session.config?.operatorSettings?.requireApproval ?? true,
43888
- currentStage: "recon",
43889
- messages: parsed,
43890
- attackSurface: [],
43891
- credentials: [],
43892
- verifiedVulns: [],
43893
- targetState: null,
43894
- hypotheses: [],
43895
- evidence: [],
43896
- actionHistory: [],
43897
- pausedAt: new Date().toISOString(),
43898
- lastRunId: ""
43899
- };
43900
- }
43901
- return parsed;
43902
- } catch (error) {
43903
- console.error("Error loading operator state:", error);
43904
- return null;
43905
- }
43906
- }
43907
- function hasOperatorState(session) {
43908
- const statePath = path2.join(session.rootPath, "messages.json");
43909
- return existsSync(statePath);
43910
- }
43911
- function getResumeMessages(messages, limit = MAX_RESUME_MESSAGES) {
43912
- if (messages.length <= limit)
43913
- return messages;
43914
- let cutIndex = messages.length - limit;
43915
- while (cutIndex < messages.length) {
43916
- if (messages[cutIndex].role === "user")
43917
- break;
43918
- cutIndex++;
43919
- }
43920
- if (cutIndex >= messages.length) {
43921
- cutIndex = messages.length - limit;
43922
- }
43923
- return messages.slice(cutIndex);
43924
- }
43925
- function normalizeMessages(messages) {
43926
- if (messages.length <= 1)
43927
- return fixToolOutputs(messages);
43928
- const result = [];
43929
- for (const msg of messages) {
43930
- const prev = result[result.length - 1];
43931
- if (prev && prev.role === "user" && msg.role === "user" && typeof prev.content === "string" && typeof msg.content === "string") {
43932
- result[result.length - 1] = {
43933
- ...prev,
43934
- content: `${prev.content}
43935
-
43936
- ${msg.content}`
43937
- };
43938
- } else if (prev && prev.role === "user" && msg.role === "user") {
43939
- result[result.length - 1] = msg;
43940
- } else {
43941
- result.push(msg);
43942
- }
43943
- }
43944
- return fixToolOutputs(result);
43945
- }
43946
- function fixToolOutputs(messages) {
43947
- let changed = false;
43948
- const fixed = messages.map((msg) => {
43949
- if (msg.role !== "tool" || !Array.isArray(msg.content))
43950
- return msg;
43951
- let partChanged = false;
43952
- const fixedContent = msg.content.map((part) => {
43953
- if (part.type === "tool-result" && typeof part.output === "string") {
43954
- partChanged = true;
43955
- return { ...part, output: { type: "text", value: part.output } };
43956
- }
43957
- return part;
43958
- });
43959
- if (partChanged) {
43960
- changed = true;
43961
- return { ...msg, content: fixedContent };
43962
- }
43963
- return msg;
43964
- });
43965
- return changed ? fixed : messages;
43966
- }
43967
- async function updateOperatorSettings(sessionId, settings) {
43968
- return await update2(sessionId, (session) => {
43969
- if (!session.config) {
43970
- session.config = {};
43971
- }
43972
- if (!session.config.operatorSettings) {
43973
- session.config.operatorSettings = {
43974
- initialMode: "manual",
43975
- requireApproval: true,
43976
- enableSuggestions: true
43977
- };
43978
- }
43979
- if (settings.initialMode !== undefined) {
43980
- session.config.operatorSettings.initialMode = settings.initialMode;
43981
- }
43982
- if (settings.requireApproval !== undefined) {
43983
- session.config.operatorSettings.requireApproval = settings.requireApproval;
43984
- }
43985
- if (settings.enableSuggestions !== undefined) {
43986
- session.config.operatorSettings.enableSuggestions = settings.enableSuggestions;
43987
- }
43988
- });
43989
- }
43990
- async function updateSessionHeaders(sessionId, headers) {
43991
- return await update2(sessionId, (session) => {
43992
- if (!session.config) {
43993
- session.config = {};
43994
- }
43995
- session.config.headers = { ...headers };
43996
- });
43997
- }
43998
- var DEFAULT_OUTCOME_GUIDANCE, EXFIL_OUTCOME_GUIDANCE, DEFAULT_HEADER_RECORD, AuthCredentialsObject, ScopeConstraintsObject, SessionHeadersRecord, OffensiveHeadersConfigObject, OperatorSettingsObject, EmailInboxConfigObject, EmailIntegrationConfigObject, SmtpConfigObject, SessionConfigObject, SessionInfoObject, get = async (id) => {
43999
- const raw = await read2(["sessions", id, "session"]);
44000
- const read3 = migrateLegacySessionData(raw);
44001
- if (read3.config?.requestsPerSecond) {
44002
- read3._rateLimiter = new RateLimiter({
44003
- requestsPerSecond: read3.config.requestsPerSecond
44004
- });
44005
- } else {
44006
- delete read3._rateLimiter;
44007
- }
44008
- return read3;
44009
- }, RemoveInput, remove2 = async (input) => {
44010
- try {
44011
- const sessionDir = getSessionRoot(input.sessionId);
44012
- const fsp = await import("fs/promises");
44013
- await fsp.rm(sessionDir, { recursive: true, force: true });
44014
- } catch (e) {
44015
- console.error(e);
44016
- }
44017
- }, RemoveMsgInput, MAX_RESUME_MESSAGES = 200, sessions;
44018
- var init_session = __esm(() => {
44019
- init_zod();
44020
- init_name();
44021
- init_credentials();
44022
- init_id();
44023
- init_installation();
44024
- init_rateLimiter();
44025
- init_storage();
44026
- init_toolset();
44027
- DEFAULT_OUTCOME_GUIDANCE = "Prove the exploit can be run but do not exfiltrate data or cause any harm to the system. " + "Create proof-of-concept exploits that demonstrate the vulnerability exists without causing damage.";
44028
- EXFIL_OUTCOME_GUIDANCE = "Exfiltrate data to extract the flag value. " + "Create proof-of-concept exploits that successfully extract the flag from the target system.";
44029
- DEFAULT_HEADER_RECORD = {
44030
- "User-Agent": "pensar-apex"
44031
- };
44032
- AuthCredentialsObject = zod_default.object({
44033
- username: zod_default.string().optional(),
44034
- password: zod_default.string().optional(),
44035
- loginUrl: zod_default.string().optional(),
44036
- additionalFields: zod_default.record(zod_default.string(), zod_default.string()).optional(),
44037
- apiKey: zod_default.string().optional(),
44038
- role: zod_default.string().optional(),
44039
- context: zod_default.string().optional(),
44040
- tokens: zod_default.object({
44041
- bearerToken: zod_default.string().optional(),
44042
- cookies: zod_default.string().optional(),
44043
- sessionToken: zod_default.string().optional(),
44044
- customHeaders: zod_default.record(zod_default.string(), zod_default.string()).optional()
44045
- }).optional()
44046
- });
44047
- ScopeConstraintsObject = zod_default.object({
44048
- allowedHosts: zod_default.string().array().optional(),
44049
- allowedPorts: zod_default.number().array().optional(),
44050
- strictScope: zod_default.boolean().optional()
44051
- });
44052
- SessionHeadersRecord = zod_default.record(zod_default.string(), zod_default.string());
44053
- OffensiveHeadersConfigObject = zod_default.object({
44054
- mode: zod_default.enum(["none", "default", "custom"]).optional(),
44055
- headers: SessionHeadersRecord.optional()
44056
- });
44057
- OperatorSettingsObject = zod_default.object({
44058
- initialMode: zod_default.enum(["plan", "manual", "auto"]).default("manual"),
44059
- requireApproval: zod_default.boolean().default(true),
44060
- enableSuggestions: zod_default.boolean().default(true)
44061
- });
44062
- EmailInboxConfigObject = zod_default.discriminatedUnion("provider", [
44063
- zod_default.object({
44064
- provider: zod_default.literal("gmail"),
44065
- id: zod_default.string(),
44066
- name: zod_default.string(),
44067
- emailAddress: zod_default.string(),
44068
- accessToken: zod_default.string(),
44069
- refreshToken: zod_default.string(),
44070
- clientId: zod_default.string().optional(),
44071
- clientSecret: zod_default.string().optional(),
44072
- tokenExpiry: zod_default.number().optional()
44073
- }),
44074
- zod_default.object({
44075
- provider: zod_default.literal("outlook"),
44076
- id: zod_default.string(),
44077
- name: zod_default.string(),
44078
- emailAddress: zod_default.string(),
44079
- accessToken: zod_default.string(),
44080
- refreshToken: zod_default.string(),
44081
- clientId: zod_default.string().optional(),
44082
- clientSecret: zod_default.string().optional(),
44083
- tokenExpiry: zod_default.number().optional()
44084
- }),
44085
- zod_default.object({
44086
- provider: zod_default.literal("imap"),
44087
- id: zod_default.string(),
44088
- name: zod_default.string(),
44089
- emailAddress: zod_default.string(),
44090
- imapHost: zod_default.string(),
44091
- imapPort: zod_default.number(),
44092
- username: zod_default.string(),
44093
- password: zod_default.string(),
44094
- tls: zod_default.boolean()
44095
- })
44096
- ]);
44097
- EmailIntegrationConfigObject = zod_default.object({
44098
- inboxes: zod_default.array(EmailInboxConfigObject)
44099
- });
44100
- SmtpConfigObject = zod_default.object({
44101
- host: zod_default.string(),
44102
- port: zod_default.number(),
44103
- username: zod_default.string(),
44104
- password: zod_default.string(),
44105
- tls: zod_default.boolean().default(true),
44106
- fromAddress: zod_default.string().optional()
44107
- });
44108
- SessionConfigObject = zod_default.object({
44109
- headers: SessionHeadersRecord.optional(),
44110
- offensiveHeaders: OffensiveHeadersConfigObject.optional(),
44111
- sessionType: zod_default.enum(["web-app"]).optional(),
44112
- mode: zod_default.enum(["auto", "driver", "operator"]).optional(),
44113
- outcomeGuidance: zod_default.string().optional(),
44114
- scopeConstraints: ScopeConstraintsObject.optional(),
44115
- authCredentials: zod_default.union([AuthCredentialsObject, zod_default.array(AuthCredentialsObject)]).optional(),
44116
- authenticationInstructions: zod_default.string().optional(),
44117
- requestsPerSecond: zod_default.number().optional(),
44118
- operatorSettings: OperatorSettingsObject.optional(),
44119
- toolsetState: ToolsetStateSchema.optional(),
44120
- enumerateSubdomains: zod_default.boolean().optional(),
44121
- codebasePath: zod_default.string().optional(),
44122
- emailIntegration: EmailIntegrationConfigObject.optional(),
44123
- smtpConfig: SmtpConfigObject.optional(),
44124
- exfilMode: zod_default.boolean().optional(),
44125
- agentCwd: zod_default.string().optional(),
44126
- prompt: zod_default.string().optional(),
44127
- taskDriven: zod_default.boolean().optional(),
44128
- requirePlan: zod_default.boolean().optional()
44129
- });
44130
- SessionInfoObject = zod_default.object({
44131
- id: schema("session"),
44132
- name: zod_default.string().optional(),
44133
- version: zod_default.string(),
44134
- targets: zod_default.array(zod_default.string()),
44135
- config: SessionConfigObject.optional(),
44136
- time: zod_default.object({
44137
- created: zod_default.number(),
44138
- updated: zod_default.number()
44139
- }),
44140
- rootPath: zod_default.string(),
44141
- logsPath: zod_default.string(),
44142
- findingsPath: zod_default.string(),
44143
- scratchpadPath: zod_default.string(),
44144
- pocsPath: zod_default.string()
44145
- });
44146
- RemoveInput = zod_default.object({
44147
- sessionId: schema("session")
44148
- });
44149
- RemoveMsgInput = zod_default.object({
44150
- sessionId: schema("session"),
44151
- messageId: schema("message")
44152
- });
44153
- sessions = {
44154
- getSessionRoot,
44155
- EXFIL_OUTCOME_GUIDANCE,
44156
- create: create2,
44157
- get,
44158
- remove: remove2,
44159
- loadOperatorState,
44160
- hasOperatorState,
44161
- getResumeMessages,
44162
- updateOperatorSettings,
44163
- updateSessionHeaders
44164
- };
44165
- });
44166
-
44167
- // src/core/logger/index.ts
44168
- import {
44169
- appendFileSync,
44170
- existsSync as existsSync2,
44171
- mkdirSync as mkdirSync2,
44172
- readFileSync as readFileSync2,
44173
- writeFileSync as writeFileSync2
44174
- } from "fs";
44175
- import os3 from "os";
44176
- import path3 from "path";
44177
- function pruneErrorLog() {
44178
- if (hasPruned)
44179
- return;
44180
- hasPruned = true;
44181
- try {
44182
- if (!existsSync2(ERROR_LOG_PATH))
44183
- return;
44184
- const cutoff = Date.now() - RETENTION_DAYS * 86400000;
44185
- const raw = readFileSync2(ERROR_LOG_PATH, "utf8");
44186
- const lines = raw.split(`
44187
- `);
44188
- const kept = [];
44189
- let keeping = true;
44190
- for (const line of lines) {
44191
- const match = TIMESTAMP_RE.exec(line);
44192
- if (match) {
44193
- keeping = new Date(match[1]).getTime() >= cutoff;
44194
- }
44195
- if (keeping) {
44196
- kept.push(line);
44197
- }
44198
- }
44199
- writeFileSync2(ERROR_LOG_PATH, kept.join(`
44200
- `), "utf8");
44201
- } catch {}
44202
- }
44203
- function writeErrorLog(error, source, fields) {
44204
- try {
44205
- pruneErrorLog();
44206
- const dir = path3.dirname(ERROR_LOG_PATH);
44207
- if (!existsSync2(dir)) {
44208
- mkdirSync2(dir, { recursive: true });
44209
- }
44210
- const timestamp = new Date().toISOString();
44211
- const tag = source ? `[${source}] ` : "";
44212
- const message = error instanceof Error ? `${error.message}
44213
- ${error.stack ?? ""}` : String(error);
44214
- let fieldsStr = "";
44215
- if (fields && Object.keys(fields).length > 0) {
44216
- try {
44217
- fieldsStr = ` ${JSON.stringify(fields)}`;
44218
- } catch {}
44219
- }
44220
- const entry = `${timestamp} - [ERROR] ${tag}${message}${fieldsStr}
44221
- `;
44222
- appendFileSync(ERROR_LOG_PATH, entry, "utf8");
44223
- } catch {}
44224
- }
44225
- var ERROR_LOG_PATH, RETENTION_DAYS = 7, TIMESTAMP_RE, hasPruned = false;
44226
- var init_logger = __esm(() => {
44227
- init_session();
44228
- init_structured();
44229
- ERROR_LOG_PATH = path3.join(os3.homedir(), ".pensar", "error.log");
44230
- TIMESTAMP_RE = /^(\d{4}-\d{2}-\d{2}T[\d:.]+Z) - /;
44231
- });
44232
-
44233
- // src/core/logger/structured.ts
44234
- function isLevel(v) {
44235
- return typeof v === "string" && VALID_LEVELS.has(v);
44236
- }
44237
- function resolveInitialLevel(env) {
44238
- const explicit = env.PENSAR_LOG_LEVEL?.trim().toUpperCase();
44239
- if (isLevel(explicit))
44240
- return explicit;
44241
- const debug = env.PENSAR_DEBUG?.toLowerCase();
44242
- if (debug === "1" || debug === "true")
44243
- return "DEBUG";
44244
- return "INFO";
44245
- }
44246
- function resolveFormat(env) {
44247
- const forced = env.PENSAR_LOG_FORMAT?.toLowerCase();
44248
- if (forced === "json" || forced === "pretty")
44249
- return forced;
44250
- return process.stderr.isTTY ? "pretty" : "json";
44251
- }
44252
-
44253
- class Logger {
44254
- level;
44255
- explicit = false;
44256
- scope;
44257
- constructor(scope, level) {
44258
- this.scope = scope;
44259
- this.level = level ?? resolveInitialLevel(process.env);
44260
- }
44261
- setLevel(level) {
44262
- this.level = level;
44263
- this.explicit = true;
44264
- }
44265
- getLevel() {
44266
- return this.level;
44267
- }
44268
- child(scope) {
44269
- const next = this.scope ? `${this.scope}:${scope}` : scope;
44270
- const child = new Logger(next, this.level);
44271
- if (this.explicit)
44272
- child.setLevel(this.level);
44273
- return child;
44274
- }
44275
- debug(msg, fields) {
44276
- this.emit("DEBUG", msg, fields);
44277
- }
44278
- info(msg, fields) {
44279
- this.emit("INFO", msg, fields);
44280
- }
44281
- warn(msg, fields) {
44282
- this.emit("WARN", msg, fields);
44283
- }
44284
- error(msg, errOrFields, fields) {
44285
- let err;
44286
- let extra;
44287
- if (errOrFields instanceof Error) {
44288
- err = errOrFields;
44289
- extra = fields;
44290
- } else if (errOrFields && typeof errOrFields === "object") {
44291
- extra = errOrFields;
44292
- }
44293
- const merged = { ...extra };
44294
- if (err) {
44295
- merged.error = err.message;
44296
- if (err.stack)
44297
- merged.stack = err.stack;
44298
- }
44299
- this.emit("ERROR", msg, merged);
44300
- if (this.level !== "SILENT") {
44301
- writeErrorLog(err ?? msg, this.scope, extra);
44302
- }
44303
- }
44304
- emit(level, msg, fields) {
44305
- if (SEVERITY[level] < SEVERITY[this.level])
44306
- return;
44307
- const ts = new Date().toISOString();
44308
- const format = resolveFormat(process.env);
44309
- const line = format === "json" ? this.formatJson(ts, level, msg, fields) : this.formatPretty(ts, level, msg, fields);
44310
- process.stderr.write(`${line}
44311
- `);
44312
- }
44313
- formatJson(ts, level, msg, fields) {
44314
- const record = { ts, level, msg };
44315
- if (this.scope)
44316
- record.scope = this.scope;
44317
- if (fields) {
44318
- for (const [k, v] of Object.entries(fields)) {
44319
- if (k !== "ts" && k !== "level" && k !== "msg" && k !== "scope") {
44320
- record[k] = v;
44321
- }
44322
- }
44323
- }
44324
- return safeStringify(record);
44325
- }
44326
- formatPretty(ts, level, msg, fields) {
44327
- const color = COLORS[level];
44328
- const tag = `${color}${level.padEnd(5)}${RESET}`;
44329
- const scope = this.scope ? ` ${DIM}[${this.scope}]${RESET}` : "";
44330
- let rest = "";
44331
- if (fields && Object.keys(fields).length > 0) {
44332
- rest = ` ${DIM}${safeStringify(fields)}${RESET}`;
44333
- }
44334
- return `${DIM}${ts}${RESET} ${tag}${scope} ${msg}${rest}`;
44335
- }
44336
- }
44337
- function safeStringify(value) {
44338
- try {
44339
- return JSON.stringify(value);
44340
- } catch {
44341
- return JSON.stringify({ msg: "[unserializable log payload]" });
44342
- }
44343
- }
44344
- function createLogger(scope) {
44345
- return new Logger(scope);
44346
- }
44347
- var SEVERITY, VALID_LEVELS, COLORS, RESET = "\x1B[0m", DIM = "\x1B[2m", logger;
44348
- var init_structured = __esm(() => {
44349
- init_logger();
44350
- SEVERITY = {
44351
- DEBUG: 10,
44352
- INFO: 20,
44353
- WARN: 30,
44354
- ERROR: 40,
44355
- SILENT: 50
44356
- };
44357
- VALID_LEVELS = new Set([
44358
- "DEBUG",
44359
- "INFO",
44360
- "WARN",
44361
- "ERROR",
44362
- "SILENT"
44363
- ]);
44364
- COLORS = {
44365
- DEBUG: "\x1B[90m",
44366
- INFO: "\x1B[36m",
44367
- WARN: "\x1B[33m",
44368
- ERROR: "\x1B[31m",
44369
- SILENT: ""
44370
- };
44371
- logger = new Logger;
44372
- });
44373
-
44374
42940
  // src/core/ai/providers/pensarFormatters.ts
44375
42941
  function convertToBedrockFormat(modelId, options) {
44376
42942
  if (modelId.includes("anthropic.claude")) {
@@ -44573,9 +43139,11 @@ async function* parseSSE(stream, options = {}) {
44573
43139
  clearTimeout(timeoutId);
44574
43140
  }
44575
43141
  if (result.done) {
44576
- log2.debug(`stream done: ${chunkCount} chunks, ${totalBytes} bytes, ${eventCount} events yielded, remaining buffer=${buffer.length} chars`);
44577
- if (buffer.length > 0) {
44578
- log2.debug(`remaining buffer: ${buffer.slice(0, 500)}`);
43142
+ if (DEBUG) {
43143
+ console.error(`[parseSSE] stream done: ${chunkCount} chunks, ${totalBytes} bytes, ${eventCount} events yielded, remaining buffer=${buffer.length} chars`);
43144
+ if (buffer.length > 0) {
43145
+ console.error(`[parseSSE] remaining buffer: ${buffer.slice(0, 500)}`);
43146
+ }
44579
43147
  }
44580
43148
  break;
44581
43149
  }
@@ -44583,8 +43151,8 @@ async function* parseSSE(stream, options = {}) {
44583
43151
  chunkCount++;
44584
43152
  totalBytes += value.byteLength;
44585
43153
  const decoded = decoder.decode(value, { stream: true });
44586
- if (chunkCount <= 3) {
44587
- log2.debug(`chunk #${chunkCount}: ${value.byteLength} bytes, preview: ${decoded.slice(0, 200)}`);
43154
+ if (DEBUG && chunkCount <= 3) {
43155
+ console.error(`[parseSSE] chunk #${chunkCount}: ${value.byteLength} bytes, preview: ${decoded.slice(0, 200)}`);
44588
43156
  }
44589
43157
  buffer += decoded;
44590
43158
  const lines = buffer.split(`
@@ -44609,38 +43177,34 @@ async function* parseSSE(stream, options = {}) {
44609
43177
  }
44610
43178
  if (currentData.length > 0) {
44611
43179
  eventCount++;
44612
- log2.debug(`flushing final event: ${currentEvent}`);
43180
+ if (DEBUG)
43181
+ console.error(`[parseSSE] flushing final event: ${currentEvent}`);
44613
43182
  yield { event: currentEvent, data: currentData.join(`
44614
43183
  `) };
44615
43184
  }
44616
43185
  if (eventCount === 0) {
44617
- log2.warn(`stream ended with 0 events! totalBytes=${totalBytes}, chunks=${chunkCount}`);
43186
+ console.error(`[parseSSE] WARNING: stream ended with 0 events! totalBytes=${totalBytes}, chunks=${chunkCount}`);
44618
43187
  }
44619
43188
  } finally {
44620
43189
  reader.releaseLock();
44621
43190
  }
44622
43191
  }
44623
- var log2;
43192
+ var DEBUG;
44624
43193
  var init_pensarSSE = __esm(() => {
44625
- init_structured();
44626
- init_lazyLogger();
44627
- log2 = scopedLogger(() => createLogger("pensarSSE"));
43194
+ DEBUG = process.env.PENSAR_DEBUG === "1" || process.env.PENSAR_DEBUG === "true";
44628
43195
  });
44629
43196
 
44630
43197
  // src/core/ai/providers/pensar.ts
44631
- function fmtArgs(args) {
44632
- return args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
44633
- }
44634
- function log3(...args) {
44635
- structuredLog.debug(fmtArgs(args));
43198
+ function log(...args) {
43199
+ if (DEBUG2)
43200
+ console.error("[pensar:debug]", ...args);
44636
43201
  }
44637
43202
  function logInfo(...args) {
44638
- structuredLog.debug(fmtArgs(args));
43203
+ if (DEBUG2)
43204
+ console.error("[pensar]", ...args);
44639
43205
  }
44640
43206
  function logError(...args) {
44641
- const err = args.find((a) => a instanceof Error);
44642
- const msg = fmtArgs(args.filter((a) => !(a instanceof Error)));
44643
- structuredLog.error(msg, err);
43207
+ console.error("[pensar:error]", ...args);
44644
43208
  }
44645
43209
  function createPensarModel(bedrockModelId, config2) {
44646
43210
  const modelId = `pensar:${bedrockModelId}`;
@@ -44656,14 +43220,14 @@ function createPensarModel(bedrockModelId, config2) {
44656
43220
  throw new Error("Pensar authentication failed. Run /login to reconnect.");
44657
43221
  }
44658
43222
  headers.Authorization = `Bearer ${result.token.slice(0, 12)}…`;
44659
- log3(` auth: ${result.type} token (${result.token.length} chars)`);
43223
+ log(` auth: ${result.type} token (${result.token.length} chars)`);
44660
43224
  if (config2.workspaceId) {
44661
43225
  headers["X-Workspace-Id"] = config2.workspaceId;
44662
43226
  }
44663
43227
  headers.Authorization = `Bearer ${result.token}`;
44664
43228
  } else {
44665
43229
  headers.Authorization = `Bearer ${config2.apiKey}`;
44666
- log3(` auth: apiKey (${config2.apiKey.length} chars)`);
43230
+ log(` auth: apiKey (${config2.apiKey.length} chars)`);
44667
43231
  if (config2.workspaceId && !config2.apiKey.startsWith("sk-")) {
44668
43232
  headers["X-Workspace-Id"] = config2.workspaceId;
44669
43233
  }
@@ -44772,7 +43336,7 @@ function createPensarModel(bedrockModelId, config2) {
44772
43336
  const body = convertToBedrockFormat(bedrockModelId, options);
44773
43337
  const url = `${config2.baseUrl}/gateway/invoke`;
44774
43338
  logInfo(`doStream → ${bedrockModelId} (${url})`);
44775
- log3(` messages: ${body.messages?.length ?? 0}, tools: ${body.tools?.length ?? 0}`);
43339
+ log(` messages: ${body.messages?.length ?? 0}, tools: ${body.tools?.length ?? 0}`);
44776
43340
  const startTime = Date.now();
44777
43341
  const serializedBody = JSON.stringify({
44778
43342
  modelId: bedrockModelId,
@@ -44785,7 +43349,7 @@ function createPensarModel(bedrockModelId, config2) {
44785
43349
  headers["X-Pensar-Timestamp"] = sig.timestamp;
44786
43350
  headers["X-Pensar-Nonce"] = sig.nonce;
44787
43351
  }
44788
- log3(` headers: ${Object.keys(headers).join(", ")}`);
43352
+ log(` headers: ${Object.keys(headers).join(", ")}`);
44789
43353
  const fetchSignal = buildStreamingFetchSignal(options.abortSignal);
44790
43354
  let response;
44791
43355
  try {
@@ -44862,10 +43426,10 @@ function createPensarModel(bedrockModelId, config2) {
44862
43426
  try {
44863
43427
  parsed = JSON.parse(sse.data);
44864
43428
  } catch {
44865
- log3(` SSE event #${eventCount}: unparseable data, skipping`);
43429
+ log(` SSE event #${eventCount}: unparseable data, skipping`);
44866
43430
  continue;
44867
43431
  }
44868
- log3(` SSE event #${eventCount}: ${sse.event} (type=${parsed.type})`);
43432
+ log(` SSE event #${eventCount}: ${sse.event} (type=${parsed.type})`);
44869
43433
  if (sse.event === "error") {
44870
43434
  const msg = parsed.error ?? "Unknown streaming error";
44871
43435
  logError(` SSE error event: ${msg}`);
@@ -44874,7 +43438,7 @@ function createPensarModel(bedrockModelId, config2) {
44874
43438
  }
44875
43439
  if (sse.event === "pensar:usage") {
44876
43440
  if (parsed.totalCost != null) {
44877
- log3(` cost: $${Number(parsed.totalCost).toFixed(6)}`);
43441
+ log(` cost: $${Number(parsed.totalCost).toFixed(6)}`);
44878
43442
  }
44879
43443
  continue;
44880
43444
  }
@@ -45061,15 +43625,13 @@ function mapStopReason(reason) {
45061
43625
  return "other";
45062
43626
  }
45063
43627
  }
45064
- var structuredLog;
43628
+ var DEBUG2;
45065
43629
  var init_pensar2 = __esm(() => {
45066
- init_structured();
45067
- init_lazyLogger();
45068
43630
  init_utils();
45069
43631
  init_pensarFormatters();
45070
43632
  init_pensarSigning();
45071
43633
  init_pensarSSE();
45072
- structuredLog = scopedLogger(() => createLogger("pensar"));
43634
+ DEBUG2 = process.env.PENSAR_DEBUG === "1" || process.env.PENSAR_DEBUG === "true";
45073
43635
  });
45074
43636
 
45075
43637
  // src/core/ai/utils.ts
@@ -45173,7 +43735,9 @@ function getProviderModel(model, authConfig) {
45173
43735
  }
45174
43736
  const gatewayUrl = authConfig?.gatewayUrl || getPensarGatewayUrl();
45175
43737
  const bedrockModelId = model.startsWith("pensar:") ? model.slice(7) : model;
45176
- log4.debug(`getProviderModel: ${model} bedrock:${bedrockModelId} via ${gatewayUrl}`);
43738
+ if (process.env.PENSAR_DEBUG === "1" || process.env.PENSAR_DEBUG === "true") {
43739
+ console.log(`[pensar] getProviderModel: ${model} → bedrock:${bedrockModelId} via ${gatewayUrl}`);
43740
+ }
45177
43741
  const modelConfig = {
45178
43742
  apiKey: pensarApiKey || authConfig?.accessToken || "",
45179
43743
  baseUrl: gatewayUrl,
@@ -45390,7 +43954,7 @@ function createSummarizationStream(messages, opts, model) {
45390
43954
  }
45391
43955
  };
45392
43956
  }
45393
- var log4, STREAMING_FETCH_TIMEOUT_MS;
43957
+ var STREAMING_FETCH_TIMEOUT_MS;
45394
43958
  var init_utils = __esm(() => {
45395
43959
  init_dist6();
45396
43960
  init_dist7();
@@ -45402,14 +43966,11 @@ var init_utils = __esm(() => {
45402
43966
  init_constants();
45403
43967
  init_auth();
45404
43968
  init_config();
45405
- init_structured();
45406
- init_lazyLogger();
45407
43969
  init_ai();
45408
43970
  init_contextManagement();
45409
43971
  init_models();
45410
43972
  init_pensar2();
45411
- log4 = scopedLogger(() => createLogger("ai:utils"));
45412
43973
  STREAMING_FETCH_TIMEOUT_MS = 15 * 60 * 1000;
45413
43974
  });
45414
43975
 
45415
- export { stepCountIs, hasToolCall, init_dist4 as init_dist, AVAILABLE_MODELS, init_models, require_tslib, scopedLogger, init_lazyLogger, buildAuthConfig, init_utils, init_ai2 as init_ai, generateRandomName, generateSessionName, init_name, CredentialManager, init_credentials, schema, descending, init_id, RateLimiter, init_rateLimiter, NotFoundError, write2 as write, createDir, writeRaw, read2 as read, update, list, init_storage, ToolsetStateSchema, init_toolset, create2 as create, list2 as list1, normalizeMessages, sessions, init_session, writeErrorLog, init_logger, createLogger, logger, init_structured, getApexTracer, init_observability, DEFAULT_OPENAI_REASONING_EFFORT, modelSupportsThinking, modelSupportsOpenAIReasoning, getOpenAIReasoningEfforts, streamResponse, generateObjectResponse, init_ai as init_ai1 };
43976
+ export { stepCountIs, hasToolCall, init_dist4 as init_dist, getApexTracer, init_observability, AVAILABLE_MODELS, init_models, require_tslib, buildAuthConfig, init_utils, DEFAULT_OPENAI_REASONING_EFFORT, modelSupportsThinking, modelSupportsOpenAIReasoning, getOpenAIReasoningEfforts, streamResponse, generateObjectResponse, init_ai };