@paybond/kit 0.9.8 → 0.11.0

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 (368) hide show
  1. package/completion-presets/catalog.json +1187 -0
  2. package/completion-presets/catalog.sha256 +1 -0
  3. package/dev/trace-ui/dashboard.html +617 -0
  4. package/dist/agent/adapter.d.ts +51 -0
  5. package/dist/agent/adapter.js +66 -0
  6. package/dist/agent/attach-bundle.d.ts +37 -0
  7. package/dist/agent/attach-bundle.js +118 -0
  8. package/dist/agent/authorization-cache.d.ts +22 -0
  9. package/dist/agent/authorization-cache.js +36 -0
  10. package/dist/agent/deferred-tools.d.ts +11 -0
  11. package/dist/agent/deferred-tools.js +62 -0
  12. package/dist/agent/discover.d.ts +41 -0
  13. package/dist/agent/discover.js +147 -0
  14. package/dist/agent/evidence.d.ts +9 -0
  15. package/dist/agent/evidence.js +28 -0
  16. package/dist/agent/facade.d.ts +48 -0
  17. package/dist/agent/facade.js +112 -0
  18. package/dist/agent/gateway-trace-reporter.d.ts +28 -0
  19. package/dist/agent/gateway-trace-reporter.js +49 -0
  20. package/dist/agent/generic-runner.d.ts +14 -0
  21. package/dist/agent/generic-runner.js +49 -0
  22. package/dist/agent/generic-sandbox-demo.d.ts +36 -0
  23. package/dist/agent/generic-sandbox-demo.js +82 -0
  24. package/dist/agent/guarded-agent.d.ts +49 -0
  25. package/dist/agent/guarded-agent.js +100 -0
  26. package/dist/agent/index.d.ts +13 -0
  27. package/dist/agent/index.js +13 -0
  28. package/dist/agent/instrument.d.ts +156 -0
  29. package/dist/agent/instrument.js +442 -0
  30. package/dist/agent/interceptor.d.ts +24 -0
  31. package/dist/agent/interceptor.js +440 -0
  32. package/dist/agent/lazy-context-tools.d.ts +15 -0
  33. package/dist/agent/lazy-context-tools.js +81 -0
  34. package/dist/agent/registry-file.d.ts +39 -0
  35. package/dist/agent/registry-file.js +219 -0
  36. package/dist/agent/registry.d.ts +37 -0
  37. package/dist/agent/registry.js +128 -0
  38. package/dist/agent/run.d.ts +124 -0
  39. package/dist/agent/run.js +301 -0
  40. package/dist/agent/types.d.ts +318 -0
  41. package/dist/agent/types.js +42 -0
  42. package/dist/agent-recognition.d.ts +72 -0
  43. package/dist/agent-recognition.js +165 -0
  44. package/dist/bincode-wire.d.ts +18 -0
  45. package/dist/bincode-wire.js +93 -0
  46. package/dist/claude-agents/config.d.ts +21 -0
  47. package/dist/claude-agents/config.js +145 -0
  48. package/dist/claude-agents/index.d.ts +2 -0
  49. package/dist/claude-agents/index.js +2 -0
  50. package/dist/claude-agents/sandbox-demo.d.ts +30 -0
  51. package/dist/claude-agents/sandbox-demo.js +91 -0
  52. package/dist/cli/agent/env-quote.d.ts +1 -0
  53. package/dist/cli/agent/env-quote.js +6 -0
  54. package/dist/cli/agent/env-write.d.ts +8 -0
  55. package/dist/cli/agent/env-write.js +47 -0
  56. package/dist/cli/agent/paybond.d.ts +16 -0
  57. package/dist/cli/agent/paybond.js +55 -0
  58. package/dist/cli/agent/policy-file.d.ts +29 -0
  59. package/dist/cli/agent/policy-file.js +61 -0
  60. package/dist/cli/agent/production-evidence.d.ts +24 -0
  61. package/dist/cli/agent/production-evidence.js +98 -0
  62. package/dist/cli/agent/run-store.d.ts +30 -0
  63. package/dist/cli/agent/run-store.js +42 -0
  64. package/dist/cli/agent/run-trace-store.d.ts +39 -0
  65. package/dist/cli/agent/run-trace-store.js +143 -0
  66. package/dist/cli/agent-run-trace-table.d.ts +9 -0
  67. package/dist/cli/agent-run-trace-table.js +24 -0
  68. package/dist/cli/agent-sandbox-smoke-checklist.d.ts +9 -0
  69. package/dist/cli/agent-sandbox-smoke-checklist.js +50 -0
  70. package/dist/cli/audit-export.d.ts +7 -0
  71. package/dist/cli/audit-export.js +120 -0
  72. package/dist/cli/automation.d.ts +25 -0
  73. package/dist/cli/automation.js +297 -0
  74. package/dist/cli/body.d.ts +7 -0
  75. package/dist/cli/body.js +22 -0
  76. package/dist/cli/color.d.ts +15 -0
  77. package/dist/cli/color.js +39 -0
  78. package/dist/cli/command-spec.d.ts +13 -0
  79. package/dist/cli/command-spec.js +611 -0
  80. package/dist/cli/commands/agent.d.ts +16 -0
  81. package/dist/cli/commands/agent.js +1135 -0
  82. package/dist/cli/commands/dev.d.ts +7 -0
  83. package/dist/cli/commands/dev.js +348 -0
  84. package/dist/cli/commands/discovery.d.ts +8 -0
  85. package/dist/cli/commands/discovery.js +194 -0
  86. package/dist/cli/commands/policy.d.ts +13 -0
  87. package/dist/cli/commands/policy.js +769 -0
  88. package/dist/cli/commands/setup.d.ts +18 -0
  89. package/dist/cli/commands/setup.js +513 -0
  90. package/dist/cli/commands/workflows.d.ts +7 -0
  91. package/dist/cli/commands/workflows.js +214 -0
  92. package/dist/cli/config.d.ts +16 -0
  93. package/dist/cli/config.js +98 -0
  94. package/dist/cli/context.d.ts +22 -0
  95. package/dist/cli/context.js +110 -0
  96. package/dist/cli/credentials.d.ts +21 -0
  97. package/dist/cli/credentials.js +141 -0
  98. package/dist/cli/doctor-agent-middleware.d.ts +5 -0
  99. package/dist/cli/doctor-agent-middleware.js +49 -0
  100. package/dist/cli/doctor-agent.d.ts +15 -0
  101. package/dist/cli/doctor-agent.js +311 -0
  102. package/dist/cli/envelope.d.ts +14 -0
  103. package/dist/cli/envelope.js +46 -0
  104. package/dist/cli/globals.d.ts +23 -0
  105. package/dist/cli/globals.js +248 -0
  106. package/dist/cli/help.d.ts +3 -0
  107. package/dist/cli/help.js +83 -0
  108. package/dist/cli/mcp-install.d.ts +41 -0
  109. package/dist/cli/mcp-install.js +95 -0
  110. package/dist/cli/mcp-policy.d.ts +26 -0
  111. package/dist/cli/mcp-policy.js +110 -0
  112. package/dist/cli/mcp-verify-config.d.ts +37 -0
  113. package/dist/cli/mcp-verify-config.js +172 -0
  114. package/dist/cli/redact.d.ts +4 -0
  115. package/dist/cli/redact.js +88 -0
  116. package/dist/cli/request-id.d.ts +2 -0
  117. package/dist/cli/request-id.js +5 -0
  118. package/dist/cli/router.d.ts +2 -0
  119. package/dist/cli/router.js +378 -0
  120. package/dist/cli/smoke-deep-links.d.ts +15 -0
  121. package/dist/cli/smoke-deep-links.js +63 -0
  122. package/dist/cli/suggest.d.ts +4 -0
  123. package/dist/cli/suggest.js +58 -0
  124. package/dist/cli/support-diagnostics.d.ts +19 -0
  125. package/dist/cli/support-diagnostics.js +47 -0
  126. package/dist/cli/telemetry.d.ts +17 -0
  127. package/dist/cli/telemetry.js +94 -0
  128. package/dist/cli/types.d.ts +72 -0
  129. package/dist/cli/types.js +60 -0
  130. package/dist/cli/ux.d.ts +8 -0
  131. package/dist/cli/ux.js +164 -0
  132. package/dist/cli.d.ts +2 -0
  133. package/dist/cli.js +38 -0
  134. package/dist/completion-catalog-digest.d.ts +2 -0
  135. package/dist/completion-catalog-digest.js +2 -0
  136. package/dist/completion-catalog-integrity.d.ts +2 -0
  137. package/dist/completion-catalog-integrity.js +17 -0
  138. package/dist/completion-catalog.d.ts +49 -0
  139. package/dist/completion-catalog.js +62 -0
  140. package/dist/completion-contract-digest.d.ts +37 -0
  141. package/dist/completion-contract-digest.js +73 -0
  142. package/dist/completion-forbidden-fields.d.ts +5 -0
  143. package/dist/completion-forbidden-fields.js +26 -0
  144. package/dist/completion-init.d.ts +8 -0
  145. package/dist/completion-init.js +334 -0
  146. package/dist/completion-resolve.d.ts +21 -0
  147. package/dist/completion-resolve.js +86 -0
  148. package/dist/completion-validate-evidence.d.ts +24 -0
  149. package/dist/completion-validate-evidence.js +145 -0
  150. package/dist/dev/offline-gateway.d.ts +24 -0
  151. package/dist/dev/offline-gateway.js +102 -0
  152. package/dist/dev/trace-buffer.d.ts +61 -0
  153. package/dist/dev/trace-buffer.js +330 -0
  154. package/dist/dev/trace-security-headers.d.ts +11 -0
  155. package/dist/dev/trace-security-headers.js +16 -0
  156. package/dist/dev/trace-server.d.ts +8 -0
  157. package/dist/dev/trace-server.js +38 -0
  158. package/dist/dev/trace-ui.d.ts +4 -0
  159. package/dist/dev/trace-ui.js +25 -0
  160. package/dist/dev/wiremock-up.d.ts +15 -0
  161. package/dist/dev/wiremock-up.js +118 -0
  162. package/dist/doctor-completion.d.ts +17 -0
  163. package/dist/doctor-completion.js +428 -0
  164. package/dist/gateway-url.d.ts +7 -0
  165. package/dist/gateway-url.js +69 -0
  166. package/dist/index.d.ts +119 -2
  167. package/dist/index.js +267 -6
  168. package/dist/init.js +380 -68
  169. package/dist/langgraph/awrap-tool-call.d.ts +25 -0
  170. package/dist/langgraph/awrap-tool-call.js +81 -0
  171. package/dist/langgraph/config.d.ts +13 -0
  172. package/dist/langgraph/config.js +11 -0
  173. package/dist/langgraph/index.d.ts +4 -0
  174. package/dist/langgraph/index.js +4 -0
  175. package/dist/langgraph/sandbox-demo.d.ts +40 -0
  176. package/dist/langgraph/sandbox-demo.js +96 -0
  177. package/dist/langgraph/tool-node.d.ts +10 -0
  178. package/dist/langgraph/tool-node.js +38 -0
  179. package/dist/login.d.ts +14 -1
  180. package/dist/login.js +130 -63
  181. package/dist/mcp/index.d.ts +1 -0
  182. package/dist/mcp/index.js +1 -0
  183. package/dist/mcp/tool-surface.d.ts +25 -0
  184. package/dist/mcp/tool-surface.js +17 -0
  185. package/dist/mcp-capability-token-cache.d.ts +24 -0
  186. package/dist/mcp-capability-token-cache.js +101 -0
  187. package/dist/mcp-evidence-policy.d.ts +48 -0
  188. package/dist/mcp-evidence-policy.js +117 -0
  189. package/dist/mcp-policy-reload.d.ts +79 -0
  190. package/dist/mcp-policy-reload.js +200 -0
  191. package/dist/mcp-sep2828-evidence.d.ts +36 -0
  192. package/dist/mcp-sep2828-evidence.js +65 -0
  193. package/dist/mcp-server.d.ts +10 -0
  194. package/dist/mcp-server.js +423 -115
  195. package/dist/openai-agents/index.d.ts +40 -0
  196. package/dist/openai-agents/index.js +151 -0
  197. package/dist/openai-agents/sandbox-demo.d.ts +34 -0
  198. package/dist/openai-agents/sandbox-demo.js +118 -0
  199. package/dist/payee-evidence.js +2 -29
  200. package/dist/policy/catalog.d.ts +31 -0
  201. package/dist/policy/catalog.js +48 -0
  202. package/dist/policy/compose-utils.d.ts +3 -0
  203. package/dist/policy/compose-utils.js +4 -0
  204. package/dist/policy/compose.d.ts +20 -0
  205. package/dist/policy/compose.js +240 -0
  206. package/dist/policy/digest.d.ts +7 -0
  207. package/dist/policy/digest.js +75 -0
  208. package/dist/policy/domain.d.ts +15 -0
  209. package/dist/policy/domain.js +28 -0
  210. package/dist/policy/guardrail-spec.d.ts +17 -0
  211. package/dist/policy/guardrail-spec.js +140 -0
  212. package/dist/policy/guardrails.d.ts +48 -0
  213. package/dist/policy/guardrails.js +72 -0
  214. package/dist/policy/index.d.ts +21 -0
  215. package/dist/policy/index.js +21 -0
  216. package/dist/policy/init.d.ts +102 -0
  217. package/dist/policy/init.js +351 -0
  218. package/dist/policy/intent-spec.d.ts +52 -0
  219. package/dist/policy/intent-spec.js +176 -0
  220. package/dist/policy/json-path.d.ts +4 -0
  221. package/dist/policy/json-path.js +23 -0
  222. package/dist/policy/layers-io.d.ts +7 -0
  223. package/dist/policy/layers-io.js +28 -0
  224. package/dist/policy/load-effective.d.ts +22 -0
  225. package/dist/policy/load-effective.js +77 -0
  226. package/dist/policy/load.d.ts +85 -0
  227. package/dist/policy/load.js +164 -0
  228. package/dist/policy/merge.d.ts +29 -0
  229. package/dist/policy/merge.js +297 -0
  230. package/dist/policy/parse-text.d.ts +2 -0
  231. package/dist/policy/parse-text.js +126 -0
  232. package/dist/policy/policy-api.d.ts +45 -0
  233. package/dist/policy/policy-api.js +61 -0
  234. package/dist/policy/presets.d.ts +19 -0
  235. package/dist/policy/presets.js +66 -0
  236. package/dist/policy/registry.d.ts +7 -0
  237. package/dist/policy/registry.js +33 -0
  238. package/dist/policy/reload.d.ts +86 -0
  239. package/dist/policy/reload.js +233 -0
  240. package/dist/policy/render-yaml.d.ts +3 -0
  241. package/dist/policy/render-yaml.js +69 -0
  242. package/dist/policy/sandbox-bootstrap.d.ts +19 -0
  243. package/dist/policy/sandbox-bootstrap.js +66 -0
  244. package/dist/policy/schema.d.ts +204 -0
  245. package/dist/policy/schema.js +255 -0
  246. package/dist/policy/snapshot.d.ts +33 -0
  247. package/dist/policy/snapshot.js +23 -0
  248. package/dist/policy/validate-remote.d.ts +43 -0
  249. package/dist/policy/validate-remote.js +104 -0
  250. package/dist/policy/validate.d.ts +36 -0
  251. package/dist/policy/validate.js +150 -0
  252. package/dist/policy/watcher.d.ts +29 -0
  253. package/dist/policy/watcher.js +112 -0
  254. package/dist/principal-intent.d.ts +52 -0
  255. package/dist/principal-intent.js +193 -37
  256. package/dist/project-init.d.ts +34 -0
  257. package/dist/project-init.js +898 -0
  258. package/dist/sep2828-signature.d.ts +10 -0
  259. package/dist/sep2828-signature.js +134 -0
  260. package/dist/solutions/api.d.ts +22 -0
  261. package/dist/solutions/api.js +40 -0
  262. package/dist/solutions/catalog.d.ts +34 -0
  263. package/dist/solutions/catalog.js +129 -0
  264. package/dist/solutions/index.d.ts +2 -0
  265. package/dist/solutions/index.js +2 -0
  266. package/dist/template-init.d.ts +54 -0
  267. package/dist/template-init.js +203 -0
  268. package/dist/vercel-ai/config.d.ts +15 -0
  269. package/dist/vercel-ai/config.js +13 -0
  270. package/dist/vercel-ai/index.d.ts +4 -0
  271. package/dist/vercel-ai/index.js +4 -0
  272. package/dist/vercel-ai/sandbox-demo.d.ts +44 -0
  273. package/dist/vercel-ai/sandbox-demo.js +153 -0
  274. package/dist/vercel-ai/tool-approval.d.ts +16 -0
  275. package/dist/vercel-ai/tool-approval.js +41 -0
  276. package/dist/vercel-ai/wrap-tools.d.ts +9 -0
  277. package/dist/vercel-ai/wrap-tools.js +40 -0
  278. package/dist/x402-receipt-evidence.d.ts +29 -0
  279. package/dist/x402-receipt-evidence.js +97 -0
  280. package/dist/x402-receipt-signature.d.ts +12 -0
  281. package/dist/x402-receipt-signature.js +211 -0
  282. package/package.json +79 -4
  283. package/solutions/aws.json +17 -0
  284. package/solutions/saas.json +17 -0
  285. package/solutions/shopping.json +17 -0
  286. package/solutions/travel.json +18 -0
  287. package/templates/manifest.json +169 -0
  288. package/templates/openai-shopping-agent/.env.example +3 -0
  289. package/templates/openai-shopping-agent/.github/workflows/smoke.yml +20 -0
  290. package/templates/openai-shopping-agent/LICENSE +201 -0
  291. package/templates/openai-shopping-agent/README.md +29 -0
  292. package/templates/openai-shopping-agent/package.json +22 -0
  293. package/templates/openai-shopping-agent/paybond.policy.yaml +22 -0
  294. package/templates/openai-shopping-agent/src/index.ts +22 -0
  295. package/templates/openai-shopping-agent/src/paybond.config.ts +51 -0
  296. package/templates/openai-shopping-agent/tsconfig.json +13 -0
  297. package/templates/paybond-aws-operator/.env.example +3 -0
  298. package/templates/paybond-aws-operator/.github/workflows/smoke.yml +20 -0
  299. package/templates/paybond-aws-operator/LICENSE +201 -0
  300. package/templates/paybond-aws-operator/README.md +29 -0
  301. package/templates/paybond-aws-operator/package.json +20 -0
  302. package/templates/paybond-aws-operator/paybond.policy.yaml +22 -0
  303. package/templates/paybond-aws-operator/src/index.ts +54 -0
  304. package/templates/paybond-aws-operator/src/paybond.config.ts +51 -0
  305. package/templates/paybond-aws-operator/tsconfig.json +13 -0
  306. package/templates/paybond-claude-agents-demo/.env.example +3 -0
  307. package/templates/paybond-claude-agents-demo/.github/workflows/smoke.yml +20 -0
  308. package/templates/paybond-claude-agents-demo/LICENSE +201 -0
  309. package/templates/paybond-claude-agents-demo/README.md +29 -0
  310. package/templates/paybond-claude-agents-demo/package.json +22 -0
  311. package/templates/paybond-claude-agents-demo/paybond.policy.yaml +22 -0
  312. package/templates/paybond-claude-agents-demo/src/index.ts +22 -0
  313. package/templates/paybond-claude-agents-demo/src/paybond.config.ts +51 -0
  314. package/templates/paybond-claude-agents-demo/tsconfig.json +13 -0
  315. package/templates/paybond-invoice-agent/.env.example +3 -0
  316. package/templates/paybond-invoice-agent/.github/workflows/smoke.yml +19 -0
  317. package/templates/paybond-invoice-agent/LICENSE +201 -0
  318. package/templates/paybond-invoice-agent/README.md +29 -0
  319. package/templates/paybond-invoice-agent/app.py +27 -0
  320. package/templates/paybond-invoice-agent/package.json +6 -0
  321. package/templates/paybond-invoice-agent/paybond.policy.yaml +22 -0
  322. package/templates/paybond-invoice-agent/paybond_config.py +45 -0
  323. package/templates/paybond-invoice-agent/requirements.txt +2 -0
  324. package/templates/paybond-mcp-coding-agent/.env.example +3 -0
  325. package/templates/paybond-mcp-coding-agent/.github/workflows/smoke.yml +20 -0
  326. package/templates/paybond-mcp-coding-agent/LICENSE +201 -0
  327. package/templates/paybond-mcp-coding-agent/README.md +39 -0
  328. package/templates/paybond-mcp-coding-agent/package.json +20 -0
  329. package/templates/paybond-mcp-coding-agent/paybond.policy.yaml +25 -0
  330. package/templates/paybond-mcp-coding-agent/src/index.ts +40 -0
  331. package/templates/paybond-mcp-coding-agent/src/paybond.config.ts +51 -0
  332. package/templates/paybond-mcp-coding-agent/tsconfig.json +13 -0
  333. package/templates/paybond-openai-agents-demo/.env.example +3 -0
  334. package/templates/paybond-openai-agents-demo/.github/workflows/smoke.yml +20 -0
  335. package/templates/paybond-openai-agents-demo/LICENSE +201 -0
  336. package/templates/paybond-openai-agents-demo/README.md +29 -0
  337. package/templates/paybond-openai-agents-demo/package.json +22 -0
  338. package/templates/paybond-openai-agents-demo/paybond.policy.yaml +22 -0
  339. package/templates/paybond-openai-agents-demo/src/index.ts +22 -0
  340. package/templates/paybond-openai-agents-demo/src/paybond.config.ts +51 -0
  341. package/templates/paybond-openai-agents-demo/tsconfig.json +13 -0
  342. package/templates/paybond-procurement-agent/.env.example +3 -0
  343. package/templates/paybond-procurement-agent/.github/workflows/smoke.yml +20 -0
  344. package/templates/paybond-procurement-agent/LICENSE +201 -0
  345. package/templates/paybond-procurement-agent/README.md +29 -0
  346. package/templates/paybond-procurement-agent/package.json +20 -0
  347. package/templates/paybond-procurement-agent/paybond.policy.yaml +25 -0
  348. package/templates/paybond-procurement-agent/src/index.ts +54 -0
  349. package/templates/paybond-procurement-agent/src/paybond.config.ts +51 -0
  350. package/templates/paybond-procurement-agent/tsconfig.json +13 -0
  351. package/templates/paybond-travel-agent/.env.example +3 -0
  352. package/templates/paybond-travel-agent/.github/workflows/smoke.yml +20 -0
  353. package/templates/paybond-travel-agent/LICENSE +201 -0
  354. package/templates/paybond-travel-agent/README.md +29 -0
  355. package/templates/paybond-travel-agent/package.json +23 -0
  356. package/templates/paybond-travel-agent/paybond.policy.yaml +22 -0
  357. package/templates/paybond-travel-agent/src/index.ts +22 -0
  358. package/templates/paybond-travel-agent/src/paybond.config.ts +51 -0
  359. package/templates/paybond-travel-agent/tsconfig.json +13 -0
  360. package/templates/paybond-vercel-shopping-agent/.env.example +3 -0
  361. package/templates/paybond-vercel-shopping-agent/.github/workflows/smoke.yml +20 -0
  362. package/templates/paybond-vercel-shopping-agent/LICENSE +201 -0
  363. package/templates/paybond-vercel-shopping-agent/README.md +29 -0
  364. package/templates/paybond-vercel-shopping-agent/package.json +22 -0
  365. package/templates/paybond-vercel-shopping-agent/paybond.policy.yaml +22 -0
  366. package/templates/paybond-vercel-shopping-agent/src/index.ts +22 -0
  367. package/templates/paybond-vercel-shopping-agent/src/paybond.config.ts +51 -0
  368. package/templates/paybond-vercel-shopping-agent/tsconfig.json +13 -0
