@piagent/platform 1.5.5 → 1.6.1

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 (323) hide show
  1. package/CHANGELOG.md +166 -0
  2. package/README.md +25 -21
  3. package/README.vi.md +34 -5
  4. package/adapters/web-frontend/profile.json +2 -4
  5. package/architecture/layers.json +18 -3
  6. package/benchmarks/deep-logic-v1/SPECIALIST_PROTOCOL.vi.md +122 -0
  7. package/benchmarks/deep-logic-v1/grade.mjs +272 -10
  8. package/benchmarks/deep-logic-v1/project/apps/admin/src/billing-summary.js +3 -0
  9. package/benchmarks/deep-logic-v1/project/benchmark-contract/public-smoke.test.js +166 -0
  10. package/benchmarks/deep-logic-v1/project/package.json +1 -1
  11. package/benchmarks/deep-logic-v1/project/packages/billing/src/close-period.js +3 -0
  12. package/benchmarks/deep-logic-v1/project/packages/billing/src/plan-timeline.js +3 -0
  13. package/benchmarks/deep-logic-v1/project/test/smoke.test.js +7 -1
  14. package/benchmarks/deep-logic-v1/prompts/budgeted-context-graph.md +2 -0
  15. package/benchmarks/deep-logic-v1/prompts/fair-dependency-scheduler.md +2 -0
  16. package/benchmarks/deep-logic-v1/prompts/layered-policy-resolution.md +2 -0
  17. package/benchmarks/deep-logic-v1/prompts/resumable-stream-assembly.md +3 -1
  18. package/benchmarks/deep-logic-v1/prompts/revision-event-reconciliation.md +2 -0
  19. package/benchmarks/deep-logic-v1/prompts/temporal-usage-billing-close.md +123 -0
  20. package/benchmarks/deep-logic-v1/prompts/transactional-config-merge.md +2 -0
  21. package/benchmarks/deep-logic-v1/suite.json +51 -3
  22. package/benchmarks/deep-logic-v1/variant.mjs +22 -1
  23. package/benchmarks/production-v1/spend-control.v1.json +92 -0
  24. package/benchmarks/production-v1/suite.json +46 -3
  25. package/catalog/capabilities.json +18 -18
  26. package/docs/authority-manifest.md +1 -1
  27. package/docs/auto-delegation-policy.md +38 -73
  28. package/docs/command-reference-vietnamese.md +27 -35
  29. package/docs/context-engine.md +12 -4
  30. package/docs/context-window-policy.md +37 -1
  31. package/docs/distribution-standard.md +7 -7
  32. package/docs/en/architecture.md +27 -13
  33. package/docs/languages.json +4 -4
  34. package/docs/model-options.md +8 -5
  35. package/docs/operator-manual-vietnamese.md +27 -45
  36. package/docs/project-adapters.md +2 -2
  37. package/docs/publishing-for-teams.md +10 -0
  38. package/docs/quality-benchmark.md +427 -62
  39. package/docs/release-install-policy.md +10 -9
  40. package/docs/runtime-harness-standard.md +3 -3
  41. package/docs/runtime-policy-design.md +4 -4
  42. package/docs/runtime-quality-baseline.md +13 -6
  43. package/docs/security-threat-model.md +2 -2
  44. package/docs/subagent-orchestration-capabilities.md +19 -51
  45. package/docs/subagents-and-multiagent.md +21 -47
  46. package/docs/task-implementation-contract.md +3 -3
  47. package/docs/task-lifecycle-vietnamese.md +3 -3
  48. package/docs/team-onboarding.md +2 -2
  49. package/docs/usage-observability.md +7 -2
  50. package/docs/vi/architecture.md +27 -13
  51. package/docs-site/architecture.html +1 -1
  52. package/docs-site/benchmark.html +89 -95
  53. package/docs-site/commands.html +1 -1
  54. package/docs-site/content/benchmark.html +88 -94
  55. package/docs-site/content/en/benchmark.html +134 -90
  56. package/docs-site/content/en/index.html +19 -19
  57. package/docs-site/content/en/runtime.html +4 -4
  58. package/docs-site/content/en/whats-new.html +12 -1
  59. package/docs-site/content/en/workflows.html +2 -2
  60. package/docs-site/content/index.html +19 -19
  61. package/docs-site/content/runtime.html +4 -4
  62. package/docs-site/content/whats-new.html +12 -1
  63. package/docs-site/content/workflows.html +2 -2
  64. package/docs-site/context-engine.html +1 -1
  65. package/docs-site/en/architecture.html +1 -1
  66. package/docs-site/en/benchmark.html +135 -91
  67. package/docs-site/en/commands.html +1 -1
  68. package/docs-site/en/context-engine.html +1 -1
  69. package/docs-site/en/index.html +20 -20
  70. package/docs-site/en/mcp-approval.html +1 -1
  71. package/docs-site/en/mcp-auth.html +1 -1
  72. package/docs-site/en/mcp-servers.html +1 -1
  73. package/docs-site/en/mcp.html +1 -1
  74. package/docs-site/en/permissions.html +1 -1
  75. package/docs-site/en/profiles.html +1 -1
  76. package/docs-site/en/quickstart.html +1 -1
  77. package/docs-site/en/runtime.html +5 -5
  78. package/docs-site/en/scope.html +1 -1
  79. package/docs-site/en/security.html +1 -1
  80. package/docs-site/en/team.html +1 -1
  81. package/docs-site/en/whats-new.html +13 -2
  82. package/docs-site/en/workflows.html +3 -3
  83. package/docs-site/index.html +20 -20
  84. package/docs-site/mcp-approval.html +1 -1
  85. package/docs-site/mcp-auth.html +1 -1
  86. package/docs-site/mcp-servers.html +1 -1
  87. package/docs-site/mcp.html +1 -1
  88. package/docs-site/permissions.html +1 -1
  89. package/docs-site/profiles.html +1 -1
  90. package/docs-site/quickstart.html +1 -1
  91. package/docs-site/runtime.html +5 -5
  92. package/docs-site/scope.html +1 -1
  93. package/docs-site/security.html +1 -1
  94. package/docs-site/team.html +1 -1
  95. package/docs-site/whats-new.html +13 -2
  96. package/docs-site/workflows.html +3 -3
  97. package/evals/fixtures/benchmark-assurance-evidence.invalid.json +1 -1
  98. package/evals/fixtures/benchmark-assurance-evidence.valid.json +1 -1
  99. package/evals/fixtures/codex-relative-efficiency-v1.invalid.json +4 -0
  100. package/evals/fixtures/codex-relative-efficiency-v1.valid.json +94 -0
  101. package/evals/fixtures/helper-request.invalid.json +1 -1
  102. package/evals/fixtures/helper-request.valid.json +1 -1
  103. package/evals/fixtures/piagent-webui/session-live-state-v1.invalid.json +18 -0
  104. package/evals/fixtures/piagent-webui/session-live-state-v1.valid.json +27 -0
  105. package/evals/fixtures/piagent-webui/subagent-tree-v1.valid.json +7 -0
  106. package/evals/fixtures/task-authority-snapshot.valid.json +4 -4
  107. package/evals/fs4-readiness-matrix.v1.json +2 -2
  108. package/evals/fs5-causal-arm.v1.json +3 -3
  109. package/evals/fs5-pilot-protocol.v1.json +3 -3
  110. package/evals/fs5-pilot-protocol.v2.json +8 -8
  111. package/evals/fs5-pilot-protocol.v3.json +8 -8
  112. package/evals/fs5-pilot-protocol.v4.json +7 -6
  113. package/evals/fs5-pilot-protocol.v5.json +9 -7
  114. package/evals/private-holdout-v1/public-exposure.v1.json +1 -1
  115. package/evals/runtime-conformance-v1/README.md +43 -0
  116. package/evals/runtime-conformance-v1/evaluate-paid-canary.mjs +198 -0
  117. package/evals/runtime-conformance-v1/lane.json +57 -0
  118. package/evals/runtime-conformance-v1/paid-canary.json +31 -0
  119. package/evals/runtime-conformance-v1/runner.mjs +456 -0
  120. package/package.json +3 -1
  121. package/packages/piagent-core/README.md +13 -4
  122. package/packages/piagent-core/benchmark/benchmark-assurance.js +4 -1
  123. package/packages/piagent-core/benchmark/benchmark-bootstrap.js +91 -9
  124. package/packages/piagent-core/benchmark/benchmark-claim-restrictions.js +38 -7
  125. package/packages/piagent-core/benchmark/benchmark-cli.js +7 -7
  126. package/packages/piagent-core/benchmark/benchmark-codex-relative-efficiency.js +698 -0
  127. package/packages/piagent-core/benchmark/benchmark-codex.js +3 -1
  128. package/packages/piagent-core/benchmark/benchmark-comparison.js +271 -2
  129. package/packages/piagent-core/benchmark/benchmark-core.js +736 -664
  130. package/packages/piagent-core/benchmark/benchmark-execution-guard.js +7 -5
  131. package/packages/piagent-core/benchmark/benchmark-forensics.js +441 -4
  132. package/packages/piagent-core/benchmark/benchmark-host-readiness.js +639 -0
  133. package/packages/piagent-core/benchmark/benchmark-matrix.js +22 -4
  134. package/packages/piagent-core/benchmark/benchmark-normalized-cost.js +317 -0
  135. package/packages/piagent-core/benchmark/benchmark-preflight.js +5 -1
  136. package/packages/piagent-core/benchmark/benchmark-process.js +6 -5
  137. package/packages/piagent-core/benchmark/benchmark-provider-free-evidence.js +345 -0
  138. package/packages/piagent-core/benchmark/benchmark-provider-wire.js +126 -0
  139. package/packages/piagent-core/benchmark/benchmark-record-validation.js +252 -0
  140. package/packages/piagent-core/benchmark/benchmark-report.js +130 -12
  141. package/packages/piagent-core/benchmark/benchmark-resume-recovery.js +14 -0
  142. package/packages/piagent-core/benchmark/benchmark-runner-policy.js +26 -0
  143. package/packages/piagent-core/benchmark/benchmark-runtime-causal.js +244 -0
  144. package/packages/piagent-core/benchmark/benchmark-stage-diagnostic.js +979 -0
  145. package/packages/piagent-core/benchmark/benchmark-statistics.js +64 -0
  146. package/packages/piagent-core/benchmark/benchmark-stop-policy.js +8 -5
  147. package/packages/piagent-core/benchmark/benchmark-suite-identity.js +31 -0
  148. package/packages/piagent-core/benchmark/benchmark-suite-runtime.js +13 -9
  149. package/packages/piagent-core/benchmark/benchmark-suite.js +149 -2
  150. package/packages/piagent-core/benchmark/benchmark-summary-support.js +380 -0
  151. package/packages/piagent-core/benchmark/benchmark-timing-diagnostics.js +971 -0
  152. package/packages/piagent-core/benchmark/benchmark-usage.js +322 -0
  153. package/packages/piagent-core/benchmark/benchmark-workflow.js +166 -0
  154. package/packages/piagent-core/capabilities/runtime-integrity.js +3 -0
  155. package/packages/piagent-core/docs/context-efficiency-improvement-plan.md +1080 -0
  156. package/packages/piagent-core/extensions/acceptance-behavior-proof.js +806 -0
  157. package/packages/piagent-core/extensions/acceptance-contract-semantics.js +83 -69
  158. package/packages/piagent-core/extensions/acceptance-error-classes.js +160 -0
  159. package/packages/piagent-core/extensions/acceptance-executable-evidence.js +12 -9
  160. package/packages/piagent-core/extensions/acceptance-receipt.js +123 -59
  161. package/packages/piagent-core/extensions/acceptance-state-machine-evidence.js +518 -0
  162. package/packages/piagent-core/extensions/acceptance-test-binding-evidence.js +60 -0
  163. package/packages/piagent-core/extensions/context-efficiency-metrics.js +302 -0
  164. package/packages/piagent-core/extensions/context-efficiency-report.js +167 -0
  165. package/packages/piagent-core/extensions/context-engine.js +149 -156
  166. package/packages/piagent-core/extensions/context-evidence.js +48 -0
  167. package/packages/piagent-core/extensions/context-import-links.js +296 -0
  168. package/packages/piagent-core/extensions/context-index-policy.js +4 -0
  169. package/packages/piagent-core/extensions/context-query-paths.js +57 -0
  170. package/packages/piagent-core/extensions/context-telemetry-integrity.js +65 -0
  171. package/packages/piagent-core/extensions/criterion-context-pack.js +435 -7
  172. package/packages/piagent-core/extensions/criterion-graph.js +82 -9
  173. package/packages/piagent-core/extensions/fallback-base-policy.ts +101 -0
  174. package/packages/piagent-core/extensions/guard-types.ts +6 -0
  175. package/packages/piagent-core/extensions/javascript-regex-evidence.js +32 -0
  176. package/packages/piagent-core/extensions/piagent-guard.ts +420 -260
  177. package/packages/piagent-core/extensions/task-contract-view.js +17 -3
  178. package/packages/piagent-core/extensions/task-lifecycle.js +39 -2
  179. package/packages/piagent-core/extensions/task-state.js +109 -142
  180. package/packages/piagent-core/extensions/verification-intelligence.js +52 -13
  181. package/packages/piagent-core/extensions/workspace-evidence-roots.js +193 -0
  182. package/packages/piagent-core/package.json +1 -1
  183. package/packages/piagent-core/policies/base-policy.json +44 -2
  184. package/packages/piagent-core/policy/authority-manifest.v1.json +3 -3
  185. package/packages/piagent-core/prompts/be-to-fe.md +2 -8
  186. package/packages/piagent-core/prompts/plan.md +1 -1
  187. package/packages/piagent-core/prompts/platform-improve.md +2 -6
  188. package/packages/piagent-core/prompts/review.md +2 -7
  189. package/packages/piagent-core/prompts/scout.md +1 -1
  190. package/packages/piagent-core/prompts/task.md +4 -3
  191. package/packages/piagent-core/runtime/context/context-delivery.ts +103 -0
  192. package/packages/piagent-core/runtime/context/context-delta-shadow.ts +53 -0
  193. package/packages/piagent-core/runtime/context/context-efficiency-format.ts +47 -0
  194. package/packages/piagent-core/runtime/context/context-evidence-qualification.ts +32 -0
  195. package/packages/piagent-core/runtime/context/prefix-telemetry.ts +47 -0
  196. package/packages/piagent-core/runtime/context/repository-memory-hints.ts +27 -0
  197. package/packages/piagent-core/runtime/hooks/agent-prompt-telemetry.ts +56 -0
  198. package/packages/piagent-core/runtime/hooks/agent-start-hook.ts +162 -102
  199. package/packages/piagent-core/runtime/hooks/completion-hook.ts +12 -12
  200. package/packages/piagent-core/runtime/hooks/input-hook.ts +17 -1
  201. package/packages/piagent-core/runtime/hooks/session-hooks.ts +22 -2
  202. package/packages/piagent-core/runtime/hooks/session-start-hook.ts +107 -3
  203. package/packages/piagent-core/runtime/hooks/tool-result-content-guards.ts +95 -0
  204. package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +134 -166
  205. package/packages/piagent-core/runtime/hooks/tool-result-value-helpers.ts +66 -0
  206. package/packages/piagent-core/runtime/inspection/activity-event-adapter.ts +4 -2
  207. package/packages/piagent-core/runtime/inspection/activity-recovery.ts +104 -0
  208. package/packages/piagent-core/runtime/inspection/bounded-emission-guard.ts +286 -0
  209. package/packages/piagent-core/runtime/inspection/runtime-event-store.ts +37 -7
  210. package/packages/piagent-core/runtime/inspection/task-compaction-history.ts +1 -1
  211. package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +1 -1
  212. package/packages/piagent-core/runtime/inspection/task-subagent-tree.ts +27 -4
  213. package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +70 -0
  214. package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +73 -9
  215. package/packages/piagent-core/runtime/model/authenticated-catalog.ts +17 -9
  216. package/packages/piagent-core/runtime/model/openai-codex-reasoning.ts +83 -0
  217. package/packages/piagent-core/runtime/model/provider-wire-fingerprint.ts +238 -0
  218. package/packages/piagent-core/runtime/orchestration/helper-lifecycle.ts +16 -12
  219. package/packages/piagent-core/runtime/orchestration/minimal-delegation-policy.ts +71 -0
  220. package/packages/piagent-core/runtime/orchestration/owned-work-budget.ts +28 -20
  221. package/packages/piagent-core/runtime/orchestration/role-policy.ts +27 -9
  222. package/packages/piagent-core/runtime/orchestration/subagent-tool-policy.ts +329 -0
  223. package/packages/piagent-core/runtime/policy/block-remedy.ts +0 -4
  224. package/packages/piagent-core/runtime/product/activity-inspector.ts +7 -2
  225. package/packages/piagent-core/runtime/product/efficiency-metrics.ts +7 -2
  226. package/packages/piagent-core/runtime/quality/edit-freshness-guard.ts +102 -0
  227. package/packages/piagent-core/runtime/quality/exact-output-contract.ts +22 -11
  228. package/packages/piagent-core/runtime/quality/performance-assurance-signals.ts +23 -0
  229. package/packages/piagent-core/runtime/quality/performance-assurance.ts +9 -5
  230. package/packages/piagent-core/runtime/recovery/continuation-budget.ts +1 -1
  231. package/packages/piagent-core/runtime/recovery/edit-recovery-context.ts +113 -0
  232. package/packages/piagent-core/runtime/recovery/edit-recovery-delivery.ts +42 -0
  233. package/packages/piagent-core/runtime/recovery/handoff-projection.ts +4 -1
  234. package/packages/piagent-core/runtime/recovery/pristine-task-policy-refresh.ts +91 -0
  235. package/packages/piagent-core/runtime/recovery/recovery-policy.ts +7 -4
  236. package/packages/piagent-core/runtime/recovery/resume-state.ts +112 -14
  237. package/packages/piagent-core/runtime/recovery/semantic-repair-handshake.ts +60 -13
  238. package/packages/piagent-core/runtime/recovery/semantic-repair-runtime.ts +55 -2
  239. package/packages/piagent-core/runtime/recovery/task-evidence-coverage-refresh.ts +217 -0
  240. package/packages/piagent-core/runtime/registration/context-commands.ts +82 -7
  241. package/packages/piagent-core/runtime/registration/knowledge-tools.ts +9 -5
  242. package/packages/piagent-core/runtime/registration/operator-request-intake.ts +49 -0
  243. package/packages/piagent-core/runtime/registration/policy-tools.ts +50 -15
  244. package/packages/piagent-core/runtime/registration/session-commands.ts +1 -1
  245. package/packages/piagent-core/runtime/registration/task-completion-tools.ts +61 -25
  246. package/packages/piagent-core/runtime/registration/task-evidence-tools.ts +21 -12
  247. package/packages/piagent-core/runtime/registration/task-start-guidance.ts +169 -0
  248. package/packages/piagent-core/runtime/registration/task-start-manifest.ts +54 -0
  249. package/packages/piagent-core/runtime/registration/task-start-retry-helpers.ts +37 -0
  250. package/packages/piagent-core/runtime/registration/task-start-tool.ts +108 -103
  251. package/packages/piagent-core/runtime/runtime-limits.ts +16 -2
  252. package/packages/piagent-core/runtime/session/adaptive-context-analysis.ts +461 -0
  253. package/packages/piagent-core/runtime/session/adaptive-context-governor.ts +464 -0
  254. package/packages/piagent-core/runtime/session/adaptive-context-ledger.ts +265 -0
  255. package/packages/piagent-core/runtime/session/message-signals.ts +7 -3
  256. package/packages/piagent-core/runtime/session/operator-request-carry.ts +44 -0
  257. package/packages/piagent-core/runtime/session/runtime-state.ts +161 -5
  258. package/packages/piagent-core/runtime/session/source-checkout-read-grants.ts +35 -0
  259. package/packages/piagent-core/runtime/session/system-prompt.ts +76 -14
  260. package/packages/piagent-core/runtime/session/task-contract-presentation.ts +39 -0
  261. package/packages/piagent-core/runtime/tools/apply-patch-tool.ts +500 -0
  262. package/packages/piagent-core/runtime/tools/phase-tools.ts +8 -8
  263. package/packages/piagent-core/runtime/tools/tool-groups.ts +12 -2
  264. package/packages/piagent-core/runtime/trajectory/trajectory-runtime.ts +2 -1
  265. package/packages/piagent-core/runtime/verification/exact-verifier-reuse.ts +101 -0
  266. package/packages/piagent-core/runtime/workflows/runtime-intake-compaction.ts +164 -0
  267. package/packages/piagent-core/runtime/workflows/task-intake.ts +207 -38
  268. package/packages/piagent-core/security/sensitive-data.js +13 -218
  269. package/packages/piagent-core/security/sensitive-project-file.js +42 -0
  270. package/packages/piagent-core/security/sensitive-source-expression.js +330 -0
  271. package/packages/piagent-core/security/sensitive-source-formats.js +394 -0
  272. package/packages/piagent-core/security/sensitive-text.js +234 -0
  273. package/packages/piagent-core/subagents/piagent-oracle.md +5 -3
  274. package/packages/piagent-core/subagents/piagent-planner.md +6 -4
  275. package/packages/piagent-core/subagents/piagent-reviewer.md +5 -3
  276. package/packages/piagent-core/subagents/piagent-scout.md +4 -2
  277. package/packages/piagent-core/subagents/piagent-worker.md +7 -5
  278. package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-rD9WJKxs.js → MarkdownMessage-B4XehTCU.js} +1 -1
  279. package/packages/piagent-webui/dist/client/assets/index-CgOEyRPG.js +176 -0
  280. package/packages/piagent-webui/dist/client/index.html +1 -1
  281. package/packages/piagent-webui/extension/piagent-webui.ts +3 -1
  282. package/packages/piagent-webui/extension/same-session-bridge.ts +1 -1
  283. package/packages/piagent-webui/extension/session-stream-adapter.ts +33 -10
  284. package/packages/piagent-webui/gateway/gateway-events.ts +109 -5
  285. package/packages/piagent-webui/gateway/gateway-service.ts +3 -0
  286. package/packages/piagent-webui/gateway/gateway-session-stream.ts +122 -20
  287. package/packages/piagent-webui/gateway/session-command-controller.ts +18 -3
  288. package/packages/piagent-webui/gateway/session-effective-options.ts +47 -0
  289. package/packages/piagent-webui/gateway/session-live-state.ts +21 -0
  290. package/packages/piagent-webui/gateway/session-operation-lifecycle.ts +237 -0
  291. package/packages/piagent-webui/gateway/session-operation-retry-control.ts +38 -0
  292. package/packages/piagent-webui/gateway/session-operation-start.ts +5 -1
  293. package/packages/piagent-webui/gateway/session-operation-watchdog.ts +165 -0
  294. package/packages/piagent-webui/gateway/session-runtime-factory.ts +45 -0
  295. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +141 -125
  296. package/packages/piagent-webui/ownership/session-lease-store.ts +5 -2
  297. package/packages/piagent-webui/server/core-inspection-provider.ts +2 -1
  298. package/packages/piagent-webui/server/loopback-server.ts +8 -0
  299. package/packages/piagent-webui/server/transcript-projection.ts +113 -9
  300. package/packages/piagent-webui/shared/text-visibility.ts +10 -0
  301. package/schemas/codex-relative-efficiency-v1.schema.json +155 -0
  302. package/schemas/piagent-webui/catalog-v1.json +9 -0
  303. package/schemas/piagent-webui/gateway-protocol-v1.schema.json +53 -3
  304. package/schemas/piagent-webui/runtime-event-v2.schema.json +15 -5
  305. package/schemas/piagent-webui/session-live-state-v1.schema.json +76 -0
  306. package/schemas/piagent-webui/subagent-tree-v1.schema.json +11 -1
  307. package/schemas/project-profile.schema.json +1 -1
  308. package/schemas/task-contract.schema.json +27 -1
  309. package/scripts/benchmark-runner-core.mjs +367 -363
  310. package/scripts/benchmark-runner-finalization.mjs +313 -0
  311. package/scripts/benchmark-runner-host-readiness.mjs +94 -0
  312. package/scripts/benchmark-runner-support.mjs +200 -0
  313. package/scripts/benchmark-session.mjs +95 -41
  314. package/scripts/configure-model-scope.sh +4 -3
  315. package/scripts/configure-subagents.sh +42 -34
  316. package/scripts/helper-evaluation.mjs +2 -2
  317. package/scripts/install-global.sh +2 -2
  318. package/scripts/pi-usage-history.mjs +37 -10
  319. package/scripts/setup.sh +2 -2
  320. package/scripts/team-doctor.sh +1 -1
  321. package/scripts/verify-local.sh +10 -1
  322. package/templates/global/settings.json +2 -1
  323. package/packages/piagent-webui/dist/client/assets/index-BZRFw1u6.js +0 -174
