@caupulican/pi-adaptative 0.81.40 → 0.81.41

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 (406) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -1
  3. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +1 -0
  4. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -1
  5. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +1 -0
  6. package/dist/cli/args.d.ts +2 -0
  7. package/dist/cli/args.d.ts.map +1 -1
  8. package/dist/cli/args.js +22 -1
  9. package/dist/cli/args.js.map +1 -1
  10. package/dist/core/agent-paths.d.ts +6 -0
  11. package/dist/core/agent-paths.d.ts.map +1 -1
  12. package/dist/core/agent-paths.js +12 -0
  13. package/dist/core/agent-paths.js.map +1 -1
  14. package/dist/core/agent-session-contracts.d.ts +293 -0
  15. package/dist/core/agent-session-contracts.d.ts.map +1 -0
  16. package/dist/core/agent-session-contracts.js +26 -0
  17. package/dist/core/agent-session-contracts.js.map +1 -0
  18. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  19. package/dist/core/agent-session-runtime.js +3 -0
  20. package/dist/core/agent-session-runtime.js.map +1 -1
  21. package/dist/core/agent-session.d.ts +26 -405
  22. package/dist/core/agent-session.d.ts.map +1 -1
  23. package/dist/core/agent-session.js +86 -307
  24. package/dist/core/agent-session.js.map +1 -1
  25. package/dist/core/auth-storage.d.ts.map +1 -1
  26. package/dist/core/auth-storage.js +3 -1
  27. package/dist/core/auth-storage.js.map +1 -1
  28. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  29. package/dist/core/autonomy/lane-tool-surface.js +2 -1
  30. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  31. package/dist/core/background-lane-controller.d.ts +3 -1
  32. package/dist/core/background-lane-controller.d.ts.map +1 -1
  33. package/dist/core/background-lane-controller.js +1 -0
  34. package/dist/core/background-lane-controller.js.map +1 -1
  35. package/dist/core/bedrock-sso-login.d.ts +16 -0
  36. package/dist/core/bedrock-sso-login.d.ts.map +1 -0
  37. package/dist/core/bedrock-sso-login.js +98 -0
  38. package/dist/core/bedrock-sso-login.js.map +1 -0
  39. package/dist/core/compaction-controller.d.ts.map +1 -1
  40. package/dist/core/compaction-controller.js +1 -1
  41. package/dist/core/compaction-controller.js.map +1 -1
  42. package/dist/core/compaction-support.d.ts +3 -8
  43. package/dist/core/compaction-support.d.ts.map +1 -1
  44. package/dist/core/compaction-support.js +3 -3
  45. package/dist/core/compaction-support.js.map +1 -1
  46. package/dist/core/context-pipeline.d.ts +1 -1
  47. package/dist/core/context-pipeline.d.ts.map +1 -1
  48. package/dist/core/context-pipeline.js +7 -33
  49. package/dist/core/context-pipeline.js.map +1 -1
  50. package/dist/core/cost/cost-summary.d.ts.map +1 -1
  51. package/dist/core/cost/cost-summary.js +5 -3
  52. package/dist/core/cost/cost-summary.js.map +1 -1
  53. package/dist/core/cost/daily-usage.d.ts.map +1 -1
  54. package/dist/core/cost/daily-usage.js +4 -5
  55. package/dist/core/cost/daily-usage.js.map +1 -1
  56. package/dist/core/default-tool-surface.d.ts.map +1 -1
  57. package/dist/core/default-tool-surface.js +1 -0
  58. package/dist/core/default-tool-surface.js.map +1 -1
  59. package/dist/core/extension-import-authority.d.ts +6 -0
  60. package/dist/core/extension-import-authority.d.ts.map +1 -0
  61. package/dist/core/extension-import-authority.js +10 -0
  62. package/dist/core/extension-import-authority.js.map +1 -0
  63. package/dist/core/extensions/loader.d.ts.map +1 -1
  64. package/dist/core/extensions/loader.js +2 -3
  65. package/dist/core/extensions/loader.js.map +1 -1
  66. package/dist/core/extensions/runner.d.ts +3 -0
  67. package/dist/core/extensions/runner.d.ts.map +1 -1
  68. package/dist/core/extensions/runner.js +14 -5
  69. package/dist/core/extensions/runner.js.map +1 -1
  70. package/dist/core/extensions/stale-context.d.ts +2 -0
  71. package/dist/core/extensions/stale-context.d.ts.map +1 -0
  72. package/dist/core/extensions/stale-context.js +2 -0
  73. package/dist/core/extensions/stale-context.js.map +1 -0
  74. package/dist/core/extensions/types.d.ts +8 -0
  75. package/dist/core/extensions/types.d.ts.map +1 -1
  76. package/dist/core/extensions/types.js.map +1 -1
  77. package/dist/core/foreground-recovery-controller.d.ts +1 -0
  78. package/dist/core/foreground-recovery-controller.d.ts.map +1 -1
  79. package/dist/core/foreground-recovery-controller.js +13 -13
  80. package/dist/core/foreground-recovery-controller.js.map +1 -1
  81. package/dist/core/goal-loop-controller.d.ts +14 -9
  82. package/dist/core/goal-loop-controller.d.ts.map +1 -1
  83. package/dist/core/goal-loop-controller.js +47 -75
  84. package/dist/core/goal-loop-controller.js.map +1 -1
  85. package/dist/core/goals/compact-goal-context.d.ts +11 -0
  86. package/dist/core/goals/compact-goal-context.d.ts.map +1 -0
  87. package/dist/core/goals/compact-goal-context.js +59 -0
  88. package/dist/core/goals/compact-goal-context.js.map +1 -0
  89. package/dist/core/goals/goal-acceptance.d.ts.map +1 -1
  90. package/dist/core/goals/goal-acceptance.js +2 -0
  91. package/dist/core/goals/goal-acceptance.js.map +1 -1
  92. package/dist/core/goals/goal-auto-continue-controller.d.ts +2 -1
  93. package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -1
  94. package/dist/core/goals/goal-auto-continue-controller.js +5 -8
  95. package/dist/core/goals/goal-auto-continue-controller.js.map +1 -1
  96. package/dist/core/goals/goal-continuation-controller.d.ts +2 -2
  97. package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
  98. package/dist/core/goals/goal-continuation-controller.js +42 -11
  99. package/dist/core/goals/goal-continuation-controller.js.map +1 -1
  100. package/dist/core/goals/goal-continuation-defaults.d.ts +4 -29
  101. package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -1
  102. package/dist/core/goals/goal-continuation-defaults.js +4 -32
  103. package/dist/core/goals/goal-continuation-defaults.js.map +1 -1
  104. package/dist/core/goals/goal-continuation-prompt.d.ts +8 -18
  105. package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
  106. package/dist/core/goals/goal-continuation-prompt.js +9 -179
  107. package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
  108. package/dist/core/goals/goal-lifecycle.d.ts +35 -12
  109. package/dist/core/goals/goal-lifecycle.d.ts.map +1 -1
  110. package/dist/core/goals/goal-lifecycle.js +98 -13
  111. package/dist/core/goals/goal-lifecycle.js.map +1 -1
  112. package/dist/core/goals/goal-record.d.ts +17 -0
  113. package/dist/core/goals/goal-record.d.ts.map +1 -0
  114. package/dist/core/goals/goal-record.js +31 -0
  115. package/dist/core/goals/goal-record.js.map +1 -0
  116. package/dist/core/goals/goal-session-controller.d.ts +42 -0
  117. package/dist/core/goals/goal-session-controller.d.ts.map +1 -0
  118. package/dist/core/goals/goal-session-controller.js +128 -0
  119. package/dist/core/goals/goal-session-controller.js.map +1 -0
  120. package/dist/core/goals/goal-state.d.ts +45 -25
  121. package/dist/core/goals/goal-state.d.ts.map +1 -1
  122. package/dist/core/goals/goal-state.js +85 -15
  123. package/dist/core/goals/goal-state.js.map +1 -1
  124. package/dist/core/goals/goal-tool-core.d.ts +1 -4
  125. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  126. package/dist/core/goals/goal-tool-core.js +49 -34
  127. package/dist/core/goals/goal-tool-core.js.map +1 -1
  128. package/dist/core/goals/session-goal-state.d.ts +18 -8
  129. package/dist/core/goals/session-goal-state.d.ts.map +1 -1
  130. package/dist/core/goals/session-goal-state.js +134 -11
  131. package/dist/core/goals/session-goal-state.js.map +1 -1
  132. package/dist/core/human-input-controller.d.ts +47 -0
  133. package/dist/core/human-input-controller.d.ts.map +1 -0
  134. package/dist/core/human-input-controller.js +181 -0
  135. package/dist/core/human-input-controller.js.map +1 -0
  136. package/dist/core/local-runtime-controller.d.ts +1 -1
  137. package/dist/core/local-runtime-controller.d.ts.map +1 -1
  138. package/dist/core/local-runtime-controller.js.map +1 -1
  139. package/dist/core/model-capability.d.ts +0 -19
  140. package/dist/core/model-capability.d.ts.map +1 -1
  141. package/dist/core/model-capability.js +0 -19
  142. package/dist/core/model-capability.js.map +1 -1
  143. package/dist/core/model-registry.d.ts +6 -1
  144. package/dist/core/model-registry.d.ts.map +1 -1
  145. package/dist/core/model-registry.js +13 -5
  146. package/dist/core/model-registry.js.map +1 -1
  147. package/dist/core/model-resolver.d.ts +16 -1
  148. package/dist/core/model-resolver.d.ts.map +1 -1
  149. package/dist/core/model-resolver.js +32 -16
  150. package/dist/core/model-resolver.js.map +1 -1
  151. package/dist/core/model-router-controller.d.ts +1 -1
  152. package/dist/core/model-router-controller.d.ts.map +1 -1
  153. package/dist/core/model-router-controller.js.map +1 -1
  154. package/dist/core/model-selection-controller.d.ts +1 -1
  155. package/dist/core/model-selection-controller.d.ts.map +1 -1
  156. package/dist/core/model-selection-controller.js.map +1 -1
  157. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
  158. package/dist/core/orchestration/delegation-ledger.js +3 -0
  159. package/dist/core/orchestration/delegation-ledger.js.map +1 -1
  160. package/dist/core/orchestration/work-state-projection.d.ts.map +1 -1
  161. package/dist/core/orchestration/work-state-projection.js +1 -1
  162. package/dist/core/orchestration/work-state-projection.js.map +1 -1
  163. package/dist/core/package-manager.d.ts.map +1 -1
  164. package/dist/core/package-manager.js +20 -3
  165. package/dist/core/package-manager.js.map +1 -1
  166. package/dist/core/profile-filter-controller.d.ts +8 -1
  167. package/dist/core/profile-filter-controller.d.ts.map +1 -1
  168. package/dist/core/profile-filter-controller.js +23 -5
  169. package/dist/core/profile-filter-controller.js.map +1 -1
  170. package/dist/core/prompt-templates.d.ts +1 -0
  171. package/dist/core/prompt-templates.d.ts.map +1 -1
  172. package/dist/core/prompt-templates.js +18 -29
  173. package/dist/core/prompt-templates.js.map +1 -1
  174. package/dist/core/reflection-controller.d.ts +1 -1
  175. package/dist/core/reflection-controller.d.ts.map +1 -1
  176. package/dist/core/reflection-controller.js +3 -1
  177. package/dist/core/reflection-controller.js.map +1 -1
  178. package/dist/core/request-auth.d.ts +7 -0
  179. package/dist/core/request-auth.d.ts.map +1 -0
  180. package/dist/core/request-auth.js +8 -0
  181. package/dist/core/request-auth.js.map +1 -0
  182. package/dist/core/resource-loader.d.ts.map +1 -1
  183. package/dist/core/resource-loader.js +16 -6
  184. package/dist/core/resource-loader.js.map +1 -1
  185. package/dist/core/risk-classifier.d.ts.map +1 -1
  186. package/dist/core/risk-classifier.js +8 -0
  187. package/dist/core/risk-classifier.js.map +1 -1
  188. package/dist/core/runtime-builder.d.ts +15 -3
  189. package/dist/core/runtime-builder.d.ts.map +1 -1
  190. package/dist/core/runtime-builder.js +132 -79
  191. package/dist/core/runtime-builder.js.map +1 -1
  192. package/dist/core/sdk.d.ts.map +1 -1
  193. package/dist/core/sdk.js +7 -1
  194. package/dist/core/sdk.js.map +1 -1
  195. package/dist/core/secrets/credential-exposure-guard.d.ts +9 -0
  196. package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -0
  197. package/dist/core/secrets/credential-exposure-guard.js +241 -0
  198. package/dist/core/secrets/credential-exposure-guard.js.map +1 -0
  199. package/dist/core/secrets/secret-dotenv.d.ts +27 -0
  200. package/dist/core/secrets/secret-dotenv.d.ts.map +1 -0
  201. package/dist/core/secrets/secret-dotenv.js +183 -0
  202. package/dist/core/secrets/secret-dotenv.js.map +1 -0
  203. package/dist/core/secrets/secret-vault-format.d.ts +112 -0
  204. package/dist/core/secrets/secret-vault-format.d.ts.map +1 -0
  205. package/dist/core/secrets/secret-vault-format.js +397 -0
  206. package/dist/core/secrets/secret-vault-format.js.map +1 -0
  207. package/dist/core/secrets/secret-vault.d.ts +72 -0
  208. package/dist/core/secrets/secret-vault.d.ts.map +1 -0
  209. package/dist/core/secrets/secret-vault.js +671 -0
  210. package/dist/core/secrets/secret-vault.js.map +1 -0
  211. package/dist/core/session-analytics.d.ts +4 -23
  212. package/dist/core/session-analytics.d.ts.map +1 -1
  213. package/dist/core/session-analytics.js +39 -69
  214. package/dist/core/session-analytics.js.map +1 -1
  215. package/dist/core/session-role.d.ts +5 -0
  216. package/dist/core/session-role.d.ts.map +1 -1
  217. package/dist/core/session-role.js +14 -1
  218. package/dist/core/session-role.js.map +1 -1
  219. package/dist/core/session-tree-navigator.d.ts +4 -6
  220. package/dist/core/session-tree-navigator.d.ts.map +1 -1
  221. package/dist/core/session-tree-navigator.js +4 -1
  222. package/dist/core/session-tree-navigator.js.map +1 -1
  223. package/dist/core/settings-manager.d.ts +1 -1
  224. package/dist/core/settings-manager.d.ts.map +1 -1
  225. package/dist/core/settings-manager.js +1 -1
  226. package/dist/core/settings-manager.js.map +1 -1
  227. package/dist/core/slash-commands.d.ts.map +1 -1
  228. package/dist/core/slash-commands.js +2 -2
  229. package/dist/core/slash-commands.js.map +1 -1
  230. package/dist/core/tool-capability-policy.d.ts.map +1 -1
  231. package/dist/core/tool-capability-policy.js +1 -0
  232. package/dist/core/tool-capability-policy.js.map +1 -1
  233. package/dist/core/tool-gate-controller.d.ts.map +1 -1
  234. package/dist/core/tool-gate-controller.js +8 -2
  235. package/dist/core/tool-gate-controller.js.map +1 -1
  236. package/dist/core/tool-protocol-controller.d.ts +2 -4
  237. package/dist/core/tool-protocol-controller.d.ts.map +1 -1
  238. package/dist/core/tool-protocol-controller.js.map +1 -1
  239. package/dist/core/tool-recovery-stats.d.ts +21 -1
  240. package/dist/core/tool-recovery-stats.d.ts.map +1 -1
  241. package/dist/core/tool-recovery-stats.js.map +1 -1
  242. package/dist/core/tools/bash.d.ts +5 -0
  243. package/dist/core/tools/bash.d.ts.map +1 -1
  244. package/dist/core/tools/bash.js +59 -5
  245. package/dist/core/tools/bash.js.map +1 -1
  246. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  247. package/dist/core/tools/delegate-status.js +6 -7
  248. package/dist/core/tools/delegate-status.js.map +1 -1
  249. package/dist/core/tools/delegate.d.ts.map +1 -1
  250. package/dist/core/tools/delegate.js +6 -8
  251. package/dist/core/tools/delegate.js.map +1 -1
  252. package/dist/core/tools/git-filter.d.ts +1 -8
  253. package/dist/core/tools/git-filter.d.ts.map +1 -1
  254. package/dist/core/tools/git-filter.js +2 -63
  255. package/dist/core/tools/git-filter.js.map +1 -1
  256. package/dist/core/tools/goal.d.ts +5 -3
  257. package/dist/core/tools/goal.d.ts.map +1 -1
  258. package/dist/core/tools/goal.js +97 -19
  259. package/dist/core/tools/goal.js.map +1 -1
  260. package/dist/core/tools/index.d.ts +1 -0
  261. package/dist/core/tools/index.d.ts.map +1 -1
  262. package/dist/core/tools/index.js +1 -0
  263. package/dist/core/tools/index.js.map +1 -1
  264. package/dist/core/tools/orchestration-panel.d.ts +1 -4
  265. package/dist/core/tools/orchestration-panel.d.ts.map +1 -1
  266. package/dist/core/tools/orchestration-panel.js +0 -44
  267. package/dist/core/tools/orchestration-panel.js.map +1 -1
  268. package/dist/core/tools/output-accumulator.d.ts +11 -0
  269. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  270. package/dist/core/tools/output-accumulator.js +36 -3
  271. package/dist/core/tools/output-accumulator.js.map +1 -1
  272. package/dist/core/tools/python.d.ts +2 -0
  273. package/dist/core/tools/python.d.ts.map +1 -1
  274. package/dist/core/tools/python.js +3 -1
  275. package/dist/core/tools/python.js.map +1 -1
  276. package/dist/core/tools/read.d.ts.map +1 -1
  277. package/dist/core/tools/read.js +1 -1
  278. package/dist/core/tools/read.js.map +1 -1
  279. package/dist/core/tools/search-command-guard.d.ts +14 -0
  280. package/dist/core/tools/search-command-guard.d.ts.map +1 -0
  281. package/dist/core/tools/search-command-guard.js +333 -0
  282. package/dist/core/tools/search-command-guard.js.map +1 -0
  283. package/dist/core/tools/secret-store.d.ts +38 -0
  284. package/dist/core/tools/secret-store.d.ts.map +1 -0
  285. package/dist/core/tools/secret-store.js +412 -0
  286. package/dist/core/tools/secret-store.js.map +1 -0
  287. package/dist/core/tools/shell-command-parser.d.ts +16 -0
  288. package/dist/core/tools/shell-command-parser.d.ts.map +1 -0
  289. package/dist/core/tools/shell-command-parser.js +113 -0
  290. package/dist/core/tools/shell-command-parser.js.map +1 -0
  291. package/dist/core/tools/task-steps.d.ts.map +1 -1
  292. package/dist/core/tools/task-steps.js +4 -7
  293. package/dist/core/tools/task-steps.js.map +1 -1
  294. package/dist/core/util/atomic-file.d.ts +6 -2
  295. package/dist/core/util/atomic-file.d.ts.map +1 -1
  296. package/dist/core/util/atomic-file.js +4 -4
  297. package/dist/core/util/atomic-file.js.map +1 -1
  298. package/dist/index.d.ts +3 -2
  299. package/dist/index.d.ts.map +1 -1
  300. package/dist/index.js +2 -1
  301. package/dist/index.js.map +1 -1
  302. package/dist/main.d.ts.map +1 -1
  303. package/dist/main.js +25 -11
  304. package/dist/main.js.map +1 -1
  305. package/dist/modes/interactive/auth-dialogs-controller.d.ts +4 -0
  306. package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
  307. package/dist/modes/interactive/auth-dialogs-controller.js +60 -1
  308. package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
  309. package/dist/modes/interactive/components/activity-lane.d.ts +55 -0
  310. package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -0
  311. package/dist/modes/interactive/components/activity-lane.js +304 -0
  312. package/dist/modes/interactive/components/activity-lane.js.map +1 -0
  313. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  314. package/dist/modes/interactive/components/assistant-message.js +19 -10
  315. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  316. package/dist/modes/interactive/components/expandable-text.d.ts +12 -0
  317. package/dist/modes/interactive/components/expandable-text.d.ts.map +1 -0
  318. package/dist/modes/interactive/components/expandable-text.js +17 -0
  319. package/dist/modes/interactive/components/expandable-text.js.map +1 -0
  320. package/dist/modes/interactive/components/extension-editor.d.ts +15 -1
  321. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  322. package/dist/modes/interactive/components/extension-editor.js +30 -21
  323. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  324. package/dist/modes/interactive/components/extension-input.d.ts +1 -0
  325. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  326. package/dist/modes/interactive/components/extension-input.js +6 -1
  327. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  328. package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
  329. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  330. package/dist/modes/interactive/components/scoped-models-selector.js +23 -14
  331. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  332. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  333. package/dist/modes/interactive/components/settings-selector.js +4 -4
  334. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  335. package/dist/modes/interactive/components/tool-execution.d.ts +19 -11
  336. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  337. package/dist/modes/interactive/components/tool-execution.js +53 -20
  338. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  339. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
  340. package/dist/modes/interactive/components/tool-group.js +3 -0
  341. package/dist/modes/interactive/components/tool-group.js.map +1 -1
  342. package/dist/modes/interactive/components/usage-action-selector.d.ts +16 -0
  343. package/dist/modes/interactive/components/usage-action-selector.d.ts.map +1 -0
  344. package/dist/modes/interactive/components/usage-action-selector.js +46 -0
  345. package/dist/modes/interactive/components/usage-action-selector.js.map +1 -0
  346. package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
  347. package/dist/modes/interactive/extension-ui-host.js +1 -0
  348. package/dist/modes/interactive/extension-ui-host.js.map +1 -1
  349. package/dist/modes/interactive/external-editor.d.ts +15 -0
  350. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  351. package/dist/modes/interactive/external-editor.js +27 -19
  352. package/dist/modes/interactive/external-editor.js.map +1 -1
  353. package/dist/modes/interactive/history-reload-math.d.ts +6 -2
  354. package/dist/modes/interactive/history-reload-math.d.ts.map +1 -1
  355. package/dist/modes/interactive/history-reload-math.js +10 -5
  356. package/dist/modes/interactive/history-reload-math.js.map +1 -1
  357. package/dist/modes/interactive/interactive-event-controller.d.ts +74 -0
  358. package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -0
  359. package/dist/modes/interactive/interactive-event-controller.js +328 -0
  360. package/dist/modes/interactive/interactive-event-controller.js.map +1 -0
  361. package/dist/modes/interactive/interactive-mode.d.ts +20 -25
  362. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  363. package/dist/modes/interactive/interactive-mode.js +196 -608
  364. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  365. package/dist/modes/interactive/loaded-resources-view.d.ts +20 -0
  366. package/dist/modes/interactive/loaded-resources-view.d.ts.map +1 -0
  367. package/dist/modes/interactive/loaded-resources-view.js +147 -0
  368. package/dist/modes/interactive/loaded-resources-view.js.map +1 -0
  369. package/dist/modes/interactive/resource-display.d.ts.map +1 -1
  370. package/dist/modes/interactive/resource-display.js +8 -2
  371. package/dist/modes/interactive/resource-display.js.map +1 -1
  372. package/dist/modes/interactive/resource-shell-commands.d.ts +1 -5
  373. package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -1
  374. package/dist/modes/interactive/resource-shell-commands.js +0 -5
  375. package/dist/modes/interactive/resource-shell-commands.js.map +1 -1
  376. package/dist/modes/interactive/session-flow-commands.d.ts +10 -6
  377. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  378. package/dist/modes/interactive/session-flow-commands.js +123 -70
  379. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  380. package/dist/modes/interactive/usage-commands.d.ts +34 -0
  381. package/dist/modes/interactive/usage-commands.d.ts.map +1 -0
  382. package/dist/modes/interactive/usage-commands.js +225 -0
  383. package/dist/modes/interactive/usage-commands.js.map +1 -0
  384. package/dist/utils/shell.d.ts.map +1 -1
  385. package/dist/utils/shell.js +5 -3
  386. package/dist/utils/shell.js.map +1 -1
  387. package/dist/utils/version-check.d.ts.map +1 -1
  388. package/dist/utils/version-check.js +3 -1
  389. package/dist/utils/version-check.js.map +1 -1
  390. package/docs/UI_POLISH_ORCHESTRATION.md +25 -31
  391. package/docs/UI_QUALITY_ORCHESTRATION.md +22 -24
  392. package/docs/providers.md +9 -1
  393. package/docs/ui-reference/README.md +6 -6
  394. package/docs/ui-reference/orchestration-after.txt +14 -7
  395. package/docs/ui-reference/orchestration-before.txt +12 -6
  396. package/docs/ui-reference/orchestration-reference.txt +15 -5
  397. package/docs/usage.md +9 -1
  398. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  399. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  400. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  401. package/examples/extensions/sandbox/package-lock.json +2 -2
  402. package/examples/extensions/sandbox/package.json +1 -1
  403. package/examples/extensions/with-deps/package-lock.json +2 -2
  404. package/examples/extensions/with-deps/package.json +1 -1
  405. package/npm-shrinkwrap.json +13 -13
  406. package/package.json +4 -4
