@pensar/apex 2.6.1 → 2.7.0-canary.1572d9a4
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/build/{agent-ayreaj6z.js → agent-3g1b578v.js} +6 -5
- package/build/{agent-yby11zaq.js → agent-p8cezgbb.js} +7 -6
- package/build/{agent-runs-g37vkrjr.js → agent-runs-f86emmgg.js} +23 -20
- package/build/agent-vaq31je6.js +14 -0
- package/build/agent-vvdqga09.js +14 -0
- package/build/{apps-xn6km9yn.js → apps-3stwnmen.js} +16 -13
- package/build/{auth-d105wc64.js → auth-7md9kwda.js} +16 -13
- package/build/blackboxAgent-ct8bejef.js +14 -0
- package/build/{blackboxPentest-ps78v3w7.js → blackboxPentest-w2nr4md3.js} +21 -15
- package/build/{cli-c05y640n.js → cli-1j28cbhy.js} +1 -1
- package/build/{cli-d37a42dc.js → cli-2jz2jz06.js} +206 -90
- package/build/{cli-az3xq70v.js → cli-4a8dsz2k.js} +4 -4
- package/build/{cli-qgz1q9g5.js → cli-58781vcf.js} +1192 -1473
- package/build/{cli-gx71jcke.js → cli-7067zzeb.js} +1 -1
- package/build/{cli-3sp6nd8d.js → cli-81smmd5w.js} +5 -5
- package/build/{cli-k2nwxta0.js → cli-8b25dhky.js} +2 -2
- package/build/{cli-fy6vh2a7.js → cli-8sw5zpqz.js} +1 -1
- package/build/{cli-709rvekb.js → cli-cg3ypx5n.js} +14 -7
- package/build/{cli-dpsw2fe6.js → cli-e9v6zg6h.js} +40941 -40172
- package/build/cli-fjxmphg1.js +36 -0
- package/build/{cli-7eea4e2y.js → cli-gzb6qrzh.js} +31 -60
- package/build/{cli-65g6rcat.js → cli-khnf5xrf.js} +2 -1
- package/build/{cli-1ve18npr.js → cli-mdzt2e8j.js} +4 -2
- package/build/{cli-n2en7j5b.js → cli-n8mmw4c4.js} +1 -1
- package/build/cli-pndb7mh9.js +1193 -0
- package/build/cli-px6ehzqx.js +54 -0
- package/build/{cli-xtc2t6me.js → cli-qs4msn6x.js} +111 -47
- package/build/{cli-kb21qhvm.js → cli-rvybdhgn.js} +4 -3
- package/build/{cli-ae8jqxqr.js → cli-v739h7hb.js} +2 -2
- package/build/{cli-ngq9dr8n.js → cli-wm8ech0x.js} +3 -3
- package/build/cli.js +170 -51
- package/build/{config-zpqkd5cz.js → config-e5v1bkh1.js} +1 -1
- package/build/{fastStrike-mcjdvwez.js → fastStrike-efp0rjs3.js} +74 -17
- package/build/{fixes-kytx5dmj.js → fixes-926cw1ej.js} +16 -13
- package/build/{index-n65z6v7b.js → index-3t41p258.js} +7 -6
- package/build/{index-qv4cc65p.js → index-bv09af6g.js} +19 -15
- package/build/{index-je6hcsqr.js → index-bv6dtwse.js} +1 -1
- package/build/{index-4vqdgb42.js → index-jt52ffgn.js} +1657 -1400
- package/build/{index-ns4m4s01.js → index-np405b9e.js} +11 -7
- package/build/{index-r9yjkfrv.js → index-qys178kp.js} +5 -4
- package/build/{index-wqetp6gq.js → index-tpyzq2wq.js} +42 -11
- package/build/{index-fv64eb32.js → index-vrcdyebh.js} +2 -2
- package/build/{index-dr3tg1w3.js → index-z1g8vbtm.js} +1 -1
- package/build/{issues-eb3q9d3a.js → issues-sncyqh14.js} +16 -13
- package/build/{knowledge-fqsvtx0f.js → knowledge-esgvy5ws.js} +16 -13
- package/build/lance-sacfgs1z.js +232 -0
- package/build/lib/{chunk-9yksqgzr.js → chunk-4aevegnc.js} +77 -45
- package/build/lib/{chunk-9tt2021m.js → chunk-4kf4a15q.js} +13 -13
- package/build/lib/{chunk-fy3bbbqy.js → chunk-5avnedwm.js} +7 -1
- package/build/lib/{chunk-bb0ekhkw.js → chunk-5nz5tk3p.js} +76 -22
- package/build/lib/{chunk-4hwzqthr.js → chunk-7s8e5wrd.js} +3 -2
- package/build/lib/{chunk-yrnrbjes.js → chunk-85kpxwzs.js} +4 -2
- package/build/lib/{chunk-mg03jdmt.js → chunk-9jkzk9nc.js} +1 -1
- package/build/lib/{chunk-r4j8ybn9.js → chunk-9wwts6r6.js} +824 -77
- package/build/lib/{chunk-nhfax4gb.js → chunk-bxznzxdy.js} +5 -1
- package/build/lib/{chunk-r2dkp4tb.js → chunk-cqxm95md.js} +1 -1
- package/build/lib/{chunk-w66ce82a.js → chunk-e3agqspc.js} +12 -4
- package/build/lib/{chunk-ba41jh41.js → chunk-eh5yw385.js} +1137 -333
- package/build/lib/{chunk-1azdancq.js → chunk-ewc9r84m.js} +5 -1
- package/build/lib/{chunk-2njv7wz3.js → chunk-hbyxyxdc.js} +4 -0
- package/build/lib/{chunk-e8yy2k73.js → chunk-jhhwts6w.js} +28 -2
- package/build/lib/{chunk-1jvwqnem.js → chunk-kbxbd1kn.js} +108 -44
- package/build/lib/{chunk-7pwa92rn.js → chunk-mph5fvk7.js} +1 -1
- package/build/lib/chunk-psc23epq.js +107 -0
- package/build/lib/{chunk-acgbyf5h.js → chunk-qxad7qjd.js} +4 -2
- package/build/lib/{chunk-3c00n0cy.js → chunk-r0v3vvgm.js} +54 -33
- package/build/lib/{chunk-1yct6cra.js → chunk-rt13120a.js} +1 -1
- package/build/lib/{chunk-v3dk9j7k.js → chunk-sgya016v.js} +93 -22
- package/build/lib/{chunk-1fy8azee.js → chunk-txef92hq.js} +1 -1
- package/build/lib/{chunk-2qsq76xq.js → chunk-vcd90qrn.js} +189 -90
- package/build/lib/{chunk-7gjdygcx.js → chunk-vwr9w3ab.js} +2 -0
- package/build/lib/{chunk-z137x08b.js → chunk-wf6ak0m3.js} +92 -70
- package/build/lib/{chunk-xhdpgpkm.js → chunk-xft0ms9j.js} +2 -2
- package/build/lib/core/agents/agentRuntime.d.ts +3 -1
- package/build/lib/core/agents/defineAgent.d.ts +3 -2
- package/build/lib/core/agents/lance.d.ts +153 -0
- package/build/lib/core/agents/lanceJudge.d.ts +3 -0
- package/build/lib/core/agents/offSecAgent/index.d.ts +3 -1
- package/build/lib/core/agents/offSecAgent/index.js +16 -14
- package/build/lib/core/agents/offSecAgent/offensiveSecurityAgent.d.ts +4 -0
- package/build/lib/core/agents/offSecAgent/prompt.d.ts +3 -1
- package/build/lib/core/agents/offSecAgent/subagentSpawner.d.ts +18 -2
- package/build/lib/core/agents/offSecAgent/subagentSpawner.js +10 -8
- package/build/lib/core/agents/offSecAgent/toolExecutionContext.d.ts +3 -0
- package/build/lib/core/agents/offSecAgent/toolLifecycle.d.ts +1 -0
- package/build/lib/core/agents/offSecAgent/tools/index.js +10 -6
- package/build/lib/core/agents/offSecAgent/tools/listMemories.d.ts +11 -1
- package/build/lib/core/agents/offSecAgent/tools/reportError.d.ts +2 -1
- package/build/lib/core/agents/offSecAgent/tools/runPentestWorkflow.d.ts +20 -1
- package/build/lib/core/agents/offSecAgent/tools/spawnPentestAgent.d.ts +4 -7
- package/build/lib/core/agents/offSecAgent/tools/spawnPentestSwarm.d.ts +7 -1
- package/build/lib/core/agents/offSecAgent/tools/types.d.ts +6 -3
- package/build/lib/core/agents/offSecAgent/tools/whiteboxCandidates.d.ts +2 -2
- package/build/lib/core/agents/offSecAgent/types.d.ts +19 -3
- package/build/lib/core/agents/specialized/attackSurface/blackboxAgent.js +13 -13
- package/build/lib/core/agents/specialized/attackSurface/schemas.js +12 -12
- package/build/lib/core/agents/specialized/authenticationAgent/index.js +14 -14
- package/build/lib/core/agents/specialized/codeAgent/agent.js +13 -13
- package/build/lib/core/agents/specialized/codeAgent/prompts.d.ts +1 -0
- package/build/lib/core/agents/specialized/cvssScorer/index.d.ts +2 -1
- package/build/lib/core/agents/specialized/findingJudge/agent.js +11 -11
- package/build/lib/core/agents/specialized/findingJudge/index.d.ts +2 -1
- package/build/lib/core/agents/specialized/findingJudge/index.js +4 -4
- package/build/lib/core/agents/specialized/patching/index.js +14 -14
- package/build/lib/core/agents/specialized/pentest/agent.d.ts +18 -4
- package/build/lib/core/agents/specialized/pentest/agent.js +15 -13
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.d.ts +2 -1
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/index.js +13 -13
- package/build/lib/core/ai/ai.d.ts +29 -70
- package/build/lib/core/ai/ai.js +5 -3
- package/build/lib/core/ai/index.d.ts +1 -0
- package/build/lib/core/ai/index.js +16 -4
- package/build/lib/core/ai/models/claude-capabilities.d.ts +3 -2
- package/build/lib/core/ai/models/concentrate.d.ts +1 -0
- package/build/lib/core/ai/models/index.d.ts +1 -1
- package/build/lib/core/ai/providers/concentrate.d.ts +1 -0
- package/build/lib/core/ai/reasoning.d.ts +44 -0
- package/build/lib/core/ai/utils.d.ts +2 -0
- package/build/lib/core/ai/utils.js +5 -3
- package/build/lib/core/api/index.d.ts +6 -0
- package/build/lib/core/api/index.js +32 -23
- package/build/lib/core/api/lance.d.ts +6 -0
- package/build/lib/core/api/offesecAgent.d.ts +1 -0
- package/build/lib/core/api/reasoning.d.ts +12 -0
- package/build/lib/core/api/targetedPentest.d.ts +1 -0
- package/build/lib/core/api/targetedPentest.js +14 -14
- package/build/lib/core/cli/reasoning.d.ts +4 -0
- package/build/lib/core/config/config.d.ts +10 -2
- package/build/lib/core/config/customProviders.d.ts +11 -0
- package/build/lib/core/config/index.js +1 -1
- package/build/lib/core/eventBus.js +1 -1
- package/build/lib/core/findings/registry.d.ts +3 -1
- package/build/lib/core/findings/registry.js +4 -4
- package/build/lib/core/observability/index.js +1 -1
- package/build/lib/core/observability/telemetry.d.ts +4 -0
- package/build/lib/core/session/index.d.ts +47 -0
- package/build/lib/core/session/index.js +6 -4
- package/build/lib/core/session/persistence.d.ts +7 -0
- package/build/lib/core/session/persistence.js +8 -4
- package/build/lib/core/tools/backends/index.js +1 -1
- package/build/lib/core/tools/backends/resolve.d.ts +1 -0
- package/build/lib/core/workflows/fastStrike.d.ts +3 -1
- package/build/lib/core/workflows/pentest.d.ts +12 -2
- package/build/lib/core/workflows/pentest.js +19 -19
- package/build/lib/core/workflows/seams.js +5 -5
- package/build/lib/core/workflows/threatModel.d.ts +1 -0
- package/build/lib/core/workflows/whiteboxAttackSurface.d.ts +6 -4
- package/build/lib/core/workflows/whiteboxAttackSurface.js +15 -15
- package/build/lib/index.js +25 -25
- package/build/{logs-x62b7hk1.js → logs-bcbjpjp6.js} +16 -13
- package/build/{native-rollout-evidence-c9yhfqcs.js → native-rollout-evidence-rph1774m.js} +5 -5
- package/build/offesecAgent-81h1p6ee.js +32 -0
- package/build/pentest-2q20q6n1.js +23 -0
- package/build/{pentests-e0f32aqx.js → pentests-jgw031mc.js} +16 -13
- package/build/recordedRunClient-6axj6fba.js +11 -0
- package/build/subagentSpawner-a861gvt0.js +12 -0
- package/build/targetedPentest-6yxznt7s.js +91 -0
- package/build/{targets-xj9g3q0z.js → targets-bjah19dp.js} +16 -13
- package/build/threatModel-739kpexm.js +24 -0
- package/build/{uninstall-7s784q4a.js → uninstall-yxrn9edt.js} +1 -1
- package/build/{upload-4gvhwmvr.js → upload-34ewrjp5.js} +4 -4
- package/build/{utils-cjrz64pc.js → utils-fzm66efw.js} +5 -5
- package/package.json +2 -1
- package/src/cli/issues.test.ts +17 -1
- package/src/cli/lance-verifier.test.ts +57 -0
- package/src/cli/lance-verifier.ts +73 -0
- package/src/cli/lance.test.ts +71 -0
- package/src/cli/lance.ts +48 -0
- package/src/cli.ts +109 -19
- package/src/core/agents/agentRuntime.test.ts +42 -0
- package/src/core/agents/agentRuntime.ts +7 -2
- package/src/core/agents/defineAgent.ts +3 -1
- package/src/core/agents/lance.test.ts +421 -0
- package/src/core/agents/lance.ts +701 -0
- package/src/core/agents/lanceJudge.test.ts +166 -0
- package/src/core/agents/lanceJudge.ts +115 -0
- package/src/core/agents/offSecAgent/index.ts +3 -0
- package/src/core/agents/offSecAgent/interruptedStepFinalization.test.ts +51 -0
- package/src/core/agents/offSecAgent/lance.test.ts +188 -0
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.test.ts +92 -5
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.ts +244 -41
- package/src/core/agents/offSecAgent/prompt.test.ts +46 -0
- package/src/core/agents/offSecAgent/prompt.ts +52 -8
- package/src/core/agents/offSecAgent/selectiveConstruction.publicPath.test.ts +38 -0
- package/src/core/agents/offSecAgent/selectiveConstruction.test.ts +64 -0
- package/src/core/agents/offSecAgent/subagentSpawner.hooks.test.ts +11 -3
- package/src/core/agents/offSecAgent/subagentSpawner.reasoning.test.ts +167 -0
- package/src/core/agents/offSecAgent/subagentSpawner.ts +82 -28
- package/src/core/agents/offSecAgent/toolExecutionContext.test.ts +230 -0
- package/src/core/agents/offSecAgent/toolExecutionContext.ts +56 -0
- package/src/core/agents/offSecAgent/toolLifecycle.ts +2 -0
- package/src/core/agents/offSecAgent/tools/delegateAuth.ts +4 -2
- package/src/core/agents/offSecAgent/tools/documentFinding.test.ts +9 -4
- package/src/core/agents/offSecAgent/tools/documentFinding.ts +10 -9
- package/src/core/agents/offSecAgent/tools/listMemories.test.ts +230 -0
- package/src/core/agents/offSecAgent/tools/listMemories.ts +73 -6
- package/src/core/agents/offSecAgent/tools/reportError.test.ts +6 -0
- package/src/core/agents/offSecAgent/tools/reportError.ts +10 -2
- package/src/core/agents/offSecAgent/tools/runAttackSurface.ts +7 -4
- package/src/core/agents/offSecAgent/tools/runPentestWorkflow.test.ts +57 -0
- package/src/core/agents/offSecAgent/tools/runPentestWorkflow.ts +21 -1
- package/src/core/agents/offSecAgent/tools/runWhiteboxScan.ts +5 -2
- package/src/core/agents/offSecAgent/tools/spawnCodingAgent.ts +50 -67
- package/src/core/agents/offSecAgent/tools/spawnPentestAgent.test.ts +79 -3
- package/src/core/agents/offSecAgent/tools/spawnPentestAgent.ts +36 -16
- package/src/core/agents/offSecAgent/tools/spawnPentestSwarm.ts +28 -5
- package/src/core/agents/offSecAgent/tools/threatModelGenerator.ts +4 -3
- package/src/core/agents/offSecAgent/tools/types.ts +12 -2
- package/src/core/agents/offSecAgent/tools/updateTask.ts +5 -1
- package/src/core/agents/offSecAgent/tools/whiteboxCandidates.ts +11 -4
- package/src/core/agents/offSecAgent/types.ts +22 -1
- package/src/core/agents/specialized/codeAgent/agent.test.ts +7 -0
- package/src/core/agents/specialized/codeAgent/agent.ts +9 -2
- package/src/core/agents/specialized/codeAgent/prompts.ts +6 -0
- package/src/core/agents/specialized/cvssScorer/index.test.ts +2 -1
- package/src/core/agents/specialized/cvssScorer/index.ts +3 -0
- package/src/core/agents/specialized/findingJudge/index.ts +6 -0
- package/src/core/agents/specialized/pentest/agent.test.ts +155 -0
- package/src/core/agents/specialized/pentest/agent.ts +181 -52
- package/src/core/agents/specialized/pentest/results.test.ts +59 -4
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.concurrency.test.ts +59 -2
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.hooks.test.ts +127 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.ts +74 -68
- package/src/core/ai/ai.durability-hooks.test.ts +25 -7
- package/src/core/ai/ai.lance.test.ts +581 -0
- package/src/core/ai/ai.operator-context.bench.test.ts +1390 -0
- package/src/core/ai/ai.recorded-context.test.ts +89 -8
- package/src/core/ai/ai.test.ts +81 -59
- package/src/core/ai/ai.ts +453 -327
- package/src/core/ai/compactionTelemetry.test.ts +69 -17
- package/src/core/ai/index.ts +11 -0
- package/src/core/ai/models/anthropic.ts +6 -0
- package/src/core/ai/models/bedrock.ts +18 -0
- package/src/core/ai/models/claude-capabilities.ts +29 -8
- package/src/core/ai/models/concentrate.ts +52 -0
- package/src/core/ai/models/index.ts +25 -4
- package/src/core/ai/models/models.test.ts +179 -7
- package/src/core/ai/models/openrouter-reasoning.json +219 -0
- package/src/core/ai/models/openrouter.ts +43 -1
- package/src/core/ai/providers/anthropic-models.test.ts +60 -1
- package/src/core/ai/providers/bedrock-models.test.ts +81 -0
- package/src/core/ai/providers/concentrate.test.ts +31 -0
- package/src/core/ai/providers/concentrate.ts +11 -0
- package/src/core/ai/providers/custom.test.ts +74 -0
- package/src/core/ai/providers/custom.ts +3 -1
- package/src/core/ai/providers/gateway-models.test.ts +16 -6
- package/src/core/ai/providers/pensarFormatters.ts +8 -1
- package/src/core/ai/reasoning.test.ts +313 -0
- package/src/core/ai/reasoning.ts +500 -0
- package/src/core/ai/streamIdleTimeout.test.ts +21 -0
- package/src/core/ai/utils.native-rollout-evidence.test.ts +21 -8
- package/src/core/ai/utils.ts +269 -163
- package/src/core/api/attackSurface.ts +1 -0
- package/src/core/api/blackboxPentest.ts +9 -1
- package/src/core/api/index.ts +17 -0
- package/src/core/api/lance.ts +23 -0
- package/src/core/api/offesecAgent.test.ts +51 -0
- package/src/core/api/offesecAgent.ts +15 -1
- package/src/core/api/reasoning.test.ts +213 -0
- package/src/core/api/reasoning.ts +44 -0
- package/src/core/api/recordedRun.loop.test.ts +5 -1
- package/src/core/api/targetedPentest.test.ts +14 -2
- package/src/core/api/targetedPentest.ts +52 -5
- package/src/core/cli/reasoning.test.ts +149 -0
- package/src/core/cli/reasoning.ts +95 -0
- package/src/core/config/config.test.ts +35 -0
- package/src/core/config/config.ts +11 -0
- package/src/core/config/customProviders.ts +21 -2
- package/src/core/eventBus.ts +1 -0
- package/src/core/findings/registry.test.ts +9 -1
- package/src/core/findings/registry.ts +6 -0
- package/src/core/observability/telemetry.test.ts +131 -79
- package/src/core/observability/telemetry.ts +5 -0
- package/src/core/runtime/sqliteRunObservation.test.ts +1 -1
- package/src/core/session/index.ts +38 -0
- package/src/core/session/persistence.test.ts +62 -0
- package/src/core/session/persistence.ts +56 -0
- package/src/core/tools/backends/resolve.ts +7 -0
- package/src/core/tools/backends/whiteboxJobs.test.ts +9 -8
- package/src/core/workflows/fastStrike.seams.test.ts +149 -0
- package/src/core/workflows/fastStrike.test.ts +18 -1
- package/src/core/workflows/fastStrike.ts +106 -11
- package/src/core/workflows/pentest.test.ts +104 -0
- package/src/core/workflows/pentest.ts +128 -7
- package/src/core/workflows/seams.test.ts +13 -0
- package/src/core/workflows/seams.ts +5 -1
- package/src/core/workflows/threatModel.ts +2 -0
- package/src/core/workflows/whiteboxAttackSurface.test.ts +74 -2
- package/src/core/workflows/whiteboxAttackSurface.ts +102 -73
- package/src/tui/command-registry.test.ts +12 -0
- package/src/tui/command-registry.ts +10 -0
- package/src/tui/components/chat/config-view.tsx +6 -10
- package/src/tui/components/chat/home-view.tsx +2 -2
- package/src/tui/components/chat/input-area.tsx +2 -2
- package/src/tui/components/chat/loading-indicator.tsx +20 -4
- package/src/tui/components/chat/message-list.tsx +1 -0
- package/src/tui/components/commands/__tests__/advanced-settings-lifecycle.tsx +164 -0
- package/src/tui/components/commands/advanced-settings.test.ts +34 -0
- package/src/tui/components/commands/advanced-settings.tsx +220 -31
- package/src/tui/components/commands/models-display.tsx +7 -1
- package/src/tui/components/model-picker/ModelPicker.tsx +65 -103
- package/src/tui/components/model-picker/ModelPickerDialog.tsx +8 -14
- package/src/tui/components/model-picker/__tests__/reasoning-control.tsx +162 -0
- package/src/tui/components/model-picker/reasoning-control.test.ts +15 -0
- package/src/tui/components/operator-dashboard/index.tsx +166 -50
- package/src/tui/components/operator-dashboard/logic.test.ts +144 -2
- package/src/tui/components/operator-dashboard/logic.ts +54 -3
- package/src/tui/components/operator-dashboard/run-events.test.ts +3 -1
- package/src/tui/components/shared/__tests__/tool-renderer-lifecycle.tsx +18 -0
- package/src/tui/components/shared/action-label.test.ts +9 -0
- package/src/tui/components/shared/compacting-icon.tsx +18 -0
- package/src/tui/components/shared/index.ts +1 -0
- package/src/tui/components/shared/tool-registry.ts +1 -0
- package/src/tui/components/shared/tool-renderer.tsx +21 -7
- package/src/tui/context/agent.tsx +32 -79
- package/src/tui/context/route.tsx +2 -0
- package/src/tui/index.tsx +1 -0
- package/src/tui/keybindings/registry.ts +2 -0
- package/build/agent-6w7egcf1.js +0 -13
- package/build/agent-9zx75feh.js +0 -13
- package/build/blackboxAgent-s56sgx9b.js +0 -13
- package/build/cli-g06s7edq.js +0 -11
- package/build/lib/chunk-z96pbjhd.js +0 -56
- package/build/offesecAgent-5whnpeta.js +0 -22
- package/build/pentest-e61hc38s.js +0 -22
- package/build/recordedRunClient-dp032c32.js +0 -11
- package/build/targetedPentest-rcbs4nvp.js +0 -57
- package/build/threatModel-jkxfa40s.js +0 -21
package/src/core/ai/ai.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
|
|
2
2
|
import { setTimeout as delay } from "node:timers/promises";
|
|
3
3
|
import type { AnthropicMessagesModelId } from "@ai-sdk/anthropic/internal";
|
|
4
|
-
import type { OpenAIResponsesProviderOptions } from "@ai-sdk/openai";
|
|
5
4
|
import type { OpenAIChatModelId } from "@ai-sdk/openai/internal";
|
|
5
|
+
import type { LanguageModelV3StreamPart } from "@ai-sdk/provider";
|
|
6
6
|
import {
|
|
7
7
|
generateText,
|
|
8
8
|
type LanguageModel,
|
|
@@ -51,6 +51,9 @@ import {
|
|
|
51
51
|
} from "./compactionTelemetry";
|
|
52
52
|
import {
|
|
53
53
|
estimateMessageTokens,
|
|
54
|
+
estimateTokens,
|
|
55
|
+
estimateToolsOverheadTokens,
|
|
56
|
+
type FitContextResult,
|
|
54
57
|
fitMessagesToContext,
|
|
55
58
|
truncateWithMarker,
|
|
56
59
|
} from "./contextManagement";
|
|
@@ -60,7 +63,7 @@ import {
|
|
|
60
63
|
runWithInferenceRecorder,
|
|
61
64
|
} from "./inference-attempt";
|
|
62
65
|
import {
|
|
63
|
-
|
|
66
|
+
type ClaudeThinkingEffort,
|
|
64
67
|
getMaxOutputTokens,
|
|
65
68
|
getModelInfo,
|
|
66
69
|
prefersSequentialToolCalls,
|
|
@@ -71,13 +74,20 @@ import {
|
|
|
71
74
|
} from "./native-rollout-evidence";
|
|
72
75
|
import { CONCENTRATE_GLM_5_3_MODEL_ID } from "./providers/concentrate";
|
|
73
76
|
import { OPENAI_PRO_TIMEOUT_MS } from "./providers/openai-pro-fetch";
|
|
77
|
+
import {
|
|
78
|
+
buildModelReasoningOptions,
|
|
79
|
+
getReasoningCapabilities,
|
|
80
|
+
type ReasoningProviderOptions,
|
|
81
|
+
type ReasoningSetting,
|
|
82
|
+
resolveReasoningSetting,
|
|
83
|
+
} from "./reasoning";
|
|
74
84
|
import { STREAM_DEBUG } from "./streamTelemetry";
|
|
75
85
|
import {
|
|
76
86
|
type AIAuthConfig,
|
|
87
|
+
CompactionRejectedError,
|
|
77
88
|
checkIfContextLengthError,
|
|
78
89
|
createSummarizationStream,
|
|
79
90
|
getProviderModel,
|
|
80
|
-
isAnthropicProvider,
|
|
81
91
|
} from "./utils";
|
|
82
92
|
|
|
83
93
|
const log = scopedLogger(() => createLogger("ai"));
|
|
@@ -125,6 +135,7 @@ export type AIModel = AnthropicMessagesModelId | OpenAIChatModelId | string; //
|
|
|
125
135
|
|
|
126
136
|
export type OpenAIReasoningEffort =
|
|
127
137
|
| "none"
|
|
138
|
+
| "minimal"
|
|
128
139
|
| "low"
|
|
129
140
|
| "medium"
|
|
130
141
|
| "high"
|
|
@@ -136,41 +147,11 @@ export const DEFAULT_OPENAI_REASONING_EFFORT: OpenAIReasoningEffort = "medium";
|
|
|
136
147
|
|
|
137
148
|
/**
|
|
138
149
|
* Anthropic adaptive-thinking effort hint. Soft guidance for how much the model
|
|
139
|
-
* reasons (see AWS "adaptive thinking"): `low` minimizes thinking
|
|
140
|
-
*
|
|
141
|
-
* support adaptive thinking
|
|
150
|
+
* reasons (see AWS "adaptive thinking"): `low` minimizes thinking while
|
|
151
|
+
* `xhigh` and `max` allow progressively deeper work. Only meaningful for
|
|
152
|
+
* models that support adaptive thinking; ignored elsewhere.
|
|
142
153
|
*/
|
|
143
|
-
export type ThinkingEffort =
|
|
144
|
-
|
|
145
|
-
const OPENAI_REASONING_MODEL_IDS = new Set([
|
|
146
|
-
"gpt-6.1-sol",
|
|
147
|
-
"gpt-6-luna",
|
|
148
|
-
"gpt-6-sol",
|
|
149
|
-
"gpt-6-astra",
|
|
150
|
-
"gpt-5.5-pro",
|
|
151
|
-
"gpt-5.5-pro-2026-04-23",
|
|
152
|
-
"gpt-5.4-nano",
|
|
153
|
-
"gpt-5.4-nano-2026-03-17",
|
|
154
|
-
"gpt-5.4-mini",
|
|
155
|
-
"gpt-5.4-mini-2026-03-17",
|
|
156
|
-
"gpt-5",
|
|
157
|
-
"gpt-5-2025-08-07",
|
|
158
|
-
"gpt-5.1",
|
|
159
|
-
"gpt-5.1-2025-11-13",
|
|
160
|
-
"gpt-5.2",
|
|
161
|
-
"gpt-5.2-2025-12-11",
|
|
162
|
-
"gpt-5.2-pro",
|
|
163
|
-
"gpt-5.2-pro-2025-12-11",
|
|
164
|
-
"gpt-5.4",
|
|
165
|
-
"gpt-5.4-2026-03-05",
|
|
166
|
-
"gpt-5.4-pro",
|
|
167
|
-
"gpt-5.4-pro-2026-03-05",
|
|
168
|
-
"gpt-5.5",
|
|
169
|
-
"gpt-5.5-2026-04-23",
|
|
170
|
-
"gpt-5.6-sol",
|
|
171
|
-
"gpt-5.6-terra",
|
|
172
|
-
"gpt-5.6-luna",
|
|
173
|
-
]);
|
|
154
|
+
export type ThinkingEffort = ClaudeThinkingEffort;
|
|
174
155
|
|
|
175
156
|
/** Per-step billing context attached to a usage report, attributing cost to a specific `(sessionId, stepSeq)`. */
|
|
176
157
|
export interface UsageStepContext {
|
|
@@ -606,7 +587,11 @@ async function* withIdleTimeout<T>(
|
|
|
606
587
|
function isStreamIdleTimeoutError(error: unknown): boolean {
|
|
607
588
|
// AI SDK may rewrap the error, so walk `cause`.
|
|
608
589
|
for (let e: unknown = error, depth = 0; e != null && depth < 6; depth++) {
|
|
609
|
-
if (
|
|
590
|
+
if (
|
|
591
|
+
e instanceof StreamIdleTimeoutError ||
|
|
592
|
+
(e as { name?: unknown }).name === "StreamIdleTimeoutError"
|
|
593
|
+
)
|
|
594
|
+
return true;
|
|
610
595
|
e = (e as { cause?: unknown }).cause;
|
|
611
596
|
}
|
|
612
597
|
return false;
|
|
@@ -640,6 +625,7 @@ function createToolExecutionGate(): {
|
|
|
640
625
|
type: string;
|
|
641
626
|
toolCallId?: string;
|
|
642
627
|
toolName?: string;
|
|
628
|
+
preliminary?: boolean;
|
|
643
629
|
}) => void;
|
|
644
630
|
} {
|
|
645
631
|
let inFlight = 0;
|
|
@@ -648,6 +634,7 @@ function createToolExecutionGate(): {
|
|
|
648
634
|
return {
|
|
649
635
|
shouldEnforceIdleTimeout: () => inFlight === 0,
|
|
650
636
|
observe: (chunk) => {
|
|
637
|
+
if (chunk.type === "tool-result" && chunk.preliminary) return;
|
|
651
638
|
if (chunk.type === "tool-call") {
|
|
652
639
|
if (chunk.toolName && NON_GATED_TOOLS.has(chunk.toolName)) return;
|
|
653
640
|
const id = chunk.toolCallId;
|
|
@@ -676,6 +663,43 @@ function createToolExecutionGate(): {
|
|
|
676
663
|
};
|
|
677
664
|
}
|
|
678
665
|
|
|
666
|
+
class InStreamCompactionRequired extends Error {
|
|
667
|
+
constructor(readonly fitted: FitContextResult) {
|
|
668
|
+
super("In-stream compaction required before provider dispatch");
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Retry once after new tool output, then let fitting handle this turn.
|
|
673
|
+
const MAX_PROACTIVE_SUMMARY_FAILURES = 2;
|
|
674
|
+
|
|
675
|
+
function shouldSummarizeBeforeFitting(
|
|
676
|
+
messages: ModelMessage[],
|
|
677
|
+
contextWindow: number,
|
|
678
|
+
maxOutputTokens: number,
|
|
679
|
+
overheadTokens: number,
|
|
680
|
+
safetyMarginTokens: number,
|
|
681
|
+
system?: string,
|
|
682
|
+
toolChoice?: ToolChoice<ToolSet>,
|
|
683
|
+
): boolean {
|
|
684
|
+
const historyBudget =
|
|
685
|
+
contextWindow -
|
|
686
|
+
maxOutputTokens -
|
|
687
|
+
overheadTokens -
|
|
688
|
+
safetyMarginTokens -
|
|
689
|
+
(system ? estimateTokens(system) : 0);
|
|
690
|
+
const estimatedHistoryTokens = estimateMessageTokens(messages);
|
|
691
|
+
// Forced-tool replays missed the summary cache; keep their fitted history path.
|
|
692
|
+
return (
|
|
693
|
+
historyBudget > 0 &&
|
|
694
|
+
messages.length > 2 &&
|
|
695
|
+
toolChoice !== "required" &&
|
|
696
|
+
typeof toolChoice !== "object" &&
|
|
697
|
+
estimatedHistoryTokens >=
|
|
698
|
+
Math.max(100_000, Math.floor(historyBudget * 0.8)) &&
|
|
699
|
+
estimatedHistoryTokens <= historyBudget
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
|
|
679
703
|
// Helper function to wrap a stream with error handling for async errors
|
|
680
704
|
function wrapStreamWithErrorHandler(
|
|
681
705
|
originalStream: StreamTextResult<ToolSet, never>,
|
|
@@ -686,6 +710,7 @@ function wrapStreamWithErrorHandler(
|
|
|
686
710
|
rateLimitRetryCount: number = 0,
|
|
687
711
|
idleResumeCount: number = 0,
|
|
688
712
|
generationSpans?: GenerationSpanTracker,
|
|
713
|
+
drainIdleStream?: (reason: unknown) => Promise<void>,
|
|
689
714
|
): StreamTextResult<ToolSet, never> {
|
|
690
715
|
// Create a lazy getter for fullStream that wraps it with error handling
|
|
691
716
|
let wrappedStream: AsyncIterable<TextStreamPart<ToolSet>> | null = null;
|
|
@@ -786,7 +811,15 @@ function wrapStreamWithErrorHandler(
|
|
|
786
811
|
|
|
787
812
|
// Check context length FIRST — these should never be retried
|
|
788
813
|
// as-is; the prompt must be reduced via summarization.
|
|
789
|
-
const isCtxError =
|
|
814
|
+
const isCtxError =
|
|
815
|
+
error instanceof InStreamCompactionRequired ||
|
|
816
|
+
error instanceof CompactionRejectedError ||
|
|
817
|
+
checkIfContextLengthError(error);
|
|
818
|
+
if (
|
|
819
|
+
opts.primaryModelOnly &&
|
|
820
|
+
(!opts.runContextCompaction || !isCtxError)
|
|
821
|
+
)
|
|
822
|
+
throw error;
|
|
790
823
|
|
|
791
824
|
// A latched persistence failure is terminal: retrying would
|
|
792
825
|
// dispatch a turn whose context was never durably committed.
|
|
@@ -798,6 +831,9 @@ function wrapStreamWithErrorHandler(
|
|
|
798
831
|
throw error;
|
|
799
832
|
}
|
|
800
833
|
|
|
834
|
+
if (isStreamIdleTimeoutError(error))
|
|
835
|
+
await drainIdleStream?.(error);
|
|
836
|
+
|
|
801
837
|
// Handle stream idle timeout — resume from accumulated messages
|
|
802
838
|
if (
|
|
803
839
|
!isCtxError &&
|
|
@@ -893,42 +929,50 @@ function wrapStreamWithErrorHandler(
|
|
|
893
929
|
}
|
|
894
930
|
|
|
895
931
|
if (isCtxError) {
|
|
896
|
-
let currentMessages: ModelMessage[] =
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
932
|
+
let currentMessages: ModelMessage[] =
|
|
933
|
+
error instanceof InStreamCompactionRequired
|
|
934
|
+
? error.fitted.messages
|
|
935
|
+
: messagesContainer.current;
|
|
936
|
+
if (!(error instanceof InStreamCompactionRequired)) {
|
|
937
|
+
try {
|
|
938
|
+
const response = await originalStream.response;
|
|
939
|
+
if (response.messages && response.messages.length > 0) {
|
|
940
|
+
currentMessages = response.messages as ModelMessage[];
|
|
941
|
+
}
|
|
942
|
+
} catch {
|
|
943
|
+
// Fall back to container messages.
|
|
901
944
|
}
|
|
902
|
-
} catch {
|
|
903
|
-
// Fall back to container messages.
|
|
904
945
|
}
|
|
905
946
|
|
|
906
|
-
const fitted =
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
947
|
+
const fitted =
|
|
948
|
+
error instanceof InStreamCompactionRequired
|
|
949
|
+
? error.fitted
|
|
950
|
+
: fitMessagesToContext(currentMessages, {
|
|
951
|
+
contextWindow: getContextWindow(
|
|
952
|
+
opts.model,
|
|
953
|
+
opts.authConfig?.customProviders,
|
|
954
|
+
opts.authConfig?.hoonifyModels,
|
|
955
|
+
),
|
|
956
|
+
maxOutputTokens: getMaxOutputTokens(
|
|
957
|
+
opts.model,
|
|
958
|
+
opts.authConfig?.customProviders,
|
|
959
|
+
opts.authConfig?.hoonifyModels,
|
|
960
|
+
),
|
|
961
|
+
system: applySequentialToolCallPolicy(
|
|
962
|
+
opts.system,
|
|
963
|
+
opts.tools,
|
|
964
|
+
opts.model,
|
|
965
|
+
),
|
|
966
|
+
tools: opts.tools,
|
|
967
|
+
sessionPath: opts.sessionPath,
|
|
968
|
+
telemetry: {
|
|
969
|
+
trigger: "context_overflow",
|
|
970
|
+
model: opts.model,
|
|
971
|
+
sessionId: opts.sessionId,
|
|
972
|
+
restartDepth: opts._restartDepth,
|
|
973
|
+
previous: opts._compaction?.last,
|
|
974
|
+
},
|
|
975
|
+
});
|
|
932
976
|
|
|
933
977
|
if (fitted.compaction && opts._compaction)
|
|
934
978
|
opts._compaction.last = fitted.compaction;
|
|
@@ -944,7 +988,11 @@ function wrapStreamWithErrorHandler(
|
|
|
944
988
|
// `MAX_RESTART_DEPTH` finally trips.
|
|
945
989
|
let postReactiveDepth = opts._restartDepth ?? 0;
|
|
946
990
|
|
|
947
|
-
if (
|
|
991
|
+
if (
|
|
992
|
+
!(error instanceof CompactionRejectedError) &&
|
|
993
|
+
fitted.fitsBudget &&
|
|
994
|
+
fitted.modified
|
|
995
|
+
) {
|
|
948
996
|
if (!silent) {
|
|
949
997
|
log.warn(
|
|
950
998
|
`Context length error — Layer 1+2 reduced to ~${fitted.estimatedInputTokens} tokens, retrying`,
|
|
@@ -1017,12 +1065,19 @@ function wrapStreamWithErrorHandler(
|
|
|
1017
1065
|
}
|
|
1018
1066
|
|
|
1019
1067
|
try {
|
|
1068
|
+
if (error instanceof CompactionRejectedError) throw error;
|
|
1020
1069
|
const summarizationStream = createSummarizationStream(
|
|
1021
1070
|
messagesForSummary,
|
|
1022
1071
|
{
|
|
1023
1072
|
...opts,
|
|
1024
1073
|
_restartDepth: postReactiveDepth,
|
|
1025
|
-
_compactionTrigger:
|
|
1074
|
+
_compactionTrigger:
|
|
1075
|
+
error instanceof InStreamCompactionRequired
|
|
1076
|
+
? "proactive"
|
|
1077
|
+
: "context_overflow",
|
|
1078
|
+
_proactiveSummaryMayFit:
|
|
1079
|
+
error instanceof InStreamCompactionRequired &&
|
|
1080
|
+
error.fitted.fitsBudget,
|
|
1026
1081
|
},
|
|
1027
1082
|
model,
|
|
1028
1083
|
);
|
|
@@ -1030,7 +1085,7 @@ function wrapStreamWithErrorHandler(
|
|
|
1030
1085
|
yield chunk;
|
|
1031
1086
|
}
|
|
1032
1087
|
} catch (summarizeError) {
|
|
1033
|
-
//
|
|
1088
|
+
// Fall through to minimal restart for context or rejected-summary
|
|
1034
1089
|
// errors. For everything else — auth failures, network
|
|
1035
1090
|
// errors, abort signals, the typed terminal
|
|
1036
1091
|
// `ContextLengthExhaustedError`, or non-`Error` throws —
|
|
@@ -1039,11 +1094,15 @@ function wrapStreamWithErrorHandler(
|
|
|
1039
1094
|
// auth failure would burn an extra cycle that fails
|
|
1040
1095
|
// identically.
|
|
1041
1096
|
if (
|
|
1097
|
+
opts.primaryModelOnly ||
|
|
1042
1098
|
summarizeError instanceof ContextLengthExhaustedError ||
|
|
1043
1099
|
(summarizeError instanceof Error &&
|
|
1044
1100
|
summarizeError.name === "AbortError") ||
|
|
1045
1101
|
opts.abortSignal?.aborted ||
|
|
1046
|
-
!
|
|
1102
|
+
!(
|
|
1103
|
+
checkIfContextLengthError(summarizeError) ||
|
|
1104
|
+
summarizeError instanceof CompactionRejectedError
|
|
1105
|
+
)
|
|
1047
1106
|
) {
|
|
1048
1107
|
throw summarizeError;
|
|
1049
1108
|
}
|
|
@@ -1137,56 +1196,27 @@ export interface ModelInfo {
|
|
|
1137
1196
|
}
|
|
1138
1197
|
|
|
1139
1198
|
export function modelRequiresThinking(modelId: string): boolean {
|
|
1140
|
-
return
|
|
1199
|
+
return getReasoningCapabilities(modelId).alwaysOn ?? false;
|
|
1141
1200
|
}
|
|
1142
1201
|
|
|
1143
|
-
/**
|
|
1144
|
-
* Check whether a model supports extended thinking based on its ID.
|
|
1145
|
-
*
|
|
1146
|
-
* Thinking is available on Claude 3.7 Sonnet and all Claude 4.x+ models
|
|
1147
|
-
* (Sonnet, Opus, Haiku 4.5). Works for Anthropic direct, Bedrock, and
|
|
1148
|
-
* Pensar provider IDs.
|
|
1149
|
-
*/
|
|
1150
1202
|
export function modelSupportsThinking(modelId: string): boolean {
|
|
1151
|
-
|
|
1152
|
-
// Normalize: strip provider prefixes so we match the base Claude model ID
|
|
1153
|
-
const normalized = modelId
|
|
1154
|
-
.replace(/^pensar:/, "")
|
|
1155
|
-
.replace(/^(us\.|eu\.|global\.|ap\.)?anthropic\./, "");
|
|
1156
|
-
|
|
1203
|
+
const cap = getReasoningCapabilities(modelId);
|
|
1157
1204
|
return (
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
/^claude-opus-4/.test(normalized) ||
|
|
1161
|
-
/^claude-haiku-4-5/.test(normalized)
|
|
1205
|
+
cap.control !== "none" &&
|
|
1206
|
+
(!!cap.thinking || modelId.startsWith("anthropic/claude-"))
|
|
1162
1207
|
);
|
|
1163
1208
|
}
|
|
1164
1209
|
|
|
1165
|
-
/**
|
|
1166
|
-
* Whether a model accepts the `adaptive` thinking type — Claude Opus 4.6+ and
|
|
1167
|
-
* Sonnet 4.6+. Pre-4.6 models (Opus 4.0–4.5, Sonnet 4.5, Haiku 4.5) support
|
|
1168
|
-
* extended thinking but reject `adaptive`, so we don't request thinking for
|
|
1169
|
-
* them at all.
|
|
1170
|
-
*/
|
|
1171
1210
|
export function modelSupportsAdaptiveThinking(modelId: string): boolean {
|
|
1172
|
-
|
|
1173
|
-
const normalized = modelId
|
|
1174
|
-
.replace(/^pensar:/, "")
|
|
1175
|
-
.replace(/^(us\.|eu\.|global\.|ap\.)?anthropic\./, "");
|
|
1176
|
-
|
|
1177
|
-
return (
|
|
1178
|
-
/^claude-sonnet-4-[6-9]/.test(normalized) ||
|
|
1179
|
-
/^claude-opus-4-[6-9]/.test(normalized)
|
|
1180
|
-
);
|
|
1211
|
+
return getReasoningCapabilities(modelId).thinking === "adaptive";
|
|
1181
1212
|
}
|
|
1182
1213
|
|
|
1183
1214
|
export function modelSupportsOpenAIReasoning(modelId: string): boolean {
|
|
1184
|
-
|
|
1185
|
-
const { provider } = getModelInfo(modelId);
|
|
1186
|
-
if (!["openai", "openrouter", "concentrate"].includes(provider)) return false;
|
|
1187
|
-
modelId = modelId.replace(/^(openai\/|concentrate:)/, "");
|
|
1215
|
+
const cap = getReasoningCapabilities(modelId);
|
|
1188
1216
|
return (
|
|
1189
|
-
|
|
1217
|
+
cap.control === "effort" &&
|
|
1218
|
+
!modelSupportsThinking(modelId) &&
|
|
1219
|
+
cap.transport !== "google"
|
|
1190
1220
|
);
|
|
1191
1221
|
}
|
|
1192
1222
|
|
|
@@ -1197,99 +1227,41 @@ export function modelRequiresReasoning(modelId: string): boolean {
|
|
|
1197
1227
|
export function getOpenAIReasoningEfforts(
|
|
1198
1228
|
modelId: string,
|
|
1199
1229
|
): OpenAIReasoningEffort[] {
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
return ["none", "low", "medium", "high"];
|
|
1206
|
-
}
|
|
1207
|
-
modelId = modelId.replace(/^(openai\/|concentrate:)/, "");
|
|
1208
|
-
if (modelId === "gpt-6-sol" || modelId === "gpt-6-luna") {
|
|
1209
|
-
return ["none", "low", "medium", "high", "xhigh", "max"];
|
|
1210
|
-
}
|
|
1211
|
-
if (/^gpt-6[.-]/.test(modelId)) {
|
|
1212
|
-
return ["low", "medium", "high", "xhigh", "max"];
|
|
1213
|
-
}
|
|
1214
|
-
if (/^gpt-5\.5-pro(?:-|$)/.test(modelId)) {
|
|
1215
|
-
return ["medium", "high", "xhigh"];
|
|
1216
|
-
}
|
|
1217
|
-
if (/^gpt-5\.4-(?:mini|nano)(?:-|$)/.test(modelId)) {
|
|
1218
|
-
return ["none", "low", "medium", "high", "xhigh"];
|
|
1219
|
-
}
|
|
1220
|
-
if (/^gpt-5\.6(?:\b|-)/.test(modelId)) {
|
|
1221
|
-
return ["low", "medium", "high", "xhigh", "max", "ultra"];
|
|
1222
|
-
}
|
|
1223
|
-
if (/^gpt-5\.5(?:\b|-)/.test(modelId)) {
|
|
1224
|
-
return ["none", "low", "medium", "high", "xhigh"];
|
|
1225
|
-
}
|
|
1226
|
-
return ["low", "medium", "high"];
|
|
1230
|
+
return modelSupportsOpenAIReasoning(modelId)
|
|
1231
|
+
? ([
|
|
1232
|
+
...getReasoningCapabilities(modelId).efforts,
|
|
1233
|
+
] as OpenAIReasoningEffort[])
|
|
1234
|
+
: [];
|
|
1227
1235
|
}
|
|
1228
1236
|
|
|
1229
1237
|
export function normalizeOpenAIReasoningEffort(
|
|
1230
1238
|
modelId: string,
|
|
1231
1239
|
effort?: OpenAIReasoningEffort | null,
|
|
1232
1240
|
): OpenAIReasoningEffort | undefined {
|
|
1233
|
-
if (modelId
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1241
|
+
if (!modelSupportsOpenAIReasoning(modelId)) return undefined;
|
|
1242
|
+
const setting = resolveReasoningSetting(modelId, {
|
|
1243
|
+
openAIReasoningEffort: effort,
|
|
1244
|
+
});
|
|
1245
|
+
return setting === "default"
|
|
1246
|
+
? undefined
|
|
1247
|
+
: (setting as OpenAIReasoningEffort | undefined);
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
export type { ReasoningProviderOptions } from "./reasoning";
|
|
1251
|
+
|
|
1252
|
+
export function mergeProviderOptions(
|
|
1253
|
+
...options: Array<ReasoningProviderOptions | undefined>
|
|
1254
|
+
): ReasoningProviderOptions | undefined {
|
|
1255
|
+
if (options.every((value) => value === undefined)) return undefined;
|
|
1256
|
+
const merged: ReasoningProviderOptions = {};
|
|
1257
|
+
for (const option of options) {
|
|
1258
|
+
for (const [provider, value] of Object.entries(option ?? {})) {
|
|
1259
|
+
merged[provider] = { ...merged[provider], ...value };
|
|
1247
1260
|
}
|
|
1248
1261
|
}
|
|
1249
|
-
|
|
1250
|
-
if (efforts.length === 0) return undefined;
|
|
1251
|
-
if (effort && efforts.includes(effort)) {
|
|
1252
|
-
// ponytail: OpenAI has no distinct ultra level; keep the UI choice as a max alias.
|
|
1253
|
-
return effort === "ultra" ? "max" : effort;
|
|
1254
|
-
}
|
|
1255
|
-
return DEFAULT_OPENAI_REASONING_EFFORT;
|
|
1262
|
+
return merged;
|
|
1256
1263
|
}
|
|
1257
1264
|
|
|
1258
|
-
/**
|
|
1259
|
-
* Provider-specific options passed to `streamText` to request reasoning /
|
|
1260
|
-
* extended thinking. Each provider reads only its own namespace:
|
|
1261
|
-
* - `anthropic.thinking` — direct Anthropic provider AND the Pensar gateway
|
|
1262
|
-
* (the gateway formatter maps it to the Bedrock `thinking` field).
|
|
1263
|
-
* - `bedrock.reasoningConfig` — the AWS Bedrock provider; it ignores the
|
|
1264
|
-
* `anthropic` namespace entirely, so Anthropic-on-Bedrock thinking is only
|
|
1265
|
-
* requested when this key is present. `display: 'summarized'` makes the
|
|
1266
|
-
* model actually return reasoning text (adaptive can otherwise omit it).
|
|
1267
|
-
* - `openai.reasoningEffort` — OpenAI/o-series reasoning models.
|
|
1268
|
-
*/
|
|
1269
|
-
export type ReasoningProviderOptions = {
|
|
1270
|
-
openrouter?: {
|
|
1271
|
-
reasoning: { effort: OpenAIReasoningEffort; enabled?: boolean };
|
|
1272
|
-
};
|
|
1273
|
-
anthropic?: {
|
|
1274
|
-
thinking:
|
|
1275
|
-
| { type: "adaptive"; display?: "summarized" }
|
|
1276
|
-
| { type: "disabled" };
|
|
1277
|
-
// Soft effort hint for adaptive thinking; omitted when no level requested
|
|
1278
|
-
// (model defaults to "high"). Sibling of `thinking` per the AI SDK.
|
|
1279
|
-
effort?: ThinkingEffort;
|
|
1280
|
-
};
|
|
1281
|
-
bedrock?: {
|
|
1282
|
-
reasoningConfig: {
|
|
1283
|
-
type: "adaptive";
|
|
1284
|
-
display: "summarized";
|
|
1285
|
-
// Bedrock's channel for the adaptive effort hint (maps to Claude's
|
|
1286
|
-
// output_config.effort). Omitted when no level requested.
|
|
1287
|
-
maxReasoningEffort?: ThinkingEffort;
|
|
1288
|
-
};
|
|
1289
|
-
};
|
|
1290
|
-
openai?: OpenAIResponsesProviderOptions;
|
|
1291
|
-
};
|
|
1292
|
-
|
|
1293
1265
|
export type OpenRouterProviderOptions = {
|
|
1294
1266
|
openrouter?: {
|
|
1295
1267
|
provider:
|
|
@@ -1344,99 +1316,21 @@ export function buildOpenRouterStructuredProviderOptions(
|
|
|
1344
1316
|
};
|
|
1345
1317
|
}
|
|
1346
1318
|
|
|
1347
|
-
/**
|
|
1348
|
-
* Build the `providerOptions` for a request based on the model and reasoning
|
|
1349
|
-
* settings. Returns `undefined` when no reasoning/thinking is requested.
|
|
1350
|
-
*
|
|
1351
|
-
* When thinking is enabled for an Anthropic-family model we set BOTH the
|
|
1352
|
-
* `anthropic` and `bedrock` keys: the resolved provider (direct Anthropic,
|
|
1353
|
-
* Pensar gateway, or Bedrock) reads only its own namespace and ignores the
|
|
1354
|
-
* other, so this is safe across all three and avoids brittle provider
|
|
1355
|
-
* branching here.
|
|
1356
|
-
*/
|
|
1357
1319
|
export function buildReasoningProviderOptions(
|
|
1358
1320
|
model: AIModel,
|
|
1359
1321
|
opts: {
|
|
1322
|
+
reasoning?: ReasoningSetting;
|
|
1360
1323
|
enableThinking?: boolean;
|
|
1361
|
-
/**
|
|
1362
|
-
* Adaptive-thinking effort hint for Anthropic models that support it
|
|
1363
|
-
* (Opus/Sonnet 4.6+). Ignored on models without adaptive support. When
|
|
1364
|
-
* omitted the model uses its own default (`high`).
|
|
1365
|
-
*/
|
|
1366
1324
|
thinkingEffort?: ThinkingEffort | null;
|
|
1367
1325
|
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
1326
|
+
customProviders?: import("../config/customProviders").CustomProviders;
|
|
1327
|
+
maxOutputTokens?: number;
|
|
1368
1328
|
},
|
|
1369
1329
|
): ReasoningProviderOptions | undefined {
|
|
1370
|
-
const
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
if (provider === "openrouter") {
|
|
1375
|
-
return {
|
|
1376
|
-
openrouter: {
|
|
1377
|
-
reasoning: {
|
|
1378
|
-
effort: thinking ? (opts.thinkingEffort ?? "high") : "none",
|
|
1379
|
-
enabled: thinking,
|
|
1380
|
-
},
|
|
1381
|
-
},
|
|
1382
|
-
};
|
|
1383
|
-
}
|
|
1384
|
-
if (provider === "concentrate") {
|
|
1385
|
-
return {
|
|
1386
|
-
openai: {
|
|
1387
|
-
forceReasoning: true,
|
|
1388
|
-
reasoningEffort: thinking ? (opts.thinkingEffort ?? "high") : "none",
|
|
1389
|
-
reasoningSummary: "auto",
|
|
1390
|
-
},
|
|
1391
|
-
};
|
|
1392
|
-
}
|
|
1393
|
-
return {
|
|
1394
|
-
anthropic: {
|
|
1395
|
-
thinking:
|
|
1396
|
-
opts.enableThinking || claude.alwaysOnThinking
|
|
1397
|
-
? { type: "adaptive", display: "summarized" }
|
|
1398
|
-
: { type: "disabled" },
|
|
1399
|
-
...(opts.thinkingEffort ? { effort: opts.thinkingEffort } : {}),
|
|
1400
|
-
},
|
|
1401
|
-
};
|
|
1402
|
-
}
|
|
1403
|
-
const useThinking =
|
|
1404
|
-
!!opts.enableThinking &&
|
|
1405
|
-
isAnthropicProvider(model) &&
|
|
1406
|
-
modelSupportsAdaptiveThinking(model);
|
|
1407
|
-
const normalizedOpenAIEffort = normalizeOpenAIReasoningEffort(
|
|
1408
|
-
model,
|
|
1409
|
-
opts.openAIReasoningEffort,
|
|
1410
|
-
);
|
|
1411
|
-
// The effort hint only rides along when adaptive thinking is actually used.
|
|
1412
|
-
const effort = useThinking ? (opts.thinkingEffort ?? undefined) : undefined;
|
|
1413
|
-
|
|
1414
|
-
if (!useThinking && !normalizedOpenAIEffort) return undefined;
|
|
1415
|
-
|
|
1416
|
-
if (getModelInfo(model).provider === "openrouter" && normalizedOpenAIEffort) {
|
|
1417
|
-
return { openrouter: { reasoning: { effort: normalizedOpenAIEffort } } };
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
return {
|
|
1421
|
-
...(useThinking
|
|
1422
|
-
? {
|
|
1423
|
-
anthropic: {
|
|
1424
|
-
thinking: { type: "adaptive" as const },
|
|
1425
|
-
...(effort ? { effort } : {}),
|
|
1426
|
-
},
|
|
1427
|
-
bedrock: {
|
|
1428
|
-
reasoningConfig: {
|
|
1429
|
-
type: "adaptive" as const,
|
|
1430
|
-
display: "summarized" as const,
|
|
1431
|
-
...(effort ? { maxReasoningEffort: effort } : {}),
|
|
1432
|
-
},
|
|
1433
|
-
},
|
|
1434
|
-
}
|
|
1435
|
-
: {}),
|
|
1436
|
-
...(normalizedOpenAIEffort
|
|
1437
|
-
? { openai: { reasoningEffort: normalizedOpenAIEffort } }
|
|
1438
|
-
: {}),
|
|
1439
|
-
};
|
|
1330
|
+
const setting = resolveReasoningSetting(model, opts);
|
|
1331
|
+
return setting === undefined
|
|
1332
|
+
? undefined
|
|
1333
|
+
: buildModelReasoningOptions(model, setting, opts);
|
|
1440
1334
|
}
|
|
1441
1335
|
|
|
1442
1336
|
/** Cache token metrics extracted from Anthropic providerMetadata */
|
|
@@ -1446,6 +1340,12 @@ export interface CacheMetrics {
|
|
|
1446
1340
|
}
|
|
1447
1341
|
|
|
1448
1342
|
export interface StreamResponseOpts {
|
|
1343
|
+
/** Disables model repair and general recovery; compaction requires explicit admission. */
|
|
1344
|
+
primaryModelOnly?: boolean;
|
|
1345
|
+
runContextCompaction?: <T>(work: () => Promise<T>) => Promise<T>;
|
|
1346
|
+
/** Session-local working state restored after compaction. */
|
|
1347
|
+
getContinuationContext?: () => string;
|
|
1348
|
+
onInvalidToolCall?: (name: string) => void;
|
|
1449
1349
|
prompt: string;
|
|
1450
1350
|
system?: string;
|
|
1451
1351
|
model: AIModel;
|
|
@@ -1474,6 +1374,11 @@ export interface StreamResponseOpts {
|
|
|
1474
1374
|
* new messages (not the full pre-summarization history).
|
|
1475
1375
|
*/
|
|
1476
1376
|
onSummarized?: (summary: string) => void;
|
|
1377
|
+
/** The fitted context and prior generated-message count for transcript writers. */
|
|
1378
|
+
onContextPrepared?: (context: {
|
|
1379
|
+
messages: ModelMessage[];
|
|
1380
|
+
responseMessageOffset: number;
|
|
1381
|
+
}) => void;
|
|
1477
1382
|
/**
|
|
1478
1383
|
* Deprecated host shim: fires only when a cache counter is `> 0`.
|
|
1479
1384
|
* Apex internals read cache from {@link normalizeStepUsage} on the step.
|
|
@@ -1488,6 +1393,7 @@ export interface StreamResponseOpts {
|
|
|
1488
1393
|
thinkingEffort?: ThinkingEffort | null;
|
|
1489
1394
|
/** OpenAI reasoning effort for GPT/o-series reasoning models. */
|
|
1490
1395
|
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
1396
|
+
reasoning?: ReasoningSetting;
|
|
1491
1397
|
/** Session root path — used by context management layers to persist truncated tool results */
|
|
1492
1398
|
sessionPath?: string;
|
|
1493
1399
|
/** Session id (`ses_…`) of the agent making this call; stamped onto AI-span telemetry so traces are filterable by session. */
|
|
@@ -1506,12 +1412,15 @@ export interface StreamResponseOpts {
|
|
|
1506
1412
|
/** Shared only by continuations of this stream, never across agents. */
|
|
1507
1413
|
_compaction?: { last?: CompactionLink };
|
|
1508
1414
|
_compactionTrigger?: CompactionTrigger;
|
|
1415
|
+
_proactiveSummaryMayFit?: boolean;
|
|
1416
|
+
_proactiveSummaryFailures?: number;
|
|
1417
|
+
_initialPrompt?: string;
|
|
1509
1418
|
}
|
|
1510
1419
|
|
|
1511
1420
|
const NATIVE_STREAM_RECOVERY = Symbol("native-stream-recovery");
|
|
1512
1421
|
|
|
1513
1422
|
interface NativeStreamRecovery {
|
|
1514
|
-
model:
|
|
1423
|
+
model: ReturnType<typeof getProviderModel>;
|
|
1515
1424
|
run<T>(fn: () => T): T;
|
|
1516
1425
|
}
|
|
1517
1426
|
|
|
@@ -1545,6 +1454,7 @@ function streamResponseWithinOperation(
|
|
|
1545
1454
|
// map. Re-entry is identity (`activeTools` already consumed).
|
|
1546
1455
|
opts = {
|
|
1547
1456
|
...opts,
|
|
1457
|
+
_initialPrompt: opts._initialPrompt ?? opts.prompt,
|
|
1548
1458
|
_compaction: compactionState,
|
|
1549
1459
|
// `activeTools` is authoritative for advertisement and execution: a tool
|
|
1550
1460
|
// (including `response`) is exposed only when the caller lists it, so the
|
|
@@ -1580,14 +1490,21 @@ function streamResponseWithinOperation(
|
|
|
1580
1490
|
enableThinking,
|
|
1581
1491
|
thinkingEffort,
|
|
1582
1492
|
openAIReasoningEffort,
|
|
1493
|
+
reasoning,
|
|
1583
1494
|
sessionId,
|
|
1495
|
+
sessionPath,
|
|
1584
1496
|
contextRecorder,
|
|
1497
|
+
onContextPrepared,
|
|
1585
1498
|
} = opts;
|
|
1586
1499
|
|
|
1587
|
-
//
|
|
1588
|
-
//
|
|
1589
|
-
//
|
|
1500
|
+
// response.messages accumulates generated steps after prepareStep rewrites
|
|
1501
|
+
// provider context. The offset prevents transcript writers from appending
|
|
1502
|
+
// older, pre-fit messages again.
|
|
1590
1503
|
let recorderBase: ModelMessage[] | undefined;
|
|
1504
|
+
let responseMessageLength = 0;
|
|
1505
|
+
const estimatedOverheadTokens = estimateToolsOverheadTokens(tools) + 1_000;
|
|
1506
|
+
let preparedInputEstimateTokens = 0;
|
|
1507
|
+
let inputSafetyMarginTokens = 10_000;
|
|
1591
1508
|
|
|
1592
1509
|
// Wrap onStepFinish to fire cache metrics and the usage callback for every
|
|
1593
1510
|
// step. Must be async so that callers returning a Promise (persistence,
|
|
@@ -1596,6 +1513,18 @@ function streamResponseWithinOperation(
|
|
|
1596
1513
|
// provider metadata is never parsed twice.
|
|
1597
1514
|
const onStepFinish: typeof userOnStepFinish = async (step) => {
|
|
1598
1515
|
const stepUsage = normalizeStepUsage(step);
|
|
1516
|
+
if (
|
|
1517
|
+
preparedInputEstimateTokens > 0 &&
|
|
1518
|
+
stepUsage.inputTokens > 0 &&
|
|
1519
|
+
step.response?.id !== "summarization" &&
|
|
1520
|
+
step.response?.id !== "tool-repair"
|
|
1521
|
+
) {
|
|
1522
|
+
// Fixed system and tool overhead is already reserved by the fitter; calibrate only the remaining tokenization gap.
|
|
1523
|
+
inputSafetyMarginTokens = Math.max(
|
|
1524
|
+
inputSafetyMarginTokens,
|
|
1525
|
+
stepUsage.inputTokens - preparedInputEstimateTokens + 10_000,
|
|
1526
|
+
);
|
|
1527
|
+
}
|
|
1599
1528
|
// Canonical commit precedes every downstream use; the recorder latches
|
|
1600
1529
|
// rejections (SDK notify() swallows them) until the next turn gate or
|
|
1601
1530
|
// agent-side flush turns the latch into a stream failure.
|
|
@@ -1611,10 +1540,20 @@ function streamResponseWithinOperation(
|
|
|
1611
1540
|
throw new Error("context recorder active without a committed base");
|
|
1612
1541
|
}
|
|
1613
1542
|
await contextRecorder.checkpoint({
|
|
1614
|
-
messages: [
|
|
1543
|
+
messages: [
|
|
1544
|
+
...recorderBase,
|
|
1545
|
+
...step.response.messages.slice(responseMessageLength),
|
|
1546
|
+
],
|
|
1615
1547
|
system: effectiveSystem ?? null,
|
|
1616
1548
|
});
|
|
1617
1549
|
}
|
|
1550
|
+
if (
|
|
1551
|
+
step.response?.id !== "summarization" &&
|
|
1552
|
+
step.response?.id !== "tool-repair" &&
|
|
1553
|
+
step.response?.messages
|
|
1554
|
+
) {
|
|
1555
|
+
responseMessageLength = step.response.messages.length;
|
|
1556
|
+
}
|
|
1618
1557
|
if (
|
|
1619
1558
|
onCacheMetrics &&
|
|
1620
1559
|
(stepUsage.cacheReadTokens > 0 || stepUsage.cacheWriteTokens > 0)
|
|
@@ -1661,22 +1600,55 @@ function streamResponseWithinOperation(
|
|
|
1661
1600
|
model,
|
|
1662
1601
|
);
|
|
1663
1602
|
|
|
1603
|
+
const contextWindow = getContextWindow(
|
|
1604
|
+
model,
|
|
1605
|
+
authConfig?.customProviders,
|
|
1606
|
+
authConfig?.hoonifyModels,
|
|
1607
|
+
);
|
|
1608
|
+
const maxOutputTokens = getMaxOutputTokens(
|
|
1609
|
+
model,
|
|
1610
|
+
authConfig?.customProviders,
|
|
1611
|
+
authConfig?.hoonifyModels,
|
|
1612
|
+
);
|
|
1613
|
+
if (
|
|
1614
|
+
messages &&
|
|
1615
|
+
(!opts.primaryModelOnly || opts.runContextCompaction) &&
|
|
1616
|
+
!opts._proactiveSummaryFailures &&
|
|
1617
|
+
shouldSummarizeBeforeFitting(
|
|
1618
|
+
messages,
|
|
1619
|
+
contextWindow,
|
|
1620
|
+
maxOutputTokens,
|
|
1621
|
+
estimatedOverheadTokens,
|
|
1622
|
+
inputSafetyMarginTokens,
|
|
1623
|
+
systemWithToolPolicy,
|
|
1624
|
+
toolChoice,
|
|
1625
|
+
)
|
|
1626
|
+
) {
|
|
1627
|
+
return wrapStreamWithErrorHandler(
|
|
1628
|
+
createSummarizationStream(
|
|
1629
|
+
messages,
|
|
1630
|
+
{
|
|
1631
|
+
...opts,
|
|
1632
|
+
_compactionTrigger: "proactive",
|
|
1633
|
+
_proactiveSummaryMayFit: true,
|
|
1634
|
+
},
|
|
1635
|
+
providerModel,
|
|
1636
|
+
),
|
|
1637
|
+
{ current: messages },
|
|
1638
|
+
opts,
|
|
1639
|
+
providerModel,
|
|
1640
|
+
silent,
|
|
1641
|
+
);
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1664
1644
|
// Proactive context fit: compact before the call. Reactive recovery
|
|
1665
1645
|
// below is a safety net for tokenizer drift the estimate doesn't catch.
|
|
1666
1646
|
let fittedMessages = messages;
|
|
1667
1647
|
let proactiveFitFailed = false;
|
|
1668
1648
|
if (messages && messages.length > 0) {
|
|
1669
1649
|
const fitted = fitMessagesToContext(messages, {
|
|
1670
|
-
contextWindow
|
|
1671
|
-
|
|
1672
|
-
authConfig?.customProviders,
|
|
1673
|
-
authConfig?.hoonifyModels,
|
|
1674
|
-
),
|
|
1675
|
-
maxOutputTokens: getMaxOutputTokens(
|
|
1676
|
-
model,
|
|
1677
|
-
authConfig?.customProviders,
|
|
1678
|
-
authConfig?.hoonifyModels,
|
|
1679
|
-
),
|
|
1650
|
+
contextWindow,
|
|
1651
|
+
maxOutputTokens,
|
|
1680
1652
|
system: systemWithToolPolicy,
|
|
1681
1653
|
tools,
|
|
1682
1654
|
sessionPath: opts.sessionPath,
|
|
@@ -1707,6 +1679,8 @@ function streamResponseWithinOperation(
|
|
|
1707
1679
|
// an overflow inside the summarization call itself escapes uncaught while
|
|
1708
1680
|
// the equivalent post-streamText path (line ~880) recovers.
|
|
1709
1681
|
if (proactiveFitFailed && fittedMessages) {
|
|
1682
|
+
if (opts.primaryModelOnly && !opts.runContextCompaction)
|
|
1683
|
+
throw new Error("Lance context budget exhausted");
|
|
1710
1684
|
if (!silent) {
|
|
1711
1685
|
log.warn(
|
|
1712
1686
|
`Proactive context fit returned fitsBudget=false on ${fittedMessages.length} messages — escalating to summarization before send`,
|
|
@@ -1723,7 +1697,11 @@ function streamResponseWithinOperation(
|
|
|
1723
1697
|
return wrapStreamWithErrorHandler(
|
|
1724
1698
|
createSummarizationStream(
|
|
1725
1699
|
fittedMessages,
|
|
1726
|
-
{
|
|
1700
|
+
{
|
|
1701
|
+
...opts,
|
|
1702
|
+
_compactionTrigger: "proactive",
|
|
1703
|
+
_proactiveSummaryMayFit: false,
|
|
1704
|
+
},
|
|
1727
1705
|
providerModel,
|
|
1728
1706
|
),
|
|
1729
1707
|
messagesContainer,
|
|
@@ -1760,12 +1738,15 @@ function streamResponseWithinOperation(
|
|
|
1760
1738
|
enableThinking,
|
|
1761
1739
|
thinkingEffort,
|
|
1762
1740
|
openAIReasoningEffort,
|
|
1741
|
+
reasoning,
|
|
1742
|
+
customProviders: authConfig?.customProviders,
|
|
1743
|
+
maxOutputTokens,
|
|
1763
1744
|
});
|
|
1764
1745
|
const openRouterProviderOptions = buildOpenRouterProviderOptions(model);
|
|
1765
|
-
const providerOptions =
|
|
1766
|
-
reasoningProviderOptions
|
|
1767
|
-
|
|
1768
|
-
|
|
1746
|
+
const providerOptions = mergeProviderOptions(
|
|
1747
|
+
reasoningProviderOptions,
|
|
1748
|
+
openRouterProviderOptions,
|
|
1749
|
+
);
|
|
1769
1750
|
|
|
1770
1751
|
let rateLimitRetryCount = 0;
|
|
1771
1752
|
|
|
@@ -1781,8 +1762,81 @@ function streamResponseWithinOperation(
|
|
|
1781
1762
|
// Create the appropriate provider instance. The span tracker captures
|
|
1782
1763
|
// the SDK's root generation span for error marking (see below).
|
|
1783
1764
|
const generationSpans = createGenerationSpanTracker();
|
|
1784
|
-
const
|
|
1765
|
+
const attemptAbort = new AbortController();
|
|
1766
|
+
const attemptSignal = abortSignal
|
|
1767
|
+
? AbortSignal.any([abortSignal, attemptAbort.signal])
|
|
1768
|
+
: attemptAbort.signal;
|
|
1769
|
+
let cancelModelStream: ((reason: unknown) => Promise<void>) | undefined;
|
|
1770
|
+
// Cancelling the SDK fullStream only detaches its subscriber.
|
|
1771
|
+
const attemptModel = wrapLanguageModel({
|
|
1785
1772
|
model: providerModel,
|
|
1773
|
+
middleware: {
|
|
1774
|
+
specificationVersion: "v3",
|
|
1775
|
+
wrapStream: async ({ doStream }) => {
|
|
1776
|
+
const pending = doStream();
|
|
1777
|
+
let reader:
|
|
1778
|
+
| ReadableStreamDefaultReader<LanguageModelV3StreamPart>
|
|
1779
|
+
| undefined;
|
|
1780
|
+
cancelModelStream = async (reason) => {
|
|
1781
|
+
try {
|
|
1782
|
+
const source = await pending;
|
|
1783
|
+
await (reader
|
|
1784
|
+
? reader.cancel(reason)
|
|
1785
|
+
: source.stream.cancel(reason));
|
|
1786
|
+
} catch (error) {
|
|
1787
|
+
if (
|
|
1788
|
+
!(error instanceof Error) ||
|
|
1789
|
+
(error.name !== "AbortError" &&
|
|
1790
|
+
!isStreamIdleTimeoutError(error))
|
|
1791
|
+
) {
|
|
1792
|
+
throw error;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
const source = await pending;
|
|
1797
|
+
reader = source.stream.getReader();
|
|
1798
|
+
const ownedReader = reader;
|
|
1799
|
+
return {
|
|
1800
|
+
...source,
|
|
1801
|
+
stream: new ReadableStream({
|
|
1802
|
+
async pull(controller) {
|
|
1803
|
+
const next = await ownedReader.read();
|
|
1804
|
+
if (next.done) controller.close();
|
|
1805
|
+
else controller.enqueue(next.value);
|
|
1806
|
+
},
|
|
1807
|
+
cancel: (reason) => ownedReader.cancel(reason),
|
|
1808
|
+
}),
|
|
1809
|
+
};
|
|
1810
|
+
},
|
|
1811
|
+
},
|
|
1812
|
+
});
|
|
1813
|
+
const drainIdleStream = async (reason: unknown) => {
|
|
1814
|
+
attemptAbort.abort(reason);
|
|
1815
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
1816
|
+
try {
|
|
1817
|
+
await Promise.race([
|
|
1818
|
+
cancelModelStream?.(reason),
|
|
1819
|
+
new Promise<never>((_, reject) => {
|
|
1820
|
+
timer = setTimeout(
|
|
1821
|
+
() =>
|
|
1822
|
+
reject(
|
|
1823
|
+
Object.assign(
|
|
1824
|
+
new Error(
|
|
1825
|
+
"Stalled model stream did not drain within 30 seconds",
|
|
1826
|
+
),
|
|
1827
|
+
{ name: "ModelStreamDrainTimeoutError" },
|
|
1828
|
+
),
|
|
1829
|
+
),
|
|
1830
|
+
30_000,
|
|
1831
|
+
);
|
|
1832
|
+
}),
|
|
1833
|
+
]);
|
|
1834
|
+
} finally {
|
|
1835
|
+
clearTimeout(timer);
|
|
1836
|
+
}
|
|
1837
|
+
};
|
|
1838
|
+
const responseOptions: Parameters<typeof streamText>[0] = {
|
|
1839
|
+
model: attemptModel,
|
|
1786
1840
|
system: effectiveSystem,
|
|
1787
1841
|
...(effectiveMessages ? { messages: effectiveMessages } : { prompt }),
|
|
1788
1842
|
stopWhen,
|
|
@@ -1802,6 +1856,10 @@ function streamResponseWithinOperation(
|
|
|
1802
1856
|
operation: "apex.agent.stream",
|
|
1803
1857
|
sessionId,
|
|
1804
1858
|
compaction: opts._compaction?.last,
|
|
1859
|
+
reasoning: {
|
|
1860
|
+
requested: reasoning ?? "legacy-default",
|
|
1861
|
+
parameters: JSON.stringify(reasoningProviderOptions ?? {}),
|
|
1862
|
+
},
|
|
1805
1863
|
}),
|
|
1806
1864
|
tracer: generationSpans.tracer,
|
|
1807
1865
|
},
|
|
@@ -1818,30 +1876,86 @@ function streamResponseWithinOperation(
|
|
|
1818
1876
|
// Awaiting inside prepareStep keeps streamResponse synchronous; the
|
|
1819
1877
|
// SDK awaits it before provider dispatch, so every turn and every
|
|
1820
1878
|
// recovery re-entry commits before use.
|
|
1821
|
-
prepareStep: async (
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1879
|
+
prepareStep: async (step) => {
|
|
1880
|
+
let stepMessages = step.messages;
|
|
1881
|
+
if (step.stepNumber > 0) {
|
|
1882
|
+
if (
|
|
1883
|
+
(!opts.primaryModelOnly || opts.runContextCompaction) &&
|
|
1884
|
+
(opts._proactiveSummaryFailures ?? 0) <
|
|
1885
|
+
MAX_PROACTIVE_SUMMARY_FAILURES &&
|
|
1886
|
+
shouldSummarizeBeforeFitting(
|
|
1887
|
+
stepMessages,
|
|
1888
|
+
contextWindow,
|
|
1889
|
+
maxOutputTokens,
|
|
1890
|
+
estimatedOverheadTokens,
|
|
1891
|
+
inputSafetyMarginTokens,
|
|
1892
|
+
effectiveSystem,
|
|
1893
|
+
toolChoice,
|
|
1894
|
+
)
|
|
1895
|
+
) {
|
|
1896
|
+
messagesContainer.current = stepMessages;
|
|
1897
|
+
throw new InStreamCompactionRequired({
|
|
1898
|
+
messages: stepMessages,
|
|
1899
|
+
estimatedInputTokens: estimateMessageTokens(stepMessages),
|
|
1900
|
+
modified: false,
|
|
1901
|
+
fitsBudget: true,
|
|
1902
|
+
});
|
|
1825
1903
|
}
|
|
1904
|
+
const fitted = fitMessagesToContext(stepMessages, {
|
|
1905
|
+
contextWindow,
|
|
1906
|
+
maxOutputTokens,
|
|
1907
|
+
system: effectiveSystem,
|
|
1908
|
+
tools,
|
|
1909
|
+
overheadTokens: estimatedOverheadTokens,
|
|
1910
|
+
sessionPath,
|
|
1911
|
+
safetyMarginTokens: inputSafetyMarginTokens,
|
|
1912
|
+
telemetry: {
|
|
1913
|
+
trigger: "proactive",
|
|
1914
|
+
model,
|
|
1915
|
+
sessionId,
|
|
1916
|
+
restartDepth,
|
|
1917
|
+
previous: compactionState.last,
|
|
1918
|
+
},
|
|
1919
|
+
});
|
|
1920
|
+
if (fitted.compaction) compactionState.last = fitted.compaction;
|
|
1921
|
+
stepMessages = fitted.messages;
|
|
1922
|
+
if (!fitted.fitsBudget) {
|
|
1923
|
+
messagesContainer.current = stepMessages;
|
|
1924
|
+
throw new InStreamCompactionRequired(fitted);
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
if (contextRecorder) {
|
|
1928
|
+
recorderBase = structuredClone(stepMessages);
|
|
1826
1929
|
// Full logical context each turn — accepted step outputs must
|
|
1827
1930
|
// survive into every later commit, and system is explicit (when
|
|
1828
1931
|
// cached into messages, effectiveSystem is undefined → null).
|
|
1829
1932
|
await contextRecorder.checkpoint({
|
|
1830
|
-
messages:
|
|
1933
|
+
messages: stepMessages,
|
|
1831
1934
|
system: effectiveSystem ?? null,
|
|
1832
1935
|
});
|
|
1833
1936
|
}
|
|
1834
1937
|
// Update the container with the latest messages
|
|
1835
|
-
messagesContainer.current =
|
|
1938
|
+
messagesContainer.current = stepMessages;
|
|
1939
|
+
preparedInputEstimateTokens =
|
|
1940
|
+
estimateMessageTokens(stepMessages) +
|
|
1941
|
+
estimatedOverheadTokens +
|
|
1942
|
+
(effectiveSystem ? estimateTokens(effectiveSystem) : 0);
|
|
1943
|
+
onContextPrepared?.({
|
|
1944
|
+
messages: stepMessages,
|
|
1945
|
+
responseMessageOffset: responseMessageLength,
|
|
1946
|
+
});
|
|
1836
1947
|
// Mark the last message so the growing conversation caches incrementally
|
|
1837
1948
|
if (cacheBreakpoint) {
|
|
1838
1949
|
return {
|
|
1839
|
-
messages: withCachedLastMessage(
|
|
1950
|
+
messages: withCachedLastMessage(stepMessages, cacheBreakpoint),
|
|
1840
1951
|
};
|
|
1841
1952
|
}
|
|
1842
|
-
return
|
|
1953
|
+
return stepMessages === step.messages
|
|
1954
|
+
? undefined
|
|
1955
|
+
: { messages: stepMessages };
|
|
1843
1956
|
},
|
|
1844
1957
|
onError: async ({ error }: { error: unknown }) => {
|
|
1958
|
+
if (opts.primaryModelOnly) return;
|
|
1845
1959
|
// Never throw here: the SDK calls this inside its stream pipeline,
|
|
1846
1960
|
// and a thrown callback kills the pipeline's terminal lifecycle —
|
|
1847
1961
|
// the root generation span never ends and nothing exports. Return
|
|
@@ -1868,7 +1982,7 @@ function streamResponseWithinOperation(
|
|
|
1868
1982
|
}
|
|
1869
1983
|
},
|
|
1870
1984
|
onStepFinish,
|
|
1871
|
-
abortSignal,
|
|
1985
|
+
abortSignal: attemptSignal,
|
|
1872
1986
|
activeTools: allowedTools,
|
|
1873
1987
|
experimental_repairToolCall: async ({
|
|
1874
1988
|
toolCall,
|
|
@@ -1876,6 +1990,8 @@ function streamResponseWithinOperation(
|
|
|
1876
1990
|
tools,
|
|
1877
1991
|
error,
|
|
1878
1992
|
}) => {
|
|
1993
|
+
opts.onInvalidToolCall?.(toolCall.toolName);
|
|
1994
|
+
if (opts.primaryModelOnly) return null;
|
|
1879
1995
|
// [response-debug] Log when repair fires for `response` (streamed args failed Zod validation), bypassing `silent`.
|
|
1880
1996
|
if (RESPONSE_DEBUG && toolCall.toolName === RESPONSE_TOOL_NAME) {
|
|
1881
1997
|
const raw = toolCall.input;
|
|
@@ -1953,8 +2069,9 @@ function streamResponseWithinOperation(
|
|
|
1953
2069
|
() =>
|
|
1954
2070
|
generateText({
|
|
1955
2071
|
model: providerModel,
|
|
2072
|
+
maxOutputTokens,
|
|
1956
2073
|
providerOptions: {
|
|
1957
|
-
...
|
|
2074
|
+
...providerOptions,
|
|
1958
2075
|
// Durable runtime: tool-call repair fires only when a
|
|
1959
2076
|
// replayed tool call fails validation — nondeterministically
|
|
1960
2077
|
// vs the first run — so it must stay off the checkpoint
|
|
@@ -1982,6 +2099,10 @@ function streamResponseWithinOperation(
|
|
|
1982
2099
|
experimental_telemetry: createAiTelemetrySettings({
|
|
1983
2100
|
operation: "apex.tool.repair",
|
|
1984
2101
|
sessionId,
|
|
2102
|
+
reasoning: {
|
|
2103
|
+
requested: reasoning ?? "legacy-default",
|
|
2104
|
+
parameters: JSON.stringify(reasoningProviderOptions ?? {}),
|
|
2105
|
+
},
|
|
1985
2106
|
}),
|
|
1986
2107
|
}),
|
|
1987
2108
|
);
|
|
@@ -2081,10 +2202,16 @@ function streamResponseWithinOperation(
|
|
|
2081
2202
|
0,
|
|
2082
2203
|
0,
|
|
2083
2204
|
generationSpans,
|
|
2205
|
+
drainIdleStream,
|
|
2084
2206
|
);
|
|
2085
2207
|
} catch (error) {
|
|
2086
2208
|
// Check if the error is related to context length
|
|
2087
2209
|
const isContextLengthError = checkIfContextLengthError(error);
|
|
2210
|
+
if (
|
|
2211
|
+
opts.primaryModelOnly &&
|
|
2212
|
+
(!opts.runContextCompaction || !isContextLengthError)
|
|
2213
|
+
)
|
|
2214
|
+
throw error;
|
|
2088
2215
|
const outerErrorMessage =
|
|
2089
2216
|
error instanceof Error ? error.message : String(error);
|
|
2090
2217
|
|
|
@@ -2136,6 +2263,7 @@ export interface GenerateObjectOpts<T extends z.ZodType> {
|
|
|
2136
2263
|
maxTokens?: number;
|
|
2137
2264
|
temperature?: number;
|
|
2138
2265
|
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
2266
|
+
reasoning?: ReasoningSetting;
|
|
2139
2267
|
authConfig?: AIAuthConfig;
|
|
2140
2268
|
abortSignal?: AbortSignal;
|
|
2141
2269
|
onTokenUsage?: (inputTokens: number, outputTokens: number) => void;
|
|
@@ -2173,6 +2301,7 @@ async function generateObjectResponseWithinRecorder<T extends z.ZodType>(
|
|
|
2173
2301
|
maxTokens,
|
|
2174
2302
|
temperature,
|
|
2175
2303
|
openAIReasoningEffort,
|
|
2304
|
+
reasoning,
|
|
2176
2305
|
authConfig,
|
|
2177
2306
|
abortSignal,
|
|
2178
2307
|
onTokenUsage,
|
|
@@ -2197,6 +2326,9 @@ async function generateObjectResponseWithinRecorder<T extends z.ZodType>(
|
|
|
2197
2326
|
: baseProviderModel;
|
|
2198
2327
|
const reasoningProviderOptions = buildReasoningProviderOptions(model, {
|
|
2199
2328
|
openAIReasoningEffort,
|
|
2329
|
+
reasoning,
|
|
2330
|
+
customProviders: authConfig?.customProviders,
|
|
2331
|
+
maxOutputTokens: maxTokens,
|
|
2200
2332
|
});
|
|
2201
2333
|
const openRouterProviderOptions =
|
|
2202
2334
|
buildOpenRouterStructuredProviderOptions(model);
|
|
@@ -2224,25 +2356,19 @@ async function generateObjectResponseWithinRecorder<T extends z.ZodType>(
|
|
|
2224
2356
|
system,
|
|
2225
2357
|
maxOutputTokens: maxTokens,
|
|
2226
2358
|
temperature,
|
|
2227
|
-
providerOptions:
|
|
2228
|
-
reasoningProviderOptions
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
...(openRouterProviderOptions
|
|
2232
|
-
? {
|
|
2233
|
-
openrouter: {
|
|
2234
|
-
...reasoningProviderOptions?.openrouter,
|
|
2235
|
-
...openRouterProviderOptions.openrouter,
|
|
2236
|
-
},
|
|
2237
|
-
}
|
|
2238
|
-
: {}),
|
|
2239
|
-
}
|
|
2240
|
-
: undefined,
|
|
2359
|
+
providerOptions: mergeProviderOptions(
|
|
2360
|
+
reasoningProviderOptions,
|
|
2361
|
+
openRouterProviderOptions,
|
|
2362
|
+
),
|
|
2241
2363
|
maxRetries: 0,
|
|
2242
2364
|
abortSignal,
|
|
2243
2365
|
experimental_telemetry: createAiTelemetrySettings({
|
|
2244
2366
|
operation: opts.operation ?? "apex.structured.generate",
|
|
2245
2367
|
sessionId,
|
|
2368
|
+
reasoning: {
|
|
2369
|
+
requested: reasoning ?? "legacy-default",
|
|
2370
|
+
parameters: JSON.stringify(reasoningProviderOptions ?? {}),
|
|
2371
|
+
},
|
|
2246
2372
|
}),
|
|
2247
2373
|
});
|
|
2248
2374
|
|