@zackbart/connecta 0.34.1 → 0.36.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/CHANGELOG.md +418 -0
- package/README.md +65 -105
- package/SECURITY.md +3 -2
- package/bin/connecta.mjs +41 -16
- package/bin/version.mjs +1 -1
- package/dist/access-tokens.d.ts +2 -1
- package/dist/access-tokens.js +66 -30
- package/dist/activity.d.ts +1 -1
- package/dist/activity.js +2 -0
- package/dist/agent-config.d.ts +23 -0
- package/dist/agent-config.js +59 -0
- package/dist/agent-description.js +16 -0
- package/dist/agent-identity.js +4 -4
- package/dist/agent-observation.js +39 -0
- package/dist/auth/clerk-sdk/client.d.ts +2 -0
- package/dist/auth/clerk-sdk/generated.js +554 -563
- package/dist/auth/clerk-transport.js +70 -3
- package/dist/auth/clerk.d.ts +13 -0
- package/dist/auth/clerk.js +653 -246
- package/dist/auth/cloudflare-access.js +46 -42
- package/dist/auth/downstream-client-metadata.js +2 -2
- package/dist/auth/downstream-oauth.js +2044 -1161
- package/dist/auth/downstream-revocation.js +88 -88
- package/dist/auth/native-call.js +20 -0
- package/dist/auth/native.js +184 -0
- package/dist/auth/oauth-start-reset.js +11 -5
- package/dist/auth/oauth-token-response.js +121 -102
- package/dist/auth/oauth-v2-migration.js +97 -78
- package/dist/auth/renewable-grant.js +10 -0
- package/dist/auth/static-oauth.js +751 -281
- package/dist/auth/vercel-agent.js +266 -0
- package/dist/auth-admission.js +204 -0
- package/dist/auth-elicitation.js +350 -241
- package/dist/authorization-handoff.js +164 -90
- package/dist/call-admission-context.js +3 -10
- package/dist/call-admission.js +2 -0
- package/dist/call-classification.js +9 -0
- package/dist/call-recovery.js +32 -13
- package/dist/canonical-json.js +8 -0
- package/dist/catalog-cache.js +369 -213
- package/dist/catalog-service.js +659 -530
- package/dist/catalog.js +5 -1
- package/dist/concurrency.js +0 -25
- package/dist/config-defaults.d.ts +1 -0
- package/dist/config-defaults.js +1 -0
- package/dist/config-schema.d.ts +3 -1
- package/dist/config-schema.js +13 -3
- package/dist/config.d.ts +40 -6
- package/dist/config.js +40 -26
- package/dist/connector-caller.d.ts +4 -0
- package/dist/connector-caller.js +17 -4
- package/dist/connectors/api-connector.d.ts +29 -7
- package/dist/connectors/api-connector.js +145 -57
- package/dist/connectors/guarded-fetch.d.ts +51 -17
- package/dist/connectors/guarded-fetch.js +215 -121
- package/dist/connectors/negotiation-cache.js +20 -10
- package/dist/connectors/remote-mcp.d.ts +10 -30
- package/dist/connectors/remote-mcp.js +955 -563
- package/dist/d1.js +10 -243
- package/dist/derived-context.js +5 -0
- package/dist/describe-config.d.ts +3 -1
- package/dist/describe-config.js +2 -0
- package/dist/downstream-input.js +347 -260
- package/dist/errors.d.ts +87 -6
- package/dist/errors.js +114 -4
- package/dist/execute.js +87 -50
- package/dist/executor-admission.js +3 -0
- package/dist/executors/quickjs.js +163 -112
- package/dist/guarded-transport.js +50 -0
- package/dist/guest-runtime.js +1 -1
- package/dist/http/client.js +439 -0
- package/dist/http/errors.js +558 -0
- package/dist/http/fields.js +49 -0
- package/dist/http/hatch-paging.js +318 -0
- package/dist/http/hatch.js +1279 -0
- package/dist/http/json-schema.js +267 -0
- package/dist/http/node-transport.js +241 -0
- package/dist/http/oauth.js +162 -0
- package/dist/http/paging.js +227 -0
- package/dist/http/provider.js +221 -0
- package/dist/http/safety.js +82 -0
- package/dist/http/services.js +79 -0
- package/dist/http/tools.js +379 -0
- package/dist/http/vendor-index.js +138 -0
- package/dist/http/vendor.js +448 -0
- package/dist/http/write-request.js +66 -0
- package/dist/http-policy.d.ts +11 -0
- package/dist/http-policy.js +45 -0
- package/dist/inbound-credential.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -0
- package/dist/invocation-auth.js +30 -19
- package/dist/invocation.js +218 -85
- package/dist/mcp-result.js +0 -4
- package/dist/membership.d.ts +4 -0
- package/dist/meta-output.js +1 -1
- package/dist/meta-tools.js +531 -406
- package/dist/native-recovery.js +52 -0
- package/dist/native-tools.js +382 -0
- package/dist/node.d.ts +4 -3
- package/dist/node.js +45 -8
- package/dist/oauth-handoff.js +177 -104
- package/dist/oauth-partition.js +6 -20
- package/dist/oauth-sealing.js +6 -7
- package/dist/operation-vocabulary.js +101 -0
- package/dist/operator-record.d.ts +2 -2
- package/dist/operator-record.js +17 -4
- package/dist/operator-ui/contract.d.ts +8 -3
- package/dist/operator-ui/generated.js +4 -4
- package/dist/operator-ui/model.d.ts +2 -3
- package/dist/program-writes.js +47 -26
- package/dist/provider-call-facts.d.ts +115 -0
- package/dist/provider-call-facts.js +182 -0
- package/dist/provider-call.d.ts +112 -0
- package/dist/provider-call.js +271 -0
- package/dist/provider.d.ts +65 -31
- package/dist/provider.js +116 -39
- package/dist/providers/_shared/google/hatch.js +91 -0
- package/dist/providers/_shared/google/kit.js +427 -0
- package/dist/providers/_shared/google/result-size.js +15 -2
- package/dist/providers/_shared/google/service-account.d.ts +2 -1
- package/dist/providers/_shared/google/service-account.js +8 -4
- package/dist/providers/_shared/google/workspace.d.ts +6 -210
- package/dist/providers/_shared/google/workspace.js +6 -425
- package/dist/providers/_shared/rest/compact-index.js +86 -0
- package/dist/providers/_shared/rest/kit.js +146 -0
- package/dist/providers/_shared/rest/operation-index.js +230 -14
- package/dist/providers/_shared/rest/response-media.js +11 -0
- package/dist/providers/_shared/rest/value-safety.js +353 -195
- package/dist/providers/_shared/sensitive-fields.js +27 -0
- package/dist/providers/breeze/api.js +584 -0
- package/dist/providers/breeze/index.d.ts +1 -3
- package/dist/providers/breeze/index.js +67 -1420
- package/dist/providers/breeze/openapi.generated.js +60 -0
- package/dist/providers/breeze/skill.generated.js +2 -6
- package/dist/providers/breeze/tools.js +696 -0
- package/dist/providers/ccb/api.js +496 -0
- package/dist/providers/ccb/index.d.ts +15 -37
- package/dist/providers/ccb/index.js +77 -1702
- package/dist/providers/ccb/lib/constants.d.ts +34 -0
- package/dist/providers/ccb/lib/constants.js +74 -0
- package/dist/providers/ccb/lib/guide.js +9 -0
- package/dist/providers/ccb/lib/verdicts.js +387 -0
- package/dist/providers/ccb/openapi.generated.js +397 -0
- package/dist/providers/ccb/safety.js +295 -0
- package/dist/providers/ccb/skill.generated.js +2 -6
- package/dist/providers/ccb/tools.js +853 -0
- package/dist/providers/cloudflare/api.js +1066 -0
- package/dist/providers/cloudflare/index.d.ts +5 -22
- package/dist/providers/cloudflare/index.js +79 -197
- package/dist/providers/cloudflare/lib/config.d.ts +16 -0
- package/dist/providers/cloudflare/lib/config.js +2 -0
- package/dist/providers/cloudflare/lib/discovery.js +29 -0
- package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
- package/dist/providers/cloudflare/lib/hatch.js +103 -0
- package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
- package/dist/providers/cloudflare/lib/response-media.js +75 -0
- package/dist/providers/cloudflare/openapi.generated.js +4 -3
- package/dist/providers/cloudflare/{value-safety.js → safety.js} +487 -0
- package/dist/providers/cloudflare/skill.generated.js +2 -10
- package/dist/providers/cloudflare/tools.js +360 -0
- package/dist/providers/docs/api.js +51 -0
- package/dist/providers/docs/index.d.ts +1 -12
- package/dist/providers/docs/index.js +53 -1165
- package/dist/providers/docs/lib/constants.d.ts +18 -0
- package/dist/providers/docs/lib/constants.js +18 -0
- package/dist/providers/docs/lib/discovery.js +26 -0
- package/dist/providers/docs/lib/requests.js +48 -0
- package/dist/providers/docs/lib/schemas.js +168 -0
- package/dist/providers/docs/openapi.generated.js +16 -0
- package/dist/providers/docs/safety.js +54 -0
- package/dist/providers/docs/skill.generated.js +2 -6
- package/dist/providers/docs/tools.js +801 -0
- package/dist/providers/drive/api.js +177 -0
- package/dist/providers/drive/index.d.ts +1 -12
- package/dist/providers/drive/index.js +38 -1448
- package/dist/providers/drive/lib/constants.d.ts +6 -0
- package/dist/providers/drive/lib/constants.js +6 -0
- package/dist/providers/drive/lib/contracts.js +532 -0
- package/dist/providers/drive/lib/hatch.js +197 -0
- package/dist/providers/drive/openapi.generated.js +77 -0
- package/dist/providers/drive/safety.js +90 -0
- package/dist/providers/drive/skill.generated.js +2 -6
- package/dist/providers/drive/tools.js +1290 -0
- package/dist/providers/forms/api.js +71 -0
- package/dist/providers/forms/index.d.ts +1 -12
- package/dist/providers/forms/index.js +49 -1145
- package/dist/providers/forms/lib/constants.d.ts +14 -0
- package/dist/providers/forms/lib/constants.js +19 -0
- package/dist/providers/forms/lib/hatch.js +72 -0
- package/dist/providers/forms/openapi.generated.js +23 -0
- package/dist/providers/forms/safety.js +34 -0
- package/dist/providers/forms/skill.generated.js +2 -8
- package/dist/providers/forms/tools.js +1023 -0
- package/dist/providers/github/api.js +150 -0
- package/dist/providers/github/index.d.ts +4 -5
- package/dist/providers/github/index.js +30 -87
- package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
- package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
- package/dist/providers/github/lib/discovery.js +132 -0
- package/dist/providers/github/lib/operations.js +58 -0
- package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
- package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
- package/dist/providers/github/openapi.generated.js +1216 -0
- package/dist/providers/github/safety.js +216 -0
- package/dist/providers/github/skill.generated.js +2 -5
- package/dist/providers/github/tools.js +506 -0
- package/dist/providers/gmail/api.js +114 -0
- package/dist/providers/gmail/index.d.ts +1 -12
- package/dist/providers/gmail/index.js +73 -1621
- package/dist/providers/gmail/lib/constants.d.ts +13 -0
- package/dist/providers/gmail/lib/constants.js +16 -0
- package/dist/providers/gmail/lib/index.js +173 -0
- package/dist/providers/gmail/lib/schemas.js +176 -0
- package/dist/providers/gmail/lib/threading.js +120 -0
- package/dist/providers/gmail/openapi.generated.js +92 -0
- package/dist/providers/gmail/safety.js +21 -0
- package/dist/providers/gmail/skill.generated.js +2 -6
- package/dist/providers/gmail/tools.js +1435 -0
- package/dist/providers/overflow/api.js +1008 -0
- package/dist/providers/overflow/index.d.ts +1 -17
- package/dist/providers/overflow/index.js +60 -1488
- package/dist/providers/overflow/skill.generated.js +2 -5
- package/dist/providers/overflow/tools.js +873 -0
- package/dist/providers/planning-center/api.js +467 -0
- package/dist/providers/planning-center/index.d.ts +4 -35
- package/dist/providers/planning-center/index.js +69 -2445
- package/dist/providers/planning-center/lib/constants.d.ts +58 -0
- package/dist/providers/planning-center/lib/constants.js +83 -0
- package/dist/providers/planning-center/lib/discovery.js +40 -0
- package/dist/providers/planning-center/lib/guide.js +39 -0
- package/dist/providers/planning-center/lib/json-api.js +83 -0
- package/dist/providers/planning-center/lib/verdicts.js +1758 -0
- package/dist/providers/planning-center/openapi.generated.js +1764 -0
- package/dist/providers/planning-center/safety.js +188 -0
- package/dist/providers/planning-center/skill.generated.js +2 -27
- package/dist/providers/planning-center/tools.js +1010 -0
- package/dist/providers/quickbooks/api.js +299 -0
- package/dist/providers/quickbooks/index.d.ts +13 -0
- package/dist/providers/quickbooks/index.js +93 -0
- package/dist/providers/quickbooks/lib/query.js +118 -0
- package/dist/providers/quickbooks/lib/writes.js +168 -0
- package/dist/providers/quickbooks/safety.js +222 -0
- package/dist/providers/quickbooks/skill.generated.js +5 -0
- package/dist/providers/quickbooks/tools.js +117 -0
- package/dist/providers/sheets/api.js +133 -0
- package/dist/providers/sheets/index.d.ts +4 -16
- package/dist/providers/sheets/index.js +61 -1172
- package/dist/providers/sheets/lib/constants.d.ts +14 -0
- package/dist/providers/sheets/lib/constants.js +14 -0
- package/dist/providers/sheets/lib/hatch.js +163 -0
- package/dist/providers/sheets/lib/requests.js +105 -0
- package/dist/providers/sheets/lib/schemas.js +138 -0
- package/dist/providers/sheets/openapi.generated.js +30 -0
- package/dist/providers/sheets/safety.js +27 -0
- package/dist/providers/sheets/skill.generated.js +2 -7
- package/dist/providers/sheets/tools.js +733 -0
- package/dist/providers/slides/api.js +147 -0
- package/dist/providers/slides/index.d.ts +2 -10
- package/dist/providers/slides/index.js +48 -2555
- package/dist/providers/slides/lib/constants.d.ts +11 -0
- package/dist/providers/slides/lib/constants.js +11 -0
- package/dist/providers/slides/lib/requests.js +60 -0
- package/dist/providers/slides/lib/schemas.js +565 -0
- package/dist/providers/slides/openapi.generated.js +18 -0
- package/dist/providers/slides/skill.generated.js +2 -6
- package/dist/providers/slides/tools.js +1968 -0
- package/dist/providers/stripe/api.js +401 -0
- package/dist/providers/stripe/index.d.ts +5 -27
- package/dist/providers/stripe/index.js +74 -210
- package/dist/providers/stripe/lib/config.d.ts +4 -0
- package/dist/providers/stripe/lib/config.js +2 -0
- package/dist/providers/stripe/openapi.generated.js +4 -3
- package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
- package/dist/providers/stripe/skill.generated.js +2 -11
- package/dist/providers/stripe/tools.js +77 -0
- package/dist/providers/tithely/api.js +531 -0
- package/dist/providers/tithely/index.d.ts +17 -0
- package/dist/providers/tithely/index.js +86 -965
- package/dist/providers/tithely/skill.generated.js +2 -5
- package/dist/providers/tithely/tools.js +426 -0
- package/dist/providers/vercel/api.js +551 -0
- package/dist/providers/vercel/index.d.ts +9 -25
- package/dist/providers/vercel/index.js +65 -260
- package/dist/providers/vercel/lib/config.d.ts +2 -0
- package/dist/providers/vercel/lib/config.js +2 -0
- package/dist/providers/vercel/lib/index.js +117 -0
- package/dist/providers/vercel/lib/logs.js +100 -0
- package/dist/providers/vercel/lib/pin.js +270 -0
- package/dist/providers/vercel/openapi.generated.js +10 -5
- package/dist/providers/vercel/{value-safety.js → safety.js} +247 -38
- package/dist/providers/vercel/skill.generated.js +2 -7
- package/dist/providers/vercel/tools.js +642 -0
- package/dist/redaction-identity.js +47 -0
- package/dist/redaction-marker.js +125 -0
- package/dist/registry.d.ts +21 -15
- package/dist/registry.js +409 -376
- package/dist/routes/access-tokens.js +1 -1
- package/dist/routes/actor-labels.js +1 -1
- package/dist/routes/connect.js +1 -1
- package/dist/routes/dispatch.js +103 -0
- package/dist/routes/mcp.js +170 -79
- package/dist/routes/oauth.js +6 -1
- package/dist/routes/operator.js +2 -2
- package/dist/routes/shared.d.ts +5 -4
- package/dist/routes/shared.js +244 -177
- package/dist/routes/skills.js +10 -8
- package/dist/routes/ui-config.js +27 -3
- package/dist/routes/ui-data.js +21 -20
- package/dist/routes/ui.js +1 -1
- package/dist/runtime/call-admission.js +0 -26
- package/dist/runtime/call-entry.js +30 -0
- package/dist/runtime/call.js +552 -0
- package/dist/runtime/connector-scope.js +7 -0
- package/dist/runtime/credential-probe.js +34 -0
- package/dist/runtime/executor.js +40 -0
- package/dist/runtime/native-storage.js +63 -0
- package/dist/runtime/registry.js +27 -0
- package/dist/runtime/request-scope.js +72 -0
- package/dist/runtime/run.js +15 -7
- package/dist/runtime/shared-read.js +34 -5
- package/dist/runtime/storage.js +34 -21
- package/dist/sent-secrets.d.ts +194 -37
- package/dist/sent-secrets.js +1743 -340
- package/dist/server.js +5 -56
- package/dist/skills.js +322 -223
- package/dist/sqlite.js +15 -14
- package/dist/storage/d1-copy.js +255 -0
- package/dist/storage/d1-driver.js +15 -0
- package/dist/storage/keys.js +28 -0
- package/dist/storage/sql-driver.js +88 -0
- package/dist/storage/sql-native.js +544 -0
- package/dist/storage/sql-schema.d.ts +6 -0
- package/dist/storage/sql-schema.js +15 -0
- package/dist/storage/sql.d.ts +14 -20
- package/dist/storage/sql.js +29 -535
- package/dist/timeout.js +0 -26
- package/dist/tool-safety.js +20 -10
- package/dist/types.d.ts +9 -109
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +0 -1
- package/dist/upward.js +3 -0
- package/dist/usage-guide.js +3 -1
- package/dist/validate.d.ts +4 -2
- package/dist/validate.js +86 -9
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker.js +312 -292
- package/dist/workspace-subject.js +5 -1
- package/dist/write-outcome.js +454 -34
- package/documentation/README.md +28 -7
- package/documentation/architecture.md +2409 -255
- package/documentation/auth.md +867 -114
- package/documentation/code-mode.md +49 -16
- package/documentation/deploying.md +164 -20
- package/documentation/hosted-mcp-migration.md +460 -0
- package/documentation/integrating.md +129 -144
- package/documentation/meta-tools.md +409 -32
- package/documentation/operating.md +27 -3
- package/documentation/operator-tests.md +3 -0
- package/documentation/operator-ui.md +84 -48
- package/documentation/provider-auth-migration.md +16 -63
- package/documentation/provider-migration-0.29.md +10 -5
- package/documentation/provider-migration-0.35.md +975 -0
- package/documentation/providers.md +1347 -0
- package/examples/worker/AGENTS.md +23 -9
- package/examples/worker/README.md +254 -135
- package/examples/worker/alchemy.run.ts +116 -0
- package/examples/worker/gitignore +10 -0
- package/examples/worker/src/connecta.config.ts +23 -21
- package/examples/worker/wrangler.jsonc +14 -5
- package/guides/connecting-agents.md +157 -0
- package/guides/how-it-works.md +156 -0
- package/guides/safety-and-trust.md +153 -0
- package/package.json +30 -50
- package/templates/node/.env.example +3 -0
- package/templates/node/README.md +22 -2
- package/templates/node/docker-compose.yml +1 -0
- package/templates/node/package.json +3 -2
- package/templates/node/src/connecta.config.ts +8 -0
- package/dist/catalog-drift.d.ts +0 -138
- package/dist/catalog-drift.js +0 -578
- package/dist/operator-ui/agents.d.ts +0 -74
- package/dist/operator-ui/agents.js +0 -104
- package/dist/operator-ui/config-summary.js +0 -565
- package/dist/operator-ui/connection-map.js +0 -376
- package/dist/operator-ui/endpoints.js +0 -221
- package/dist/operator-ui/fix-prompts.d.ts +0 -18
- package/dist/operator-ui/fix-prompts.js +0 -87
- package/dist/operator-ui/health.js +0 -52
- package/dist/operator-ui/member-page.js +0 -97
- package/dist/operator-ui/overview.js +0 -123
- package/dist/operator-ui/setup-commands.js +0 -51
- package/dist/operator-ui/view.d.ts +0 -401
- package/dist/operator-ui/view.js +0 -705
- package/dist/providers/_shared/request-token.js +0 -83
- package/dist/providers/_shared/rest/dispatch.js +0 -41
- package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
- package/dist/providers/_shared/rest/tools.d.ts +0 -141
- package/dist/providers/_shared/rest/tools.js +0 -569
- package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
- package/dist/providers/basecamp/index.d.ts +0 -45
- package/dist/providers/basecamp/index.js +0 -997
- package/dist/providers/basecamp/skill.generated.js +0 -9
- package/dist/providers/cloudflare/rest.d.ts +0 -37
- package/dist/providers/cloudflare/rest.js +0 -1097
- package/dist/providers/github/hosted.js +0 -218
- package/dist/providers/github/rest.js +0 -321
- package/dist/providers/infisical/index.d.ts +0 -7
- package/dist/providers/infisical/index.js +0 -713
- package/dist/providers/infisical/skill.generated.js +0 -8
- package/dist/providers/intercom/index.d.ts +0 -24
- package/dist/providers/intercom/index.js +0 -121
- package/dist/providers/intercom/skill.generated.js +0 -8
- package/dist/providers/linear/index.d.ts +0 -55
- package/dist/providers/linear/index.js +0 -537
- package/dist/providers/linear/skill.generated.js +0 -8
- package/dist/providers/mixpanel/index.d.ts +0 -59
- package/dist/providers/mixpanel/index.js +0 -472
- package/dist/providers/mixpanel/operations.js +0 -20
- package/dist/providers/mixpanel/rest.js +0 -603
- package/dist/providers/mixpanel/skill.generated.js +0 -10
- package/dist/providers/mixpanel/value-safety.js +0 -16
- package/dist/providers/notion/index.d.ts +0 -67
- package/dist/providers/notion/index.js +0 -368
- package/dist/providers/notion/openapi.generated.js +0 -75
- package/dist/providers/notion/rest.d.ts +0 -24
- package/dist/providers/notion/rest.js +0 -1226
- package/dist/providers/notion/skill.generated.js +0 -11
- package/dist/providers/notion/value-safety.js +0 -56
- package/dist/providers/revenuecat/index.d.ts +0 -51
- package/dist/providers/revenuecat/index.js +0 -697
- package/dist/providers/revenuecat/skill.generated.js +0 -11
- package/dist/providers/stripe/rest.d.ts +0 -14
- package/dist/providers/stripe/rest.js +0 -402
- package/dist/providers/vercel/rest.d.ts +0 -20
- package/dist/providers/vercel/rest.js +0 -1020
- package/dist/providers/wispr-flow/index.d.ts +0 -14
- package/dist/providers/wispr-flow/index.js +0 -117
- package/dist/providers/wispr-flow/skill.generated.js +0 -8
- /package/dist/providers/github/{key.js → lib/key.js} +0 -0
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
// Whose account a Google Workspace connector acts as, for the operator
|
|
2
2
|
// matrix (#837, decisions/0006). The Workspace providers tag the connector
|
|
3
3
|
// they build; nothing else can, and nothing a request sends reaches this.
|
|
4
|
-
//
|
|
4
|
+
// The operator contract never shows a mapping function; mapped subjects also
|
|
5
|
+
// mark the connector for the core's caller-bound continuations.
|
|
6
|
+
import { tagCallerIdentity } from "./connector-caller.js";
|
|
5
7
|
const tagged = new WeakMap();
|
|
6
8
|
/** Tag a Workspace connector with its subject kind, returning it unchanged. */
|
|
7
9
|
export function tagWorkspaceSubject(connector, subject) {
|
|
8
10
|
tagged.set(connector, typeof subject === "string" ? { kind: "fixed", subject } : { kind: "mapping" });
|
|
11
|
+
if (typeof subject !== "string")
|
|
12
|
+
tagCallerIdentity(connector);
|
|
9
13
|
return connector;
|
|
10
14
|
}
|
|
11
15
|
/**
|
package/dist/write-outcome.js
CHANGED
|
@@ -1,47 +1,467 @@
|
|
|
1
|
+
import { callerSignal } from "./runtime/call.js";
|
|
2
|
+
// Whether a dispatched write landed, as far as anyone can know. Shared by the
|
|
3
|
+
// invocation layer (which attaches recovery facts to every unknown outcome),
|
|
4
|
+
// trusted-program write accounting, and every connector that must tell an
|
|
5
|
+
// agent a write it sent once is not safe to repeat (INV-9). It imports only
|
|
6
|
+
// classification, errors and operator facts, without depending on a provider.
|
|
7
|
+
import { callClassification } from "./call-classification.js";
|
|
8
|
+
import { classifyCallError, classifyWithoutAdvice, ConnectorCallError, networkErrorCode, WithheldTextError, } from "./errors.js";
|
|
9
|
+
import { authorizationFailure, explainedUnauthorizedVerdict, explainsUnauthorized, inLogicalCall, settledWrite, isKnownProviderFailure, knownProviderFailure, nestedProviderCall, nestedProviderRequests, providerRequests, readRequest, refusalRequest, refusedStatus, unauthorizedAnswer, } from "./provider-call.js";
|
|
10
|
+
import { attachFailureFacts, carryFailureFacts, errorLabel } from "./operator-record.js";
|
|
1
11
|
/**
|
|
2
12
|
* Whether a write landed, as far as anyone can know.
|
|
3
13
|
*
|
|
4
14
|
* `unknown` is the outcome a result must never paper over: the call left
|
|
5
15
|
* connecta and no answer came back, so sending it again could do it twice and
|
|
6
|
-
* not sending it could leave it undone.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* `
|
|
16
|
+
* not sending it could leave it undone. A dispatched write is `failed` only on
|
|
17
|
+
* positive refusal provenance, recorded where the evidence was observed: (a)
|
|
18
|
+
* the ledger shows a request connecta refused before it left, or (b) the
|
|
19
|
+
* downstream served a refusing status, a 4xx other than 408, that its provider
|
|
20
|
+
* does not read as `unavailable` or a timeout (`servedRefusal`; a 5xx never
|
|
21
|
+
* proves a write unapplied, and a 401 does only with the vendor's reviewed
|
|
22
|
+
* `authBeforeExecution` evidence). The evidence must
|
|
23
|
+
* hold for the whole logical call (`knownCallFailure`, which `answered`
|
|
24
|
+
* reports for a served call): every request the call sent is proven not
|
|
25
|
+
* applied, and the failing request carries the refusal. A downstream tool's
|
|
26
|
+
* `isError` arrives over a 2xx after its handler ran, so it is no such
|
|
27
|
+
* evidence for a write. Nor is an error code by itself: a mapper, parser,
|
|
28
|
+
* output validator, or JSON-RPC error (`-32602` included) can follow a write
|
|
29
|
+
* that applied, so its `rate_limited` or `invalid_args` is `unknown`. So is
|
|
30
|
+
* any failure the connector marked unknown (`writeOutcome`), such as a renewal
|
|
31
|
+
* that failed after a 401. A call that was never dispatched is `failed`:
|
|
32
|
+
* nothing was sent. `result_processing_failed` means the downstream call
|
|
33
|
+
* completed.
|
|
13
34
|
*/
|
|
14
35
|
export function classifyWriteOutcome(outcome) {
|
|
15
36
|
if (outcome.ok)
|
|
16
37
|
return "ok";
|
|
17
38
|
if (!outcome.dispatched)
|
|
18
39
|
return "failed";
|
|
19
|
-
|
|
20
|
-
if (code === "result_processing_failed")
|
|
21
|
-
return "ok";
|
|
22
|
-
if (code === "timeout" || code === "cancelled" || code === "unavailable") {
|
|
40
|
+
if (outcome.error?.writeOutcome === "unknown")
|
|
23
41
|
return "unknown";
|
|
24
|
-
|
|
25
|
-
if (code !== undefined && REFUSALS.has(code))
|
|
42
|
+
if (outcome.answered === true || isKnownProviderFailure(outcome.error))
|
|
26
43
|
return "failed";
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
if (outcome.error?.code === "result_processing_failed")
|
|
45
|
+
return "ok";
|
|
46
|
+
return "unknown";
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A write's retryable common failure, told as an unknown outcome (INV-9). A
|
|
50
|
+
* request that is not safe to repeat (a write without an idempotency key)
|
|
51
|
+
* must never be advertised as retryable after it may have reached the vendor:
|
|
52
|
+
* a 5xx, a gateway's 502 to 504, a broken-off reply, or a connection lost
|
|
53
|
+
* after sending. No network failure proves a write unsent: one send can hide
|
|
54
|
+
* several attempts (a 421 or HTTP/2 refused-stream resend, a retrying
|
|
55
|
+
* dispatcher), so a refusal on the last says nothing about the first. Other
|
|
56
|
+
* failures pass through for {@link providerCallFailure} to decide, and
|
|
57
|
+
* timeouts pass through for a served call's invocation to report as
|
|
58
|
+
* `write_outcome_unknown`.
|
|
59
|
+
*/
|
|
60
|
+
function unknownOutcome(vendor, error) {
|
|
61
|
+
if (error instanceof WithheldTextError) {
|
|
62
|
+
if (!error.retryable || error.timeout)
|
|
63
|
+
return error;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
if (!(error instanceof ConnectorCallError) || !error.retryable)
|
|
67
|
+
return error;
|
|
68
|
+
if (error.code !== "unavailable" && error.code !== "connector_call_failed")
|
|
69
|
+
return error;
|
|
70
|
+
if (isTimeout(error))
|
|
71
|
+
return error;
|
|
72
|
+
}
|
|
73
|
+
return new ConnectorCallError("connector_call_failed", `${error.message} Whether the write took effect at ${vendor.title} is unknown: it carried no idempotency key, ` +
|
|
74
|
+
"so check the target before repeating it.", { retryable: false, writeOutcome: "unknown" });
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A call's result, settled as its failure would be ({@link settleWriteResult}):
|
|
78
|
+
* by the invocation for its logical call, and otherwise here, at the
|
|
79
|
+
* outermost boundary, over every ledger beneath it. The verdict to throw in
|
|
80
|
+
* place of the result, or undefined when the result stands.
|
|
81
|
+
*/
|
|
82
|
+
export function providerCallResult(ctx, fallback, request) {
|
|
83
|
+
if ((callClassification(ctx) ?? fallback) !== "write")
|
|
84
|
+
return undefined;
|
|
85
|
+
// A transport inside a ledger only records; its api() boundary settles.
|
|
86
|
+
if (request && providerRequests(ctx))
|
|
87
|
+
return undefined;
|
|
88
|
+
const requests = providerRequests(ctx) ?? (request && [request]);
|
|
89
|
+
if (!requests || inLogicalCall(ctx) || nestedProviderCall(ctx))
|
|
90
|
+
return undefined;
|
|
91
|
+
return settleWriteResult([...requests, ...nestedProviderRequests(ctx)]);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* #902's failure decision for a write, and the one place a direct write's
|
|
95
|
+
* failure is finalized (INV-9). Every connector surface hands a write's
|
|
96
|
+
* failure here before it leaves: the `api()` handler boundary, a guarded
|
|
97
|
+
* transport outside a call ledger (inside one, beneath `ctx.fetch`, the
|
|
98
|
+
* shared REST layer, or Google, it defers to the `api()` boundary), and
|
|
99
|
+
* every `remoteMcp().callTool()` write, direct or served. Nothing passes a
|
|
100
|
+
* direct write's failure on ahead of it, the caller's own abort included.
|
|
101
|
+
*
|
|
102
|
+
* The served verdict outranks transport defaults. A remote MCP dispatch's
|
|
103
|
+
* source-write ledger mark additionally requires write outcome accounting.
|
|
104
|
+
* Dispatch facts come from the transport, never from a provider's
|
|
105
|
+
* interpretation of its HTTP method. A write is a known failure only on
|
|
106
|
+
* refusal provenance recorded where the evidence was observed: (a) the
|
|
107
|
+
* ledger shows the request never left connecta, or (b) the downstream served
|
|
108
|
+
* an HTTP refusal, a 4xx other than 408 (`refusedStatus`, `vendorRefusal`),
|
|
109
|
+
* where a 401 also needs the vendor's reviewed `authBeforeExecution`
|
|
110
|
+
* evidence. An error code is never that evidence. A write that may have left
|
|
111
|
+
* and then timed out, was aborted, or failed any other way is an unknown
|
|
112
|
+
* outcome, never retryable, unless a direct caller sent an idempotency key
|
|
113
|
+
* the vendor honors (`repeatable`, or the request's recorded `key`, when it
|
|
114
|
+
* is the only request the call sent; no operation hint counts). A served
|
|
115
|
+
* call's invocation reports its own timeouts and aborts.
|
|
116
|
+
*
|
|
117
|
+
* Q8 is not decided here but once per call, over its whole ledger
|
|
118
|
+
* ({@link settleWrite}): by the invocation that opened a logical call, and
|
|
119
|
+
* otherwise only here, at the outermost boundary, after this decision.
|
|
120
|
+
*/
|
|
121
|
+
export function providerCallFailure(ctx, vendor, error, facts) {
|
|
122
|
+
const served = callClassification(ctx);
|
|
123
|
+
if ((served ?? facts.fallback) !== "write" && facts.request?.sourceWrite !== true)
|
|
124
|
+
return error;
|
|
125
|
+
const requests = providerRequests(ctx);
|
|
126
|
+
// Guarded transports collect facts; only api() knows when the logical call
|
|
127
|
+
// has ended. Google may add phases or recovery words in the meantime.
|
|
128
|
+
if (requests && !facts.finalize)
|
|
129
|
+
return error;
|
|
130
|
+
const decided = writeFailure(ctx, vendor, error, facts, served, requests);
|
|
131
|
+
// The invocation settles Q8 over its logical call; without one, the
|
|
132
|
+
// outermost boundary does, over every ledger beneath it.
|
|
133
|
+
if (inLogicalCall(ctx) || nestedProviderCall(ctx))
|
|
134
|
+
return decided;
|
|
135
|
+
return settleWrite(requests ? [...requests, ...nestedProviderRequests(ctx)] : facts.request ? [facts.request] : [], decided, isKnownProviderFailure(decided));
|
|
136
|
+
}
|
|
137
|
+
function writeFailure(ctx, vendor, error, facts, served, requests) {
|
|
138
|
+
if (requests) {
|
|
139
|
+
// In flight counts as sent. The call is closed, so nothing else leaves.
|
|
140
|
+
const sent = (request) => request.dispatched && (!request.auxiliary || request.blocksAuxiliaryProof === true);
|
|
141
|
+
const dispatched = requests.filter(sent);
|
|
142
|
+
// What api() boundaries nested in the handler sent is this call's too.
|
|
143
|
+
const nested = nestedProviderRequests(ctx).filter(sent);
|
|
144
|
+
// An empty or partial ledger is no proof for a handler that can send
|
|
145
|
+
// around it: nothing it saw rules out a request it did not see.
|
|
146
|
+
if (dispatched.length === 0 && nested.length === 0 && !facts.untracked)
|
|
147
|
+
return knownProviderFailure(error);
|
|
148
|
+
// A refusal or a key speaks for the call only as its one request, sent
|
|
149
|
+
// by this boundary: an inner call's verdict is never this one's.
|
|
150
|
+
const sole = !facts.untracked && dispatched.length === 1 && nested.length === 0 ? dispatched[0] : undefined;
|
|
151
|
+
const refusal = refusalRequest(error);
|
|
152
|
+
// An explicit unknown marker (a renewal after a 401, say) wins.
|
|
153
|
+
const own = !(error instanceof ConnectorCallError && error.writeOutcome === "unknown") &&
|
|
154
|
+
refusal !== undefined &&
|
|
155
|
+
sole === refusal;
|
|
156
|
+
if (own && servedRefusal(error, refusal.status, refusal.authBeforeExecution === true))
|
|
157
|
+
return knownProviderFailure(error);
|
|
158
|
+
if (facts.untracked)
|
|
159
|
+
return uncertainProviderFailure(vendor, error, ctx);
|
|
160
|
+
if (served === undefined && sole?.key !== undefined)
|
|
161
|
+
return error;
|
|
162
|
+
return uncertainProviderFailure({ title: dispatched[0]?.provider ?? vendor.title }, error, ctx);
|
|
163
|
+
}
|
|
164
|
+
// Provenance (a): the ledger shows the request never left connecta, unless
|
|
165
|
+
// the connector itself could not tell (an explicit unknown marker).
|
|
166
|
+
if (!facts.dispatched)
|
|
167
|
+
return error instanceof ConnectorCallError && error.writeOutcome === "unknown"
|
|
168
|
+
? error
|
|
169
|
+
: knownProviderFailure(error);
|
|
170
|
+
const status = facts.status ?? facts.request?.status;
|
|
171
|
+
const declared = facts.authBeforeExecution === true || facts.request?.authBeforeExecution === true;
|
|
172
|
+
if (served === undefined) {
|
|
173
|
+
// A direct transport user may prove idempotency with a key the vendor
|
|
174
|
+
// honors. A deployment's served write verdict still requires
|
|
175
|
+
// reconciliation rather than retry advice.
|
|
176
|
+
if (facts.repeatable === true)
|
|
177
|
+
return error;
|
|
178
|
+
// Read before any code filter: a timeout or an abort, whatever its code
|
|
179
|
+
// or source, is no verdict, and no invocation will report it.
|
|
180
|
+
if (timedOutOrAborted(error, ctx))
|
|
181
|
+
return uncertainProviderFailure(vendor, error, ctx);
|
|
182
|
+
if (!(error instanceof ConnectorCallError)) {
|
|
183
|
+
const converted = unknownOutcome(vendor, error);
|
|
184
|
+
return converted === error ? uncertainProviderFailure(vendor, error, ctx) : converted;
|
|
185
|
+
}
|
|
186
|
+
if (error.writeOutcome === "unknown")
|
|
187
|
+
return uncertainProviderFailure(vendor, error, ctx);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
if (!(error instanceof ConnectorCallError))
|
|
191
|
+
return unknownOutcome(vendor, error);
|
|
192
|
+
if (error.writeOutcome === "unknown")
|
|
193
|
+
return error;
|
|
194
|
+
// The served call's invocation reports it as `write_outcome_unknown`.
|
|
195
|
+
if (isTimeout(error))
|
|
196
|
+
return error;
|
|
197
|
+
}
|
|
198
|
+
// Provenance (b). An error code alone (a mapper's `rate_limited` after a
|
|
199
|
+
// 2xx, a JSON-RPC `-32602`, an output validator's `invalid_args`) is never
|
|
200
|
+
// this evidence.
|
|
201
|
+
if (servedRefusal(error, status, declared))
|
|
202
|
+
return knownProviderFailure(error);
|
|
203
|
+
const serverError = status !== undefined && status >= 500;
|
|
204
|
+
if (facts.repeatable === true && error.retryable) {
|
|
205
|
+
return carryFailureFacts(error, new ConnectorCallError("connector_call_failed", `${error.message} Whether the write took effect at ${vendor.title} is unknown; check the target before repeating it.`, { retryable: false, writeOutcome: "unknown" }));
|
|
206
|
+
}
|
|
207
|
+
const converted = unknownOutcome(vendor, error);
|
|
208
|
+
if (converted instanceof ConnectorCallError && converted !== error)
|
|
209
|
+
return carryFailureFacts(error, converted);
|
|
210
|
+
return carryFailureFacts(error, new ConnectorCallError(serverError ? "connector_call_failed" : error.code, error.message, {
|
|
211
|
+
retryable: false,
|
|
212
|
+
writeOutcome: "unknown",
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Provenance (b), the one rule for the ledger and for a transport outside
|
|
217
|
+
* one: the downstream served a refusing HTTP status (`refusedStatus`, a 4xx
|
|
218
|
+
* other than 408), and its provider read that status as a refusal. A
|
|
219
|
+
* provider that reads it as `unavailable` or a timeout (Stripe's 424) says
|
|
220
|
+
* the outcome is not proven. A 401 proves nothing by itself: a server may act
|
|
221
|
+
* on a request before it rejects the credential, so it is a refusal only where
|
|
222
|
+
* the vendor's reviewed `authBeforeExecution` evidence says it authenticates
|
|
223
|
+
* first. Of the maintained providers, only Stripe's API-key connector
|
|
224
|
+
* declares that evidence.
|
|
225
|
+
*/
|
|
226
|
+
function servedRefusal(error, status, authBeforeExecution) {
|
|
227
|
+
if (!refusedStatus(status))
|
|
228
|
+
return false;
|
|
229
|
+
if (status === 401 && !authBeforeExecution)
|
|
230
|
+
return false;
|
|
231
|
+
const code = classifyCallError(error).code;
|
|
232
|
+
return code !== "unavailable" && code !== "timeout";
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Q8, the one decision for a write answered 401, made once per logical call
|
|
236
|
+
* over every request it recorded: nested `api()` calls, remote MCP, guarded
|
|
237
|
+
* transports and the kit alike. The invocation makes it for a served call,
|
|
238
|
+
* whatever failed (a thrown or mapped error, a custom wrapper's, a
|
|
239
|
+
* program's call, its own deadline or the caller's cancellation, as
|
|
240
|
+
* `error` undefined), and `providerCallFailure` for a direct one at its
|
|
241
|
+
* outermost boundary. Boundaries only record what they observed: dispatch,
|
|
242
|
+
* status, a reviewed `authBeforeExecution` match, the 401's mapped verdict
|
|
243
|
+
* (`vendorRefusal`) and a renewal of that request's own credential
|
|
244
|
+
* (`renewedAfterUnauthorized`).
|
|
245
|
+
*
|
|
246
|
+
* A write request answered 401 means a server may have acted before it
|
|
247
|
+
* rejected the credential, so the call's outcome is unknown, never
|
|
248
|
+
* retryable, with no wait and no resend or key-reuse advice (INV-9). While
|
|
249
|
+
* any such 401 is unrenewed, authorization is still needed: the verdict
|
|
250
|
+
* keeps an authorization code, and so the `authorize_connector` handoff,
|
|
251
|
+
* whose words reconcile before any fresh call ({@link unauthorizedVerdict}).
|
|
252
|
+
* Only a renewal of every one drops the handoff ({@link renewedVerdict}).
|
|
253
|
+
* The one exception is reviewed vendor evidence: a 401 matching the
|
|
254
|
+
* vendor's `authBeforeExecution` declaration that is the only request the
|
|
255
|
+
* call sent, whose own refusal is the failure and is known for the whole
|
|
256
|
+
* call (`knownRefusal`: the boundary that sent it proved it, and, served,
|
|
257
|
+
* `knownCallFailure`), stays that refusal. Returns `error` itself when no
|
|
258
|
+
* write request was answered 401.
|
|
259
|
+
*/
|
|
260
|
+
export function settleWrite(requests, error, knownRefusal) {
|
|
261
|
+
const sent = requests.filter((request) => request.dispatched && !request.auxiliary);
|
|
262
|
+
const answers = sent.filter((request) => request.status === 401);
|
|
263
|
+
const [only] = answers;
|
|
264
|
+
if (only === undefined)
|
|
265
|
+
return error;
|
|
266
|
+
if (knownRefusal && sent.length === 1 && only.authBeforeExecution === true && standingRefusal(error, only))
|
|
267
|
+
return error;
|
|
268
|
+
const unrenewed = answers.find((request) => request.renewed !== true);
|
|
269
|
+
return settledWrite(unrenewed ? unauthorizedVerdict(unrenewed, error) : renewedVerdict(answers, error));
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* The same decision for a call that returned a result: any undeclared write
|
|
273
|
+
* 401 blocks success, even after renewal. A positively classified read's 401
|
|
274
|
+
* and a declared refusal do not invalidate the handler's successful result.
|
|
275
|
+
*/
|
|
276
|
+
export function settleWriteResult(requests) {
|
|
277
|
+
return settleWrite(requests.filter((request) => !readRequest(request) && request.authBeforeExecution !== true), undefined, false);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* The declared 401's own refusal is the failure, typed and not made unknown;
|
|
281
|
+
* or no failure arrived at all (the invocation's deadline), so nothing after
|
|
282
|
+
* the refusal can have run.
|
|
283
|
+
*/
|
|
284
|
+
function standingRefusal(error, request) {
|
|
285
|
+
if (error === undefined)
|
|
286
|
+
return true;
|
|
287
|
+
return (error instanceof ConnectorCallError &&
|
|
288
|
+
error.writeOutcome !== "unknown" &&
|
|
289
|
+
refusalRequest(error) === request &&
|
|
290
|
+
servedRefusal(error, 401, true));
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* The verdict of a call with an unrenewed write 401: `error` when it is an
|
|
294
|
+
* authorization verdict, else the one that 401's own answer was mapped to,
|
|
295
|
+
* else `auth_required`; never retryable, unknown, without a wait or advice.
|
|
296
|
+
* A verdict that already accounts for the 401 keeps its words; any other
|
|
297
|
+
* gains the sentence that the write was sent before the vendor rejected its
|
|
298
|
+
* credential.
|
|
299
|
+
*/
|
|
300
|
+
function unauthorizedVerdict(answer, error) {
|
|
301
|
+
const base = authorizationFailure(error)
|
|
302
|
+
? error
|
|
303
|
+
: (unauthorizedAnswer(answer) ??
|
|
304
|
+
attachFailureFacts(new ConnectorCallError("auth_required", `${answer.provider} answered this write with HTTP 401.`), answer.status === undefined ? {} : { httpStatus: answer.status }));
|
|
305
|
+
if (explainsUnauthorized(base))
|
|
306
|
+
return carryFailureFacts(error, withoutRetry(base));
|
|
307
|
+
return explainedUnauthorizedVerdict(carryFailureFacts(error, carryFailureFacts(base, new ConnectorCallError(base.code, `${base.message} The write was sent before ${answer.provider} rejected its credential, so whether it ` +
|
|
308
|
+
"took effect is unknown: check the target before repeating it.", { retryable: false, writeOutcome: "unknown" }))));
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Every write 401 the call recorded was renewed: nothing is left to
|
|
312
|
+
* authorize, and the outcome stays unknown. The renewed 401's own verdict,
|
|
313
|
+
* or no failure at all (the invocation's deadline), reads as the renewal
|
|
314
|
+
* did ({@link unsentAfterUnauthorized}); any other failure keeps its words,
|
|
315
|
+
* unknown, without a retry flag or a wait.
|
|
316
|
+
*/
|
|
317
|
+
function renewedVerdict(answers, error) {
|
|
318
|
+
const own = refusalRequest(error);
|
|
319
|
+
const subject = (own ?? answers[0]).provider;
|
|
320
|
+
if (error === undefined || (authorizationFailure(error) && own !== undefined && answers.includes(own)))
|
|
321
|
+
return carryFailureFacts(error, unsentAfterUnauthorized(subject));
|
|
322
|
+
// Every failure, typed or not (a raw network error, an abort, a thrown
|
|
323
|
+
// string), reads as #902's unknown outcome, without a retry flag or wait.
|
|
324
|
+
return withoutRetry(uncertainProviderFailure({ title: subject }, error, undefined));
|
|
325
|
+
}
|
|
326
|
+
/** An unknown outcome as it stands, without a retry flag or a wait. */
|
|
327
|
+
function withoutRetry(error) {
|
|
328
|
+
if (!error.retryable && error.retryAfterMs === undefined && error.writeOutcome === "unknown")
|
|
329
|
+
return error;
|
|
330
|
+
return carryFailureFacts(error, new ConnectorCallError(error.code, error.message, {
|
|
331
|
+
retryable: false,
|
|
332
|
+
writeOutcome: "unknown",
|
|
333
|
+
...(error.details ? { details: error.details } : {}),
|
|
334
|
+
...(error.validation ? { validation: error.validation } : {}),
|
|
335
|
+
...(error.repair ? { repair: error.repair } : {}),
|
|
336
|
+
...(error.current ? { current: error.current } : {}),
|
|
337
|
+
}));
|
|
338
|
+
}
|
|
339
|
+
function isTimeoutCode(code) {
|
|
340
|
+
return code === "timeout" || code === "ETIMEDOUT" || code?.endsWith("_TIMEOUT") === true;
|
|
341
|
+
}
|
|
342
|
+
/** `code: "timeout"` (an SDK or connecta deadline, an HTTP 408) or a timeout errno. */
|
|
343
|
+
function isTimeout(error) {
|
|
344
|
+
return error.code === "timeout" || isTimeoutCode(error.details?.code);
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* A direct caller's own abort reason, when its signal had aborted by the time
|
|
348
|
+
* the failure arrived. Node's fetch rejects with that reason itself; workerd's
|
|
349
|
+
* with an error of its own, so identity alone cannot tell. A served call's
|
|
350
|
+
* signal is its invocation's, which reports its own deadline and cancellation.
|
|
351
|
+
*/
|
|
352
|
+
function callerAbort(ctx) {
|
|
353
|
+
const signal = callerSignal(ctx);
|
|
354
|
+
return signal?.aborted === true && callClassification(ctx) === undefined ? { reason: signal.reason } : undefined;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Every timeout and abort a direct write can meet: the caller's own signal
|
|
358
|
+
* (an `AbortSignal.timeout` included), the SDK's request deadline and
|
|
359
|
+
* connecta's own (`code: "timeout"`), and a runtime's timeout errno
|
|
360
|
+
* (`ETIMEDOUT`, undici's `UND_ERR_*_TIMEOUT`) or `AbortError`.
|
|
361
|
+
*/
|
|
362
|
+
function timedOutOrAborted(error, ctx) {
|
|
363
|
+
if (callerAbort(ctx) !== undefined)
|
|
364
|
+
return true;
|
|
365
|
+
if (error instanceof WithheldTextError)
|
|
366
|
+
return error.timeout;
|
|
367
|
+
if (error instanceof ConnectorCallError)
|
|
368
|
+
return isTimeout(error);
|
|
369
|
+
return isTimeoutCode(networkErrorCode(error));
|
|
370
|
+
}
|
|
371
|
+
/** Change recovery wording without rebuilding a provider's shared verdict. */
|
|
372
|
+
export function providerFailureMessage(error, message) {
|
|
373
|
+
return carryFailureFacts(error, new ConnectorCallError(error.code, message, {
|
|
374
|
+
retryable: error.retryable,
|
|
375
|
+
...(error.writeOutcome ? { writeOutcome: error.writeOutcome } : {}),
|
|
376
|
+
...(error.retryAfterMs === undefined ? {} : { retryAfterMs: error.retryAfterMs }),
|
|
377
|
+
...(error.details ? { details: error.details } : {}),
|
|
378
|
+
...(error.validation ? { validation: error.validation } : {}),
|
|
379
|
+
...(error.repair ? { repair: error.repair } : {}),
|
|
380
|
+
...(error.current ? { current: error.current } : {}),
|
|
381
|
+
}));
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Final ambiguous call verdict, including typed handler failures after 2xx
|
|
385
|
+
* and the caller's own abort.
|
|
386
|
+
*/
|
|
387
|
+
function uncertainProviderFailure(vendor, error, ctx) {
|
|
388
|
+
if (error instanceof ConnectorCallError && error.writeOutcome === "unknown" && !error.retryable)
|
|
389
|
+
return error;
|
|
390
|
+
const abort = ctx && callerAbort(ctx);
|
|
391
|
+
if (abort)
|
|
392
|
+
return callerAborted(vendor, error, abort.reason);
|
|
393
|
+
const details = classifyWithoutAdvice(error);
|
|
394
|
+
const timeout = details.code === "timeout" || (details.code === "unavailable" && isTimeoutCode(details.details?.code));
|
|
395
|
+
const common = error instanceof ConnectorCallError && (error.code === "unavailable" || error.code === "connector_call_failed");
|
|
396
|
+
const message = !timeout && common && error.retryable
|
|
397
|
+
? `${details.message} Whether the write took effect at ${vendor.title} is unknown; check the target before repeating it.`
|
|
398
|
+
: details.message;
|
|
399
|
+
const code = error instanceof ConnectorCallError && (error.code !== "unavailable" || timeout)
|
|
400
|
+
? error.code
|
|
401
|
+
: timeout
|
|
402
|
+
? "timeout"
|
|
403
|
+
: "connector_call_failed";
|
|
404
|
+
return carryFailureFacts(error, new ConnectorCallError(code, message, {
|
|
405
|
+
retryable: false,
|
|
406
|
+
writeOutcome: "unknown",
|
|
407
|
+
// Diagnostics stay with the code they describe.
|
|
408
|
+
...(error instanceof ConnectorCallError && code === error.code && error.details
|
|
409
|
+
? { details: error.details }
|
|
410
|
+
: {}),
|
|
411
|
+
...(error instanceof ConnectorCallError
|
|
412
|
+
? {
|
|
413
|
+
...(error.retryAfterMs === undefined ? {} : { retryAfterMs: error.retryAfterMs }),
|
|
414
|
+
...(error.validation ? { validation: error.validation } : {}),
|
|
415
|
+
...(error.repair ? { repair: error.repair } : {}),
|
|
416
|
+
...(error.current ? { current: error.current } : {}),
|
|
417
|
+
}
|
|
418
|
+
: {}),
|
|
419
|
+
}));
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* A direct write the caller's own signal aborted after it may have left: a
|
|
423
|
+
* `timeout` when the reason is one (`AbortSignal.timeout`), else
|
|
424
|
+
* `connector_call_failed`. The reason stays the cause, since the caller wrote
|
|
425
|
+
* it, and its class and timeout code stay in `details`, so the caller can
|
|
426
|
+
* still tell its own abort apart on every runtime.
|
|
427
|
+
*/
|
|
428
|
+
function callerAborted(vendor, error, reason) {
|
|
429
|
+
const code = networkErrorCode(reason);
|
|
430
|
+
const name = errorLabel(reason);
|
|
431
|
+
return carryFailureFacts(error, new ConnectorCallError(isTimeoutCode(code) ? "timeout" : "connector_call_failed", `The caller's signal aborted this call${name ? ` (${name})` : ""} after the write may have reached ` +
|
|
432
|
+
`${vendor.title}. Whether it took effect is unknown; check the target before repeating it.`, {
|
|
433
|
+
retryable: false,
|
|
434
|
+
writeOutcome: "unknown",
|
|
435
|
+
cause: reason,
|
|
436
|
+
...(name || code ? { details: { ...(name ? { name } : {}), ...(code ? { code } : {}) } } : {}),
|
|
437
|
+
}));
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* A write the downstream answered with HTTP 401, then credential renewal ran.
|
|
441
|
+
* A server may act on a request before it rejects the token, so the write is
|
|
442
|
+
* never sent again (INV-9), and nothing renewal meets afterwards (a refresh or
|
|
443
|
+
* login that fails, a disconnect, an unreachable token endpoint) may be
|
|
444
|
+
* reported as safe to retry. `renewal` is renewal's failure, or undefined
|
|
445
|
+
* when the credential was renewed and a deliberate repeat will use it.
|
|
446
|
+
*
|
|
447
|
+
* Until renewal succeeds the 401's authorization verdict stands: renewal's
|
|
448
|
+
* own verdict when it reached one, else `code`, the 401's. Either keeps its
|
|
449
|
+
* recovery handoff, which the invocation layer marks `reconciliationRequired`.
|
|
450
|
+
* Only a renewed credential drops the handoff, since nothing is left to
|
|
451
|
+
* recover. Either way the write's outcome is unknown (`writeOutcome`), so a
|
|
452
|
+
* program that catches the failure still reports it.
|
|
453
|
+
*/
|
|
454
|
+
export function unsentAfterUnauthorized(subject, renewal, code = "auth_required") {
|
|
455
|
+
if (renewal instanceof ConnectorCallError &&
|
|
456
|
+
(renewal.code === "auth_required" || renewal.code === "downstream_oauth_required")) {
|
|
457
|
+
return explainedUnauthorizedVerdict(carryFailureFacts(renewal, new ConnectorCallError(renewal.code, renewal.message, { retryable: false, writeOutcome: "unknown" })));
|
|
458
|
+
}
|
|
459
|
+
// Only the class of what renewal met: its own text may say to try again,
|
|
460
|
+
// which this write must not be told. Operator records keep its facts.
|
|
461
|
+
const renewed = renewal === undefined
|
|
462
|
+
? "The credential is renewed for the next call, but the write"
|
|
463
|
+
: `Renewing the credential failed (${classifyCallError(renewal).code}), and the write`;
|
|
464
|
+
const unsent = new ConnectorCallError(renewal === undefined ? "connector_call_failed" : code, `${subject} answered this write with HTTP 401. ${renewed} was not sent again, so whether it took effect is ` +
|
|
465
|
+
"unknown: check the target before repeating it.", { retryable: false, writeOutcome: "unknown" });
|
|
466
|
+
return explainedUnauthorizedVerdict(renewal === undefined ? unsent : carryFailureFacts(renewal, unsent));
|
|
467
|
+
}
|
package/documentation/README.md
CHANGED
|
@@ -11,18 +11,36 @@ For a new deployment, start with [Deploying Connecta](./deploying.md).
|
|
|
11
11
|
| Task | Self-contained procedure |
|
|
12
12
|
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
13
13
|
| Add or remove a connector | [Change the connector roster](./integrating.md#add-or-remove-a-connector) |
|
|
14
|
+
| Set up a maintained provider | [Maintained provider setup](./providers.md) |
|
|
15
|
+
| Inspect maintained API sources and tools | [API sources and tool inventory](./providers.md#api-sources-and-tool-inventory) |
|
|
14
16
|
| Organize an agent's pools and tiers | [Organizing an agent's pools](./auth.md#organizing-an-agents-pools) |
|
|
15
17
|
| Add a person (maintainer or pool member) | [Add a person](./auth.md#add-a-person), [member page](./operator-ui.md#use-the-member-page) |
|
|
16
18
|
| Connect a shared credential | [Connect a shared credential](./auth.md#connect-a-shared-credential) |
|
|
17
19
|
| Issue, rotate, or revoke an agent token | [Manage an agent token](./auth.md#issue-rotate-or-revoke-an-agent-token) |
|
|
18
20
|
| Upgrade between versions | [Upgrade an existing deployment](./deploying.md#upgrade-an-existing-deployment), including [migration to 0.33](./migration-0.33.md) |
|
|
19
21
|
| Diagnose with `connecta doctor` | [Verify and diagnose](./deploying.md#verify-and-diagnose) |
|
|
22
|
+
| Connect a client with tool search | [Native tool surface](./meta-tools.md#native-tool-surface), [Eve agents](./meta-tools.md#eve-agents) |
|
|
23
|
+
|
|
24
|
+
For removed hosted presets and the former hosted modes of Stripe, Vercel,
|
|
25
|
+
Cloudflare, and GitHub, use [Migrate hosted MCP presets](./hosted-mcp-migration.md).
|
|
26
|
+
Notion and Mixpanel lose only their maintained API providers in 0.35.0; their
|
|
27
|
+
hosted MCP servers remain connectable through generic `remoteMcp()` entries
|
|
28
|
+
in that guide. For all three removed API providers, including Infisical, use
|
|
29
|
+
[Provider migration for 0.35](./provider-migration-0.35.md).
|
|
30
|
+
|
|
31
|
+
For a Vercel-hosted agent without a provisioned Connecta token, use
|
|
32
|
+
[Vercel workload credentials (available from 0.35.0)](./auth.md#vercel-workload-credentials).
|
|
33
|
+
|
|
34
|
+
The separate `@zackbart/connecta-eve` helper is available from 0.35.0. Its
|
|
35
|
+
[package guide](https://github.com/zackbart/connecta/blob/main/packages/connecta-eve/README.md)
|
|
36
|
+
owns installation, supported Node/Eve versions, and token-source setup.
|
|
20
37
|
|
|
21
38
|
## Audience rule
|
|
22
39
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
40
|
+
`documentation/`, `templates/`, and `examples/worker/` are written first for an
|
|
41
|
+
agent operating a deployment from the installed package. The root `README.md`
|
|
42
|
+
and `guides/` explain the product for people and also ship in the package;
|
|
43
|
+
they own no operator contracts. Operator conventions must be self-contained rules plus a
|
|
26
44
|
neutral example. Decision records and issues explain why; no operator task
|
|
27
45
|
requires them, `spec/`, `.claude/`, or the Connecta source checkout. Those
|
|
28
46
|
three directories do not ship. Contributor source maps, INV citations, and
|
|
@@ -44,6 +62,7 @@ product names stay.
|
|
|
44
62
|
| [Operator UI tests (contributor reference)](./operator-tests.md) | Browser state matrix, real-server flows, and snapshot maintenance |
|
|
45
63
|
| [Migration to 0.33](./migration-0.33.md) | Upgrade actions from 0.32 options to maintainers, members, agents, agent endpoints, and pool owners |
|
|
46
64
|
| [Provider migration for 0.29](./provider-migration-0.29.md) | Upgrade actions for Notion, Vercel, and Cloudflare; provider reconciliation tables supply exact name mappings |
|
|
65
|
+
| [Provider migration for 0.35](./provider-migration-0.35.md) | Provider upgrade actions for 0.35.0 |
|
|
47
66
|
| [Provider auth migration](./provider-auth-migration.md) | Upgrade actions when `auth` selects hosted MCP or Connecta's REST connector, Stripe and Vercel |
|
|
48
67
|
|
|
49
68
|
Each long contract starts with task routes. Follow those section links before
|
|
@@ -55,9 +74,11 @@ implementation evidence.
|
|
|
55
74
|
### Documentation ownership
|
|
56
75
|
|
|
57
76
|
The root [README](../README.md) explains the product for people. It owns what
|
|
58
|
-
Connecta offers
|
|
59
|
-
|
|
60
|
-
|
|
77
|
+
Connecta offers and the setup handoff. The human guides explain
|
|
78
|
+
[how it works](../guides/how-it-works.md), [connecting agents](../guides/connecting-agents.md),
|
|
79
|
+
and [safety and trust](../guides/safety-and-trust.md). Keep their examples small
|
|
80
|
+
and consistent with these contracts. Configuration references, complete setup
|
|
81
|
+
procedures, migrations, and internal module maps belong here in agent documentation.
|
|
61
82
|
|
|
62
83
|
[AGENTS.md](https://github.com/zackbart/connecta/blob/main/AGENTS.md) is the
|
|
63
84
|
canonical repository policy, with `CLAUDE.md` as its symlink. Do not copy its
|
|
@@ -83,6 +104,6 @@ The [changelog](../CHANGELOG.md) records shipped releases.
|
|
|
83
104
|
[Decisions](https://github.com/zackbart/connecta/tree/main/decisions) explain
|
|
84
105
|
history and may be superseded. [Spec coverage](https://github.com/zackbart/connecta/blob/main/spec/coverage.json)
|
|
85
106
|
records implemented support, gaps, and test evidence. The
|
|
86
|
-
[
|
|
107
|
+
[#703 rework](https://github.com/zackbart/connecta/issues/703) and other
|
|
87
108
|
issues describe planned work; do not turn their goals into claims of shipped
|
|
88
109
|
behavior.
|