@pensar/apex 0.0.36-canary.0 → 0.0.39-canary.2f181ec5
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 +128 -23
- package/build/index.js +186 -62
- package/build/pentest.js +127 -22
- package/build/quicktest.js +96 -16
- package/build/swarm.js +96 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
<h1 align="center">Pensar Apex</h1>
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<a href="https://www.npmjs.com/package/@pensar/apex"><img src="https://img.shields.io/npm/v/@pensar/apex" alt="npm version"></a>
|
|
4
|
+
<a href="https://www.npmjs.com/package/@pensar/apex"><img src="https://img.shields.io/npm/v/@pensar/apex?label=latest" alt="npm version"></a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/@pensar/apex"><img src="https://img.shields.io/npm/v/@pensar/apex/canary?label=prerelease&color=yellow" alt="npm prerelease version"></a>
|
|
6
|
+
<!-- <a href="https://www.npmjs.com/package/@pensar/apex"><img src="https://img.shields.io/npm/dm/@pensar/apex" alt="npm downloads"></a> -->
|
|
7
|
+
<a href="https://github.com/pensarai/homebrew-tap"><img src="https://img.shields.io/github/v/release/pensarai/apex?label=homebrew&logo=homebrew&color=orange" alt="Homebrew"></a>
|
|
8
|
+
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-blue" alt="Apache 2.0 License"></a>
|
|
9
|
+
<a href="https://docs.pensar.dev/apex"><img src="https://img.shields.io/badge/docs-docs.pensar.dev/apex-purple?logo=readthedocs&logoColor=white" alt="Documentation"></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
5
12
|
<p align="center">
|
|
6
13
|
<img src="screenshot.png" alt="Pensar Apex Screenshot" width="800">
|
|
7
14
|
</p>
|
|
@@ -40,6 +47,27 @@ Download installer from `https://nmap.org/download.html` and ensure `nmap` is on
|
|
|
40
47
|
|
|
41
48
|
### Install Apex
|
|
42
49
|
|
|
50
|
+
#### macOS / Linux (Quick Install)
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
curl -fsSL https://pensarai.com/install.sh | bash
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### Homebrew
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
brew tap pensarai/tap
|
|
60
|
+
brew install apex
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### Windows (PowerShell)
|
|
64
|
+
|
|
65
|
+
```powershell
|
|
66
|
+
irm https://pensarai.com/apex.ps1 | iex
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### npm
|
|
70
|
+
|
|
43
71
|
```bash
|
|
44
72
|
npm install -g @pensar/apex
|
|
45
73
|
```
|
package/build/benchmark.js
CHANGED
|
@@ -84615,7 +84615,7 @@ async function installApex(sandbox, branch) {
|
|
|
84615
84615
|
const prefix = branch ? `[${branch}] ` : "";
|
|
84616
84616
|
console.log(`${prefix}\uD83D\uDCE6 Installing Apex globally via bun...`);
|
|
84617
84617
|
try {
|
|
84618
|
-
const installResult = await sandbox.process.executeCommand('export BUN_INSTALL="$HOME/.bun" && export PATH="$BUN_INSTALL/bin:$PATH" && bun install -g @pensar/apex');
|
|
84618
|
+
const installResult = await sandbox.process.executeCommand('export BUN_INSTALL="$HOME/.bun" && export PATH="$BUN_INSTALL/bin:$PATH" && bun install -g @pensar/apex@canary');
|
|
84619
84619
|
if (installResult.exitCode !== 0) {
|
|
84620
84620
|
throw new Error(`Bun install failed with exit code ${installResult.exitCode}`);
|
|
84621
84621
|
}
|
|
@@ -121194,6 +121194,12 @@ var OPENROUTER_MODELS = [
|
|
|
121194
121194
|
provider: "openrouter",
|
|
121195
121195
|
contextLength: 64000
|
|
121196
121196
|
},
|
|
121197
|
+
{
|
|
121198
|
+
id: "mistralai/mistral-large-2512",
|
|
121199
|
+
name: "Mistral Large 3 2512",
|
|
121200
|
+
provider: "openrouter",
|
|
121201
|
+
contextLength: 262144
|
|
121202
|
+
},
|
|
121197
121203
|
{
|
|
121198
121204
|
id: "moonshotai/kimi-k2-thinking",
|
|
121199
121205
|
name: "Kimi K2 Thinking",
|
|
@@ -121795,11 +121801,38 @@ async function summarizeConversation(messages, opts, model) {
|
|
|
121795
121801
|
content: `Summarize this conversation to pass to another agent. This was the system prompt: ${opts.system} `
|
|
121796
121802
|
}
|
|
121797
121803
|
];
|
|
121798
|
-
const { text: summary } = await generateText({
|
|
121804
|
+
const { text: summary, usage: summaryUsage } = await generateText({
|
|
121799
121805
|
model,
|
|
121800
121806
|
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.`,
|
|
121801
121807
|
messages: summarizedMessages
|
|
121802
121808
|
});
|
|
121809
|
+
if (opts.onStepFinish && summaryUsage) {
|
|
121810
|
+
opts.onStepFinish({
|
|
121811
|
+
text: "",
|
|
121812
|
+
reasoning: undefined,
|
|
121813
|
+
reasoningDetails: [],
|
|
121814
|
+
files: [],
|
|
121815
|
+
sources: [],
|
|
121816
|
+
toolCalls: [],
|
|
121817
|
+
toolResults: [],
|
|
121818
|
+
finishReason: "stop",
|
|
121819
|
+
usage: {
|
|
121820
|
+
inputTokens: summaryUsage.inputTokens ?? 0,
|
|
121821
|
+
outputTokens: summaryUsage.outputTokens ?? 0,
|
|
121822
|
+
totalTokens: summaryUsage.totalTokens ?? 0
|
|
121823
|
+
},
|
|
121824
|
+
warnings: [],
|
|
121825
|
+
request: {},
|
|
121826
|
+
response: {
|
|
121827
|
+
id: "summarization",
|
|
121828
|
+
timestamp: new Date,
|
|
121829
|
+
modelId: ""
|
|
121830
|
+
},
|
|
121831
|
+
providerMetadata: undefined,
|
|
121832
|
+
stepType: "initial",
|
|
121833
|
+
isContinued: false
|
|
121834
|
+
});
|
|
121835
|
+
}
|
|
121803
121836
|
const originalLength = typeof opts.prompt === "string" ? opts.prompt.length : 0;
|
|
121804
121837
|
const enhancedPrompt = originalLength > 1e5 ? `Context: The previous conversation contained very long content that was summarized.
|
|
121805
121838
|
|
|
@@ -121962,6 +121995,7 @@ function streamResponse(opts) {
|
|
|
121962
121995
|
} = opts;
|
|
121963
121996
|
const messagesContainer = { current: messages || [] };
|
|
121964
121997
|
const providerModel = getProviderModel(model, authConfig);
|
|
121998
|
+
let rateLimitRetryCount = 0;
|
|
121965
121999
|
try {
|
|
121966
122000
|
const response = streamText({
|
|
121967
122001
|
model: providerModel,
|
|
@@ -121975,6 +122009,16 @@ function streamResponse(opts) {
|
|
|
121975
122009
|
messagesContainer.current = opts2.messages;
|
|
121976
122010
|
return;
|
|
121977
122011
|
},
|
|
122012
|
+
onError: async ({ error: error46 }) => {
|
|
122013
|
+
if (error46.message.toLowerCase().includes("too many tokens") || error46.message.toLowerCase().includes("overloaded")) {
|
|
122014
|
+
rateLimitRetryCount++;
|
|
122015
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1000 * rateLimitRetryCount));
|
|
122016
|
+
if (rateLimitRetryCount < 20) {
|
|
122017
|
+
return;
|
|
122018
|
+
}
|
|
122019
|
+
}
|
|
122020
|
+
throw error46;
|
|
122021
|
+
},
|
|
121978
122022
|
onStepFinish,
|
|
121979
122023
|
abortSignal,
|
|
121980
122024
|
activeTools,
|
|
@@ -121993,7 +122037,7 @@ function streamResponse(opts) {
|
|
|
121993
122037
|
throw new Error(`Tool ${toolCall.toolName} not found or has no schema`);
|
|
121994
122038
|
}
|
|
121995
122039
|
const jsonSchema2 = inputSchema({ toolName: toolCall.toolName });
|
|
121996
|
-
const { object: repairedArgs } = await generateObject({
|
|
122040
|
+
const { object: repairedArgs, usage: repairUsage } = await generateObject({
|
|
121997
122041
|
model: providerModel,
|
|
121998
122042
|
schema: tool2.inputSchema,
|
|
121999
122043
|
prompt: [
|
|
@@ -122006,6 +122050,33 @@ function streamResponse(opts) {
|
|
|
122006
122050
|
].join(`
|
|
122007
122051
|
`)
|
|
122008
122052
|
});
|
|
122053
|
+
if (onStepFinish && repairUsage) {
|
|
122054
|
+
onStepFinish({
|
|
122055
|
+
text: "",
|
|
122056
|
+
reasoning: undefined,
|
|
122057
|
+
reasoningDetails: [],
|
|
122058
|
+
files: [],
|
|
122059
|
+
sources: [],
|
|
122060
|
+
toolCalls: [],
|
|
122061
|
+
toolResults: [],
|
|
122062
|
+
finishReason: "stop",
|
|
122063
|
+
usage: {
|
|
122064
|
+
inputTokens: repairUsage.inputTokens ?? 0,
|
|
122065
|
+
outputTokens: repairUsage.outputTokens ?? 0,
|
|
122066
|
+
totalTokens: repairUsage.totalTokens ?? 0
|
|
122067
|
+
},
|
|
122068
|
+
warnings: [],
|
|
122069
|
+
request: {},
|
|
122070
|
+
response: {
|
|
122071
|
+
id: "tool-repair",
|
|
122072
|
+
timestamp: new Date,
|
|
122073
|
+
modelId: ""
|
|
122074
|
+
},
|
|
122075
|
+
providerMetadata: undefined,
|
|
122076
|
+
stepType: "initial",
|
|
122077
|
+
isContinued: false
|
|
122078
|
+
});
|
|
122079
|
+
}
|
|
122009
122080
|
return { ...toolCall, input: JSON.stringify(repairedArgs) };
|
|
122010
122081
|
} catch (repairError) {
|
|
122011
122082
|
if (!silent) {
|
|
@@ -122032,9 +122103,9 @@ function streamResponse(opts) {
|
|
|
122032
122103
|
}
|
|
122033
122104
|
}
|
|
122034
122105
|
async function generateObjectResponse(opts) {
|
|
122035
|
-
const { model, schema, prompt, system, maxTokens, temperature, authConfig } = opts;
|
|
122106
|
+
const { model, schema, prompt, system, maxTokens, temperature, authConfig, onTokenUsage } = opts;
|
|
122036
122107
|
const providerModel = getProviderModel(model, authConfig);
|
|
122037
|
-
const { object: object3 } = await generateObject({
|
|
122108
|
+
const { object: object3, usage } = await generateObject({
|
|
122038
122109
|
model: providerModel,
|
|
122039
122110
|
schema,
|
|
122040
122111
|
prompt,
|
|
@@ -122042,6 +122113,9 @@ async function generateObjectResponse(opts) {
|
|
|
122042
122113
|
maxTokens,
|
|
122043
122114
|
temperature
|
|
122044
122115
|
});
|
|
122116
|
+
if (onTokenUsage && usage) {
|
|
122117
|
+
onTokenUsage(usage.inputTokens ?? 0, usage.outputTokens ?? 0);
|
|
122118
|
+
}
|
|
122045
122119
|
return object3;
|
|
122046
122120
|
}
|
|
122047
122121
|
// src/core/agent/benchmark/prompts.ts
|
|
@@ -126855,6 +126929,7 @@ function runAgent(opts) {
|
|
|
126855
126929
|
objective,
|
|
126856
126930
|
model,
|
|
126857
126931
|
onStepFinish,
|
|
126932
|
+
onToolTokenUsage,
|
|
126858
126933
|
abortSignal,
|
|
126859
126934
|
silent,
|
|
126860
126935
|
authConfig,
|
|
@@ -126874,7 +126949,7 @@ function runAgent(opts) {
|
|
|
126874
126949
|
analyze_scan,
|
|
126875
126950
|
scratchpad,
|
|
126876
126951
|
generate_report
|
|
126877
|
-
} = createPentestTools(session, undefined, toolOverride);
|
|
126952
|
+
} = createPentestTools(session, undefined, toolOverride, onToolTokenUsage);
|
|
126878
126953
|
const document_finding = tool({
|
|
126879
126954
|
name: "document_finding",
|
|
126880
126955
|
description: `Document a security finding with severity, impact, and remediation guidance.
|
|
@@ -128705,7 +128780,7 @@ Example workflow:
|
|
|
128705
128780
|
execute: async (params) => recordTestResultCore(session, params)
|
|
128706
128781
|
});
|
|
128707
128782
|
}
|
|
128708
|
-
async function generateTestStrategy(params, model) {
|
|
128783
|
+
async function generateTestStrategy(params, model, onTokenUsage) {
|
|
128709
128784
|
const prompt = `You are a penetration testing expert. Generate a concise testing strategy:
|
|
128710
128785
|
|
|
128711
128786
|
Attack Type: ${params.knowledge.name}
|
|
@@ -128731,12 +128806,15 @@ Be tactical and specific.`;
|
|
|
128731
128806
|
model: providerModel,
|
|
128732
128807
|
prompt
|
|
128733
128808
|
});
|
|
128809
|
+
if (onTokenUsage && result.usage) {
|
|
128810
|
+
onTokenUsage(result.usage.inputTokens ?? 0, result.usage.outputTokens ?? 0);
|
|
128811
|
+
}
|
|
128734
128812
|
return result.text;
|
|
128735
128813
|
} catch (error46) {
|
|
128736
128814
|
return params.knowledge.adaptiveStrategy;
|
|
128737
128815
|
}
|
|
128738
128816
|
}
|
|
128739
|
-
async function generatePayload(params, model) {
|
|
128817
|
+
async function generatePayload(params, model, onTokenUsage) {
|
|
128740
128818
|
const prompt = `Generate ONE ${params.knowledge.name} payload for testing.
|
|
128741
128819
|
|
|
128742
128820
|
Techniques:
|
|
@@ -128760,7 +128838,8 @@ Generate ONE specific payload. Return ONLY JSON:
|
|
|
128760
128838
|
const result = await generateObjectResponse({
|
|
128761
128839
|
model,
|
|
128762
128840
|
schema: PayloadSchema,
|
|
128763
|
-
prompt
|
|
128841
|
+
prompt,
|
|
128842
|
+
onTokenUsage
|
|
128764
128843
|
});
|
|
128765
128844
|
return result;
|
|
128766
128845
|
} catch (error46) {
|
|
@@ -128773,7 +128852,7 @@ Generate ONE specific payload. Return ONLY JSON:
|
|
|
128773
128852
|
technique: technique.name
|
|
128774
128853
|
};
|
|
128775
128854
|
}
|
|
128776
|
-
async function analyzeResponse(params, model) {
|
|
128855
|
+
async function analyzeResponse(params, model, onTokenUsage) {
|
|
128777
128856
|
const prompt = `Analyze this security test response:
|
|
128778
128857
|
|
|
128779
128858
|
Attack: ${params.knowledge.name}
|
|
@@ -128801,7 +128880,8 @@ Analyze: Is this vulnerable? Return ONLY JSON:
|
|
|
128801
128880
|
const result = await generateObjectResponse({
|
|
128802
128881
|
model,
|
|
128803
128882
|
schema: AnalysisSchema,
|
|
128804
|
-
prompt
|
|
128883
|
+
prompt,
|
|
128884
|
+
onTokenUsage
|
|
128805
128885
|
});
|
|
128806
128886
|
return result;
|
|
128807
128887
|
} catch (error46) {
|
|
@@ -128820,7 +128900,7 @@ Analyze: Is this vulnerable? Return ONLY JSON:
|
|
|
128820
128900
|
suggestedNextTest: "Try alternative payload or technique"
|
|
128821
128901
|
};
|
|
128822
128902
|
}
|
|
128823
|
-
function createSmartTestTool(session, model) {
|
|
128903
|
+
function createSmartTestTool(session, model, onTokenUsage) {
|
|
128824
128904
|
return tool({
|
|
128825
128905
|
name: "test_parameter",
|
|
128826
128906
|
description: `Intelligently test a parameter for a vulnerability using AI-powered adaptive testing.
|
|
@@ -128890,7 +128970,7 @@ test_parameter({
|
|
|
128890
128970
|
parameter,
|
|
128891
128971
|
endpoint,
|
|
128892
128972
|
context
|
|
128893
|
-
}, model);
|
|
128973
|
+
}, model, onTokenUsage);
|
|
128894
128974
|
console.log(`Strategy: ${strategy}`);
|
|
128895
128975
|
const results = [];
|
|
128896
128976
|
let vulnerable = false;
|
|
@@ -128903,7 +128983,7 @@ test_parameter({
|
|
|
128903
128983
|
context: { ...context, parameter, endpoint },
|
|
128904
128984
|
previousResults: results,
|
|
128905
128985
|
round
|
|
128906
|
-
}, model);
|
|
128986
|
+
}, model, onTokenUsage);
|
|
128907
128987
|
console.log(` Payload: ${payloadData.payload}`);
|
|
128908
128988
|
console.log(` Reasoning: ${payloadData.reasoning}`);
|
|
128909
128989
|
let response;
|
|
@@ -128932,7 +129012,7 @@ test_parameter({
|
|
|
128932
129012
|
attackType,
|
|
128933
129013
|
knowledge,
|
|
128934
129014
|
previousResults: results
|
|
128935
|
-
}, model);
|
|
129015
|
+
}, model, onTokenUsage);
|
|
128936
129016
|
console.log(` Analysis: ${analysis.reasoning}`);
|
|
128937
129017
|
console.log(` Vulnerable: ${analysis.vulnerable} (confidence: ${analysis.confidence})`);
|
|
128938
129018
|
results.push({
|
|
@@ -129382,7 +129462,7 @@ function wrapCommandWithHeaders(command, headers) {
|
|
|
129382
129462
|
}
|
|
129383
129463
|
return wrapped;
|
|
129384
129464
|
}
|
|
129385
|
-
function createPentestTools(session, model, toolOverride) {
|
|
129465
|
+
function createPentestTools(session, model, toolOverride, onTokenUsage) {
|
|
129386
129466
|
const offensiveHeaders = getOffensiveHeaders(session);
|
|
129387
129467
|
const rateLimiter = session._rateLimiter;
|
|
129388
129468
|
const executeCommand = tool({
|
|
@@ -129556,7 +129636,7 @@ COMMON TESTING PATTERNS:
|
|
|
129556
129636
|
http_request: httpRequest,
|
|
129557
129637
|
document_finding: createDocumentFindingTool(session),
|
|
129558
129638
|
record_test_result: createRecordTestResultTool(session),
|
|
129559
|
-
test_parameter: createSmartTestTool(session, model || "claude-sonnet-4-20250514"),
|
|
129639
|
+
test_parameter: createSmartTestTool(session, model || "claude-sonnet-4-20250514", onTokenUsage),
|
|
129560
129640
|
check_testing_coverage: createCheckTestingCoverageTool(session),
|
|
129561
129641
|
validate_completeness: createValidateCompletenessTool(session),
|
|
129562
129642
|
enumerate_endpoints: createEnumerateEndpointsTool(session),
|
|
@@ -129572,7 +129652,7 @@ COMMON TESTING PATTERNS:
|
|
|
129572
129652
|
import { join as join5 } from "path";
|
|
129573
129653
|
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync7 } from "fs";
|
|
129574
129654
|
function runAgent2(opts) {
|
|
129575
|
-
const { target, model, onStepFinish, abortSignal } = opts;
|
|
129655
|
+
const { target, model, onStepFinish, onToolTokenUsage, abortSignal } = opts;
|
|
129576
129656
|
const session = opts.session || createSession(target);
|
|
129577
129657
|
const subagentId = `attack-surface-${nanoid3(6)}`;
|
|
129578
129658
|
console.log(`Created attack surface session: ${session.id}`);
|
|
@@ -129581,7 +129661,7 @@ function runAgent2(opts) {
|
|
|
129581
129661
|
if (!existsSync7(assetsPath)) {
|
|
129582
129662
|
mkdirSync5(assetsPath, { recursive: true });
|
|
129583
129663
|
}
|
|
129584
|
-
const { analyze_scan, execute_command, http_request } = createPentestTools(session, model);
|
|
129664
|
+
const { analyze_scan, execute_command, http_request } = createPentestTools(session, model, undefined, onToolTokenUsage);
|
|
129585
129665
|
const document_asset = tool({
|
|
129586
129666
|
name: "document_asset",
|
|
129587
129667
|
description: `Document a discovered asset during attack surface analysis.
|
|
@@ -129742,13 +129822,14 @@ function runAgent3(opts) {
|
|
|
129742
129822
|
onSubagentSpawn,
|
|
129743
129823
|
onSubagentMessage,
|
|
129744
129824
|
onSubagentComplete,
|
|
129825
|
+
onSubagentTokenUsage,
|
|
129745
129826
|
session: sessionProp
|
|
129746
129827
|
} = opts;
|
|
129747
129828
|
const session = sessionProp || createSession(target, undefined, undefined, sessionConfig);
|
|
129748
129829
|
const logger = new Logger(session);
|
|
129749
129830
|
logger.log(`Created thorough pentest session: ${session.id}`);
|
|
129750
129831
|
logger.log(`Session path: ${session.rootPath}`);
|
|
129751
|
-
const tools2 = createOrchestratorTools(session, model, abortSignal, onSubagentSpawn, onSubagentMessage, onSubagentComplete, logger);
|
|
129832
|
+
const tools2 = createOrchestratorTools(session, model, abortSignal, onSubagentSpawn, onSubagentMessage, onSubagentComplete, onSubagentTokenUsage, logger);
|
|
129752
129833
|
const enhancedPrompt = `
|
|
129753
129834
|
TARGET: ${target}
|
|
129754
129835
|
|
|
@@ -129784,7 +129865,7 @@ Begin by using the get_attack_surface tool to map the complete attack surface of
|
|
|
129784
129865
|
streamResult.session = session;
|
|
129785
129866
|
return { streamResult, session };
|
|
129786
129867
|
}
|
|
129787
|
-
function createOrchestratorTools(session, model, abortSignal, onSubagentSpawn, onSubagentMessage, onSubagentComplete, logger) {
|
|
129868
|
+
function createOrchestratorTools(session, model, abortSignal, onSubagentSpawn, onSubagentMessage, onSubagentComplete, onSubagentTokenUsage, logger) {
|
|
129788
129869
|
const getAttackSurface = tool({
|
|
129789
129870
|
name: "get_attack_surface",
|
|
129790
129871
|
description: `Run the attack surface analysis agent to discover all assets and identify targets.
|
|
@@ -129816,7 +129897,19 @@ Use this as the FIRST step in your thorough penetration test.`,
|
|
|
129816
129897
|
target,
|
|
129817
129898
|
objective,
|
|
129818
129899
|
model,
|
|
129819
|
-
abortSignal
|
|
129900
|
+
abortSignal,
|
|
129901
|
+
onStepFinish: ({ usage }) => {
|
|
129902
|
+
if (onSubagentTokenUsage) {
|
|
129903
|
+
const inputTokens = usage.inputTokens ?? 0;
|
|
129904
|
+
const outputTokens = usage.outputTokens ?? 0;
|
|
129905
|
+
onSubagentTokenUsage(subagentId, inputTokens, outputTokens);
|
|
129906
|
+
}
|
|
129907
|
+
},
|
|
129908
|
+
onToolTokenUsage: (inputTokens, outputTokens) => {
|
|
129909
|
+
if (onSubagentTokenUsage) {
|
|
129910
|
+
onSubagentTokenUsage(subagentId, inputTokens, outputTokens);
|
|
129911
|
+
}
|
|
129912
|
+
}
|
|
129820
129913
|
});
|
|
129821
129914
|
const allMessages = [];
|
|
129822
129915
|
let currentAssistantText = "";
|
|
@@ -129991,7 +130084,19 @@ You can spawn multiple agents in parallel - they will run concurrently.`,
|
|
|
129991
130084
|
target: targetInfo.target,
|
|
129992
130085
|
objective: targetInfo.objective,
|
|
129993
130086
|
model,
|
|
129994
|
-
abortSignal
|
|
130087
|
+
abortSignal,
|
|
130088
|
+
onStepFinish: ({ usage }) => {
|
|
130089
|
+
if (onSubagentTokenUsage) {
|
|
130090
|
+
const inputTokens = usage.inputTokens ?? 0;
|
|
130091
|
+
const outputTokens = usage.outputTokens ?? 0;
|
|
130092
|
+
onSubagentTokenUsage(subagentId, inputTokens, outputTokens);
|
|
130093
|
+
}
|
|
130094
|
+
},
|
|
130095
|
+
onToolTokenUsage: (inputTokens, outputTokens) => {
|
|
130096
|
+
if (onSubagentTokenUsage) {
|
|
130097
|
+
onSubagentTokenUsage(subagentId, inputTokens, outputTokens);
|
|
130098
|
+
}
|
|
130099
|
+
}
|
|
129995
130100
|
});
|
|
129996
130101
|
const allMessages = [];
|
|
129997
130102
|
let currentAssistantText = "";
|