@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.
- package/completion-presets/catalog.json +1187 -0
- package/completion-presets/catalog.sha256 +1 -0
- package/dev/trace-ui/dashboard.html +617 -0
- package/dist/agent/adapter.d.ts +51 -0
- package/dist/agent/adapter.js +66 -0
- package/dist/agent/attach-bundle.d.ts +37 -0
- package/dist/agent/attach-bundle.js +118 -0
- package/dist/agent/authorization-cache.d.ts +22 -0
- package/dist/agent/authorization-cache.js +36 -0
- package/dist/agent/deferred-tools.d.ts +11 -0
- package/dist/agent/deferred-tools.js +62 -0
- package/dist/agent/discover.d.ts +41 -0
- package/dist/agent/discover.js +147 -0
- package/dist/agent/evidence.d.ts +9 -0
- package/dist/agent/evidence.js +28 -0
- package/dist/agent/facade.d.ts +48 -0
- package/dist/agent/facade.js +112 -0
- package/dist/agent/gateway-trace-reporter.d.ts +28 -0
- package/dist/agent/gateway-trace-reporter.js +49 -0
- package/dist/agent/generic-runner.d.ts +14 -0
- package/dist/agent/generic-runner.js +49 -0
- package/dist/agent/generic-sandbox-demo.d.ts +36 -0
- package/dist/agent/generic-sandbox-demo.js +82 -0
- package/dist/agent/guarded-agent.d.ts +49 -0
- package/dist/agent/guarded-agent.js +100 -0
- package/dist/agent/index.d.ts +13 -0
- package/dist/agent/index.js +13 -0
- package/dist/agent/instrument.d.ts +156 -0
- package/dist/agent/instrument.js +442 -0
- package/dist/agent/interceptor.d.ts +24 -0
- package/dist/agent/interceptor.js +440 -0
- package/dist/agent/lazy-context-tools.d.ts +15 -0
- package/dist/agent/lazy-context-tools.js +81 -0
- package/dist/agent/registry-file.d.ts +39 -0
- package/dist/agent/registry-file.js +219 -0
- package/dist/agent/registry.d.ts +37 -0
- package/dist/agent/registry.js +128 -0
- package/dist/agent/run.d.ts +124 -0
- package/dist/agent/run.js +301 -0
- package/dist/agent/types.d.ts +318 -0
- package/dist/agent/types.js +42 -0
- package/dist/agent-recognition.d.ts +72 -0
- package/dist/agent-recognition.js +165 -0
- package/dist/bincode-wire.d.ts +18 -0
- package/dist/bincode-wire.js +93 -0
- package/dist/claude-agents/config.d.ts +21 -0
- package/dist/claude-agents/config.js +145 -0
- package/dist/claude-agents/index.d.ts +2 -0
- package/dist/claude-agents/index.js +2 -0
- package/dist/claude-agents/sandbox-demo.d.ts +30 -0
- package/dist/claude-agents/sandbox-demo.js +91 -0
- package/dist/cli/agent/env-quote.d.ts +1 -0
- package/dist/cli/agent/env-quote.js +6 -0
- package/dist/cli/agent/env-write.d.ts +8 -0
- package/dist/cli/agent/env-write.js +47 -0
- package/dist/cli/agent/paybond.d.ts +16 -0
- package/dist/cli/agent/paybond.js +55 -0
- package/dist/cli/agent/policy-file.d.ts +29 -0
- package/dist/cli/agent/policy-file.js +61 -0
- package/dist/cli/agent/production-evidence.d.ts +24 -0
- package/dist/cli/agent/production-evidence.js +98 -0
- package/dist/cli/agent/run-store.d.ts +30 -0
- package/dist/cli/agent/run-store.js +42 -0
- package/dist/cli/agent/run-trace-store.d.ts +39 -0
- package/dist/cli/agent/run-trace-store.js +143 -0
- package/dist/cli/agent-run-trace-table.d.ts +9 -0
- package/dist/cli/agent-run-trace-table.js +24 -0
- package/dist/cli/agent-sandbox-smoke-checklist.d.ts +9 -0
- package/dist/cli/agent-sandbox-smoke-checklist.js +50 -0
- package/dist/cli/audit-export.d.ts +7 -0
- package/dist/cli/audit-export.js +120 -0
- package/dist/cli/automation.d.ts +25 -0
- package/dist/cli/automation.js +297 -0
- package/dist/cli/body.d.ts +7 -0
- package/dist/cli/body.js +22 -0
- package/dist/cli/color.d.ts +15 -0
- package/dist/cli/color.js +39 -0
- package/dist/cli/command-spec.d.ts +13 -0
- package/dist/cli/command-spec.js +611 -0
- package/dist/cli/commands/agent.d.ts +16 -0
- package/dist/cli/commands/agent.js +1135 -0
- package/dist/cli/commands/dev.d.ts +7 -0
- package/dist/cli/commands/dev.js +348 -0
- package/dist/cli/commands/discovery.d.ts +8 -0
- package/dist/cli/commands/discovery.js +194 -0
- package/dist/cli/commands/policy.d.ts +13 -0
- package/dist/cli/commands/policy.js +769 -0
- package/dist/cli/commands/setup.d.ts +18 -0
- package/dist/cli/commands/setup.js +513 -0
- package/dist/cli/commands/workflows.d.ts +7 -0
- package/dist/cli/commands/workflows.js +214 -0
- package/dist/cli/config.d.ts +16 -0
- package/dist/cli/config.js +98 -0
- package/dist/cli/context.d.ts +22 -0
- package/dist/cli/context.js +110 -0
- package/dist/cli/credentials.d.ts +21 -0
- package/dist/cli/credentials.js +141 -0
- package/dist/cli/doctor-agent-middleware.d.ts +5 -0
- package/dist/cli/doctor-agent-middleware.js +49 -0
- package/dist/cli/doctor-agent.d.ts +15 -0
- package/dist/cli/doctor-agent.js +311 -0
- package/dist/cli/envelope.d.ts +14 -0
- package/dist/cli/envelope.js +46 -0
- package/dist/cli/globals.d.ts +23 -0
- package/dist/cli/globals.js +248 -0
- package/dist/cli/help.d.ts +3 -0
- package/dist/cli/help.js +83 -0
- package/dist/cli/mcp-install.d.ts +41 -0
- package/dist/cli/mcp-install.js +95 -0
- package/dist/cli/mcp-policy.d.ts +26 -0
- package/dist/cli/mcp-policy.js +110 -0
- package/dist/cli/mcp-verify-config.d.ts +37 -0
- package/dist/cli/mcp-verify-config.js +172 -0
- package/dist/cli/redact.d.ts +4 -0
- package/dist/cli/redact.js +88 -0
- package/dist/cli/request-id.d.ts +2 -0
- package/dist/cli/request-id.js +5 -0
- package/dist/cli/router.d.ts +2 -0
- package/dist/cli/router.js +378 -0
- package/dist/cli/smoke-deep-links.d.ts +15 -0
- package/dist/cli/smoke-deep-links.js +63 -0
- package/dist/cli/suggest.d.ts +4 -0
- package/dist/cli/suggest.js +58 -0
- package/dist/cli/support-diagnostics.d.ts +19 -0
- package/dist/cli/support-diagnostics.js +47 -0
- package/dist/cli/telemetry.d.ts +17 -0
- package/dist/cli/telemetry.js +94 -0
- package/dist/cli/types.d.ts +72 -0
- package/dist/cli/types.js +60 -0
- package/dist/cli/ux.d.ts +8 -0
- package/dist/cli/ux.js +164 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +38 -0
- package/dist/completion-catalog-digest.d.ts +2 -0
- package/dist/completion-catalog-digest.js +2 -0
- package/dist/completion-catalog-integrity.d.ts +2 -0
- package/dist/completion-catalog-integrity.js +17 -0
- package/dist/completion-catalog.d.ts +49 -0
- package/dist/completion-catalog.js +62 -0
- package/dist/completion-contract-digest.d.ts +37 -0
- package/dist/completion-contract-digest.js +73 -0
- package/dist/completion-forbidden-fields.d.ts +5 -0
- package/dist/completion-forbidden-fields.js +26 -0
- package/dist/completion-init.d.ts +8 -0
- package/dist/completion-init.js +334 -0
- package/dist/completion-resolve.d.ts +21 -0
- package/dist/completion-resolve.js +86 -0
- package/dist/completion-validate-evidence.d.ts +24 -0
- package/dist/completion-validate-evidence.js +145 -0
- package/dist/dev/offline-gateway.d.ts +24 -0
- package/dist/dev/offline-gateway.js +102 -0
- package/dist/dev/trace-buffer.d.ts +61 -0
- package/dist/dev/trace-buffer.js +330 -0
- package/dist/dev/trace-security-headers.d.ts +11 -0
- package/dist/dev/trace-security-headers.js +16 -0
- package/dist/dev/trace-server.d.ts +8 -0
- package/dist/dev/trace-server.js +38 -0
- package/dist/dev/trace-ui.d.ts +4 -0
- package/dist/dev/trace-ui.js +25 -0
- package/dist/dev/wiremock-up.d.ts +15 -0
- package/dist/dev/wiremock-up.js +118 -0
- package/dist/doctor-completion.d.ts +17 -0
- package/dist/doctor-completion.js +428 -0
- package/dist/gateway-url.d.ts +7 -0
- package/dist/gateway-url.js +69 -0
- package/dist/index.d.ts +119 -2
- package/dist/index.js +267 -6
- package/dist/init.js +380 -68
- package/dist/langgraph/awrap-tool-call.d.ts +25 -0
- package/dist/langgraph/awrap-tool-call.js +81 -0
- package/dist/langgraph/config.d.ts +13 -0
- package/dist/langgraph/config.js +11 -0
- package/dist/langgraph/index.d.ts +4 -0
- package/dist/langgraph/index.js +4 -0
- package/dist/langgraph/sandbox-demo.d.ts +40 -0
- package/dist/langgraph/sandbox-demo.js +96 -0
- package/dist/langgraph/tool-node.d.ts +10 -0
- package/dist/langgraph/tool-node.js +38 -0
- package/dist/login.d.ts +14 -1
- package/dist/login.js +130 -63
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/tool-surface.d.ts +25 -0
- package/dist/mcp/tool-surface.js +17 -0
- package/dist/mcp-capability-token-cache.d.ts +24 -0
- package/dist/mcp-capability-token-cache.js +101 -0
- package/dist/mcp-evidence-policy.d.ts +48 -0
- package/dist/mcp-evidence-policy.js +117 -0
- package/dist/mcp-policy-reload.d.ts +79 -0
- package/dist/mcp-policy-reload.js +200 -0
- package/dist/mcp-sep2828-evidence.d.ts +36 -0
- package/dist/mcp-sep2828-evidence.js +65 -0
- package/dist/mcp-server.d.ts +10 -0
- package/dist/mcp-server.js +423 -115
- package/dist/openai-agents/index.d.ts +40 -0
- package/dist/openai-agents/index.js +151 -0
- package/dist/openai-agents/sandbox-demo.d.ts +34 -0
- package/dist/openai-agents/sandbox-demo.js +118 -0
- package/dist/payee-evidence.js +2 -29
- package/dist/policy/catalog.d.ts +31 -0
- package/dist/policy/catalog.js +48 -0
- package/dist/policy/compose-utils.d.ts +3 -0
- package/dist/policy/compose-utils.js +4 -0
- package/dist/policy/compose.d.ts +20 -0
- package/dist/policy/compose.js +240 -0
- package/dist/policy/digest.d.ts +7 -0
- package/dist/policy/digest.js +75 -0
- package/dist/policy/domain.d.ts +15 -0
- package/dist/policy/domain.js +28 -0
- package/dist/policy/guardrail-spec.d.ts +17 -0
- package/dist/policy/guardrail-spec.js +140 -0
- package/dist/policy/guardrails.d.ts +48 -0
- package/dist/policy/guardrails.js +72 -0
- package/dist/policy/index.d.ts +21 -0
- package/dist/policy/index.js +21 -0
- package/dist/policy/init.d.ts +102 -0
- package/dist/policy/init.js +351 -0
- package/dist/policy/intent-spec.d.ts +52 -0
- package/dist/policy/intent-spec.js +176 -0
- package/dist/policy/json-path.d.ts +4 -0
- package/dist/policy/json-path.js +23 -0
- package/dist/policy/layers-io.d.ts +7 -0
- package/dist/policy/layers-io.js +28 -0
- package/dist/policy/load-effective.d.ts +22 -0
- package/dist/policy/load-effective.js +77 -0
- package/dist/policy/load.d.ts +85 -0
- package/dist/policy/load.js +164 -0
- package/dist/policy/merge.d.ts +29 -0
- package/dist/policy/merge.js +297 -0
- package/dist/policy/parse-text.d.ts +2 -0
- package/dist/policy/parse-text.js +126 -0
- package/dist/policy/policy-api.d.ts +45 -0
- package/dist/policy/policy-api.js +61 -0
- package/dist/policy/presets.d.ts +19 -0
- package/dist/policy/presets.js +66 -0
- package/dist/policy/registry.d.ts +7 -0
- package/dist/policy/registry.js +33 -0
- package/dist/policy/reload.d.ts +86 -0
- package/dist/policy/reload.js +233 -0
- package/dist/policy/render-yaml.d.ts +3 -0
- package/dist/policy/render-yaml.js +69 -0
- package/dist/policy/sandbox-bootstrap.d.ts +19 -0
- package/dist/policy/sandbox-bootstrap.js +66 -0
- package/dist/policy/schema.d.ts +204 -0
- package/dist/policy/schema.js +255 -0
- package/dist/policy/snapshot.d.ts +33 -0
- package/dist/policy/snapshot.js +23 -0
- package/dist/policy/validate-remote.d.ts +43 -0
- package/dist/policy/validate-remote.js +104 -0
- package/dist/policy/validate.d.ts +36 -0
- package/dist/policy/validate.js +150 -0
- package/dist/policy/watcher.d.ts +29 -0
- package/dist/policy/watcher.js +112 -0
- package/dist/principal-intent.d.ts +52 -0
- package/dist/principal-intent.js +193 -37
- package/dist/project-init.d.ts +34 -0
- package/dist/project-init.js +898 -0
- package/dist/sep2828-signature.d.ts +10 -0
- package/dist/sep2828-signature.js +134 -0
- package/dist/solutions/api.d.ts +22 -0
- package/dist/solutions/api.js +40 -0
- package/dist/solutions/catalog.d.ts +34 -0
- package/dist/solutions/catalog.js +129 -0
- package/dist/solutions/index.d.ts +2 -0
- package/dist/solutions/index.js +2 -0
- package/dist/template-init.d.ts +54 -0
- package/dist/template-init.js +203 -0
- package/dist/vercel-ai/config.d.ts +15 -0
- package/dist/vercel-ai/config.js +13 -0
- package/dist/vercel-ai/index.d.ts +4 -0
- package/dist/vercel-ai/index.js +4 -0
- package/dist/vercel-ai/sandbox-demo.d.ts +44 -0
- package/dist/vercel-ai/sandbox-demo.js +153 -0
- package/dist/vercel-ai/tool-approval.d.ts +16 -0
- package/dist/vercel-ai/tool-approval.js +41 -0
- package/dist/vercel-ai/wrap-tools.d.ts +9 -0
- package/dist/vercel-ai/wrap-tools.js +40 -0
- package/dist/x402-receipt-evidence.d.ts +29 -0
- package/dist/x402-receipt-evidence.js +97 -0
- package/dist/x402-receipt-signature.d.ts +12 -0
- package/dist/x402-receipt-signature.js +211 -0
- package/package.json +79 -4
- package/solutions/aws.json +17 -0
- package/solutions/saas.json +17 -0
- package/solutions/shopping.json +17 -0
- package/solutions/travel.json +18 -0
- package/templates/manifest.json +169 -0
- package/templates/openai-shopping-agent/.env.example +3 -0
- package/templates/openai-shopping-agent/.github/workflows/smoke.yml +20 -0
- package/templates/openai-shopping-agent/LICENSE +201 -0
- package/templates/openai-shopping-agent/README.md +29 -0
- package/templates/openai-shopping-agent/package.json +22 -0
- package/templates/openai-shopping-agent/paybond.policy.yaml +22 -0
- package/templates/openai-shopping-agent/src/index.ts +22 -0
- package/templates/openai-shopping-agent/src/paybond.config.ts +51 -0
- package/templates/openai-shopping-agent/tsconfig.json +13 -0
- package/templates/paybond-aws-operator/.env.example +3 -0
- package/templates/paybond-aws-operator/.github/workflows/smoke.yml +20 -0
- package/templates/paybond-aws-operator/LICENSE +201 -0
- package/templates/paybond-aws-operator/README.md +29 -0
- package/templates/paybond-aws-operator/package.json +20 -0
- package/templates/paybond-aws-operator/paybond.policy.yaml +22 -0
- package/templates/paybond-aws-operator/src/index.ts +54 -0
- package/templates/paybond-aws-operator/src/paybond.config.ts +51 -0
- package/templates/paybond-aws-operator/tsconfig.json +13 -0
- package/templates/paybond-claude-agents-demo/.env.example +3 -0
- package/templates/paybond-claude-agents-demo/.github/workflows/smoke.yml +20 -0
- package/templates/paybond-claude-agents-demo/LICENSE +201 -0
- package/templates/paybond-claude-agents-demo/README.md +29 -0
- package/templates/paybond-claude-agents-demo/package.json +22 -0
- package/templates/paybond-claude-agents-demo/paybond.policy.yaml +22 -0
- package/templates/paybond-claude-agents-demo/src/index.ts +22 -0
- package/templates/paybond-claude-agents-demo/src/paybond.config.ts +51 -0
- package/templates/paybond-claude-agents-demo/tsconfig.json +13 -0
- package/templates/paybond-invoice-agent/.env.example +3 -0
- package/templates/paybond-invoice-agent/.github/workflows/smoke.yml +19 -0
- package/templates/paybond-invoice-agent/LICENSE +201 -0
- package/templates/paybond-invoice-agent/README.md +29 -0
- package/templates/paybond-invoice-agent/app.py +27 -0
- package/templates/paybond-invoice-agent/package.json +6 -0
- package/templates/paybond-invoice-agent/paybond.policy.yaml +22 -0
- package/templates/paybond-invoice-agent/paybond_config.py +45 -0
- package/templates/paybond-invoice-agent/requirements.txt +2 -0
- package/templates/paybond-mcp-coding-agent/.env.example +3 -0
- package/templates/paybond-mcp-coding-agent/.github/workflows/smoke.yml +20 -0
- package/templates/paybond-mcp-coding-agent/LICENSE +201 -0
- package/templates/paybond-mcp-coding-agent/README.md +39 -0
- package/templates/paybond-mcp-coding-agent/package.json +20 -0
- package/templates/paybond-mcp-coding-agent/paybond.policy.yaml +25 -0
- package/templates/paybond-mcp-coding-agent/src/index.ts +40 -0
- package/templates/paybond-mcp-coding-agent/src/paybond.config.ts +51 -0
- package/templates/paybond-mcp-coding-agent/tsconfig.json +13 -0
- package/templates/paybond-openai-agents-demo/.env.example +3 -0
- package/templates/paybond-openai-agents-demo/.github/workflows/smoke.yml +20 -0
- package/templates/paybond-openai-agents-demo/LICENSE +201 -0
- package/templates/paybond-openai-agents-demo/README.md +29 -0
- package/templates/paybond-openai-agents-demo/package.json +22 -0
- package/templates/paybond-openai-agents-demo/paybond.policy.yaml +22 -0
- package/templates/paybond-openai-agents-demo/src/index.ts +22 -0
- package/templates/paybond-openai-agents-demo/src/paybond.config.ts +51 -0
- package/templates/paybond-openai-agents-demo/tsconfig.json +13 -0
- package/templates/paybond-procurement-agent/.env.example +3 -0
- package/templates/paybond-procurement-agent/.github/workflows/smoke.yml +20 -0
- package/templates/paybond-procurement-agent/LICENSE +201 -0
- package/templates/paybond-procurement-agent/README.md +29 -0
- package/templates/paybond-procurement-agent/package.json +20 -0
- package/templates/paybond-procurement-agent/paybond.policy.yaml +25 -0
- package/templates/paybond-procurement-agent/src/index.ts +54 -0
- package/templates/paybond-procurement-agent/src/paybond.config.ts +51 -0
- package/templates/paybond-procurement-agent/tsconfig.json +13 -0
- package/templates/paybond-travel-agent/.env.example +3 -0
- package/templates/paybond-travel-agent/.github/workflows/smoke.yml +20 -0
- package/templates/paybond-travel-agent/LICENSE +201 -0
- package/templates/paybond-travel-agent/README.md +29 -0
- package/templates/paybond-travel-agent/package.json +23 -0
- package/templates/paybond-travel-agent/paybond.policy.yaml +22 -0
- package/templates/paybond-travel-agent/src/index.ts +22 -0
- package/templates/paybond-travel-agent/src/paybond.config.ts +51 -0
- package/templates/paybond-travel-agent/tsconfig.json +13 -0
- package/templates/paybond-vercel-shopping-agent/.env.example +3 -0
- package/templates/paybond-vercel-shopping-agent/.github/workflows/smoke.yml +20 -0
- package/templates/paybond-vercel-shopping-agent/LICENSE +201 -0
- package/templates/paybond-vercel-shopping-agent/README.md +29 -0
- package/templates/paybond-vercel-shopping-agent/package.json +22 -0
- package/templates/paybond-vercel-shopping-agent/paybond.policy.yaml +22 -0
- package/templates/paybond-vercel-shopping-agent/src/index.ts +22 -0
- package/templates/paybond-vercel-shopping-agent/src/paybond.config.ts +51 -0
- 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<
|
|
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 =
|
|
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:
|
|
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 !== "" &&
|
|
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 ===
|
|
225
|
+
if (ignoreResult.code === GIT_CHECK_IGNORE_MATCHED) {
|
|
185
226
|
return;
|
|
186
227
|
}
|
|
187
|
-
if (ignoreResult.code ===
|
|
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 &&
|
|
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:
|
|
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 ===
|
|
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 &&
|
|
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 &&
|
|
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:
|
|
238
|
-
await fs.chmod(envPath,
|
|
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") ||
|
|
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",
|
|
294
|
-
interval: numberField(body, "interval",
|
|
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 ||
|
|
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 ||
|
|
336
|
-
const expiresAtMs = deps.now() + Math.max(1, start.expires_in) *
|
|
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 *
|
|
339
|
-
if (deps.now() > expiresAtMs +
|
|
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 >=
|
|
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 >
|
|
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 ===
|
|
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
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
stdout.write(`
|
|
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
|
|
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
|
-
|
|
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/")
|
|
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(
|
|
529
|
+
return normalizeFileURL(pathToFileURL(resolved).href);
|
|
464
530
|
}
|
|
465
|
-
return (await realFileURL(scriptPath)) ===
|
|
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
|
-
|
|
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;
|