@@ -0,0 +1,237 @@
1
+ import { hasVisibleText } from "../shared/text-visibility.ts";
2
+
3
+ export type SessionOperationPhase = "pending" | "running" | "retry" | "compaction" | "settled";
4
+
5
+ export type SessionOperationRetryPolicy = Readonly<{
6
+ maximumAttempts: number;
7
+ maximumDelayMs: number;
8
+ }>;
9
+
10
+ export type SessionOperationRetryPolicyOptions = Partial<SessionOperationRetryPolicy>;
11
+
12
+ export type SessionOperationObservation = Readonly<{
13
+ accepted: boolean;
14
+ phase: SessionOperationPhase;
15
+ retry: "none" | "allowed" | "abort";
16
+ reasonCode: string | null;
17
+ }>;
18
+
19
+ const DEFAULT_RETRY_POLICY: SessionOperationRetryPolicy = Object.freeze({
20
+ // Pi's provider retry is useful before a response exists, but a long retry
21
+ // chain burns quota and keeps the browser in Working. One automatic retry
22
+ // absorbs an ordinary transient failure without replaying a persistent one.
23
+ maximumAttempts: 1,
24
+ maximumDelayMs: 8_000
25
+ });
26
+
27
+ function boundedInteger(value: unknown, fallback: number, minimum: number, maximum: number): number {
28
+ if (value === undefined) return fallback;
29
+ if (!Number.isSafeInteger(value) || Number(value) < minimum || Number(value) > maximum) {
30
+ throw new Error("session-operation-retry-policy-invalid");
31
+ }
32
+ return Number(value);
33
+ }
34
+
35
+ export function sessionOperationRetryPolicy(
36
+ options: SessionOperationRetryPolicyOptions = {}
37
+ ): SessionOperationRetryPolicy {
38
+ return Object.freeze({
39
+ maximumAttempts: boundedInteger(options.maximumAttempts, DEFAULT_RETRY_POLICY.maximumAttempts, 0, 10),
40
+ maximumDelayMs: boundedInteger(options.maximumDelayMs, DEFAULT_RETRY_POLICY.maximumDelayMs, 0, 300_000)
41
+ });
42
+ }
43
+
44
+ function correlationRef(event: any): string | null {
45
+ for (const key of ["operationRef", "agentOperationId", "operationId"]) {
46
+ if (typeof event?.[key] === "string" && event[key]) return event[key];
47
+ }
48
+ return null;
49
+ }
50
+
51
+ function visibleAssistantContent(message: any): boolean {
52
+ if (typeof message?.content === "string") return hasVisibleText(message.content);
53
+ if (!Array.isArray(message?.content)) return false;
54
+ return message.content.some((item: any) => {
55
+ if (item?.type === "text") return hasVisibleText(item.text);
56
+ // Images and every model-emitted tool/server-tool block are observable
57
+ // output even when they do not contain user-visible text.
58
+ return ["image", "image_url", "toolCall", "tool_call", "tool_use", "server_tool_use"]
59
+ .includes(String(item?.type ?? ""));
60
+ });
61
+ }
62
+
63
+ function attempt(value: unknown): number | null {
64
+ return Number.isSafeInteger(value) && Number(value) >= 1 ? Number(value) : null;
65
+ }
66
+
67
+ function delay(value: unknown): number | null {
68
+ return Number.isSafeInteger(value) && Number(value) >= 0 ? Number(value) : null;
69
+ }
70
+
71
+ /**
72
+ * Operation-local authority for provider retry, compaction and settlement.
73
+ *
74
+ * Pi's pinned host owns the actual provider retry. This state machine owns the
75
+ * stricter Piagent admission decision and is shared by the Gateway stream and
76
+ * runtime supervisor. It never treats compaction as a provider retry, and it
77
+ * fails closed once assistant output or a tool call makes replay unsafe.
78
+ */
79
+ export class SessionOperationLifecycle {
80
+ readonly operationRef: string;
81
+ readonly retryPolicy: SessionOperationRetryPolicy;
82
+ #phase: SessionOperationPhase = "pending";
83
+ #started = false;
84
+ #hostSettled = false;
85
+ #terminal = false;
86
+ #visibleAssistantOutput = false;
87
+ #toolCallObserved = false;
88
+ #lastRetryAttempt = 0;
89
+ #activeRetryAttempt: number | null = null;
90
+ #retryAbortRequired = false;
91
+
92
+ constructor(options: {
93
+ operationRef: string;
94
+ retryPolicy?: SessionOperationRetryPolicyOptions | SessionOperationRetryPolicy;
95
+ }) {
96
+ this.operationRef = options.operationRef;
97
+ this.retryPolicy = sessionOperationRetryPolicy(options.retryPolicy);
98
+ }
99
+
100
+ get phase(): SessionOperationPhase { return this.#phase; }
101
+ get started(): boolean { return this.#started; }
102
+ get hostSettled(): boolean { return this.#hostSettled; }
103
+ get terminal(): boolean { return this.#terminal; }
104
+ get replayUnsafe(): boolean { return this.#visibleAssistantOutput || this.#toolCallObserved; }
105
+ get retryAbortRequired(): boolean { return this.#retryAbortRequired; }
106
+
107
+ forceHostSettlement(): void {
108
+ this.#started = true;
109
+ this.#hostSettled = true;
110
+ this.#phase = "settled";
111
+ }
112
+
113
+ markTerminal(): boolean {
114
+ if (this.#terminal) return false;
115
+ this.#terminal = true;
116
+ this.#hostSettled = true;
117
+ this.#phase = "settled";
118
+ return true;
119
+ }
120
+
121
+ observe(event: any): SessionOperationObservation {
122
+ if (this.#terminal || this.#hostSettled) return this.#ignored("operation-event-after-settlement");
123
+ const correlated = correlationRef(event);
124
+ if (correlated && correlated !== this.operationRef) return this.#ignored("operation-correlation-mismatch");
125
+ const type = String(event?.type ?? "");
126
+
127
+ if (type === "agent_start") {
128
+ this.#started = true;
129
+ this.#phase = "running";
130
+ return this.#accepted();
131
+ }
132
+ if (type === "agent_settled") {
133
+ this.#started = true;
134
+ this.#hostSettled = true;
135
+ this.#phase = "settled";
136
+ return this.#accepted();
137
+ }
138
+
139
+ // Direct stream fixtures and some deferred command hosts begin with a
140
+ // message/tool event. Treat that as an observed start while still refusing
141
+ // uncorrelated retry/compaction lifecycle events before any operation work.
142
+ if (["message_start", "message_update", "message_end", "tool_execution_start",
143
+ "tool_execution_update", "tool_execution_end", "turn_start", "turn_end"].includes(type)) {
144
+ this.#started = true;
145
+ if (this.#phase === "pending") this.#phase = "running";
146
+ }
147
+
148
+ if (type === "message_update") {
149
+ const update = event?.assistantMessageEvent;
150
+ if (update?.type === "text_delta" && hasVisibleText(update.delta)) this.#visibleAssistantOutput = true;
151
+ if (visibleAssistantContent(event?.message)) this.#visibleAssistantOutput = true;
152
+ return this.#accepted();
153
+ }
154
+ if (type === "message_end" && event?.message?.role === "assistant") {
155
+ if (visibleAssistantContent(event.message)) this.#visibleAssistantOutput = true;
156
+ return this.#accepted();
157
+ }
158
+ if (type === "tool_execution_start") {
159
+ this.#toolCallObserved = true;
160
+ return this.#accepted();
161
+ }
162
+
163
+ if (type === "agent_end" && event?.willRetry === true && this.replayUnsafe) {
164
+ return this.#abortRetry("automatic-retry-replay-unsafe");
165
+ }
166
+ if (type === "auto_retry_start") return this.#retryStarted(event);
167
+ if (type === "auto_retry_end") return this.#retryEnded(event);
168
+
169
+ // Summarization retries belong to compaction and never consume or inherit
170
+ // the provider-turn retry budget.
171
+ if (type === "compaction_start") {
172
+ if (!this.#started) return this.#ignored("operation-event-before-start");
173
+ if (this.#phase === "retry") this.#retryAbortRequired = true;
174
+ this.#phase = "compaction";
175
+ return this.#retryAbortRequired
176
+ ? this.#abortRetry("automatic-retry-compaction-overlap")
177
+ : this.#accepted();
178
+ }
179
+ if (type === "compaction_end") {
180
+ if (this.#phase !== "compaction") return this.#ignored("compaction-event-stale");
181
+ this.#phase = "running";
182
+ return this.#accepted();
183
+ }
184
+ if (["summarization_retry_scheduled", "summarization_retry_attempt_start",
185
+ "summarization_retry_finished"].includes(type)) {
186
+ return this.#phase === "compaction" ? this.#accepted() : this.#ignored("compaction-event-stale");
187
+ }
188
+ return this.#accepted();
189
+ }
190
+
191
+ #retryStarted(event: any): SessionOperationObservation {
192
+ if (!this.#started) return this.#ignored("operation-event-before-start");
193
+ const currentAttempt = attempt(event?.attempt), currentDelay = delay(event?.delayMs);
194
+ if (currentAttempt === null || currentDelay === null) return this.#abortRetry("automatic-retry-metadata-invalid");
195
+ if (currentAttempt === this.#lastRetryAttempt) return this.#ignored("automatic-retry-event-duplicate");
196
+ if (currentAttempt !== this.#lastRetryAttempt + 1) {
197
+ this.#activeRetryAttempt = currentAttempt;
198
+ this.#phase = "retry";
199
+ return this.#abortRetry("automatic-retry-attempt-stale");
200
+ }
201
+ this.#lastRetryAttempt = currentAttempt;
202
+ this.#activeRetryAttempt = currentAttempt;
203
+ if (this.#phase === "compaction") return this.#abortRetry("automatic-retry-compaction-overlap");
204
+ this.#phase = "retry";
205
+ if (this.replayUnsafe) return this.#abortRetry("automatic-retry-replay-unsafe");
206
+ if (currentAttempt > this.retryPolicy.maximumAttempts) return this.#abortRetry("automatic-retry-attempt-limit");
207
+ if (currentDelay > this.retryPolicy.maximumDelayMs) return this.#abortRetry("automatic-retry-delay-limit");
208
+ return { accepted: true, phase: this.#phase, retry: "allowed", reasonCode: null };
209
+ }
210
+
211
+ #retryEnded(event: any): SessionOperationObservation {
212
+ const currentAttempt = attempt(event?.attempt);
213
+ if (currentAttempt === null || currentAttempt !== this.#activeRetryAttempt) {
214
+ return this.#ignored("automatic-retry-event-stale");
215
+ }
216
+ this.#activeRetryAttempt = null;
217
+ // Keep the highest attempt for the whole logical operation so hosts that
218
+ // emit retry_end between attempts still have a monotonic sequence. Keep an
219
+ // abort latched too: retry_end can arrive synchronously before the
220
+ // supervisor's cancellation microtask observes the host AbortController.
221
+ if (this.#phase === "retry") this.#phase = "running";
222
+ return this.#accepted();
223
+ }
224
+
225
+ #abortRetry(reasonCode: string): SessionOperationObservation {
226
+ this.#retryAbortRequired = true;
227
+ return { accepted: true, phase: this.#phase, retry: "abort", reasonCode };
228
+ }
229
+
230
+ #accepted(): SessionOperationObservation {
231
+ return { accepted: true, phase: this.#phase, retry: "none", reasonCode: null };
232
+ }
233
+
234
+ #ignored(reasonCode: string): SessionOperationObservation {
235
+ return { accepted: false, phase: this.#phase, retry: "none", reasonCode };
236
+ }
237
+ }
@@ -0,0 +1,38 @@
1
+ type RetryObservation = { retry?: unknown } | null | undefined;
2
+
3
+ function invoke(action: (() => unknown) | null): void {
4
+ if (!action) return;
5
+ try {
6
+ const result = action();
7
+ if (result && typeof (result as PromiseLike<unknown>).then === "function") {
8
+ void Promise.resolve(result).catch(() => undefined);
9
+ }
10
+ } catch { /* the operation watchdog remains the terminal authority */ }
11
+ }
12
+
13
+ /**
14
+ * Cancels a host-owned provider retry without replaying the prompt. Pinned Pi
15
+ * creates its retry AbortController immediately after auto_retry_start is
16
+ * emitted, so the microtask always runs before even a zero-millisecond timer.
17
+ */
18
+ export class SessionOperationRetryCancellation {
19
+ readonly #session: any;
20
+ #fallbackIssued = false;
21
+
22
+ constructor(session: any) { this.#session = session; }
23
+
24
+ observe(observation: RetryObservation): void {
25
+ if (observation?.retry !== "abort") return;
26
+ if (typeof this.#session?.abortRetry === "function") {
27
+ const cancel = () => invoke(() => this.#session.abortRetry());
28
+ cancel();
29
+ queueMicrotask(cancel);
30
+ return;
31
+ }
32
+ // Unknown hosts fail closed once. Replaying a tool-capable turn is more
33
+ // dangerous than ending the logical operation with an explicit error.
34
+ if (this.#fallbackIssued || typeof this.#session?.abort !== "function") return;
35
+ this.#fallbackIssued = true;
36
+ invoke(() => this.#session.abort());
37
+ }
38
+ }
@@ -12,7 +12,10 @@ export async function waitForOperationStart(
12
12
  prompt.then(() => ({ state: "prompt-resolved" as const }),
13
13
  (error: unknown) => ({ state: "prompt-rejected" as const, error }))
14
14
  ]);
15
- if (first.state === "started") return "prompt-owned";
15
+ if (first.state === "started") {
16
+ if (stream.lifecycleTerminationReasonCode) throw new Error(stream.lifecycleTerminationReasonCode);
17
+ return "prompt-owned";
18
+ }
16
19
  if (first.state === "prompt-rejected") throw first.error;
17
20
 
18
21
  // Extension commands such as `/workflow` launch their agent turn through
@@ -27,6 +30,7 @@ export async function waitForOperationStart(
27
30
  DEFERRED_OPERATION_START_GRACE_MS);
28
31
  })
29
32
  ]);
33
+ if (stream.lifecycleTerminationReasonCode) throw new Error(stream.lifecycleTerminationReasonCode);
30
34
  return "deferred";
31
35
  } finally {
32
36
  if (timer) clearTimeout(timer);
@@ -0,0 +1,165 @@
1
+ import { SessionOperationRetryCancellation } from "./session-operation-retry-control.ts";
2
+
3
+ export type SessionOperationDeadlineReason = "operation-inactivity-timeout" | "operation-deadline-exceeded";
4
+
5
+ export type SessionOperationDeadlinePolicy = Readonly<{
6
+ inactivityTimeoutMs: number;
7
+ maximumDurationMs: number;
8
+ terminationTimeoutMs: number;
9
+ projectionTimeoutMs: number;
10
+ }>;
11
+
12
+ export type SessionOperationWatchdogOptions = Partial<SessionOperationDeadlinePolicy>;
13
+ export type BoundedResult<T> = { state: "settled"; value: T } | { state: "rejected"; error: unknown } | { state: "timeout" };
14
+ export type SessionOperationTerminationResult = { state: "settled" } | { state: "quarantine"; reasonCode: string };
15
+
16
+ export function bestEffortUnsubscribe(unsubscribe: (() => void) | null): void {
17
+ try { unsubscribe?.(); } catch { /* broken host cleanup cannot retain operation authority */ }
18
+ }
19
+
20
+ // A silent tool/provider gets 15 minutes. Any observed host event refreshes that
21
+ // allowance, while the six-hour ceiling prevents an endless stream of progress
22
+ // events from retaining runtime authority forever. Cleanup itself is separately
23
+ // bounded so Stop and watchdog recovery cannot inherit the original hang.
24
+ const DEFAULT_POLICY: SessionOperationDeadlinePolicy = Object.freeze({
25
+ inactivityTimeoutMs: 15 * 60_000,
26
+ maximumDurationMs: 6 * 60 * 60_000,
27
+ terminationTimeoutMs: 5_000,
28
+ projectionTimeoutMs: 2_500
29
+ });
30
+ const MAX_TIMEOUT_MS = 24 * 60 * 60_000;
31
+ const TERMINATION_CLEANUP_FAILED = "operation-termination-cleanup-failed";
32
+
33
+ function duration(value: unknown, fallback: number): number {
34
+ if (value === undefined) return fallback;
35
+ if (!Number.isSafeInteger(value) || Number(value) < 1 || Number(value) > MAX_TIMEOUT_MS) {
36
+ throw new Error("session-operation-watchdog-config-invalid");
37
+ }
38
+ return Number(value);
39
+ }
40
+
41
+ export function sessionOperationDeadlinePolicy(options: SessionOperationWatchdogOptions = {}): SessionOperationDeadlinePolicy {
42
+ const policy = {
43
+ inactivityTimeoutMs: duration(options.inactivityTimeoutMs, DEFAULT_POLICY.inactivityTimeoutMs),
44
+ maximumDurationMs: duration(options.maximumDurationMs, DEFAULT_POLICY.maximumDurationMs),
45
+ terminationTimeoutMs: duration(options.terminationTimeoutMs, DEFAULT_POLICY.terminationTimeoutMs),
46
+ projectionTimeoutMs: duration(options.projectionTimeoutMs, DEFAULT_POLICY.projectionTimeoutMs)
47
+ };
48
+ if (policy.projectionTimeoutMs > policy.terminationTimeoutMs) throw new Error("session-operation-watchdog-config-invalid");
49
+ return Object.freeze(policy);
50
+ }
51
+
52
+ export async function boundedResult<T>(promise: PromiseLike<T>, timeoutMs: number): Promise<BoundedResult<T>> {
53
+ let timer: ReturnType<typeof setTimeout> | undefined;
54
+ try {
55
+ return await Promise.race([
56
+ Promise.resolve(promise).then((value) => ({ state: "settled" as const, value }),
57
+ (error: unknown) => ({ state: "rejected" as const, error })),
58
+ new Promise<{ state: "timeout" }>((resolve) => { timer = setTimeout(() => resolve({ state: "timeout" }), timeoutMs); })
59
+ ]);
60
+ } finally {
61
+ if (timer) clearTimeout(timer);
62
+ }
63
+ }
64
+
65
+ export class SessionOperationWatchdog {
66
+ readonly policy: SessionOperationDeadlinePolicy;
67
+ #idleTimer: ReturnType<typeof setTimeout> | null = null;
68
+ #maximumTimer: ReturnType<typeof setTimeout> | null = null;
69
+ #expire: ((reason: SessionOperationDeadlineReason) => void) | null = null;
70
+ #closed = false;
71
+ #termination: Promise<unknown> | null = null;
72
+
73
+ constructor(policy: SessionOperationDeadlinePolicy) { this.policy = policy; }
74
+ get terminating(): boolean { return this.#termination !== null; }
75
+
76
+ start(expire: (reason: SessionOperationDeadlineReason) => void): void {
77
+ if (this.#expire || this.#closed) throw new Error("session-operation-watchdog-state-invalid");
78
+ this.#expire = expire;
79
+ this.#armIdle();
80
+ this.#maximumTimer = setTimeout(() => this.#deadline("operation-deadline-exceeded"), this.policy.maximumDurationMs);
81
+ // An accepted operation owns live runtime work until it settles. Keep both
82
+ // deadline timers referenced so a headless Gateway cannot let Node exit
83
+ // while the provider promise is pending and silently skip recovery.
84
+ }
85
+
86
+ progress(): void {
87
+ if (this.#closed || !this.#expire) return;
88
+ this.#armIdle();
89
+ }
90
+
91
+ close(): void {
92
+ if (this.#closed) return;
93
+ this.#closed = true;
94
+ if (this.#idleTimer) clearTimeout(this.#idleTimer);
95
+ if (this.#maximumTimer) clearTimeout(this.#maximumTimer);
96
+ this.#idleTimer = null; this.#maximumTimer = null; this.#expire = null;
97
+ }
98
+
99
+ terminate<T>(run: () => Promise<T>): Promise<T> {
100
+ if (!this.#termination) { this.close(); this.#termination = Promise.resolve().then(run); }
101
+ return this.#termination as Promise<T>;
102
+ }
103
+
104
+ #armIdle(): void {
105
+ if (this.#idleTimer) clearTimeout(this.#idleTimer);
106
+ this.#idleTimer = setTimeout(() => this.#deadline("operation-inactivity-timeout"), this.policy.inactivityTimeoutMs);
107
+ }
108
+
109
+ #deadline(reason: SessionOperationDeadlineReason): void {
110
+ if (this.#closed) return;
111
+ const expire = this.#expire; this.close(); expire?.(reason);
112
+ }
113
+ }
114
+
115
+ export function armSessionOperationWatchdog(options: {
116
+ watchdog: SessionOperationWatchdog;
117
+ subscribe(listener: (event: unknown) => void): unknown;
118
+ observe(event: unknown): unknown;
119
+ retrySession?: any;
120
+ expire(reason: SessionOperationDeadlineReason): void;
121
+ }): () => void {
122
+ const retry = new SessionOperationRetryCancellation(options.retrySession);
123
+ const unsubscribe = options.subscribe((event) => {
124
+ options.watchdog.progress();
125
+ retry.observe(options.observe(event) as { retry?: unknown } | null | undefined);
126
+ });
127
+ if (typeof unsubscribe !== "function") throw new Error("session-operation-subscribe-invalid");
128
+ try { options.watchdog.start(options.expire); }
129
+ catch (error) { try { unsubscribe(); } catch { /* authority is quarantined by the caller */ } throw error; }
130
+ return () => { unsubscribe(); };
131
+ }
132
+
133
+ export async function terminateWatchedSessionOperation(options: {
134
+ watchdog: SessionOperationWatchdog;
135
+ settlement: "aborted" | "error";
136
+ reasonCode: string;
137
+ forcedReasonCode: string;
138
+ stream: { markAborted(reasonCode: string): void; markError(reasonCode: string): void;
139
+ forceLifecycleTermination(reasonCode: string): void };
140
+ completion(): Promise<void> | null;
141
+ settledCleanly(): boolean;
142
+ cancelApproval(reasonCode: string): void;
143
+ abortHost(): unknown;
144
+ clearQueue?(): void;
145
+ }): Promise<SessionOperationTerminationResult> {
146
+ return await options.watchdog.terminate(async () => {
147
+ const mark = (reasonCode: string) => options.settlement === "aborted"
148
+ ? options.stream.markAborted(reasonCode) : options.stream.markError(reasonCode);
149
+ let cleanupFailed = false;
150
+ try { options.cancelApproval(options.reasonCode); } catch { cleanupFailed = true; }
151
+ try { options.clearQueue?.(); } catch { cleanupFailed = true; }
152
+ const terminalReason = cleanupFailed ? TERMINATION_CLEANUP_FAILED : options.reasonCode;
153
+ mark(terminalReason);
154
+ void Promise.resolve().then(options.abortHost).catch(() => undefined);
155
+ const completion = options.completion();
156
+ const completed = completion ? await boundedResult(completion, options.watchdog.policy.terminationTimeoutMs)
157
+ : { state: "timeout" as const };
158
+ if (!cleanupFailed && completed.state === "settled" && options.settledCleanly()) return { state: "settled" as const };
159
+ const quarantineReason = cleanupFailed ? TERMINATION_CLEANUP_FAILED : options.forcedReasonCode;
160
+ mark(quarantineReason); options.stream.forceLifecycleTermination(quarantineReason);
161
+ const forcedCompletion = options.completion();
162
+ if (forcedCompletion) await boundedResult(forcedCompletion, options.watchdog.policy.projectionTimeoutMs);
163
+ return { state: "quarantine" as const, reasonCode: quarantineReason };
164
+ });
165
+ }
@@ -0,0 +1,45 @@
1
+ import path from "node:path";
2
+
3
+ import type { PiSessionInfo } from "./session-catalog.ts";
4
+ import { preferAuthoritativePiagentGuard } from "./extension-authority.ts";
5
+ import { rpcUiContext } from "./rpc-ui-context.ts";
6
+
7
+ export type RuntimeHandle = { dispose(): Promise<void>; session?: any };
8
+ export type RuntimeFactory = (info: PiSessionInfo, runtimeInstanceRef: string,
9
+ sessionManager?: any) => Promise<RuntimeHandle>;
10
+
11
+ export function createProductionRuntimeFactory(options: {
12
+ host: any;
13
+ agentDir: string;
14
+ packageRoot: string;
15
+ modelRuntime?: any;
16
+ }): RuntimeFactory {
17
+ return async (info, _runtimeInstanceRef, sessionManager) => {
18
+ const guard = path.join(options.packageRoot, "packages", "piagent-core", "extensions", "piagent-guard.ts");
19
+ const createRuntime = async ({ cwd, agentDir, sessionManager, sessionStartEvent }: any) => {
20
+ const services = await options.host.createAgentSessionServices({
21
+ cwd, agentDir, modelRuntime: options.modelRuntime,
22
+ resourceLoaderOptions: {
23
+ additionalExtensionPaths: [guard],
24
+ extensionsOverride: preferAuthoritativePiagentGuard(guard)
25
+ }
26
+ });
27
+ const extensionErrors = services.resourceLoader.getExtensions().errors;
28
+ if (extensionErrors.length) throw new Error("session-runtime-extension-load-failed");
29
+ const created = await options.host.createAgentSessionFromServices({ services, sessionManager, sessionStartEvent });
30
+ return { ...created, services, diagnostics: services.diagnostics };
31
+ };
32
+ const manager = sessionManager ?? options.host.SessionManager.open(info.path);
33
+ const runtime = await options.host.createAgentSessionRuntime(createRuntime, {
34
+ cwd: info.cwd,
35
+ agentDir: options.agentDir,
36
+ sessionManager: manager,
37
+ sessionStartEvent: { type: "session_start", reason: "resume", previousSessionFile: info.path }
38
+ });
39
+ const bind = async (session: any) => session.bindExtensions({ mode: "rpc", uiContext: rpcUiContext() });
40
+ runtime.setRebindSession(bind);
41
+ try { await bind(runtime.session); }
42
+ catch (error) { await runtime.dispose().catch(() => undefined); throw error; }
43
+ return runtime;
44
+ };
45
+ }