@@ -0,0 +1,241 @@
1
+ import { realpathSync, statSync } from "node:fs";
2
+ import { basename, isAbsolute, relative, resolve, sep } from "node:path";
3
+ import { redactKnownSecrets } from "../security/secret-text.js";
4
+ const DIRECT_PATH_TOOLS = new Set(["read", "edit", "write", "ls"]);
5
+ const SHELL_INSPECTION_COMMAND_RE = /\b(cat|head|tail|less|more|sed|awk|grep|rg|type|get-content|select-string|source)\b([^\n;&|]*)/gi;
6
+ const SHELL_SECRET_READ_RE = /\b(?:cat|head|tail|less|more|sed|awk|grep|rg|type|get-content|select-string|source)\b[^\n;&|]*(?:^|[\\/])?\.env(?:\.[A-Za-z0-9._-]+)?\b/i;
7
+ const PYTHON_SECRET_READ_RE = /\b(?:open|read_text|read_bytes)\s*\([^\n)]*(?:^|[\\/])?\.env(?:\.[A-Za-z0-9._-]+)?\b/i;
8
+ const PYTHON_INSPECTION_RE = /\b(?:open|read_text|read_bytes)\b/;
9
+ const QUOTED_TEXT_RE = /(["'])([^"'\\]*(?:\\.[^"'\\]*)*)\1/g;
10
+ const MAX_REDACTED_DETAIL_DEPTH = 8;
11
+ const MAX_REDACTED_DETAIL_NODES = 10_000;
12
+ function isRecord(value) {
13
+ return typeof value === "object" && value !== null && !Array.isArray(value);
14
+ }
15
+ function isInside(root, target) {
16
+ const fromRoot = relative(root, target);
17
+ return fromRoot === "" || (!fromRoot.startsWith(`..${sep}`) && fromRoot !== ".." && !isAbsolute(fromRoot));
18
+ }
19
+ export function isProtectedCredentialPath(rawPath, cwd, vault) {
20
+ const resolved = resolve(cwd, rawPath);
21
+ const candidates = [resolved];
22
+ try {
23
+ const canonical = realpathSync.native(resolved);
24
+ if (canonical !== resolved)
25
+ candidates.push(canonical);
26
+ }
27
+ catch {
28
+ // Nonexistent write targets still receive the lexical filename check.
29
+ }
30
+ const vaultPaths = vault ? [resolve(vault.vaultPath)] : [];
31
+ const materializedRoots = vault ? [resolve(vault.materializedDir)] : [];
32
+ if (vault) {
33
+ try {
34
+ vaultPaths.push(realpathSync.native(vault.vaultPath));
35
+ }
36
+ catch {
37
+ // A not-yet-created vault still retains its lexical protected path.
38
+ }
39
+ try {
40
+ materializedRoots.push(realpathSync.native(vault.materializedDir));
41
+ }
42
+ catch {
43
+ // A not-yet-created materialization directory still retains its lexical protected root.
44
+ }
45
+ }
46
+ return candidates.some((candidate) => {
47
+ if (vault && (vaultPaths.includes(candidate) || materializedRoots.some((root) => isInside(root, candidate)))) {
48
+ return true;
49
+ }
50
+ const fileName = basename(candidate);
51
+ return fileName === ".env" || fileName.startsWith(".env.") || fileName.endsWith(".env");
52
+ });
53
+ }
54
+ function shellCredentialRisk(command, cwd, vault) {
55
+ SHELL_INSPECTION_COMMAND_RE.lastIndex = 0;
56
+ for (const match of command.matchAll(SHELL_INSPECTION_COMMAND_RE)) {
57
+ const toolName = (match[1] ?? "").toLowerCase();
58
+ const tokens = (match[2] ?? "").match(/"[^"]*"|'[^']*'|\S+/g) ?? [];
59
+ for (const rawToken of tokens) {
60
+ const token = rawToken.replace(/^["']|["']$/g, "");
61
+ if (!token || token.startsWith("-") || token === ".")
62
+ continue;
63
+ if (isProtectedCredentialPath(token, cwd, vault))
64
+ return "credential_path";
65
+ }
66
+ if ((toolName === "grep" || toolName === "rg") && !shellSearchHasCredentialSafeScope(tokens, cwd)) {
67
+ return "broad_search";
68
+ }
69
+ }
70
+ return undefined;
71
+ }
72
+ function isCredentialSafeGlob(glob) {
73
+ if (/(?:^|[\\/])?\.env(?:\.|\*|$)/i.test(glob))
74
+ return false;
75
+ const filePattern = glob.replace(/\\/g, "/").split("/").at(-1) ?? "";
76
+ const suffix = filePattern.match(/\.([A-Za-z0-9_-]+)$/)?.[1]?.toLowerCase();
77
+ return suffix !== undefined && suffix !== "env";
78
+ }
79
+ function isExistingRegularFile(rawPath, cwd) {
80
+ try {
81
+ return statSync(resolve(cwd, rawPath)).isFile();
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ }
87
+ function shellSearchHasCredentialSafeScope(rawTokens, cwd) {
88
+ const tokens = rawTokens.map((token) => token.replace(/^["']|["']$/g, ""));
89
+ const positiveGlobs = [];
90
+ for (let index = 0; index < tokens.length; index++) {
91
+ const token = tokens[index] ?? "";
92
+ if (token === "-g" || token === "--glob") {
93
+ const glob = tokens[++index];
94
+ if (glob && !glob.startsWith("!"))
95
+ positiveGlobs.push(glob);
96
+ }
97
+ else if (token.startsWith("--glob=")) {
98
+ const glob = token.slice("--glob=".length);
99
+ if (glob && !glob.startsWith("!"))
100
+ positiveGlobs.push(glob);
101
+ }
102
+ }
103
+ if (positiveGlobs.length > 0)
104
+ return positiveGlobs.every(isCredentialSafeGlob);
105
+ let skippedPattern = false;
106
+ for (const token of tokens) {
107
+ if (!token || token.startsWith("-"))
108
+ continue;
109
+ if (!skippedPattern) {
110
+ skippedPattern = true;
111
+ continue;
112
+ }
113
+ if (isExistingRegularFile(token, cwd))
114
+ return true;
115
+ }
116
+ return false;
117
+ }
118
+ function pythonInspectsCredentialPath(code, cwd, vault) {
119
+ if (!PYTHON_INSPECTION_RE.test(code))
120
+ return false;
121
+ QUOTED_TEXT_RE.lastIndex = 0;
122
+ for (const match of code.matchAll(QUOTED_TEXT_RE)) {
123
+ const candidate = match[2]?.replace(/\\([\\"'])/g, "$1");
124
+ if (candidate && isProtectedCredentialPath(candidate, cwd, vault))
125
+ return true;
126
+ }
127
+ return false;
128
+ }
129
+ function directPathFromArgs(args) {
130
+ if (!isRecord(args))
131
+ return undefined;
132
+ return typeof args.path === "string" ? args.path : undefined;
133
+ }
134
+ /** Stable model-facing refusal for direct inspection/mutation of credential material. */
135
+ export function credentialToolBlockReason(toolName, args, cwd, vault) {
136
+ if (toolName === "secret_store" || !isRecord(args))
137
+ return undefined;
138
+ if (DIRECT_PATH_TOOLS.has(toolName)) {
139
+ const path = directPathFromArgs(args);
140
+ if (path && isProtectedCredentialPath(path, cwd, vault)) {
141
+ return "Credential file access is model-blind. Use secret_store to edit or materialize the bound profile, then run the consuming application without inspecting the dotenv file.";
142
+ }
143
+ }
144
+ if (toolName === "grep") {
145
+ const path = typeof args.path === "string" ? args.path : undefined;
146
+ const glob = typeof args.glob === "string" ? args.glob : undefined;
147
+ if ((path && isProtectedCredentialPath(path, cwd, vault)) ||
148
+ (glob && /(?:^|[\\/])?\.env(?:\.|\*|$)/i.test(glob))) {
149
+ return "Credential dotenv files are excluded from model-facing search. Use secret_store metadata instead.";
150
+ }
151
+ if (!(path && isExistingRegularFile(path, cwd)) && !(glob && isCredentialSafeGlob(glob))) {
152
+ return "Credential-safe grep requires one explicit regular file or a narrow non-dotenv file glob (for example *.ts). Refine the search instead of scanning a directory without a file filter.";
153
+ }
154
+ }
155
+ if (toolName === "find") {
156
+ const path = typeof args.path === "string" ? args.path : undefined;
157
+ const pattern = typeof args.pattern === "string" ? args.pattern : undefined;
158
+ if ((path && isProtectedCredentialPath(path, cwd, vault)) ||
159
+ (pattern && /(?:^|[\\/])?\.env(?:\.|\*|$)/i.test(pattern))) {
160
+ return "Credential dotenv files are excluded from model-facing discovery. Use secret_store list instead.";
161
+ }
162
+ }
163
+ if (toolName === "bash" || toolName === "powershell" || toolName === "run_process") {
164
+ const command = typeof args.command === "string" ? args.command : "";
165
+ const shellRisk = shellCredentialRisk(command, cwd, vault);
166
+ if (shellRisk === "broad_search") {
167
+ return "Credential-safe shell search requires a narrow non-dotenv file glob (for example -g '*.ts') or one explicit regular file. Refine the rg/grep command before retrying.";
168
+ }
169
+ if (SHELL_SECRET_READ_RE.test(command) || shellRisk === "credential_path") {
170
+ return "Direct shell inspection of credential dotenv files is blocked. Use secret_store, then run the credential-consuming command normally.";
171
+ }
172
+ }
173
+ if (toolName === "python") {
174
+ const code = typeof args.code === "string" ? args.code : "";
175
+ const scriptPath = typeof args.scriptPath === "string" ? args.scriptPath : undefined;
176
+ if (PYTHON_SECRET_READ_RE.test(code) ||
177
+ pythonInspectsCredentialPath(code, cwd, vault) ||
178
+ (scriptPath !== undefined && isProtectedCredentialPath(scriptPath, cwd, vault))) {
179
+ return "Direct Python inspection of credential dotenv files is blocked. Use secret_store, then run the credential-consuming program normally.";
180
+ }
181
+ }
182
+ return undefined;
183
+ }
184
+ function redactResult(result, vault) {
185
+ const redact = (text) => (vault ? vault.redactSensitiveText(text) : redactKnownSecrets(text));
186
+ const budget = { nodes: 0 };
187
+ return {
188
+ ...result,
189
+ content: result.content.map((block) => (block.type === "text" ? { ...block, text: redact(block.text) } : block)),
190
+ details: redactStructuredDetails(result.details, redact, budget),
191
+ };
192
+ }
193
+ function redactStructuredDetails(value, redact, budget, depth = 0) {
194
+ if (typeof value === "string")
195
+ return redact(value);
196
+ if (value === null || typeof value !== "object")
197
+ return value;
198
+ budget.nodes++;
199
+ if (depth >= MAX_REDACTED_DETAIL_DEPTH || budget.nodes > MAX_REDACTED_DETAIL_NODES) {
200
+ return "[DETAIL OMITTED AT CREDENTIAL BOUNDARY]";
201
+ }
202
+ if (Array.isArray(value)) {
203
+ return value.map((entry) => redactStructuredDetails(entry, redact, budget, depth + 1));
204
+ }
205
+ let prototype;
206
+ try {
207
+ prototype = Object.getPrototypeOf(value);
208
+ }
209
+ catch {
210
+ return "[UNREADABLE DETAIL OMITTED AT CREDENTIAL BOUNDARY]";
211
+ }
212
+ if (prototype !== Object.prototype && prototype !== null)
213
+ return value;
214
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, redactStructuredDetails(entry, redact, budget, depth + 1)]));
215
+ }
216
+ /** Apply the same path refusal and output redaction to foreground, extension, scout, and lane tools. */
217
+ export function wrapToolWithCredentialExposureGuard(tool, cwd, vault) {
218
+ return {
219
+ ...tool,
220
+ async execute(toolCallId, params, signal, onUpdate) {
221
+ const refusal = credentialToolBlockReason(tool.name, params, cwd, vault);
222
+ if (refusal)
223
+ throw new Error(refusal);
224
+ const safeUpdate = onUpdate
225
+ ? (partial) => {
226
+ onUpdate(redactResult(partial, vault));
227
+ }
228
+ : undefined;
229
+ try {
230
+ return redactResult(await tool.execute(toolCallId, params, signal, safeUpdate), vault);
231
+ }
232
+ catch (error) {
233
+ if (error instanceof Error) {
234
+ throw new Error(vault ? vault.redactSensitiveText(error.message) : redactKnownSecrets(error.message));
235
+ }
236
+ throw new Error("Credential-safe tool execution failed without retaining raw error output.");
237
+ }
238
+ },
239
+ };
240
+ }
241
+ //# sourceMappingURL=credential-exposure-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-exposure-guard.js","sourceRoot":"","sources":["../../../src/core/secrets/credential-exposure-guard.ts"],"names":[],"mappings":"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","sourcesContent":["import { realpathSync, statSync } from \"node:fs\";\nimport { basename, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { AgentTool, AgentToolResult } from \"@caupulican/pi-agent-core\";\nimport type { TSchema } from \"typebox\";\nimport { redactKnownSecrets } from \"../security/secret-text.ts\";\nimport type { SecretVault } from \"./secret-vault.ts\";\n\nconst DIRECT_PATH_TOOLS = new Set([\"read\", \"edit\", \"write\", \"ls\"]);\nconst SHELL_INSPECTION_COMMAND_RE =\n\t/\\b(cat|head|tail|less|more|sed|awk|grep|rg|type|get-content|select-string|source)\\b([^\\n;&|]*)/gi;\nconst SHELL_SECRET_READ_RE =\n\t/\\b(?:cat|head|tail|less|more|sed|awk|grep|rg|type|get-content|select-string|source)\\b[^\\n;&|]*(?:^|[\\\\/])?\\.env(?:\\.[A-Za-z0-9._-]+)?\\b/i;\nconst PYTHON_SECRET_READ_RE = /\\b(?:open|read_text|read_bytes)\\s*\\([^\\n)]*(?:^|[\\\\/])?\\.env(?:\\.[A-Za-z0-9._-]+)?\\b/i;\nconst PYTHON_INSPECTION_RE = /\\b(?:open|read_text|read_bytes)\\b/;\nconst QUOTED_TEXT_RE = /([\"'])([^\"'\\\\]*(?:\\\\.[^\"'\\\\]*)*)\\1/g;\nconst MAX_REDACTED_DETAIL_DEPTH = 8;\nconst MAX_REDACTED_DETAIL_NODES = 10_000;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isInside(root: string, target: string): boolean {\n\tconst fromRoot = relative(root, target);\n\treturn fromRoot === \"\" || (!fromRoot.startsWith(`..${sep}`) && fromRoot !== \"..\" && !isAbsolute(fromRoot));\n}\n\nexport function isProtectedCredentialPath(rawPath: string, cwd: string, vault?: SecretVault): boolean {\n\tconst resolved = resolve(cwd, rawPath);\n\tconst candidates = [resolved];\n\ttry {\n\t\tconst canonical = realpathSync.native(resolved);\n\t\tif (canonical !== resolved) candidates.push(canonical);\n\t} catch {\n\t\t// Nonexistent write targets still receive the lexical filename check.\n\t}\n\tconst vaultPaths = vault ? [resolve(vault.vaultPath)] : [];\n\tconst materializedRoots = vault ? [resolve(vault.materializedDir)] : [];\n\tif (vault) {\n\t\ttry {\n\t\t\tvaultPaths.push(realpathSync.native(vault.vaultPath));\n\t\t} catch {\n\t\t\t// A not-yet-created vault still retains its lexical protected path.\n\t\t}\n\t\ttry {\n\t\t\tmaterializedRoots.push(realpathSync.native(vault.materializedDir));\n\t\t} catch {\n\t\t\t// A not-yet-created materialization directory still retains its lexical protected root.\n\t\t}\n\t}\n\treturn candidates.some((candidate) => {\n\t\tif (vault && (vaultPaths.includes(candidate) || materializedRoots.some((root) => isInside(root, candidate)))) {\n\t\t\treturn true;\n\t\t}\n\t\tconst fileName = basename(candidate);\n\t\treturn fileName === \".env\" || fileName.startsWith(\".env.\") || fileName.endsWith(\".env\");\n\t});\n}\n\nfunction shellCredentialRisk(\n\tcommand: string,\n\tcwd: string,\n\tvault?: SecretVault,\n): \"broad_search\" | \"credential_path\" | undefined {\n\tSHELL_INSPECTION_COMMAND_RE.lastIndex = 0;\n\tfor (const match of command.matchAll(SHELL_INSPECTION_COMMAND_RE)) {\n\t\tconst toolName = (match[1] ?? \"\").toLowerCase();\n\t\tconst tokens = (match[2] ?? \"\").match(/\"[^\"]*\"|'[^']*'|\\S+/g) ?? [];\n\t\tfor (const rawToken of tokens) {\n\t\t\tconst token = rawToken.replace(/^[\"']|[\"']$/g, \"\");\n\t\t\tif (!token || token.startsWith(\"-\") || token === \".\") continue;\n\t\t\tif (isProtectedCredentialPath(token, cwd, vault)) return \"credential_path\";\n\t\t}\n\t\tif ((toolName === \"grep\" || toolName === \"rg\") && !shellSearchHasCredentialSafeScope(tokens, cwd)) {\n\t\t\treturn \"broad_search\";\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction isCredentialSafeGlob(glob: string): boolean {\n\tif (/(?:^|[\\\\/])?\\.env(?:\\.|\\*|$)/i.test(glob)) return false;\n\tconst filePattern = glob.replace(/\\\\/g, \"/\").split(\"/\").at(-1) ?? \"\";\n\tconst suffix = filePattern.match(/\\.([A-Za-z0-9_-]+)$/)?.[1]?.toLowerCase();\n\treturn suffix !== undefined && suffix !== \"env\";\n}\n\nfunction isExistingRegularFile(rawPath: string, cwd: string): boolean {\n\ttry {\n\t\treturn statSync(resolve(cwd, rawPath)).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction shellSearchHasCredentialSafeScope(rawTokens: readonly string[], cwd: string): boolean {\n\tconst tokens = rawTokens.map((token) => token.replace(/^[\"']|[\"']$/g, \"\"));\n\tconst positiveGlobs: string[] = [];\n\tfor (let index = 0; index < tokens.length; index++) {\n\t\tconst token = tokens[index] ?? \"\";\n\t\tif (token === \"-g\" || token === \"--glob\") {\n\t\t\tconst glob = tokens[++index];\n\t\t\tif (glob && !glob.startsWith(\"!\")) positiveGlobs.push(glob);\n\t\t} else if (token.startsWith(\"--glob=\")) {\n\t\t\tconst glob = token.slice(\"--glob=\".length);\n\t\t\tif (glob && !glob.startsWith(\"!\")) positiveGlobs.push(glob);\n\t\t}\n\t}\n\tif (positiveGlobs.length > 0) return positiveGlobs.every(isCredentialSafeGlob);\n\n\tlet skippedPattern = false;\n\tfor (const token of tokens) {\n\t\tif (!token || token.startsWith(\"-\")) continue;\n\t\tif (!skippedPattern) {\n\t\t\tskippedPattern = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isExistingRegularFile(token, cwd)) return true;\n\t}\n\treturn false;\n}\n\nfunction pythonInspectsCredentialPath(code: string, cwd: string, vault?: SecretVault): boolean {\n\tif (!PYTHON_INSPECTION_RE.test(code)) return false;\n\tQUOTED_TEXT_RE.lastIndex = 0;\n\tfor (const match of code.matchAll(QUOTED_TEXT_RE)) {\n\t\tconst candidate = match[2]?.replace(/\\\\([\\\\\"'])/g, \"$1\");\n\t\tif (candidate && isProtectedCredentialPath(candidate, cwd, vault)) return true;\n\t}\n\treturn false;\n}\n\nfunction directPathFromArgs(args: unknown): string | undefined {\n\tif (!isRecord(args)) return undefined;\n\treturn typeof args.path === \"string\" ? args.path : undefined;\n}\n\n/** Stable model-facing refusal for direct inspection/mutation of credential material. */\nexport function credentialToolBlockReason(\n\ttoolName: string,\n\targs: unknown,\n\tcwd: string,\n\tvault?: SecretVault,\n): string | undefined {\n\tif (toolName === \"secret_store\" || !isRecord(args)) return undefined;\n\tif (DIRECT_PATH_TOOLS.has(toolName)) {\n\t\tconst path = directPathFromArgs(args);\n\t\tif (path && isProtectedCredentialPath(path, cwd, vault)) {\n\t\t\treturn \"Credential file access is model-blind. Use secret_store to edit or materialize the bound profile, then run the consuming application without inspecting the dotenv file.\";\n\t\t}\n\t}\n\tif (toolName === \"grep\") {\n\t\tconst path = typeof args.path === \"string\" ? args.path : undefined;\n\t\tconst glob = typeof args.glob === \"string\" ? args.glob : undefined;\n\t\tif (\n\t\t\t(path && isProtectedCredentialPath(path, cwd, vault)) ||\n\t\t\t(glob && /(?:^|[\\\\/])?\\.env(?:\\.|\\*|$)/i.test(glob))\n\t\t) {\n\t\t\treturn \"Credential dotenv files are excluded from model-facing search. Use secret_store metadata instead.\";\n\t\t}\n\t\tif (!(path && isExistingRegularFile(path, cwd)) && !(glob && isCredentialSafeGlob(glob))) {\n\t\t\treturn \"Credential-safe grep requires one explicit regular file or a narrow non-dotenv file glob (for example *.ts). Refine the search instead of scanning a directory without a file filter.\";\n\t\t}\n\t}\n\tif (toolName === \"find\") {\n\t\tconst path = typeof args.path === \"string\" ? args.path : undefined;\n\t\tconst pattern = typeof args.pattern === \"string\" ? args.pattern : undefined;\n\t\tif (\n\t\t\t(path && isProtectedCredentialPath(path, cwd, vault)) ||\n\t\t\t(pattern && /(?:^|[\\\\/])?\\.env(?:\\.|\\*|$)/i.test(pattern))\n\t\t) {\n\t\t\treturn \"Credential dotenv files are excluded from model-facing discovery. Use secret_store list instead.\";\n\t\t}\n\t}\n\tif (toolName === \"bash\" || toolName === \"powershell\" || toolName === \"run_process\") {\n\t\tconst command = typeof args.command === \"string\" ? args.command : \"\";\n\t\tconst shellRisk = shellCredentialRisk(command, cwd, vault);\n\t\tif (shellRisk === \"broad_search\") {\n\t\t\treturn \"Credential-safe shell search requires a narrow non-dotenv file glob (for example -g '*.ts') or one explicit regular file. Refine the rg/grep command before retrying.\";\n\t\t}\n\t\tif (SHELL_SECRET_READ_RE.test(command) || shellRisk === \"credential_path\") {\n\t\t\treturn \"Direct shell inspection of credential dotenv files is blocked. Use secret_store, then run the credential-consuming command normally.\";\n\t\t}\n\t}\n\tif (toolName === \"python\") {\n\t\tconst code = typeof args.code === \"string\" ? args.code : \"\";\n\t\tconst scriptPath = typeof args.scriptPath === \"string\" ? args.scriptPath : undefined;\n\t\tif (\n\t\t\tPYTHON_SECRET_READ_RE.test(code) ||\n\t\t\tpythonInspectsCredentialPath(code, cwd, vault) ||\n\t\t\t(scriptPath !== undefined && isProtectedCredentialPath(scriptPath, cwd, vault))\n\t\t) {\n\t\t\treturn \"Direct Python inspection of credential dotenv files is blocked. Use secret_store, then run the credential-consuming program normally.\";\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction redactResult<T>(result: AgentToolResult<T>, vault?: SecretVault): AgentToolResult<T> {\n\tconst redact = (text: string) => (vault ? vault.redactSensitiveText(text) : redactKnownSecrets(text));\n\tconst budget = { nodes: 0 };\n\treturn {\n\t\t...result,\n\t\tcontent: result.content.map((block) => (block.type === \"text\" ? { ...block, text: redact(block.text) } : block)),\n\t\tdetails: redactStructuredDetails(result.details, redact, budget) as T,\n\t};\n}\n\nfunction redactStructuredDetails(\n\tvalue: unknown,\n\tredact: (text: string) => string,\n\tbudget: { nodes: number },\n\tdepth = 0,\n): unknown {\n\tif (typeof value === \"string\") return redact(value);\n\tif (value === null || typeof value !== \"object\") return value;\n\tbudget.nodes++;\n\tif (depth >= MAX_REDACTED_DETAIL_DEPTH || budget.nodes > MAX_REDACTED_DETAIL_NODES) {\n\t\treturn \"[DETAIL OMITTED AT CREDENTIAL BOUNDARY]\";\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => redactStructuredDetails(entry, redact, budget, depth + 1));\n\t}\n\tlet prototype: object | null;\n\ttry {\n\t\tprototype = Object.getPrototypeOf(value);\n\t} catch {\n\t\treturn \"[UNREADABLE DETAIL OMITTED AT CREDENTIAL BOUNDARY]\";\n\t}\n\tif (prototype !== Object.prototype && prototype !== null) return value;\n\treturn Object.fromEntries(\n\t\tObject.entries(value).map(([key, entry]) => [key, redactStructuredDetails(entry, redact, budget, depth + 1)]),\n\t);\n}\n\n/** Apply the same path refusal and output redaction to foreground, extension, scout, and lane tools. */\nexport function wrapToolWithCredentialExposureGuard<TParameters extends TSchema, TDetails>(\n\ttool: AgentTool<TParameters, TDetails>,\n\tcwd: string,\n\tvault?: SecretVault,\n): AgentTool<TParameters, TDetails> {\n\treturn {\n\t\t...tool,\n\t\tasync execute(toolCallId, params, signal, onUpdate) {\n\t\t\tconst refusal = credentialToolBlockReason(tool.name, params, cwd, vault);\n\t\t\tif (refusal) throw new Error(refusal);\n\t\t\tconst safeUpdate = onUpdate\n\t\t\t\t? (partial: AgentToolResult<TDetails>) => {\n\t\t\t\t\t\tonUpdate(redactResult(partial, vault));\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\t\t\ttry {\n\t\t\t\treturn redactResult(await tool.execute(toolCallId, params, signal, safeUpdate), vault);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tthrow new Error(vault ? vault.redactSensitiveText(error.message) : redactKnownSecrets(error.message));\n\t\t\t\t}\n\t\t\t\tthrow new Error(\"Credential-safe tool execution failed without retaining raw error output.\");\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,27 @@
1
+ export declare const SECRET_VARIABLE_NAME_MAX_CHARS = 128;
2
+ export declare const SECRET_VARIABLE_NAME_PATTERN = "^[A-Za-z_][A-Za-z0-9_]*$";
3
+ export declare const MAX_DOTENV_VARIABLES = 64;
4
+ export declare const MAX_DOTENV_VALUE_BYTES: number;
5
+ export declare const MAX_DOTENV_DOCUMENT_BYTES: number;
6
+ export declare class SecretDotenvError extends Error {
7
+ readonly line?: number;
8
+ constructor(message: string, line?: number);
9
+ }
10
+ export interface ParsedDotenvVariable {
11
+ name: string;
12
+ value: string;
13
+ }
14
+ export interface ParsedDotenvDocument {
15
+ document: string;
16
+ variables: ParsedDotenvVariable[];
17
+ }
18
+ export declare function validateDotenvVariableName(name: string): string;
19
+ export declare function validateDotenvValue(value: string): string;
20
+ /**
21
+ * Parse the practical dotenv surface Pi materializes: comments, blank lines, optional `export`,
22
+ * unquoted values, and single/double/backtick quoted values (including multiline quoted values).
23
+ * Error messages contain only a line number and grammar reason, never the rejected value.
24
+ */
25
+ export declare function parseDotenvDocument(input: string): ParsedDotenvDocument;
26
+ export declare function formatDotenvVariables(variables: readonly ParsedDotenvVariable[]): string;
27
+ //# sourceMappingURL=secret-dotenv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-dotenv.d.ts","sourceRoot":"","sources":["../../../src/core/secrets/secret-dotenv.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AACvE,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,sBAAsB,QAAY,CAAC;AAChD,eAAO,MAAM,yBAAyB,QAAa,CAAC;AAEpD,qBAAa,iBAAkB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEvB,YAAY,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAIzC;CACD;AAED,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,oBAAoB,EAAE,CAAC;CAClC;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMzD;AA6DD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,CA0EvE;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,SAAS,oBAAoB,EAAE,GAAG,MAAM,CAQxF","sourcesContent":["const ENV_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport const SECRET_VARIABLE_NAME_MAX_CHARS = 128;\nexport const SECRET_VARIABLE_NAME_PATTERN = \"^[A-Za-z_][A-Za-z0-9_]*$\";\nexport const MAX_DOTENV_VARIABLES = 64;\nexport const MAX_DOTENV_VALUE_BYTES = 64 * 1024;\nexport const MAX_DOTENV_DOCUMENT_BYTES = 512 * 1024;\n\nexport class SecretDotenvError extends Error {\n\treadonly line?: number;\n\n\tconstructor(message: string, line?: number) {\n\t\tsuper(line === undefined ? message : `Dotenv line ${line}: ${message}`);\n\t\tthis.name = \"SecretDotenvError\";\n\t\tthis.line = line;\n\t}\n}\n\nexport interface ParsedDotenvVariable {\n\tname: string;\n\tvalue: string;\n}\n\nexport interface ParsedDotenvDocument {\n\tdocument: string;\n\tvariables: ParsedDotenvVariable[];\n}\n\nexport function validateDotenvVariableName(name: string): string {\n\tif (!ENV_NAME_RE.test(name) || name.length > SECRET_VARIABLE_NAME_MAX_CHARS) {\n\t\tthrow new SecretDotenvError(\"environment variable name must use portable dotenv syntax\");\n\t}\n\treturn name;\n}\n\nexport function validateDotenvValue(value: string): string {\n\tif (value.includes(\"\\0\")) throw new SecretDotenvError(\"values cannot contain null bytes\");\n\tif (Buffer.byteLength(value, \"utf8\") > MAX_DOTENV_VALUE_BYTES) {\n\t\tthrow new SecretDotenvError(\"a value exceeds the 64 KiB limit\");\n\t}\n\treturn value;\n}\n\nfunction decodeDoubleQuoted(value: string, line: number): string {\n\tlet decoded = \"\";\n\tfor (let index = 0; index < value.length; index++) {\n\t\tconst character = value[index] ?? \"\";\n\t\tif (character !== \"\\\\\") {\n\t\t\tdecoded += character;\n\t\t\tcontinue;\n\t\t}\n\t\tconst escaped = value[++index];\n\t\tif (escaped === undefined) throw new SecretDotenvError(\"double-quoted value ends with an escape\", line);\n\t\tswitch (escaped) {\n\t\t\tcase \"n\":\n\t\t\t\tdecoded += \"\\n\";\n\t\t\t\tbreak;\n\t\t\tcase \"r\":\n\t\t\t\tdecoded += \"\\r\";\n\t\t\t\tbreak;\n\t\t\tcase \"t\":\n\t\t\t\tdecoded += \"\\t\";\n\t\t\t\tbreak;\n\t\t\tcase \"\\\\\":\n\t\t\tcase '\"':\n\t\t\tcase \"$\":\n\t\t\t\tdecoded += escaped;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdecoded += `\\\\${escaped}`;\n\t\t}\n\t}\n\treturn decoded;\n}\n\nfunction findClosingQuote(document: string, start: number, quote: string, line: number): number {\n\tfor (let index = start; index < document.length; index++) {\n\t\tif (document[index] !== quote) continue;\n\t\tif (quote !== '\"') return index;\n\t\tlet slashCount = 0;\n\t\tfor (let cursor = index - 1; cursor >= start && document[cursor] === \"\\\\\"; cursor--) slashCount++;\n\t\tif (slashCount % 2 === 0) return index;\n\t}\n\tthrow new SecretDotenvError(\"quoted value is not terminated\", line);\n}\n\nfunction endOfPhysicalLine(document: string, start: number): number {\n\tconst newline = document.indexOf(\"\\n\", start);\n\treturn newline === -1 ? document.length : newline;\n}\n\nfunction parseUnquotedValue(raw: string): string {\n\tlet commentIndex = -1;\n\tfor (let index = 0; index < raw.length; index++) {\n\t\tif (raw[index] === \"#\" && (index === 0 || /\\s/.test(raw[index - 1] ?? \"\"))) {\n\t\t\tcommentIndex = index;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn (commentIndex === -1 ? raw : raw.slice(0, commentIndex)).trim();\n}\n\n/**\n * Parse the practical dotenv surface Pi materializes: comments, blank lines, optional `export`,\n * unquoted values, and single/double/backtick quoted values (including multiline quoted values).\n * Error messages contain only a line number and grammar reason, never the rejected value.\n */\nexport function parseDotenvDocument(input: string): ParsedDotenvDocument {\n\tconst document = input.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\tif (document.includes(\"\\0\")) throw new SecretDotenvError(\"document cannot contain null bytes\");\n\tif (Buffer.byteLength(document, \"utf8\") > MAX_DOTENV_DOCUMENT_BYTES) {\n\t\tthrow new SecretDotenvError(\"document exceeds the 512 KiB limit\");\n\t}\n\n\tconst variables: ParsedDotenvVariable[] = [];\n\tconst names = new Set<string>();\n\tlet offset = 0;\n\tlet line = 1;\n\twhile (offset < document.length) {\n\t\tconst physicalEnd = endOfPhysicalLine(document, offset);\n\t\tconst physical = document.slice(offset, physicalEnd);\n\t\tconst leading = physical.match(/^\\s*/)?.[0].length ?? 0;\n\t\tlet cursor = offset + leading;\n\t\tif (cursor >= physicalEnd || document[cursor] === \"#\") {\n\t\t\toffset = physicalEnd < document.length ? physicalEnd + 1 : document.length;\n\t\t\tline++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (document.slice(cursor, cursor + 6) === \"export\" && /\\s/.test(document[cursor + 6] ?? \"\")) {\n\t\t\tcursor += 6;\n\t\t\twhile (cursor < physicalEnd && /\\s/.test(document[cursor] ?? \"\")) cursor++;\n\t\t}\n\t\tconst equals = document.indexOf(\"=\", cursor);\n\t\tif (equals === -1 || equals > physicalEnd) throw new SecretDotenvError(\"expected NAME=value\", line);\n\t\tlet name: string;\n\t\ttry {\n\t\t\tname = validateDotenvVariableName(document.slice(cursor, equals).trim());\n\t\t} catch (error) {\n\t\t\tif (error instanceof SecretDotenvError) throw new SecretDotenvError(error.message, line);\n\t\t\tthrow error;\n\t\t}\n\t\tif (names.has(name)) throw new SecretDotenvError(`variable ${name} is duplicated`, line);\n\t\tif (variables.length >= MAX_DOTENV_VARIABLES) {\n\t\t\tthrow new SecretDotenvError(`profile exceeds the ${MAX_DOTENV_VARIABLES}-variable limit`, line);\n\t\t}\n\n\t\tcursor = equals + 1;\n\t\twhile (cursor < physicalEnd && (document[cursor] === \" \" || document[cursor] === \"\\t\")) cursor++;\n\t\tlet value: string;\n\t\tlet nextOffset: number;\n\t\tconst quote = document[cursor];\n\t\tif (quote === '\"' || quote === \"'\" || quote === \"`\") {\n\t\t\tconst closing = findClosingQuote(document, cursor + 1, quote, line);\n\t\t\tconst quoted = document.slice(cursor + 1, closing);\n\t\t\tconst trailingEnd = endOfPhysicalLine(document, closing + 1);\n\t\t\tconst trailing = document.slice(closing + 1, trailingEnd).trim();\n\t\t\tif (trailing && !trailing.startsWith(\"#\")) {\n\t\t\t\tthrow new SecretDotenvError(\"unexpected text follows the quoted value\", line);\n\t\t\t}\n\t\t\tvalue = quote === '\"' ? decodeDoubleQuoted(quoted, line) : quoted;\n\t\t\tconst consumedLines = document.slice(offset, trailingEnd).split(\"\\n\").length;\n\t\t\tline += consumedLines;\n\t\t\tnextOffset = trailingEnd < document.length ? trailingEnd + 1 : document.length;\n\t\t} else {\n\t\t\tvalue = parseUnquotedValue(document.slice(cursor, physicalEnd));\n\t\t\tline++;\n\t\t\tnextOffset = physicalEnd < document.length ? physicalEnd + 1 : document.length;\n\t\t}\n\t\ttry {\n\t\t\tvalidateDotenvValue(value);\n\t\t} catch (error) {\n\t\t\tif (error instanceof SecretDotenvError) throw new SecretDotenvError(error.message, line - 1);\n\t\t\tthrow error;\n\t\t}\n\t\tnames.add(name);\n\t\tvariables.push({ name, value });\n\t\toffset = nextOffset;\n\t}\n\n\tif (variables.length === 0) throw new SecretDotenvError(\"document must contain at least one assignment\");\n\treturn { document, variables };\n}\n\nexport function formatDotenvVariables(variables: readonly ParsedDotenvVariable[]): string {\n\treturn `${[...variables]\n\t\t.sort((left, right) => left.name.localeCompare(right.name))\n\t\t.map(\n\t\t\t(variable) =>\n\t\t\t\t`${validateDotenvVariableName(variable.name)}=${JSON.stringify(validateDotenvValue(variable.value))}`,\n\t\t)\n\t\t.join(\"\\n\")}\\n`;\n}\n"]}
@@ -0,0 +1,183 @@
1
+ const ENV_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
2
+ export const SECRET_VARIABLE_NAME_MAX_CHARS = 128;
3
+ export const SECRET_VARIABLE_NAME_PATTERN = "^[A-Za-z_][A-Za-z0-9_]*$";
4
+ export const MAX_DOTENV_VARIABLES = 64;
5
+ export const MAX_DOTENV_VALUE_BYTES = 64 * 1024;
6
+ export const MAX_DOTENV_DOCUMENT_BYTES = 512 * 1024;
7
+ export class SecretDotenvError extends Error {
8
+ line;
9
+ constructor(message, line) {
10
+ super(line === undefined ? message : `Dotenv line ${line}: ${message}`);
11
+ this.name = "SecretDotenvError";
12
+ this.line = line;
13
+ }
14
+ }
15
+ export function validateDotenvVariableName(name) {
16
+ if (!ENV_NAME_RE.test(name) || name.length > SECRET_VARIABLE_NAME_MAX_CHARS) {
17
+ throw new SecretDotenvError("environment variable name must use portable dotenv syntax");
18
+ }
19
+ return name;
20
+ }
21
+ export function validateDotenvValue(value) {
22
+ if (value.includes("\0"))
23
+ throw new SecretDotenvError("values cannot contain null bytes");
24
+ if (Buffer.byteLength(value, "utf8") > MAX_DOTENV_VALUE_BYTES) {
25
+ throw new SecretDotenvError("a value exceeds the 64 KiB limit");
26
+ }
27
+ return value;
28
+ }
29
+ function decodeDoubleQuoted(value, line) {
30
+ let decoded = "";
31
+ for (let index = 0; index < value.length; index++) {
32
+ const character = value[index] ?? "";
33
+ if (character !== "\\") {
34
+ decoded += character;
35
+ continue;
36
+ }
37
+ const escaped = value[++index];
38
+ if (escaped === undefined)
39
+ throw new SecretDotenvError("double-quoted value ends with an escape", line);
40
+ switch (escaped) {
41
+ case "n":
42
+ decoded += "\n";
43
+ break;
44
+ case "r":
45
+ decoded += "\r";
46
+ break;
47
+ case "t":
48
+ decoded += "\t";
49
+ break;
50
+ case "\\":
51
+ case '"':
52
+ case "$":
53
+ decoded += escaped;
54
+ break;
55
+ default:
56
+ decoded += `\\${escaped}`;
57
+ }
58
+ }
59
+ return decoded;
60
+ }
61
+ function findClosingQuote(document, start, quote, line) {
62
+ for (let index = start; index < document.length; index++) {
63
+ if (document[index] !== quote)
64
+ continue;
65
+ if (quote !== '"')
66
+ return index;
67
+ let slashCount = 0;
68
+ for (let cursor = index - 1; cursor >= start && document[cursor] === "\\"; cursor--)
69
+ slashCount++;
70
+ if (slashCount % 2 === 0)
71
+ return index;
72
+ }
73
+ throw new SecretDotenvError("quoted value is not terminated", line);
74
+ }
75
+ function endOfPhysicalLine(document, start) {
76
+ const newline = document.indexOf("\n", start);
77
+ return newline === -1 ? document.length : newline;
78
+ }
79
+ function parseUnquotedValue(raw) {
80
+ let commentIndex = -1;
81
+ for (let index = 0; index < raw.length; index++) {
82
+ if (raw[index] === "#" && (index === 0 || /\s/.test(raw[index - 1] ?? ""))) {
83
+ commentIndex = index;
84
+ break;
85
+ }
86
+ }
87
+ return (commentIndex === -1 ? raw : raw.slice(0, commentIndex)).trim();
88
+ }
89
+ /**
90
+ * Parse the practical dotenv surface Pi materializes: comments, blank lines, optional `export`,
91
+ * unquoted values, and single/double/backtick quoted values (including multiline quoted values).
92
+ * Error messages contain only a line number and grammar reason, never the rejected value.
93
+ */
94
+ export function parseDotenvDocument(input) {
95
+ const document = input.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
96
+ if (document.includes("\0"))
97
+ throw new SecretDotenvError("document cannot contain null bytes");
98
+ if (Buffer.byteLength(document, "utf8") > MAX_DOTENV_DOCUMENT_BYTES) {
99
+ throw new SecretDotenvError("document exceeds the 512 KiB limit");
100
+ }
101
+ const variables = [];
102
+ const names = new Set();
103
+ let offset = 0;
104
+ let line = 1;
105
+ while (offset < document.length) {
106
+ const physicalEnd = endOfPhysicalLine(document, offset);
107
+ const physical = document.slice(offset, physicalEnd);
108
+ const leading = physical.match(/^\s*/)?.[0].length ?? 0;
109
+ let cursor = offset + leading;
110
+ if (cursor >= physicalEnd || document[cursor] === "#") {
111
+ offset = physicalEnd < document.length ? physicalEnd + 1 : document.length;
112
+ line++;
113
+ continue;
114
+ }
115
+ if (document.slice(cursor, cursor + 6) === "export" && /\s/.test(document[cursor + 6] ?? "")) {
116
+ cursor += 6;
117
+ while (cursor < physicalEnd && /\s/.test(document[cursor] ?? ""))
118
+ cursor++;
119
+ }
120
+ const equals = document.indexOf("=", cursor);
121
+ if (equals === -1 || equals > physicalEnd)
122
+ throw new SecretDotenvError("expected NAME=value", line);
123
+ let name;
124
+ try {
125
+ name = validateDotenvVariableName(document.slice(cursor, equals).trim());
126
+ }
127
+ catch (error) {
128
+ if (error instanceof SecretDotenvError)
129
+ throw new SecretDotenvError(error.message, line);
130
+ throw error;
131
+ }
132
+ if (names.has(name))
133
+ throw new SecretDotenvError(`variable ${name} is duplicated`, line);
134
+ if (variables.length >= MAX_DOTENV_VARIABLES) {
135
+ throw new SecretDotenvError(`profile exceeds the ${MAX_DOTENV_VARIABLES}-variable limit`, line);
136
+ }
137
+ cursor = equals + 1;
138
+ while (cursor < physicalEnd && (document[cursor] === " " || document[cursor] === "\t"))
139
+ cursor++;
140
+ let value;
141
+ let nextOffset;
142
+ const quote = document[cursor];
143
+ if (quote === '"' || quote === "'" || quote === "`") {
144
+ const closing = findClosingQuote(document, cursor + 1, quote, line);
145
+ const quoted = document.slice(cursor + 1, closing);
146
+ const trailingEnd = endOfPhysicalLine(document, closing + 1);
147
+ const trailing = document.slice(closing + 1, trailingEnd).trim();
148
+ if (trailing && !trailing.startsWith("#")) {
149
+ throw new SecretDotenvError("unexpected text follows the quoted value", line);
150
+ }
151
+ value = quote === '"' ? decodeDoubleQuoted(quoted, line) : quoted;
152
+ const consumedLines = document.slice(offset, trailingEnd).split("\n").length;
153
+ line += consumedLines;
154
+ nextOffset = trailingEnd < document.length ? trailingEnd + 1 : document.length;
155
+ }
156
+ else {
157
+ value = parseUnquotedValue(document.slice(cursor, physicalEnd));
158
+ line++;
159
+ nextOffset = physicalEnd < document.length ? physicalEnd + 1 : document.length;
160
+ }
161
+ try {
162
+ validateDotenvValue(value);
163
+ }
164
+ catch (error) {
165
+ if (error instanceof SecretDotenvError)
166
+ throw new SecretDotenvError(error.message, line - 1);
167
+ throw error;
168
+ }
169
+ names.add(name);
170
+ variables.push({ name, value });
171
+ offset = nextOffset;
172
+ }
173
+ if (variables.length === 0)
174
+ throw new SecretDotenvError("document must contain at least one assignment");
175
+ return { document, variables };
176
+ }
177
+ export function formatDotenvVariables(variables) {
178
+ return `${[...variables]
179
+ .sort((left, right) => left.name.localeCompare(right.name))
180
+ .map((variable) => `${validateDotenvVariableName(variable.name)}=${JSON.stringify(validateDotenvValue(variable.value))}`)
181
+ .join("\n")}\n`;
182
+ }
183
+ //# sourceMappingURL=secret-dotenv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-dotenv.js","sourceRoot":"","sources":["../../../src/core/secrets/secret-dotenv.ts"],"names":[],"mappings":"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","sourcesContent":["const ENV_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport const SECRET_VARIABLE_NAME_MAX_CHARS = 128;\nexport const SECRET_VARIABLE_NAME_PATTERN = \"^[A-Za-z_][A-Za-z0-9_]*$\";\nexport const MAX_DOTENV_VARIABLES = 64;\nexport const MAX_DOTENV_VALUE_BYTES = 64 * 1024;\nexport const MAX_DOTENV_DOCUMENT_BYTES = 512 * 1024;\n\nexport class SecretDotenvError extends Error {\n\treadonly line?: number;\n\n\tconstructor(message: string, line?: number) {\n\t\tsuper(line === undefined ? message : `Dotenv line ${line}: ${message}`);\n\t\tthis.name = \"SecretDotenvError\";\n\t\tthis.line = line;\n\t}\n}\n\nexport interface ParsedDotenvVariable {\n\tname: string;\n\tvalue: string;\n}\n\nexport interface ParsedDotenvDocument {\n\tdocument: string;\n\tvariables: ParsedDotenvVariable[];\n}\n\nexport function validateDotenvVariableName(name: string): string {\n\tif (!ENV_NAME_RE.test(name) || name.length > SECRET_VARIABLE_NAME_MAX_CHARS) {\n\t\tthrow new SecretDotenvError(\"environment variable name must use portable dotenv syntax\");\n\t}\n\treturn name;\n}\n\nexport function validateDotenvValue(value: string): string {\n\tif (value.includes(\"\\0\")) throw new SecretDotenvError(\"values cannot contain null bytes\");\n\tif (Buffer.byteLength(value, \"utf8\") > MAX_DOTENV_VALUE_BYTES) {\n\t\tthrow new SecretDotenvError(\"a value exceeds the 64 KiB limit\");\n\t}\n\treturn value;\n}\n\nfunction decodeDoubleQuoted(value: string, line: number): string {\n\tlet decoded = \"\";\n\tfor (let index = 0; index < value.length; index++) {\n\t\tconst character = value[index] ?? \"\";\n\t\tif (character !== \"\\\\\") {\n\t\t\tdecoded += character;\n\t\t\tcontinue;\n\t\t}\n\t\tconst escaped = value[++index];\n\t\tif (escaped === undefined) throw new SecretDotenvError(\"double-quoted value ends with an escape\", line);\n\t\tswitch (escaped) {\n\t\t\tcase \"n\":\n\t\t\t\tdecoded += \"\\n\";\n\t\t\t\tbreak;\n\t\t\tcase \"r\":\n\t\t\t\tdecoded += \"\\r\";\n\t\t\t\tbreak;\n\t\t\tcase \"t\":\n\t\t\t\tdecoded += \"\\t\";\n\t\t\t\tbreak;\n\t\t\tcase \"\\\\\":\n\t\t\tcase '\"':\n\t\t\tcase \"$\":\n\t\t\t\tdecoded += escaped;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdecoded += `\\\\${escaped}`;\n\t\t}\n\t}\n\treturn decoded;\n}\n\nfunction findClosingQuote(document: string, start: number, quote: string, line: number): number {\n\tfor (let index = start; index < document.length; index++) {\n\t\tif (document[index] !== quote) continue;\n\t\tif (quote !== '\"') return index;\n\t\tlet slashCount = 0;\n\t\tfor (let cursor = index - 1; cursor >= start && document[cursor] === \"\\\\\"; cursor--) slashCount++;\n\t\tif (slashCount % 2 === 0) return index;\n\t}\n\tthrow new SecretDotenvError(\"quoted value is not terminated\", line);\n}\n\nfunction endOfPhysicalLine(document: string, start: number): number {\n\tconst newline = document.indexOf(\"\\n\", start);\n\treturn newline === -1 ? document.length : newline;\n}\n\nfunction parseUnquotedValue(raw: string): string {\n\tlet commentIndex = -1;\n\tfor (let index = 0; index < raw.length; index++) {\n\t\tif (raw[index] === \"#\" && (index === 0 || /\\s/.test(raw[index - 1] ?? \"\"))) {\n\t\t\tcommentIndex = index;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn (commentIndex === -1 ? raw : raw.slice(0, commentIndex)).trim();\n}\n\n/**\n * Parse the practical dotenv surface Pi materializes: comments, blank lines, optional `export`,\n * unquoted values, and single/double/backtick quoted values (including multiline quoted values).\n * Error messages contain only a line number and grammar reason, never the rejected value.\n */\nexport function parseDotenvDocument(input: string): ParsedDotenvDocument {\n\tconst document = input.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\tif (document.includes(\"\\0\")) throw new SecretDotenvError(\"document cannot contain null bytes\");\n\tif (Buffer.byteLength(document, \"utf8\") > MAX_DOTENV_DOCUMENT_BYTES) {\n\t\tthrow new SecretDotenvError(\"document exceeds the 512 KiB limit\");\n\t}\n\n\tconst variables: ParsedDotenvVariable[] = [];\n\tconst names = new Set<string>();\n\tlet offset = 0;\n\tlet line = 1;\n\twhile (offset < document.length) {\n\t\tconst physicalEnd = endOfPhysicalLine(document, offset);\n\t\tconst physical = document.slice(offset, physicalEnd);\n\t\tconst leading = physical.match(/^\\s*/)?.[0].length ?? 0;\n\t\tlet cursor = offset + leading;\n\t\tif (cursor >= physicalEnd || document[cursor] === \"#\") {\n\t\t\toffset = physicalEnd < document.length ? physicalEnd + 1 : document.length;\n\t\t\tline++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (document.slice(cursor, cursor + 6) === \"export\" && /\\s/.test(document[cursor + 6] ?? \"\")) {\n\t\t\tcursor += 6;\n\t\t\twhile (cursor < physicalEnd && /\\s/.test(document[cursor] ?? \"\")) cursor++;\n\t\t}\n\t\tconst equals = document.indexOf(\"=\", cursor);\n\t\tif (equals === -1 || equals > physicalEnd) throw new SecretDotenvError(\"expected NAME=value\", line);\n\t\tlet name: string;\n\t\ttry {\n\t\t\tname = validateDotenvVariableName(document.slice(cursor, equals).trim());\n\t\t} catch (error) {\n\t\t\tif (error instanceof SecretDotenvError) throw new SecretDotenvError(error.message, line);\n\t\t\tthrow error;\n\t\t}\n\t\tif (names.has(name)) throw new SecretDotenvError(`variable ${name} is duplicated`, line);\n\t\tif (variables.length >= MAX_DOTENV_VARIABLES) {\n\t\t\tthrow new SecretDotenvError(`profile exceeds the ${MAX_DOTENV_VARIABLES}-variable limit`, line);\n\t\t}\n\n\t\tcursor = equals + 1;\n\t\twhile (cursor < physicalEnd && (document[cursor] === \" \" || document[cursor] === \"\\t\")) cursor++;\n\t\tlet value: string;\n\t\tlet nextOffset: number;\n\t\tconst quote = document[cursor];\n\t\tif (quote === '\"' || quote === \"'\" || quote === \"`\") {\n\t\t\tconst closing = findClosingQuote(document, cursor + 1, quote, line);\n\t\t\tconst quoted = document.slice(cursor + 1, closing);\n\t\t\tconst trailingEnd = endOfPhysicalLine(document, closing + 1);\n\t\t\tconst trailing = document.slice(closing + 1, trailingEnd).trim();\n\t\t\tif (trailing && !trailing.startsWith(\"#\")) {\n\t\t\t\tthrow new SecretDotenvError(\"unexpected text follows the quoted value\", line);\n\t\t\t}\n\t\t\tvalue = quote === '\"' ? decodeDoubleQuoted(quoted, line) : quoted;\n\t\t\tconst consumedLines = document.slice(offset, trailingEnd).split(\"\\n\").length;\n\t\t\tline += consumedLines;\n\t\t\tnextOffset = trailingEnd < document.length ? trailingEnd + 1 : document.length;\n\t\t} else {\n\t\t\tvalue = parseUnquotedValue(document.slice(cursor, physicalEnd));\n\t\t\tline++;\n\t\t\tnextOffset = physicalEnd < document.length ? physicalEnd + 1 : document.length;\n\t\t}\n\t\ttry {\n\t\t\tvalidateDotenvValue(value);\n\t\t} catch (error) {\n\t\t\tif (error instanceof SecretDotenvError) throw new SecretDotenvError(error.message, line - 1);\n\t\t\tthrow error;\n\t\t}\n\t\tnames.add(name);\n\t\tvariables.push({ name, value });\n\t\toffset = nextOffset;\n\t}\n\n\tif (variables.length === 0) throw new SecretDotenvError(\"document must contain at least one assignment\");\n\treturn { document, variables };\n}\n\nexport function formatDotenvVariables(variables: readonly ParsedDotenvVariable[]): string {\n\treturn `${[...variables]\n\t\t.sort((left, right) => left.name.localeCompare(right.name))\n\t\t.map(\n\t\t\t(variable) =>\n\t\t\t\t`${validateDotenvVariableName(variable.name)}=${JSON.stringify(validateDotenvValue(variable.value))}`,\n\t\t)\n\t\t.join(\"\\n\")}\\n`;\n}\n"]}