@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,94 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { platform } from "node:os";
|
|
3
|
+
import { loadConfigFile, saveConfigFile } from "./config.js";
|
|
4
|
+
import { packageVersion } from "./doctor-agent.js";
|
|
5
|
+
import { isLocalGatewayHost } from "../gateway-url.js";
|
|
6
|
+
const INSTALL_ID_HASH_PREFIX = "paybond-kit-cli:";
|
|
7
|
+
function telemetryEnvDisabled() {
|
|
8
|
+
const raw = process.env.PAYBOND_TELEMETRY?.trim().toLowerCase();
|
|
9
|
+
return raw === "0" || raw === "false" || raw === "off" || raw === "no";
|
|
10
|
+
}
|
|
11
|
+
function telemetryEnvForced() {
|
|
12
|
+
const raw = process.env.PAYBOND_TELEMETRY?.trim().toLowerCase();
|
|
13
|
+
return raw === "1" || raw === "true" || raw === "on" || raw === "yes";
|
|
14
|
+
}
|
|
15
|
+
function isCiEnvironment() {
|
|
16
|
+
const ci = process.env.CI?.trim().toLowerCase();
|
|
17
|
+
return ci === "true" || ci === "1";
|
|
18
|
+
}
|
|
19
|
+
function isLocalGateway(gateway) {
|
|
20
|
+
try {
|
|
21
|
+
return isLocalGatewayHost(new URL(gateway).hostname);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function hashCliInstallId(installId) {
|
|
28
|
+
return createHash("sha256").update(`${INSTALL_ID_HASH_PREFIX}${installId}`).digest("hex");
|
|
29
|
+
}
|
|
30
|
+
export async function resolveCliInstallId() {
|
|
31
|
+
const config = await loadConfigFile();
|
|
32
|
+
const existing = config.install_id?.trim();
|
|
33
|
+
if (existing) {
|
|
34
|
+
return existing;
|
|
35
|
+
}
|
|
36
|
+
const installId = randomUUID();
|
|
37
|
+
await saveConfigFile({ ...config, install_id: installId });
|
|
38
|
+
return installId;
|
|
39
|
+
}
|
|
40
|
+
export async function cliTelemetryEnabled(gateway) {
|
|
41
|
+
if (telemetryEnvDisabled() || isCiEnvironment()) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (telemetryEnvForced()) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
const config = await loadConfigFile();
|
|
48
|
+
if (config.telemetry === false) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return !isLocalGateway(gateway);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Fire-and-forget adoption telemetry for successful local dev commands.
|
|
55
|
+
* Failures are swallowed so CLI workflows never depend on analytics.
|
|
56
|
+
*/
|
|
57
|
+
export async function reportCliCommandSuccess(ctx, input) {
|
|
58
|
+
if (!(await cliTelemetryEnabled(ctx.globals.gateway))) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const installId = await resolveCliInstallId();
|
|
62
|
+
const body = {
|
|
63
|
+
command_path: input.commandPath,
|
|
64
|
+
success: true,
|
|
65
|
+
offline: input.offline,
|
|
66
|
+
kit_version: packageVersion(),
|
|
67
|
+
runtime: "node",
|
|
68
|
+
install_id_sha256: hashCliInstallId(installId),
|
|
69
|
+
os_name: platform(),
|
|
70
|
+
client_context: {
|
|
71
|
+
format: ctx.globals.format,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
const url = `${ctx.globals.gateway.replace(/\/+$/, "")}/v1/public/analytics/kit-cli`;
|
|
75
|
+
const controller = new AbortController();
|
|
76
|
+
const timeout = setTimeout(() => controller.abort(), 2_000);
|
|
77
|
+
try {
|
|
78
|
+
await ctx.fetch(url, {
|
|
79
|
+
method: "POST",
|
|
80
|
+
headers: { "content-type": "application/json" },
|
|
81
|
+
body: JSON.stringify(body),
|
|
82
|
+
signal: controller.signal,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Telemetry must never block or fail the CLI command.
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
clearTimeout(timeout);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export function scheduleCliCommandTelemetry(ctx, input) {
|
|
93
|
+
void reportCliCommandSuccess(ctx, input);
|
|
94
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type OutputFormat = "table" | "json";
|
|
2
|
+
export type ColorMode = "auto" | "always" | "never";
|
|
3
|
+
export type ErrorCategory = "usage" | "auth" | "forbidden" | "validation" | "not_found" | "gone" | "confirmation_required" | "rate_limit" | "gateway" | "network" | "environment" | "internal";
|
|
4
|
+
export type CliErrorDetails = Record<string, unknown>;
|
|
5
|
+
export type CliErrorShape = {
|
|
6
|
+
category: ErrorCategory;
|
|
7
|
+
code: string;
|
|
8
|
+
message: string;
|
|
9
|
+
details?: CliErrorDetails;
|
|
10
|
+
};
|
|
11
|
+
export type CliEnvelope<T> = {
|
|
12
|
+
ok: boolean;
|
|
13
|
+
command: string;
|
|
14
|
+
data: T | null;
|
|
15
|
+
warnings: string[];
|
|
16
|
+
request_id: string;
|
|
17
|
+
error: CliErrorShape | null;
|
|
18
|
+
};
|
|
19
|
+
export type GlobalOptions = {
|
|
20
|
+
gateway: string;
|
|
21
|
+
envFile: string;
|
|
22
|
+
format: OutputFormat;
|
|
23
|
+
color: ColorMode;
|
|
24
|
+
profile?: string;
|
|
25
|
+
requestId: string;
|
|
26
|
+
yes: boolean;
|
|
27
|
+
noOpen: boolean;
|
|
28
|
+
/** Comma-separated field names for automation output (`--json`). */
|
|
29
|
+
jsonFields?: string;
|
|
30
|
+
/** jq-style filter expression (`--jq`). */
|
|
31
|
+
jqExpr?: string;
|
|
32
|
+
};
|
|
33
|
+
export type Writable = {
|
|
34
|
+
write(chunk: string): boolean;
|
|
35
|
+
};
|
|
36
|
+
export type CliDependencies = {
|
|
37
|
+
cwd?: string;
|
|
38
|
+
fetch?: typeof fetch;
|
|
39
|
+
stdout?: Writable;
|
|
40
|
+
stderr?: Writable;
|
|
41
|
+
now?: () => number;
|
|
42
|
+
sleep?: (ms: number) => Promise<void>;
|
|
43
|
+
openBrowser?: (url: string) => Promise<boolean>;
|
|
44
|
+
};
|
|
45
|
+
export type CommandResult<T = Record<string, unknown>> = {
|
|
46
|
+
data: T;
|
|
47
|
+
warnings?: string[];
|
|
48
|
+
};
|
|
49
|
+
export declare const EXIT_SUCCESS = 0;
|
|
50
|
+
export declare const EXIT_FAILURE = 1;
|
|
51
|
+
export declare const EXIT_AUTH = 2;
|
|
52
|
+
export declare const EXIT_FORBIDDEN = 3;
|
|
53
|
+
export declare const EXIT_CONFIRMATION = 4;
|
|
54
|
+
export declare const EXIT_GATEWAY = 5;
|
|
55
|
+
export declare const EXIT_ENVIRONMENT = 6;
|
|
56
|
+
export declare class CliError extends Error {
|
|
57
|
+
readonly category: ErrorCategory;
|
|
58
|
+
readonly code: string;
|
|
59
|
+
readonly exitCode: number;
|
|
60
|
+
readonly details?: CliErrorDetails;
|
|
61
|
+
constructor(message: string, options?: {
|
|
62
|
+
category?: ErrorCategory;
|
|
63
|
+
code?: string;
|
|
64
|
+
exitCode?: number;
|
|
65
|
+
details?: CliErrorDetails;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
export declare function exitCodeForCategory(category: ErrorCategory): number;
|
|
69
|
+
export declare function exitCodeForHttpStatus(status: number): {
|
|
70
|
+
exitCode: number;
|
|
71
|
+
category: ErrorCategory;
|
|
72
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const EXIT_SUCCESS = 0;
|
|
2
|
+
export const EXIT_FAILURE = 1;
|
|
3
|
+
export const EXIT_AUTH = 2;
|
|
4
|
+
export const EXIT_FORBIDDEN = 3;
|
|
5
|
+
export const EXIT_CONFIRMATION = 4;
|
|
6
|
+
export const EXIT_GATEWAY = 5;
|
|
7
|
+
export const EXIT_ENVIRONMENT = 6;
|
|
8
|
+
export class CliError extends Error {
|
|
9
|
+
category;
|
|
10
|
+
code;
|
|
11
|
+
exitCode;
|
|
12
|
+
details;
|
|
13
|
+
constructor(message, options = {}) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "CliError";
|
|
16
|
+
this.category = options.category ?? "usage";
|
|
17
|
+
this.code = options.code ?? `cli.${this.category}`;
|
|
18
|
+
this.exitCode = options.exitCode ?? exitCodeForCategory(this.category);
|
|
19
|
+
this.details = options.details;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function exitCodeForCategory(category) {
|
|
23
|
+
switch (category) {
|
|
24
|
+
case "auth":
|
|
25
|
+
return EXIT_AUTH;
|
|
26
|
+
case "forbidden":
|
|
27
|
+
return EXIT_FORBIDDEN;
|
|
28
|
+
case "confirmation_required":
|
|
29
|
+
return EXIT_CONFIRMATION;
|
|
30
|
+
case "gateway":
|
|
31
|
+
case "rate_limit":
|
|
32
|
+
case "network":
|
|
33
|
+
return EXIT_GATEWAY;
|
|
34
|
+
case "environment":
|
|
35
|
+
return EXIT_ENVIRONMENT;
|
|
36
|
+
default:
|
|
37
|
+
return EXIT_FAILURE;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function exitCodeForHttpStatus(status) {
|
|
41
|
+
if (status === 401) {
|
|
42
|
+
return { exitCode: EXIT_AUTH, category: "auth" };
|
|
43
|
+
}
|
|
44
|
+
if (status === 403) {
|
|
45
|
+
return { exitCode: EXIT_FORBIDDEN, category: "forbidden" };
|
|
46
|
+
}
|
|
47
|
+
if (status === 404) {
|
|
48
|
+
return { exitCode: EXIT_FAILURE, category: "not_found" };
|
|
49
|
+
}
|
|
50
|
+
if (status === 410) {
|
|
51
|
+
return { exitCode: EXIT_FAILURE, category: "gone" };
|
|
52
|
+
}
|
|
53
|
+
if (status === 429) {
|
|
54
|
+
return { exitCode: EXIT_GATEWAY, category: "rate_limit" };
|
|
55
|
+
}
|
|
56
|
+
if (status >= 500) {
|
|
57
|
+
return { exitCode: EXIT_GATEWAY, category: "gateway" };
|
|
58
|
+
}
|
|
59
|
+
return { exitCode: EXIT_FAILURE, category: "validation" };
|
|
60
|
+
}
|
package/dist/cli/ux.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CliContext } from "./context.js";
|
|
2
|
+
import { type CommandResult } from "./types.js";
|
|
3
|
+
export declare function resolveHelpPath(argv: string[]): string;
|
|
4
|
+
export declare function renderHelpText(path: string): string;
|
|
5
|
+
export declare function handleHelpCommand(argv: string[]): CommandResult;
|
|
6
|
+
export declare function handleExamplesCommand(argv: string[]): CommandResult;
|
|
7
|
+
export declare function handleCompletionCommand(argv: string[]): CommandResult;
|
|
8
|
+
export declare function handleOnboarding(ctx: CliContext, argv: string[]): Promise<CommandResult>;
|
package/dist/cli/ux.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { access } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { COMMAND_EXAMPLES, COMPLETION_SCRIPTS, WORKFLOWS } from "./command-spec.js";
|
|
4
|
+
import { resolvedDefaultsForDoctor } from "./credentials.js";
|
|
5
|
+
import { helpForCommand } from "./help.js";
|
|
6
|
+
import { consumeFlag } from "./globals.js";
|
|
7
|
+
import { planMcpInstall, parseMcpInstallFormat, parseMcpInstallHost, parseMcpInstallScope } from "./mcp-install.js";
|
|
8
|
+
import { CliError } from "./types.js";
|
|
9
|
+
import { handleDoctor } from "./commands/setup.js";
|
|
10
|
+
export function resolveHelpPath(argv) {
|
|
11
|
+
return argv.filter((part) => part !== "--help" && part !== "-h").join(" ");
|
|
12
|
+
}
|
|
13
|
+
export function renderHelpText(path) {
|
|
14
|
+
return helpForCommand(path);
|
|
15
|
+
}
|
|
16
|
+
export function handleHelpCommand(argv) {
|
|
17
|
+
const helpPath = resolveHelpPath(argv);
|
|
18
|
+
return { data: { text: renderHelpText(helpPath), path: helpPath || "paybond" } };
|
|
19
|
+
}
|
|
20
|
+
export function handleExamplesCommand(argv) {
|
|
21
|
+
const filterPath = argv.filter((part) => part !== "--help" && part !== "-h").join(" ");
|
|
22
|
+
const lines = [];
|
|
23
|
+
if (!filterPath) {
|
|
24
|
+
lines.push("Workflows:");
|
|
25
|
+
for (const workflow of WORKFLOWS) {
|
|
26
|
+
lines.push("", workflow.title);
|
|
27
|
+
if (workflow.description) {
|
|
28
|
+
lines.push(workflow.description);
|
|
29
|
+
}
|
|
30
|
+
for (const example of workflow.examples) {
|
|
31
|
+
lines.push(` $ ${example}`);
|
|
32
|
+
}
|
|
33
|
+
if (workflow.next) {
|
|
34
|
+
lines.push(` Next: ${workflow.next}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
lines.push("", "Commands:");
|
|
38
|
+
}
|
|
39
|
+
const entries = filterPath
|
|
40
|
+
? Object.entries(COMMAND_EXAMPLES).filter(([commandPath]) => commandPath === filterPath || commandPath.startsWith(`${filterPath} `))
|
|
41
|
+
: Object.entries(COMMAND_EXAMPLES);
|
|
42
|
+
if (filterPath && entries.length === 0) {
|
|
43
|
+
throw new CliError(`no examples found for: ${filterPath}`, {
|
|
44
|
+
category: "usage",
|
|
45
|
+
code: "cli.usage.unknown_command",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
for (const [commandPath, examples] of entries) {
|
|
49
|
+
lines.push("", `paybond ${commandPath}`);
|
|
50
|
+
for (const example of examples) {
|
|
51
|
+
lines.push(` $ ${example}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { data: { text: lines.join("\n").trim(), filter: filterPath || null, count: entries.length } };
|
|
55
|
+
}
|
|
56
|
+
export function handleCompletionCommand(argv) {
|
|
57
|
+
const shell = argv[0];
|
|
58
|
+
if (!shell || shell === "--help" || shell === "-h") {
|
|
59
|
+
throw new CliError("completion requires bash|zsh|fish", {
|
|
60
|
+
category: "usage",
|
|
61
|
+
code: "cli.usage.missing_completion_shell",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const script = COMPLETION_SCRIPTS[shell];
|
|
65
|
+
if (!script) {
|
|
66
|
+
throw new CliError(`unsupported completion shell: ${shell} (expected bash|zsh|fish)`, {
|
|
67
|
+
category: "usage",
|
|
68
|
+
code: "cli.usage.invalid_completion_shell",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return { data: { shell, script } };
|
|
72
|
+
}
|
|
73
|
+
export async function handleOnboarding(ctx, argv) {
|
|
74
|
+
const hostFlag = consumeFlag(argv, "--host");
|
|
75
|
+
let installHost = "generic";
|
|
76
|
+
try {
|
|
77
|
+
if (hostFlag.present) {
|
|
78
|
+
installHost = parseMcpInstallHost(hostFlag.value);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
throw new CliError(err instanceof Error ? err.message : String(err), {
|
|
83
|
+
category: "usage",
|
|
84
|
+
code: "cli.usage.invalid_mcp_install",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const steps = [];
|
|
88
|
+
steps.push({
|
|
89
|
+
name: "runtime",
|
|
90
|
+
ok: true,
|
|
91
|
+
message: `node ${process.version}`,
|
|
92
|
+
});
|
|
93
|
+
const defaults = resolvedDefaultsForDoctor(ctx.globals);
|
|
94
|
+
const envPath = path.isAbsolute(defaults.envFile)
|
|
95
|
+
? path.resolve(defaults.envFile)
|
|
96
|
+
: path.resolve(ctx.cwd, defaults.envFile);
|
|
97
|
+
let loggedIn = false;
|
|
98
|
+
try {
|
|
99
|
+
const { resolveApiKey } = await import("./credentials.js");
|
|
100
|
+
const apiKey = await resolveApiKey(ctx.globals, ctx.cwd);
|
|
101
|
+
loggedIn = true;
|
|
102
|
+
const { maskApiKey } = await import("./redact.js");
|
|
103
|
+
steps.push({
|
|
104
|
+
name: "login",
|
|
105
|
+
ok: true,
|
|
106
|
+
message: `credentials found (${maskApiKey(apiKey)})`,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
steps.push({
|
|
111
|
+
name: "login",
|
|
112
|
+
ok: false,
|
|
113
|
+
message: err instanceof Error ? err.message : String(err),
|
|
114
|
+
command: "paybond login",
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const guardrailPath = path.resolve(ctx.cwd, "paybond-paid-tool-guard.ts");
|
|
118
|
+
let guardrailExists = false;
|
|
119
|
+
try {
|
|
120
|
+
await access(guardrailPath);
|
|
121
|
+
guardrailExists = true;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
guardrailExists = false;
|
|
125
|
+
}
|
|
126
|
+
steps.push({
|
|
127
|
+
name: "guardrail",
|
|
128
|
+
ok: guardrailExists,
|
|
129
|
+
message: guardrailExists ? `found ${guardrailPath}` : `guardrail file not found (${guardrailPath})`,
|
|
130
|
+
command: guardrailExists ? undefined : "paybond init guardrail",
|
|
131
|
+
});
|
|
132
|
+
const plan = planMcpInstall({
|
|
133
|
+
host: installHost,
|
|
134
|
+
scope: parseMcpInstallScope("local"),
|
|
135
|
+
format: parseMcpInstallFormat(undefined, installHost),
|
|
136
|
+
envFile: defaults.envFile,
|
|
137
|
+
cwd: ctx.cwd,
|
|
138
|
+
home: process.env.HOME ?? process.env.USERPROFILE ?? ctx.cwd,
|
|
139
|
+
});
|
|
140
|
+
steps.push({
|
|
141
|
+
name: "mcp_config",
|
|
142
|
+
ok: true,
|
|
143
|
+
message: `preview ready for host=${plan.host} (non-destructive --scope local)`,
|
|
144
|
+
command: `paybond mcp install --host ${plan.host} --scope local`,
|
|
145
|
+
});
|
|
146
|
+
const doctor = await handleDoctor(ctx, loggedIn ? ["--agent"] : []);
|
|
147
|
+
const doctorOk = String(doctor.data.summary) === "pass";
|
|
148
|
+
steps.push({
|
|
149
|
+
name: "doctor",
|
|
150
|
+
ok: doctorOk,
|
|
151
|
+
message: `doctor ${doctor.data.summary}`,
|
|
152
|
+
command: doctorOk ? undefined : "paybond doctor --agent",
|
|
153
|
+
});
|
|
154
|
+
const summary = steps.every((step) => step.ok) ? "pass" : "fail";
|
|
155
|
+
return {
|
|
156
|
+
data: {
|
|
157
|
+
steps,
|
|
158
|
+
summary,
|
|
159
|
+
env_file: envPath,
|
|
160
|
+
mcp_preview: plan.printed ? plan.payload : undefined,
|
|
161
|
+
doctor_checks: doctor.data.checks,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
import { runCli } from "./cli/router.js";
|
|
6
|
+
async function invokedFromCLI() {
|
|
7
|
+
const scriptPath = process.argv[1];
|
|
8
|
+
if (!scriptPath) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
async function realFileURL(filePath) {
|
|
12
|
+
let resolved = path.resolve(filePath);
|
|
13
|
+
try {
|
|
14
|
+
resolved = await fs.realpath(resolved);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// keep absolute path
|
|
18
|
+
}
|
|
19
|
+
const href = pathToFileURL(resolved).href;
|
|
20
|
+
return href.startsWith("file:///var/") ? href.replace("file:///var/", "file:///private/var/") : href;
|
|
21
|
+
}
|
|
22
|
+
return (await realFileURL(scriptPath)) === (await realFileURL(fileURLToPath(import.meta.url)));
|
|
23
|
+
}
|
|
24
|
+
invokedFromCLI().then((invoked) => {
|
|
25
|
+
if (!invoked) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
runCli(process.argv.slice(2)).then((code) => {
|
|
29
|
+
process.exitCode = code;
|
|
30
|
+
}, (err) => {
|
|
31
|
+
process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
|
|
32
|
+
process.exitCode = 1;
|
|
33
|
+
});
|
|
34
|
+
}, (err) => {
|
|
35
|
+
process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
|
|
36
|
+
process.exitCode = 1;
|
|
37
|
+
});
|
|
38
|
+
export { runCli } from "./cli/router.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { BUNDLED_COMPLETION_CATALOG_SHA256_HEX } from "./completion-catalog-digest.js";
|
|
3
|
+
const INTEGRITY_SKIP = "skip";
|
|
4
|
+
function integrityCheckSkipped() {
|
|
5
|
+
return process.env.PAYBOND_COMPLETION_CATALOG_INTEGRITY?.trim().toLowerCase() === INTEGRITY_SKIP;
|
|
6
|
+
}
|
|
7
|
+
/** Verifies raw catalog bytes against the bundled SHA-256 digest. */
|
|
8
|
+
export function verifyBundledCompletionCatalogIntegrity(raw) {
|
|
9
|
+
if (integrityCheckSkipped()) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const bytes = typeof raw === "string" ? Buffer.from(raw, "utf8") : raw;
|
|
13
|
+
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
14
|
+
if (digest !== BUNDLED_COMPLETION_CATALOG_SHA256_HEX) {
|
|
15
|
+
throw new Error(`completion preset catalog integrity check failed (sha256=${digest}, expected=${BUNDLED_COMPLETION_CATALOG_SHA256_HEX})`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type CompletionPreset = {
|
|
2
|
+
preset_id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
description: string;
|
|
5
|
+
harbor_template_id: string;
|
|
6
|
+
parameters: Record<string, unknown>;
|
|
7
|
+
evidence_schema: Record<string, unknown>;
|
|
8
|
+
sample_evidence: Record<string, unknown>;
|
|
9
|
+
sample_failing_evidence: Record<string, unknown>;
|
|
10
|
+
human_summary: string;
|
|
11
|
+
recommended_amount_cents?: number;
|
|
12
|
+
spend_hints?: {
|
|
13
|
+
approval_threshold_cents?: number;
|
|
14
|
+
per_tool_max_cents?: number;
|
|
15
|
+
};
|
|
16
|
+
kind?: "archetype" | "vendor_pack";
|
|
17
|
+
archetype_preset_id?: string;
|
|
18
|
+
evidence_field_map?: Record<string, string>;
|
|
19
|
+
vendor_evidence_schema?: Record<string, unknown>;
|
|
20
|
+
vendor_sample_evidence?: Record<string, unknown>;
|
|
21
|
+
scope?: "tool_completion" | "sandbox_smoke";
|
|
22
|
+
rail_hints?: string[];
|
|
23
|
+
forbidden_evidence_fields?: string[];
|
|
24
|
+
anti_patterns?: string[];
|
|
25
|
+
deprecated?: boolean;
|
|
26
|
+
superseded_by?: string;
|
|
27
|
+
vendor_contract?: {
|
|
28
|
+
provider: "stripe" | "x402" | "mcp" | "generic";
|
|
29
|
+
api_version: string;
|
|
30
|
+
contract_kind: "json_schema" | "openapi_fragment" | "mapper_version";
|
|
31
|
+
schema_digest_hex: string;
|
|
32
|
+
canonical_schema_digest_hex: string;
|
|
33
|
+
quality_fields: string[];
|
|
34
|
+
supersedes?: string;
|
|
35
|
+
migration_notes?: string;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export type CompletionPresetCatalog = {
|
|
39
|
+
version: number;
|
|
40
|
+
presets: CompletionPreset[];
|
|
41
|
+
};
|
|
42
|
+
export declare function loadCompletionCatalog(): CompletionPresetCatalog;
|
|
43
|
+
export declare function listCompletionPresetIds(): string[];
|
|
44
|
+
export declare function getCompletionPreset(presetId: string): CompletionPreset;
|
|
45
|
+
export declare function getCompletionPresetByTemplateId(templateId: string): CompletionPreset | undefined;
|
|
46
|
+
export declare function listCompletionPresetsByTemplateId(templateId: string): CompletionPreset[];
|
|
47
|
+
export declare function jsonLiteral(value: unknown, indent?: number): string;
|
|
48
|
+
export declare function catalogPathForTests(): string;
|
|
49
|
+
export declare function catalogFileUrl(): string;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
+
import { verifyBundledCompletionCatalogIntegrity } from "./completion-catalog-integrity.js";
|
|
5
|
+
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
function catalogCandidatePaths() {
|
|
7
|
+
return [
|
|
8
|
+
join(MODULE_DIR, "../completion-presets/catalog.json"),
|
|
9
|
+
join(MODULE_DIR, "../../../kit/completion-presets/catalog.json"),
|
|
10
|
+
join(MODULE_DIR, "../../completion-presets/catalog.json"),
|
|
11
|
+
];
|
|
12
|
+
}
|
|
13
|
+
let cachedCatalog;
|
|
14
|
+
export function loadCompletionCatalog() {
|
|
15
|
+
if (cachedCatalog) {
|
|
16
|
+
return cachedCatalog;
|
|
17
|
+
}
|
|
18
|
+
let lastError;
|
|
19
|
+
for (const candidate of catalogCandidatePaths()) {
|
|
20
|
+
try {
|
|
21
|
+
const raw = readFileSync(candidate, "utf8");
|
|
22
|
+
verifyBundledCompletionCatalogIntegrity(raw);
|
|
23
|
+
cachedCatalog = JSON.parse(raw);
|
|
24
|
+
return cachedCatalog;
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
lastError = err;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
throw new Error(`completion preset catalog not found (${catalogCandidatePaths().join(", ")}): ${lastError instanceof Error ? lastError.message : String(lastError)}`);
|
|
31
|
+
}
|
|
32
|
+
export function listCompletionPresetIds() {
|
|
33
|
+
return loadCompletionCatalog().presets.map((preset) => preset.preset_id);
|
|
34
|
+
}
|
|
35
|
+
export function getCompletionPreset(presetId) {
|
|
36
|
+
const preset = loadCompletionCatalog().presets.find((entry) => entry.preset_id === presetId);
|
|
37
|
+
if (!preset) {
|
|
38
|
+
throw new Error(`unknown completion preset: ${presetId}`);
|
|
39
|
+
}
|
|
40
|
+
return preset;
|
|
41
|
+
}
|
|
42
|
+
export function getCompletionPresetByTemplateId(templateId) {
|
|
43
|
+
const matches = loadCompletionCatalog().presets.filter((entry) => entry.harbor_template_id === templateId);
|
|
44
|
+
if (matches.length === 0) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
return (matches.find((entry) => entry.kind !== "vendor_pack") ??
|
|
48
|
+
matches.find((entry) => entry.kind === "archetype") ??
|
|
49
|
+
matches[0]);
|
|
50
|
+
}
|
|
51
|
+
export function listCompletionPresetsByTemplateId(templateId) {
|
|
52
|
+
return loadCompletionCatalog().presets.filter((entry) => entry.harbor_template_id === templateId);
|
|
53
|
+
}
|
|
54
|
+
export function jsonLiteral(value, indent = 2) {
|
|
55
|
+
return JSON.stringify(value, null, indent);
|
|
56
|
+
}
|
|
57
|
+
export function catalogPathForTests() {
|
|
58
|
+
return join(MODULE_DIR, "../completion-presets/catalog.json");
|
|
59
|
+
}
|
|
60
|
+
export function catalogFileUrl() {
|
|
61
|
+
return pathToFileURL(catalogPathForTests()).href;
|
|
62
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BLAKE3 digests for completion preset vendor_contract schema pinning.
|
|
3
|
+
* Matches `paybond-evidence::json_value_digest` and Harbor signing digests.
|
|
4
|
+
*/
|
|
5
|
+
import type { CompletionPreset } from "./completion-catalog.js";
|
|
6
|
+
export type VendorContract = {
|
|
7
|
+
provider: "stripe" | "x402" | "mcp" | "generic";
|
|
8
|
+
api_version: string;
|
|
9
|
+
contract_kind: "json_schema" | "openapi_fragment" | "mapper_version";
|
|
10
|
+
schema_digest_hex: string;
|
|
11
|
+
canonical_schema_digest_hex: string;
|
|
12
|
+
quality_fields: string[];
|
|
13
|
+
supersedes?: string;
|
|
14
|
+
migration_notes?: string;
|
|
15
|
+
};
|
|
16
|
+
export type VendorContractDigests = {
|
|
17
|
+
schema_digest_hex: string;
|
|
18
|
+
canonical_schema_digest_hex: string;
|
|
19
|
+
};
|
|
20
|
+
/** Hex-encode a 32-byte BLAKE3 digest. */
|
|
21
|
+
export declare function digestToHex(digest: Uint8Array): string;
|
|
22
|
+
/** BLAKE3 hex digest of JCS-canonical JSON for a completion evidence schema object. */
|
|
23
|
+
export declare function completionSchemaDigestHex(schema: Record<string, unknown>): string;
|
|
24
|
+
/** Compute vendor and canonical schema digests for a vendor_pack preset. */
|
|
25
|
+
export declare function computeVendorContractDigests(preset: {
|
|
26
|
+
vendor_evidence_schema: Record<string, unknown>;
|
|
27
|
+
evidence_schema: Record<string, unknown>;
|
|
28
|
+
}): VendorContractDigests;
|
|
29
|
+
/**
|
|
30
|
+
* Assert catalog-declared vendor_contract digests and quality_fields match computed values.
|
|
31
|
+
* @throws when a vendor_pack contract is missing, stale, or references unknown quality fields.
|
|
32
|
+
*/
|
|
33
|
+
export declare function verifyVendorContract(preset: CompletionPreset): void;
|
|
34
|
+
/** Verify all vendor_pack presets in a catalog document. */
|
|
35
|
+
export declare function verifyCatalogVendorContracts(catalog: {
|
|
36
|
+
presets: CompletionPreset[];
|
|
37
|
+
}): void;
|