@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.
Files changed (328) hide show
  1. package/build/{agent-ayreaj6z.js → agent-3g1b578v.js} +6 -5
  2. package/build/{agent-yby11zaq.js → agent-p8cezgbb.js} +7 -6
  3. package/build/{agent-runs-g37vkrjr.js → agent-runs-f86emmgg.js} +23 -20
  4. package/build/agent-vaq31je6.js +14 -0
  5. package/build/agent-vvdqga09.js +14 -0
  6. package/build/{apps-xn6km9yn.js → apps-3stwnmen.js} +16 -13
  7. package/build/{auth-d105wc64.js → auth-7md9kwda.js} +16 -13
  8. package/build/blackboxAgent-ct8bejef.js +14 -0
  9. package/build/{blackboxPentest-ps78v3w7.js → blackboxPentest-w2nr4md3.js} +21 -15
  10. package/build/{cli-c05y640n.js → cli-1j28cbhy.js} +1 -1
  11. package/build/{cli-d37a42dc.js → cli-2jz2jz06.js} +206 -90
  12. package/build/{cli-az3xq70v.js → cli-4a8dsz2k.js} +4 -4
  13. package/build/{cli-qgz1q9g5.js → cli-58781vcf.js} +1192 -1473
  14. package/build/{cli-gx71jcke.js → cli-7067zzeb.js} +1 -1
  15. package/build/{cli-3sp6nd8d.js → cli-81smmd5w.js} +5 -5
  16. package/build/{cli-k2nwxta0.js → cli-8b25dhky.js} +2 -2
  17. package/build/{cli-fy6vh2a7.js → cli-8sw5zpqz.js} +1 -1
  18. package/build/{cli-709rvekb.js → cli-cg3ypx5n.js} +14 -7
  19. package/build/{cli-dpsw2fe6.js → cli-e9v6zg6h.js} +40941 -40172
  20. package/build/cli-fjxmphg1.js +36 -0
  21. package/build/{cli-7eea4e2y.js → cli-gzb6qrzh.js} +31 -60
  22. package/build/{cli-65g6rcat.js → cli-khnf5xrf.js} +2 -1
  23. package/build/{cli-1ve18npr.js → cli-mdzt2e8j.js} +4 -2
  24. package/build/{cli-n2en7j5b.js → cli-n8mmw4c4.js} +1 -1
  25. package/build/cli-pndb7mh9.js +1193 -0
  26. package/build/cli-px6ehzqx.js +54 -0
  27. package/build/{cli-xtc2t6me.js → cli-qs4msn6x.js} +111 -47
  28. package/build/{cli-kb21qhvm.js → cli-rvybdhgn.js} +4 -3
  29. package/build/{cli-ae8jqxqr.js → cli-v739h7hb.js} +2 -2
  30. package/build/{cli-ngq9dr8n.js → cli-wm8ech0x.js} +3 -3
  31. package/build/cli.js +170 -51
  32. package/build/{config-zpqkd5cz.js → config-e5v1bkh1.js} +1 -1
  33. package/build/{fastStrike-mcjdvwez.js → fastStrike-efp0rjs3.js} +74 -17
  34. package/build/{fixes-kytx5dmj.js → fixes-926cw1ej.js} +16 -13
  35. package/build/{index-n65z6v7b.js → index-3t41p258.js} +7 -6
  36. package/build/{index-qv4cc65p.js → index-bv09af6g.js} +19 -15
  37. package/build/{index-je6hcsqr.js → index-bv6dtwse.js} +1 -1
  38. package/build/{index-4vqdgb42.js → index-jt52ffgn.js} +1657 -1400
  39. package/build/{index-ns4m4s01.js → index-np405b9e.js} +11 -7
  40. package/build/{index-r9yjkfrv.js → index-qys178kp.js} +5 -4
  41. package/build/{index-wqetp6gq.js → index-tpyzq2wq.js} +42 -11
  42. package/build/{index-fv64eb32.js → index-vrcdyebh.js} +2 -2
  43. package/build/{index-dr3tg1w3.js → index-z1g8vbtm.js} +1 -1
  44. package/build/{issues-eb3q9d3a.js → issues-sncyqh14.js} +16 -13
  45. package/build/{knowledge-fqsvtx0f.js → knowledge-esgvy5ws.js} +16 -13
  46. package/build/lance-sacfgs1z.js +232 -0
  47. package/build/lib/{chunk-9yksqgzr.js → chunk-4aevegnc.js} +77 -45
  48. package/build/lib/{chunk-9tt2021m.js → chunk-4kf4a15q.js} +13 -13
  49. package/build/lib/{chunk-fy3bbbqy.js → chunk-5avnedwm.js} +7 -1
  50. package/build/lib/{chunk-bb0ekhkw.js → chunk-5nz5tk3p.js} +76 -22
  51. package/build/lib/{chunk-4hwzqthr.js → chunk-7s8e5wrd.js} +3 -2
  52. package/build/lib/{chunk-yrnrbjes.js → chunk-85kpxwzs.js} +4 -2
  53. package/build/lib/{chunk-mg03jdmt.js → chunk-9jkzk9nc.js} +1 -1
  54. package/build/lib/{chunk-r4j8ybn9.js → chunk-9wwts6r6.js} +824 -77
  55. package/build/lib/{chunk-nhfax4gb.js → chunk-bxznzxdy.js} +5 -1
  56. package/build/lib/{chunk-r2dkp4tb.js → chunk-cqxm95md.js} +1 -1
  57. package/build/lib/{chunk-w66ce82a.js → chunk-e3agqspc.js} +12 -4
  58. package/build/lib/{chunk-ba41jh41.js → chunk-eh5yw385.js} +1137 -333
  59. package/build/lib/{chunk-1azdancq.js → chunk-ewc9r84m.js} +5 -1
  60. package/build/lib/{chunk-2njv7wz3.js → chunk-hbyxyxdc.js} +4 -0
  61. package/build/lib/{chunk-e8yy2k73.js → chunk-jhhwts6w.js} +28 -2
  62. package/build/lib/{chunk-1jvwqnem.js → chunk-kbxbd1kn.js} +108 -44
  63. package/build/lib/{chunk-7pwa92rn.js → chunk-mph5fvk7.js} +1 -1
  64. package/build/lib/chunk-psc23epq.js +107 -0
  65. package/build/lib/{chunk-acgbyf5h.js → chunk-qxad7qjd.js} +4 -2
  66. package/build/lib/{chunk-3c00n0cy.js → chunk-r0v3vvgm.js} +54 -33
  67. package/build/lib/{chunk-1yct6cra.js → chunk-rt13120a.js} +1 -1
  68. package/build/lib/{chunk-v3dk9j7k.js → chunk-sgya016v.js} +93 -22
  69. package/build/lib/{chunk-1fy8azee.js → chunk-txef92hq.js} +1 -1
  70. package/build/lib/{chunk-2qsq76xq.js → chunk-vcd90qrn.js} +189 -90
  71. package/build/lib/{chunk-7gjdygcx.js → chunk-vwr9w3ab.js} +2 -0
  72. package/build/lib/{chunk-z137x08b.js → chunk-wf6ak0m3.js} +92 -70
  73. package/build/lib/{chunk-xhdpgpkm.js → chunk-xft0ms9j.js} +2 -2
  74. package/build/lib/core/agents/agentRuntime.d.ts +3 -1
  75. package/build/lib/core/agents/defineAgent.d.ts +3 -2
  76. package/build/lib/core/agents/lance.d.ts +153 -0
  77. package/build/lib/core/agents/lanceJudge.d.ts +3 -0
  78. package/build/lib/core/agents/offSecAgent/index.d.ts +3 -1
  79. package/build/lib/core/agents/offSecAgent/index.js +16 -14
  80. package/build/lib/core/agents/offSecAgent/offensiveSecurityAgent.d.ts +4 -0
  81. package/build/lib/core/agents/offSecAgent/prompt.d.ts +3 -1
  82. package/build/lib/core/agents/offSecAgent/subagentSpawner.d.ts +18 -2
  83. package/build/lib/core/agents/offSecAgent/subagentSpawner.js +10 -8
  84. package/build/lib/core/agents/offSecAgent/toolExecutionContext.d.ts +3 -0
  85. package/build/lib/core/agents/offSecAgent/toolLifecycle.d.ts +1 -0
  86. package/build/lib/core/agents/offSecAgent/tools/index.js +10 -6
  87. package/build/lib/core/agents/offSecAgent/tools/listMemories.d.ts +11 -1
  88. package/build/lib/core/agents/offSecAgent/tools/reportError.d.ts +2 -1
  89. package/build/lib/core/agents/offSecAgent/tools/runPentestWorkflow.d.ts +20 -1
  90. package/build/lib/core/agents/offSecAgent/tools/spawnPentestAgent.d.ts +4 -7
  91. package/build/lib/core/agents/offSecAgent/tools/spawnPentestSwarm.d.ts +7 -1
  92. package/build/lib/core/agents/offSecAgent/tools/types.d.ts +6 -3
  93. package/build/lib/core/agents/offSecAgent/tools/whiteboxCandidates.d.ts +2 -2
  94. package/build/lib/core/agents/offSecAgent/types.d.ts +19 -3
  95. package/build/lib/core/agents/specialized/attackSurface/blackboxAgent.js +13 -13
  96. package/build/lib/core/agents/specialized/attackSurface/schemas.js +12 -12
  97. package/build/lib/core/agents/specialized/authenticationAgent/index.js +14 -14
  98. package/build/lib/core/agents/specialized/codeAgent/agent.js +13 -13
  99. package/build/lib/core/agents/specialized/codeAgent/prompts.d.ts +1 -0
  100. package/build/lib/core/agents/specialized/cvssScorer/index.d.ts +2 -1
  101. package/build/lib/core/agents/specialized/findingJudge/agent.js +11 -11
  102. package/build/lib/core/agents/specialized/findingJudge/index.d.ts +2 -1
  103. package/build/lib/core/agents/specialized/findingJudge/index.js +4 -4
  104. package/build/lib/core/agents/specialized/patching/index.js +14 -14
  105. package/build/lib/core/agents/specialized/pentest/agent.d.ts +18 -4
  106. package/build/lib/core/agents/specialized/pentest/agent.js +15 -13
  107. package/build/lib/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.d.ts +2 -1
  108. package/build/lib/core/agents/specialized/whiteboxAttackSurface/index.js +13 -13
  109. package/build/lib/core/ai/ai.d.ts +29 -70
  110. package/build/lib/core/ai/ai.js +5 -3
  111. package/build/lib/core/ai/index.d.ts +1 -0
  112. package/build/lib/core/ai/index.js +16 -4
  113. package/build/lib/core/ai/models/claude-capabilities.d.ts +3 -2
  114. package/build/lib/core/ai/models/concentrate.d.ts +1 -0
  115. package/build/lib/core/ai/models/index.d.ts +1 -1
  116. package/build/lib/core/ai/providers/concentrate.d.ts +1 -0
  117. package/build/lib/core/ai/reasoning.d.ts +44 -0
  118. package/build/lib/core/ai/utils.d.ts +2 -0
  119. package/build/lib/core/ai/utils.js +5 -3
  120. package/build/lib/core/api/index.d.ts +6 -0
  121. package/build/lib/core/api/index.js +32 -23
  122. package/build/lib/core/api/lance.d.ts +6 -0
  123. package/build/lib/core/api/offesecAgent.d.ts +1 -0
  124. package/build/lib/core/api/reasoning.d.ts +12 -0
  125. package/build/lib/core/api/targetedPentest.d.ts +1 -0
  126. package/build/lib/core/api/targetedPentest.js +14 -14
  127. package/build/lib/core/cli/reasoning.d.ts +4 -0
  128. package/build/lib/core/config/config.d.ts +10 -2
  129. package/build/lib/core/config/customProviders.d.ts +11 -0
  130. package/build/lib/core/config/index.js +1 -1
  131. package/build/lib/core/eventBus.js +1 -1
  132. package/build/lib/core/findings/registry.d.ts +3 -1
  133. package/build/lib/core/findings/registry.js +4 -4
  134. package/build/lib/core/observability/index.js +1 -1
  135. package/build/lib/core/observability/telemetry.d.ts +4 -0
  136. package/build/lib/core/session/index.d.ts +47 -0
  137. package/build/lib/core/session/index.js +6 -4
  138. package/build/lib/core/session/persistence.d.ts +7 -0
  139. package/build/lib/core/session/persistence.js +8 -4
  140. package/build/lib/core/tools/backends/index.js +1 -1
  141. package/build/lib/core/tools/backends/resolve.d.ts +1 -0
  142. package/build/lib/core/workflows/fastStrike.d.ts +3 -1
  143. package/build/lib/core/workflows/pentest.d.ts +12 -2
  144. package/build/lib/core/workflows/pentest.js +19 -19
  145. package/build/lib/core/workflows/seams.js +5 -5
  146. package/build/lib/core/workflows/threatModel.d.ts +1 -0
  147. package/build/lib/core/workflows/whiteboxAttackSurface.d.ts +6 -4
  148. package/build/lib/core/workflows/whiteboxAttackSurface.js +15 -15
  149. package/build/lib/index.js +25 -25
  150. package/build/{logs-x62b7hk1.js → logs-bcbjpjp6.js} +16 -13
  151. package/build/{native-rollout-evidence-c9yhfqcs.js → native-rollout-evidence-rph1774m.js} +5 -5
  152. package/build/offesecAgent-81h1p6ee.js +32 -0
  153. package/build/pentest-2q20q6n1.js +23 -0
  154. package/build/{pentests-e0f32aqx.js → pentests-jgw031mc.js} +16 -13
  155. package/build/recordedRunClient-6axj6fba.js +11 -0
  156. package/build/subagentSpawner-a861gvt0.js +12 -0
  157. package/build/targetedPentest-6yxznt7s.js +91 -0
  158. package/build/{targets-xj9g3q0z.js → targets-bjah19dp.js} +16 -13
  159. package/build/threatModel-739kpexm.js +24 -0
  160. package/build/{uninstall-7s784q4a.js → uninstall-yxrn9edt.js} +1 -1
  161. package/build/{upload-4gvhwmvr.js → upload-34ewrjp5.js} +4 -4
  162. package/build/{utils-cjrz64pc.js → utils-fzm66efw.js} +5 -5
  163. package/package.json +2 -1
  164. package/src/cli/issues.test.ts +17 -1
  165. package/src/cli/lance-verifier.test.ts +57 -0
  166. package/src/cli/lance-verifier.ts +73 -0
  167. package/src/cli/lance.test.ts +71 -0
  168. package/src/cli/lance.ts +48 -0
  169. package/src/cli.ts +109 -19
  170. package/src/core/agents/agentRuntime.test.ts +42 -0
  171. package/src/core/agents/agentRuntime.ts +7 -2
  172. package/src/core/agents/defineAgent.ts +3 -1
  173. package/src/core/agents/lance.test.ts +421 -0
  174. package/src/core/agents/lance.ts +701 -0
  175. package/src/core/agents/lanceJudge.test.ts +166 -0
  176. package/src/core/agents/lanceJudge.ts +115 -0
  177. package/src/core/agents/offSecAgent/index.ts +3 -0
  178. package/src/core/agents/offSecAgent/interruptedStepFinalization.test.ts +51 -0
  179. package/src/core/agents/offSecAgent/lance.test.ts +188 -0
  180. package/src/core/agents/offSecAgent/offensiveSecurityAgent.test.ts +92 -5
  181. package/src/core/agents/offSecAgent/offensiveSecurityAgent.ts +244 -41
  182. package/src/core/agents/offSecAgent/prompt.test.ts +46 -0
  183. package/src/core/agents/offSecAgent/prompt.ts +52 -8
  184. package/src/core/agents/offSecAgent/selectiveConstruction.publicPath.test.ts +38 -0
  185. package/src/core/agents/offSecAgent/selectiveConstruction.test.ts +64 -0
  186. package/src/core/agents/offSecAgent/subagentSpawner.hooks.test.ts +11 -3
  187. package/src/core/agents/offSecAgent/subagentSpawner.reasoning.test.ts +167 -0
  188. package/src/core/agents/offSecAgent/subagentSpawner.ts +82 -28
  189. package/src/core/agents/offSecAgent/toolExecutionContext.test.ts +230 -0
  190. package/src/core/agents/offSecAgent/toolExecutionContext.ts +56 -0
  191. package/src/core/agents/offSecAgent/toolLifecycle.ts +2 -0
  192. package/src/core/agents/offSecAgent/tools/delegateAuth.ts +4 -2
  193. package/src/core/agents/offSecAgent/tools/documentFinding.test.ts +9 -4
  194. package/src/core/agents/offSecAgent/tools/documentFinding.ts +10 -9
  195. package/src/core/agents/offSecAgent/tools/listMemories.test.ts +230 -0
  196. package/src/core/agents/offSecAgent/tools/listMemories.ts +73 -6
  197. package/src/core/agents/offSecAgent/tools/reportError.test.ts +6 -0
  198. package/src/core/agents/offSecAgent/tools/reportError.ts +10 -2
  199. package/src/core/agents/offSecAgent/tools/runAttackSurface.ts +7 -4
  200. package/src/core/agents/offSecAgent/tools/runPentestWorkflow.test.ts +57 -0
  201. package/src/core/agents/offSecAgent/tools/runPentestWorkflow.ts +21 -1
  202. package/src/core/agents/offSecAgent/tools/runWhiteboxScan.ts +5 -2
  203. package/src/core/agents/offSecAgent/tools/spawnCodingAgent.ts +50 -67
  204. package/src/core/agents/offSecAgent/tools/spawnPentestAgent.test.ts +79 -3
  205. package/src/core/agents/offSecAgent/tools/spawnPentestAgent.ts +36 -16
  206. package/src/core/agents/offSecAgent/tools/spawnPentestSwarm.ts +28 -5
  207. package/src/core/agents/offSecAgent/tools/threatModelGenerator.ts +4 -3
  208. package/src/core/agents/offSecAgent/tools/types.ts +12 -2
  209. package/src/core/agents/offSecAgent/tools/updateTask.ts +5 -1
  210. package/src/core/agents/offSecAgent/tools/whiteboxCandidates.ts +11 -4
  211. package/src/core/agents/offSecAgent/types.ts +22 -1
  212. package/src/core/agents/specialized/codeAgent/agent.test.ts +7 -0
  213. package/src/core/agents/specialized/codeAgent/agent.ts +9 -2
  214. package/src/core/agents/specialized/codeAgent/prompts.ts +6 -0
  215. package/src/core/agents/specialized/cvssScorer/index.test.ts +2 -1
  216. package/src/core/agents/specialized/cvssScorer/index.ts +3 -0
  217. package/src/core/agents/specialized/findingJudge/index.ts +6 -0
  218. package/src/core/agents/specialized/pentest/agent.test.ts +155 -0
  219. package/src/core/agents/specialized/pentest/agent.ts +181 -52
  220. package/src/core/agents/specialized/pentest/results.test.ts +59 -4
  221. package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.concurrency.test.ts +59 -2
  222. package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.hooks.test.ts +127 -0
  223. package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.ts +74 -68
  224. package/src/core/ai/ai.durability-hooks.test.ts +25 -7
  225. package/src/core/ai/ai.lance.test.ts +581 -0
  226. package/src/core/ai/ai.operator-context.bench.test.ts +1390 -0
  227. package/src/core/ai/ai.recorded-context.test.ts +89 -8
  228. package/src/core/ai/ai.test.ts +81 -59
  229. package/src/core/ai/ai.ts +453 -327
  230. package/src/core/ai/compactionTelemetry.test.ts +69 -17
  231. package/src/core/ai/index.ts +11 -0
  232. package/src/core/ai/models/anthropic.ts +6 -0
  233. package/src/core/ai/models/bedrock.ts +18 -0
  234. package/src/core/ai/models/claude-capabilities.ts +29 -8
  235. package/src/core/ai/models/concentrate.ts +52 -0
  236. package/src/core/ai/models/index.ts +25 -4
  237. package/src/core/ai/models/models.test.ts +179 -7
  238. package/src/core/ai/models/openrouter-reasoning.json +219 -0
  239. package/src/core/ai/models/openrouter.ts +43 -1
  240. package/src/core/ai/providers/anthropic-models.test.ts +60 -1
  241. package/src/core/ai/providers/bedrock-models.test.ts +81 -0
  242. package/src/core/ai/providers/concentrate.test.ts +31 -0
  243. package/src/core/ai/providers/concentrate.ts +11 -0
  244. package/src/core/ai/providers/custom.test.ts +74 -0
  245. package/src/core/ai/providers/custom.ts +3 -1
  246. package/src/core/ai/providers/gateway-models.test.ts +16 -6
  247. package/src/core/ai/providers/pensarFormatters.ts +8 -1
  248. package/src/core/ai/reasoning.test.ts +313 -0
  249. package/src/core/ai/reasoning.ts +500 -0
  250. package/src/core/ai/streamIdleTimeout.test.ts +21 -0
  251. package/src/core/ai/utils.native-rollout-evidence.test.ts +21 -8
  252. package/src/core/ai/utils.ts +269 -163
  253. package/src/core/api/attackSurface.ts +1 -0
  254. package/src/core/api/blackboxPentest.ts +9 -1
  255. package/src/core/api/index.ts +17 -0
  256. package/src/core/api/lance.ts +23 -0
  257. package/src/core/api/offesecAgent.test.ts +51 -0
  258. package/src/core/api/offesecAgent.ts +15 -1
  259. package/src/core/api/reasoning.test.ts +213 -0
  260. package/src/core/api/reasoning.ts +44 -0
  261. package/src/core/api/recordedRun.loop.test.ts +5 -1
  262. package/src/core/api/targetedPentest.test.ts +14 -2
  263. package/src/core/api/targetedPentest.ts +52 -5
  264. package/src/core/cli/reasoning.test.ts +149 -0
  265. package/src/core/cli/reasoning.ts +95 -0
  266. package/src/core/config/config.test.ts +35 -0
  267. package/src/core/config/config.ts +11 -0
  268. package/src/core/config/customProviders.ts +21 -2
  269. package/src/core/eventBus.ts +1 -0
  270. package/src/core/findings/registry.test.ts +9 -1
  271. package/src/core/findings/registry.ts +6 -0
  272. package/src/core/observability/telemetry.test.ts +131 -79
  273. package/src/core/observability/telemetry.ts +5 -0
  274. package/src/core/runtime/sqliteRunObservation.test.ts +1 -1
  275. package/src/core/session/index.ts +38 -0
  276. package/src/core/session/persistence.test.ts +62 -0
  277. package/src/core/session/persistence.ts +56 -0
  278. package/src/core/tools/backends/resolve.ts +7 -0
  279. package/src/core/tools/backends/whiteboxJobs.test.ts +9 -8
  280. package/src/core/workflows/fastStrike.seams.test.ts +149 -0
  281. package/src/core/workflows/fastStrike.test.ts +18 -1
  282. package/src/core/workflows/fastStrike.ts +106 -11
  283. package/src/core/workflows/pentest.test.ts +104 -0
  284. package/src/core/workflows/pentest.ts +128 -7
  285. package/src/core/workflows/seams.test.ts +13 -0
  286. package/src/core/workflows/seams.ts +5 -1
  287. package/src/core/workflows/threatModel.ts +2 -0
  288. package/src/core/workflows/whiteboxAttackSurface.test.ts +74 -2
  289. package/src/core/workflows/whiteboxAttackSurface.ts +102 -73
  290. package/src/tui/command-registry.test.ts +12 -0
  291. package/src/tui/command-registry.ts +10 -0
  292. package/src/tui/components/chat/config-view.tsx +6 -10
  293. package/src/tui/components/chat/home-view.tsx +2 -2
  294. package/src/tui/components/chat/input-area.tsx +2 -2
  295. package/src/tui/components/chat/loading-indicator.tsx +20 -4
  296. package/src/tui/components/chat/message-list.tsx +1 -0
  297. package/src/tui/components/commands/__tests__/advanced-settings-lifecycle.tsx +164 -0
  298. package/src/tui/components/commands/advanced-settings.test.ts +34 -0
  299. package/src/tui/components/commands/advanced-settings.tsx +220 -31
  300. package/src/tui/components/commands/models-display.tsx +7 -1
  301. package/src/tui/components/model-picker/ModelPicker.tsx +65 -103
  302. package/src/tui/components/model-picker/ModelPickerDialog.tsx +8 -14
  303. package/src/tui/components/model-picker/__tests__/reasoning-control.tsx +162 -0
  304. package/src/tui/components/model-picker/reasoning-control.test.ts +15 -0
  305. package/src/tui/components/operator-dashboard/index.tsx +166 -50
  306. package/src/tui/components/operator-dashboard/logic.test.ts +144 -2
  307. package/src/tui/components/operator-dashboard/logic.ts +54 -3
  308. package/src/tui/components/operator-dashboard/run-events.test.ts +3 -1
  309. package/src/tui/components/shared/__tests__/tool-renderer-lifecycle.tsx +18 -0
  310. package/src/tui/components/shared/action-label.test.ts +9 -0
  311. package/src/tui/components/shared/compacting-icon.tsx +18 -0
  312. package/src/tui/components/shared/index.ts +1 -0
  313. package/src/tui/components/shared/tool-registry.ts +1 -0
  314. package/src/tui/components/shared/tool-renderer.tsx +21 -7
  315. package/src/tui/context/agent.tsx +32 -79
  316. package/src/tui/context/route.tsx +2 -0
  317. package/src/tui/index.tsx +1 -0
  318. package/src/tui/keybindings/registry.ts +2 -0
  319. package/build/agent-6w7egcf1.js +0 -13
  320. package/build/agent-9zx75feh.js +0 -13
  321. package/build/blackboxAgent-s56sgx9b.js +0 -13
  322. package/build/cli-g06s7edq.js +0 -11
  323. package/build/lib/chunk-z96pbjhd.js +0 -56
  324. package/build/offesecAgent-5whnpeta.js +0 -22
  325. package/build/pentest-e61hc38s.js +0 -22
  326. package/build/recordedRunClient-dp032c32.js +0 -11
  327. package/build/targetedPentest-rcbs4nvp.js +0 -57
  328. package/build/threatModel-jkxfa40s.js +0 -21
