@pensar/apex 0.0.37-canary.0 → 0.0.39-canary.efda0f61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -1
- package/build/benchmark.js +121 -22
- package/build/index.js +180 -62
- package/build/pentest.js +121 -22
- package/build/quicktest.js +90 -16
- package/build/swarm.js +90 -16
- package/package.json +1 -1
package/build/pentest.js
CHANGED
|
@@ -40120,11 +40120,38 @@ async function summarizeConversation(messages, opts, model) {
|
|
|
40120
40120
|
content: `Summarize this conversation to pass to another agent. This was the system prompt: ${opts.system} `
|
|
40121
40121
|
}
|
|
40122
40122
|
];
|
|
40123
|
-
const { text: summary } = await generateText({
|
|
40123
|
+
const { text: summary, usage: summaryUsage } = await generateText({
|
|
40124
40124
|
model,
|
|
40125
40125
|
system: `You are a helpful assistant that summarizes conversations to pass to another agent. Review the conversation and system prompt at the end provided by the user.`,
|
|
40126
40126
|
messages: summarizedMessages
|
|
40127
40127
|
});
|
|
40128
|
+
if (opts.onStepFinish && summaryUsage) {
|
|
40129
|
+
opts.onStepFinish({
|
|
40130
|
+
text: "",
|
|
40131
|
+
reasoning: undefined,
|
|
40132
|
+
reasoningDetails: [],
|
|
40133
|
+
files: [],
|
|
40134
|
+
sources: [],
|
|
40135
|
+
toolCalls: [],
|
|
40136
|
+
toolResults: [],
|
|
40137
|
+
finishReason: "stop",
|
|
40138
|
+
usage: {
|
|
40139
|
+
inputTokens: summaryUsage.inputTokens ?? 0,
|
|
40140
|
+
outputTokens: summaryUsage.outputTokens ?? 0,
|
|
40141
|
+
totalTokens: summaryUsage.totalTokens ?? 0
|
|
40142
|
+
},
|
|
40143
|
+
warnings: [],
|
|
40144
|
+
request: {},
|
|
40145
|
+
response: {
|
|
40146
|
+
id: "summarization",
|
|
40147
|
+
timestamp: new Date,
|
|
40148
|
+
modelId: ""
|
|
40149
|
+
},
|
|
40150
|
+
providerMetadata: undefined,
|
|
40151
|
+
stepType: "initial",
|
|
40152
|
+
isContinued: false
|
|
40153
|
+
});
|
|
40154
|
+
}
|
|
40128
40155
|
const originalLength = typeof opts.prompt === "string" ? opts.prompt.length : 0;
|
|
40129
40156
|
const enhancedPrompt = originalLength > 1e5 ? `Context: The previous conversation contained very long content that was summarized.
|
|
40130
40157
|
|
|
@@ -40287,6 +40314,7 @@ function streamResponse(opts) {
|
|
|
40287
40314
|
} = opts;
|
|
40288
40315
|
const messagesContainer = { current: messages || [] };
|
|
40289
40316
|
const providerModel = getProviderModel(model, authConfig);
|
|
40317
|
+
let rateLimitRetryCount = 0;
|
|
40290
40318
|
try {
|
|
40291
40319
|
const response = streamText({
|
|
40292
40320
|
model: providerModel,
|
|
@@ -40300,6 +40328,16 @@ function streamResponse(opts) {
|
|
|
40300
40328
|
messagesContainer.current = opts2.messages;
|
|
40301
40329
|
return;
|
|
40302
40330
|
},
|
|
40331
|
+
onError: async ({ error: error46 }) => {
|
|
40332
|
+
if (error46.message.toLowerCase().includes("too many tokens") || error46.message.toLowerCase().includes("overloaded")) {
|
|
40333
|
+
rateLimitRetryCount++;
|
|
40334
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1000 * rateLimitRetryCount));
|
|
40335
|
+
if (rateLimitRetryCount < 20) {
|
|
40336
|
+
return;
|
|
40337
|
+
}
|
|
40338
|
+
}
|
|
40339
|
+
throw error46;
|
|
40340
|
+
},
|
|
40303
40341
|
onStepFinish,
|
|
40304
40342
|
abortSignal,
|
|
40305
40343
|
activeTools,
|
|
@@ -40318,7 +40356,7 @@ function streamResponse(opts) {
|
|
|
40318
40356
|
throw new Error(`Tool ${toolCall.toolName} not found or has no schema`);
|
|
40319
40357
|
}
|
|
40320
40358
|
const jsonSchema2 = inputSchema({ toolName: toolCall.toolName });
|
|
40321
|
-
const { object: repairedArgs } = await generateObject({
|
|
40359
|
+
const { object: repairedArgs, usage: repairUsage } = await generateObject({
|
|
40322
40360
|
model: providerModel,
|
|
40323
40361
|
schema: tool2.inputSchema,
|
|
40324
40362
|
prompt: [
|
|
@@ -40331,6 +40369,33 @@ function streamResponse(opts) {
|
|
|
40331
40369
|
].join(`
|
|
40332
40370
|
`)
|
|
40333
40371
|
});
|
|
40372
|
+
if (onStepFinish && repairUsage) {
|
|
40373
|
+
onStepFinish({
|
|
40374
|
+
text: "",
|
|
40375
|
+
reasoning: undefined,
|
|
40376
|
+
reasoningDetails: [],
|
|
40377
|
+
files: [],
|
|
40378
|
+
sources: [],
|
|
40379
|
+
toolCalls: [],
|
|
40380
|
+
toolResults: [],
|
|
40381
|
+
finishReason: "stop",
|
|
40382
|
+
usage: {
|
|
40383
|
+
inputTokens: repairUsage.inputTokens ?? 0,
|
|
40384
|
+
outputTokens: repairUsage.outputTokens ?? 0,
|
|
40385
|
+
totalTokens: repairUsage.totalTokens ?? 0
|
|
40386
|
+
},
|
|
40387
|
+
warnings: [],
|
|
40388
|
+
request: {},
|
|
40389
|
+
response: {
|
|
40390
|
+
id: "tool-repair",
|
|
40391
|
+
timestamp: new Date,
|
|
40392
|
+
modelId: ""
|
|
40393
|
+
},
|
|
40394
|
+
providerMetadata: undefined,
|
|
40395
|
+
stepType: "initial",
|
|
40396
|
+
isContinued: false
|
|
40397
|
+
});
|
|
40398
|
+
}
|
|
40334
40399
|
return { ...toolCall, input: JSON.stringify(repairedArgs) };
|
|
40335
40400
|
} catch (repairError) {
|
|
40336
40401
|
if (!silent) {
|
|
@@ -40357,9 +40422,9 @@ function streamResponse(opts) {
|
|
|
40357
40422
|
}
|
|
40358
40423
|
}
|
|
40359
40424
|
async function generateObjectResponse(opts) {
|
|
40360
|
-
const { model, schema, prompt, system, maxTokens, temperature, authConfig } = opts;
|
|
40425
|
+
const { model, schema, prompt, system, maxTokens, temperature, authConfig, onTokenUsage } = opts;
|
|
40361
40426
|
const providerModel = getProviderModel(model, authConfig);
|
|
40362
|
-
const { object: object3 } = await generateObject({
|
|
40427
|
+
const { object: object3, usage } = await generateObject({
|
|
40363
40428
|
model: providerModel,
|
|
40364
40429
|
schema,
|
|
40365
40430
|
prompt,
|
|
@@ -40367,6 +40432,9 @@ async function generateObjectResponse(opts) {
|
|
|
40367
40432
|
maxTokens,
|
|
40368
40433
|
temperature
|
|
40369
40434
|
});
|
|
40435
|
+
if (onTokenUsage && usage) {
|
|
40436
|
+
onTokenUsage(usage.inputTokens ?? 0, usage.outputTokens ?? 0);
|
|
40437
|
+
}
|
|
40370
40438
|
return object3;
|
|
40371
40439
|
}
|
|
40372
40440
|
// src/core/agent/thoroughPentestAgent/prompts.ts
|
|
@@ -44917,6 +44985,7 @@ function runAgent(opts) {
|
|
|
44917
44985
|
objective,
|
|
44918
44986
|
model,
|
|
44919
44987
|
onStepFinish,
|
|
44988
|
+
onToolTokenUsage,
|
|
44920
44989
|
abortSignal,
|
|
44921
44990
|
silent,
|
|
44922
44991
|
authConfig,
|
|
@@ -44936,7 +45005,7 @@ function runAgent(opts) {
|
|
|
44936
45005
|
analyze_scan,
|
|
44937
45006
|
scratchpad,
|
|
44938
45007
|
generate_report
|
|
44939
|
-
} = createPentestTools(session, undefined, toolOverride);
|
|
45008
|
+
} = createPentestTools(session, undefined, toolOverride, onToolTokenUsage);
|
|
44940
45009
|
const document_finding = tool({
|
|
44941
45010
|
name: "document_finding",
|
|
44942
45011
|
description: `Document a security finding with severity, impact, and remediation guidance.
|
|
@@ -46767,7 +46836,7 @@ Example workflow:
|
|
|
46767
46836
|
execute: async (params) => recordTestResultCore(session, params)
|
|
46768
46837
|
});
|
|
46769
46838
|
}
|
|
46770
|
-
async function generateTestStrategy(params, model) {
|
|
46839
|
+
async function generateTestStrategy(params, model, onTokenUsage) {
|
|
46771
46840
|
const prompt = `You are a penetration testing expert. Generate a concise testing strategy:
|
|
46772
46841
|
|
|
46773
46842
|
Attack Type: ${params.knowledge.name}
|
|
@@ -46793,12 +46862,15 @@ Be tactical and specific.`;
|
|
|
46793
46862
|
model: providerModel,
|
|
46794
46863
|
prompt
|
|
46795
46864
|
});
|
|
46865
|
+
if (onTokenUsage && result.usage) {
|
|
46866
|
+
onTokenUsage(result.usage.inputTokens ?? 0, result.usage.outputTokens ?? 0);
|
|
46867
|
+
}
|
|
46796
46868
|
return result.text;
|
|
46797
46869
|
} catch (error46) {
|
|
46798
46870
|
return params.knowledge.adaptiveStrategy;
|
|
46799
46871
|
}
|
|
46800
46872
|
}
|
|
46801
|
-
async function generatePayload(params, model) {
|
|
46873
|
+
async function generatePayload(params, model, onTokenUsage) {
|
|
46802
46874
|
const prompt = `Generate ONE ${params.knowledge.name} payload for testing.
|
|
46803
46875
|
|
|
46804
46876
|
Techniques:
|
|
@@ -46822,7 +46894,8 @@ Generate ONE specific payload. Return ONLY JSON:
|
|
|
46822
46894
|
const result = await generateObjectResponse({
|
|
46823
46895
|
model,
|
|
46824
46896
|
schema: PayloadSchema,
|
|
46825
|
-
prompt
|
|
46897
|
+
prompt,
|
|
46898
|
+
onTokenUsage
|
|
46826
46899
|
});
|
|
46827
46900
|
return result;
|
|
46828
46901
|
} catch (error46) {
|
|
@@ -46835,7 +46908,7 @@ Generate ONE specific payload. Return ONLY JSON:
|
|
|
46835
46908
|
technique: technique.name
|
|
46836
46909
|
};
|
|
46837
46910
|
}
|
|
46838
|
-
async function analyzeResponse(params, model) {
|
|
46911
|
+
async function analyzeResponse(params, model, onTokenUsage) {
|
|
46839
46912
|
const prompt = `Analyze this security test response:
|
|
46840
46913
|
|
|
46841
46914
|
Attack: ${params.knowledge.name}
|
|
@@ -46863,7 +46936,8 @@ Analyze: Is this vulnerable? Return ONLY JSON:
|
|
|
46863
46936
|
const result = await generateObjectResponse({
|
|
46864
46937
|
model,
|
|
46865
46938
|
schema: AnalysisSchema,
|
|
46866
|
-
prompt
|
|
46939
|
+
prompt,
|
|
46940
|
+
onTokenUsage
|
|
46867
46941
|
});
|
|
46868
46942
|
return result;
|
|
46869
46943
|
} catch (error46) {
|
|
@@ -46882,7 +46956,7 @@ Analyze: Is this vulnerable? Return ONLY JSON:
|
|
|
46882
46956
|
suggestedNextTest: "Try alternative payload or technique"
|
|
46883
46957
|
};
|
|
46884
46958
|
}
|
|
46885
|
-
function createSmartTestTool(session, model) {
|
|
46959
|
+
function createSmartTestTool(session, model, onTokenUsage) {
|
|
46886
46960
|
return tool({
|
|
46887
46961
|
name: "test_parameter",
|
|
46888
46962
|
description: `Intelligently test a parameter for a vulnerability using AI-powered adaptive testing.
|
|
@@ -46952,7 +47026,7 @@ test_parameter({
|
|
|
46952
47026
|
parameter,
|
|
46953
47027
|
endpoint,
|
|
46954
47028
|
context
|
|
46955
|
-
}, model);
|
|
47029
|
+
}, model, onTokenUsage);
|
|
46956
47030
|
console.log(`Strategy: ${strategy}`);
|
|
46957
47031
|
const results = [];
|
|
46958
47032
|
let vulnerable = false;
|
|
@@ -46965,7 +47039,7 @@ test_parameter({
|
|
|
46965
47039
|
context: { ...context, parameter, endpoint },
|
|
46966
47040
|
previousResults: results,
|
|
46967
47041
|
round
|
|
46968
|
-
}, model);
|
|
47042
|
+
}, model, onTokenUsage);
|
|
46969
47043
|
console.log(` Payload: ${payloadData.payload}`);
|
|
46970
47044
|
console.log(` Reasoning: ${payloadData.reasoning}`);
|
|
46971
47045
|
let response;
|
|
@@ -46994,7 +47068,7 @@ test_parameter({
|
|
|
46994
47068
|
attackType,
|
|
46995
47069
|
knowledge,
|
|
46996
47070
|
previousResults: results
|
|
46997
|
-
}, model);
|
|
47071
|
+
}, model, onTokenUsage);
|
|
46998
47072
|
console.log(` Analysis: ${analysis.reasoning}`);
|
|
46999
47073
|
console.log(` Vulnerable: ${analysis.vulnerable} (confidence: ${analysis.confidence})`);
|
|
47000
47074
|
results.push({
|
|
@@ -47444,7 +47518,7 @@ function wrapCommandWithHeaders(command, headers) {
|
|
|
47444
47518
|
}
|
|
47445
47519
|
return wrapped;
|
|
47446
47520
|
}
|
|
47447
|
-
function createPentestTools(session, model, toolOverride) {
|
|
47521
|
+
function createPentestTools(session, model, toolOverride, onTokenUsage) {
|
|
47448
47522
|
const offensiveHeaders = getOffensiveHeaders(session);
|
|
47449
47523
|
const rateLimiter = session._rateLimiter;
|
|
47450
47524
|
const executeCommand = tool({
|
|
@@ -47618,7 +47692,7 @@ COMMON TESTING PATTERNS:
|
|
|
47618
47692
|
http_request: httpRequest,
|
|
47619
47693
|
document_finding: createDocumentFindingTool(session),
|
|
47620
47694
|
record_test_result: createRecordTestResultTool(session),
|
|
47621
|
-
test_parameter: createSmartTestTool(session, model || "claude-sonnet-4-20250514"),
|
|
47695
|
+
test_parameter: createSmartTestTool(session, model || "claude-sonnet-4-20250514", onTokenUsage),
|
|
47622
47696
|
check_testing_coverage: createCheckTestingCoverageTool(session),
|
|
47623
47697
|
validate_completeness: createValidateCompletenessTool(session),
|
|
47624
47698
|
enumerate_endpoints: createEnumerateEndpointsTool(session),
|
|
@@ -47634,7 +47708,7 @@ COMMON TESTING PATTERNS:
|
|
|
47634
47708
|
import { join as join5 } from "path";
|
|
47635
47709
|
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync7 } from "fs";
|
|
47636
47710
|
function runAgent2(opts) {
|
|
47637
|
-
const { target, model, onStepFinish, abortSignal } = opts;
|
|
47711
|
+
const { target, model, onStepFinish, onToolTokenUsage, abortSignal } = opts;
|
|
47638
47712
|
const session = opts.session || createSession(target);
|
|
47639
47713
|
const subagentId = `attack-surface-${nanoid3(6)}`;
|
|
47640
47714
|
console.log(`Created attack surface session: ${session.id}`);
|
|
@@ -47643,7 +47717,7 @@ function runAgent2(opts) {
|
|
|
47643
47717
|
if (!existsSync7(assetsPath)) {
|
|
47644
47718
|
mkdirSync5(assetsPath, { recursive: true });
|
|
47645
47719
|
}
|
|
47646
|
-
const { analyze_scan, execute_command, http_request } = createPentestTools(session, model);
|
|
47720
|
+
const { analyze_scan, execute_command, http_request } = createPentestTools(session, model, undefined, onToolTokenUsage);
|
|
47647
47721
|
const document_asset = tool({
|
|
47648
47722
|
name: "document_asset",
|
|
47649
47723
|
description: `Document a discovered asset during attack surface analysis.
|
|
@@ -47940,13 +48014,14 @@ function runAgent3(opts) {
|
|
|
47940
48014
|
onSubagentSpawn,
|
|
47941
48015
|
onSubagentMessage,
|
|
47942
48016
|
onSubagentComplete,
|
|
48017
|
+
onSubagentTokenUsage,
|
|
47943
48018
|
session: sessionProp
|
|
47944
48019
|
} = opts;
|
|
47945
48020
|
const session = sessionProp || createSession(target, undefined, undefined, sessionConfig);
|
|
47946
48021
|
const logger = new Logger(session);
|
|
47947
48022
|
logger.log(`Created thorough pentest session: ${session.id}`);
|
|
47948
48023
|
logger.log(`Session path: ${session.rootPath}`);
|
|
47949
|
-
const tools2 = createOrchestratorTools(session, model, abortSignal, onSubagentSpawn, onSubagentMessage, onSubagentComplete, logger);
|
|
48024
|
+
const tools2 = createOrchestratorTools(session, model, abortSignal, onSubagentSpawn, onSubagentMessage, onSubagentComplete, onSubagentTokenUsage, logger);
|
|
47950
48025
|
const enhancedPrompt = `
|
|
47951
48026
|
TARGET: ${target}
|
|
47952
48027
|
|
|
@@ -47982,7 +48057,7 @@ Begin by using the get_attack_surface tool to map the complete attack surface of
|
|
|
47982
48057
|
streamResult.session = session;
|
|
47983
48058
|
return { streamResult, session };
|
|
47984
48059
|
}
|
|
47985
|
-
function createOrchestratorTools(session, model, abortSignal, onSubagentSpawn, onSubagentMessage, onSubagentComplete, logger) {
|
|
48060
|
+
function createOrchestratorTools(session, model, abortSignal, onSubagentSpawn, onSubagentMessage, onSubagentComplete, onSubagentTokenUsage, logger) {
|
|
47986
48061
|
const getAttackSurface = tool({
|
|
47987
48062
|
name: "get_attack_surface",
|
|
47988
48063
|
description: `Run the attack surface analysis agent to discover all assets and identify targets.
|
|
@@ -48014,7 +48089,19 @@ Use this as the FIRST step in your thorough penetration test.`,
|
|
|
48014
48089
|
target,
|
|
48015
48090
|
objective,
|
|
48016
48091
|
model,
|
|
48017
|
-
abortSignal
|
|
48092
|
+
abortSignal,
|
|
48093
|
+
onStepFinish: ({ usage }) => {
|
|
48094
|
+
if (onSubagentTokenUsage) {
|
|
48095
|
+
const inputTokens = usage.inputTokens ?? 0;
|
|
48096
|
+
const outputTokens = usage.outputTokens ?? 0;
|
|
48097
|
+
onSubagentTokenUsage(subagentId, inputTokens, outputTokens);
|
|
48098
|
+
}
|
|
48099
|
+
},
|
|
48100
|
+
onToolTokenUsage: (inputTokens, outputTokens) => {
|
|
48101
|
+
if (onSubagentTokenUsage) {
|
|
48102
|
+
onSubagentTokenUsage(subagentId, inputTokens, outputTokens);
|
|
48103
|
+
}
|
|
48104
|
+
}
|
|
48018
48105
|
});
|
|
48019
48106
|
const allMessages = [];
|
|
48020
48107
|
let currentAssistantText = "";
|
|
@@ -48189,7 +48276,19 @@ You can spawn multiple agents in parallel - they will run concurrently.`,
|
|
|
48189
48276
|
target: targetInfo.target,
|
|
48190
48277
|
objective: targetInfo.objective,
|
|
48191
48278
|
model,
|
|
48192
|
-
abortSignal
|
|
48279
|
+
abortSignal,
|
|
48280
|
+
onStepFinish: ({ usage }) => {
|
|
48281
|
+
if (onSubagentTokenUsage) {
|
|
48282
|
+
const inputTokens = usage.inputTokens ?? 0;
|
|
48283
|
+
const outputTokens = usage.outputTokens ?? 0;
|
|
48284
|
+
onSubagentTokenUsage(subagentId, inputTokens, outputTokens);
|
|
48285
|
+
}
|
|
48286
|
+
},
|
|
48287
|
+
onToolTokenUsage: (inputTokens, outputTokens) => {
|
|
48288
|
+
if (onSubagentTokenUsage) {
|
|
48289
|
+
onSubagentTokenUsage(subagentId, inputTokens, outputTokens);
|
|
48290
|
+
}
|
|
48291
|
+
}
|
|
48193
48292
|
});
|
|
48194
48293
|
const allMessages = [];
|
|
48195
48294
|
let currentAssistantText = "";
|
package/build/quicktest.js
CHANGED
|
@@ -40120,11 +40120,38 @@ async function summarizeConversation(messages, opts, model) {
|
|
|
40120
40120
|
content: `Summarize this conversation to pass to another agent. This was the system prompt: ${opts.system} `
|
|
40121
40121
|
}
|
|
40122
40122
|
];
|
|
40123
|
-
const { text: summary } = await generateText({
|
|
40123
|
+
const { text: summary, usage: summaryUsage } = await generateText({
|
|
40124
40124
|
model,
|
|
40125
40125
|
system: `You are a helpful assistant that summarizes conversations to pass to another agent. Review the conversation and system prompt at the end provided by the user.`,
|
|
40126
40126
|
messages: summarizedMessages
|
|
40127
40127
|
});
|
|
40128
|
+
if (opts.onStepFinish && summaryUsage) {
|
|
40129
|
+
opts.onStepFinish({
|
|
40130
|
+
text: "",
|
|
40131
|
+
reasoning: undefined,
|
|
40132
|
+
reasoningDetails: [],
|
|
40133
|
+
files: [],
|
|
40134
|
+
sources: [],
|
|
40135
|
+
toolCalls: [],
|
|
40136
|
+
toolResults: [],
|
|
40137
|
+
finishReason: "stop",
|
|
40138
|
+
usage: {
|
|
40139
|
+
inputTokens: summaryUsage.inputTokens ?? 0,
|
|
40140
|
+
outputTokens: summaryUsage.outputTokens ?? 0,
|
|
40141
|
+
totalTokens: summaryUsage.totalTokens ?? 0
|
|
40142
|
+
},
|
|
40143
|
+
warnings: [],
|
|
40144
|
+
request: {},
|
|
40145
|
+
response: {
|
|
40146
|
+
id: "summarization",
|
|
40147
|
+
timestamp: new Date,
|
|
40148
|
+
modelId: ""
|
|
40149
|
+
},
|
|
40150
|
+
providerMetadata: undefined,
|
|
40151
|
+
stepType: "initial",
|
|
40152
|
+
isContinued: false
|
|
40153
|
+
});
|
|
40154
|
+
}
|
|
40128
40155
|
const originalLength = typeof opts.prompt === "string" ? opts.prompt.length : 0;
|
|
40129
40156
|
const enhancedPrompt = originalLength > 1e5 ? `Context: The previous conversation contained very long content that was summarized.
|
|
40130
40157
|
|
|
@@ -40272,6 +40299,7 @@ function streamResponse(opts) {
|
|
|
40272
40299
|
} = opts;
|
|
40273
40300
|
const messagesContainer = { current: messages || [] };
|
|
40274
40301
|
const providerModel = getProviderModel(model, authConfig);
|
|
40302
|
+
let rateLimitRetryCount = 0;
|
|
40275
40303
|
try {
|
|
40276
40304
|
const response = streamText({
|
|
40277
40305
|
model: providerModel,
|
|
@@ -40285,6 +40313,16 @@ function streamResponse(opts) {
|
|
|
40285
40313
|
messagesContainer.current = opts2.messages;
|
|
40286
40314
|
return;
|
|
40287
40315
|
},
|
|
40316
|
+
onError: async ({ error: error46 }) => {
|
|
40317
|
+
if (error46.message.toLowerCase().includes("too many tokens") || error46.message.toLowerCase().includes("overloaded")) {
|
|
40318
|
+
rateLimitRetryCount++;
|
|
40319
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1000 * rateLimitRetryCount));
|
|
40320
|
+
if (rateLimitRetryCount < 20) {
|
|
40321
|
+
return;
|
|
40322
|
+
}
|
|
40323
|
+
}
|
|
40324
|
+
throw error46;
|
|
40325
|
+
},
|
|
40288
40326
|
onStepFinish,
|
|
40289
40327
|
abortSignal,
|
|
40290
40328
|
activeTools,
|
|
@@ -40303,7 +40341,7 @@ function streamResponse(opts) {
|
|
|
40303
40341
|
throw new Error(`Tool ${toolCall.toolName} not found or has no schema`);
|
|
40304
40342
|
}
|
|
40305
40343
|
const jsonSchema2 = inputSchema({ toolName: toolCall.toolName });
|
|
40306
|
-
const { object: repairedArgs } = await generateObject({
|
|
40344
|
+
const { object: repairedArgs, usage: repairUsage } = await generateObject({
|
|
40307
40345
|
model: providerModel,
|
|
40308
40346
|
schema: tool2.inputSchema,
|
|
40309
40347
|
prompt: [
|
|
@@ -40316,6 +40354,33 @@ function streamResponse(opts) {
|
|
|
40316
40354
|
].join(`
|
|
40317
40355
|
`)
|
|
40318
40356
|
});
|
|
40357
|
+
if (onStepFinish && repairUsage) {
|
|
40358
|
+
onStepFinish({
|
|
40359
|
+
text: "",
|
|
40360
|
+
reasoning: undefined,
|
|
40361
|
+
reasoningDetails: [],
|
|
40362
|
+
files: [],
|
|
40363
|
+
sources: [],
|
|
40364
|
+
toolCalls: [],
|
|
40365
|
+
toolResults: [],
|
|
40366
|
+
finishReason: "stop",
|
|
40367
|
+
usage: {
|
|
40368
|
+
inputTokens: repairUsage.inputTokens ?? 0,
|
|
40369
|
+
outputTokens: repairUsage.outputTokens ?? 0,
|
|
40370
|
+
totalTokens: repairUsage.totalTokens ?? 0
|
|
40371
|
+
},
|
|
40372
|
+
warnings: [],
|
|
40373
|
+
request: {},
|
|
40374
|
+
response: {
|
|
40375
|
+
id: "tool-repair",
|
|
40376
|
+
timestamp: new Date,
|
|
40377
|
+
modelId: ""
|
|
40378
|
+
},
|
|
40379
|
+
providerMetadata: undefined,
|
|
40380
|
+
stepType: "initial",
|
|
40381
|
+
isContinued: false
|
|
40382
|
+
});
|
|
40383
|
+
}
|
|
40319
40384
|
return { ...toolCall, input: JSON.stringify(repairedArgs) };
|
|
40320
40385
|
} catch (repairError) {
|
|
40321
40386
|
if (!silent) {
|
|
@@ -40342,9 +40407,9 @@ function streamResponse(opts) {
|
|
|
40342
40407
|
}
|
|
40343
40408
|
}
|
|
40344
40409
|
async function generateObjectResponse(opts) {
|
|
40345
|
-
const { model, schema, prompt, system, maxTokens, temperature, authConfig } = opts;
|
|
40410
|
+
const { model, schema, prompt, system, maxTokens, temperature, authConfig, onTokenUsage } = opts;
|
|
40346
40411
|
const providerModel = getProviderModel(model, authConfig);
|
|
40347
|
-
const { object: object3 } = await generateObject({
|
|
40412
|
+
const { object: object3, usage } = await generateObject({
|
|
40348
40413
|
model: providerModel,
|
|
40349
40414
|
schema,
|
|
40350
40415
|
prompt,
|
|
@@ -40352,6 +40417,9 @@ async function generateObjectResponse(opts) {
|
|
|
40352
40417
|
maxTokens,
|
|
40353
40418
|
temperature
|
|
40354
40419
|
});
|
|
40420
|
+
if (onTokenUsage && usage) {
|
|
40421
|
+
onTokenUsage(usage.inputTokens ?? 0, usage.outputTokens ?? 0);
|
|
40422
|
+
}
|
|
40355
40423
|
return object3;
|
|
40356
40424
|
}
|
|
40357
40425
|
// src/core/agent/pentestAgent/prompts.ts
|
|
@@ -43703,7 +43771,7 @@ Example workflow:
|
|
|
43703
43771
|
execute: async (params) => recordTestResultCore(session, params)
|
|
43704
43772
|
});
|
|
43705
43773
|
}
|
|
43706
|
-
async function generateTestStrategy(params, model) {
|
|
43774
|
+
async function generateTestStrategy(params, model, onTokenUsage) {
|
|
43707
43775
|
const prompt = `You are a penetration testing expert. Generate a concise testing strategy:
|
|
43708
43776
|
|
|
43709
43777
|
Attack Type: ${params.knowledge.name}
|
|
@@ -43729,12 +43797,15 @@ Be tactical and specific.`;
|
|
|
43729
43797
|
model: providerModel,
|
|
43730
43798
|
prompt
|
|
43731
43799
|
});
|
|
43800
|
+
if (onTokenUsage && result.usage) {
|
|
43801
|
+
onTokenUsage(result.usage.inputTokens ?? 0, result.usage.outputTokens ?? 0);
|
|
43802
|
+
}
|
|
43732
43803
|
return result.text;
|
|
43733
43804
|
} catch (error46) {
|
|
43734
43805
|
return params.knowledge.adaptiveStrategy;
|
|
43735
43806
|
}
|
|
43736
43807
|
}
|
|
43737
|
-
async function generatePayload(params, model) {
|
|
43808
|
+
async function generatePayload(params, model, onTokenUsage) {
|
|
43738
43809
|
const prompt = `Generate ONE ${params.knowledge.name} payload for testing.
|
|
43739
43810
|
|
|
43740
43811
|
Techniques:
|
|
@@ -43758,7 +43829,8 @@ Generate ONE specific payload. Return ONLY JSON:
|
|
|
43758
43829
|
const result = await generateObjectResponse({
|
|
43759
43830
|
model,
|
|
43760
43831
|
schema: PayloadSchema,
|
|
43761
|
-
prompt
|
|
43832
|
+
prompt,
|
|
43833
|
+
onTokenUsage
|
|
43762
43834
|
});
|
|
43763
43835
|
return result;
|
|
43764
43836
|
} catch (error46) {
|
|
@@ -43771,7 +43843,7 @@ Generate ONE specific payload. Return ONLY JSON:
|
|
|
43771
43843
|
technique: technique.name
|
|
43772
43844
|
};
|
|
43773
43845
|
}
|
|
43774
|
-
async function analyzeResponse(params, model) {
|
|
43846
|
+
async function analyzeResponse(params, model, onTokenUsage) {
|
|
43775
43847
|
const prompt = `Analyze this security test response:
|
|
43776
43848
|
|
|
43777
43849
|
Attack: ${params.knowledge.name}
|
|
@@ -43799,7 +43871,8 @@ Analyze: Is this vulnerable? Return ONLY JSON:
|
|
|
43799
43871
|
const result = await generateObjectResponse({
|
|
43800
43872
|
model,
|
|
43801
43873
|
schema: AnalysisSchema,
|
|
43802
|
-
prompt
|
|
43874
|
+
prompt,
|
|
43875
|
+
onTokenUsage
|
|
43803
43876
|
});
|
|
43804
43877
|
return result;
|
|
43805
43878
|
} catch (error46) {
|
|
@@ -43818,7 +43891,7 @@ Analyze: Is this vulnerable? Return ONLY JSON:
|
|
|
43818
43891
|
suggestedNextTest: "Try alternative payload or technique"
|
|
43819
43892
|
};
|
|
43820
43893
|
}
|
|
43821
|
-
function createSmartTestTool(session, model) {
|
|
43894
|
+
function createSmartTestTool(session, model, onTokenUsage) {
|
|
43822
43895
|
return tool({
|
|
43823
43896
|
name: "test_parameter",
|
|
43824
43897
|
description: `Intelligently test a parameter for a vulnerability using AI-powered adaptive testing.
|
|
@@ -43888,7 +43961,7 @@ test_parameter({
|
|
|
43888
43961
|
parameter,
|
|
43889
43962
|
endpoint,
|
|
43890
43963
|
context
|
|
43891
|
-
}, model);
|
|
43964
|
+
}, model, onTokenUsage);
|
|
43892
43965
|
console.log(`Strategy: ${strategy}`);
|
|
43893
43966
|
const results = [];
|
|
43894
43967
|
let vulnerable = false;
|
|
@@ -43901,7 +43974,7 @@ test_parameter({
|
|
|
43901
43974
|
context: { ...context, parameter, endpoint },
|
|
43902
43975
|
previousResults: results,
|
|
43903
43976
|
round
|
|
43904
|
-
}, model);
|
|
43977
|
+
}, model, onTokenUsage);
|
|
43905
43978
|
console.log(` Payload: ${payloadData.payload}`);
|
|
43906
43979
|
console.log(` Reasoning: ${payloadData.reasoning}`);
|
|
43907
43980
|
let response;
|
|
@@ -43930,7 +44003,7 @@ test_parameter({
|
|
|
43930
44003
|
attackType,
|
|
43931
44004
|
knowledge,
|
|
43932
44005
|
previousResults: results
|
|
43933
|
-
}, model);
|
|
44006
|
+
}, model, onTokenUsage);
|
|
43934
44007
|
console.log(` Analysis: ${analysis.reasoning}`);
|
|
43935
44008
|
console.log(` Vulnerable: ${analysis.vulnerable} (confidence: ${analysis.confidence})`);
|
|
43936
44009
|
results.push({
|
|
@@ -44380,7 +44453,7 @@ function wrapCommandWithHeaders(command, headers) {
|
|
|
44380
44453
|
}
|
|
44381
44454
|
return wrapped;
|
|
44382
44455
|
}
|
|
44383
|
-
function createPentestTools(session, model, toolOverride) {
|
|
44456
|
+
function createPentestTools(session, model, toolOverride, onTokenUsage) {
|
|
44384
44457
|
const offensiveHeaders = getOffensiveHeaders(session);
|
|
44385
44458
|
const rateLimiter = session._rateLimiter;
|
|
44386
44459
|
const executeCommand = tool({
|
|
@@ -44554,7 +44627,7 @@ COMMON TESTING PATTERNS:
|
|
|
44554
44627
|
http_request: httpRequest,
|
|
44555
44628
|
document_finding: createDocumentFindingTool(session),
|
|
44556
44629
|
record_test_result: createRecordTestResultTool(session),
|
|
44557
|
-
test_parameter: createSmartTestTool(session, model || "claude-sonnet-4-20250514"),
|
|
44630
|
+
test_parameter: createSmartTestTool(session, model || "claude-sonnet-4-20250514", onTokenUsage),
|
|
44558
44631
|
check_testing_coverage: createCheckTestingCoverageTool(session),
|
|
44559
44632
|
validate_completeness: createValidateCompletenessTool(session),
|
|
44560
44633
|
enumerate_endpoints: createEnumerateEndpointsTool(session),
|
|
@@ -45606,6 +45679,7 @@ function runAgent(opts) {
|
|
|
45606
45679
|
objective,
|
|
45607
45680
|
model,
|
|
45608
45681
|
onStepFinish,
|
|
45682
|
+
onToolTokenUsage,
|
|
45609
45683
|
abortSignal,
|
|
45610
45684
|
silent,
|
|
45611
45685
|
authConfig,
|
|
@@ -45625,7 +45699,7 @@ function runAgent(opts) {
|
|
|
45625
45699
|
analyze_scan,
|
|
45626
45700
|
scratchpad,
|
|
45627
45701
|
generate_report
|
|
45628
|
-
} = createPentestTools(session, undefined, toolOverride);
|
|
45702
|
+
} = createPentestTools(session, undefined, toolOverride, onToolTokenUsage);
|
|
45629
45703
|
const document_finding = tool({
|
|
45630
45704
|
name: "document_finding",
|
|
45631
45705
|
description: `Document a security finding with severity, impact, and remediation guidance.
|