@pensar/apex 2.5.0 → 2.6.1-canary.025b1ecf
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 +38 -0
- package/bin/pensar.js +12 -4
- package/build/agent-b37fm1yh.js +13 -0
- package/build/{agent-m30a62kh.js → agent-f8rpt4sb.js} +48 -50
- package/build/agent-gqexqg2q.js +13 -0
- package/build/agent-qk30vqmf.js +15 -0
- package/build/agent-runs-nw7dwp1d.js +313 -0
- package/build/{apps-x4ef2gpc.js → apps-zeqbjbs4.js} +50 -58
- package/build/{auth-7ay8qgxm.js → auth-038hsg1s.js} +61 -68
- package/build/blackboxAgent-fjrv4q3d.js +13 -0
- package/build/blackboxPentest-6dtb7vnq.js +59 -0
- package/build/{cli-73k43t1r.js → cli-17ndymmb.js} +53 -78
- package/build/{cli-3py0a0wg.js → cli-1rwe9a9v.js} +206 -136
- package/build/{cli-y3dpm18e.js → cli-2tfnaeca.js} +75 -92
- package/build/{cli-ee3axgts.js → cli-3gt761d2.js} +7 -1
- package/build/cli-3qznjsnr.js +14 -0
- package/build/{cli-sx3jkv7p.js → cli-3w0mx2mv.js} +28872 -25951
- package/build/cli-5qq1655n.js +175 -0
- package/build/{cli-53rm0rrz.js → cli-8w8k4dph.js} +1 -1
- package/build/{cli-68260ckj.js → cli-91gs9whc.js} +1658 -1606
- package/build/cli-99gxp2yb.js +62 -0
- package/build/cli-ayqhdajr.js +22 -0
- package/build/{cli-knd276ed.js → cli-bb02pjt0.js} +31 -31
- package/build/{cli-p4r7q012.js → cli-bw31v3z7.js} +16743 -13352
- package/build/{cli-j54qa6tm.js → cli-c2k4xxaw.js} +42 -42
- package/build/{cli-z5c0ypg1.js → cli-czwr2xmh.js} +4 -4
- package/build/{cli-k71t434r.js → cli-ec2hwkv3.js} +34 -76
- package/build/{cli-vkbzcnw1.js → cli-fxmref08.js} +43 -40
- package/build/cli-g06s7edq.js +11 -0
- package/build/cli-gsaf4jk3.js +280 -0
- package/build/{cli-bc05qbss.js → cli-h6y3bt60.js} +13 -21
- package/build/cli-jdrx44ge.js +14 -0
- package/build/{cli-x92fkt2f.js → cli-m3btkdbx.js} +55 -97
- package/build/cli-mdk51kby.js +429 -0
- package/build/{cli-bw2ddttk.js → cli-mnpzhtg6.js} +4730 -267
- package/build/cli-mz5pk30x.js +5508 -0
- package/build/cli-pwm29ks7.js +6337 -0
- package/build/cli-retw3rw5.js +12 -0
- package/build/{cli-kff2bbq7.js → cli-rxj14t82.js} +43 -43
- package/build/cli-se8ae8z3.js +2250 -0
- package/build/cli-skedjgqy.js +186 -0
- package/build/{cli-dm0fc0bm.js → cli-v1sarr4y.js} +5 -9
- package/build/cli-vfzpbv3g.js +355 -0
- package/build/cli-xcy2vxj2.js +1732 -0
- package/build/{cli-zav1yx5k.js → cli-yn4sj3z1.js} +990 -632
- package/build/{cli-7vg06q5r.js → cli-zsq8kfgc.js} +135 -125
- package/build/cli.js +769 -195
- package/build/{config-4kzh88xz.js → config-4emx9c35.js} +16 -19
- package/build/{doctor-rz7sx6ev.js → doctor-z94afr10.js} +26 -15
- package/build/export-trajectory-rt4tf07k.js +112 -0
- package/build/{fastStrike-a54atjc8.js → fastStrike-mnn8g4ay.js} +56 -31
- package/build/{fixes-fv66yn1z.js → fixes-hm5569vq.js} +22 -30
- package/build/{getMachineId-bsd-xj3bn2fv.js → getMachineId-bsd-zr67nd9p.js} +5 -5
- package/build/{getMachineId-darwin-07jzjcx6.js → getMachineId-darwin-fd1d562d.js} +5 -5
- package/build/{getMachineId-linux-ahngynxd.js → getMachineId-linux-kjmg243j.js} +4 -4
- package/build/{getMachineId-unsupported-vy43b44z.js → getMachineId-unsupported-n4r58vke.js} +4 -4
- package/build/{getMachineId-win-8x66cynz.js → getMachineId-win-yzgpfsrb.js} +5 -5
- package/build/index-0yfxwj9h.js +25 -0
- package/build/{index-kyd1jm89.js → index-1qjwwg4x.js} +159 -169
- package/build/index-939ypn8a.js +12 -0
- package/build/index-a0bxw5zq.js +17477 -0
- package/build/{index-cbwn03kz.js → index-a2xycbjs.js} +12 -31
- package/build/{index-psqjpw5m.js → index-c1h0g35p.js} +11 -11
- package/build/{index-fpwr10qm.js → index-f2xpfw4x.js} +5106 -3803
- package/build/index-g9akqryt.js +9 -0
- package/build/index-mrrfbsyz.js +17 -0
- package/build/index-qnyevb6q.js +1563 -0
- package/build/index-ttwhf2se.js +36 -0
- package/build/index-vy2pm5zf.js +121 -0
- package/build/index-x8ab8x86.js +102 -0
- package/build/{issues-019678t0.js → issues-wxd3ca1d.js} +51 -47
- package/build/knowledge-rvcpbak8.js +139 -0
- package/build/lib/chunk-0y40tebt.js +102 -0
- package/build/lib/chunk-0ydfy4hq.js +510 -0
- package/build/lib/chunk-2njv7wz3.js +178 -0
- package/build/lib/chunk-3q89v4xv.js +21 -0
- package/build/lib/chunk-4p2n69vn.js +62 -0
- package/build/lib/chunk-7gjdygcx.js +171 -0
- package/build/lib/chunk-8d8w07a9.js +431 -0
- package/build/lib/chunk-8dqz8cwa.js +27 -0
- package/build/lib/chunk-8vhr65w3.js +272 -0
- package/build/lib/chunk-8xnzgfs0.js +56 -0
- package/build/lib/chunk-9nsrd4xg.js +12 -0
- package/build/lib/chunk-a3gxgj9r.js +317 -0
- package/build/lib/chunk-afef65e0.js +7150 -0
- package/build/lib/chunk-b8eq85d2.js +143 -0
- package/build/lib/chunk-bqrmw2tn.js +439 -0
- package/build/lib/chunk-bx94rwt5.js +24 -0
- package/build/lib/chunk-c2b0hxs7.js +143 -0
- package/build/lib/chunk-cwj17b1f.js +345 -0
- package/build/lib/chunk-cx7yrzh1.js +2429 -0
- package/build/lib/chunk-eb4h4k1f.js +213 -0
- package/build/lib/chunk-esymacwg.js +14 -0
- package/build/lib/chunk-fy3bbbqy.js +7896 -0
- package/build/lib/chunk-gdrv2h1p.js +11157 -0
- package/build/lib/chunk-ja7j565c.js +743 -0
- package/build/lib/chunk-jdjagvgr.js +85 -0
- package/build/lib/chunk-k4rz1yvj.js +31 -0
- package/build/lib/chunk-kfvq4m1s.js +685 -0
- package/build/lib/chunk-mgppdr6j.js +980 -0
- package/build/lib/chunk-mhxe717m.js +572 -0
- package/build/lib/chunk-mv74mq5n.js +59 -0
- package/build/lib/chunk-n0ba7khr.js +64 -0
- package/build/lib/chunk-q5e23acz.js +52 -0
- package/build/lib/chunk-q8bk9dys.js +922 -0
- package/build/lib/chunk-sgd2126b.js +9294 -0
- package/build/lib/chunk-t5bt5vn1.js +146 -0
- package/build/lib/chunk-v2q8anzw.js +120 -0
- package/build/lib/chunk-vd6hr8pm.js +212 -0
- package/build/lib/chunk-ve7m90fb.js +317 -0
- package/build/lib/chunk-vx228eeq.js +82 -0
- package/build/lib/chunk-wchtd611.js +186 -0
- package/build/lib/chunk-ws86wx87.js +1412 -0
- package/build/lib/chunk-xpfg2fbk.js +90 -0
- package/build/lib/chunk-zrbqn62x.js +697 -0
- package/build/lib/core/agents/agentRuntime.d.ts +47 -0
- package/build/lib/core/agents/defineAgent.d.ts +82 -0
- package/build/lib/core/agents/offSecAgent/index.d.ts +9 -0
- package/build/lib/core/agents/offSecAgent/index.js +225 -0
- package/build/lib/core/agents/offSecAgent/interruptedStepFinalization.d.ts +23 -0
- package/build/lib/core/agents/offSecAgent/interruptedStepMessages.d.ts +42 -0
- package/build/lib/core/agents/offSecAgent/messagePersistence.d.ts +39 -0
- package/build/lib/core/agents/offSecAgent/offensiveSecurityAgent.d.ts +233 -0
- package/build/lib/core/agents/offSecAgent/prompt.d.ts +35 -0
- package/build/lib/core/agents/offSecAgent/recordedTools.d.ts +11 -0
- package/build/lib/core/agents/offSecAgent/runtimeContext.d.ts +43 -0
- package/build/lib/core/agents/offSecAgent/streamDiagnostics.d.ts +67 -0
- package/build/lib/core/agents/offSecAgent/subagentSpawner.d.ts +223 -0
- package/build/lib/core/agents/offSecAgent/subagentSpawner.js +19 -0
- package/build/lib/core/agents/offSecAgent/toolLifecycle.d.ts +54 -0
- package/build/lib/core/agents/offSecAgent/tools/__tests__/sandboxScript.d.ts +1 -0
- package/build/lib/core/agents/offSecAgent/tools/addMemory.d.ts +16 -0
- package/build/lib/core/agents/offSecAgent/tools/agentScratch.d.ts +17 -0
- package/build/lib/core/agents/offSecAgent/tools/applyPatch.d.ts +8 -0
- package/build/lib/core/agents/offSecAgent/tools/applyPatchImpl.d.ts +24 -0
- package/build/lib/core/agents/offSecAgent/tools/askUserQuestions.d.ts +42 -0
- package/build/lib/core/agents/offSecAgent/tools/browserHeaderRouting.d.ts +9 -0
- package/build/lib/core/agents/offSecAgent/tools/browserToolFactories.d.ts +40 -0
- package/build/lib/core/agents/offSecAgent/tools/browserTools.d.ts +96 -0
- package/build/lib/core/agents/offSecAgent/tools/callbackListener.d.ts +212 -0
- package/build/lib/core/agents/offSecAgent/tools/camoufox.d.ts +106 -0
- package/build/lib/core/agents/offSecAgent/tools/checkpointState.d.ts +17 -0
- package/build/lib/core/agents/offSecAgent/tools/completeAuthentication.d.ts +39 -0
- package/build/lib/core/agents/offSecAgent/tools/crawlAuthenticated.d.ts +36 -0
- package/build/lib/core/agents/offSecAgent/tools/createAttackSurfaceReport.d.ts +31 -0
- package/build/lib/core/agents/offSecAgent/tools/createFile.d.ts +12 -0
- package/build/lib/core/agents/offSecAgent/tools/createTask.d.ts +20 -0
- package/build/lib/core/agents/offSecAgent/tools/delegateAuth.d.ts +72 -0
- package/build/lib/core/agents/offSecAgent/tools/deleteFile.d.ts +10 -0
- package/build/lib/core/agents/offSecAgent/tools/destructiveGuard.d.ts +94 -0
- package/build/lib/core/agents/offSecAgent/tools/detectAuthScheme.d.ts +72 -0
- package/build/lib/core/agents/offSecAgent/tools/documentApp.d.ts +38 -0
- package/build/lib/core/agents/offSecAgent/tools/documentEndpoint.d.ts +111 -0
- package/build/lib/core/agents/offSecAgent/tools/documentFinding.d.ts +285 -0
- package/build/lib/core/agents/offSecAgent/tools/email/adapters.d.ts +45 -0
- package/build/lib/core/agents/offSecAgent/tools/email/adapters.js +8 -0
- package/build/lib/core/agents/offSecAgent/tools/email/getAttachments.d.ts +33 -0
- package/build/lib/core/agents/offSecAgent/tools/email/getMessage.d.ts +20 -0
- package/build/lib/core/agents/offSecAgent/tools/email/index.d.ts +145 -0
- package/build/lib/core/agents/offSecAgent/tools/email/listInboxes.d.ts +23 -0
- package/build/lib/core/agents/offSecAgent/tools/email/listMessages.d.ts +22 -0
- package/build/lib/core/agents/offSecAgent/tools/email/markRead.d.ts +20 -0
- package/build/lib/core/agents/offSecAgent/tools/email/searchMessages.d.ts +24 -0
- package/build/lib/core/agents/offSecAgent/tools/email/sendEmail.d.ts +28 -0
- package/build/lib/core/agents/offSecAgent/tools/email/types.d.ts +40 -0
- package/build/lib/core/agents/offSecAgent/tools/email/types.js +0 -0
- package/build/lib/core/agents/offSecAgent/tools/executeCommand.d.ts +84 -0
- package/build/lib/core/agents/offSecAgent/tools/extractJsEndpoints.d.ts +13 -0
- package/build/lib/core/agents/offSecAgent/tools/fileWorkspace.d.ts +21 -0
- package/build/lib/core/agents/offSecAgent/tools/fileWorkspaceRemote.d.ts +13 -0
- package/build/lib/core/agents/offSecAgent/tools/getMemory.d.ts +12 -0
- package/build/lib/core/agents/offSecAgent/tools/getPage.d.ts +17 -0
- package/build/lib/core/agents/offSecAgent/tools/gitDiff.d.ts +12 -0
- package/build/lib/core/agents/offSecAgent/tools/gitStatus.d.ts +10 -0
- package/build/lib/core/agents/offSecAgent/tools/glob.d.ts +8 -0
- package/build/lib/core/agents/offSecAgent/tools/globImpl.d.ts +13 -0
- package/build/lib/core/agents/offSecAgent/tools/globPattern.d.ts +7 -0
- package/build/lib/core/agents/offSecAgent/tools/grep.d.ts +10 -0
- package/build/lib/core/agents/offSecAgent/tools/grepImpl.d.ts +34 -0
- package/build/lib/core/agents/offSecAgent/tools/httpRequest.d.ts +70 -0
- package/build/lib/core/agents/offSecAgent/tools/index.d.ts +466 -0
- package/build/lib/core/agents/offSecAgent/tools/index.js +262 -0
- package/build/lib/core/agents/offSecAgent/tools/listFiles.d.ts +9 -0
- package/build/lib/core/agents/offSecAgent/tools/listFilesImpl.d.ts +27 -0
- package/build/lib/core/agents/offSecAgent/tools/listMemories.d.ts +13 -0
- package/build/lib/core/agents/offSecAgent/tools/listPromptInjections.d.ts +18 -0
- package/build/lib/core/agents/offSecAgent/tools/listTasks.d.ts +24 -0
- package/build/lib/core/agents/offSecAgent/tools/patchApply.d.ts +24 -0
- package/build/lib/core/agents/offSecAgent/tools/patchParse.d.ts +24 -0
- package/build/lib/core/agents/offSecAgent/tools/perCommandShell.d.ts +82 -0
- package/build/lib/core/agents/offSecAgent/tools/playwrightMcp.d.ts +369 -0
- package/build/lib/core/agents/offSecAgent/tools/probeAuthEndpoints.d.ts +28 -0
- package/build/lib/core/agents/offSecAgent/tools/profileCodebase.d.ts +33 -0
- package/build/lib/core/agents/offSecAgent/tools/provideComparisonResults.d.ts +31 -0
- package/build/lib/core/agents/offSecAgent/tools/queryWhiteboxCatalog.d.ts +17 -0
- package/build/lib/core/agents/offSecAgent/tools/readFile.d.ts +11 -0
- package/build/lib/core/agents/offSecAgent/tools/readFileImpl.d.ts +31 -0
- package/build/lib/core/agents/offSecAgent/tools/readSkill.d.ts +15 -0
- package/build/lib/core/agents/offSecAgent/tools/reportError.d.ts +31 -0
- package/build/lib/core/agents/offSecAgent/tools/response.d.ts +15 -0
- package/build/lib/core/agents/offSecAgent/tools/runAttackSurface.d.ts +81 -0
- package/build/lib/core/agents/offSecAgent/tools/runCodeQuery.d.ts +44 -0
- package/build/lib/core/agents/offSecAgent/tools/runPentestWorkflow.d.ts +32 -0
- package/build/lib/core/agents/offSecAgent/tools/runWhiteboxScan.d.ts +52 -0
- package/build/lib/core/agents/offSecAgent/tools/sandbox.d.ts +30 -0
- package/build/lib/core/agents/offSecAgent/tools/sandboxPlaywright.d.ts +137 -0
- package/build/lib/core/agents/offSecAgent/tools/sandboxScript.d.ts +6 -0
- package/build/lib/core/agents/offSecAgent/tools/scopeGuard.d.ts +91 -0
- package/build/lib/core/agents/offSecAgent/tools/scriptSyntaxCheck.d.ts +45 -0
- package/build/lib/core/agents/offSecAgent/tools/smsInbox.d.ts +67 -0
- package/build/lib/core/agents/offSecAgent/tools/smsInbox.js +6 -0
- package/build/lib/core/agents/offSecAgent/tools/smsListMessages.d.ts +29 -0
- package/build/lib/core/agents/offSecAgent/tools/spawnCodingAgent.d.ts +43 -0
- package/build/lib/core/agents/offSecAgent/tools/spawnPentestAgent.d.ts +51 -0
- package/build/lib/core/agents/offSecAgent/tools/spawnPentestSwarm.d.ts +52 -0
- package/build/lib/core/agents/offSecAgent/tools/submitPlan.d.ts +12 -0
- package/build/lib/core/agents/offSecAgent/tools/testEndpointVariations.d.ts +34 -0
- package/build/lib/core/agents/offSecAgent/tools/threatModelGenerator.d.ts +32 -0
- package/build/lib/core/agents/offSecAgent/tools/toolOutput.d.ts +23 -0
- package/build/lib/core/agents/offSecAgent/tools/types.d.ts +215 -0
- package/build/lib/core/agents/offSecAgent/tools/updateFile.d.ts +14 -0
- package/build/lib/core/agents/offSecAgent/tools/updateTask.d.ts +20 -0
- package/build/lib/core/agents/offSecAgent/tools/validateDiscovery.d.ts +24 -0
- package/build/lib/core/agents/offSecAgent/tools/webSearch.d.ts +16 -0
- package/build/lib/core/agents/offSecAgent/tools/whiteboxCandidates.d.ts +108 -0
- package/build/lib/core/agents/offSecAgent/tools/whiteboxJobs.d.ts +157 -0
- package/build/lib/core/agents/offSecAgent/tools/windowsCurl.d.ts +20 -0
- package/build/lib/core/agents/offSecAgent/tools/workspaceApps.d.ts +120 -0
- package/build/lib/core/agents/offSecAgent/tools/workspaceDomains.d.ts +22 -0
- package/build/lib/core/agents/offSecAgent/tools/workspaceFailure.d.ts +6 -0
- package/build/lib/core/agents/offSecAgent/tools/writePlan.d.ts +13 -0
- package/build/lib/core/agents/offSecAgent/trace.d.ts +268 -0
- package/build/lib/core/agents/offSecAgent/types.d.ts +543 -0
- package/build/lib/core/agents/offSecAgent/types.js +7 -0
- package/build/lib/core/agents/specialized/attackSurface/blackboxAgent.d.ts +66 -0
- package/build/lib/core/agents/specialized/attackSurface/blackboxAgent.js +33 -0
- package/build/lib/core/agents/specialized/attackSurface/blackboxRiskScoring.d.ts +30 -0
- package/build/lib/core/agents/specialized/attackSurface/grpcSchema.d.ts +93 -0
- package/build/lib/core/agents/specialized/attackSurface/jsExtraction.d.ts +42 -0
- package/build/lib/core/agents/specialized/attackSurface/prompts.d.ts +1 -0
- package/build/lib/core/agents/specialized/attackSurface/schemas.d.ts +284 -0
- package/build/lib/core/agents/specialized/attackSurface/schemas.js +144 -0
- package/build/lib/core/agents/specialized/attackSurface/types.d.ts +32 -0
- package/build/lib/core/agents/specialized/authenticationAgent/agent.d.ts +73 -0
- package/build/lib/core/agents/specialized/authenticationAgent/index.d.ts +4 -0
- package/build/lib/core/agents/specialized/authenticationAgent/index.js +71 -0
- package/build/lib/core/agents/specialized/authenticationAgent/prompts.d.ts +10 -0
- package/build/lib/core/agents/specialized/authenticationAgent/types.d.ts +620 -0
- package/build/lib/core/agents/specialized/benchmark/comparisonAgent.d.ts +10 -0
- package/build/lib/core/agents/specialized/benchmark/docker-utils.d.ts +17 -0
- package/build/lib/core/agents/specialized/benchmark/flag-detector.d.ts +60 -0
- package/build/lib/core/agents/specialized/benchmark/index.d.ts +8 -0
- package/build/lib/core/agents/specialized/benchmark/prompts.d.ts +1 -0
- package/build/lib/core/agents/specialized/benchmark/remote/circuit-breaker.d.ts +22 -0
- package/build/lib/core/agents/specialized/benchmark/remote/daytona-wrapper.d.ts +33 -0
- package/build/lib/core/agents/specialized/benchmark/remote/index.d.ts +2 -0
- package/build/lib/core/agents/specialized/benchmark/types.d.ts +92 -0
- package/build/lib/core/agents/specialized/benchmarkComparisonAgent.d.ts +27 -0
- package/build/lib/core/agents/specialized/codeAgent/agent.d.ts +50 -0
- package/build/lib/core/agents/specialized/codeAgent/agent.js +31 -0
- package/build/lib/core/agents/specialized/codeAgent/prompts.d.ts +1 -0
- package/build/lib/core/agents/specialized/codeAgent/schemas.d.ts +11 -0
- package/build/lib/core/agents/specialized/codeAgent/schemas.js +10 -0
- package/build/lib/core/agents/specialized/cvssScorer/index.d.ts +56 -0
- package/build/lib/core/agents/specialized/environment/agent.d.ts +43 -0
- package/build/lib/core/agents/specialized/environment/index.d.ts +4 -0
- package/build/lib/core/agents/specialized/environment/prompts.d.ts +10 -0
- package/build/lib/core/agents/specialized/environment/types.d.ts +37 -0
- package/build/lib/core/agents/specialized/findingJudge/agent.d.ts +22 -0
- package/build/lib/core/agents/specialized/findingJudge/agent.js +224 -0
- package/build/lib/core/agents/specialized/findingJudge/index.d.ts +31 -0
- package/build/lib/core/agents/specialized/findingJudge/index.js +13 -0
- package/build/lib/core/agents/specialized/findingJudge/prompts.d.ts +3 -0
- package/build/lib/core/agents/specialized/findingJudge/types.d.ts +77 -0
- package/build/lib/core/agents/specialized/googleSignInPrompt.d.ts +4 -0
- package/build/lib/core/agents/specialized/mobileOtpPrompt.d.ts +1 -0
- package/build/lib/core/agents/specialized/patching/agent.d.ts +64 -0
- package/build/lib/core/agents/specialized/patching/index.d.ts +4 -0
- package/build/lib/core/agents/specialized/patching/index.js +44 -0
- package/build/lib/core/agents/specialized/patching/prompts.d.ts +17 -0
- package/build/lib/core/agents/specialized/patching/types.d.ts +40 -0
- package/build/lib/core/agents/specialized/pentest/agent.d.ts +172 -0
- package/build/lib/core/agents/specialized/pentest/agent.js +43 -0
- package/build/lib/core/agents/specialized/pentest/helperWorkspace.d.ts +16 -0
- package/build/lib/core/agents/specialized/pentest/planPrompt.d.ts +13 -0
- package/build/lib/core/agents/specialized/utils.d.ts +7 -0
- package/build/lib/core/agents/specialized/vulnerabilityReproduction/agent.d.ts +94 -0
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/agent.d.ts +148 -0
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.d.ts +61 -0
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/index.d.ts +5 -0
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/index.js +47 -0
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/prompts.d.ts +34 -0
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/types.d.ts +382 -0
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/types.js +21 -0
- package/build/lib/core/ai/ai.d.ts +342 -0
- package/build/lib/core/ai/ai.js +68 -0
- package/build/lib/core/ai/caching.d.ts +26 -0
- package/build/lib/core/ai/compactionEvidence.d.ts +15 -0
- package/build/lib/core/ai/compactionTelemetry.d.ts +55 -0
- package/build/lib/core/ai/contextManagement.d.ts +85 -0
- package/build/lib/core/ai/index.d.ts +10 -0
- package/build/lib/core/ai/index.js +72 -0
- package/build/lib/core/ai/inference-attempt/adapters.d.ts +15 -0
- package/build/lib/core/ai/inference-attempt/builder.d.ts +31 -0
- package/build/lib/core/ai/inference-attempt/envelope.d.ts +120 -0
- package/build/lib/core/ai/inference-attempt/errors.d.ts +6 -0
- package/build/lib/core/ai/inference-attempt/identity.d.ts +13 -0
- package/build/lib/core/ai/inference-attempt/index.d.ts +36 -0
- package/build/lib/core/ai/inference-attempt/project.d.ts +21 -0
- package/build/lib/core/ai/inference-attempt/recording.d.ts +23 -0
- package/build/lib/core/ai/inference-attempt/tokens.d.ts +13 -0
- package/build/lib/core/ai/inference-attempt/validate.d.ts +2 -0
- package/build/lib/core/ai/mantle.d.ts +28 -0
- package/build/lib/core/ai/model-history.d.ts +4 -0
- package/build/lib/core/ai/models/anthropic.d.ts +2 -0
- package/build/lib/core/ai/models/bedrock.d.ts +2 -0
- package/build/lib/core/ai/models/claude-capabilities.d.ts +7 -0
- package/build/lib/core/ai/models/concentrate.d.ts +2 -0
- package/build/lib/core/ai/models/google.d.ts +2 -0
- package/build/lib/core/ai/models/inception.d.ts +2 -0
- package/build/lib/core/ai/models/index.d.ts +29 -0
- package/build/lib/core/ai/models/mantle.d.ts +2 -0
- package/build/lib/core/ai/models/openai.d.ts +2 -0
- package/build/lib/core/ai/models/openrouter.d.ts +2 -0
- package/build/lib/core/ai/models/pensar.d.ts +2 -0
- package/build/lib/core/ai/native-rollout-evidence/capture.d.ts +31 -0
- package/build/lib/core/ai/native-rollout-evidence/content.d.ts +14 -0
- package/build/lib/core/ai/native-rollout-evidence/index.d.ts +9 -0
- package/build/lib/core/ai/native-rollout-evidence/provider-metadata.d.ts +15 -0
- package/build/lib/core/ai/native-rollout-evidence/schema.d.ts +554 -0
- package/build/lib/core/ai/native-rollout-evidence/validate.d.ts +8 -0
- package/build/lib/core/ai/providers/anthropic.d.ts +2 -0
- package/build/lib/core/ai/providers/concentrate.d.ts +9 -0
- package/build/lib/core/ai/providers/custom.d.ts +3 -0
- package/build/lib/core/ai/providers/hoonify.d.ts +6 -0
- package/build/lib/core/ai/providers/openai-pro-fetch.d.ts +2 -0
- package/build/lib/core/ai/providers/pensar.d.ts +34 -0
- package/build/lib/core/ai/providers/pensarFormatters.d.ts +2 -0
- package/build/lib/core/ai/providers/pensarResponsesStream.d.ts +15 -0
- package/build/lib/core/ai/providers/pensarSSE.d.ts +23 -0
- package/build/lib/core/ai/providers/pensarSigning.d.ts +1 -0
- package/build/lib/core/ai/providers/pensarStreamUsage.d.ts +19 -0
- package/build/lib/core/ai/streamTelemetry.d.ts +22 -0
- package/build/lib/core/ai/utils.d.ts +90 -0
- package/build/lib/core/ai/utils.js +22 -0
- package/build/lib/core/api/apiClient.d.ts +7 -0
- package/build/lib/core/api/apps.d.ts +213 -0
- package/build/lib/core/api/attackSurface.d.ts +14 -0
- package/build/lib/core/api/authentication.d.ts +3 -0
- package/build/lib/core/api/benchmark.d.ts +5 -0
- package/build/lib/core/api/blackboxPentest.d.ts +11 -0
- package/build/lib/core/api/clientIdentity.d.ts +10 -0
- package/build/lib/core/api/constants.d.ts +5 -0
- package/build/lib/core/api/domains.d.ts +19 -0
- package/build/lib/core/api/environment.d.ts +16 -0
- package/build/lib/core/api/index.d.ts +41 -0
- package/build/lib/core/api/index.js +187 -0
- package/build/lib/core/api/issues.d.ts +273 -0
- package/build/lib/core/api/knowledge.d.ts +33 -0
- package/build/lib/core/api/localWorker.d.ts +4 -0
- package/build/lib/core/api/offesecAgent.d.ts +34 -0
- package/build/lib/core/api/patching.d.ts +15 -0
- package/build/lib/core/api/recordedRun.d.ts +36 -0
- package/build/lib/core/api/targetedPentest.d.ts +15 -0
- package/build/lib/core/api/targetedPentest.js +32 -0
- package/build/lib/core/api/threatModel.d.ts +1 -0
- package/build/lib/core/api/trajectoryExport.d.ts +38 -0
- package/build/lib/core/api/vulnerabilityReproduction.d.ts +10 -0
- package/build/lib/core/assets/wordlists.d.ts +31 -0
- package/build/lib/core/atif/convert.d.ts +27 -0
- package/build/lib/core/atif/index.d.ts +7 -0
- package/build/lib/core/atif/schema.d.ts +459 -0
- package/build/lib/core/atif/serialize.d.ts +2 -0
- package/build/lib/core/atif/test-fixtures.d.ts +28 -0
- package/build/lib/core/atif/validate.d.ts +12 -0
- package/build/lib/core/auth/connection.d.ts +12 -0
- package/build/lib/core/auth/device-flow.d.ts +38 -0
- package/build/lib/core/auth/gateway.d.ts +25 -0
- package/build/lib/core/auth/index.d.ts +8 -0
- package/build/lib/core/auth/signing.d.ts +14 -0
- package/build/lib/core/auth/token.d.ts +17 -0
- package/build/lib/core/auth/types.d.ts +85 -0
- package/build/lib/core/auth/workspaces.d.ts +34 -0
- package/build/lib/core/benchmark/index.d.ts +3 -0
- package/build/lib/core/benchmark/report.d.ts +3 -0
- package/build/lib/core/benchmark/runner.d.ts +3 -0
- package/build/lib/core/benchmark/types.d.ts +80 -0
- package/build/lib/core/cli/logLevelArgs.d.ts +18 -0
- package/build/lib/core/cli/model.d.ts +9 -0
- package/build/lib/core/cli/pentestMode.d.ts +5 -0
- package/build/lib/core/cli/tuiArgs.d.ts +5 -0
- package/build/lib/core/config/config.d.ts +86 -0
- package/build/lib/core/config/customProviders.d.ts +62 -0
- package/build/lib/core/config/index.d.ts +6 -0
- package/build/lib/core/config/index.js +6 -0
- package/build/lib/core/credentials/index.d.ts +2 -0
- package/build/lib/core/credentials/manager.d.ts +85 -0
- package/build/lib/core/credentials/types.d.ts +79 -0
- package/build/lib/core/doctor.d.ts +1 -0
- package/build/lib/core/eventBus.d.ts +195 -0
- package/build/lib/core/eventBus.js +6 -0
- package/build/lib/core/findings/attackSurfaceRegistry.d.ts +88 -0
- package/build/lib/core/findings/attackSurfaceRegistry.js +6 -0
- package/build/lib/core/findings/registry.d.ts +177 -0
- package/build/lib/core/findings/registry.js +21 -0
- package/build/lib/core/history.d.ts +23 -0
- package/build/lib/core/hoonify.d.ts +8 -0
- package/build/lib/core/http/parse.d.ts +50 -0
- package/build/lib/core/http/redirects.d.ts +23 -0
- package/build/lib/core/http/targetHeaders.d.ts +30 -0
- package/build/lib/core/http/targetScope.d.ts +12 -0
- package/build/lib/core/http/types.d.ts +11 -0
- package/build/lib/core/id/id.d.ts +60 -0
- package/build/lib/core/id/id.js +28 -0
- package/build/lib/core/installation/index.d.ts +25 -0
- package/build/lib/core/integrations/herdr.d.ts +13 -0
- package/build/lib/core/integrations/surface/index.d.ts +37 -0
- package/build/lib/core/integrations/surface/types.d.ts +22 -0
- package/build/lib/core/integrations/wandb/client.d.ts +23 -0
- package/build/lib/core/integrations/wandb/upload.d.ts +36 -0
- package/build/lib/core/logger/index.d.ts +62 -0
- package/build/lib/core/logger/structured.d.ts +30 -0
- package/build/lib/core/memory/index.d.ts +92 -0
- package/build/lib/core/memory/index.js +21 -0
- package/build/lib/core/messages/types.d.ts +96 -0
- package/build/lib/core/obfuscation/engine.d.ts +51 -0
- package/build/lib/core/obfuscation/index.d.ts +20 -0
- package/build/lib/core/observability/active-root-spans.d.ts +5 -0
- package/build/lib/core/observability/active-spans.d.ts +22 -0
- package/build/lib/core/observability/index.d.ts +36 -0
- package/build/lib/core/observability/index.js +27 -0
- package/build/lib/core/observability/runtime.d.ts +63 -0
- package/build/lib/core/observability/telemetry.d.ts +52 -0
- package/build/lib/core/observability/testkit.d.ts +24 -0
- package/build/lib/core/operator/approvalGate.d.ts +61 -0
- package/build/lib/core/operator/index.d.ts +9 -0
- package/build/lib/core/operator/types.d.ts +167 -0
- package/build/lib/core/plan/index.d.ts +16 -0
- package/build/lib/core/prompt-injections/index.d.ts +111 -0
- package/build/lib/core/prompt-injections/index.js +24 -0
- package/build/lib/core/providers/index.d.ts +5 -0
- package/build/lib/core/providers/types.d.ts +13 -0
- package/build/lib/core/providers/utils.d.ts +15 -0
- package/build/lib/core/providers/verify.d.ts +11 -0
- package/build/lib/core/report/builder.d.ts +9 -0
- package/build/lib/core/report/index.d.ts +7 -0
- package/build/lib/core/report/renderers/json.d.ts +2 -0
- package/build/lib/core/report/renderers/markdown.d.ts +2 -0
- package/build/lib/core/report/schemas.d.ts +115 -0
- package/build/lib/core/runtime/agentExecution.d.ts +15 -0
- package/build/lib/core/runtime/launchLocalWorker.d.ts +33 -0
- package/build/lib/core/runtime/localRunLock.d.ts +9 -0
- package/build/lib/core/runtime/localRunWorker.d.ts +18 -0
- package/build/lib/core/runtime/localWorkerEndpoint.d.ts +14 -0
- package/build/lib/core/runtime/localWorkerProtocol.d.ts +294 -0
- package/build/lib/core/runtime/localWorkerTransport.d.ts +30 -0
- package/build/lib/core/runtime/persistenceError.d.ts +9 -0
- package/build/lib/core/runtime/recordedExecution.d.ts +6 -0
- package/build/lib/core/runtime/recordedRunClient.d.ts +34 -0
- package/build/lib/core/runtime/runCheckpointStore.d.ts +11 -0
- package/build/lib/core/runtime/runContext.d.ts +48 -0
- package/build/lib/core/runtime/runControl.d.ts +44 -0
- package/build/lib/core/runtime/runControlStore.d.ts +83 -0
- package/build/lib/core/runtime/runDeadline.d.ts +4 -0
- package/build/lib/core/runtime/runEvidence.d.ts +37 -0
- package/build/lib/core/runtime/runInference.d.ts +9 -0
- package/build/lib/core/runtime/runModelStore.d.ts +27 -0
- package/build/lib/core/runtime/runObservation.d.ts +19 -0
- package/build/lib/core/runtime/runRecoveryContext.d.ts +20 -0
- package/build/lib/core/runtime/runRecoveryPlan.d.ts +38 -0
- package/build/lib/core/runtime/runRecoveryStore.d.ts +77 -0
- package/build/lib/core/runtime/runStore.d.ts +133 -0
- package/build/lib/core/runtime/runStorePath.d.ts +1 -0
- package/build/lib/core/runtime/runToolStore.d.ts +50 -0
- package/build/lib/core/runtime/runTools.d.ts +16 -0
- package/build/lib/core/runtime/sqliteControlStore.d.ts +41 -0
- package/build/lib/core/runtime/sqliteModelStore.d.ts +20 -0
- package/build/lib/core/runtime/sqliteRecoveryStore.d.ts +35 -0
- package/build/lib/core/runtime/sqliteRunStore.d.ts +8 -0
- package/build/lib/core/runtime/sqliteToolStore.d.ts +30 -0
- package/build/lib/core/runtime/testfixtures/localWorkerChild.d.ts +1 -0
- package/build/lib/core/runtime/testfixtures/localWorkerLauncher.d.ts +1 -0
- package/build/lib/core/runtime/testfixtures/recoveryChild.d.ts +1 -0
- package/build/lib/core/services/rateLimiter/index.d.ts +36 -0
- package/build/lib/core/services/rateLimiter/types.d.ts +10 -0
- package/build/lib/core/session/execution-metrics.d.ts +37 -0
- package/build/lib/core/session/index.d.ts +586 -0
- package/build/lib/core/session/index.js +36 -0
- package/build/lib/core/session/loader.d.ts +30 -0
- package/build/lib/core/session/persistence.d.ts +215 -0
- package/build/lib/core/session/persistence.js +35 -0
- package/build/lib/core/session/types.d.ts +59 -0
- package/build/lib/core/session/usage.d.ts +37 -0
- package/build/lib/core/skills/builtins/index.d.ts +13 -0
- package/build/lib/core/skills/builtins/pentest.d.ts +19 -0
- package/build/lib/core/skills/builtins/promptInjection.d.ts +2 -0
- package/build/lib/core/skills/builtins/threatModel.d.ts +11 -0
- package/build/lib/core/skills/index.d.ts +5 -0
- package/build/lib/core/skills/parser.d.ts +11 -0
- package/build/lib/core/skills/registry.d.ts +30 -0
- package/build/lib/core/skills/scanner.d.ts +12 -0
- package/build/lib/core/skills/types.d.ts +44 -0
- package/build/lib/core/skills/utils.d.ts +6 -0
- package/build/lib/core/storage/index.d.ts +248 -0
- package/build/lib/core/tasks/index.d.ts +78 -0
- package/build/lib/core/tools/backends/capture.d.ts +10 -0
- package/build/lib/core/tools/backends/collectCommand.d.ts +9 -0
- package/build/lib/core/tools/backends/helpers.d.ts +43 -0
- package/build/lib/core/tools/backends/httpTransport.d.ts +18 -0
- package/build/lib/core/tools/backends/index.d.ts +8 -0
- package/build/lib/core/tools/backends/index.js +31 -0
- package/build/lib/core/tools/backends/local.d.ts +11 -0
- package/build/lib/core/tools/backends/policy.d.ts +39 -0
- package/build/lib/core/tools/backends/resolve.d.ts +25 -0
- package/build/lib/core/tools/backends/types.d.ts +240 -0
- package/build/lib/core/tools/backends/whitebox.d.ts +6 -0
- package/build/lib/core/tools/backends/whiteboxJobs.d.ts +18 -0
- package/build/lib/core/tools/backends/windowsProgram.d.ts +4 -0
- package/build/lib/core/tools/daytonaSandbox.d.ts +14 -0
- package/build/lib/core/toolset/index.d.ts +28 -0
- package/build/lib/core/util/lazyLogger.d.ts +16 -0
- package/build/lib/core/utils/concurrency.d.ts +16 -0
- package/build/lib/core/utils/prompt.d.ts +12 -0
- package/build/lib/core/whitebox/adapters.d.ts +29 -0
- package/build/lib/core/whitebox/artifacts.d.ts +32 -0
- package/build/lib/core/whitebox/boundedProcess.d.ts +35 -0
- package/build/lib/core/whitebox/candidates.d.ts +29 -0
- package/build/lib/core/whitebox/catalog.d.ts +10 -0
- package/build/lib/core/whitebox/index.d.ts +9 -0
- package/build/lib/core/whitebox/jobKernel.d.ts +33 -0
- package/build/lib/core/whitebox/jobSupervisor.d.ts +14 -0
- package/build/lib/core/whitebox/jobs.d.ts +17 -0
- package/build/lib/core/whitebox/paths.d.ts +22 -0
- package/build/lib/core/whitebox/profileTransport.d.ts +10 -0
- package/build/lib/core/whitebox/profiles.d.ts +3 -0
- package/build/lib/core/whitebox/repoProfile.d.ts +4 -0
- package/build/lib/core/whitebox/types.d.ts +108 -0
- package/build/lib/core/workflows/fastStrike.d.ts +4 -0
- package/build/lib/core/workflows/pentest.d.ts +167 -0
- package/build/lib/core/workflows/pentest.js +42 -0
- package/build/lib/core/workflows/seams.d.ts +102 -0
- package/build/lib/core/workflows/seams.js +37 -0
- package/build/lib/core/workflows/threatModel.d.ts +26 -0
- package/build/lib/core/workflows/whiteboxAttackSurface.d.ts +142 -0
- package/build/lib/core/workflows/whiteboxAttackSurface.js +36 -0
- package/build/lib/index.d.ts +26 -0
- package/build/lib/index.js +96 -0
- package/build/lib/lib/attack-path/types.d.ts +9 -0
- package/build/lib/lib/cvss/calculator.d.ts +31 -0
- package/build/lib/lib/cvss/index.d.ts +24 -0
- package/build/lib/lib/cvss/index.js +24 -0
- package/build/lib/lib/cvss/macrovector-scores.d.ts +59 -0
- package/build/lib/lib/cvss/types.d.ts +114 -0
- package/build/lib/lib/cvss/types.js +8 -0
- package/build/lib/lib/cwe/cwe-catalog.d.ts +13 -0
- package/build/lib/lib/cwe/types.d.ts +28 -0
- package/build/lib/lib/cwe/validate.d.ts +15 -0
- package/build/lib/lib/evidence/types.d.ts +12 -0
- package/build/lib/util/errors.d.ts +186 -0
- package/build/lib/util/lock.d.ts +2 -0
- package/build/lib/util/name.d.ts +14 -0
- package/build/lib/util/url.d.ts +40 -0
- package/build/{logs-wzr5176k.js → logs-v5503qqk.js} +22 -30
- package/build/{multipart-parser-g2xxkezz.js → multipart-parser-vjjdbpd1.js} +10 -10
- package/build/native-rollout-evidence-1qwze8nm.js +135 -0
- package/build/offesecAgent-w5a2r0wa.js +22 -0
- package/build/{parse-rtccymzn.js → parse-cqecqrc5.js} +0 -4
- package/build/pentest-fxya42cg.js +22 -0
- package/build/pentests-6qntz6wz.js +143 -0
- package/build/recordedRunClient-rtdeagzx.js +11 -0
- package/build/{targetedPentest-tdwtgmxm.js → targetedPentest-khnxcvmb.js} +22 -22
- package/build/{targets-763n91t7.js → targets-ty7dahv4.js} +24 -32
- package/build/threatModel-28ayxe0n.js +21 -0
- package/build/{token-3bbp59y6.js → token-mk7t8y0y.js} +2 -2
- package/build/{token-util-6xjme11b.js → token-util-vd776hrv.js} +1 -2
- package/build/{uninstall-d33159cz.js → uninstall-nrhvt32a.js} +3 -3
- package/build/{upload-9qj1kpt9.js → upload-sx9gth59.js} +8 -14
- package/build/{utils-t7gc2903.js → utils-qetcfvgg.js} +29 -29
- package/package.json +230 -5
- package/src/cli/agent-runs.attach.test.ts +359 -0
- package/src/cli/agent-runs.test.ts +1172 -0
- package/src/cli/agent-runs.ts +430 -0
- package/src/cli/apps.test.ts +63 -0
- package/src/cli/apps.ts +526 -0
- package/src/cli/auth.ts +375 -0
- package/src/cli/command-exit.test.ts +15 -0
- package/src/cli/command-exit.ts +3 -0
- package/src/cli/config.ts +210 -0
- package/src/cli/export-trajectory.test.ts +224 -0
- package/src/cli/export-trajectory.ts +119 -0
- package/src/cli/fixes.ts +56 -0
- package/src/cli/issues.test.ts +214 -0
- package/src/cli/issues.ts +242 -0
- package/src/cli/json-output.test.ts +62 -0
- package/src/cli/knowledge.test.ts +140 -0
- package/src/cli/knowledge.ts +146 -0
- package/src/cli/launcher.test.ts +81 -0
- package/src/cli/logs.ts +111 -0
- package/src/cli/native-rollout-evidence.test.ts +322 -0
- package/src/cli/native-rollout-evidence.ts +206 -0
- package/src/cli/pentests.test.ts +194 -0
- package/src/cli/pentests.ts +159 -0
- package/src/cli/resume.test.ts +107 -0
- package/src/cli/targets.ts +125 -0
- package/src/cli/uninstall.ts +302 -0
- package/src/cli.ts +882 -0
- package/src/core/agents/agentRuntime.test.ts +242 -0
- package/src/core/agents/agentRuntime.ts +120 -0
- package/src/core/agents/defineAgent.ts +134 -0
- package/src/core/agents/offSecAgent/index.ts +162 -0
- package/src/core/agents/offSecAgent/interruptedStepFinalization.test.ts +295 -0
- package/src/core/agents/offSecAgent/interruptedStepFinalization.ts +162 -0
- package/src/core/agents/offSecAgent/interruptedStepMessages.test.ts +296 -0
- package/src/core/agents/offSecAgent/interruptedStepMessages.ts +137 -0
- package/src/core/agents/offSecAgent/messagePersistence.test.ts +281 -0
- package/src/core/agents/offSecAgent/messagePersistence.ts +111 -0
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.runtimeContext.test.ts +689 -0
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.test.ts +2899 -0
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.ts +1610 -0
- package/src/core/agents/offSecAgent/prompt.test.ts +72 -0
- package/src/core/agents/offSecAgent/prompt.ts +368 -0
- package/src/core/agents/offSecAgent/recordedTools.test.ts +580 -0
- package/src/core/agents/offSecAgent/recordedTools.ts +162 -0
- package/src/core/agents/offSecAgent/runtimeContext.test.ts +531 -0
- package/src/core/agents/offSecAgent/runtimeContext.ts +387 -0
- package/src/core/agents/offSecAgent/selectiveConstruction.publicPath.test.ts +295 -0
- package/src/core/agents/offSecAgent/selectiveConstruction.test.ts +498 -0
- package/src/core/agents/offSecAgent/streamDiagnostics.test.ts +310 -0
- package/src/core/agents/offSecAgent/streamDiagnostics.ts +237 -0
- package/src/core/agents/offSecAgent/subagentSpawner.hooks.test.ts +102 -0
- package/src/core/agents/offSecAgent/subagentSpawner.test.ts +384 -0
- package/src/core/agents/offSecAgent/subagentSpawner.ts +664 -0
- package/src/core/agents/offSecAgent/toolLifecycle.test.ts +199 -0
- package/src/core/agents/offSecAgent/toolLifecycle.ts +171 -0
- package/src/core/agents/offSecAgent/tools/__tests__/sandboxScript.ts +14 -0
- package/src/core/agents/offSecAgent/tools/addMemory.ts +87 -0
- package/src/core/agents/offSecAgent/tools/agentScratch.test.ts +36 -0
- package/src/core/agents/offSecAgent/tools/agentScratch.ts +23 -0
- package/src/core/agents/offSecAgent/tools/applyPatch.test.ts +546 -0
- package/src/core/agents/offSecAgent/tools/applyPatch.ts +58 -0
- package/src/core/agents/offSecAgent/tools/applyPatchImpl.ts +300 -0
- package/src/core/agents/offSecAgent/tools/askUserQuestions.ts +81 -0
- package/src/core/agents/offSecAgent/tools/authBackendStatus.test.ts +112 -0
- package/src/core/agents/offSecAgent/tools/browserHeaderRouting.test.ts +136 -0
- package/src/core/agents/offSecAgent/tools/browserHeaderRouting.ts +81 -0
- package/src/core/agents/offSecAgent/tools/browserToolFactories.ts +372 -0
- package/src/core/agents/offSecAgent/tools/browserTools.test.ts +243 -0
- package/src/core/agents/offSecAgent/tools/browserTools.ts +285 -0
- package/src/core/agents/offSecAgent/tools/callbackListener.test.ts +1011 -0
- package/src/core/agents/offSecAgent/tools/callbackListener.ts +1038 -0
- package/src/core/agents/offSecAgent/tools/camoufox.test.ts +119 -0
- package/src/core/agents/offSecAgent/tools/camoufox.ts +199 -0
- package/src/core/agents/offSecAgent/tools/checkpointState.ts +79 -0
- package/src/core/agents/offSecAgent/tools/codingTools.windows.test.ts +625 -0
- package/src/core/agents/offSecAgent/tools/completeAuthentication.ts +136 -0
- package/src/core/agents/offSecAgent/tools/crawlAuthenticated.test.ts +267 -0
- package/src/core/agents/offSecAgent/tools/crawlAuthenticated.ts +170 -0
- package/src/core/agents/offSecAgent/tools/createAttackSurfaceReport.ts +75 -0
- package/src/core/agents/offSecAgent/tools/createFile.test.ts +111 -0
- package/src/core/agents/offSecAgent/tools/createFile.ts +44 -0
- package/src/core/agents/offSecAgent/tools/createTask.ts +118 -0
- package/src/core/agents/offSecAgent/tools/delegateAuth.ts +391 -0
- package/src/core/agents/offSecAgent/tools/deleteFile.test.ts +102 -0
- package/src/core/agents/offSecAgent/tools/deleteFile.ts +39 -0
- package/src/core/agents/offSecAgent/tools/destructiveGuard.test.ts +827 -0
- package/src/core/agents/offSecAgent/tools/destructiveGuard.ts +747 -0
- package/src/core/agents/offSecAgent/tools/detectAuthScheme.ts +191 -0
- package/src/core/agents/offSecAgent/tools/documentApp.ts +242 -0
- package/src/core/agents/offSecAgent/tools/documentEndpoint.ts +291 -0
- package/src/core/agents/offSecAgent/tools/documentFinding.test.ts +2091 -0
- package/src/core/agents/offSecAgent/tools/documentFinding.ts +1240 -0
- package/src/core/agents/offSecAgent/tools/email/adapters.test.ts +279 -0
- package/src/core/agents/offSecAgent/tools/email/adapters.ts +1121 -0
- package/src/core/agents/offSecAgent/tools/email/getAttachments.ts +73 -0
- package/src/core/agents/offSecAgent/tools/email/getMessage.ts +56 -0
- package/src/core/agents/offSecAgent/tools/email/inboxBackend.test.ts +137 -0
- package/src/core/agents/offSecAgent/tools/email/index.ts +55 -0
- package/src/core/agents/offSecAgent/tools/email/listInboxes.ts +47 -0
- package/src/core/agents/offSecAgent/tools/email/listMessages.ts +67 -0
- package/src/core/agents/offSecAgent/tools/email/markRead.ts +57 -0
- package/src/core/agents/offSecAgent/tools/email/searchMessages.ts +76 -0
- package/src/core/agents/offSecAgent/tools/email/sendEmail.ts +165 -0
- package/src/core/agents/offSecAgent/tools/email/types.ts +45 -0
- package/src/core/agents/offSecAgent/tools/executeCommand.backends.test.ts +171 -0
- package/src/core/agents/offSecAgent/tools/executeCommand.test.ts +1153 -0
- package/src/core/agents/offSecAgent/tools/executeCommand.ts +604 -0
- package/src/core/agents/offSecAgent/tools/extractJsEndpoints.ts +44 -0
- package/src/core/agents/offSecAgent/tools/fileBackends.test.ts +66 -0
- package/src/core/agents/offSecAgent/tools/fileMutations.test.ts +159 -0
- package/src/core/agents/offSecAgent/tools/fileToolBackendPurity.test.ts +72 -0
- package/src/core/agents/offSecAgent/tools/fileWorkspace.test.ts +357 -0
- package/src/core/agents/offSecAgent/tools/fileWorkspace.ts +434 -0
- package/src/core/agents/offSecAgent/tools/fileWorkspaceRemote.ts +263 -0
- package/src/core/agents/offSecAgent/tools/getMemory.ts +69 -0
- package/src/core/agents/offSecAgent/tools/getPage.test.ts +1127 -0
- package/src/core/agents/offSecAgent/tools/getPage.ts +70 -0
- package/src/core/agents/offSecAgent/tools/gitDiff.ts +67 -0
- package/src/core/agents/offSecAgent/tools/gitStatus.ts +61 -0
- package/src/core/agents/offSecAgent/tools/gitTools.test.ts +237 -0
- package/src/core/agents/offSecAgent/tools/glob.test.ts +695 -0
- package/src/core/agents/offSecAgent/tools/glob.ts +51 -0
- package/src/core/agents/offSecAgent/tools/globImpl.ts +313 -0
- package/src/core/agents/offSecAgent/tools/globPattern.ts +203 -0
- package/src/core/agents/offSecAgent/tools/grep.test.ts +922 -0
- package/src/core/agents/offSecAgent/tools/grep.ts +73 -0
- package/src/core/agents/offSecAgent/tools/grepImpl.ts +718 -0
- package/src/core/agents/offSecAgent/tools/httpBackends.test.ts +534 -0
- package/src/core/agents/offSecAgent/tools/httpRequest.test.ts +2409 -0
- package/src/core/agents/offSecAgent/tools/httpRequest.ts +425 -0
- package/src/core/agents/offSecAgent/tools/index.ts +787 -0
- package/src/core/agents/offSecAgent/tools/listFiles.bounded.test.ts +514 -0
- package/src/core/agents/offSecAgent/tools/listFiles.public-counters.test.ts +163 -0
- package/src/core/agents/offSecAgent/tools/listFiles.test.ts +521 -0
- package/src/core/agents/offSecAgent/tools/listFiles.ts +49 -0
- package/src/core/agents/offSecAgent/tools/listFilesImpl.ts +351 -0
- package/src/core/agents/offSecAgent/tools/listMemories.ts +71 -0
- package/src/core/agents/offSecAgent/tools/listPromptInjections.test.ts +201 -0
- package/src/core/agents/offSecAgent/tools/listPromptInjections.ts +78 -0
- package/src/core/agents/offSecAgent/tools/listTasks.ts +100 -0
- package/src/core/agents/offSecAgent/tools/patchApply.test.ts +573 -0
- package/src/core/agents/offSecAgent/tools/patchApply.ts +430 -0
- package/src/core/agents/offSecAgent/tools/patchParse.test.ts +383 -0
- package/src/core/agents/offSecAgent/tools/patchParse.ts +354 -0
- package/src/core/agents/offSecAgent/tools/perCommandShell.drain.test.ts +109 -0
- package/src/core/agents/offSecAgent/tools/perCommandShell.test.ts +565 -0
- package/src/core/agents/offSecAgent/tools/perCommandShell.ts +516 -0
- package/src/core/agents/offSecAgent/tools/perCommandShell.windows.test.ts +142 -0
- package/src/core/agents/offSecAgent/tools/playwrightMcp.test.ts +778 -0
- package/src/core/agents/offSecAgent/tools/playwrightMcp.ts +1426 -0
- package/src/core/agents/offSecAgent/tools/probeAuthEndpoints.ts +262 -0
- package/src/core/agents/offSecAgent/tools/profileCodebase.ts +110 -0
- package/src/core/agents/offSecAgent/tools/provideComparisonResults.ts +106 -0
- package/src/core/agents/offSecAgent/tools/queryWhiteboxCatalog.coalescing-cost.test.ts +108 -0
- package/src/core/agents/offSecAgent/tools/queryWhiteboxCatalog.test.ts +183 -0
- package/src/core/agents/offSecAgent/tools/queryWhiteboxCatalog.ts +143 -0
- package/src/core/agents/offSecAgent/tools/readFile.test.ts +1242 -0
- package/src/core/agents/offSecAgent/tools/readFile.ts +89 -0
- package/src/core/agents/offSecAgent/tools/readFileImpl.ts +956 -0
- package/src/core/agents/offSecAgent/tools/readSkill.ts +38 -0
- package/src/core/agents/offSecAgent/tools/reportError.test.ts +48 -0
- package/src/core/agents/offSecAgent/tools/reportError.ts +65 -0
- package/src/core/agents/offSecAgent/tools/response.ts +27 -0
- package/src/core/agents/offSecAgent/tools/runAttackSurface.ts +198 -0
- package/src/core/agents/offSecAgent/tools/runCodeQuery.test.ts +82 -0
- package/src/core/agents/offSecAgent/tools/runCodeQuery.ts +237 -0
- package/src/core/agents/offSecAgent/tools/runPentestWorkflow.ts +122 -0
- package/src/core/agents/offSecAgent/tools/runWhiteboxScan.ts +189 -0
- package/src/core/agents/offSecAgent/tools/runtimeBackendConsumers.test.ts +143 -0
- package/src/core/agents/offSecAgent/tools/sandbox.ts +37 -0
- package/src/core/agents/offSecAgent/tools/sandboxPlaywright.test.ts +235 -0
- package/src/core/agents/offSecAgent/tools/sandboxPlaywright.ts +1029 -0
- package/src/core/agents/offSecAgent/tools/sandboxScript.test.ts +31 -0
- package/src/core/agents/offSecAgent/tools/sandboxScript.ts +60 -0
- package/src/core/agents/offSecAgent/tools/scopeGuard.test.ts +574 -0
- package/src/core/agents/offSecAgent/tools/scopeGuard.ts +317 -0
- package/src/core/agents/offSecAgent/tools/scriptSyntaxCheck.test.ts +566 -0
- package/src/core/agents/offSecAgent/tools/scriptSyntaxCheck.ts +240 -0
- package/src/core/agents/offSecAgent/tools/selectiveFactories.test.ts +476 -0
- package/src/core/agents/offSecAgent/tools/smsInbox.ts +130 -0
- package/src/core/agents/offSecAgent/tools/smsListMessages.test.ts +443 -0
- package/src/core/agents/offSecAgent/tools/smsListMessages.ts +123 -0
- package/src/core/agents/offSecAgent/tools/spawnCodingAgent.ts +229 -0
- package/src/core/agents/offSecAgent/tools/spawnPentestAgent.test.ts +413 -0
- package/src/core/agents/offSecAgent/tools/spawnPentestAgent.ts +266 -0
- package/src/core/agents/offSecAgent/tools/spawnPentestSwarm.ts +146 -0
- package/src/core/agents/offSecAgent/tools/submitPlan.ts +51 -0
- package/src/core/agents/offSecAgent/tools/testEndpointVariations.ts +127 -0
- package/src/core/agents/offSecAgent/tools/threatModelGenerator.ts +664 -0
- package/src/core/agents/offSecAgent/tools/toolOutput.test.ts +480 -0
- package/src/core/agents/offSecAgent/tools/toolOutput.ts +160 -0
- package/src/core/agents/offSecAgent/tools/types.ts +267 -0
- package/src/core/agents/offSecAgent/tools/updateFile.ts +121 -0
- package/src/core/agents/offSecAgent/tools/updateTask.ts +107 -0
- package/src/core/agents/offSecAgent/tools/validateDiscovery.ts +123 -0
- package/src/core/agents/offSecAgent/tools/webSearch.ts +265 -0
- package/src/core/agents/offSecAgent/tools/whiteboxCandidates.ts +197 -0
- package/src/core/agents/offSecAgent/tools/whiteboxJobs.ts +312 -0
- package/src/core/agents/offSecAgent/tools/windowsCurl.test.ts +801 -0
- package/src/core/agents/offSecAgent/tools/windowsCurl.ts +202 -0
- package/src/core/agents/offSecAgent/tools/workspaceApps.test.ts +257 -0
- package/src/core/agents/offSecAgent/tools/workspaceApps.ts +334 -0
- package/src/core/agents/offSecAgent/tools/workspaceDomains.test.ts +113 -0
- package/src/core/agents/offSecAgent/tools/workspaceDomains.ts +57 -0
- package/src/core/agents/offSecAgent/tools/workspaceFailure.ts +11 -0
- package/src/core/agents/offSecAgent/tools/writePlan.ts +65 -0
- package/src/core/agents/offSecAgent/trace.test.ts +796 -0
- package/src/core/agents/offSecAgent/trace.ts +633 -0
- package/src/core/agents/offSecAgent/types.test.ts +224 -0
- package/src/core/agents/offSecAgent/types.ts +676 -0
- package/src/core/agents/specialized/attackSurface/blackboxAgent.test.ts +31 -0
- package/src/core/agents/specialized/attackSurface/blackboxAgent.ts +272 -0
- package/src/core/agents/specialized/attackSurface/blackboxRiskScoring.ts +276 -0
- package/src/core/agents/specialized/attackSurface/grpcSchema.ts +142 -0
- package/src/core/agents/specialized/attackSurface/jsExtraction.test.ts +237 -0
- package/src/core/agents/specialized/attackSurface/jsExtraction.ts +174 -0
- package/src/core/agents/specialized/attackSurface/prompts.ts +349 -0
- package/src/core/agents/specialized/attackSurface/schemas.ts +300 -0
- package/src/core/agents/specialized/attackSurface/types.ts +100 -0
- package/src/core/agents/specialized/authenticationAgent/agent.test.ts +111 -0
- package/src/core/agents/specialized/authenticationAgent/agent.ts +300 -0
- package/src/core/agents/specialized/authenticationAgent/index.ts +74 -0
- package/src/core/agents/specialized/authenticationAgent/prompts.test.ts +36 -0
- package/src/core/agents/specialized/authenticationAgent/prompts.ts +645 -0
- package/src/core/agents/specialized/authenticationAgent/types.ts +833 -0
- package/src/core/agents/specialized/benchmark/comparisonAgent.ts +344 -0
- package/src/core/agents/specialized/benchmark/docker-utils.ts +257 -0
- package/src/core/agents/specialized/benchmark/flag-detector.ts +686 -0
- package/src/core/agents/specialized/benchmark/index.ts +28 -0
- package/src/core/agents/specialized/benchmark/prompts.ts +257 -0
- package/src/core/agents/specialized/benchmark/remote/circuit-breaker.ts +108 -0
- package/src/core/agents/specialized/benchmark/remote/daytona-wrapper.ts +1005 -0
- package/src/core/agents/specialized/benchmark/remote/index.ts +2 -0
- package/src/core/agents/specialized/benchmark/types.ts +98 -0
- package/src/core/agents/specialized/benchmarkComparisonAgent.test.ts +111 -0
- package/src/core/agents/specialized/benchmarkComparisonAgent.ts +203 -0
- package/src/core/agents/specialized/codeAgent/agent.test.ts +89 -0
- package/src/core/agents/specialized/codeAgent/agent.ts +134 -0
- package/src/core/agents/specialized/codeAgent/prompts.ts +48 -0
- package/src/core/agents/specialized/codeAgent/schemas.ts +33 -0
- package/src/core/agents/specialized/cvssScorer/index.test.ts +87 -0
- package/src/core/agents/specialized/cvssScorer/index.ts +546 -0
- package/src/core/agents/specialized/environment/agent.ts +75 -0
- package/src/core/agents/specialized/environment/index.ts +16 -0
- package/src/core/agents/specialized/environment/prompts.ts +194 -0
- package/src/core/agents/specialized/environment/types.ts +48 -0
- package/src/core/agents/specialized/findingJudge/agent.test.ts +114 -0
- package/src/core/agents/specialized/findingJudge/agent.ts +59 -0
- package/src/core/agents/specialized/findingJudge/index.test.ts +155 -0
- package/src/core/agents/specialized/findingJudge/index.ts +166 -0
- package/src/core/agents/specialized/findingJudge/prompts.ts +140 -0
- package/src/core/agents/specialized/findingJudge/types.ts +115 -0
- package/src/core/agents/specialized/googleSignInPrompt.test.ts +29 -0
- package/src/core/agents/specialized/googleSignInPrompt.ts +18 -0
- package/src/core/agents/specialized/mobileOtpPrompt.ts +9 -0
- package/src/core/agents/specialized/patching/agent.test.ts +220 -0
- package/src/core/agents/specialized/patching/agent.ts +146 -0
- package/src/core/agents/specialized/patching/index.ts +20 -0
- package/src/core/agents/specialized/patching/prompts.test.ts +172 -0
- package/src/core/agents/specialized/patching/prompts.ts +396 -0
- package/src/core/agents/specialized/patching/types.ts +49 -0
- package/src/core/agents/specialized/pentest/agent.test.ts +1046 -0
- package/src/core/agents/specialized/pentest/agent.ts +1482 -0
- package/src/core/agents/specialized/pentest/helperLifecycle.test.ts +425 -0
- package/src/core/agents/specialized/pentest/helperWorkspace.test.ts +84 -0
- package/src/core/agents/specialized/pentest/helperWorkspace.ts +33 -0
- package/src/core/agents/specialized/pentest/planPrompt.ts +68 -0
- package/src/core/agents/specialized/pentest/results.test.ts +198 -0
- package/src/core/agents/specialized/utils.test.ts +16 -0
- package/src/core/agents/specialized/utils.ts +28 -0
- package/src/core/agents/specialized/vulnerabilityReproduction/agent.test.ts +195 -0
- package/src/core/agents/specialized/vulnerabilityReproduction/agent.ts +159 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/agent.test.ts +39 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/agent.ts +227 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.concurrency.test.ts +138 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.test.ts +199 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.ts +330 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/index.ts +24 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/prompts.ts +345 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/types.test.ts +67 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/types.ts +234 -0
- package/src/core/ai/ai.contract.test.ts +43 -0
- package/src/core/ai/ai.durability-hooks.test.ts +527 -0
- package/src/core/ai/ai.effective-tools.test.ts +739 -0
- package/src/core/ai/ai.native-rollout-evidence.test.ts +373 -0
- package/src/core/ai/ai.outer-catch-recovery.test.ts +82 -0
- package/src/core/ai/ai.proactive-recovery.test.ts +69 -0
- package/src/core/ai/ai.recorded-attempts.test.ts +621 -0
- package/src/core/ai/ai.recorded-context.test.ts +448 -0
- package/src/core/ai/ai.recorded-tools.test.ts +850 -0
- package/src/core/ai/ai.request-retention.test.ts +296 -0
- package/src/core/ai/ai.test.ts +690 -0
- package/src/core/ai/ai.ts +2377 -0
- package/src/core/ai/caching.test.ts +179 -0
- package/src/core/ai/caching.ts +119 -0
- package/src/core/ai/compactionEvidence.test.ts +52 -0
- package/src/core/ai/compactionEvidence.ts +101 -0
- package/src/core/ai/compactionTelemetry.test.ts +621 -0
- package/src/core/ai/compactionTelemetry.ts +287 -0
- package/src/core/ai/concentrate.test.ts +28 -0
- package/src/core/ai/contextManagement.test.ts +350 -0
- package/src/core/ai/contextManagement.ts +594 -0
- package/src/core/ai/index.ts +73 -0
- package/src/core/ai/inference-attempt/adapters.test.ts +84 -0
- package/src/core/ai/inference-attempt/adapters.ts +391 -0
- package/src/core/ai/inference-attempt/attempt.test.ts +198 -0
- package/src/core/ai/inference-attempt/builder.ts +171 -0
- package/src/core/ai/inference-attempt/envelope.ts +120 -0
- package/src/core/ai/inference-attempt/errors.ts +15 -0
- package/src/core/ai/inference-attempt/fixtures/anthropic-messages-cache-create.json +18 -0
- package/src/core/ai/inference-attempt/fixtures/anthropic-messages-cache-read.json +18 -0
- package/src/core/ai/inference-attempt/fixtures/anthropic-messages-incomplete.json +16 -0
- package/src/core/ai/inference-attempt/fixtures/anthropic-messages-mixed.json +22 -0
- package/src/core/ai/inference-attempt/fixtures/anthropic-messages-non-cache.json +26 -0
- package/src/core/ai/inference-attempt/fixtures/bedrock-converse-cache-create.json +18 -0
- package/src/core/ai/inference-attempt/fixtures/bedrock-converse-cache-read.json +26 -0
- package/src/core/ai/inference-attempt/fixtures/bedrock-converse-incomplete.json +19 -0
- package/src/core/ai/inference-attempt/fixtures/bedrock-converse-mixed.json +20 -0
- package/src/core/ai/inference-attempt/fixtures/bedrock-converse-non-cache.json +24 -0
- package/src/core/ai/inference-attempt/fixtures/openai-responses-cache-read.json +17 -0
- package/src/core/ai/inference-attempt/fixtures/openai-responses-incomplete.json +16 -0
- package/src/core/ai/inference-attempt/fixtures/openai-responses-non-cache.json +23 -0
- package/src/core/ai/inference-attempt/fixtures/pensar-anthropic-rest-incomplete.json +21 -0
- package/src/core/ai/inference-attempt/fixtures/pensar-anthropic-rest-native.json +16 -0
- package/src/core/ai/inference-attempt/fixtures/pensar-anthropic-stream-cache-create.json +20 -0
- package/src/core/ai/inference-attempt/fixtures/pensar-anthropic-stream-cache-read.json +20 -0
- package/src/core/ai/inference-attempt/fixtures/pensar-anthropic-stream-incomplete.json +16 -0
- package/src/core/ai/inference-attempt/fixtures/pensar-anthropic-stream-mixed.json +21 -0
- package/src/core/ai/inference-attempt/fixtures/pensar-anthropic-stream-non-cache.json +19 -0
- package/src/core/ai/inference-attempt/fixtures/reject-cache-read-exceeds-inclusive.json +11 -0
- package/src/core/ai/inference-attempt/fixtures/reject-components-exceed-inclusive.json +12 -0
- package/src/core/ai/inference-attempt/fixtures/reject-identity-mismatch.json +13 -0
- package/src/core/ai/inference-attempt/fixtures/reject-negative-token.json +9 -0
- package/src/core/ai/inference-attempt/fixtures/reject-non-integer-token.json +8 -0
- package/src/core/ai/inference-attempt/fixtures/sdk-normalized-cache-read.json +19 -0
- package/src/core/ai/inference-attempt/fixtures/sdk-normalized-incomplete.json +15 -0
- package/src/core/ai/inference-attempt/fixtures/sdk-normalized-mixed.json +20 -0
- package/src/core/ai/inference-attempt/fixtures/sdk-normalized-non-cache.json +16 -0
- package/src/core/ai/inference-attempt/identity.ts +25 -0
- package/src/core/ai/inference-attempt/index.ts +70 -0
- package/src/core/ai/inference-attempt/project.test.ts +118 -0
- package/src/core/ai/inference-attempt/project.ts +60 -0
- package/src/core/ai/inference-attempt/recording.ts +46 -0
- package/src/core/ai/inference-attempt/tokens.ts +165 -0
- package/src/core/ai/inference-attempt/validate.ts +20 -0
- package/src/core/ai/mantle.test.ts +50 -0
- package/src/core/ai/mantle.ts +45 -0
- package/src/core/ai/model-history.test.ts +53 -0
- package/src/core/ai/model-history.ts +38 -0
- package/src/core/ai/models/anthropic.ts +151 -0
- package/src/core/ai/models/bedrock.ts +618 -0
- package/src/core/ai/models/claude-capabilities.ts +43 -0
- package/src/core/ai/models/concentrate.ts +192 -0
- package/src/core/ai/models/google.ts +154 -0
- package/src/core/ai/models/inception.ts +10 -0
- package/src/core/ai/models/index.ts +253 -0
- package/src/core/ai/models/mantle.ts +14 -0
- package/src/core/ai/models/models.test.ts +313 -0
- package/src/core/ai/models/openai.ts +409 -0
- package/src/core/ai/models/openrouter.ts +342 -0
- package/src/core/ai/models/pensar.ts +66 -0
- package/src/core/ai/native-rollout-evidence/capture.test.ts +1836 -0
- package/src/core/ai/native-rollout-evidence/capture.ts +1572 -0
- package/src/core/ai/native-rollout-evidence/content.test.ts +55 -0
- package/src/core/ai/native-rollout-evidence/content.ts +129 -0
- package/src/core/ai/native-rollout-evidence/index.ts +68 -0
- package/src/core/ai/native-rollout-evidence/provider-metadata.test.ts +85 -0
- package/src/core/ai/native-rollout-evidence/provider-metadata.ts +129 -0
- package/src/core/ai/native-rollout-evidence/recording.test.ts +398 -0
- package/src/core/ai/native-rollout-evidence/schema.test.ts +210 -0
- package/src/core/ai/native-rollout-evidence/schema.ts +353 -0
- package/src/core/ai/native-rollout-evidence/validate.ts +141 -0
- package/src/core/ai/providers/anthropic-models.test.ts +348 -0
- package/src/core/ai/providers/anthropic.ts +73 -0
- package/src/core/ai/providers/bedrock-models.test.ts +81 -0
- package/src/core/ai/providers/concentrate.live.test.ts +71 -0
- package/src/core/ai/providers/concentrate.test.ts +160 -0
- package/src/core/ai/providers/concentrate.ts +145 -0
- package/src/core/ai/providers/custom.live.test.ts +42 -0
- package/src/core/ai/providers/custom.test.ts +474 -0
- package/src/core/ai/providers/custom.ts +70 -0
- package/src/core/ai/providers/gateway-models.test.ts +648 -0
- package/src/core/ai/providers/hoonify.live.test.ts +72 -0
- package/src/core/ai/providers/hoonify.test.ts +284 -0
- package/src/core/ai/providers/hoonify.ts +32 -0
- package/src/core/ai/providers/openai-models.test.ts +356 -0
- package/src/core/ai/providers/openai-pro-fetch.test.ts +64 -0
- package/src/core/ai/providers/openai-pro-fetch.ts +32 -0
- package/src/core/ai/providers/pensar.ts +645 -0
- package/src/core/ai/providers/pensarFormatters.test.ts +272 -0
- package/src/core/ai/providers/pensarFormatters.ts +533 -0
- package/src/core/ai/providers/pensarResponsesStream.test.ts +191 -0
- package/src/core/ai/providers/pensarResponsesStream.ts +294 -0
- package/src/core/ai/providers/pensarSSE.test.ts +83 -0
- package/src/core/ai/providers/pensarSSE.ts +128 -0
- package/src/core/ai/providers/pensarSigning.ts +2 -0
- package/src/core/ai/providers/pensarStreamUsage.test.ts +79 -0
- package/src/core/ai/providers/pensarStreamUsage.ts +62 -0
- package/src/core/ai/stepContext.test.ts +61 -0
- package/src/core/ai/streamIdleTimeout.test.ts +390 -0
- package/src/core/ai/streamTelemetry.ts +90 -0
- package/src/core/ai/usage-callback.test.ts +511 -0
- package/src/core/ai/utils.native-rollout-evidence.test.ts +135 -0
- package/src/core/ai/utils.pensar.test.ts +59 -0
- package/src/core/ai/utils.ts +795 -0
- package/src/core/api/apiClient.test.ts +58 -0
- package/src/core/api/apiClient.ts +73 -0
- package/src/core/api/apps.test.ts +78 -0
- package/src/core/api/apps.ts +388 -0
- package/src/core/api/attackSurface.test.ts +24 -0
- package/src/core/api/attackSurface.ts +89 -0
- package/src/core/api/authentication.ts +8 -0
- package/src/core/api/benchmark.ts +35 -0
- package/src/core/api/blackboxPentest.test.ts +89 -0
- package/src/core/api/blackboxPentest.ts +64 -0
- package/src/core/api/clientIdentity.test.ts +61 -0
- package/src/core/api/clientIdentity.ts +57 -0
- package/src/core/api/comments.test.ts +69 -0
- package/src/core/api/constants.ts +15 -0
- package/src/core/api/domains.test.ts +35 -0
- package/src/core/api/domains.ts +32 -0
- package/src/core/api/environment.ts +47 -0
- package/src/core/api/index.ts +219 -0
- package/src/core/api/issues.test.ts +82 -0
- package/src/core/api/issues.ts +439 -0
- package/src/core/api/knowledge.ts +70 -0
- package/src/core/api/localWorker.ts +29 -0
- package/src/core/api/offesecAgent.test.ts +289 -0
- package/src/core/api/offesecAgent.ts +77 -0
- package/src/core/api/patching.ts +44 -0
- package/src/core/api/recordedRun.control.test.ts +830 -0
- package/src/core/api/recordedRun.inference.test.ts +529 -0
- package/src/core/api/recordedRun.loop.test.ts +290 -0
- package/src/core/api/recordedRun.recovery.test.ts +651 -0
- package/src/core/api/recordedRun.test.ts +646 -0
- package/src/core/api/recordedRun.ts +542 -0
- package/src/core/api/targetedPentest.test.ts +177 -0
- package/src/core/api/targetedPentest.ts +83 -0
- package/src/core/api/threatModel.ts +5 -0
- package/src/core/api/trajectoryExport.test.ts +299 -0
- package/src/core/api/trajectoryExport.ts +362 -0
- package/src/core/api/vulnerabilityReproduction.test.ts +56 -0
- package/src/core/api/vulnerabilityReproduction.ts +54 -0
- package/src/core/assets/wordlists.test.ts +85 -0
- package/src/core/assets/wordlists.ts +111 -0
- package/src/core/atif/compatibility.test.ts +107 -0
- package/src/core/atif/convert.test.ts +815 -0
- package/src/core/atif/convert.ts +1658 -0
- package/src/core/atif/fixtures/portable-bundle-v1.json +813 -0
- package/src/core/atif/index.ts +34 -0
- package/src/core/atif/schema.ts +345 -0
- package/src/core/atif/serialize.test.ts +244 -0
- package/src/core/atif/serialize.ts +419 -0
- package/src/core/atif/test-fixtures.ts +184 -0
- package/src/core/atif/validate.test.ts +188 -0
- package/src/core/atif/validate.ts +289 -0
- package/src/core/auth/connection.ts +26 -0
- package/src/core/auth/device-flow.ts +203 -0
- package/src/core/auth/gateway.ts +66 -0
- package/src/core/auth/index.ts +29 -0
- package/src/core/auth/signing.ts +25 -0
- package/src/core/auth/token.ts +140 -0
- package/src/core/auth/types.ts +106 -0
- package/src/core/auth/workspaces.ts +192 -0
- package/src/core/benchmark/index.ts +11 -0
- package/src/core/benchmark/report.ts +257 -0
- package/src/core/benchmark/runner.ts +698 -0
- package/src/core/benchmark/types.ts +80 -0
- package/src/core/cli/logLevelArgs.test.ts +83 -0
- package/src/core/cli/logLevelArgs.ts +62 -0
- package/src/core/cli/model.ts +35 -0
- package/src/core/cli/pentestMode.test.ts +24 -0
- package/src/core/cli/pentestMode.ts +23 -0
- package/src/core/cli/tuiArgs.test.ts +58 -0
- package/src/core/cli/tuiArgs.ts +28 -0
- package/src/core/config/config.test.ts +183 -0
- package/src/core/config/config.ts +201 -0
- package/src/core/config/customProviders.test.ts +183 -0
- package/src/core/config/customProviders.ts +190 -0
- package/src/core/config/index.ts +7 -0
- package/src/core/credentials/index.ts +6 -0
- package/src/core/credentials/manager.ts +313 -0
- package/src/core/credentials/types.ts +112 -0
- package/src/core/doctor.ts +138 -0
- package/src/core/eventBus.test.ts +374 -0
- package/src/core/eventBus.ts +410 -0
- package/src/core/findings/attackSurfaceRegistry.ts +294 -0
- package/src/core/findings/registry.test.ts +1680 -0
- package/src/core/findings/registry.ts +800 -0
- package/src/core/history.ts +82 -0
- package/src/core/hoonify.test.ts +250 -0
- package/src/core/hoonify.ts +163 -0
- package/src/core/http/headers.contract.test.ts +1161 -0
- package/src/core/http/parse.ts +257 -0
- package/src/core/http/redirects.test.ts +207 -0
- package/src/core/http/redirects.ts +145 -0
- package/src/core/http/targetHeaders.ts +604 -0
- package/src/core/http/targetScope.ts +52 -0
- package/src/core/http/types.ts +39 -0
- package/src/core/id/id.test.ts +88 -0
- package/src/core/id/id.ts +138 -0
- package/src/core/installation/index.ts +222 -0
- package/src/core/installation/installation.test.ts +415 -0
- package/src/core/integrations/herdr.test.ts +335 -0
- package/src/core/integrations/herdr.ts +163 -0
- package/src/core/integrations/surface/index.test.ts +534 -0
- package/src/core/integrations/surface/index.ts +224 -0
- package/src/core/integrations/surface/types.ts +29 -0
- package/src/core/integrations/wandb/client.ts +167 -0
- package/src/core/integrations/wandb/upload.test.ts +415 -0
- package/src/core/integrations/wandb/upload.ts +76 -0
- package/src/core/logger/errorLog.test.ts +98 -0
- package/src/core/logger/index.ts +214 -0
- package/src/core/logger/structured.test.ts +212 -0
- package/src/core/logger/structured.ts +207 -0
- package/src/core/memory/backend.test.ts +186 -0
- package/src/core/memory/index.ts +279 -0
- package/src/core/memory/memory.test.ts +362 -0
- package/src/core/messages/types.ts +141 -0
- package/src/core/obfuscation/engine.test.ts +314 -0
- package/src/core/obfuscation/engine.ts +647 -0
- package/src/core/obfuscation/index.ts +27 -0
- package/src/core/observability/active-root-spans.ts +30 -0
- package/src/core/observability/active-spans.ts +80 -0
- package/src/core/observability/index.ts +91 -0
- package/src/core/observability/log-correlation.test.ts +276 -0
- package/src/core/observability/payload-capture.test.ts +59 -0
- package/src/core/observability/runtime.test.ts +743 -0
- package/src/core/observability/runtime.ts +371 -0
- package/src/core/observability/shutdown.test.ts +551 -0
- package/src/core/observability/telemetry.test.ts +895 -0
- package/src/core/observability/telemetry.ts +220 -0
- package/src/core/observability/testkit.test.ts +66 -0
- package/src/core/observability/testkit.ts +97 -0
- package/src/core/observability/trace-contract.test.ts +1031 -0
- package/src/core/observability.test.ts +135 -0
- package/src/core/operator/approvalGate.test.ts +300 -0
- package/src/core/operator/approvalGate.ts +287 -0
- package/src/core/operator/index.ts +30 -0
- package/src/core/operator/types.ts +355 -0
- package/src/core/plan/index.ts +44 -0
- package/src/core/prompt-injections/index.test.ts +248 -0
- package/src/core/prompt-injections/index.ts +350 -0
- package/src/core/providers/index.ts +5 -0
- package/src/core/providers/types.ts +87 -0
- package/src/core/providers/utils.test.ts +189 -0
- package/src/core/providers/utils.ts +183 -0
- package/src/core/providers/verify.test.ts +49 -0
- package/src/core/providers/verify.ts +198 -0
- package/src/core/report/builder.test.ts +229 -0
- package/src/core/report/builder.ts +58 -0
- package/src/core/report/index.ts +13 -0
- package/src/core/report/renderers/json.test.ts +76 -0
- package/src/core/report/renderers/json.ts +5 -0
- package/src/core/report/renderers/markdown.test.ts +366 -0
- package/src/core/report/renderers/markdown.ts +133 -0
- package/src/core/report/schemas.ts +48 -0
- package/src/core/runtime/agentExecution.test.ts +94 -0
- package/src/core/runtime/agentExecution.ts +27 -0
- package/src/core/runtime/launchLocalWorker.test.ts +707 -0
- package/src/core/runtime/launchLocalWorker.ts +273 -0
- package/src/core/runtime/localRunLock.ts +118 -0
- package/src/core/runtime/localRunWorker.test.ts +381 -0
- package/src/core/runtime/localRunWorker.ts +287 -0
- package/src/core/runtime/localWorker.acceptance.test.ts +548 -0
- package/src/core/runtime/localWorkerEndpoint.test.ts +145 -0
- package/src/core/runtime/localWorkerEndpoint.ts +82 -0
- package/src/core/runtime/localWorkerProtocol.ts +176 -0
- package/src/core/runtime/localWorkerTransport.test.ts +841 -0
- package/src/core/runtime/localWorkerTransport.ts +434 -0
- package/src/core/runtime/persistenceError.ts +14 -0
- package/src/core/runtime/recordedExecution.ts +43 -0
- package/src/core/runtime/recordedRunClient.integration.test.ts +106 -0
- package/src/core/runtime/recordedRunClient.test.ts +677 -0
- package/src/core/runtime/recordedRunClient.ts +303 -0
- package/src/core/runtime/runCheckpointStore.ts +23 -0
- package/src/core/runtime/runContext.test.ts +445 -0
- package/src/core/runtime/runContext.ts +184 -0
- package/src/core/runtime/runControl.test.ts +923 -0
- package/src/core/runtime/runControl.ts +419 -0
- package/src/core/runtime/runControlStore.ts +106 -0
- package/src/core/runtime/runDeadline.test.ts +44 -0
- package/src/core/runtime/runDeadline.ts +28 -0
- package/src/core/runtime/runEvidence.test.ts +384 -0
- package/src/core/runtime/runEvidence.ts +267 -0
- package/src/core/runtime/runInference.test.ts +408 -0
- package/src/core/runtime/runInference.ts +125 -0
- package/src/core/runtime/runModelStore.ts +55 -0
- package/src/core/runtime/runObservation.ts +24 -0
- package/src/core/runtime/runRecoveryContext.test.ts +602 -0
- package/src/core/runtime/runRecoveryContext.ts +195 -0
- package/src/core/runtime/runRecoveryPlan.test.ts +851 -0
- package/src/core/runtime/runRecoveryPlan.ts +540 -0
- package/src/core/runtime/runRecoveryStore.ts +78 -0
- package/src/core/runtime/runStore.ts +148 -0
- package/src/core/runtime/runStorePath.ts +13 -0
- package/src/core/runtime/runToolStore.ts +66 -0
- package/src/core/runtime/runTools.crash.test.ts +414 -0
- package/src/core/runtime/runTools.test.ts +689 -0
- package/src/core/runtime/runTools.ts +208 -0
- package/src/core/runtime/sqliteControlStore.test.ts +917 -0
- package/src/core/runtime/sqliteControlStore.ts +555 -0
- package/src/core/runtime/sqliteModelStore.test.ts +619 -0
- package/src/core/runtime/sqliteModelStore.ts +286 -0
- package/src/core/runtime/sqliteRecoveryStore.public.test.ts +374 -0
- package/src/core/runtime/sqliteRecoveryStore.test.ts +836 -0
- package/src/core/runtime/sqliteRecoveryStore.ts +435 -0
- package/src/core/runtime/sqliteRunContext.test.ts +1000 -0
- package/src/core/runtime/sqliteRunObservation.test.ts +432 -0
- package/src/core/runtime/sqliteRunStore.test.ts +698 -0
- package/src/core/runtime/sqliteRunStore.ts +593 -0
- package/src/core/runtime/sqliteToolStore.test.ts +1231 -0
- package/src/core/runtime/sqliteToolStore.ts +419 -0
- package/src/core/runtime/testfixtures/localWorkerChild.ts +254 -0
- package/src/core/runtime/testfixtures/localWorkerLauncher.ts +15 -0
- package/src/core/runtime/testfixtures/recoveryChild.ts +159 -0
- package/src/core/services/rateLimiter/index.test.ts +106 -0
- package/src/core/services/rateLimiter/index.ts +157 -0
- package/src/core/services/rateLimiter/types.ts +10 -0
- package/src/core/session/admitted-config.test.ts +50 -0
- package/src/core/session/deprecated-headers-shim.test.ts +111 -0
- package/src/core/session/execution-metrics.test.ts +297 -0
- package/src/core/session/execution-metrics.ts +176 -0
- package/src/core/session/index.ts +1085 -0
- package/src/core/session/loader.ts +212 -0
- package/src/core/session/persistence.test.ts +1210 -0
- package/src/core/session/persistence.ts +1076 -0
- package/src/core/session/rehydrate.test.ts +393 -0
- package/src/core/session/types.ts +139 -0
- package/src/core/session/usage.test.ts +99 -0
- package/src/core/session/usage.ts +84 -0
- package/src/core/skills/builtins/index.ts +22 -0
- package/src/core/skills/builtins/pentest.ts +135 -0
- package/src/core/skills/builtins/promptInjection.ts +44 -0
- package/src/core/skills/builtins/threatModel.ts +336 -0
- package/src/core/skills/index.ts +15 -0
- package/src/core/skills/parser.test.ts +120 -0
- package/src/core/skills/parser.ts +106 -0
- package/src/core/skills/registry.test.ts +202 -0
- package/src/core/skills/registry.ts +109 -0
- package/src/core/skills/scanner.test.ts +157 -0
- package/src/core/skills/scanner.ts +115 -0
- package/src/core/skills/types.ts +45 -0
- package/src/core/skills/utils.ts +16 -0
- package/src/core/storage/index.ts +150 -0
- package/src/core/tasks/index.ts +242 -0
- package/src/core/tools/backends/capture.ts +38 -0
- package/src/core/tools/backends/collectCommand.test.ts +33 -0
- package/src/core/tools/backends/collectCommand.ts +28 -0
- package/src/core/tools/backends/helpers.ts +140 -0
- package/src/core/tools/backends/httpTransport.ts +534 -0
- package/src/core/tools/backends/index.ts +61 -0
- package/src/core/tools/backends/local.test.ts +307 -0
- package/src/core/tools/backends/local.ts +820 -0
- package/src/core/tools/backends/policy.test.ts +137 -0
- package/src/core/tools/backends/policy.ts +129 -0
- package/src/core/tools/backends/resolve.test.ts +309 -0
- package/src/core/tools/backends/resolve.ts +152 -0
- package/src/core/tools/backends/types.ts +279 -0
- package/src/core/tools/backends/whitebox.test.ts +275 -0
- package/src/core/tools/backends/whitebox.ts +14 -0
- package/src/core/tools/backends/whiteboxJobs.test.ts +375 -0
- package/src/core/tools/backends/whiteboxJobs.ts +157 -0
- package/src/core/tools/backends/windowsProgram.ts +36 -0
- package/src/core/tools/daytonaSandbox.test.ts +491 -0
- package/src/core/tools/daytonaSandbox.ts +232 -0
- package/src/core/toolset/index.ts +583 -0
- package/src/core/util/lazyLogger.ts +32 -0
- package/src/core/utils/concurrency.test.ts +204 -0
- package/src/core/utils/concurrency.ts +75 -0
- package/src/core/utils/prompt.ts +28 -0
- package/src/core/whitebox/adapters.ts +277 -0
- package/src/core/whitebox/artifacts.ts +128 -0
- package/src/core/whitebox/boundedProcess.ts +265 -0
- package/src/core/whitebox/candidates.ts +268 -0
- package/src/core/whitebox/catalog.ts +82 -0
- package/src/core/whitebox/index.ts +53 -0
- package/src/core/whitebox/jobKernel.test.ts +91 -0
- package/src/core/whitebox/jobKernel.ts +347 -0
- package/src/core/whitebox/jobSupervisor.ts +264 -0
- package/src/core/whitebox/jobs.ts +21 -0
- package/src/core/whitebox/paths.ts +94 -0
- package/src/core/whitebox/profileTransport.ts +225 -0
- package/src/core/whitebox/profiles.ts +294 -0
- package/src/core/whitebox/repoProfile.test.ts +217 -0
- package/src/core/whitebox/repoProfile.ts +256 -0
- package/src/core/whitebox/types.ts +189 -0
- package/src/core/whitebox/whitebox.test.ts +789 -0
- package/src/core/workflows/fastStrike.seams.test.ts +217 -0
- package/src/core/workflows/fastStrike.test.ts +29 -0
- package/src/core/workflows/fastStrike.ts +239 -0
- package/src/core/workflows/pentest.test.ts +575 -0
- package/src/core/workflows/pentest.ts +1022 -0
- package/src/core/workflows/seams.test.ts +386 -0
- package/src/core/workflows/seams.ts +276 -0
- package/src/core/workflows/threatModel.ts +108 -0
- package/src/core/workflows/usage-forwarding.test.ts +203 -0
- package/src/core/workflows/whiteboxAttackSurface.test.ts +695 -0
- package/src/core/workflows/whiteboxAttackSurface.ts +1740 -0
- package/src/index.ts +49 -0
- package/src/lib/attack-path/types.ts +13 -0
- package/src/lib/cvss/calculator.test.ts +2090 -0
- package/src/lib/cvss/calculator.ts +643 -0
- package/src/lib/cvss/index.ts +65 -0
- package/src/lib/cvss/macrovector-scores.ts +402 -0
- package/src/lib/cvss/types.ts +241 -0
- package/src/lib/cwe/cwe-catalog.ts +444 -0
- package/src/lib/cwe/types.test.ts +142 -0
- package/src/lib/cwe/types.ts +37 -0
- package/src/lib/cwe/validate.test.ts +110 -0
- package/src/lib/cwe/validate.ts +53 -0
- package/src/lib/evidence/types.ts +9 -0
- package/src/tests/agentWorkingDirectory.test.ts +175 -0
- package/src/tests/attackSurface.test.ts +35 -0
- package/src/tests/auth.test.ts +196 -0
- package/src/tests/authCookieExport.test.ts +143 -0
- package/src/tests/authPentestHandoff.test.ts +231 -0
- package/src/tests/browserCookies.test.ts +128 -0
- package/src/tests/credentialManager.test.ts +657 -0
- package/src/tests/data/console.openapi.json +1037 -0
- package/src/tests/data/console.sitemap.xml +348 -0
- package/src/tests/delegateAuthMerge.test.ts +48 -0
- package/src/tui/auto-copy.ts +36 -0
- package/src/tui/clipboard.ts +65 -0
- package/src/tui/command-registry.test.ts +124 -0
- package/src/tui/command-registry.ts +645 -0
- package/src/tui/command-router.ts +81 -0
- package/src/tui/components/agent-display.tsx +480 -0
- package/src/tui/components/ascii-art.tsx +225 -0
- package/src/tui/components/chat/approval-inline.tsx +51 -0
- package/src/tui/components/chat/config-view.tsx +279 -0
- package/src/tui/components/chat/home-view.tsx +288 -0
- package/src/tui/components/chat/index.tsx +161 -0
- package/src/tui/components/chat/input-area.tsx +529 -0
- package/src/tui/components/chat/lib/play-core/num.ts +102 -0
- package/src/tui/components/chat/lib/wave-simulation.ts +124 -0
- package/src/tui/components/chat/loading-indicator.test.ts +33 -0
- package/src/tui/components/chat/loading-indicator.tsx +131 -0
- package/src/tui/components/chat/message-list.tsx +265 -0
- package/src/tui/components/chat/petri-animation.tsx +175 -0
- package/src/tui/components/chat/plan-review-message.tsx +49 -0
- package/src/tui/components/chat/questions-form.tsx +756 -0
- package/src/tui/components/commands/__tests__/recorded-runs-lifecycle.tsx +907 -0
- package/src/tui/components/commands/advanced-settings.tsx +94 -0
- package/src/tui/components/commands/api-key-input.tsx +122 -0
- package/src/tui/components/commands/auth-flow-logic.test.ts +58 -0
- package/src/tui/components/commands/auth-flow-logic.ts +30 -0
- package/src/tui/components/commands/auth-flow.tsx +702 -0
- package/src/tui/components/commands/credits-flow.tsx +210 -0
- package/src/tui/components/commands/help-dialog.tsx +238 -0
- package/src/tui/components/commands/models-display.tsx +111 -0
- package/src/tui/components/commands/operator-wizard.tsx +328 -0
- package/src/tui/components/commands/provider-manager.tsx +241 -0
- package/src/tui/components/commands/provider-selection.tsx +129 -0
- package/src/tui/components/commands/recorded-runs.test.ts +40 -0
- package/src/tui/components/commands/recorded-runs.tsx +793 -0
- package/src/tui/components/commands/sessions-display.tsx +365 -0
- package/src/tui/components/commands/shortcuts-dialog.tsx +52 -0
- package/src/tui/components/commands/skills-dialog.tsx +308 -0
- package/src/tui/components/commands/theme-picker.tsx +177 -0
- package/src/tui/components/commands/web-wizard.tsx +965 -0
- package/src/tui/components/dialog-layout.tsx +73 -0
- package/src/tui/components/error-boundary.tsx +82 -0
- package/src/tui/components/footer.tsx +101 -0
- package/src/tui/components/input.tsx +43 -0
- package/src/tui/components/loaders.tsx +784 -0
- package/src/tui/components/model-picker/ModelPicker.tsx +907 -0
- package/src/tui/components/model-picker/ModelPickerDialog.tsx +75 -0
- package/src/tui/components/model-picker/index.ts +2 -0
- package/src/tui/components/model-picker/model-navigation.test.ts +102 -0
- package/src/tui/components/model-picker/model-navigation.ts +54 -0
- package/src/tui/components/model-picker/model-search.test.ts +62 -0
- package/src/tui/components/model-picker/model-search.ts +42 -0
- package/src/tui/components/model-picker/model-visibility.test.ts +65 -0
- package/src/tui/components/model-picker/model-visibility.ts +59 -0
- package/src/tui/components/operator-dashboard/conversation.test.ts +431 -0
- package/src/tui/components/operator-dashboard/conversation.ts +179 -0
- package/src/tui/components/operator-dashboard/display-state.test.ts +369 -0
- package/src/tui/components/operator-dashboard/display-state.ts +163 -0
- package/src/tui/components/operator-dashboard/herdr-state.test.ts +162 -0
- package/src/tui/components/operator-dashboard/herdr-state.ts +81 -0
- package/src/tui/components/operator-dashboard/index.tsx +2044 -0
- package/src/tui/components/operator-dashboard/logic.test.ts +753 -0
- package/src/tui/components/operator-dashboard/logic.ts +465 -0
- package/src/tui/components/operator-dashboard/queue.test.ts +147 -0
- package/src/tui/components/operator-dashboard/queue.ts +55 -0
- package/src/tui/components/operator-dashboard/queued-messages.tsx +50 -0
- package/src/tui/components/operator-dashboard/run-events.test.ts +915 -0
- package/src/tui/components/operator-dashboard/run-events.ts +507 -0
- package/src/tui/components/operator-dashboard/run-tracing.test.ts +206 -0
- package/src/tui/components/operator-dashboard/run-tracing.ts +105 -0
- package/src/tui/components/operator-dashboard/subagent-detail-view.tsx +51 -0
- package/src/tui/components/operator-dashboard/subagent-dialog.tsx +142 -0
- package/src/tui/components/operator-dashboard/subagent-hub.test.ts +162 -0
- package/src/tui/components/operator-dashboard/subagent-hub.tsx +266 -0
- package/src/tui/components/operator-dashboard/subagent-state.test.ts +431 -0
- package/src/tui/components/operator-dashboard/subagent-state.ts +404 -0
- package/src/tui/components/operator-dashboard/subagent-status-bar.tsx +80 -0
- package/src/tui/components/operator-dashboard/tool-argument-buffer.test.ts +317 -0
- package/src/tui/components/operator-dashboard/tool-arguments.perf.test.ts +121 -0
- package/src/tui/components/operator-dashboard/welcome-logo.tsx +79 -0
- package/src/tui/components/operator-dashboard/workflow-data.test.ts +291 -0
- package/src/tui/components/operator-dashboard/workflow-data.ts +130 -0
- package/src/tui/components/report-viewer-dialog.tsx +98 -0
- package/src/tui/components/responsible-use-disclosure.tsx +55 -0
- package/src/tui/components/screenshot-modal.tsx +204 -0
- package/src/tui/components/shared/__tests__/prompt-input-lifecycle.tsx +64 -0
- package/src/tui/components/shared/__tests__/tool-renderer-lifecycle.tsx +87 -0
- package/src/tui/components/shared/action-label.test.ts +142 -0
- package/src/tui/components/shared/action-label.ts +18 -0
- package/src/tui/components/shared/ascii-spinner.tsx +40 -0
- package/src/tui/components/shared/compacting-icon.tsx +18 -0
- package/src/tui/components/shared/dialog-controls.tsx +76 -0
- package/src/tui/components/shared/index.ts +38 -0
- package/src/tui/components/shared/markdown-viewer.tsx +188 -0
- package/src/tui/components/shared/markdown.ts +239 -0
- package/src/tui/components/shared/message-renderer.tsx +178 -0
- package/src/tui/components/shared/message-utils.ts +175 -0
- package/src/tui/components/shared/pentest-workflow-display.tsx +330 -0
- package/src/tui/components/shared/prompt-input-lifecycle.test.ts +22 -0
- package/src/tui/components/shared/prompt-input-logic.test.ts +782 -0
- package/src/tui/components/shared/prompt-input-logic.ts +423 -0
- package/src/tui/components/shared/prompt-input.tsx +782 -0
- package/src/tui/components/shared/result-registry.test.ts +90 -0
- package/src/tui/components/shared/result-registry.ts +900 -0
- package/src/tui/components/shared/syntax-highlight.ts +242 -0
- package/src/tui/components/shared/tool-registry.test.ts +59 -0
- package/src/tui/components/shared/tool-registry.ts +280 -0
- package/src/tui/components/shared/tool-renderer.test.ts +13 -0
- package/src/tui/components/shared/tool-renderer.tsx +237 -0
- package/src/tui/components/shared/type-guards.ts +64 -0
- package/src/tui/components/shared/use-paste-extmarks.ts +109 -0
- package/src/tui/components/switch.tsx +81 -0
- package/src/tui/components/terminal-focus-handler.tsx +34 -0
- package/src/tui/components/toast.tsx +82 -0
- package/src/tui/components/usage-labels.test.ts +191 -0
- package/src/tui/components/usage-labels.ts +78 -0
- package/src/tui/console-theme.ts +59 -0
- package/src/tui/context/agent.tsx +251 -0
- package/src/tui/context/command.tsx +291 -0
- package/src/tui/context/config.tsx +59 -0
- package/src/tui/context/dialog.tsx +206 -0
- package/src/tui/context/dimensions.tsx +31 -0
- package/src/tui/context/focus-ownership.test.ts +26 -0
- package/src/tui/context/focus-ownership.ts +12 -0
- package/src/tui/context/focus.tsx +86 -0
- package/src/tui/context/herdr.tsx +28 -0
- package/src/tui/context/input.tsx +45 -0
- package/src/tui/context/keybinding.tsx +92 -0
- package/src/tui/context/obfuscation.tsx +114 -0
- package/src/tui/context/route.tsx +127 -0
- package/src/tui/context/session-usage.test.ts +295 -0
- package/src/tui/context/session-usage.ts +204 -0
- package/src/tui/context/session.tsx +62 -0
- package/src/tui/context/toast.tsx +66 -0
- package/src/tui/generated-ascii-art.json +1 -0
- package/src/tui/generated-ascii-art.json.d.ts +2 -0
- package/src/tui/herdr-startup.test.ts +157 -0
- package/src/tui/hooks/use-sessions-list.ts +165 -0
- package/src/tui/index.tsx +838 -0
- package/src/tui/keybindings/index.ts +126 -0
- package/src/tui/keybindings/registry.ts +146 -0
- package/src/tui/keybindings-registry.ts +43 -0
- package/src/tui/obfuscation/patch.ts +139 -0
- package/src/tui/terminal-focus.ts +218 -0
- package/src/tui/theme/colors.ts +43 -0
- package/src/tui/theme/context.tsx +137 -0
- package/src/tui/theme/detect-mode.ts +56 -0
- package/src/tui/theme/index.ts +75 -0
- package/src/tui/theme/registry.ts +29 -0
- package/src/tui/theme/themes/apex.ts +190 -0
- package/src/tui/theme/themes/ayu.ts +189 -0
- package/src/tui/theme/themes/catppuccin.ts +189 -0
- package/src/tui/theme/themes/dracula.ts +190 -0
- package/src/tui/theme/themes/everforest.ts +189 -0
- package/src/tui/theme/themes/flexoki.ts +190 -0
- package/src/tui/theme/themes/github.ts +189 -0
- package/src/tui/theme/themes/gruvbox.ts +189 -0
- package/src/tui/theme/themes/index.ts +54 -0
- package/src/tui/theme/themes/kanagawa.ts +189 -0
- package/src/tui/theme/themes/material.ts +190 -0
- package/src/tui/theme/themes/monokai.ts +190 -0
- package/src/tui/theme/themes/nightfox.ts +189 -0
- package/src/tui/theme/themes/nord.ts +190 -0
- package/src/tui/theme/themes/onedark.ts +190 -0
- package/src/tui/theme/themes/rose-pine.ts +189 -0
- package/src/tui/theme/themes/solarized.ts +189 -0
- package/src/tui/theme/themes/tokyonight.ts +189 -0
- package/src/tui/theme/themes/vesper.ts +191 -0
- package/src/tui/theme/types.ts +143 -0
- package/src/tui/utils/command-flags.test.ts +269 -0
- package/src/tui/utils/command-flags.ts +377 -0
- package/src/tui/utils/kitty-graphics.ts +76 -0
- package/src/tui/utils/open-file.ts +37 -0
- package/src/tui/utils/open-report.ts +34 -0
- package/src/tui/utils/open-url.ts +39 -0
- package/src/tui/utils/paste.ts +8 -0
- package/src/tui/utils/scroll.ts +81 -0
- package/src/util/errors.ts +58 -0
- package/src/util/lock.ts +100 -0
- package/src/util/name.ts +148 -0
- package/src/util/url.test.ts +162 -0
- package/src/util/url.ts +107 -0
- package/build/agent-13rrhp8d.js +0 -20
- package/build/agent-zbj2331s.js +0 -30
- package/build/authentication-f4j3w5vs.js +0 -20
- package/build/blackboxAgent-v2vx9ws4.js +0 -20
- package/build/blackboxPentest-w5nwzpvk.js +0 -70
- package/build/cli-5wemv37a.js +0 -194
- package/build/cli-7s062hr6.js +0 -22
- package/build/cli-9qbxkhye.js +0 -55
- package/build/cli-avmhkjtv.js +0 -22961
- package/build/cli-g3czc3jz.js +0 -204
- package/build/cli-ww7hbazg.js +0 -88
- package/build/index-18vyy6mj.js +0 -19
- package/build/index-5wh7gq37.js +0 -12858
- package/build/index-e23zc8g4.js +0 -34
- package/build/index-hnwhswqj.js +0 -213
- package/build/index-wkmnr4nm.js +0 -39
- package/build/index-ywmfnd30.js +0 -12
- package/build/offesecAgent-c97pqzcn.js +0 -27
- package/build/pentest-4p5jt7gj.js +0 -30
- package/build/pentests-v98eg8n3.js +0 -92
- package/build/threatModel-81d4rcbk.js +0 -29
- /package/build/{cli-c8131c4q.js → cli-0wsh8j2t.js} +0 -0
- /package/build/{cli-9pbk8m32.js → cli-ag6jtndp.js} +0 -0
- /package/build/{cli-e08r86zk.js → cli-b3dvxjgk.js} +0 -0
- /package/build/{cli-fw5r7pfj.js → cli-q126f6ef.js} +0 -0
- /package/build/{cli-9fsre5pt.js → cli-qba2x69h.js} +0 -0
- /package/build/{cli-7q3ae3ft.js → cli-z82n3qk1.js} +0 -0
|
@@ -0,0 +1,2377 @@
|
|
|
1
|
+
import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
|
|
2
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
3
|
+
import type { AnthropicMessagesModelId } from "@ai-sdk/anthropic/internal";
|
|
4
|
+
import type { OpenAIResponsesProviderOptions } from "@ai-sdk/openai";
|
|
5
|
+
import type { OpenAIChatModelId } from "@ai-sdk/openai/internal";
|
|
6
|
+
import {
|
|
7
|
+
generateText,
|
|
8
|
+
type LanguageModel,
|
|
9
|
+
type LanguageModelMiddleware,
|
|
10
|
+
type ModelMessage,
|
|
11
|
+
Output,
|
|
12
|
+
type StopCondition,
|
|
13
|
+
type StreamTextOnFinishCallback,
|
|
14
|
+
type StreamTextOnStepFinishCallback,
|
|
15
|
+
type StreamTextResult,
|
|
16
|
+
streamText,
|
|
17
|
+
type TextStreamPart,
|
|
18
|
+
type ToolChoice,
|
|
19
|
+
type ToolSet,
|
|
20
|
+
wrapLanguageModel,
|
|
21
|
+
} from "ai";
|
|
22
|
+
import type { z } from "zod";
|
|
23
|
+
import {
|
|
24
|
+
type CustomProviders,
|
|
25
|
+
parseCustomModelId,
|
|
26
|
+
resolveCustomModel,
|
|
27
|
+
} from "../config/customProviders";
|
|
28
|
+
import { type HoonifyModel, resolveHoonifyModel } from "../hoonify";
|
|
29
|
+
import { createLogger } from "../logger/structured";
|
|
30
|
+
import {
|
|
31
|
+
type AiTelemetryOperation,
|
|
32
|
+
createAiTelemetrySettings,
|
|
33
|
+
createGenerationSpanTracker,
|
|
34
|
+
type GenerationSpanTracker,
|
|
35
|
+
withModelCallDiagnostics,
|
|
36
|
+
} from "../observability";
|
|
37
|
+
import { RunPersistenceError } from "../runtime/persistenceError";
|
|
38
|
+
import type { RunContextRecorder } from "../runtime/runContext";
|
|
39
|
+
import { RunControlInterruption } from "../runtime/runControlStore";
|
|
40
|
+
import { RunLimitError } from "../runtime/runModelStore";
|
|
41
|
+
import { scopedLogger } from "../util/lazyLogger";
|
|
42
|
+
import {
|
|
43
|
+
cacheBreakpointFor,
|
|
44
|
+
withCachedLastMessage,
|
|
45
|
+
withCachedSystemPrompt,
|
|
46
|
+
} from "./caching";
|
|
47
|
+
import {
|
|
48
|
+
beginCompaction,
|
|
49
|
+
type CompactionLink,
|
|
50
|
+
type CompactionTrigger,
|
|
51
|
+
} from "./compactionTelemetry";
|
|
52
|
+
import {
|
|
53
|
+
estimateMessageTokens,
|
|
54
|
+
fitMessagesToContext,
|
|
55
|
+
truncateWithMarker,
|
|
56
|
+
} from "./contextManagement";
|
|
57
|
+
import {
|
|
58
|
+
getInferenceRecorder,
|
|
59
|
+
type InferenceRecorder,
|
|
60
|
+
runWithInferenceRecorder,
|
|
61
|
+
} from "./inference-attempt";
|
|
62
|
+
import {
|
|
63
|
+
type ClaudeThinkingEffort,
|
|
64
|
+
getClaudeCapabilities,
|
|
65
|
+
getMaxOutputTokens,
|
|
66
|
+
getModelInfo,
|
|
67
|
+
prefersSequentialToolCalls,
|
|
68
|
+
} from "./models";
|
|
69
|
+
import {
|
|
70
|
+
runWithNativeRolloutOperation,
|
|
71
|
+
withNativeRolloutEvidenceModel,
|
|
72
|
+
} from "./native-rollout-evidence";
|
|
73
|
+
import { CONCENTRATE_GLM_5_3_MODEL_ID } from "./providers/concentrate";
|
|
74
|
+
import { OPENAI_PRO_TIMEOUT_MS } from "./providers/openai-pro-fetch";
|
|
75
|
+
import { STREAM_DEBUG } from "./streamTelemetry";
|
|
76
|
+
import {
|
|
77
|
+
type AIAuthConfig,
|
|
78
|
+
checkIfContextLengthError,
|
|
79
|
+
createSummarizationStream,
|
|
80
|
+
getProviderModel,
|
|
81
|
+
isAnthropicProvider,
|
|
82
|
+
} from "./utils";
|
|
83
|
+
|
|
84
|
+
const log = scopedLogger(() => createLogger("ai"));
|
|
85
|
+
|
|
86
|
+
// Opt-in debug logging for the empty-`{}` / looping response failure; bypasses `silent`.
|
|
87
|
+
const RESPONSE_DEBUG =
|
|
88
|
+
process.env.RESPONSE_DEBUG === "1" || process.env.RESPONSE_DEBUG === "true";
|
|
89
|
+
const RESPONSE_TOOL_NAME = "response";
|
|
90
|
+
|
|
91
|
+
function nativeRolloutOperation(
|
|
92
|
+
operation?: AiTelemetryOperation,
|
|
93
|
+
): "structured.generate" | "context.summarize" | "tool.repair" {
|
|
94
|
+
if (operation === "apex.context.summarize") return "context.summarize";
|
|
95
|
+
if (operation === "apex.tool.repair") return "tool.repair";
|
|
96
|
+
return "structured.generate";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Tools whose arguments carry a security-authorization boundary the model must
|
|
101
|
+
* never have re-synthesized by tool-call repair. Repair asks a model to invent
|
|
102
|
+
* schema-valid arguments from a failed call; for these tools a fabricated value
|
|
103
|
+
* (e.g. a default/localhost `target`) would silently bypass deterministic scope
|
|
104
|
+
* enforcement. Repair therefore FAILS CLOSED for them — it returns `null` and
|
|
105
|
+
* the original invalid call is never executed.
|
|
106
|
+
*
|
|
107
|
+
* Result-submission tools (`submit_results`, `document_vulnerability`) are
|
|
108
|
+
* deliberately NOT listed: they carry no authorization boundary, so repair is
|
|
109
|
+
* safe and desirable — it re-prompts the model to fix a mis-shaped field (e.g.
|
|
110
|
+
* `method` sent as an array) instead of dropping a completed recon or a
|
|
111
|
+
* confirmed finding.
|
|
112
|
+
*/
|
|
113
|
+
const REPAIR_FAIL_CLOSED_TOOLS: ReadonlySet<string> = new Set([
|
|
114
|
+
"spawn_pentest_agent",
|
|
115
|
+
]);
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Whether tool-call repair must fail closed (no argument synthesis) for a tool.
|
|
119
|
+
* Exported for regression tests covering the repaired-invalid-call path.
|
|
120
|
+
*/
|
|
121
|
+
export function isRepairFailClosedTool(toolName: string): boolean {
|
|
122
|
+
return REPAIR_FAIL_CLOSED_TOOLS.has(toolName);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export type AIModel = AnthropicMessagesModelId | OpenAIChatModelId | string; // For gateway and Bedrock model IDs
|
|
126
|
+
|
|
127
|
+
export type OpenAIReasoningEffort =
|
|
128
|
+
| "none"
|
|
129
|
+
| "low"
|
|
130
|
+
| "medium"
|
|
131
|
+
| "high"
|
|
132
|
+
| "xhigh"
|
|
133
|
+
| "max"
|
|
134
|
+
| "ultra";
|
|
135
|
+
|
|
136
|
+
export const DEFAULT_OPENAI_REASONING_EFFORT: OpenAIReasoningEffort = "medium";
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Anthropic adaptive-thinking effort hint. Soft guidance for how much the model
|
|
140
|
+
* reasons (see AWS "adaptive thinking"): `low` minimizes thinking while
|
|
141
|
+
* `xhigh` and `max` allow progressively deeper work. Only meaningful for
|
|
142
|
+
* models that support adaptive thinking; ignored elsewhere.
|
|
143
|
+
*/
|
|
144
|
+
export type ThinkingEffort = ClaudeThinkingEffort;
|
|
145
|
+
|
|
146
|
+
const OPENAI_REASONING_MODEL_IDS = new Set([
|
|
147
|
+
"gpt-6.1-sol",
|
|
148
|
+
"gpt-6-luna",
|
|
149
|
+
"gpt-6-sol",
|
|
150
|
+
"gpt-6-astra",
|
|
151
|
+
"gpt-5.5-pro",
|
|
152
|
+
"gpt-5.5-pro-2026-04-23",
|
|
153
|
+
"gpt-5.4-nano",
|
|
154
|
+
"gpt-5.4-nano-2026-03-17",
|
|
155
|
+
"gpt-5.4-mini",
|
|
156
|
+
"gpt-5.4-mini-2026-03-17",
|
|
157
|
+
"gpt-5",
|
|
158
|
+
"gpt-5-2025-08-07",
|
|
159
|
+
"gpt-5.1",
|
|
160
|
+
"gpt-5.1-2025-11-13",
|
|
161
|
+
"gpt-5.2",
|
|
162
|
+
"gpt-5.2-2025-12-11",
|
|
163
|
+
"gpt-5.2-pro",
|
|
164
|
+
"gpt-5.2-pro-2025-12-11",
|
|
165
|
+
"gpt-5.4",
|
|
166
|
+
"gpt-5.4-2026-03-05",
|
|
167
|
+
"gpt-5.4-pro",
|
|
168
|
+
"gpt-5.4-pro-2026-03-05",
|
|
169
|
+
"gpt-5.5",
|
|
170
|
+
"gpt-5.5-2026-04-23",
|
|
171
|
+
"gpt-5.6-sol",
|
|
172
|
+
"gpt-5.6-terra",
|
|
173
|
+
"gpt-5.6-luna",
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
/** Per-step billing context attached to a usage report, attributing cost to a specific `(sessionId, stepSeq)`. */
|
|
177
|
+
export interface UsageStepContext {
|
|
178
|
+
sessionId?: string;
|
|
179
|
+
stepSeq?: number;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Context attached to every usage report. The cache counters are always
|
|
184
|
+
* present — zero when the provider supplies none — and are already included
|
|
185
|
+
* in `inputTokens`:
|
|
186
|
+
* `uncachedInputTokens = inputTokens - cacheReadTokens - cacheWriteTokens`.
|
|
187
|
+
*/
|
|
188
|
+
export interface UsageCallbackContext extends UsageStepContext {
|
|
189
|
+
cacheReadTokens: number;
|
|
190
|
+
cacheWriteTokens: number;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Callback for reporting token usage from AI operations. */
|
|
194
|
+
export type UsageCallback = (
|
|
195
|
+
modelId: string,
|
|
196
|
+
inputTokens: number,
|
|
197
|
+
outputTokens: number,
|
|
198
|
+
context: UsageCallbackContext,
|
|
199
|
+
) => void | Promise<void>;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Per-run usage recorder threaded through {@link StreamResponseOpts}. When set
|
|
203
|
+
* it replaces the ALS run sink and the ambient {@link onUsage} callback for
|
|
204
|
+
* that call. Async work is awaited before the next model step. Receives the
|
|
205
|
+
* same cache-aware {@link UsageCallbackContext} as the global callback, so
|
|
206
|
+
* the cached/uncached split travels on the usage event itself.
|
|
207
|
+
*/
|
|
208
|
+
export type UsageRecorder = (
|
|
209
|
+
model: string,
|
|
210
|
+
inputTokens: number,
|
|
211
|
+
outputTokens: number,
|
|
212
|
+
context?: UsageCallbackContext,
|
|
213
|
+
) => void | Promise<void>;
|
|
214
|
+
|
|
215
|
+
let _usageCallback: UsageCallback | null = null;
|
|
216
|
+
|
|
217
|
+
/** Ambient default usage sink when no run-context sink is set. */
|
|
218
|
+
export function onUsage(cb: UsageCallback | null): void {
|
|
219
|
+
_usageCallback = cb;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Normalized per-step usage: input/output plus cache buckets, provider-agnostic. */
|
|
223
|
+
export interface NormalizedStepUsage {
|
|
224
|
+
inputTokens: number;
|
|
225
|
+
outputTokens: number;
|
|
226
|
+
cacheReadTokens: number;
|
|
227
|
+
cacheWriteTokens: number;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Extract normalized usage from one completed model step. A single function
|
|
232
|
+
* feeds both `onCacheMetrics` and the usage callback so provider metadata is
|
|
233
|
+
* never parsed twice. Anthropic's `providerMetadata.anthropic` wins; the
|
|
234
|
+
* SDK's normalized `usage.inputTokenDetails` is the fallback (Pensar
|
|
235
|
+
* provider). Input stays inclusive of cached tokens.
|
|
236
|
+
*/
|
|
237
|
+
export function normalizeStepUsage(step: {
|
|
238
|
+
usage?: {
|
|
239
|
+
inputTokens?: number;
|
|
240
|
+
outputTokens?: number;
|
|
241
|
+
inputTokenDetails?: {
|
|
242
|
+
cacheReadTokens?: number;
|
|
243
|
+
cacheWriteTokens?: number;
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
providerMetadata?: unknown;
|
|
247
|
+
}): NormalizedStepUsage {
|
|
248
|
+
const inputTokens = step.usage?.inputTokens ?? 0;
|
|
249
|
+
const outputTokens = step.usage?.outputTokens ?? 0;
|
|
250
|
+
|
|
251
|
+
// Extract Anthropic cache metrics from providerMetadata (direct Anthropic / Bedrock SDK)
|
|
252
|
+
const meta = (
|
|
253
|
+
step.providerMetadata as
|
|
254
|
+
| { anthropic?: Record<string, unknown> }
|
|
255
|
+
| null
|
|
256
|
+
| undefined
|
|
257
|
+
)?.anthropic;
|
|
258
|
+
let cacheRead = (meta?.cacheReadInputTokens as number) ?? 0;
|
|
259
|
+
let cacheWrite = (meta?.cacheCreationInputTokens as number) ?? 0;
|
|
260
|
+
|
|
261
|
+
// Pensar provider doesn't populate providerMetadata.anthropic;
|
|
262
|
+
// fall back to the SDK's normalized usage.inputTokenDetails.
|
|
263
|
+
const details = step.usage?.inputTokenDetails;
|
|
264
|
+
if (cacheRead === 0) {
|
|
265
|
+
cacheRead = details?.cacheReadTokens ?? 0;
|
|
266
|
+
}
|
|
267
|
+
if (cacheWrite === 0) {
|
|
268
|
+
cacheWrite = details?.cacheWriteTokens ?? 0;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return {
|
|
272
|
+
inputTokens,
|
|
273
|
+
outputTokens,
|
|
274
|
+
cacheReadTokens: cacheRead,
|
|
275
|
+
cacheWriteTokens: cacheWrite,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Per-run step counter for billing attribution, scoped via AsyncLocalStorage so
|
|
280
|
+
// concurrent runs never race a shared index. Not a strict global sequence —
|
|
281
|
+
// the DB `stepSeq` on `agent_messages` remains authoritative; this only labels
|
|
282
|
+
// live usage reports.
|
|
283
|
+
|
|
284
|
+
interface StepContext {
|
|
285
|
+
sessionId?: string;
|
|
286
|
+
/** Next step index to hand out; mutated in place as steps finish. */
|
|
287
|
+
next: number;
|
|
288
|
+
/** Per-run usage sink; wins over the ambient {@link onUsage} callback. */
|
|
289
|
+
usageSink?: UsageCallback;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const stepContextStore = new AsyncLocalStorage<StepContext>();
|
|
293
|
+
|
|
294
|
+
/** Runs `fn` in a per-run step-counting context; `streamResponse` steps inside it report usage tagged with `sessionId` and an increasing `stepSeq` starting at `seedStepSeq`. */
|
|
295
|
+
export function runWithStepContext<T>(
|
|
296
|
+
opts: {
|
|
297
|
+
sessionId?: string;
|
|
298
|
+
seedStepSeq?: number;
|
|
299
|
+
usageSink?: UsageCallback;
|
|
300
|
+
},
|
|
301
|
+
fn: () => T,
|
|
302
|
+
): T {
|
|
303
|
+
const parent = stepContextStore.getStore();
|
|
304
|
+
return stepContextStore.run(
|
|
305
|
+
{
|
|
306
|
+
sessionId: opts.sessionId,
|
|
307
|
+
next: opts.seedStepSeq ?? 0,
|
|
308
|
+
usageSink: opts.usageSink ?? parent?.usageSink,
|
|
309
|
+
},
|
|
310
|
+
fn,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** Takes and advances the next `stepSeq` for the current run; returns `undefined` outside any run context. */
|
|
315
|
+
export function takeStepContext(): UsageStepContext | undefined {
|
|
316
|
+
const store = stepContextStore.getStore();
|
|
317
|
+
if (!store) return undefined;
|
|
318
|
+
const stepSeq = store.next;
|
|
319
|
+
store.next += 1;
|
|
320
|
+
return { sessionId: store.sessionId, stepSeq };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Report one finished model call to a usage sink. Advances `stepSeq` whenever
|
|
325
|
+
* a sink is present (including zero-token steps) so the index stays aligned
|
|
326
|
+
* with the AI SDK. Skips the callback itself when both token counts are 0.
|
|
327
|
+
*/
|
|
328
|
+
async function emitUsage(
|
|
329
|
+
model: string,
|
|
330
|
+
stepUsage: NormalizedStepUsage,
|
|
331
|
+
sink: UsageRecorder | UsageCallback | null | undefined,
|
|
332
|
+
): Promise<void> {
|
|
333
|
+
if (!sink) return;
|
|
334
|
+
const stepCtx = takeStepContext();
|
|
335
|
+
if (stepUsage.inputTokens <= 0 && stepUsage.outputTokens <= 0) return;
|
|
336
|
+
await sink(model, stepUsage.inputTokens, stepUsage.outputTokens, {
|
|
337
|
+
...stepCtx,
|
|
338
|
+
cacheReadTokens: stepUsage.cacheReadTokens,
|
|
339
|
+
cacheWriteTokens: stepUsage.cacheWriteTokens,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** explicit recorder > ALS run sink > ambient {@link onUsage}. */
|
|
344
|
+
function resolveUsageSink(
|
|
345
|
+
explicit?: UsageRecorder,
|
|
346
|
+
): UsageRecorder | UsageCallback | null {
|
|
347
|
+
return explicit ?? stepContextStore.getStore()?.usageSink ?? _usageCallback;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export type AIModelProvider =
|
|
351
|
+
| "custom"
|
|
352
|
+
| "anthropic"
|
|
353
|
+
| "openai"
|
|
354
|
+
| "google"
|
|
355
|
+
| "openrouter"
|
|
356
|
+
| "concentrate"
|
|
357
|
+
| "bedrock"
|
|
358
|
+
| "bedrock-mantle"
|
|
359
|
+
| "pensar"
|
|
360
|
+
| "inception"
|
|
361
|
+
| "hoonify"
|
|
362
|
+
| "local";
|
|
363
|
+
|
|
364
|
+
/** Conservative default when `getModelInfo` doesn't have a `contextLength`. */
|
|
365
|
+
export function getContextWindow(
|
|
366
|
+
modelId: string,
|
|
367
|
+
customProviders?: CustomProviders,
|
|
368
|
+
hoonifyModels?: HoonifyModel[],
|
|
369
|
+
): number {
|
|
370
|
+
if (modelId.startsWith("hoonify:"))
|
|
371
|
+
return resolveHoonifyModel(modelId, hoonifyModels).contextLength;
|
|
372
|
+
if (parseCustomModelId(modelId))
|
|
373
|
+
return resolveCustomModel(modelId, customProviders).model.contextLength;
|
|
374
|
+
return getModelInfo(modelId).contextLength ?? 200_000;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function checkIfRateLimitError(error: unknown): boolean {
|
|
378
|
+
const errObj =
|
|
379
|
+
typeof error === "object" && error !== null
|
|
380
|
+
? (error as Record<string, unknown>)
|
|
381
|
+
: {};
|
|
382
|
+
|
|
383
|
+
// Check message — works for both Error instances and plain objects
|
|
384
|
+
// (Bedrock streaming errors are plain { message: "..." } records)
|
|
385
|
+
const errorMessage = (
|
|
386
|
+
typeof errObj.message === "string" ? errObj.message : ""
|
|
387
|
+
).toLowerCase();
|
|
388
|
+
const errorCode = String(
|
|
389
|
+
typeof errObj.code === "string" ? errObj.code : "",
|
|
390
|
+
).toLowerCase();
|
|
391
|
+
// AWS SDK errors surface the exception type via .name
|
|
392
|
+
const errorName = (
|
|
393
|
+
typeof errObj.name === "string" ? errObj.name : ""
|
|
394
|
+
).toLowerCase();
|
|
395
|
+
// Bedrock HTTP-level errors include $metadata.httpStatusCode
|
|
396
|
+
const httpStatus =
|
|
397
|
+
typeof errObj.$metadata === "object" && errObj.$metadata !== null
|
|
398
|
+
? (errObj.$metadata as Record<string, unknown>).httpStatusCode
|
|
399
|
+
: undefined;
|
|
400
|
+
// Stringified fallback for opaque error objects (e.g. Bedrock stream records)
|
|
401
|
+
const errorString =
|
|
402
|
+
errorMessage || errorName ? "" : String(error).toLowerCase();
|
|
403
|
+
|
|
404
|
+
return (
|
|
405
|
+
// Message-based detection
|
|
406
|
+
errorMessage.includes("too many tokens") ||
|
|
407
|
+
errorMessage.includes("rate limit") ||
|
|
408
|
+
errorMessage.includes("request rate") ||
|
|
409
|
+
errorMessage.includes("throttl") ||
|
|
410
|
+
errorMessage.includes("overloaded") ||
|
|
411
|
+
errorMessage.includes("too many requests") ||
|
|
412
|
+
errorMessage.includes("please wait") ||
|
|
413
|
+
errorMessage.includes("service unavailable") ||
|
|
414
|
+
// AWS SDK exception names (ThrottlingException, TooManyRequestsException)
|
|
415
|
+
errorName.includes("throttl") ||
|
|
416
|
+
errorName.includes("toomanyrequests") ||
|
|
417
|
+
errorName.includes("serviceunavailable") ||
|
|
418
|
+
// Error codes
|
|
419
|
+
errorCode === "rate_limit_exceeded" ||
|
|
420
|
+
errorCode === "throttling" ||
|
|
421
|
+
errorCode === "429" ||
|
|
422
|
+
// HTTP status from AWS SDK $metadata
|
|
423
|
+
httpStatus === 429 ||
|
|
424
|
+
httpStatus === 529 ||
|
|
425
|
+
httpStatus === 503 ||
|
|
426
|
+
// Fallback: stringified error for opaque Bedrock stream records
|
|
427
|
+
errorString.includes("throttl") ||
|
|
428
|
+
errorString.includes("too many") ||
|
|
429
|
+
errorString.includes("request rate")
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Injected into the system prompt for models that mis-parse parallel tool
|
|
434
|
+
// calls (DeepSeek V3.1 on Bedrock). See prefersSequentialToolCalls.
|
|
435
|
+
const SEQUENTIAL_TOOL_CALL_INSTRUCTION =
|
|
436
|
+
"CRITICAL TOOL-CALLING RULE: Emit EXACTLY ONE tool call per response. " +
|
|
437
|
+
"Never emit more than one tool call in a single turn. After each tool call, " +
|
|
438
|
+
"wait for its result before making the next one. Emitting multiple tool " +
|
|
439
|
+
"calls in one turn corrupts their arguments.";
|
|
440
|
+
|
|
441
|
+
// Returns the system prompt that is actually sent to the provider, accounting
|
|
442
|
+
// for the sequential-tool-call policy appended for models that mis-parse
|
|
443
|
+
// parallel tool calls. Token budgeting (`fitMessagesToContext`) must use this
|
|
444
|
+
// value, not the raw `system`, or it underestimates the system prompt size and
|
|
445
|
+
// overestimates the message budget near the context limit.
|
|
446
|
+
function applySequentialToolCallPolicy(
|
|
447
|
+
system: string | undefined,
|
|
448
|
+
tools: ToolSet | undefined,
|
|
449
|
+
model: AIModel,
|
|
450
|
+
): string | undefined {
|
|
451
|
+
if (
|
|
452
|
+
tools &&
|
|
453
|
+
Object.keys(tools).length > 0 &&
|
|
454
|
+
prefersSequentialToolCalls(model)
|
|
455
|
+
) {
|
|
456
|
+
return `${system ? `${system}\n\n` : ""}${SEQUENTIAL_TOOL_CALL_INSTRUCTION}`;
|
|
457
|
+
}
|
|
458
|
+
return system;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// The structured-output `response` tool is injected by the caller alongside its
|
|
462
|
+
// own tools, so an allowlist of those tools must not hide it from the model.
|
|
463
|
+
// Composed into `resolveEffectiveTools` at the call site so the executable map
|
|
464
|
+
// keeps `response` even when a caller omits it from `activeTools`.
|
|
465
|
+
export function withResponseToolActive(
|
|
466
|
+
tools: ToolSet | undefined,
|
|
467
|
+
activeTools: string[] | undefined,
|
|
468
|
+
): string[] | undefined {
|
|
469
|
+
if (
|
|
470
|
+
!tools ||
|
|
471
|
+
!activeTools ||
|
|
472
|
+
activeTools.length === 0 ||
|
|
473
|
+
!(RESPONSE_TOOL_NAME in tools) ||
|
|
474
|
+
activeTools.includes(RESPONSE_TOOL_NAME)
|
|
475
|
+
) {
|
|
476
|
+
return activeTools;
|
|
477
|
+
}
|
|
478
|
+
return [...activeTools, RESPONSE_TOOL_NAME];
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Resolve the effective toolset from `activeTools` before any context
|
|
483
|
+
* fitting. The AI SDK treats `activeTools` as advertise-only — it still
|
|
484
|
+
* parses, executes, and enumerates every tool in the full map — so the
|
|
485
|
+
* executable map itself must be filtered here for budgeting, provider
|
|
486
|
+
* exposure, execution, and repair to agree. Built with DefineOwnProperty
|
|
487
|
+
* semantics so prototype-shaped names like `__proto__` survive as own keys.
|
|
488
|
+
* Feed it `withResponseToolActive(tools, activeTools)` so the injected
|
|
489
|
+
* structured-output tool survives the filter.
|
|
490
|
+
*/
|
|
491
|
+
export function resolveEffectiveTools(
|
|
492
|
+
tools: ToolSet | undefined,
|
|
493
|
+
activeTools: string[] | undefined,
|
|
494
|
+
): Pick<StreamResponseOpts, "tools" | "activeTools"> {
|
|
495
|
+
if (!tools || !activeTools) return {};
|
|
496
|
+
if (activeTools.length === 0) return { tools: {}, activeTools: undefined };
|
|
497
|
+
const allow = new Set(activeTools);
|
|
498
|
+
return {
|
|
499
|
+
tools: Object.fromEntries(
|
|
500
|
+
Object.entries(tools).filter(([name]) => allow.has(name)),
|
|
501
|
+
),
|
|
502
|
+
activeTools: undefined,
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Kept for callers/tests that filter a tool map without consuming `activeTools`
|
|
507
|
+
// (e.g. `withResponseToolActive` composition). `resolveEffectiveTools` is the
|
|
508
|
+
// stream-loop entry point; this is the same filter returning just the map.
|
|
509
|
+
export function restrictToolsToActive(
|
|
510
|
+
tools: ToolSet | undefined,
|
|
511
|
+
activeTools: string[] | undefined,
|
|
512
|
+
): ToolSet | undefined {
|
|
513
|
+
if (!tools || !activeTools || activeTools.length === 0) {
|
|
514
|
+
return tools;
|
|
515
|
+
}
|
|
516
|
+
const allow = new Set(activeTools);
|
|
517
|
+
const restricted: ToolSet = {};
|
|
518
|
+
for (const [name, tool] of Object.entries(tools)) {
|
|
519
|
+
if (allow.has(name)) {
|
|
520
|
+
restricted[name] = tool;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return restricted;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const MAX_RATE_LIMIT_RETRIES = 20;
|
|
527
|
+
const MAX_IDLE_RESUME_RETRIES = 3;
|
|
528
|
+
const STREAM_IDLE_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
529
|
+
|
|
530
|
+
// Observe the existing depth allowance only for accepted restarts.
|
|
531
|
+
export async function recordContextRestart(
|
|
532
|
+
depth: number,
|
|
533
|
+
opts?: Pick<StreamResponseOpts, "inferenceRecorder">,
|
|
534
|
+
): Promise<void> {
|
|
535
|
+
if (depth > MAX_RESTART_DEPTH) return;
|
|
536
|
+
await getInferenceRecorder(opts)?.retry({
|
|
537
|
+
authority: "context-restart",
|
|
538
|
+
count: depth,
|
|
539
|
+
maxRetries: MAX_RESTART_DEPTH,
|
|
540
|
+
delayMs: 0,
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function getStreamIdleTimeoutMs(model: AIModel): number {
|
|
545
|
+
// Pro cannot stream progress while reasoning; wait for its completed response.
|
|
546
|
+
return /^(?:openai\/)?gpt-5\.5-pro(?:-|$)/.test(model)
|
|
547
|
+
? OPENAI_PRO_TIMEOUT_MS
|
|
548
|
+
: STREAM_IDLE_TIMEOUT_MS;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
class StreamIdleTimeoutError extends Error {
|
|
552
|
+
constructor(idleMs: number) {
|
|
553
|
+
super(`Stream idle for ${Math.round(idleMs / 1000)}s — no chunks received`);
|
|
554
|
+
this.name = "StreamIdleTimeoutError";
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Wraps an async iterable with a per-chunk idle timeout. If no chunk arrives
|
|
560
|
+
* within `idleMs`, throws a {@link StreamIdleTimeoutError} so the caller can
|
|
561
|
+
* resume the conversation from accumulated messages.
|
|
562
|
+
*
|
|
563
|
+
* @param isIdleTimerActive Optional predicate evaluated before awaiting each
|
|
564
|
+
* chunk. When it returns `false` the timer is skipped for that chunk and we
|
|
565
|
+
* wait indefinitely. This lets callers suppress the timeout during expected
|
|
566
|
+
* long pauses (e.g. while a tool call is executing) so a slow tool isn't
|
|
567
|
+
* misread as a stalled provider stream.
|
|
568
|
+
*/
|
|
569
|
+
async function* withIdleTimeout<T>(
|
|
570
|
+
stream: AsyncIterable<T>,
|
|
571
|
+
idleMs: number,
|
|
572
|
+
isIdleTimerActive?: () => boolean,
|
|
573
|
+
): AsyncGenerator<T> {
|
|
574
|
+
const iterator = stream[Symbol.asyncIterator]();
|
|
575
|
+
try {
|
|
576
|
+
while (true) {
|
|
577
|
+
const timerActive = isIdleTimerActive?.() ?? true;
|
|
578
|
+
let result: IteratorResult<T>;
|
|
579
|
+
if (timerActive) {
|
|
580
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
581
|
+
result = await Promise.race([
|
|
582
|
+
iterator.next(),
|
|
583
|
+
new Promise<never>((_, reject) => {
|
|
584
|
+
timer = setTimeout(
|
|
585
|
+
() => reject(new StreamIdleTimeoutError(idleMs)),
|
|
586
|
+
idleMs,
|
|
587
|
+
);
|
|
588
|
+
if (typeof timer === "object" && "unref" in timer) timer.unref();
|
|
589
|
+
}),
|
|
590
|
+
]);
|
|
591
|
+
clearTimeout(timer);
|
|
592
|
+
} else {
|
|
593
|
+
result = await iterator.next();
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (result.done) return;
|
|
597
|
+
yield result.value;
|
|
598
|
+
}
|
|
599
|
+
} finally {
|
|
600
|
+
// Best-effort cleanup — don't block on a stuck iterator. The underlying
|
|
601
|
+
// stream may be wedged (that's why we're here), so a hanging return()
|
|
602
|
+
// would deadlock the consumer.
|
|
603
|
+
iterator.return?.()?.catch?.(() => {});
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function isStreamIdleTimeoutError(error: unknown): boolean {
|
|
608
|
+
// AI SDK may rewrap the error, so walk `cause`.
|
|
609
|
+
for (let e: unknown = error, depth = 0; e != null && depth < 6; depth++) {
|
|
610
|
+
if (e instanceof StreamIdleTimeoutError) return true;
|
|
611
|
+
e = (e as { cause?: unknown }).cause;
|
|
612
|
+
}
|
|
613
|
+
return false;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Gates the idle-timeout in {@link withIdleTimeout} so it only fires while
|
|
618
|
+
* we're waiting on the **model**, not while a tool is executing.
|
|
619
|
+
*
|
|
620
|
+
* The provider stream emits nothing between a `tool-call` chunk and the
|
|
621
|
+
* matching `tool-result`. A slow tool (e.g. `run_attack_surface`, which
|
|
622
|
+
* spawns a multi-minute sub-agent) would otherwise be misread as a stalled
|
|
623
|
+
* stream — triggering the auto-resume path and causing the model to re-issue
|
|
624
|
+
* the same tool call, which spawns a duplicate sub-agent.
|
|
625
|
+
*
|
|
626
|
+
* Parallel tool calls are tracked by `toolCallId`. Duplicate `tool-call`
|
|
627
|
+
* chunks for the same id (defensive — should never happen in practice) are
|
|
628
|
+
* deduplicated. Terminal chunks (`tool-result` / `tool-error`) without a
|
|
629
|
+
* matching open call are ignored so the counter can never go negative.
|
|
630
|
+
*
|
|
631
|
+
* EXCEPTION: `response` is never gated — its `execute` returns synchronously so
|
|
632
|
+
* it's not a slow tool, but a Bedrock stream wedging mid-payload while
|
|
633
|
+
* streaming its (often large) args would otherwise suppress the idle timeout
|
|
634
|
+
* forever (confirmed hang). Leaving it ungated keeps idle-timeout auto-resume working.
|
|
635
|
+
*/
|
|
636
|
+
const NON_GATED_TOOLS = new Set<string>(["response"]);
|
|
637
|
+
|
|
638
|
+
function createToolExecutionGate(): {
|
|
639
|
+
shouldEnforceIdleTimeout: () => boolean;
|
|
640
|
+
observe: (chunk: {
|
|
641
|
+
type: string;
|
|
642
|
+
toolCallId?: string;
|
|
643
|
+
toolName?: string;
|
|
644
|
+
}) => void;
|
|
645
|
+
} {
|
|
646
|
+
let inFlight = 0;
|
|
647
|
+
const open = new Set<string>();
|
|
648
|
+
|
|
649
|
+
return {
|
|
650
|
+
shouldEnforceIdleTimeout: () => inFlight === 0,
|
|
651
|
+
observe: (chunk) => {
|
|
652
|
+
if (chunk.type === "tool-call") {
|
|
653
|
+
if (chunk.toolName && NON_GATED_TOOLS.has(chunk.toolName)) return;
|
|
654
|
+
const id = chunk.toolCallId;
|
|
655
|
+
if (id) {
|
|
656
|
+
if (!open.has(id)) {
|
|
657
|
+
open.add(id);
|
|
658
|
+
inFlight++;
|
|
659
|
+
}
|
|
660
|
+
} else {
|
|
661
|
+
inFlight++;
|
|
662
|
+
}
|
|
663
|
+
} else if (chunk.type === "tool-result" || chunk.type === "tool-error") {
|
|
664
|
+
// A failed tool is just as terminal for the gate as a successful one —
|
|
665
|
+
// without this, a tool-error leaves its slot open forever, suppressing
|
|
666
|
+
// the idle timeout for the rest of the run.
|
|
667
|
+
const id = chunk.toolCallId;
|
|
668
|
+
if (id) {
|
|
669
|
+
if (open.delete(id)) {
|
|
670
|
+
inFlight = Math.max(0, inFlight - 1);
|
|
671
|
+
}
|
|
672
|
+
} else if (!(chunk.toolName && NON_GATED_TOOLS.has(chunk.toolName))) {
|
|
673
|
+
inFlight = Math.max(0, inFlight - 1);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
},
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// Helper function to wrap a stream with error handling for async errors
|
|
681
|
+
function wrapStreamWithErrorHandler(
|
|
682
|
+
originalStream: StreamTextResult<ToolSet, never>,
|
|
683
|
+
messagesContainer: { current: ModelMessage[] },
|
|
684
|
+
opts: StreamResponseOpts,
|
|
685
|
+
model: LanguageModel,
|
|
686
|
+
silent?: boolean,
|
|
687
|
+
rateLimitRetryCount: number = 0,
|
|
688
|
+
idleResumeCount: number = 0,
|
|
689
|
+
generationSpans?: GenerationSpanTracker,
|
|
690
|
+
): StreamTextResult<ToolSet, never> {
|
|
691
|
+
// Create a lazy getter for fullStream that wraps it with error handling
|
|
692
|
+
let wrappedStream: AsyncIterable<TextStreamPart<ToolSet>> | null = null;
|
|
693
|
+
|
|
694
|
+
const handler = {
|
|
695
|
+
get(_target: StreamTextResult<ToolSet, never>, prop: string | symbol) {
|
|
696
|
+
// Intercept access to fullStream
|
|
697
|
+
if (prop === "fullStream") {
|
|
698
|
+
if (!wrappedStream) {
|
|
699
|
+
// Tool-execution gate: keeps the idle timer paused while a tool
|
|
700
|
+
// is in flight (see {@link createToolExecutionGate}). The gate's
|
|
701
|
+
// predicate is read by `withIdleTimeout` at the top of each
|
|
702
|
+
// iteration — which always runs AFTER the previous chunk's body
|
|
703
|
+
// finished mutating the gate, so observations are always visible
|
|
704
|
+
// before the next idle-race begins.
|
|
705
|
+
const toolGate = createToolExecutionGate();
|
|
706
|
+
|
|
707
|
+
wrappedStream = (async function* () {
|
|
708
|
+
let streamError: unknown;
|
|
709
|
+
try {
|
|
710
|
+
for await (const chunk of withIdleTimeout(
|
|
711
|
+
originalStream.fullStream,
|
|
712
|
+
getStreamIdleTimeoutMs(opts.model),
|
|
713
|
+
toolGate.shouldEnforceIdleTimeout,
|
|
714
|
+
)) {
|
|
715
|
+
toolGate.observe(chunk);
|
|
716
|
+
|
|
717
|
+
// [response-debug] Log AI-SDK-level response-tool chunks / finish-step, below the consume() loop.
|
|
718
|
+
if (RESPONSE_DEBUG) {
|
|
719
|
+
const c = chunk as {
|
|
720
|
+
type: string;
|
|
721
|
+
toolName?: string;
|
|
722
|
+
toolCallId?: string;
|
|
723
|
+
finishReason?: string;
|
|
724
|
+
invalid?: boolean;
|
|
725
|
+
};
|
|
726
|
+
if (
|
|
727
|
+
(c.type === "tool-call" ||
|
|
728
|
+
c.type === "tool-error" ||
|
|
729
|
+
c.type === "tool-result") &&
|
|
730
|
+
c.toolName === RESPONSE_TOOL_NAME
|
|
731
|
+
) {
|
|
732
|
+
log.warn(
|
|
733
|
+
`[response-debug] ai-layer chunk=${c.type} response id=${c.toolCallId} invalid=${c.invalid === true}`,
|
|
734
|
+
);
|
|
735
|
+
} else if (c.type === "finish-step") {
|
|
736
|
+
log.warn(
|
|
737
|
+
`[response-debug] ai-layer finish-step finishReason=${c.finishReason}`,
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// Only stream-level errors are fatal; tool-level errors
|
|
743
|
+
// flow through so the UI renders them as failed tool results.
|
|
744
|
+
// Instead of throwing mid-stream, capture the error and drain
|
|
745
|
+
// the tail (finish-step/finish): the AI SDK's terminal
|
|
746
|
+
// lifecycle — root-span end included — only runs when the
|
|
747
|
+
// stream completes, and aborting the iteration leaks it.
|
|
748
|
+
if (chunk.type === "error") {
|
|
749
|
+
streamError = (chunk as unknown as { error: unknown }).error;
|
|
750
|
+
// Mark the root generation span failed NOW: the SDK's
|
|
751
|
+
// flush ends it mid-drain, before the loop exits — a
|
|
752
|
+
// later mark is a no-op on an ended span.
|
|
753
|
+
generationSpans?.markFailed(streamError);
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
// Drain the post-error tail silently: the terminal parts
|
|
757
|
+
// must be consumed for the SDK's finalization, but consumers
|
|
758
|
+
// must not observe step-close-out after a fatal error.
|
|
759
|
+
if (streamError !== undefined) {
|
|
760
|
+
continue;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
yield chunk;
|
|
764
|
+
}
|
|
765
|
+
if (streamError !== undefined) {
|
|
766
|
+
// The tail is consumed but the SDK's finalization
|
|
767
|
+
// (root-span end) settles with the response promise —
|
|
768
|
+
// await it so the error never overtakes the span lifecycle.
|
|
769
|
+
await Promise.resolve(originalStream.response).catch(() => {});
|
|
770
|
+
throw streamError;
|
|
771
|
+
}
|
|
772
|
+
} catch (caughtError) {
|
|
773
|
+
// A tail-drain failure must not replace the provider error that
|
|
774
|
+
// put the wrapper into drain mode.
|
|
775
|
+
const error =
|
|
776
|
+
streamError !== undefined ? streamError : caughtError;
|
|
777
|
+
// Error-part runs complete normally inside the SDK, so nothing
|
|
778
|
+
// sets the root generation span failed — mark it here (the
|
|
779
|
+
// SDK's own thrown-error marking is guarded against below).
|
|
780
|
+
generationSpans?.markFailed(error);
|
|
781
|
+
|
|
782
|
+
const errorMessage =
|
|
783
|
+
error instanceof Error ? error.message : String(error);
|
|
784
|
+
|
|
785
|
+
// SDK RetryError can wrap a critical failure after a prior provider retry.
|
|
786
|
+
await getInferenceRecorder(opts)?.flush();
|
|
787
|
+
|
|
788
|
+
// Check context length FIRST — these should never be retried
|
|
789
|
+
// as-is; the prompt must be reduced via summarization.
|
|
790
|
+
const isCtxError = checkIfContextLengthError(error);
|
|
791
|
+
|
|
792
|
+
// A latched persistence failure is terminal: retrying would
|
|
793
|
+
// dispatch a turn whose context was never durably committed.
|
|
794
|
+
if (
|
|
795
|
+
error instanceof RunPersistenceError ||
|
|
796
|
+
error instanceof RunLimitError ||
|
|
797
|
+
error instanceof RunControlInterruption
|
|
798
|
+
) {
|
|
799
|
+
throw error;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// Handle stream idle timeout — resume from accumulated messages
|
|
803
|
+
if (
|
|
804
|
+
!isCtxError &&
|
|
805
|
+
isStreamIdleTimeoutError(error) &&
|
|
806
|
+
idleResumeCount < MAX_IDLE_RESUME_RETRIES &&
|
|
807
|
+
messagesContainer.current.length > 0
|
|
808
|
+
) {
|
|
809
|
+
const nextIdleCount = idleResumeCount + 1;
|
|
810
|
+
await getInferenceRecorder(opts)?.retry({
|
|
811
|
+
authority: "stream-idle",
|
|
812
|
+
count: nextIdleCount,
|
|
813
|
+
maxRetries: MAX_IDLE_RESUME_RETRIES,
|
|
814
|
+
delayMs: 0,
|
|
815
|
+
});
|
|
816
|
+
// Surfaced on silent sub-agents too when stream-debugging.
|
|
817
|
+
if (!silent || STREAM_DEBUG) {
|
|
818
|
+
log.warn(
|
|
819
|
+
`Stream stalled (attempt ${nextIdleCount}/${MAX_IDLE_RESUME_RETRIES}), resuming with ${messagesContainer.current.length} messages: ${errorMessage}`,
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const retriedStream = streamResponse({
|
|
824
|
+
...opts,
|
|
825
|
+
messages: messagesContainer.current,
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
const wrappedRetriedStream = wrapStreamWithErrorHandler(
|
|
829
|
+
retriedStream,
|
|
830
|
+
messagesContainer,
|
|
831
|
+
opts,
|
|
832
|
+
model,
|
|
833
|
+
silent,
|
|
834
|
+
rateLimitRetryCount,
|
|
835
|
+
nextIdleCount,
|
|
836
|
+
);
|
|
837
|
+
|
|
838
|
+
for await (const chunk of wrappedRetriedStream.fullStream) {
|
|
839
|
+
yield chunk;
|
|
840
|
+
}
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// Handle rate limit errors with exponential backoff retry
|
|
845
|
+
if (
|
|
846
|
+
!isCtxError &&
|
|
847
|
+
checkIfRateLimitError(error) &&
|
|
848
|
+
rateLimitRetryCount < MAX_RATE_LIMIT_RETRIES
|
|
849
|
+
) {
|
|
850
|
+
const nextRetryCount = rateLimitRetryCount + 1;
|
|
851
|
+
const delayMs = Math.min(1000 * nextRetryCount, 30000);
|
|
852
|
+
const recorder = getInferenceRecorder(opts);
|
|
853
|
+
await recorder?.retry({
|
|
854
|
+
authority: "stream-rate-limit",
|
|
855
|
+
count: nextRetryCount,
|
|
856
|
+
maxRetries: MAX_RATE_LIMIT_RETRIES,
|
|
857
|
+
delayMs,
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
if (!silent) {
|
|
861
|
+
log.warn(
|
|
862
|
+
`Rate limit error (attempt ${nextRetryCount}/${MAX_RATE_LIMIT_RETRIES}), waiting ${delayMs}ms: ${errorMessage}`,
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
if (recorder) {
|
|
867
|
+
await delay(delayMs, undefined, { signal: opts.abortSignal });
|
|
868
|
+
} else {
|
|
869
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
const retriedStream = streamResponse({
|
|
873
|
+
...opts,
|
|
874
|
+
messages:
|
|
875
|
+
messagesContainer.current.length > 0
|
|
876
|
+
? messagesContainer.current
|
|
877
|
+
: undefined,
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
const wrappedRetriedStream = wrapStreamWithErrorHandler(
|
|
881
|
+
retriedStream,
|
|
882
|
+
messagesContainer,
|
|
883
|
+
opts,
|
|
884
|
+
model,
|
|
885
|
+
silent,
|
|
886
|
+
nextRetryCount,
|
|
887
|
+
idleResumeCount,
|
|
888
|
+
);
|
|
889
|
+
|
|
890
|
+
for await (const chunk of wrappedRetriedStream.fullStream) {
|
|
891
|
+
yield chunk;
|
|
892
|
+
}
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
if (isCtxError) {
|
|
897
|
+
let currentMessages: ModelMessage[] = messagesContainer.current;
|
|
898
|
+
try {
|
|
899
|
+
const response = await originalStream.response;
|
|
900
|
+
if (response.messages && response.messages.length > 0) {
|
|
901
|
+
currentMessages = response.messages as ModelMessage[];
|
|
902
|
+
}
|
|
903
|
+
} catch {
|
|
904
|
+
// Fall back to container messages.
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
const fitted = fitMessagesToContext(currentMessages, {
|
|
908
|
+
contextWindow: getContextWindow(
|
|
909
|
+
opts.model,
|
|
910
|
+
opts.authConfig?.customProviders,
|
|
911
|
+
opts.authConfig?.hoonifyModels,
|
|
912
|
+
),
|
|
913
|
+
maxOutputTokens: getMaxOutputTokens(
|
|
914
|
+
opts.model,
|
|
915
|
+
opts.authConfig?.customProviders,
|
|
916
|
+
opts.authConfig?.hoonifyModels,
|
|
917
|
+
),
|
|
918
|
+
system: applySequentialToolCallPolicy(
|
|
919
|
+
opts.system,
|
|
920
|
+
opts.tools,
|
|
921
|
+
opts.model,
|
|
922
|
+
),
|
|
923
|
+
tools: opts.tools,
|
|
924
|
+
sessionPath: opts.sessionPath,
|
|
925
|
+
telemetry: {
|
|
926
|
+
trigger: "context_overflow",
|
|
927
|
+
model: opts.model,
|
|
928
|
+
sessionId: opts.sessionId,
|
|
929
|
+
restartDepth: opts._restartDepth,
|
|
930
|
+
previous: opts._compaction?.last,
|
|
931
|
+
},
|
|
932
|
+
});
|
|
933
|
+
|
|
934
|
+
if (fitted.compaction && opts._compaction)
|
|
935
|
+
opts._compaction.last = fitted.compaction;
|
|
936
|
+
|
|
937
|
+
messagesContainer.current = fitted.messages;
|
|
938
|
+
|
|
939
|
+
// Track depth across the reactive paths so that a failed
|
|
940
|
+
// Layer 1+2 retry CONTRIBUTES to the Layer 3 budget too.
|
|
941
|
+
// Without this, a failed retry's increment is "lost" on
|
|
942
|
+
// fall-through (Layer 3 reads outer `opts._restartDepth`,
|
|
943
|
+
// not the post-retry value) and recovery can burn close
|
|
944
|
+
// to double the intended provider calls before
|
|
945
|
+
// `MAX_RESTART_DEPTH` finally trips.
|
|
946
|
+
let postReactiveDepth = opts._restartDepth ?? 0;
|
|
947
|
+
|
|
948
|
+
if (fitted.fitsBudget && fitted.modified) {
|
|
949
|
+
if (!silent) {
|
|
950
|
+
log.warn(
|
|
951
|
+
`Context length error — Layer 1+2 reduced to ~${fitted.estimatedInputTokens} tokens, retrying`,
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
try {
|
|
955
|
+
// Bump `_restartDepth` so a tokenizer-drift loop where
|
|
956
|
+
// every reactive retry trips the same provider rejection
|
|
957
|
+
// (fitsBudget=true by our estimator, still rejected by
|
|
958
|
+
// the provider) eventually exhausts the depth bound at
|
|
959
|
+
// the top of `streamResponse` instead of looping
|
|
960
|
+
// forever. Without this, only Layer-3 escalation
|
|
961
|
+
// increments depth and a drift-driven loop can burn
|
|
962
|
+
// arbitrarily many failed provider calls.
|
|
963
|
+
await recordContextRestart(postReactiveDepth + 1, opts);
|
|
964
|
+
const retried = streamResponse({
|
|
965
|
+
...opts,
|
|
966
|
+
messages: fitted.messages,
|
|
967
|
+
_restartDepth: postReactiveDepth + 1,
|
|
968
|
+
});
|
|
969
|
+
const wrappedRetry = wrapStreamWithErrorHandler(
|
|
970
|
+
retried,
|
|
971
|
+
messagesContainer,
|
|
972
|
+
opts,
|
|
973
|
+
model,
|
|
974
|
+
silent,
|
|
975
|
+
rateLimitRetryCount,
|
|
976
|
+
idleResumeCount,
|
|
977
|
+
);
|
|
978
|
+
for await (const chunk of wrappedRetry.fullStream) {
|
|
979
|
+
yield chunk;
|
|
980
|
+
}
|
|
981
|
+
return;
|
|
982
|
+
} catch (retryError) {
|
|
983
|
+
// Always propagate the typed terminal error and
|
|
984
|
+
// cancellations — these MUST escape the cascade
|
|
985
|
+
// immediately. Currently `ContextLengthExhaustedError`
|
|
986
|
+
// propagates only by accident (its message
|
|
987
|
+
// "Context-length recovery exhausted…" uses a hyphen
|
|
988
|
+
// that doesn't match any `checkIfContextLengthError`
|
|
989
|
+
// pattern); the explicit `instanceof` and abort
|
|
990
|
+
// checks are defensive against a future message-text
|
|
991
|
+
// tweak that would otherwise silently swallow
|
|
992
|
+
// recovery exhaustion. Mirrors the Layer 3
|
|
993
|
+
// `summarizeError` catch below for symmetry.
|
|
994
|
+
if (
|
|
995
|
+
retryError instanceof ContextLengthExhaustedError ||
|
|
996
|
+
(retryError instanceof Error &&
|
|
997
|
+
retryError.name === "AbortError") ||
|
|
998
|
+
opts.abortSignal?.aborted ||
|
|
999
|
+
!checkIfContextLengthError(retryError)
|
|
1000
|
+
) {
|
|
1001
|
+
throw retryError;
|
|
1002
|
+
}
|
|
1003
|
+
// Account for the depth slot the failed retry just
|
|
1004
|
+
// consumed so the Layer 3 paths below don't grant a
|
|
1005
|
+
// fresh budget on top of the already-spent cycle.
|
|
1006
|
+
postReactiveDepth += 1;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
// Layer 3: full summarization. Wrapped because
|
|
1011
|
+
// `summarizeConversation` itself calls `generateText` and
|
|
1012
|
+
// can throw — fall back to a minimal-context restart.
|
|
1013
|
+
const messagesForSummary = messagesContainer.current;
|
|
1014
|
+
if (!silent) {
|
|
1015
|
+
log.warn(
|
|
1016
|
+
`Context length error — summarizing ${messagesForSummary.length} messages`,
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
try {
|
|
1021
|
+
const summarizationStream = createSummarizationStream(
|
|
1022
|
+
messagesForSummary,
|
|
1023
|
+
{
|
|
1024
|
+
...opts,
|
|
1025
|
+
_restartDepth: postReactiveDepth,
|
|
1026
|
+
_compactionTrigger: "context_overflow",
|
|
1027
|
+
},
|
|
1028
|
+
model,
|
|
1029
|
+
);
|
|
1030
|
+
for await (const chunk of summarizationStream.fullStream) {
|
|
1031
|
+
yield chunk;
|
|
1032
|
+
}
|
|
1033
|
+
} catch (summarizeError) {
|
|
1034
|
+
// Only fall through to minimal-restart for context-length
|
|
1035
|
+
// errors. For everything else — auth failures, network
|
|
1036
|
+
// errors, abort signals, the typed terminal
|
|
1037
|
+
// `ContextLengthExhaustedError`, or non-`Error` throws —
|
|
1038
|
+
// propagate immediately. Without this, an aborted call
|
|
1039
|
+
// would spawn a new provider request, and a transient
|
|
1040
|
+
// auth failure would burn an extra cycle that fails
|
|
1041
|
+
// identically.
|
|
1042
|
+
if (
|
|
1043
|
+
summarizeError instanceof ContextLengthExhaustedError ||
|
|
1044
|
+
(summarizeError instanceof Error &&
|
|
1045
|
+
summarizeError.name === "AbortError") ||
|
|
1046
|
+
opts.abortSignal?.aborted ||
|
|
1047
|
+
!checkIfContextLengthError(summarizeError)
|
|
1048
|
+
) {
|
|
1049
|
+
throw summarizeError;
|
|
1050
|
+
}
|
|
1051
|
+
if (!silent) {
|
|
1052
|
+
const sumMsg =
|
|
1053
|
+
summarizeError instanceof Error
|
|
1054
|
+
? summarizeError.message
|
|
1055
|
+
: String(summarizeError);
|
|
1056
|
+
log.warn(
|
|
1057
|
+
`Layer 3 summarization failed (${sumMsg}). Falling back to minimal-context restart.`,
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
1060
|
+
opts.onSummarized?.("");
|
|
1061
|
+
const minimalPrompt =
|
|
1062
|
+
typeof opts.prompt === "string" && opts.prompt.length > 0
|
|
1063
|
+
? opts.prompt.slice(0, 4_000)
|
|
1064
|
+
: MINIMAL_RESTART_PROMPT;
|
|
1065
|
+
const reset = beginCompaction("reset", {
|
|
1066
|
+
trigger: "summary_overflow",
|
|
1067
|
+
model: opts.model,
|
|
1068
|
+
sessionId: opts.sessionId,
|
|
1069
|
+
restartDepth: postReactiveDepth,
|
|
1070
|
+
previous: opts._compaction?.last,
|
|
1071
|
+
});
|
|
1072
|
+
reset?.capture("before", () => ({
|
|
1073
|
+
messages: messagesForSummary,
|
|
1074
|
+
system: opts.system,
|
|
1075
|
+
prompt: opts.prompt,
|
|
1076
|
+
}));
|
|
1077
|
+
reset?.measure(
|
|
1078
|
+
"before",
|
|
1079
|
+
() => estimateMessageTokens(messagesForSummary),
|
|
1080
|
+
messagesForSummary.length,
|
|
1081
|
+
);
|
|
1082
|
+
reset?.measure(
|
|
1083
|
+
"after",
|
|
1084
|
+
() =>
|
|
1085
|
+
estimateMessageTokens([
|
|
1086
|
+
{ role: "user", content: minimalPrompt },
|
|
1087
|
+
]),
|
|
1088
|
+
1,
|
|
1089
|
+
);
|
|
1090
|
+
reset?.capture("after", () => ({
|
|
1091
|
+
messages: [{ role: "user", content: minimalPrompt }],
|
|
1092
|
+
system: opts.system,
|
|
1093
|
+
}));
|
|
1094
|
+
reset?.finish("completed");
|
|
1095
|
+
if (reset && opts._compaction)
|
|
1096
|
+
opts._compaction.last = reset.link;
|
|
1097
|
+
await recordContextRestart(postReactiveDepth + 1, opts);
|
|
1098
|
+
const fallback = streamResponse({
|
|
1099
|
+
...opts,
|
|
1100
|
+
prompt: minimalPrompt,
|
|
1101
|
+
messages: undefined,
|
|
1102
|
+
_restartDepth: postReactiveDepth + 1,
|
|
1103
|
+
});
|
|
1104
|
+
for await (const chunk of fallback.fullStream) {
|
|
1105
|
+
yield chunk;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
} else {
|
|
1109
|
+
if (!silent) {
|
|
1110
|
+
log.error("Non-recoverable stream error, re-throwing", {
|
|
1111
|
+
error: errorMessage,
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
1114
|
+
throw error;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
})();
|
|
1118
|
+
}
|
|
1119
|
+
return wrappedStream;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
// For all other properties, return the original
|
|
1123
|
+
return (originalStream as unknown as Record<string | symbol, unknown>)[
|
|
1124
|
+
prop
|
|
1125
|
+
];
|
|
1126
|
+
},
|
|
1127
|
+
};
|
|
1128
|
+
|
|
1129
|
+
return new Proxy(originalStream, handler);
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
// Available models with names
|
|
1133
|
+
export interface ModelInfo {
|
|
1134
|
+
id: AIModel;
|
|
1135
|
+
name: string;
|
|
1136
|
+
provider: AIModelProvider;
|
|
1137
|
+
contextLength?: number;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
export function modelRequiresThinking(modelId: string): boolean {
|
|
1141
|
+
return getClaudeCapabilities(modelId)?.alwaysOnThinking ?? false;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
/**
|
|
1145
|
+
* Check whether a model supports extended thinking based on its ID.
|
|
1146
|
+
*
|
|
1147
|
+
* Thinking is available on Claude 3.7 Sonnet and all Claude 4.x+ models
|
|
1148
|
+
* (Sonnet, Opus, Haiku 4.5). Works for Anthropic direct, Bedrock, and
|
|
1149
|
+
* Pensar provider IDs.
|
|
1150
|
+
*/
|
|
1151
|
+
export function modelSupportsThinking(modelId: string): boolean {
|
|
1152
|
+
if (getClaudeCapabilities(modelId)) return true;
|
|
1153
|
+
// Normalize: strip provider prefixes so we match the base Claude model ID
|
|
1154
|
+
const normalized = modelId
|
|
1155
|
+
.replace(/^pensar:/, "")
|
|
1156
|
+
.replace(/^(us\.|eu\.|global\.|ap\.)?anthropic\./, "");
|
|
1157
|
+
|
|
1158
|
+
return (
|
|
1159
|
+
/^claude-3-7-sonnet/.test(normalized) ||
|
|
1160
|
+
/^claude-sonnet-4/.test(normalized) ||
|
|
1161
|
+
/^claude-opus-4/.test(normalized) ||
|
|
1162
|
+
/^claude-haiku-4-5/.test(normalized)
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
/**
|
|
1167
|
+
* Whether a model accepts the `adaptive` thinking type — Claude Opus 4.6+ and
|
|
1168
|
+
* Sonnet 4.6+. Pre-4.6 models (Opus 4.0–4.5, Sonnet 4.5, Haiku 4.5) support
|
|
1169
|
+
* extended thinking but reject `adaptive`, so we don't request thinking for
|
|
1170
|
+
* them at all.
|
|
1171
|
+
*/
|
|
1172
|
+
export function modelSupportsAdaptiveThinking(modelId: string): boolean {
|
|
1173
|
+
if (getClaudeCapabilities(modelId)) return true;
|
|
1174
|
+
const normalized = modelId
|
|
1175
|
+
.replace(/^pensar:/, "")
|
|
1176
|
+
.replace(/^(us\.|eu\.|global\.|ap\.)?anthropic\./, "");
|
|
1177
|
+
|
|
1178
|
+
return (
|
|
1179
|
+
/^claude-sonnet-4-[6-9]/.test(normalized) ||
|
|
1180
|
+
/^claude-opus-4-[6-9]/.test(normalized)
|
|
1181
|
+
);
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
export function modelSupportsOpenAIReasoning(modelId: string): boolean {
|
|
1185
|
+
if (modelId === CONCENTRATE_GLM_5_3_MODEL_ID) return true;
|
|
1186
|
+
const { provider } = getModelInfo(modelId);
|
|
1187
|
+
if (!["openai", "openrouter", "concentrate"].includes(provider)) return false;
|
|
1188
|
+
modelId = modelId.replace(/^(openai\/|concentrate:)/, "");
|
|
1189
|
+
return (
|
|
1190
|
+
OPENAI_REASONING_MODEL_IDS.has(modelId) || /^o[134](?:\b|-)/.test(modelId)
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
export function modelRequiresReasoning(modelId: string): boolean {
|
|
1195
|
+
return modelId === CONCENTRATE_GLM_5_3_MODEL_ID;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
export function getOpenAIReasoningEfforts(
|
|
1199
|
+
modelId: string,
|
|
1200
|
+
): OpenAIReasoningEffort[] {
|
|
1201
|
+
if (!modelSupportsOpenAIReasoning(modelId)) return [];
|
|
1202
|
+
if (modelId === CONCENTRATE_GLM_5_3_MODEL_ID) {
|
|
1203
|
+
return ["low", "high", "max"];
|
|
1204
|
+
}
|
|
1205
|
+
if (/^concentrate:gpt-5\.4-(?:mini|nano)$/.test(modelId)) {
|
|
1206
|
+
return ["none", "low", "medium", "high"];
|
|
1207
|
+
}
|
|
1208
|
+
modelId = modelId.replace(/^(openai\/|concentrate:)/, "");
|
|
1209
|
+
if (modelId === "gpt-6-sol" || modelId === "gpt-6-luna") {
|
|
1210
|
+
return ["none", "low", "medium", "high", "xhigh", "max"];
|
|
1211
|
+
}
|
|
1212
|
+
if (/^gpt-6[.-]/.test(modelId)) {
|
|
1213
|
+
return ["low", "medium", "high", "xhigh", "max"];
|
|
1214
|
+
}
|
|
1215
|
+
if (/^gpt-5\.5-pro(?:-|$)/.test(modelId)) {
|
|
1216
|
+
return ["medium", "high", "xhigh"];
|
|
1217
|
+
}
|
|
1218
|
+
if (/^gpt-5\.4-(?:mini|nano)(?:-|$)/.test(modelId)) {
|
|
1219
|
+
return ["none", "low", "medium", "high", "xhigh"];
|
|
1220
|
+
}
|
|
1221
|
+
if (/^gpt-5\.6(?:\b|-)/.test(modelId)) {
|
|
1222
|
+
return ["low", "medium", "high", "xhigh", "max", "ultra"];
|
|
1223
|
+
}
|
|
1224
|
+
if (/^gpt-5\.5(?:\b|-)/.test(modelId)) {
|
|
1225
|
+
return ["none", "low", "medium", "high", "xhigh"];
|
|
1226
|
+
}
|
|
1227
|
+
return ["low", "medium", "high"];
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
export function normalizeOpenAIReasoningEffort(
|
|
1231
|
+
modelId: string,
|
|
1232
|
+
effort?: OpenAIReasoningEffort | null,
|
|
1233
|
+
): OpenAIReasoningEffort | undefined {
|
|
1234
|
+
if (modelId === CONCENTRATE_GLM_5_3_MODEL_ID) {
|
|
1235
|
+
switch (effort) {
|
|
1236
|
+
case "none":
|
|
1237
|
+
case "low":
|
|
1238
|
+
return "low";
|
|
1239
|
+
case "medium":
|
|
1240
|
+
case "high":
|
|
1241
|
+
return "high";
|
|
1242
|
+
case "xhigh":
|
|
1243
|
+
case "max":
|
|
1244
|
+
case "ultra":
|
|
1245
|
+
return "max";
|
|
1246
|
+
default:
|
|
1247
|
+
return "high";
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
const efforts = getOpenAIReasoningEfforts(modelId);
|
|
1251
|
+
if (efforts.length === 0) return undefined;
|
|
1252
|
+
if (effort && efforts.includes(effort)) {
|
|
1253
|
+
// ponytail: OpenAI has no distinct ultra level; keep the UI choice as a max alias.
|
|
1254
|
+
return effort === "ultra" ? "max" : effort;
|
|
1255
|
+
}
|
|
1256
|
+
return DEFAULT_OPENAI_REASONING_EFFORT;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
/**
|
|
1260
|
+
* Provider-specific options passed to `streamText` to request reasoning /
|
|
1261
|
+
* extended thinking. Each provider reads only its own namespace:
|
|
1262
|
+
* - `anthropic.thinking` — direct Anthropic provider AND the Pensar gateway
|
|
1263
|
+
* (the gateway formatter maps it to the Bedrock `thinking` field).
|
|
1264
|
+
* - `bedrock.reasoningConfig` — the AWS Bedrock provider; it ignores the
|
|
1265
|
+
* `anthropic` namespace entirely, so Anthropic-on-Bedrock thinking is only
|
|
1266
|
+
* requested when this key is present. `display: 'summarized'` makes the
|
|
1267
|
+
* model actually return reasoning text (adaptive can otherwise omit it).
|
|
1268
|
+
* - `openai.reasoningEffort` — OpenAI/o-series reasoning models.
|
|
1269
|
+
*/
|
|
1270
|
+
export type ReasoningProviderOptions = {
|
|
1271
|
+
openrouter?: {
|
|
1272
|
+
reasoning: { effort: OpenAIReasoningEffort; enabled?: boolean };
|
|
1273
|
+
};
|
|
1274
|
+
anthropic?: {
|
|
1275
|
+
thinking:
|
|
1276
|
+
| { type: "adaptive"; display?: "summarized" }
|
|
1277
|
+
| { type: "disabled" };
|
|
1278
|
+
// Soft effort hint for adaptive thinking; omitted when no level requested
|
|
1279
|
+
// (model defaults to "high"). Sibling of `thinking` per the AI SDK.
|
|
1280
|
+
effort?: ThinkingEffort;
|
|
1281
|
+
};
|
|
1282
|
+
bedrock?: {
|
|
1283
|
+
reasoningConfig:
|
|
1284
|
+
| {
|
|
1285
|
+
type: "adaptive";
|
|
1286
|
+
display: "summarized";
|
|
1287
|
+
// Bedrock's channel for the adaptive effort hint (maps to Claude's
|
|
1288
|
+
// output_config.effort).
|
|
1289
|
+
maxReasoningEffort?: ThinkingEffort;
|
|
1290
|
+
}
|
|
1291
|
+
| { type: "disabled" };
|
|
1292
|
+
/** Explicitly forwarded for Anthropic because the Bedrock SDK currently
|
|
1293
|
+
* drops reasoningConfig.type="disabled" instead of sending it. */
|
|
1294
|
+
additionalModelRequestFields?: {
|
|
1295
|
+
thinking: { type: "disabled" };
|
|
1296
|
+
};
|
|
1297
|
+
};
|
|
1298
|
+
openai?: OpenAIResponsesProviderOptions;
|
|
1299
|
+
};
|
|
1300
|
+
|
|
1301
|
+
export type OpenRouterProviderOptions = {
|
|
1302
|
+
openrouter?: {
|
|
1303
|
+
provider:
|
|
1304
|
+
| {
|
|
1305
|
+
only: ["z-ai"];
|
|
1306
|
+
allow_fallbacks: false;
|
|
1307
|
+
}
|
|
1308
|
+
| {
|
|
1309
|
+
order: ["z-ai"];
|
|
1310
|
+
allow_fallbacks: true;
|
|
1311
|
+
require_parameters: true;
|
|
1312
|
+
};
|
|
1313
|
+
};
|
|
1314
|
+
};
|
|
1315
|
+
|
|
1316
|
+
function isZaiPinnedModel(model: AIModel): boolean {
|
|
1317
|
+
return model === "z-ai/glm-5.2" || model === "z-ai/glm-5.3";
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
export function buildOpenRouterProviderOptions(
|
|
1321
|
+
model: AIModel,
|
|
1322
|
+
): OpenRouterProviderOptions | undefined {
|
|
1323
|
+
if (!isZaiPinnedModel(model)) return undefined;
|
|
1324
|
+
return {
|
|
1325
|
+
openrouter: {
|
|
1326
|
+
provider: {
|
|
1327
|
+
only: ["z-ai"],
|
|
1328
|
+
allow_fallbacks: false,
|
|
1329
|
+
},
|
|
1330
|
+
},
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
/**
|
|
1335
|
+
* Z.AI's endpoint is the only `z-ai/*` provider that does not advertise
|
|
1336
|
+
* `structured_outputs`, so under the hard pin above `response_format` is a soft
|
|
1337
|
+
* preference and nothing enforces the schema. Prefer Z.AI, but require an
|
|
1338
|
+
* endpoint that enforces it rather than silently returning unparseable output.
|
|
1339
|
+
*/
|
|
1340
|
+
export function buildOpenRouterStructuredProviderOptions(
|
|
1341
|
+
model: AIModel,
|
|
1342
|
+
): OpenRouterProviderOptions | undefined {
|
|
1343
|
+
if (!isZaiPinnedModel(model)) return undefined;
|
|
1344
|
+
return {
|
|
1345
|
+
openrouter: {
|
|
1346
|
+
provider: {
|
|
1347
|
+
order: ["z-ai"],
|
|
1348
|
+
allow_fallbacks: true,
|
|
1349
|
+
require_parameters: true,
|
|
1350
|
+
},
|
|
1351
|
+
},
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/**
|
|
1356
|
+
* Build the `providerOptions` for a request based on the model and reasoning
|
|
1357
|
+
* settings. Returns `undefined` when no reasoning/thinking is requested.
|
|
1358
|
+
*
|
|
1359
|
+
* When thinking is enabled for an Anthropic-family model we set BOTH the
|
|
1360
|
+
* `anthropic` and `bedrock` keys: the resolved provider (direct Anthropic,
|
|
1361
|
+
* Pensar gateway, or Bedrock) reads only its own namespace and ignores the
|
|
1362
|
+
* other, so this is safe across all three and avoids brittle provider
|
|
1363
|
+
* branching here.
|
|
1364
|
+
*/
|
|
1365
|
+
export function buildReasoningProviderOptions(
|
|
1366
|
+
model: AIModel,
|
|
1367
|
+
opts: {
|
|
1368
|
+
enableThinking?: boolean;
|
|
1369
|
+
/**
|
|
1370
|
+
* Adaptive-thinking effort hint for Anthropic models that support it
|
|
1371
|
+
* Ignored on models without adaptive support. When omitted, models in the
|
|
1372
|
+
* Claude capability registry use their documented provider default.
|
|
1373
|
+
*/
|
|
1374
|
+
thinkingEffort?: ThinkingEffort | null;
|
|
1375
|
+
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
1376
|
+
},
|
|
1377
|
+
): ReasoningProviderOptions | undefined {
|
|
1378
|
+
const claude = getClaudeCapabilities(model);
|
|
1379
|
+
if (claude) {
|
|
1380
|
+
const provider = getModelInfo(model).provider;
|
|
1381
|
+
const thinking = !!opts.enableThinking || claude.alwaysOnThinking;
|
|
1382
|
+
const effort = opts.thinkingEffort ?? claude.defaultEffort;
|
|
1383
|
+
if (provider === "openrouter") {
|
|
1384
|
+
return {
|
|
1385
|
+
openrouter: {
|
|
1386
|
+
reasoning: {
|
|
1387
|
+
effort: thinking ? effort : "none",
|
|
1388
|
+
enabled: thinking,
|
|
1389
|
+
},
|
|
1390
|
+
},
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
if (provider === "concentrate") {
|
|
1394
|
+
return {
|
|
1395
|
+
openai: {
|
|
1396
|
+
forceReasoning: true,
|
|
1397
|
+
reasoningEffort: thinking ? effort : "none",
|
|
1398
|
+
reasoningSummary: "auto",
|
|
1399
|
+
},
|
|
1400
|
+
};
|
|
1401
|
+
}
|
|
1402
|
+
return {
|
|
1403
|
+
anthropic: {
|
|
1404
|
+
thinking: thinking
|
|
1405
|
+
? { type: "adaptive", display: "summarized" }
|
|
1406
|
+
: { type: "disabled" },
|
|
1407
|
+
...(thinking ? { effort } : {}),
|
|
1408
|
+
},
|
|
1409
|
+
...(provider === "bedrock"
|
|
1410
|
+
? {
|
|
1411
|
+
bedrock: {
|
|
1412
|
+
reasoningConfig: thinking
|
|
1413
|
+
? {
|
|
1414
|
+
type: "adaptive" as const,
|
|
1415
|
+
display: "summarized" as const,
|
|
1416
|
+
maxReasoningEffort: effort,
|
|
1417
|
+
}
|
|
1418
|
+
: { type: "disabled" as const },
|
|
1419
|
+
...(!thinking
|
|
1420
|
+
? {
|
|
1421
|
+
additionalModelRequestFields: {
|
|
1422
|
+
thinking: { type: "disabled" as const },
|
|
1423
|
+
},
|
|
1424
|
+
}
|
|
1425
|
+
: {}),
|
|
1426
|
+
},
|
|
1427
|
+
}
|
|
1428
|
+
: {}),
|
|
1429
|
+
};
|
|
1430
|
+
}
|
|
1431
|
+
const useThinking =
|
|
1432
|
+
!!opts.enableThinking &&
|
|
1433
|
+
isAnthropicProvider(model) &&
|
|
1434
|
+
modelSupportsAdaptiveThinking(model);
|
|
1435
|
+
const normalizedOpenAIEffort = normalizeOpenAIReasoningEffort(
|
|
1436
|
+
model,
|
|
1437
|
+
opts.openAIReasoningEffort,
|
|
1438
|
+
);
|
|
1439
|
+
// The effort hint only rides along when adaptive thinking is actually used.
|
|
1440
|
+
const effort = useThinking ? (opts.thinkingEffort ?? undefined) : undefined;
|
|
1441
|
+
|
|
1442
|
+
if (!useThinking && !normalizedOpenAIEffort) return undefined;
|
|
1443
|
+
|
|
1444
|
+
if (getModelInfo(model).provider === "openrouter" && normalizedOpenAIEffort) {
|
|
1445
|
+
return { openrouter: { reasoning: { effort: normalizedOpenAIEffort } } };
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
return {
|
|
1449
|
+
...(useThinking
|
|
1450
|
+
? {
|
|
1451
|
+
anthropic: {
|
|
1452
|
+
thinking: { type: "adaptive" as const },
|
|
1453
|
+
...(effort ? { effort } : {}),
|
|
1454
|
+
},
|
|
1455
|
+
bedrock: {
|
|
1456
|
+
reasoningConfig: {
|
|
1457
|
+
type: "adaptive" as const,
|
|
1458
|
+
display: "summarized" as const,
|
|
1459
|
+
...(effort ? { maxReasoningEffort: effort } : {}),
|
|
1460
|
+
},
|
|
1461
|
+
},
|
|
1462
|
+
}
|
|
1463
|
+
: {}),
|
|
1464
|
+
...(normalizedOpenAIEffort
|
|
1465
|
+
? { openai: { reasoningEffort: normalizedOpenAIEffort } }
|
|
1466
|
+
: {}),
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
/** Cache token metrics extracted from Anthropic providerMetadata */
|
|
1471
|
+
export interface CacheMetrics {
|
|
1472
|
+
cacheReadInputTokens: number;
|
|
1473
|
+
cacheCreationInputTokens: number;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
export interface StreamResponseOpts {
|
|
1477
|
+
prompt: string;
|
|
1478
|
+
system?: string;
|
|
1479
|
+
model: AIModel;
|
|
1480
|
+
messages?: Array<ModelMessage>;
|
|
1481
|
+
stopWhen?:
|
|
1482
|
+
| StopCondition<NoInfer<ToolSet>>
|
|
1483
|
+
| StopCondition<NoInfer<ToolSet>>[];
|
|
1484
|
+
toolChoice?: ToolChoice<ToolSet>;
|
|
1485
|
+
tools?: ToolSet;
|
|
1486
|
+
onStepFinish?: StreamTextOnStepFinishCallback<ToolSet>;
|
|
1487
|
+
/** Provider middleware applied only to this stream's model calls. */
|
|
1488
|
+
languageModelMiddleware?: LanguageModelMiddleware | LanguageModelMiddleware[];
|
|
1489
|
+
/** Explicit undefined clears an inherited recorder for an unrecorded child. */
|
|
1490
|
+
inferenceRecorder?: InferenceRecorder;
|
|
1491
|
+
/** Per-run usage recorder; when set it replaces the global usage callback for this stream. */
|
|
1492
|
+
usageRecorder?: UsageRecorder;
|
|
1493
|
+
abortSignal?: AbortSignal;
|
|
1494
|
+
activeTools?: string[];
|
|
1495
|
+
silent?: boolean;
|
|
1496
|
+
authConfig?: AIAuthConfig;
|
|
1497
|
+
onFinish?: StreamTextOnFinishCallback<ToolSet>;
|
|
1498
|
+
/**
|
|
1499
|
+
* Called when the context window overflows and the conversation is
|
|
1500
|
+
* summarized. Callers should use this to discard stale message history
|
|
1501
|
+
* so that subsequent persistence writes only include the summary +
|
|
1502
|
+
* new messages (not the full pre-summarization history).
|
|
1503
|
+
*/
|
|
1504
|
+
onSummarized?: (summary: string) => void;
|
|
1505
|
+
/**
|
|
1506
|
+
* Deprecated host shim: fires only when a cache counter is `> 0`.
|
|
1507
|
+
* Apex internals read cache from {@link normalizeStepUsage} on the step.
|
|
1508
|
+
*/
|
|
1509
|
+
onCacheMetrics?: (metrics: CacheMetrics) => void;
|
|
1510
|
+
/** Enable extended thinking for supported models (Anthropic Claude 3.7+) */
|
|
1511
|
+
enableThinking?: boolean;
|
|
1512
|
+
/**
|
|
1513
|
+
* Adaptive-thinking effort hint for Anthropic models that support it
|
|
1514
|
+
* (Opus/Sonnet 4.6+). Ignored where unsupported; model defaults to `high`.
|
|
1515
|
+
*/
|
|
1516
|
+
thinkingEffort?: ThinkingEffort | null;
|
|
1517
|
+
/** OpenAI reasoning effort for GPT/o-series reasoning models. */
|
|
1518
|
+
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
1519
|
+
/** Session root path — used by context management layers to persist truncated tool results */
|
|
1520
|
+
sessionPath?: string;
|
|
1521
|
+
/** Session id (`ses_…`) of the agent making this call; stamped onto AI-span telemetry so traces are filterable by session. */
|
|
1522
|
+
sessionId?: string;
|
|
1523
|
+
/**
|
|
1524
|
+
* Opt-in durable context authority for recorded runs. Turn-0 base and each
|
|
1525
|
+
* step's cumulative context are checkpointed before selection/dispatch;
|
|
1526
|
+
* unset → legacy behavior, no persistence.
|
|
1527
|
+
*/
|
|
1528
|
+
contextRecorder?: RunContextRecorder;
|
|
1529
|
+
/**
|
|
1530
|
+
* Internal: recovery-recursion depth. Bumped at each summarize → resume
|
|
1531
|
+
* boundary; throws `ContextLengthExhaustedError` past `MAX_RESTART_DEPTH`.
|
|
1532
|
+
*/
|
|
1533
|
+
_restartDepth?: number;
|
|
1534
|
+
/** Shared only by continuations of this stream, never across agents. */
|
|
1535
|
+
_compaction?: { last?: CompactionLink };
|
|
1536
|
+
_compactionTrigger?: CompactionTrigger;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
const NATIVE_STREAM_RECOVERY = Symbol("native-stream-recovery");
|
|
1540
|
+
|
|
1541
|
+
interface NativeStreamRecovery {
|
|
1542
|
+
model: LanguageModel;
|
|
1543
|
+
run<T>(fn: () => T): T;
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
type InternalStreamResponseOpts = StreamResponseOpts & {
|
|
1547
|
+
[NATIVE_STREAM_RECOVERY]?: NativeStreamRecovery;
|
|
1548
|
+
};
|
|
1549
|
+
|
|
1550
|
+
export function streamResponse(
|
|
1551
|
+
opts: StreamResponseOpts,
|
|
1552
|
+
): StreamTextResult<ToolSet, never> {
|
|
1553
|
+
opts = { ...opts, inferenceRecorder: getInferenceRecorder(opts) };
|
|
1554
|
+
return runWithInferenceRecorder(opts.inferenceRecorder, () => {
|
|
1555
|
+
const recovery = (opts as InternalStreamResponseOpts)[
|
|
1556
|
+
NATIVE_STREAM_RECOVERY
|
|
1557
|
+
];
|
|
1558
|
+
if (recovery) {
|
|
1559
|
+
return recovery.run(() => streamResponseWithinOperation(opts, recovery));
|
|
1560
|
+
}
|
|
1561
|
+
return streamResponseWithinOperation(opts);
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
function streamResponseWithinOperation(
|
|
1566
|
+
opts: StreamResponseOpts,
|
|
1567
|
+
nativeRecovery?: NativeStreamRecovery,
|
|
1568
|
+
): StreamTextResult<ToolSet, never> {
|
|
1569
|
+
const compactionState = opts._compaction ?? {};
|
|
1570
|
+
// One effective tool selection per stream, before any fitting: proactive
|
|
1571
|
+
// fit, provider schemas, execution, repair, and every continuation path
|
|
1572
|
+
// below spread this same opts object, so they must all see the filtered
|
|
1573
|
+
// map. Re-entry is identity (`activeTools` already consumed).
|
|
1574
|
+
opts = {
|
|
1575
|
+
...opts,
|
|
1576
|
+
_compaction: compactionState,
|
|
1577
|
+
// `activeTools` is authoritative for advertisement and execution: a tool
|
|
1578
|
+
// (including `response`) is exposed only when the caller lists it, so the
|
|
1579
|
+
// structured-output tool is included when listed and inert when omitted.
|
|
1580
|
+
...resolveEffectiveTools(opts.tools, opts.activeTools),
|
|
1581
|
+
};
|
|
1582
|
+
// Bound recovery recursion (summarize → resume → overflow → …).
|
|
1583
|
+
const restartDepth = opts._restartDepth ?? 0;
|
|
1584
|
+
if (restartDepth > MAX_RESTART_DEPTH) {
|
|
1585
|
+
throw new ContextLengthExhaustedError(
|
|
1586
|
+
`Context-length recovery exhausted after ${restartDepth} restart cycles`,
|
|
1587
|
+
restartDepth,
|
|
1588
|
+
);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
const {
|
|
1592
|
+
prompt,
|
|
1593
|
+
system,
|
|
1594
|
+
model,
|
|
1595
|
+
messages,
|
|
1596
|
+
stopWhen,
|
|
1597
|
+
toolChoice,
|
|
1598
|
+
tools,
|
|
1599
|
+
onStepFinish: userOnStepFinish,
|
|
1600
|
+
languageModelMiddleware,
|
|
1601
|
+
usageRecorder,
|
|
1602
|
+
abortSignal,
|
|
1603
|
+
activeTools,
|
|
1604
|
+
silent,
|
|
1605
|
+
authConfig,
|
|
1606
|
+
onFinish,
|
|
1607
|
+
onCacheMetrics,
|
|
1608
|
+
enableThinking,
|
|
1609
|
+
thinkingEffort,
|
|
1610
|
+
openAIReasoningEffort,
|
|
1611
|
+
sessionId,
|
|
1612
|
+
contextRecorder,
|
|
1613
|
+
} = opts;
|
|
1614
|
+
|
|
1615
|
+
// Recorded-run base, captured once at the first prepareStep of this
|
|
1616
|
+
// streamText call; only used to reconstruct cumulative prefixes in
|
|
1617
|
+
// onStepFinish (response.messages excludes the input base).
|
|
1618
|
+
let recorderBase: ModelMessage[] | undefined;
|
|
1619
|
+
|
|
1620
|
+
// Wrap onStepFinish to fire cache metrics and the usage callback for every
|
|
1621
|
+
// step. Must be async so that callers returning a Promise (persistence,
|
|
1622
|
+
// issue queuing, or the usage callback itself) are fully awaited before
|
|
1623
|
+
// the AI SDK starts the next step. One normalization feeds both sinks —
|
|
1624
|
+
// provider metadata is never parsed twice.
|
|
1625
|
+
const onStepFinish: typeof userOnStepFinish = async (step) => {
|
|
1626
|
+
const stepUsage = normalizeStepUsage(step);
|
|
1627
|
+
// Canonical commit precedes every downstream use; the recorder latches
|
|
1628
|
+
// rejections (SDK notify() swallows them) until the next turn gate or
|
|
1629
|
+
// agent-side flush turns the latch into a stream failure.
|
|
1630
|
+
// Synthetic summarization/tool-repair events re-report context that
|
|
1631
|
+
// already includes the base (messagesContainer.current) — committing
|
|
1632
|
+
// them would duplicate the prefix.
|
|
1633
|
+
if (
|
|
1634
|
+
contextRecorder &&
|
|
1635
|
+
step.response.id !== "summarization" &&
|
|
1636
|
+
step.response.id !== "tool-repair"
|
|
1637
|
+
) {
|
|
1638
|
+
if (!recorderBase) {
|
|
1639
|
+
throw new Error("context recorder active without a committed base");
|
|
1640
|
+
}
|
|
1641
|
+
await contextRecorder.checkpoint({
|
|
1642
|
+
messages: [...recorderBase, ...step.response.messages],
|
|
1643
|
+
system: effectiveSystem ?? null,
|
|
1644
|
+
});
|
|
1645
|
+
}
|
|
1646
|
+
if (
|
|
1647
|
+
onCacheMetrics &&
|
|
1648
|
+
(stepUsage.cacheReadTokens > 0 || stepUsage.cacheWriteTokens > 0)
|
|
1649
|
+
) {
|
|
1650
|
+
await onCacheMetrics({
|
|
1651
|
+
cacheReadInputTokens: stepUsage.cacheReadTokens,
|
|
1652
|
+
cacheCreationInputTokens: stepUsage.cacheWriteTokens,
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
await userOnStepFinish?.(step);
|
|
1656
|
+
await emitUsage(model, stepUsage, resolveUsageSink(usageRecorder));
|
|
1657
|
+
};
|
|
1658
|
+
const providerModel =
|
|
1659
|
+
nativeRecovery?.model ??
|
|
1660
|
+
(() => {
|
|
1661
|
+
const baseProviderModel = withNativeRolloutEvidenceModel(
|
|
1662
|
+
withModelCallDiagnostics(getProviderModel(model, authConfig)),
|
|
1663
|
+
{
|
|
1664
|
+
requestedModelId: model,
|
|
1665
|
+
operationKind: "agent.stream",
|
|
1666
|
+
sessionId,
|
|
1667
|
+
},
|
|
1668
|
+
);
|
|
1669
|
+
return languageModelMiddleware
|
|
1670
|
+
? wrapLanguageModel({
|
|
1671
|
+
model: baseProviderModel,
|
|
1672
|
+
middleware: languageModelMiddleware,
|
|
1673
|
+
})
|
|
1674
|
+
: baseProviderModel;
|
|
1675
|
+
})();
|
|
1676
|
+
// Undefined when the model has no cache breakpoint we can express (non-Claude
|
|
1677
|
+
// Bedrock models, OpenAI/Google/OpenRouter) — those run uncached.
|
|
1678
|
+
const cacheBreakpoint = cacheBreakpointFor(model);
|
|
1679
|
+
|
|
1680
|
+
// Models that mis-parse multiple tool calls per turn (DeepSeek V3.1 on
|
|
1681
|
+
// Bedrock) are constrained to one tool call per turn via system prompt —
|
|
1682
|
+
// single calls parse correctly, parallel calls drop/empty arguments. Only
|
|
1683
|
+
// applied when tools are actually bound. See prefersSequentialToolCalls.
|
|
1684
|
+
// Computed before context fitting so token budgeting accounts for the
|
|
1685
|
+
// appended instruction that is actually sent to the provider.
|
|
1686
|
+
const systemWithToolPolicy = applySequentialToolCallPolicy(
|
|
1687
|
+
system,
|
|
1688
|
+
tools,
|
|
1689
|
+
model,
|
|
1690
|
+
);
|
|
1691
|
+
|
|
1692
|
+
// Proactive context fit: compact before the call. Reactive recovery
|
|
1693
|
+
// below is a safety net for tokenizer drift the estimate doesn't catch.
|
|
1694
|
+
let fittedMessages = messages;
|
|
1695
|
+
let proactiveFitFailed = false;
|
|
1696
|
+
if (messages && messages.length > 0) {
|
|
1697
|
+
const fitted = fitMessagesToContext(messages, {
|
|
1698
|
+
contextWindow: getContextWindow(
|
|
1699
|
+
model,
|
|
1700
|
+
authConfig?.customProviders,
|
|
1701
|
+
authConfig?.hoonifyModels,
|
|
1702
|
+
),
|
|
1703
|
+
maxOutputTokens: getMaxOutputTokens(
|
|
1704
|
+
model,
|
|
1705
|
+
authConfig?.customProviders,
|
|
1706
|
+
authConfig?.hoonifyModels,
|
|
1707
|
+
),
|
|
1708
|
+
system: systemWithToolPolicy,
|
|
1709
|
+
tools,
|
|
1710
|
+
sessionPath: opts.sessionPath,
|
|
1711
|
+
telemetry: {
|
|
1712
|
+
trigger: "proactive",
|
|
1713
|
+
model,
|
|
1714
|
+
sessionId,
|
|
1715
|
+
restartDepth,
|
|
1716
|
+
previous: opts._compaction?.last,
|
|
1717
|
+
},
|
|
1718
|
+
});
|
|
1719
|
+
if (fitted.compaction) compactionState.last = fitted.compaction;
|
|
1720
|
+
fittedMessages = fitted.messages;
|
|
1721
|
+
proactiveFitFailed = !fitted.fitsBudget;
|
|
1722
|
+
if (fitted.modified && !silent) {
|
|
1723
|
+
log.warn(
|
|
1724
|
+
`Proactive context fit: compacted messages to ~${fitted.estimatedInputTokens} tokens (fits=${fitted.fitsBudget})`,
|
|
1725
|
+
);
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
// Container reference is stable; value gets reassigned by `prepareStep`
|
|
1730
|
+
// and the recovery paths so nested retries read the latest compacted view.
|
|
1731
|
+
const messagesContainer = { current: fittedMessages || [] };
|
|
1732
|
+
|
|
1733
|
+
// Layer 1+2 alone can't fit — escalate before sending a doomed request.
|
|
1734
|
+
// Wrap with the same error handler the streamText path uses, otherwise
|
|
1735
|
+
// an overflow inside the summarization call itself escapes uncaught while
|
|
1736
|
+
// the equivalent post-streamText path (line ~880) recovers.
|
|
1737
|
+
if (proactiveFitFailed && fittedMessages) {
|
|
1738
|
+
if (!silent) {
|
|
1739
|
+
log.warn(
|
|
1740
|
+
`Proactive context fit returned fitsBudget=false on ${fittedMessages.length} messages — escalating to summarization before send`,
|
|
1741
|
+
);
|
|
1742
|
+
}
|
|
1743
|
+
// Pass `opts` through unchanged. The slot for this escalation is
|
|
1744
|
+
// consumed by `summarizeConversation`'s internal `_restartDepth + 1`
|
|
1745
|
+
// bump on the resumed `streamResponse` call — pre-bumping here would
|
|
1746
|
+
// double-count vs the reactive Layer 3 path (which also passes
|
|
1747
|
+
// `opts._restartDepth` to `createSummarizationStream` after a
|
|
1748
|
+
// no-retry fall-through). With the post-bump, all three escalation
|
|
1749
|
+
// entry points (proactive, outer-catch, reactive Layer 3) consume
|
|
1750
|
+
// exactly one depth slot per summarization attempt — symmetric.
|
|
1751
|
+
return wrapStreamWithErrorHandler(
|
|
1752
|
+
createSummarizationStream(
|
|
1753
|
+
fittedMessages,
|
|
1754
|
+
{ ...opts, _compactionTrigger: "proactive" },
|
|
1755
|
+
providerModel,
|
|
1756
|
+
),
|
|
1757
|
+
messagesContainer,
|
|
1758
|
+
opts,
|
|
1759
|
+
providerModel,
|
|
1760
|
+
silent,
|
|
1761
|
+
);
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
// For cacheable models, move the system prompt into messages behind a cache
|
|
1765
|
+
// breakpoint. This caches tools + system prompt across multi-turn
|
|
1766
|
+
// conversations (~90% cost reduction on cache hits).
|
|
1767
|
+
let effectiveSystem: string | undefined = systemWithToolPolicy;
|
|
1768
|
+
let effectiveMessages: ModelMessage[] | undefined = fittedMessages;
|
|
1769
|
+
|
|
1770
|
+
if (cacheBreakpoint && systemWithToolPolicy) {
|
|
1771
|
+
const baseMessages: ModelMessage[] = fittedMessages ?? [
|
|
1772
|
+
{ role: "user" as const, content: prompt },
|
|
1773
|
+
];
|
|
1774
|
+
effectiveMessages = withCachedSystemPrompt(
|
|
1775
|
+
systemWithToolPolicy,
|
|
1776
|
+
baseMessages,
|
|
1777
|
+
cacheBreakpoint,
|
|
1778
|
+
);
|
|
1779
|
+
effectiveSystem = undefined;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
// Build providerOptions for extended thinking when enabled on a supported model.
|
|
1783
|
+
// Caching uses message-level breakpoints (withCachedSystemPrompt / withCachedLastMessage),
|
|
1784
|
+
// not top-level providerOptions, so there is no collision.
|
|
1785
|
+
// Note: when thinking is enabled, temperature must not be set (Anthropic rejects it);
|
|
1786
|
+
// this path never sets temperature, so there is nothing to clear.
|
|
1787
|
+
const reasoningProviderOptions = buildReasoningProviderOptions(model, {
|
|
1788
|
+
enableThinking,
|
|
1789
|
+
thinkingEffort,
|
|
1790
|
+
openAIReasoningEffort,
|
|
1791
|
+
});
|
|
1792
|
+
const openRouterProviderOptions = buildOpenRouterProviderOptions(model);
|
|
1793
|
+
const providerOptions =
|
|
1794
|
+
reasoningProviderOptions || openRouterProviderOptions
|
|
1795
|
+
? { ...reasoningProviderOptions, ...openRouterProviderOptions }
|
|
1796
|
+
: undefined;
|
|
1797
|
+
|
|
1798
|
+
let rateLimitRetryCount = 0;
|
|
1799
|
+
|
|
1800
|
+
// Make `activeTools` authoritative: advertise, execute, and enumerate only
|
|
1801
|
+
// the allowlisted tools. A no-op when `activeTools` is empty/undefined.
|
|
1802
|
+
// `resolveEffectiveTools` above already filtered the map and cleared
|
|
1803
|
+
// `activeTools`, so this is a no-op on the normal path; kept for callers that
|
|
1804
|
+
// reach streamText with an intact `activeTools` (identity when undefined).
|
|
1805
|
+
const allowedTools = withResponseToolActive(tools, activeTools);
|
|
1806
|
+
const effectiveTools = restrictToolsToActive(tools, allowedTools);
|
|
1807
|
+
|
|
1808
|
+
try {
|
|
1809
|
+
// Create the appropriate provider instance. The span tracker captures
|
|
1810
|
+
// the SDK's root generation span for error marking (see below).
|
|
1811
|
+
const generationSpans = createGenerationSpanTracker();
|
|
1812
|
+
const responseOptions: Parameters<typeof streamText>[0] = {
|
|
1813
|
+
model: providerModel,
|
|
1814
|
+
system: effectiveSystem,
|
|
1815
|
+
...(effectiveMessages ? { messages: effectiveMessages } : { prompt }),
|
|
1816
|
+
stopWhen,
|
|
1817
|
+
toolChoice,
|
|
1818
|
+
tools: effectiveTools,
|
|
1819
|
+
maxRetries: 3,
|
|
1820
|
+
providerOptions,
|
|
1821
|
+
// Step history would retain a serialized request body per step, and
|
|
1822
|
+
// later steps re-send the whole conversation, so they accumulate.
|
|
1823
|
+
// Native capture reads the provider stream result, not this filter.
|
|
1824
|
+
experimental_include: { requestBody: false },
|
|
1825
|
+
// The forwarding tracer keeps a handle on the SDK's root generation
|
|
1826
|
+
// span: error-part runs complete normally in the SDK, so nothing
|
|
1827
|
+
// marks the span failed — the wrapper's catch does.
|
|
1828
|
+
experimental_telemetry: {
|
|
1829
|
+
...createAiTelemetrySettings({
|
|
1830
|
+
operation: "apex.agent.stream",
|
|
1831
|
+
sessionId,
|
|
1832
|
+
compaction: opts._compaction?.last,
|
|
1833
|
+
}),
|
|
1834
|
+
tracer: generationSpans.tracer,
|
|
1835
|
+
},
|
|
1836
|
+
// Pin actual emission to the same value `fitMessagesToContext`
|
|
1837
|
+
// reserved for output. Without this, the SDK applies provider
|
|
1838
|
+
// defaults that can exceed our budget — e.g. GPT-4o defaults to
|
|
1839
|
+
// 16K output but our messages were sized assuming a smaller
|
|
1840
|
+
// reservation. Making the value explicit closes that drift class.
|
|
1841
|
+
maxOutputTokens: getMaxOutputTokens(
|
|
1842
|
+
model,
|
|
1843
|
+
authConfig?.customProviders,
|
|
1844
|
+
authConfig?.hoonifyModels,
|
|
1845
|
+
),
|
|
1846
|
+
// Awaiting inside prepareStep keeps streamResponse synchronous; the
|
|
1847
|
+
// SDK awaits it before provider dispatch, so every turn and every
|
|
1848
|
+
// recovery re-entry commits before use.
|
|
1849
|
+
prepareStep: async (opts) => {
|
|
1850
|
+
if (contextRecorder) {
|
|
1851
|
+
if (recorderBase === undefined) {
|
|
1852
|
+
recorderBase = structuredClone(opts.messages);
|
|
1853
|
+
}
|
|
1854
|
+
// Full logical context each turn — accepted step outputs must
|
|
1855
|
+
// survive into every later commit, and system is explicit (when
|
|
1856
|
+
// cached into messages, effectiveSystem is undefined → null).
|
|
1857
|
+
await contextRecorder.checkpoint({
|
|
1858
|
+
messages: opts.messages,
|
|
1859
|
+
system: effectiveSystem ?? null,
|
|
1860
|
+
});
|
|
1861
|
+
}
|
|
1862
|
+
// Update the container with the latest messages
|
|
1863
|
+
messagesContainer.current = opts.messages;
|
|
1864
|
+
// Mark the last message so the growing conversation caches incrementally
|
|
1865
|
+
if (cacheBreakpoint) {
|
|
1866
|
+
return {
|
|
1867
|
+
messages: withCachedLastMessage(opts.messages, cacheBreakpoint),
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
return undefined;
|
|
1871
|
+
},
|
|
1872
|
+
onError: async ({ error }: { error: unknown }) => {
|
|
1873
|
+
// Never throw here: the SDK calls this inside its stream pipeline,
|
|
1874
|
+
// and a thrown callback kills the pipeline's terminal lifecycle —
|
|
1875
|
+
// the root generation span never ends and nothing exports. Return
|
|
1876
|
+
// normally instead; the error part continues downstream and the
|
|
1877
|
+
// consumption wrapper converts it to a thrown error (after the
|
|
1878
|
+
// tail drains), where the retry machinery takes over.
|
|
1879
|
+
const errorMessage =
|
|
1880
|
+
error instanceof Error ? error.message : String(error);
|
|
1881
|
+
if (
|
|
1882
|
+
errorMessage.toLowerCase().includes("too many tokens") ||
|
|
1883
|
+
errorMessage.toLowerCase().includes("overloaded")
|
|
1884
|
+
) {
|
|
1885
|
+
rateLimitRetryCount++;
|
|
1886
|
+
if (getInferenceRecorder(opts)) {
|
|
1887
|
+
// This SDK callback must not throw, including when cancellation ends its wait.
|
|
1888
|
+
await delay(1000 * rateLimitRetryCount, undefined, {
|
|
1889
|
+
signal: abortSignal,
|
|
1890
|
+
}).catch(() => {});
|
|
1891
|
+
} else {
|
|
1892
|
+
await new Promise((resolve) =>
|
|
1893
|
+
setTimeout(resolve, 1000 * rateLimitRetryCount),
|
|
1894
|
+
);
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
},
|
|
1898
|
+
onStepFinish,
|
|
1899
|
+
abortSignal,
|
|
1900
|
+
activeTools: allowedTools,
|
|
1901
|
+
experimental_repairToolCall: async ({
|
|
1902
|
+
toolCall,
|
|
1903
|
+
inputSchema,
|
|
1904
|
+
tools,
|
|
1905
|
+
error,
|
|
1906
|
+
}) => {
|
|
1907
|
+
// [response-debug] Log when repair fires for `response` (streamed args failed Zod validation), bypassing `silent`.
|
|
1908
|
+
if (RESPONSE_DEBUG && toolCall.toolName === RESPONSE_TOOL_NAME) {
|
|
1909
|
+
const raw = toolCall.input;
|
|
1910
|
+
const rawLen =
|
|
1911
|
+
typeof raw === "string" ? raw.length : JSON.stringify(raw).length;
|
|
1912
|
+
log.warn(
|
|
1913
|
+
`[response-debug] experimental_repairToolCall FIRED for response ` +
|
|
1914
|
+
`rawInputChars=${rawLen} error=${(error.message || String(error)).slice(0, 200)}`,
|
|
1915
|
+
);
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
// Fail closed for security-sensitive tools: never let repair invent or
|
|
1919
|
+
// replace arguments (e.g. a spawn `target`). Returning null drops the
|
|
1920
|
+
// invalid call instead of executing a model-synthesized one.
|
|
1921
|
+
if (isRepairFailClosedTool(toolCall.toolName)) {
|
|
1922
|
+
if (!silent) {
|
|
1923
|
+
log.warn(
|
|
1924
|
+
`Tool-call repair disabled for security-sensitive tool "${toolCall.toolName}" — failing closed (no argument synthesis).`,
|
|
1925
|
+
);
|
|
1926
|
+
}
|
|
1927
|
+
return null;
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
try {
|
|
1931
|
+
if (!silent) {
|
|
1932
|
+
log.debug(`Repairing tool call: ${toolCall.toolName}`, {
|
|
1933
|
+
error: error.message || String(error),
|
|
1934
|
+
});
|
|
1935
|
+
|
|
1936
|
+
// Log specific details for common enum errors
|
|
1937
|
+
if (
|
|
1938
|
+
error.message &&
|
|
1939
|
+
(error.message.includes("severity") ||
|
|
1940
|
+
error.message.includes("riskLevel"))
|
|
1941
|
+
) {
|
|
1942
|
+
log.debug(
|
|
1943
|
+
"Enum validation error — tool call repair will normalize the value",
|
|
1944
|
+
);
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// Get the actual tool definition which contains the Zod schema
|
|
1949
|
+
const tool = tools[toolCall.toolName];
|
|
1950
|
+
if (!tool?.inputSchema) {
|
|
1951
|
+
if (!silent) {
|
|
1952
|
+
log.warn(
|
|
1953
|
+
`Cannot repair tool call: ${toolCall.toolName} not found or has no schema`,
|
|
1954
|
+
);
|
|
1955
|
+
}
|
|
1956
|
+
return null;
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
const jsonSchema = inputSchema({ toolName: toolCall.toolName });
|
|
1960
|
+
|
|
1961
|
+
// Bound input + schema so the repair call can't itself overflow.
|
|
1962
|
+
const rawInput = toolCall.input;
|
|
1963
|
+
const inputAsText =
|
|
1964
|
+
typeof rawInput === "string" ? rawInput : JSON.stringify(rawInput);
|
|
1965
|
+
const boundedInput = truncateWithMarker(
|
|
1966
|
+
inputAsText,
|
|
1967
|
+
MAX_TOOL_INPUT_CHARS,
|
|
1968
|
+
);
|
|
1969
|
+
const boundedSchema = truncateWithMarker(
|
|
1970
|
+
JSON.stringify(jsonSchema),
|
|
1971
|
+
MAX_SCHEMA_CHARS,
|
|
1972
|
+
"schema",
|
|
1973
|
+
);
|
|
1974
|
+
|
|
1975
|
+
const {
|
|
1976
|
+
output: repairedArgs,
|
|
1977
|
+
usage: repairUsage,
|
|
1978
|
+
providerMetadata: repairProviderMetadata,
|
|
1979
|
+
} = await runWithNativeRolloutOperation(
|
|
1980
|
+
{ operationKind: "tool.repair", sessionId },
|
|
1981
|
+
() =>
|
|
1982
|
+
generateText({
|
|
1983
|
+
model: providerModel,
|
|
1984
|
+
providerOptions: {
|
|
1985
|
+
...openRouterProviderOptions,
|
|
1986
|
+
// Durable runtime: tool-call repair fires only when a
|
|
1987
|
+
// replayed tool call fails validation — nondeterministically
|
|
1988
|
+
// vs the first run — so it must stay off the checkpoint
|
|
1989
|
+
// journal. The agent-runtime middleware reads this namespace
|
|
1990
|
+
// and runs the call without a durable step; the underlying
|
|
1991
|
+
// provider ignores it.
|
|
1992
|
+
pensarRuntime: { ephemeral: true },
|
|
1993
|
+
},
|
|
1994
|
+
output: Output.object({
|
|
1995
|
+
schema: tool.inputSchema, // Use the actual Zod schema from the tool
|
|
1996
|
+
}),
|
|
1997
|
+
prompt: [
|
|
1998
|
+
`The model tried to call the tool "${toolCall.toolName}"` +
|
|
1999
|
+
` with the following inputs:`,
|
|
2000
|
+
boundedInput,
|
|
2001
|
+
`The tool accepts the following schema:`,
|
|
2002
|
+
boundedSchema,
|
|
2003
|
+
`Error encountered: ${error}`,
|
|
2004
|
+
"Please fix the inputs to match the schema.",
|
|
2005
|
+
"",
|
|
2006
|
+
"IMPORTANT: For enum fields like 'severity' or 'riskLevel', use ONLY the exact values from the enum (e.g., 'HIGH', 'CRITICAL', 'MEDIUM', 'LOW').",
|
|
2007
|
+
"Do not add prefixes, suffixes, or formatting characters like '>', '-', '!', etc.",
|
|
2008
|
+
].join("\n"),
|
|
2009
|
+
abortSignal,
|
|
2010
|
+
experimental_telemetry: createAiTelemetrySettings({
|
|
2011
|
+
operation: "apex.tool.repair",
|
|
2012
|
+
sessionId,
|
|
2013
|
+
}),
|
|
2014
|
+
}),
|
|
2015
|
+
);
|
|
2016
|
+
|
|
2017
|
+
// Report tool repair token usage if onStepFinish callback is
|
|
2018
|
+
// provided. Awaited: the callback persists messages and records
|
|
2019
|
+
// usage — a detached invocation would leak unhandled rejections
|
|
2020
|
+
// into the tool loop. Provider metadata and cache details flow
|
|
2021
|
+
// through so repair usage stays attributable.
|
|
2022
|
+
if (onStepFinish && repairUsage) {
|
|
2023
|
+
try {
|
|
2024
|
+
await onStepFinish({
|
|
2025
|
+
text: "",
|
|
2026
|
+
reasoning: undefined,
|
|
2027
|
+
reasoningDetails: [],
|
|
2028
|
+
files: [],
|
|
2029
|
+
sources: [],
|
|
2030
|
+
toolCalls: [],
|
|
2031
|
+
toolResults: [],
|
|
2032
|
+
finishReason: "stop",
|
|
2033
|
+
usage: {
|
|
2034
|
+
inputTokens: repairUsage.inputTokens ?? 0,
|
|
2035
|
+
outputTokens: repairUsage.outputTokens ?? 0,
|
|
2036
|
+
totalTokens: repairUsage.totalTokens ?? 0,
|
|
2037
|
+
...(repairUsage.inputTokenDetails
|
|
2038
|
+
? { inputTokenDetails: repairUsage.inputTokenDetails }
|
|
2039
|
+
: {}),
|
|
2040
|
+
},
|
|
2041
|
+
warnings: [],
|
|
2042
|
+
request: {},
|
|
2043
|
+
response: {
|
|
2044
|
+
id: "tool-repair",
|
|
2045
|
+
timestamp: new Date(),
|
|
2046
|
+
modelId: "",
|
|
2047
|
+
messages: messagesContainer.current,
|
|
2048
|
+
},
|
|
2049
|
+
providerMetadata: repairProviderMetadata,
|
|
2050
|
+
stepType: "initial",
|
|
2051
|
+
isContinued: false,
|
|
2052
|
+
} as unknown as Parameters<
|
|
2053
|
+
StreamTextOnStepFinishCallback<ToolSet>
|
|
2054
|
+
>[0]);
|
|
2055
|
+
} catch (callbackError) {
|
|
2056
|
+
if (!silent) {
|
|
2057
|
+
log.warn("Error reporting tool repair usage", {
|
|
2058
|
+
error: String(callbackError),
|
|
2059
|
+
});
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
if (repairedArgs === undefined || repairedArgs === null) {
|
|
2065
|
+
if (!silent) {
|
|
2066
|
+
log.warn(
|
|
2067
|
+
`Tool call repair for "${toolCall.toolName}" produced no valid output`,
|
|
2068
|
+
);
|
|
2069
|
+
}
|
|
2070
|
+
return null;
|
|
2071
|
+
}
|
|
2072
|
+
return { ...toolCall, input: JSON.stringify(repairedArgs) };
|
|
2073
|
+
} catch (repairError) {
|
|
2074
|
+
if (!silent) {
|
|
2075
|
+
log.warn("Error repairing tool call", {
|
|
2076
|
+
error: String(repairError),
|
|
2077
|
+
});
|
|
2078
|
+
}
|
|
2079
|
+
return null;
|
|
2080
|
+
}
|
|
2081
|
+
},
|
|
2082
|
+
onFinish,
|
|
2083
|
+
};
|
|
2084
|
+
let recovery = nativeRecovery;
|
|
2085
|
+
const response = recovery
|
|
2086
|
+
? streamText(responseOptions)
|
|
2087
|
+
: runWithNativeRolloutOperation(
|
|
2088
|
+
{ operationKind: "agent.stream", sessionId },
|
|
2089
|
+
() => {
|
|
2090
|
+
const operation = new AsyncResource("apex.native-stream-recovery");
|
|
2091
|
+
recovery = {
|
|
2092
|
+
model: providerModel,
|
|
2093
|
+
run: (fn) => operation.runInAsyncScope(fn),
|
|
2094
|
+
};
|
|
2095
|
+
return streamText(responseOptions);
|
|
2096
|
+
},
|
|
2097
|
+
);
|
|
2098
|
+
|
|
2099
|
+
// Wrap the stream to catch async errors during consumption
|
|
2100
|
+
const recoveryOpts: InternalStreamResponseOpts = recovery
|
|
2101
|
+
? { ...opts, [NATIVE_STREAM_RECOVERY]: recovery }
|
|
2102
|
+
: opts;
|
|
2103
|
+
return wrapStreamWithErrorHandler(
|
|
2104
|
+
response,
|
|
2105
|
+
messagesContainer,
|
|
2106
|
+
recoveryOpts,
|
|
2107
|
+
providerModel,
|
|
2108
|
+
silent,
|
|
2109
|
+
0,
|
|
2110
|
+
0,
|
|
2111
|
+
generationSpans,
|
|
2112
|
+
);
|
|
2113
|
+
} catch (error) {
|
|
2114
|
+
// Check if the error is related to context length
|
|
2115
|
+
const isContextLengthError = checkIfContextLengthError(error);
|
|
2116
|
+
const outerErrorMessage =
|
|
2117
|
+
error instanceof Error ? error.message : String(error);
|
|
2118
|
+
|
|
2119
|
+
if (isContextLengthError) {
|
|
2120
|
+
if (!silent) {
|
|
2121
|
+
log.warn(
|
|
2122
|
+
`Context length error, summarizing ${messagesContainer.current.length} messages`,
|
|
2123
|
+
{ error: outerErrorMessage },
|
|
2124
|
+
);
|
|
2125
|
+
}
|
|
2126
|
+
// Wrap so a context error inside the summarization stream itself
|
|
2127
|
+
// (or the resumed `streamResponse` it triggers) is caught and routed
|
|
2128
|
+
// through the same recovery cascade as the proactive and reactive
|
|
2129
|
+
// paths — invariant I4: every context-recovery failure must be caught
|
|
2130
|
+
// at the `streamResponse` boundary, never escape raw to the consumer.
|
|
2131
|
+
//
|
|
2132
|
+
// Pass `opts` through unchanged — the slot is consumed by
|
|
2133
|
+
// `summarizeConversation`'s internal `_restartDepth + 1` bump on
|
|
2134
|
+
// the resumed call. See the proactive escalation comment above
|
|
2135
|
+
// for the symmetry rationale.
|
|
2136
|
+
return wrapStreamWithErrorHandler(
|
|
2137
|
+
createSummarizationStream(
|
|
2138
|
+
messagesContainer.current,
|
|
2139
|
+
{ ...opts, _compactionTrigger: "context_overflow" },
|
|
2140
|
+
providerModel,
|
|
2141
|
+
),
|
|
2142
|
+
messagesContainer,
|
|
2143
|
+
opts,
|
|
2144
|
+
providerModel,
|
|
2145
|
+
silent,
|
|
2146
|
+
);
|
|
2147
|
+
}
|
|
2148
|
+
if (!silent) {
|
|
2149
|
+
log.error("Non-context length error, re-throwing", {
|
|
2150
|
+
error: outerErrorMessage,
|
|
2151
|
+
});
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
// Re-throw if it's not a context length error
|
|
2155
|
+
throw error;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
export interface GenerateObjectOpts<T extends z.ZodType> {
|
|
2160
|
+
model: AIModel;
|
|
2161
|
+
schema: T;
|
|
2162
|
+
prompt: string;
|
|
2163
|
+
system?: string;
|
|
2164
|
+
maxTokens?: number;
|
|
2165
|
+
temperature?: number;
|
|
2166
|
+
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
2167
|
+
authConfig?: AIAuthConfig;
|
|
2168
|
+
abortSignal?: AbortSignal;
|
|
2169
|
+
onTokenUsage?: (inputTokens: number, outputTokens: number) => void;
|
|
2170
|
+
/** Provider middleware applied only to this call's model. */
|
|
2171
|
+
languageModelMiddleware?: LanguageModelMiddleware | LanguageModelMiddleware[];
|
|
2172
|
+
/** Explicit undefined clears an inherited recorder for an unrecorded child. */
|
|
2173
|
+
inferenceRecorder?: InferenceRecorder;
|
|
2174
|
+
/** Per-run usage recorder; when set it replaces the global usage callback. */
|
|
2175
|
+
usageRecorder?: UsageRecorder;
|
|
2176
|
+
/** Session id (`ses_…`) of the caller — stamped onto AI-span telemetry. */
|
|
2177
|
+
sessionId?: string;
|
|
2178
|
+
/** Stable operation id; defaults to `apex.structured.generate`. */
|
|
2179
|
+
operation?: AiTelemetryOperation;
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
const MAX_OBJECT_RATE_LIMIT_RETRIES = 8;
|
|
2183
|
+
|
|
2184
|
+
export async function generateObjectResponse<T extends z.ZodType>(
|
|
2185
|
+
opts: GenerateObjectOpts<T>,
|
|
2186
|
+
): Promise<z.infer<T>> {
|
|
2187
|
+
opts = { ...opts, inferenceRecorder: getInferenceRecorder(opts) };
|
|
2188
|
+
return runWithInferenceRecorder(opts.inferenceRecorder, () =>
|
|
2189
|
+
generateObjectResponseWithinRecorder(opts),
|
|
2190
|
+
);
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
async function generateObjectResponseWithinRecorder<T extends z.ZodType>(
|
|
2194
|
+
opts: GenerateObjectOpts<T>,
|
|
2195
|
+
): Promise<z.infer<T>> {
|
|
2196
|
+
const {
|
|
2197
|
+
model,
|
|
2198
|
+
schema,
|
|
2199
|
+
prompt,
|
|
2200
|
+
system,
|
|
2201
|
+
maxTokens,
|
|
2202
|
+
temperature,
|
|
2203
|
+
openAIReasoningEffort,
|
|
2204
|
+
authConfig,
|
|
2205
|
+
abortSignal,
|
|
2206
|
+
onTokenUsage,
|
|
2207
|
+
languageModelMiddleware,
|
|
2208
|
+
usageRecorder,
|
|
2209
|
+
sessionId,
|
|
2210
|
+
} = opts;
|
|
2211
|
+
|
|
2212
|
+
const baseProviderModel = withNativeRolloutEvidenceModel(
|
|
2213
|
+
withModelCallDiagnostics(getProviderModel(model, authConfig)),
|
|
2214
|
+
{
|
|
2215
|
+
requestedModelId: model,
|
|
2216
|
+
operationKind: nativeRolloutOperation(opts.operation),
|
|
2217
|
+
sessionId,
|
|
2218
|
+
},
|
|
2219
|
+
);
|
|
2220
|
+
const providerModel = languageModelMiddleware
|
|
2221
|
+
? wrapLanguageModel({
|
|
2222
|
+
model: baseProviderModel,
|
|
2223
|
+
middleware: languageModelMiddleware,
|
|
2224
|
+
})
|
|
2225
|
+
: baseProviderModel;
|
|
2226
|
+
const reasoningProviderOptions = buildReasoningProviderOptions(model, {
|
|
2227
|
+
openAIReasoningEffort,
|
|
2228
|
+
});
|
|
2229
|
+
const openRouterProviderOptions =
|
|
2230
|
+
buildOpenRouterStructuredProviderOptions(model);
|
|
2231
|
+
|
|
2232
|
+
return runWithNativeRolloutOperation(
|
|
2233
|
+
{
|
|
2234
|
+
operationKind: nativeRolloutOperation(opts.operation),
|
|
2235
|
+
sessionId,
|
|
2236
|
+
},
|
|
2237
|
+
async () => {
|
|
2238
|
+
let lastError: unknown;
|
|
2239
|
+
|
|
2240
|
+
for (
|
|
2241
|
+
let attempt = 0;
|
|
2242
|
+
attempt <= MAX_OBJECT_RATE_LIMIT_RETRIES;
|
|
2243
|
+
attempt++
|
|
2244
|
+
) {
|
|
2245
|
+
try {
|
|
2246
|
+
const { output, usage, providerMetadata } = await generateText({
|
|
2247
|
+
model: providerModel,
|
|
2248
|
+
output: Output.object({
|
|
2249
|
+
schema,
|
|
2250
|
+
}),
|
|
2251
|
+
prompt,
|
|
2252
|
+
system,
|
|
2253
|
+
maxOutputTokens: maxTokens,
|
|
2254
|
+
temperature,
|
|
2255
|
+
providerOptions:
|
|
2256
|
+
reasoningProviderOptions || openRouterProviderOptions
|
|
2257
|
+
? {
|
|
2258
|
+
...reasoningProviderOptions,
|
|
2259
|
+
...(openRouterProviderOptions
|
|
2260
|
+
? {
|
|
2261
|
+
openrouter: {
|
|
2262
|
+
...reasoningProviderOptions?.openrouter,
|
|
2263
|
+
...openRouterProviderOptions.openrouter,
|
|
2264
|
+
},
|
|
2265
|
+
}
|
|
2266
|
+
: {}),
|
|
2267
|
+
}
|
|
2268
|
+
: undefined,
|
|
2269
|
+
maxRetries: 0,
|
|
2270
|
+
abortSignal,
|
|
2271
|
+
experimental_telemetry: createAiTelemetrySettings({
|
|
2272
|
+
operation: opts.operation ?? "apex.structured.generate",
|
|
2273
|
+
sessionId,
|
|
2274
|
+
}),
|
|
2275
|
+
});
|
|
2276
|
+
|
|
2277
|
+
if (onTokenUsage && usage) {
|
|
2278
|
+
onTokenUsage(usage.inputTokens ?? 0, usage.outputTokens ?? 0);
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
if (usage) {
|
|
2282
|
+
await emitUsage(
|
|
2283
|
+
model,
|
|
2284
|
+
normalizeStepUsage({ usage, providerMetadata }),
|
|
2285
|
+
resolveUsageSink(usageRecorder),
|
|
2286
|
+
);
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
// zod v4: the AI SDK's `Output.object` no longer carries the schema's
|
|
2290
|
+
// inferred type through `output` (it widens to `unknown`), so restore it
|
|
2291
|
+
// from the schema generic for callers.
|
|
2292
|
+
return output as z.infer<T>;
|
|
2293
|
+
} catch (error) {
|
|
2294
|
+
// Surface latched persistence/limit failures before any retry
|
|
2295
|
+
// classification — they are terminal, never delayed or retried.
|
|
2296
|
+
await getInferenceRecorder(opts)?.flush();
|
|
2297
|
+
if (
|
|
2298
|
+
error instanceof RunPersistenceError ||
|
|
2299
|
+
error instanceof RunLimitError ||
|
|
2300
|
+
error instanceof RunControlInterruption
|
|
2301
|
+
) {
|
|
2302
|
+
throw error;
|
|
2303
|
+
}
|
|
2304
|
+
lastError = error;
|
|
2305
|
+
|
|
2306
|
+
if (checkIfContextLengthError(error)) {
|
|
2307
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2308
|
+
throw new ContextLengthError(
|
|
2309
|
+
`Prompt exceeds model context window: ${msg}`,
|
|
2310
|
+
);
|
|
2311
|
+
}
|
|
2312
|
+
|
|
2313
|
+
if (
|
|
2314
|
+
checkIfRateLimitError(error) &&
|
|
2315
|
+
attempt < MAX_OBJECT_RATE_LIMIT_RETRIES
|
|
2316
|
+
) {
|
|
2317
|
+
const delayMs = Math.min(1000 * 2 ** attempt, 60_000);
|
|
2318
|
+
const recorder = getInferenceRecorder(opts);
|
|
2319
|
+
await recorder?.retry({
|
|
2320
|
+
authority: "object-rate-limit",
|
|
2321
|
+
count: attempt + 1,
|
|
2322
|
+
maxRetries: MAX_OBJECT_RATE_LIMIT_RETRIES,
|
|
2323
|
+
delayMs,
|
|
2324
|
+
});
|
|
2325
|
+
if (recorder) {
|
|
2326
|
+
await delay(delayMs, undefined, { signal: abortSignal });
|
|
2327
|
+
} else {
|
|
2328
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
2329
|
+
}
|
|
2330
|
+
continue;
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
throw error;
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
throw lastError;
|
|
2338
|
+
},
|
|
2339
|
+
);
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2342
|
+
class ContextLengthError extends Error {
|
|
2343
|
+
constructor(message: string) {
|
|
2344
|
+
super(message);
|
|
2345
|
+
this.name = "ContextLengthError";
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2349
|
+
/**
|
|
2350
|
+
* Terminal: all recovery paths exhausted. The only context-length error
|
|
2351
|
+
* allowed to escape `streamResponse` — others are recoverable by design.
|
|
2352
|
+
*/
|
|
2353
|
+
export class ContextLengthExhaustedError extends Error {
|
|
2354
|
+
readonly restartDepth: number;
|
|
2355
|
+
constructor(message: string, restartDepth: number) {
|
|
2356
|
+
super(message);
|
|
2357
|
+
this.name = "ContextLengthExhaustedError";
|
|
2358
|
+
this.restartDepth = restartDepth;
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
const MAX_RESTART_DEPTH = 3;
|
|
2363
|
+
|
|
2364
|
+
const MAX_TOOL_INPUT_CHARS = 8_000;
|
|
2365
|
+
const MAX_SCHEMA_CHARS = 6_000;
|
|
2366
|
+
|
|
2367
|
+
const MINIMAL_RESTART_PROMPT =
|
|
2368
|
+
"Continue the previous task. Earlier context was discarded due to repeated context-length errors.";
|
|
2369
|
+
|
|
2370
|
+
export {
|
|
2371
|
+
applySequentialToolCallPolicy,
|
|
2372
|
+
createToolExecutionGate,
|
|
2373
|
+
getStreamIdleTimeoutMs,
|
|
2374
|
+
SEQUENTIAL_TOOL_CALL_INSTRUCTION,
|
|
2375
|
+
StreamIdleTimeoutError,
|
|
2376
|
+
withIdleTimeout,
|
|
2377
|
+
};
|