@@ -96,6 +96,8 @@ const OperatorSettingsObject = z.object({
96
96
  enableSuggestions: z.boolean().default(true),
97
97
  /** Run the top-level operator as a focused solo researcher without orchestration tools. */
98
98
  strikeMode: z.boolean().optional(),
99
+ lanceMode: z.boolean().optional(),
100
+ findingPolicy: z.enum(["native", "external"]).optional(),
99
101
  });
100
102
 
101
103
  export type OperatorSettings = z.infer<typeof OperatorSettingsObject>;
@@ -216,6 +218,23 @@ function resolveSmtpConfig(explicit?: SmtpConfig): SmtpConfig | undefined {
216
218
  }
217
219
 
218
220
  const SessionConfigObject = z.object({
221
+ modelReasoning: z
222
+ .object({
223
+ model: z.string(),
224
+ setting: z.enum([
225
+ "default",
226
+ "enabled",
227
+ "disabled",
228
+ "none",
229
+ "minimal",
230
+ "low",
231
+ "medium",
232
+ "high",
233
+ "xhigh",
234
+ "max",
235
+ ]),
236
+ })
237
+ .optional(),
219
238
  /**
220
239
  * Custom HTTP headers for outbound target requests. Snapshotted from
221
240
  * `config.defaultHeaders` at create time; read via the resolver in
@@ -989,6 +1008,7 @@ export async function updateOperatorSettings(
989
1008
  requireApproval: true,
990
1009
  enableSuggestions: true,
991
1010
  strikeMode: false,
1011
+ findingPolicy: "native",
992
1012
  };
993
1013
  }
994
1014
 
@@ -1004,9 +1024,15 @@ export async function updateOperatorSettings(
1004
1024
  session.config.operatorSettings.enableSuggestions =
1005
1025
  settings.enableSuggestions;
1006
1026
  }
1027
+ if (settings.lanceMode !== undefined) {
1028
+ session.config.operatorSettings.lanceMode = settings.lanceMode;
1029
+ }
1007
1030
  if (settings.strikeMode !== undefined) {
1008
1031
  session.config.operatorSettings.strikeMode = settings.strikeMode;
1009
1032
  }
1033
+ if (settings.findingPolicy !== undefined) {
1034
+ session.config.operatorSettings.findingPolicy = settings.findingPolicy;
1035
+ }
1010
1036
  });
1011
1037
  }
1012
1038
 
@@ -1082,4 +1108,16 @@ export const sessions = {
1082
1108
  getResumeMessages,
1083
1109
  updateOperatorSettings,
1084
1110
  updateSessionHeaders,
1111
+ updateModelReasoning,
1085
1112
  };
1113
+
1114
+ export async function updateModelReasoning(
1115
+ id: string,
1116
+ model: string,
1117
+ setting: NonNullable<SessionConfig["modelReasoning"]>["setting"],
1118
+ ): Promise<SessionInfo> {
1119
+ return update(id, (session) => {
1120
+ session.config ??= {};
1121
+ session.config.modelReasoning = { model, setting };
1122
+ });
1123
+ }
@@ -18,6 +18,7 @@ import {
18
18
  convertModelMessagesToUI,
19
19
  finalizeManifest,
20
20
  getCompletedAgentIds,
21
+ loadSubagentObjectiveResults,
21
22
  loadSubagents,
22
23
  readAgentManifest,
23
24
  reconcileManifestOnResume,
@@ -239,6 +240,67 @@ describe("saveSubagentData + loadSubagents roundtrip", () => {
239
240
  });
240
241
  });
241
242
 
243
+ describe("loadSubagentObjectiveResults", () => {
244
+ it("roundtrips completed objective coverage, including an empty result", () => {
245
+ const session = makeSession();
246
+ const objectiveResults = [
247
+ { objective: "Test authorization", completed: true, result: "No bypass" },
248
+ { objective: "Test injection", completed: false },
249
+ ];
250
+ saveSubagentData(session, {
251
+ agentName: "pentest-agent-1",
252
+ target: "http://localhost:8080",
253
+ status: "completed",
254
+ reportedFindings: [],
255
+ objectiveResults,
256
+ messages: [],
257
+ });
258
+
259
+ expect(loadSubagentObjectiveResults(session, "pentest-agent-1")).toEqual(
260
+ objectiveResults,
261
+ );
262
+
263
+ saveSubagentData(session, {
264
+ agentName: "pentest-agent-1",
265
+ target: "http://localhost:8080",
266
+ status: "completed",
267
+ reportedFindings: [],
268
+ objectiveResults: [],
269
+ messages: [],
270
+ });
271
+ expect(loadSubagentObjectiveResults(session, "pentest-agent-1")).toEqual(
272
+ [],
273
+ );
274
+ });
275
+
276
+ it("rejects missing, failed, and malformed objective coverage", () => {
277
+ const session = makeSession();
278
+ const key = "pentest-agent-1";
279
+ const snapshotPath = join(tmpDir, "subagents", `${key}.json`);
280
+ expect(loadSubagentObjectiveResults(session, key)).toBeNull();
281
+ mkdirSync(join(tmpDir, "subagents"));
282
+
283
+ const invalidSnapshots = [
284
+ { status: "failed", objectiveResults: [] },
285
+ { status: "completed" },
286
+ { status: "completed", objectiveResults: null },
287
+ { status: "completed", objectiveResults: [{ objective: "Test" }] },
288
+ {
289
+ status: "completed",
290
+ objectiveResults: [{ objective: "Test", completed: "true" }],
291
+ },
292
+ {
293
+ status: "completed",
294
+ objectiveResults: [{ objective: "Test", completed: true, result: 42 }],
295
+ },
296
+ ];
297
+ for (const snapshot of invalidSnapshots) {
298
+ writeFileSync(snapshotPath, JSON.stringify(snapshot));
299
+ expect(loadSubagentObjectiveResults(session, key)).toBeNull();
300
+ }
301
+ });
302
+ });
303
+
242
304
  // ---------------------------------------------------------------------------
243
305
  // Manifest roundtrip
244
306
  // ---------------------------------------------------------------------------
@@ -28,6 +28,7 @@ export type { SessionInfo };
28
28
 
29
29
  import type { ModelMessage } from "ai";
30
30
  import type { GrpcPentestContext } from "../agents/specialized/attackSurface/grpcSchema";
31
+ import type { ObjectiveResult } from "../agents/specialized/pentest/agent";
31
32
  import { newSessionId, type SessionID } from "../id/id";
32
33
  import type { AuthenticationInfo } from "./types";
33
34
 
@@ -56,6 +57,8 @@ interface SavedSubagentData {
56
57
  toolCallCount?: number;
57
58
  stepCount?: number;
58
59
  findingsCount?: number;
60
+ reportedFindings?: string[];
61
+ objectiveResults?: ObjectiveResult[];
59
62
  status?: string;
60
63
  error?: string;
61
64
  messages?: ModelMessage[];
@@ -115,6 +118,8 @@ export interface SubagentSaveInput {
115
118
  status: string;
116
119
  error?: string;
117
120
  findingsCount?: number;
121
+ reportedFindings?: string[];
122
+ objectiveResults?: ObjectiveResult[];
118
123
  /** Raw AI SDK messages from onStepFinish (e.response.messages) */
119
124
  messages: ModelMessage[];
120
125
  /** System prompt used for this agent (for training data export) */
@@ -150,6 +155,55 @@ export function loadSubagentMessages(
150
155
  }
151
156
  }
152
157
 
158
+ /** Read external findings from a completed swarm target on resume. */
159
+ export function loadSubagentReportedFindings(
160
+ session: SessionInfo,
161
+ key: string,
162
+ ): string[] | null {
163
+ const snapshotPath = join(session.rootPath, SUBAGENTS_DIR, `${key}.json`);
164
+ if (!existsSync(snapshotPath)) return null;
165
+ try {
166
+ const data = JSON.parse(
167
+ readFileSync(snapshotPath, "utf-8"),
168
+ ) as SavedSubagentData;
169
+ return data.status === "completed" &&
170
+ Array.isArray(data.reportedFindings) &&
171
+ data.reportedFindings.every((finding) => typeof finding === "string")
172
+ ? data.reportedFindings
173
+ : null;
174
+ } catch {
175
+ return null;
176
+ }
177
+ }
178
+
179
+ /** Read completed objective coverage from a swarm target on resume. */
180
+ export function loadSubagentObjectiveResults(
181
+ session: SessionInfo,
182
+ key: string,
183
+ ): ObjectiveResult[] | null {
184
+ const snapshotPath = join(session.rootPath, SUBAGENTS_DIR, `${key}.json`);
185
+ if (!existsSync(snapshotPath)) return null;
186
+ try {
187
+ const data = JSON.parse(
188
+ readFileSync(snapshotPath, "utf-8"),
189
+ ) as SavedSubagentData;
190
+ return data.status === "completed" &&
191
+ Array.isArray(data.objectiveResults) &&
192
+ data.objectiveResults.every(
193
+ (result) =>
194
+ result !== null &&
195
+ typeof result === "object" &&
196
+ typeof result.objective === "string" &&
197
+ typeof result.completed === "boolean" &&
198
+ (result.result === undefined || typeof result.result === "string"),
199
+ )
200
+ ? data.objectiveResults
201
+ : null;
202
+ } catch {
203
+ return null;
204
+ }
205
+ }
206
+
153
207
  /** Writes to `{session.rootPath}/{SUBAGENTS_DIR}/{name}.json`. */
154
208
  export function saveSubagentData(
155
209
  session: SessionInfo,
@@ -181,6 +235,8 @@ export function saveSubagentData(
181
235
  toolCallCount,
182
236
  stepCount,
183
237
  findingsCount: data.findingsCount ?? 0,
238
+ reportedFindings: data.reportedFindings,
239
+ objectiveResults: data.objectiveResults,
184
240
  status: data.status,
185
241
  error: data.error,
186
242
  messages: data.messages,
@@ -1,3 +1,4 @@
1
+ import { posix } from "node:path";
1
2
  import { appendLocalWorkspaceFile } from "../../agents/offSecAgent/tools/fileWorkspace";
2
3
  import type { ToolContext } from "../../agents/offSecAgent/tools/types";
3
4
  import { LocalBackends, runLocalProgram } from "./local";
@@ -6,6 +7,12 @@ import { windowsProgramInvocation } from "./windowsProgram";
6
7
 
7
8
  export const SANDBOX_ARTIFACTS_ROOT = "/workspace/repo/.pensar";
8
9
 
10
+ export function sandboxArtifactsRoot(session: ToolContext["session"]): string {
11
+ return session.config?.remoteFileWorkspaceRoot
12
+ ? posix.join(session.config.remoteFileWorkspaceRoot, ".pensar")
13
+ : SANDBOX_ARTIFACTS_ROOT;
14
+ }
15
+
9
16
  const localByContext = new WeakMap<ToolContext, ToolBackends>();
10
17
 
11
18
  /** The backends a tool should execute against: injected, else local (memoised per context). */
@@ -12,7 +12,7 @@ import {
12
12
  import { tmpdir } from "node:os";
13
13
  import { join } from "node:path";
14
14
  import { promisify } from "node:util";
15
- import { afterEach, describe, expect, it } from "vitest";
15
+ import { afterEach, describe, expect, it, vi } from "vitest";
16
16
  import type { ToolContext } from "../../agents/offSecAgent/tools/types";
17
17
  import * as tools from "../../agents/offSecAgent/tools/whiteboxJobs";
18
18
  import { LocalBackends } from "./local";
@@ -363,13 +363,14 @@ it.skipIf(process.platform !== "win32")(
363
363
  });
364
364
  stops.push(() => jobs.stop(record.id));
365
365
  expect((await jobs.poll(record.id))?.status).toBe("running");
366
- let output = "";
367
- for (let i = 0; i < 20 && !output.includes("\n\nready & quoted"); i++) {
368
- output = (await jobs.read(record.id)).content;
369
- if (!output.includes("\n\nready & quoted"))
370
- await new Promise((resolve) => setTimeout(resolve, 50));
371
- }
372
- expect(output).toContain("\n\nready & quoted");
366
+ await vi.waitFor(
367
+ async () => {
368
+ expect((await jobs.read(record.id)).content).toContain(
369
+ "\n\nready & quoted",
370
+ );
371
+ },
372
+ { timeout: 15_000, interval: 100 },
373
+ );
373
374
  expect((await jobs.stop(record.id))?.status).toBe("stopped");
374
375
  },
375
376
  );
@@ -61,6 +61,7 @@ let rootPath: string;
61
61
  let session: SessionInfo;
62
62
 
63
63
  beforeEach(() => {
64
+ mocks.registry.groupByRootCause.mockClear();
64
65
  rootPath = mkdtempSync(join(tmpdir(), "faststrike-seams-"));
65
66
  session = {
66
67
  id: "ses_faststrike_seams",
@@ -215,3 +216,151 @@ it("forwards canonical hooks and legacy fields to the fast-strike operator", asy
215
216
  });
216
217
  expect(mocks.fastStrikeInputs[0]).toMatchObject({ ...hooks, usageRecorder });
217
218
  });
219
+
220
+ describe("external Fast Strike", () => {
221
+ it("keeps exfiltration mode explicit and returns the extracted result", async () => {
222
+ session.config = { exfilMode: true };
223
+ mocks.consumeImpl = async () => ({
224
+ solved: true,
225
+ summary: "Extracted FLAG{example}",
226
+ reportedFindings: ["Confirmed scoped weakness"],
227
+ submissionJson: "",
228
+ });
229
+
230
+ const result = await runFastStrike({
231
+ target: "https://example.com",
232
+ model: {} as PentestWorkflowInput["model"],
233
+ session,
234
+ findingPolicy: "external",
235
+ });
236
+
237
+ expect(String(mocks.fastStrikeInputs.at(-1)?.prompt)).toContain(
238
+ "Exfiltration goal: locate and extract FLAG{...}",
239
+ );
240
+ expect(result).toMatchObject({
241
+ solved: true,
242
+ summary: "Extracted FLAG{example}",
243
+ });
244
+ });
245
+
246
+ it("returns exact submission JSON and skips native finding aggregation", async () => {
247
+ const submissionJson = JSON.stringify({
248
+ schema_version: "penbench-finding/v1",
249
+ status: "finding",
250
+ surfaces: ["GET /private"],
251
+ root_cause: "Tenant scope is not enforced",
252
+ impact: "Cross-tenant read",
253
+ });
254
+ mocks.consumeImpl = async () => ({
255
+ solved: true,
256
+ summary: "Cross-tenant read found",
257
+ reportedFindings: ["GET /private reads another tenant's data"],
258
+ submissionJson,
259
+ });
260
+
261
+ const result = await runFastStrike({
262
+ target: "https://example.com",
263
+ model: {} as PentestWorkflowInput["model"],
264
+ session,
265
+ findingPolicy: "external",
266
+ enableThinking: true,
267
+ thinkingEffort: "high",
268
+ });
269
+
270
+ expect(result).toMatchObject({
271
+ findings: [],
272
+ reportedFindings: ["GET /private reads another tenant's data"],
273
+ submissionJson,
274
+ solved: true,
275
+ summary: "Cross-tenant read found",
276
+ reportPath: null,
277
+ });
278
+ expect(mocks.registry.groupByRootCause).not.toHaveBeenCalled();
279
+ const input = mocks.fastStrikeInputs.at(-1);
280
+ expect(input).toMatchObject({
281
+ findingPolicy: "external",
282
+ enableThinking: true,
283
+ thinkingEffort: "high",
284
+ });
285
+ expect(String(input?.system)).not.toContain("document_vulnerability");
286
+ const responseSchema = input?.responseSchema as {
287
+ safeParse: (value: unknown) => { success: boolean };
288
+ };
289
+ expect(
290
+ responseSchema.safeParse({
291
+ solved: true,
292
+ summary: "Found it",
293
+ reportedFindings: [],
294
+ submissionJson,
295
+ }).success,
296
+ ).toBe(true);
297
+ expect(
298
+ responseSchema.safeParse({ solved: true, summary: "Found it" }).success,
299
+ ).toBe(false);
300
+ });
301
+
302
+ it("fails closed when the external response omits the submission", async () => {
303
+ mocks.consumeImpl = async () => ({
304
+ solved: true,
305
+ summary: "Found it",
306
+ reportedFindings: ["finding"],
307
+ });
308
+ await expect(
309
+ runFastStrike({
310
+ target: "https://example.com",
311
+ model: {} as PentestWorkflowInput["model"],
312
+ session,
313
+ findingPolicy: "external",
314
+ }),
315
+ ).rejects.toThrow("without a structured findings response");
316
+ });
317
+
318
+ it.each([
319
+ ["undefined", undefined],
320
+ ["null", null],
321
+ [
322
+ "wrong field types",
323
+ {
324
+ solved: true,
325
+ summary: "claimed",
326
+ reportedFindings: "claimed",
327
+ submissionJson: "{}",
328
+ },
329
+ ],
330
+ ])("marks a %s external response as failed before completion hooks", async (_label, outcome) => {
331
+ mocks.consumeImpl = async () => outcome;
332
+ const emit = vi.fn();
333
+ const onEndpointDone = vi.fn();
334
+ const onEndpointFailed = vi.fn();
335
+
336
+ await expect(
337
+ runFastStrike({
338
+ target: "https://example.com",
339
+ model: {} as PentestWorkflowInput["model"],
340
+ session,
341
+ findingPolicy: "external",
342
+ eventBus: { emit } as unknown as NonNullable<
343
+ PentestWorkflowInput["eventBus"]
344
+ >,
345
+ seams: inProcessSeams({
346
+ hooks: { onEndpointDone, onEndpointFailed },
347
+ registries: {
348
+ findings: () => mocks.registry,
349
+ attackSurface: () => ({}) as never,
350
+ },
351
+ }),
352
+ }),
353
+ ).rejects.toThrow("without a structured findings response");
354
+
355
+ expect(onEndpointDone).not.toHaveBeenCalled();
356
+ expect(onEndpointFailed).toHaveBeenCalledOnce();
357
+ expect(emit).toHaveBeenCalledWith("subagent-complete", {
358
+ subagentId: "fast-strike",
359
+ status: "failed",
360
+ });
361
+ expect(emit).not.toHaveBeenCalledWith("subagent-complete", {
362
+ subagentId: "fast-strike",
363
+ status: "completed",
364
+ });
365
+ });
366
+ });
@@ -1,5 +1,8 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { FAST_STRIKE_SYSTEM_PROMPT } from "./fastStrike";
2
+ import {
3
+ buildFastStrikeSystemPrompt,
4
+ FAST_STRIKE_SYSTEM_PROMPT,
5
+ } from "./fastStrike";
3
6
 
4
7
  describe("Fast Strike system prompt", () => {
5
8
  it("externalizes complex exploit chains into editable scripts", () => {
@@ -26,4 +29,18 @@ describe("Fast Strike system prompt", () => {
26
29
  "call the response tool with the correct solved value",
27
30
  );
28
31
  });
32
+
33
+ it("keeps the native prompt as the default policy", () => {
34
+ expect(buildFastStrikeSystemPrompt()).toBe(FAST_STRIKE_SYSTEM_PROMPT);
35
+ });
36
+
37
+ it("keeps the Strike loop but hands finding acceptance to the caller", () => {
38
+ const prompt = buildFastStrikeSystemPrompt("external");
39
+ expect(prompt).toContain("OBSERVE");
40
+ expect(prompt).toContain("HYPOTHESIZE");
41
+ expect(prompt).toContain("editable script");
42
+ expect(prompt).toContain("submissionJson");
43
+ expect(prompt).not.toContain("document_vulnerability");
44
+ expect(prompt).not.toContain("validation judge");
45
+ });
29
46
  });