@@ -0,0 +1,11 @@
1
+ import { paybondAwrapToolCall } from "./awrap-tool-call.js";
2
+ import { paybondToolNode } from "./tool-node.js";
3
+ /**
4
+ * Framework runner helper for LangGraph `ToolNode` and `awrap_tool_call` integration.
5
+ */
6
+ export function createPaybondLangGraphHooks(run) {
7
+ return {
8
+ awrapToolCall: paybondAwrapToolCall(run),
9
+ createToolNode: (tools, options) => paybondToolNode(tools, run, options),
10
+ };
11
+ }
@@ -0,0 +1,4 @@
1
+ export { createPaybondLangGraphHooks, type PaybondLangGraphHooks, } from "./config.js";
2
+ export { paybondAwrapToolCall, paybondAwrapToolCallCapability, normalizeLangGraphHookResult, type PaybondLangGraphAwrapToolCall, type PaybondLangGraphToolCallRequest, } from "./awrap-tool-call.js";
3
+ export { paybondToolNode } from "./tool-node.js";
4
+ export { runLangGraphSandboxDemo, type RunLangGraphSandboxDemoInput, type RunLangGraphSandboxDemoResult, } from "./sandbox-demo.js";
@@ -0,0 +1,4 @@
1
+ export { createPaybondLangGraphHooks, } from "./config.js";
2
+ export { paybondAwrapToolCall, paybondAwrapToolCallCapability, normalizeLangGraphHookResult, } from "./awrap-tool-call.js";
3
+ export { paybondToolNode } from "./tool-node.js";
4
+ export { runLangGraphSandboxDemo, } from "./sandbox-demo.js";
@@ -0,0 +1,40 @@
1
+ import type { Paybond } from "../index.js";
2
+ export type RunLangGraphSandboxDemoInput = {
3
+ paybond: Paybond;
4
+ operation?: string;
5
+ requestedSpendCents?: number;
6
+ evidencePreset?: string;
7
+ toolCallId?: string;
8
+ };
9
+ export type RunLangGraphSandboxDemoResult = {
10
+ bind: {
11
+ run_id: string;
12
+ tenant_id: string;
13
+ intent_id: string;
14
+ capability_token: string;
15
+ operation: string;
16
+ sandbox_lifecycle_status?: string;
17
+ };
18
+ authorization: {
19
+ allow: boolean;
20
+ audit_id?: string;
21
+ decision_id?: string;
22
+ };
23
+ tool_message: {
24
+ content: string;
25
+ status: string;
26
+ name: string;
27
+ tool_call_id: string;
28
+ };
29
+ evidence: {
30
+ submitted: boolean;
31
+ sandbox_lifecycle_status?: string;
32
+ predicate_passed?: boolean | null;
33
+ intent_state?: string;
34
+ };
35
+ intent_state?: string;
36
+ };
37
+ /**
38
+ * No-LLM LangGraph sandbox demo: `ToolNode` + Paybond interceptor + auto-evidence.
39
+ */
40
+ export declare function runLangGraphSandboxDemo(input: RunLangGraphSandboxDemoInput): Promise<RunLangGraphSandboxDemoResult>;
@@ -0,0 +1,96 @@
1
+ import { AIMessage } from "@langchain/core/messages";
2
+ import { tool } from "@langchain/core/tools";
3
+ import { z } from "zod";
4
+ import { createPaybondToolRegistry } from "../agent/registry.js";
5
+ import { paybondToolNode } from "./tool-node.js";
6
+ async function executePaidTool(args) {
7
+ return { status: "completed", cost_cents: args.estimatedPriceCents };
8
+ }
9
+ /**
10
+ * No-LLM LangGraph sandbox demo: `ToolNode` + Paybond interceptor + auto-evidence.
11
+ */
12
+ export async function runLangGraphSandboxDemo(input) {
13
+ const operation = (input.operation ?? "paid-tool").trim();
14
+ const requestedSpendCents = input.requestedSpendCents ?? 100;
15
+ const evidencePreset = (input.evidencePreset ?? "cost_and_completion").trim();
16
+ const toolCallId = (input.toolCallId ?? "langgraph-demo-1").trim();
17
+ const registry = createPaybondToolRegistry({
18
+ defaultDeny: true,
19
+ sideEffecting: {
20
+ [operation]: {
21
+ operation,
22
+ evidencePreset,
23
+ spendCents: (args) => typeof args === "object" &&
24
+ args !== null &&
25
+ "estimatedPriceCents" in args &&
26
+ typeof args.estimatedPriceCents === "number"
27
+ ? args.estimatedPriceCents
28
+ : requestedSpendCents,
29
+ evidenceMapper: (result) => {
30
+ const payload = result;
31
+ return {
32
+ status: payload.status,
33
+ cost_cents: payload.cost_cents,
34
+ };
35
+ },
36
+ },
37
+ },
38
+ });
39
+ const run = await input.paybond.agentRun.bind({
40
+ bootstrap: {
41
+ kind: "sandbox",
42
+ operation,
43
+ requestedSpendCents,
44
+ completionPreset: evidencePreset,
45
+ },
46
+ registry,
47
+ });
48
+ const paidTool = tool(executePaidTool, {
49
+ name: operation,
50
+ description: `Paid operation ${operation}`,
51
+ schema: z.object({
52
+ estimatedPriceCents: z.number().int().nonnegative(),
53
+ }),
54
+ });
55
+ const node = paybondToolNode([paidTool], run);
56
+ const fakeAi = new AIMessage({
57
+ content: "",
58
+ tool_calls: [
59
+ {
60
+ name: operation,
61
+ args: { estimatedPriceCents: requestedSpendCents },
62
+ id: toolCallId,
63
+ type: "tool_call",
64
+ },
65
+ ],
66
+ });
67
+ const out = await node.invoke([fakeAi]);
68
+ const messages = Array.isArray(out) ? out : out.messages;
69
+ const toolMessage = messages[messages.length - 1];
70
+ const sandboxStatus = run.binding.sandbox?.sandboxLifecycleStatus;
71
+ return {
72
+ bind: {
73
+ run_id: run.runId,
74
+ tenant_id: run.tenantId,
75
+ intent_id: run.intentId,
76
+ capability_token: run.capabilityToken,
77
+ operation,
78
+ sandbox_lifecycle_status: sandboxStatus,
79
+ },
80
+ authorization: {
81
+ allow: toolMessage.status !== "error",
82
+ },
83
+ tool_message: {
84
+ content: String(toolMessage.content),
85
+ status: String(toolMessage.status ?? "success"),
86
+ name: String(toolMessage.name ?? operation),
87
+ tool_call_id: String(toolMessage.tool_call_id ?? toolCallId),
88
+ },
89
+ evidence: {
90
+ submitted: toolMessage.status !== "error",
91
+ sandbox_lifecycle_status: sandboxStatus,
92
+ predicate_passed: toolMessage.status !== "error" ? true : null,
93
+ },
94
+ intent_state: sandboxStatus,
95
+ };
96
+ }
@@ -0,0 +1,10 @@
1
+ import type { DynamicTool, StructuredToolInterface } from "@langchain/core/tools";
2
+ import type { RunnableToolLike } from "@langchain/core/runnables";
3
+ import { ToolNode, type ToolNodeOptions } from "@langchain/langgraph/prebuilt";
4
+ import type { PaybondAgentRun } from "../agent/run.js";
5
+ type LangGraphTool = StructuredToolInterface | DynamicTool | RunnableToolLike;
6
+ /**
7
+ * Convenience factory: `ToolNode` with Paybond spend guard + auto-evidence on every tool call.
8
+ */
9
+ export declare function paybondToolNode(tools: LangGraphTool[], run: PaybondAgentRun, options?: ToolNodeOptions): ToolNode;
10
+ export {};
@@ -0,0 +1,38 @@
1
+ import { ToolNode } from "@langchain/langgraph/prebuilt";
2
+ import { normalizeLangGraphHookResult, paybondAwrapToolCall, } from "./awrap-tool-call.js";
3
+ /**
4
+ * `ToolNode` subclass that runs {@link paybondAwrapToolCall} before each tool invocation.
5
+ *
6
+ * LangGraph JS does not yet expose `awrapToolCall` on `ToolNode`; this wrapper provides the
7
+ * same interceptor boundary as Python's `ToolNode(..., awrap_tool_call=...)`.
8
+ */
9
+ class PaybondGuardedToolNode extends ToolNode {
10
+ awrap;
11
+ constructor(tools, run, options) {
12
+ super(tools, options);
13
+ this.awrap = paybondAwrapToolCall(run);
14
+ }
15
+ async runTool(call, config, state) {
16
+ const request = {
17
+ tool_call: {
18
+ name: call.name,
19
+ id: call.id,
20
+ args: (call.args ?? {}),
21
+ },
22
+ };
23
+ const execute = async (req) => super.runTool({
24
+ ...call,
25
+ name: req.tool_call.name,
26
+ id: req.tool_call.id ?? call.id,
27
+ args: req.tool_call.args ?? call.args,
28
+ }, config, state);
29
+ const result = await this.awrap(request, execute);
30
+ return normalizeLangGraphHookResult(call, result);
31
+ }
32
+ }
33
+ /**
34
+ * Convenience factory: `ToolNode` with Paybond spend guard + auto-evidence on every tool call.
35
+ */
36
+ export function paybondToolNode(tools, run, options) {
37
+ return new PaybondGuardedToolNode(tools, run, options);
38
+ }
package/dist/login.d.ts CHANGED
@@ -10,6 +10,17 @@ export type LoginOptions = {
10
10
  noOpen: boolean;
11
11
  force: boolean;
12
12
  };
