@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,49 @@
|
|
|
1
|
+
import { apiKeyEnvironment } from "./agent/paybond.js";
|
|
2
|
+
import { handleAgentSandboxSmoke } from "./commands/agent.js";
|
|
3
|
+
import { CliError } from "./types.js";
|
|
4
|
+
export const AGENT_MIDDLEWARE_SMOKE_NEXT = "paybond agent sandbox smoke --operation paid-tool --requested-spend-cents 100 --evidence-preset cost_and_completion --result-body '{\"status\":\"ok\",\"cost_cents\":100}' --format json";
|
|
5
|
+
/** Run sandbox middleware smoke as a doctor --agent check (uses ctx.fetch / project cwd). */
|
|
6
|
+
export async function runAgentMiddlewareDoctorCheck(ctx, apiKey) {
|
|
7
|
+
if (!apiKey) {
|
|
8
|
+
return {
|
|
9
|
+
name: "agent_middleware_smoke",
|
|
10
|
+
ok: false,
|
|
11
|
+
message: "skipped (missing API key)",
|
|
12
|
+
details: { next_command: AGENT_MIDDLEWARE_SMOKE_NEXT },
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
if (apiKeyEnvironment(apiKey) === "live") {
|
|
16
|
+
return {
|
|
17
|
+
name: "agent_middleware_smoke",
|
|
18
|
+
ok: true,
|
|
19
|
+
message: "skipped (live API key; smoke uses sandbox guardrails bootstrap)",
|
|
20
|
+
details: { next_command: AGENT_MIDDLEWARE_SMOKE_NEXT },
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
await handleAgentSandboxSmoke(ctx, [
|
|
25
|
+
"--operation",
|
|
26
|
+
"paid-tool",
|
|
27
|
+
"--requested-spend-cents",
|
|
28
|
+
"100",
|
|
29
|
+
"--evidence-preset",
|
|
30
|
+
"cost_and_completion",
|
|
31
|
+
"--result-body",
|
|
32
|
+
'{"status":"ok","cost_cents":100}',
|
|
33
|
+
]);
|
|
34
|
+
return {
|
|
35
|
+
name: "agent_middleware_smoke",
|
|
36
|
+
ok: true,
|
|
37
|
+
message: "bind, authorize, execute, and auto-evidence succeeded",
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
const message = err instanceof CliError ? err.message : err instanceof Error ? err.message : String(err);
|
|
42
|
+
return {
|
|
43
|
+
name: "agent_middleware_smoke",
|
|
44
|
+
ok: false,
|
|
45
|
+
message,
|
|
46
|
+
details: { next_command: AGENT_MIDDLEWARE_SMOKE_NEXT },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type DoctorCheck = {
|
|
2
|
+
name: string;
|
|
3
|
+
ok: boolean;
|
|
4
|
+
message: string;
|
|
5
|
+
details?: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
export declare function packageVersion(): string;
|
|
8
|
+
export declare function encodeMcpMessage(payload: Record<string, unknown>): Buffer;
|
|
9
|
+
export declare function runAgentMcpChecks(input: {
|
|
10
|
+
envFile: string;
|
|
11
|
+
cwd: string;
|
|
12
|
+
host?: string;
|
|
13
|
+
serverCommand?: string[];
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
}): Promise<DoctorCheck[]>;
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { access } from "node:fs/promises";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { defaultMcpInstallFormat, defaultMcpServerCommand, parseMcpInstallHost, planMcpInstall, } from "./mcp-install.js";
|
|
6
|
+
import { validateMcpToolSchema } from "./mcp-policy.js";
|
|
7
|
+
import { validateMcpHostConfig } from "./mcp-verify-config.js";
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const packageJson = require("../../package.json");
|
|
10
|
+
export function packageVersion() {
|
|
11
|
+
return packageJson.version;
|
|
12
|
+
}
|
|
13
|
+
export function encodeMcpMessage(payload) {
|
|
14
|
+
const body = JSON.stringify(payload);
|
|
15
|
+
return Buffer.from(`Content-Length: ${Buffer.byteLength(body, "utf8")}\r\n\r\n${body}`, "utf8");
|
|
16
|
+
}
|
|
17
|
+
function consumeMcpMessages(raw) {
|
|
18
|
+
const messages = [];
|
|
19
|
+
let offset = 0;
|
|
20
|
+
while (true) {
|
|
21
|
+
const headerEnd = raw.indexOf("\r\n\r\n", offset);
|
|
22
|
+
if (headerEnd < 0) {
|
|
23
|
+
return { messages, remainder: raw.subarray(offset) };
|
|
24
|
+
}
|
|
25
|
+
const headerText = raw.subarray(offset, headerEnd).toString("ascii");
|
|
26
|
+
const contentLength = Number.parseInt(headerText
|
|
27
|
+
.split("\r\n")
|
|
28
|
+
.find((line) => line.toLowerCase().startsWith("content-length:"))
|
|
29
|
+
?.split(":", 2)[1]
|
|
30
|
+
?.trim() ?? "", 10);
|
|
31
|
+
if (!Number.isFinite(contentLength) || contentLength <= 0) {
|
|
32
|
+
throw new Error("MCP response missing Content-Length");
|
|
33
|
+
}
|
|
34
|
+
const bodyStart = headerEnd + 4;
|
|
35
|
+
const bodyEnd = bodyStart + contentLength;
|
|
36
|
+
if (raw.length < bodyEnd) {
|
|
37
|
+
return { messages, remainder: raw.subarray(offset) };
|
|
38
|
+
}
|
|
39
|
+
const body = raw.subarray(bodyStart, bodyEnd).toString("utf8");
|
|
40
|
+
const parsed = JSON.parse(body);
|
|
41
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
42
|
+
throw new Error("MCP response was not a JSON object");
|
|
43
|
+
}
|
|
44
|
+
messages.push(parsed);
|
|
45
|
+
offset = bodyEnd;
|
|
46
|
+
if (offset >= raw.length) {
|
|
47
|
+
return { messages, remainder: Buffer.alloc(0) };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function readMcpMessage(stream, deadlineMs, rawBuffer) {
|
|
52
|
+
const started = Date.now();
|
|
53
|
+
while (true) {
|
|
54
|
+
const joined = Buffer.concat(rawBuffer);
|
|
55
|
+
const { messages, remainder } = consumeMcpMessages(joined);
|
|
56
|
+
rawBuffer.length = 0;
|
|
57
|
+
if (remainder.length > 0) {
|
|
58
|
+
rawBuffer.push(remainder);
|
|
59
|
+
}
|
|
60
|
+
if (messages[0]) {
|
|
61
|
+
return messages[0];
|
|
62
|
+
}
|
|
63
|
+
if (Date.now() - started > deadlineMs) {
|
|
64
|
+
throw new Error("timed out waiting for MCP response");
|
|
65
|
+
}
|
|
66
|
+
const chunk = await new Promise((resolve, reject) => {
|
|
67
|
+
const onData = (data) => {
|
|
68
|
+
cleanup();
|
|
69
|
+
resolve(data);
|
|
70
|
+
};
|
|
71
|
+
const onEnd = () => {
|
|
72
|
+
cleanup();
|
|
73
|
+
resolve(null);
|
|
74
|
+
};
|
|
75
|
+
const onError = (err) => {
|
|
76
|
+
cleanup();
|
|
77
|
+
reject(err);
|
|
78
|
+
};
|
|
79
|
+
const cleanup = () => {
|
|
80
|
+
stream.off("data", onData);
|
|
81
|
+
stream.off("end", onEnd);
|
|
82
|
+
stream.off("error", onError);
|
|
83
|
+
};
|
|
84
|
+
stream.once("data", onData);
|
|
85
|
+
stream.once("end", onEnd);
|
|
86
|
+
stream.once("error", onError);
|
|
87
|
+
});
|
|
88
|
+
if (!chunk) {
|
|
89
|
+
throw new Error("MCP server closed stdout before responding");
|
|
90
|
+
}
|
|
91
|
+
rawBuffer.push(chunk);
|
|
92
|
+
if (Buffer.concat(rawBuffer).length > 1_048_576) {
|
|
93
|
+
throw new Error("MCP stdout buffer too large");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function stdoutIsMcpPure(rawStdout) {
|
|
98
|
+
if (rawStdout.length === 0) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const { messages, remainder } = consumeMcpMessages(rawStdout);
|
|
103
|
+
if (remainder.toString("utf8").trim()) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return messages.length > 0;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export async function runAgentMcpChecks(input) {
|
|
113
|
+
const checks = [];
|
|
114
|
+
const installHost = parseMcpInstallHost(input.host ?? "generic");
|
|
115
|
+
const format = defaultMcpInstallFormat(installHost);
|
|
116
|
+
const plan = planMcpInstall({
|
|
117
|
+
host: installHost,
|
|
118
|
+
scope: "local",
|
|
119
|
+
format,
|
|
120
|
+
envFile: input.envFile,
|
|
121
|
+
cwd: input.cwd,
|
|
122
|
+
home: process.env.HOME ?? process.env.USERPROFILE ?? input.cwd,
|
|
123
|
+
serverCommand: input.serverCommand ?? defaultMcpServerCommand(),
|
|
124
|
+
});
|
|
125
|
+
const configResult = validateMcpHostConfig({
|
|
126
|
+
host: installHost,
|
|
127
|
+
format,
|
|
128
|
+
payload: plan.payload,
|
|
129
|
+
cwd: input.cwd,
|
|
130
|
+
expectedEnvFile: input.envFile,
|
|
131
|
+
});
|
|
132
|
+
checks.push({
|
|
133
|
+
name: "mcp_host_config",
|
|
134
|
+
ok: configResult.ok,
|
|
135
|
+
message: configResult.message,
|
|
136
|
+
details: { host: installHost, format },
|
|
137
|
+
});
|
|
138
|
+
const envPath = path.isAbsolute(input.envFile)
|
|
139
|
+
? path.resolve(input.envFile)
|
|
140
|
+
: path.resolve(input.cwd, input.envFile);
|
|
141
|
+
let envOk = false;
|
|
142
|
+
try {
|
|
143
|
+
await access(envPath);
|
|
144
|
+
envOk = true;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
envOk = false;
|
|
148
|
+
}
|
|
149
|
+
checks.push({
|
|
150
|
+
name: "mcp_env_resolution",
|
|
151
|
+
ok: envOk,
|
|
152
|
+
message: envOk ? envPath : `env file not found: ${envPath}`,
|
|
153
|
+
details: { env_file: input.envFile, resolved: envPath },
|
|
154
|
+
});
|
|
155
|
+
if (!envOk) {
|
|
156
|
+
checks.push({ name: "mcp_launch", ok: false, message: "skipped (env file missing)" }, { name: "mcp_initialize", ok: false, message: "skipped (env file missing)" }, { name: "mcp_tools_list", ok: false, message: "skipped (env file missing)" }, { name: "mcp_tool_schemas", ok: false, message: "skipped (env file missing)" }, { name: "mcp_stdout_purity", ok: false, message: "skipped (env file missing)" });
|
|
157
|
+
return checks;
|
|
158
|
+
}
|
|
159
|
+
const command = input.serverCommand ?? defaultMcpServerCommand();
|
|
160
|
+
const env = {
|
|
161
|
+
...process.env,
|
|
162
|
+
PAYBOND_ENV_FILE: envPath,
|
|
163
|
+
};
|
|
164
|
+
delete env.PAYBOND_API_KEY;
|
|
165
|
+
return await new Promise((resolve) => {
|
|
166
|
+
let child;
|
|
167
|
+
try {
|
|
168
|
+
child = spawn(command[0], command.slice(1), {
|
|
169
|
+
cwd: input.cwd,
|
|
170
|
+
env,
|
|
171
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
resolve([
|
|
176
|
+
{ name: "mcp_launch", ok: false, message: `unable to launch MCP server: ${err instanceof Error ? err.message : String(err)}` },
|
|
177
|
+
{ name: "mcp_initialize", ok: false, message: "skipped (launch failed)" },
|
|
178
|
+
{ name: "mcp_tools_list", ok: false, message: "skipped (launch failed)" },
|
|
179
|
+
{ name: "mcp_tool_schemas", ok: false, message: "skipped (probe failed)" },
|
|
180
|
+
{ name: "mcp_stdout_purity", ok: false, message: "skipped (launch failed)" },
|
|
181
|
+
]);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const timeoutMs = input.timeoutMs ?? 10_000;
|
|
185
|
+
const stderrChunks = [];
|
|
186
|
+
const rawStdout = [];
|
|
187
|
+
child.stderr?.on("data", (chunk) => {
|
|
188
|
+
stderrChunks.push(chunk);
|
|
189
|
+
});
|
|
190
|
+
child.stdout?.on("data", (chunk) => {
|
|
191
|
+
rawStdout.push(chunk);
|
|
192
|
+
});
|
|
193
|
+
void (async () => {
|
|
194
|
+
try {
|
|
195
|
+
if (!child.stdin || !child.stdout) {
|
|
196
|
+
throw new Error("MCP server stdio pipes unavailable");
|
|
197
|
+
}
|
|
198
|
+
checks.push({
|
|
199
|
+
name: "mcp_launch",
|
|
200
|
+
ok: true,
|
|
201
|
+
message: `launched ${command.join(" ")}`,
|
|
202
|
+
});
|
|
203
|
+
child.stdin.write(encodeMcpMessage({
|
|
204
|
+
jsonrpc: "2.0",
|
|
205
|
+
id: 1,
|
|
206
|
+
method: "initialize",
|
|
207
|
+
params: {
|
|
208
|
+
protocolVersion: "2025-11-25",
|
|
209
|
+
capabilities: {},
|
|
210
|
+
clientInfo: { name: "paybond-doctor", version: packageVersion() },
|
|
211
|
+
},
|
|
212
|
+
}));
|
|
213
|
+
const initResponse = await readMcpMessage(child.stdout, timeoutMs, rawStdout);
|
|
214
|
+
if (initResponse.error) {
|
|
215
|
+
checks.push({
|
|
216
|
+
name: "mcp_initialize",
|
|
217
|
+
ok: false,
|
|
218
|
+
message: "MCP initialize failed",
|
|
219
|
+
details: { error: initResponse.error },
|
|
220
|
+
});
|
|
221
|
+
checks.push({ name: "mcp_tools_list", ok: false, message: "skipped (initialize failed)" }, { name: "mcp_tool_schemas", ok: false, message: "skipped (initialize failed)" }, { name: "mcp_stdout_purity", ok: false, message: "skipped (initialize failed)" });
|
|
222
|
+
resolve(checks);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const serverInfo = initResponse.result?.serverInfo;
|
|
226
|
+
const initOk = Boolean(serverInfo && typeof serverInfo === "object");
|
|
227
|
+
checks.push({
|
|
228
|
+
name: "mcp_initialize",
|
|
229
|
+
ok: initOk,
|
|
230
|
+
message: initOk ? "MCP initialize succeeded" : "MCP initialize response missing serverInfo",
|
|
231
|
+
details: initOk
|
|
232
|
+
? {
|
|
233
|
+
server_name: serverInfo.name,
|
|
234
|
+
server_version: serverInfo.version,
|
|
235
|
+
}
|
|
236
|
+
: undefined,
|
|
237
|
+
});
|
|
238
|
+
if (!initOk) {
|
|
239
|
+
checks.push({ name: "mcp_tools_list", ok: false, message: "skipped (initialize failed)" }, { name: "mcp_tool_schemas", ok: false, message: "skipped (initialize failed)" }, { name: "mcp_stdout_purity", ok: false, message: "skipped (initialize failed)" });
|
|
240
|
+
resolve(checks);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
child.stdin.write(encodeMcpMessage({
|
|
244
|
+
jsonrpc: "2.0",
|
|
245
|
+
method: "notifications/initialized",
|
|
246
|
+
}));
|
|
247
|
+
child.stdin.write(encodeMcpMessage({
|
|
248
|
+
jsonrpc: "2.0",
|
|
249
|
+
id: 2,
|
|
250
|
+
method: "tools/list",
|
|
251
|
+
params: {},
|
|
252
|
+
}));
|
|
253
|
+
const toolsResponse = await readMcpMessage(child.stdout, timeoutMs, rawStdout);
|
|
254
|
+
if (toolsResponse.error) {
|
|
255
|
+
checks.push({
|
|
256
|
+
name: "mcp_tools_list",
|
|
257
|
+
ok: false,
|
|
258
|
+
message: "MCP tools/list failed",
|
|
259
|
+
details: { error: toolsResponse.error },
|
|
260
|
+
});
|
|
261
|
+
checks.push({ name: "mcp_tool_schemas", ok: false, message: "skipped (tools/list failed)" }, { name: "mcp_stdout_purity", ok: false, message: "skipped (tools/list failed)" });
|
|
262
|
+
resolve(checks);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const tools = toolsResponse.result?.tools;
|
|
266
|
+
const toolCount = Array.isArray(tools) ? tools.length : 0;
|
|
267
|
+
checks.push({
|
|
268
|
+
name: "mcp_tools_list",
|
|
269
|
+
ok: toolCount > 0,
|
|
270
|
+
message: `${toolCount} tools listed`,
|
|
271
|
+
details: { tool_count: toolCount },
|
|
272
|
+
});
|
|
273
|
+
const schemaErrors = [];
|
|
274
|
+
if (Array.isArray(tools)) {
|
|
275
|
+
for (const tool of tools) {
|
|
276
|
+
if (tool && typeof tool === "object" && !Array.isArray(tool)) {
|
|
277
|
+
schemaErrors.push(...validateMcpToolSchema(tool));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
checks.push({
|
|
282
|
+
name: "mcp_tool_schemas",
|
|
283
|
+
ok: toolCount > 0 && schemaErrors.length === 0,
|
|
284
|
+
message: schemaErrors.length === 0 ? "all listed tools have valid schemas" : schemaErrors[0],
|
|
285
|
+
details: { invalid_count: schemaErrors.length, errors: schemaErrors.slice(0, 5) },
|
|
286
|
+
});
|
|
287
|
+
const pure = stdoutIsMcpPure(Buffer.concat(rawStdout));
|
|
288
|
+
checks.push({
|
|
289
|
+
name: "mcp_stdout_purity",
|
|
290
|
+
ok: pure,
|
|
291
|
+
message: pure ? "stdout contains only MCP-framed JSON-RPC" : "stdout contains non-MCP material",
|
|
292
|
+
});
|
|
293
|
+
resolve(checks);
|
|
294
|
+
}
|
|
295
|
+
catch (err) {
|
|
296
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf8").trim();
|
|
297
|
+
const suffix = stderr ? `: ${stderr}` : "";
|
|
298
|
+
checks.push({
|
|
299
|
+
name: "mcp_initialize",
|
|
300
|
+
ok: false,
|
|
301
|
+
message: `MCP stdio probe failed: ${err instanceof Error ? err.message : String(err)}${suffix}`,
|
|
302
|
+
});
|
|
303
|
+
checks.push({ name: "mcp_tools_list", ok: false, message: "skipped (probe failed)" }, { name: "mcp_tool_schemas", ok: false, message: "skipped (probe failed)" }, { name: "mcp_stdout_purity", ok: false, message: "skipped (probe failed)" });
|
|
304
|
+
resolve(checks);
|
|
305
|
+
}
|
|
306
|
+
finally {
|
|
307
|
+
child.kill("SIGTERM");
|
|
308
|
+
}
|
|
309
|
+
})();
|
|
310
|
+
});
|
|
311
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CliEnvelope, CliErrorShape, CommandResult, GlobalOptions, Writable } from "./types.js";
|
|
2
|
+
export declare function mergeWarnings(result: CommandResult, extra?: string[]): string[];
|
|
3
|
+
export declare function prepareCommandOutput(command: string, globals: GlobalOptions, result: CommandResult): {
|
|
4
|
+
data: unknown;
|
|
5
|
+
warnings: string[];
|
|
6
|
+
automationPlain: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare function successEnvelope<T>(command: string, globals: GlobalOptions, result: CommandResult<T> | {
|
|
9
|
+
data: T;
|
|
10
|
+
warnings?: string[];
|
|
11
|
+
}): CliEnvelope<T>;
|
|
12
|
+
export declare function failureEnvelope(command: string, globals: GlobalOptions, error: CliErrorShape): CliEnvelope<null>;
|
|
13
|
+
export declare function writeEnvelope<T>(stdout: Writable, envelope: CliEnvelope<T>): void;
|
|
14
|
+
export declare function writeTableLines(stdout: Writable, lines: string[]): void;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { applyAutomationTransforms } from "./automation.js";
|
|
2
|
+
export function mergeWarnings(result, extra = []) {
|
|
3
|
+
const merged = [...(result.warnings ?? []), ...extra];
|
|
4
|
+
return [...new Set(merged)];
|
|
5
|
+
}
|
|
6
|
+
export function prepareCommandOutput(command, globals, result) {
|
|
7
|
+
const warnings = mergeWarnings(result);
|
|
8
|
+
const automationRequested = Boolean(globals.jsonFields || globals.jqExpr);
|
|
9
|
+
const data = applyAutomationTransforms(command, result.data, {
|
|
10
|
+
jsonFields: globals.jsonFields,
|
|
11
|
+
jqExpr: globals.jqExpr,
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
data,
|
|
15
|
+
warnings,
|
|
16
|
+
automationPlain: automationRequested && globals.format !== "json",
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export function successEnvelope(command, globals, result) {
|
|
20
|
+
return {
|
|
21
|
+
ok: true,
|
|
22
|
+
command,
|
|
23
|
+
data: result.data,
|
|
24
|
+
warnings: result.warnings ?? [],
|
|
25
|
+
request_id: globals.requestId,
|
|
26
|
+
error: null,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function failureEnvelope(command, globals, error) {
|
|
30
|
+
return {
|
|
31
|
+
ok: false,
|
|
32
|
+
command,
|
|
33
|
+
data: null,
|
|
34
|
+
warnings: [],
|
|
35
|
+
request_id: globals.requestId,
|
|
36
|
+
error,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function writeEnvelope(stdout, envelope) {
|
|
40
|
+
stdout.write(`${JSON.stringify(envelope, null, 2)}\n`);
|
|
41
|
+
}
|
|
42
|
+
export function writeTableLines(stdout, lines) {
|
|
43
|
+
for (const line of lines) {
|
|
44
|
+
stdout.write(`${line}\n`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type GlobalOptions } from "./types.js";
|
|
2
|
+
export declare const DEFAULT_GATEWAY = "https://api.paybond.ai";
|
|
3
|
+
export declare const DEFAULT_ENV_FILE = ".env.local";
|
|
4
|
+
export declare const TENANT_OVERRIDE_FLAGS: readonly ["--tenant-id", "--tenant", "--tenant_id"];
|
|
5
|
+
export declare function rejectsTenantOverrideFlag(arg: string): boolean;
|
|
6
|
+
export declare function validateCliGateway(url: string): string;
|
|
7
|
+
export declare function parseRequiredNonNegativeInt(raw: string, field: string): number;
|
|
8
|
+
export declare function parseOptionalNonNegativeInt(raw: string | undefined, field: string): number;
|
|
9
|
+
export declare function defaultGlobalOptions(): GlobalOptions;
|
|
10
|
+
export type ParsedCliArgv = {
|
|
11
|
+
globals: GlobalOptions;
|
|
12
|
+
command: string[];
|
|
13
|
+
};
|
|
14
|
+
export declare function parseCliArgv(argv: string[]): ParsedCliArgv;
|
|
15
|
+
export declare function consumeFlag(argv: string[], flag: string): {
|
|
16
|
+
present: boolean;
|
|
17
|
+
value?: string;
|
|
18
|
+
rest: string[];
|
|
19
|
+
};
|
|
20
|
+
export declare function consumeBooleanFlag(argv: string[], flag: string): {
|
|
21
|
+
present: boolean;
|
|
22
|
+
rest: string[];
|
|
23
|
+
};
|