13
+ export type LoginResult = {
14
+ envPath: string;
15
+ keyMasked: string;
16
+ keyWritten: true;
17
+ environment: DeviceEnvironment;
18
+ tenantId: string;
19
+ tenantUuid: string;
20
+ expiresAt?: string;
21
+ verificationUri: string;
22
+ userCode: string;
23
+ };
13
24
  type FetchInput = string | URL;
14
25
  type FetchInit = {
15
26
  method?: string;
@@ -25,11 +36,13 @@ export type LoginDependencies = {
25
36
  stdout?: Writable;
26
37
  stderr?: Writable;
27
38
  now?: () => number;
39
+ /** When false, suppress human-readable progress lines (for JSON CLI output). */
40
+ humanOutput?: boolean;
28
41
  };
29
42
  export declare function parseArgs(argv: string[]): LoginOptions | "help";
30
43
  export declare function assertGitIgnored(envPath: string, cwd: string): Promise<void>;
31
44
  export declare function assertCanWriteEnvFile(envPath: string, force: boolean): Promise<void>;
32
45
  export declare function writeEnvFile(envPath: string, rawKey: string, force: boolean): Promise<void>;
33
- export declare function runLogin(options: LoginOptions, deps?: LoginDependencies): Promise<number>;
46
+ export declare function runLogin(options: LoginOptions, deps?: LoginDependencies): Promise<LoginResult>;
34
47
  export declare function main(argv?: string[], deps?: LoginDependencies): Promise<number>;
35
48
  export {};
package/dist/login.js CHANGED
@@ -1,10 +1,31 @@
1
1
  #!/usr/bin/env node
2
+ import { spawn } from "node:child_process";
3
+ import fs from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { fileURLToPath, pathToFileURL } from "node:url";
6
+ import { runCli } from "./cli/router.js";
7
+ import { requireSecureGatewayUrl } from "./gateway-url.js";
2
8
  const DEFAULT_GATEWAY = "https://api.paybond.ai";
3
9
  const DEFAULT_ENV_FILE = ".env.local";
4
10
  const CLIENT_ID = "paybond-kit-cli";
5
11
  const CLIENT_NAME = "Paybond CLI";
6
12
  const DEVICE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
7
13
  const MIN_POLL_INTERVAL_SECONDS = 1;
14
+ const DEFAULT_DEVICE_EXPIRES_IN_SECONDS = 600;
15
+ const DEFAULT_DEVICE_POLL_INTERVAL_SECONDS = 5;
16
+ const MS_PER_SECOND = 1_000;
17
+ const DEVICE_EXPIRY_GRACE_MS = MS_PER_SECOND;
18
+ const PROCESS_EXIT_SUCCESS = 0;
19
+ const SPAWN_COMMAND_NOT_FOUND_EXIT_CODE = 127;
20
+ const GIT_CHECK_IGNORE_MATCHED = PROCESS_EXIT_SUCCESS;
21
+ const GIT_CHECK_IGNORE_NOT_MATCHED = 1;
22
+ const MAX_GIT_WORKTREE_WALK_DEPTH = 256;
23
+ const ENV_FILE_MODE = 0o600;
24
+ const GITIGNORE_FILE_MODE = 0o644;
25
+ const API_KEY_MASK_MIN_PARTS = 5;
26
+ const API_KEY_MASK_MIN_ID_LENGTH = 12;
27
+ const API_KEY_MASK_ID_PREFIX_LENGTH = 8;
28
+ const API_KEY_MASK_ID_SUFFIX_LENGTH = 4;
8
29
  class PaybondLoginError extends Error {
9
30
  constructor(message) {
10
31
  super(message);
@@ -104,6 +125,12 @@ export function parseArgs(argv) {
104
125
  if (!gateway.trim()) {
105
126
  throw new PaybondLoginError("invalid --gateway");
106
127
  }
128
+ try {
129
+ gateway = requireSecureGatewayUrl(gateway);
130
+ }
131
+ catch (err) {
132
+ throw new PaybondLoginError(err instanceof Error ? err.message : String(err));
133
+ }
107
134
  return { envFile, gateway, environment, noOpen, force };
108
135
  }
109
136
  function envKeyPattern() {
@@ -127,19 +154,9 @@ function replaceOrAppendEnvValue(existing, rawKey, force) {
127
154
  const suffix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
128
155
  return `${existing}${suffix}${line}\n`;
129
156
  }
130
- async function pathModule() {
131
- // @ts-expect-error Node builtins are available in the published CLI runtime.
132
- return await import("node:path");
133
- }
134
- async function fsModule() {
135
- // @ts-expect-error Node builtins are available in the published CLI runtime.
136
- return await import("node:fs/promises");
137
- }
138
157
  async function spawnCommand(command, args, cwd) {
139
- // @ts-expect-error Node builtins are available in the published CLI runtime.
140
- const childProcess = await import("node:child_process");
141
158
  return await new Promise((resolve) => {
142
- const child = childProcess.spawn(command, args, {
159
+ const child = spawn(command, args, {
143
160
  cwd,
144
161
  stdio: ["ignore", "pipe", "pipe"],
145
162
  });
@@ -152,7 +169,7 @@ async function spawnCommand(command, args, cwd) {
152
169
  stderr += String(chunk);
153
170
  });
154
171
  child.on("error", (err) => {
155
- resolve({ code: 127, stdout: "", stderr: err.message });
172
+ resolve({ code: SPAWN_COMMAND_NOT_FOUND_EXIT_CODE, stdout: "", stderr: err.message });
156
173
  });
157
174
  child.on("close", (code) => {
158
175
  resolve({ code, stdout, stderr });
@@ -160,31 +177,55 @@ async function spawnCommand(command, args, cwd) {
160
177
  });
161
178
  }
162
179
  async function resolveEnvFile(envFile, cwd) {
163
- const path = await pathModule();
164
180
  return path.isAbsolute(envFile) ? path.resolve(envFile) : path.resolve(cwd, envFile);
165
181
  }
166
182
  export async function assertGitIgnored(envPath, cwd) {
167
183
  await ensureGitIgnored(envPath, cwd, false);
168
184
  }
185
+ async function inGitWorkTree(start) {
186
+ let current = path.resolve(start);
187
+ for (let depth = 0; depth < MAX_GIT_WORKTREE_WALK_DEPTH; depth += 1) {
188
+ try {
189
+ await fs.access(path.join(current, ".git"));
190
+ return true;
191
+ }
192
+ catch {
193
+ // continue walking parents
194
+ }
195
+ const parent = path.dirname(current);
196
+ if (parent === current) {
197
+ return false;
198
+ }
199
+ current = parent;
200
+ }
201
+ return false;
202
+ }
203
+ function gitMissingForSecretWriteError() {
204
+ return new PaybondLoginError("git is required to verify the env file is ignored before writing secrets; install git or pass --env-file outside the repository");
205
+ }
169
206
  async function ensureGitIgnored(envPath, cwd, autoAddDefaultEnvFile) {
170
- const path = await pathModule();
171
- const fs = await fsModule();
172
207
  const rootResult = await spawnCommand("git", ["rev-parse", "--show-toplevel"], cwd);
173
208
  if (rootResult.code !== 0) {
209
+ if (rootResult.code === SPAWN_COMMAND_NOT_FOUND_EXIT_CODE || /ENOENT/i.test(rootResult.stderr)) {
210
+ if (await inGitWorkTree(cwd)) {
211
+ throw gitMissingForSecretWriteError();
212
+ }
213
+ }
174
214
  return;
175
215
  }
176
216
  const repoRoot = await fs.realpath(path.resolve(rootResult.stdout.trim()));
177
217
  const targetDir = await fs.realpath(path.dirname(path.resolve(envPath)));
178
218
  const target = path.resolve(targetDir, path.basename(envPath));
179
219
  const relativeTarget = path.relative(repoRoot, target);
180
- if (relativeTarget !== "" && (relativeTarget.startsWith("..") || path.isAbsolute(relativeTarget))) {
220
+ if (relativeTarget !== "" &&
221
+ (relativeTarget.startsWith("..") || path.isAbsolute(relativeTarget))) {
181
222
  return;
182
223
  }
183
224
  const ignoreResult = await spawnCommand("git", ["-C", repoRoot, "check-ignore", "--quiet", "--", relativeTarget], cwd);
184
- if (ignoreResult.code === 0) {
225
+ if (ignoreResult.code === GIT_CHECK_IGNORE_MATCHED) {
185
226
  return;
186
227
  }
187
- if (ignoreResult.code === 1) {
228
+ if (ignoreResult.code === GIT_CHECK_IGNORE_NOT_MATCHED) {
188
229
  if (autoAddDefaultEnvFile && relativeTarget === DEFAULT_ENV_FILE) {
189
230
  const gitignorePath = path.resolve(repoRoot, ".gitignore");
190
231
  let existing = "";
@@ -192,14 +233,17 @@ async function ensureGitIgnored(envPath, cwd, autoAddDefaultEnvFile) {
192
233
  existing = await fs.readFile(gitignorePath, "utf8");
193
234
  }
194
235
  catch (err) {
195
- if (!(err && typeof err === "object" && "code" in err && err.code === "ENOENT")) {
236
+ if (!(err &&
237
+ typeof err === "object" &&
238
+ "code" in err &&
239
+ err.code === "ENOENT")) {
196
240
  throw err;
197
241
  }
198
242
  }
199
243
  const suffix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
200
- await fs.writeFile(gitignorePath, `${existing}${suffix}${DEFAULT_ENV_FILE}\n`, { encoding: "utf8", mode: 0o644 });
244
+ await fs.writeFile(gitignorePath, `${existing}${suffix}${DEFAULT_ENV_FILE}\n`, { encoding: "utf8", mode: GITIGNORE_FILE_MODE });
201
245
  const recheck = await spawnCommand("git", ["-C", repoRoot, "check-ignore", "--quiet", "--", relativeTarget], cwd);
202
- if (recheck.code === 0) {
246
+ if (recheck.code === GIT_CHECK_IGNORE_MATCHED) {
203
247
  return;
204
248
  }
205
249
  }
@@ -208,7 +252,6 @@ async function ensureGitIgnored(envPath, cwd, autoAddDefaultEnvFile) {
208
252
  throw new PaybondLoginError(`Unable to verify git ignore status for ${target}: ${ignoreResult.stderr.trim() || "git check-ignore failed"}`);
209
253
  }
210
254
  export async function assertCanWriteEnvFile(envPath, force) {
211
- const fs = await fsModule();
212
255
  try {
213
256
  const existing = await fs.readFile(envPath, "utf8");
214
257
  if (envKeyPattern().test(existing) && !force) {
@@ -216,26 +259,31 @@ export async function assertCanWriteEnvFile(envPath, force) {
216
259
  }
217
260
  }
218
261
  catch (err) {
219
- if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
262
+ if (err &&
263
+ typeof err === "object" &&
264
+ "code" in err &&
265
+ err.code === "ENOENT") {
220
266
  return;
221
267
  }
222
268
  throw err;
223
269
  }
224
270
  }
225
271
  export async function writeEnvFile(envPath, rawKey, force) {
226
- const fs = await fsModule();
227
272
  let existing = "";
228
273
  try {
229
274
  existing = await fs.readFile(envPath, "utf8");
230
275
  }
231
276
  catch (err) {
232
- if (!(err && typeof err === "object" && "code" in err && err.code === "ENOENT")) {
277
+ if (!(err &&
278
+ typeof err === "object" &&
279
+ "code" in err &&
280
+ err.code === "ENOENT")) {
233
281
  throw err;
234
282
  }
235
283
  }
236
284
  const next = replaceOrAppendEnvValue(existing, rawKey, force);
237
- await fs.writeFile(envPath, next, { encoding: "utf8", mode: 0o600 });
238
- await fs.chmod(envPath, 0o600);
285
+ await fs.writeFile(envPath, next, { encoding: "utf8", mode: ENV_FILE_MODE });
286
+ await fs.chmod(envPath, ENV_FILE_MODE);
239
287
  }
240
288
  function gatewayUrl(base, path) {
241
289
  return `${base.trim().replace(/\/+$/, "")}${path}`;
@@ -278,7 +326,8 @@ async function postGatewayJson(fetchFn, gateway, path, body) {
278
326
  if (error) {
279
327
  throw new OAuthPollError({
280
328
  error,
281
- error_description: stringField(parsed, "error_description") || stringField(parsed, "message"),
329
+ error_description: stringField(parsed, "error_description") ||
330
+ stringField(parsed, "message"),
282
331
  interval: numberField(parsed, "interval", 0) || undefined,
283
332
  });
284
333
  }
@@ -290,10 +339,12 @@ function toDeviceStartResponse(body) {
290
339
  user_code: stringField(body, "user_code"),
291
340
  verification_uri: stringField(body, "verification_uri"),
292
341
  verification_uri_complete: stringField(body, "verification_uri_complete") || undefined,
293
- expires_in: numberField(body, "expires_in", 600),
294
- interval: numberField(body, "interval", 5),
342
+ expires_in: numberField(body, "expires_in", DEFAULT_DEVICE_EXPIRES_IN_SECONDS),
343
+ interval: numberField(body, "interval", DEFAULT_DEVICE_POLL_INTERVAL_SECONDS),
295
344
  };
296
- if (!response.device_code || !response.user_code || !response.verification_uri) {
345
+ if (!response.device_code ||
346
+ !response.user_code ||
347
+ !response.verification_uri) {
297
348
  throw new PaybondLoginError("Gateway device start response was missing required fields.");
298
349
  }
299
350
  return response;
@@ -332,11 +383,11 @@ async function startDeviceFlow(fetchFn, gateway, environment) {
332
383
  return toDeviceStartResponse(body);
333
384
  }
334
385
  async function pollDeviceToken(fetchFn, gateway, environment, start, deps) {
335
- let intervalSeconds = Math.max(MIN_POLL_INTERVAL_SECONDS, Math.trunc(start.interval || 5));
336
- const expiresAtMs = deps.now() + Math.max(1, start.expires_in) * 1000;
386
+ let intervalSeconds = Math.max(MIN_POLL_INTERVAL_SECONDS, Math.trunc(start.interval || DEFAULT_DEVICE_POLL_INTERVAL_SECONDS));
387
+ const expiresAtMs = deps.now() + Math.max(1, start.expires_in) * MS_PER_SECOND;
337
388
  for (;;) {
338
- await deps.sleep(intervalSeconds * 1000);
339
- if (deps.now() > expiresAtMs + 1000) {
389
+ await deps.sleep(intervalSeconds * MS_PER_SECOND);
390
+ if (deps.now() > expiresAtMs + DEVICE_EXPIRY_GRACE_MS) {
340
391
  throw new PaybondLoginError("Device authorization expired before approval.");
341
392
  }
342
393
  try {
@@ -372,10 +423,12 @@ async function pollDeviceToken(fetchFn, gateway, environment, start, deps) {
372
423
  function maskAPIKey(rawKey) {
373
424
  const trimmed = rawKey.trim();
374
425
  const parts = trimmed.split("_");
375
- if (parts.length >= 5 && parts[0] === "paybond" && parts[1] === "sk") {
426
+ if (parts.length >= API_KEY_MASK_MIN_PARTS && parts[0] === "paybond" && parts[1] === "sk") {
376
427
  const environment = parts[2];
377
428
  const keyID = parts[3];
378
- const redactedKeyID = keyID.length > 12 ? `${keyID.slice(0, 8)}...${keyID.slice(-4)}` : "redacted";
429
+ const redactedKeyID = keyID.length > API_KEY_MASK_MIN_ID_LENGTH
430
+ ? `${keyID.slice(0, API_KEY_MASK_ID_PREFIX_LENGTH)}...${keyID.slice(-API_KEY_MASK_ID_SUFFIX_LENGTH)}`
431
+ : "redacted";
379
432
  return `paybond_sk_${environment}_${redactedKeyID}`;
380
433
  }
381
434
  return "paybond_sk_...";
@@ -388,11 +441,12 @@ async function defaultOpenBrowser(url) {
388
441
  const command = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
389
442
  const args = platform === "win32" ? ["/c", "start", "", url] : [url];
390
443
  const result = await spawnCommand(command, args, process.cwd());
391
- return result.code === 0;
444
+ return result.code === PROCESS_EXIT_SUCCESS;
392
445
  }
393
446
  export async function runLogin(options, deps = {}) {
394
447
  const cwd = deps.cwd ?? process.cwd();
395
448
  const stdout = deps.stdout ?? process.stdout;
449
+ const humanOutput = deps.humanOutput ?? true;
396
450
  const fetchFn = deps.fetch ?? fetch;
397
451
  const sleep = deps.sleep ?? defaultSleep;
398
452
  const now = deps.now ?? Date.now;
@@ -402,25 +456,40 @@ export async function runLogin(options, deps = {}) {
402
456
  await ensureGitIgnored(envPath, cwd, options.envFile === DEFAULT_ENV_FILE);
403
457
  const start = await startDeviceFlow(fetchFn, options.gateway, options.environment);
404
458
  const verificationUrl = start.verification_uri_complete || start.verification_uri;
405
- stdout.write(`Paybond ${options.environment} login\n`);
406
- stdout.write(`Verification URL: ${verificationUrl}\n`);
407
- stdout.write(`Code: ${start.user_code}\n`);
408
- if (!options.noOpen) {
409
- const opened = await openBrowser(verificationUrl);
410
- if (!opened) {
411
- stdout.write(`Open the verification URL in a browser to approve this login.\n`);
459
+ if (humanOutput) {
460
+ stdout.write(`Paybond ${options.environment} login\n`);
461
+ stdout.write(`Verification URL: ${verificationUrl}\n`);
462
+ stdout.write(`Code: ${start.user_code}\n`);
463
+ if (!options.noOpen) {
464
+ const opened = await openBrowser(verificationUrl);
465
+ if (!opened) {
466
+ stdout.write(`Open the verification URL in a browser to approve this login.\n`);
467
+ }
412
468
  }
469
+ stdout.write(`Waiting for approval...\n`);
413
470
  }
414
- stdout.write(`Waiting for approval...\n`);
415
471
  const token = await pollDeviceToken(fetchFn, options.gateway, options.environment, start, { sleep, now });
416
472
  await writeEnvFile(envPath, token.access_token, options.force);
417
- stdout.write(`Wrote PAYBOND_API_KEY to ${envPath}\n`);
418
- stdout.write(`Key: ${maskAPIKey(token.access_token)}\n`);
419
- stdout.write(`Target ${token.environment} tenant: ${token.tenant_id} (${token.tenant_uuid})\n`);
420
- if (token.expires_at) {
421
- stdout.write(`This key auto-expires at ${token.expires_at}; re-run paybond login to mint a new one.\n`);
473
+ const keyMasked = maskAPIKey(token.access_token);
474
+ if (humanOutput) {
475
+ stdout.write(`Wrote PAYBOND_API_KEY to ${envPath}\n`);
476
+ stdout.write(`Key: ${keyMasked}\n`);
477
+ stdout.write(`Target ${token.environment} tenant: ${token.tenant_id} (${token.tenant_uuid})\n`);
478
+ if (token.expires_at) {
479
+ stdout.write(`This key auto-expires at ${token.expires_at}; re-run paybond login to mint a new one.\n`);
480
+ }
422
481
  }
423
- return 0;
482
+ return {
483
+ envPath,
484
+ keyMasked,
485
+ keyWritten: true,
486
+ environment: options.environment,
487
+ tenantId: token.tenant_id,
488
+ tenantUuid: token.tenant_uuid,
489
+ expiresAt: token.expires_at || undefined,
490
+ verificationUri: verificationUrl,
491
+ userCode: start.user_code,
492
+ };
424
493
  }
425
494
  export async function main(argv = process.argv.slice(2), deps = {}) {
426
495
  let parsed;
@@ -430,7 +499,8 @@ export async function main(argv = process.argv.slice(2), deps = {}) {
430
499
  (deps.stdout ?? process.stdout).write(`${usage()}\n`);
431
500
  return 0;
432
501
  }
433
- return await runLogin(parsed, deps);
502
+ await runLogin(parsed, deps);
503
+ return 0;
434
504
  }
435
505
  catch (err) {
436
506
  (deps.stderr ?? process.stderr).write(`${err instanceof Error ? err.message : String(err)}\n`);
@@ -438,19 +508,15 @@ export async function main(argv = process.argv.slice(2), deps = {}) {
438
508
  }
439
509
  }
440
510
  function normalizeFileURL(url) {
441
- return url.startsWith("file:///var/") ? url.replace("file:///var/", "file:///private/var/") : url;
511
+ return url.startsWith("file:///var/")
512
+ ? url.replace("file:///var/", "file:///private/var/")
513
+ : url;
442
514
  }
443
515
  async function invokedFromCLI() {
444
516
  const scriptPath = process.argv[1];
445
517
  if (!scriptPath) {
446
518
  return false;
447
519
  }
448
- // @ts-ignore Node builtins are available in the published CLI runtime.
449
- const fs = (await import("node:fs/promises"));
450
- // @ts-ignore Node builtins are available in the published CLI runtime.
451
- const path = (await import("node:path"));
452
- // @ts-ignore Node builtins are available in the published CLI runtime.
453
- const url = (await import("node:url"));
454
520
  async function realFileURL(filePath) {
455
521
  let resolved = path.resolve(filePath);
456
522
  try {
@@ -460,15 +526,16 @@ async function invokedFromCLI() {
460
526
  // If realpath fails, compare the absolute path. This keeps direct execution
461
527
  // working even when the script path disappears during process startup.
462
528
  }
463
- return normalizeFileURL(url.pathToFileURL(resolved).href);
529
+ return normalizeFileURL(pathToFileURL(resolved).href);
464
530
  }
465
- return (await realFileURL(scriptPath)) === (await realFileURL(url.fileURLToPath(import.meta.url)));
531
+ return ((await realFileURL(scriptPath)) ===
532
+ (await realFileURL(fileURLToPath(import.meta.url))));
466
533
  }
467
534
  invokedFromCLI().then((invoked) => {
468
535
  if (!invoked) {
469
536
  return;
470
537
  }
471
- main().then((code) => {
538
+ runCli(["login", ...process.argv.slice(2)]).then((code) => {
472
539
  process.exitCode = code;
473
540
  }, (err) => {
474
541
  process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
@@ -0,0 +1 @@
1
+ export { createPaybondMcpToolSurface, type PaybondMcpToolSurface, type PaybondMcpToolSurfaceOptions, } from "./tool-surface.js";
@@ -0,0 +1 @@
1
+ export { createPaybondMcpToolSurface, } from "./tool-surface.js";
@@ -0,0 +1,25 @@
1
+ import type { PaybondAgentRun } from "../agent/run.js";
2
+ import { type McpInstallFormat, type McpServerEntry } from "../cli/mcp-install.js";
3
+ import type { McpToolPolicyConfig } from "../cli/mcp-policy.js";
4
+ export type PaybondMcpToolSurfaceOptions = {
5
+ /** Env file referenced by `PAYBOND_ENV_FILE` in the MCP host config (default `.env.local`). */
6
+ envFile?: string;
7
+ /** Override stdio server launch command (default: package-local `paybond-mcp-server`). */
8
+ serverCommand?: string[];
9
+ /** Optional MCP tool exposure policy for the stdio server process. */
10
+ toolPolicy?: McpToolPolicyConfig | null;
11
+ };
12
+ /** Stdio MCP host configuration derived from `paybond mcp install` patterns. */
13
+ export type PaybondMcpToolSurface = {
14
+ serverConfig: McpServerEntry;
15
+ /** Serialize host config as JSON (Claude Desktop, generic) or TOML (Codex). */
16
+ installPayload: (format?: McpInstallFormat) => string;
17
+ };
18
+ /**
19
+ * Framework runner helper for external MCP hosts (Claude Desktop, Codex, generic stdio).
20
+ *
21
+ * The bound {@link PaybondAgentRun} establishes tenant/intent context for your app;
22
+ * the returned `serverConfig` is the stdio entry coding-agent hosts consume via
23
+ * `PAYBOND_ENV_FILE` (never raw API keys in host config files).
24
+ */
25
+ export declare function createPaybondMcpToolSurface(_run: PaybondAgentRun, options?: PaybondMcpToolSurfaceOptions): PaybondMcpToolSurface;