@zackbart/connecta 0.34.0 → 0.35.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 +393 -0
- package/README.md +62 -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 +2051 -1160
- 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 +663 -271
- 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 +15 -7
- package/dist/connectors/api-connector.js +147 -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/option-shapes.js +1 -1
- package/dist/connectors/remote-mcp.d.ts +12 -30
- package/dist/connectors/remote-mcp.js +960 -564
- package/dist/d1.js +10 -243
- package/dist/derived-context.js +5 -0
- package/dist/describe-config.d.ts +5 -1
- package/dist/describe-config.js +3 -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 +228 -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 +383 -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 +221 -87
- 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 +534 -408
- 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/agents.d.ts +5 -4
- package/dist/operator-ui/agents.js +17 -7
- package/dist/operator-ui/config-summary.js +8 -4
- package/dist/operator-ui/connection-map.js +9 -6
- package/dist/operator-ui/contract.d.ts +7 -3
- package/dist/operator-ui/endpoints.js +5 -14
- package/dist/operator-ui/fix-prompts.d.ts +1 -1
- package/dist/operator-ui/fix-prompts.js +0 -8
- package/dist/operator-ui/generated.js +3 -3
- package/dist/operator-ui/health.js +52 -0
- package/dist/operator-ui/model.d.ts +2 -3
- package/dist/operator-ui/overview.js +11 -19
- package/dist/operator-ui/setup-commands.js +0 -4
- package/dist/operator-ui/view.d.ts +5 -29
- package/dist/operator-ui/view.js +3 -59
- 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 +71 -32
- package/dist/provider.js +134 -40
- package/dist/providers/_shared/google/hatch.js +91 -0
- package/dist/providers/_shared/google/kit.js +537 -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 +8 -209
- package/dist/providers/_shared/google/workspace.js +7 -426
- package/dist/providers/_shared/rest/compact-index.js +86 -0
- package/dist/providers/_shared/rest/dispatch.js +3 -23
- package/dist/providers/_shared/rest/kit.js +546 -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/tools.js +101 -78
- 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 +3 -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 +17 -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 +7 -22
- package/dist/providers/cloudflare/index.js +80 -194
- 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 +3299 -3208
- package/dist/providers/cloudflare/{value-safety.js → safety.js} +538 -18
- 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 +802 -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 +1024 -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 +3 -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 +6 -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/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 +734 -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 +7 -27
- package/dist/providers/stripe/index.js +75 -191
- 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 -10
- package/dist/providers/stripe/tools.js +77 -0
- package/dist/providers/tithely/api.js +531 -0
- package/dist/providers/tithely/index.d.ts +19 -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 +11 -25
- package/dist/providers/vercel/index.js +67 -261
- 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 +398 -376
- package/dist/providers/vercel/{value-safety.js → safety.js} +261 -42
- 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 +30 -28
- package/dist/registry.js +446 -413
- 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 +3 -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 +29 -22
- 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 +556 -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 +330 -224
- 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 +11 -99
- 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 +27 -7
- package/documentation/architecture.md +2550 -186
- package/documentation/auth.md +821 -98
- package/documentation/code-mode.md +56 -21
- package/documentation/deploying.md +164 -20
- package/documentation/hosted-mcp-migration.md +460 -0
- package/documentation/integrating.md +144 -105
- package/documentation/meta-tools.md +411 -34
- package/documentation/operating.md +28 -4
- package/documentation/operator-tests.md +11 -2
- package/documentation/operator-ui.md +103 -33
- package/documentation/provider-auth-migration.md +38 -63
- package/documentation/provider-migration-0.29.md +10 -5
- package/documentation/provider-migration-0.35.md +975 -0
- package/documentation/providers.md +965 -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 +27 -42
- 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 -134
- package/dist/catalog-drift.js +0 -493
- package/dist/providers/_shared/request-token.js +0 -83
- 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/value-safety.d.ts +0 -201
- package/dist/providers/basecamp/index.d.ts +0 -43
- 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 -1078
- 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/linear/index.d.ts +0 -55
- package/dist/providers/linear/index.js +0 -352
- package/dist/providers/linear/skill.generated.js +0 -8
- package/dist/providers/mixpanel/index.d.ts +0 -57
- package/dist/providers/mixpanel/index.js +0 -468
- 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 -65
- 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 -49
- package/dist/providers/revenuecat/index.js +0 -557
- 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
package/dist/errors.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type ConnectorCallErrorCode = "timeout" | "auth_required" | "downstream_o
|
|
|
13
13
|
* re-authorizing, or repairing arguments, and a program looping over ids can
|
|
14
14
|
* continue past it where `connector_call_failed` would abort. Map a status
|
|
15
15
|
* here only where the provider distinguishes absence from a permission gap —
|
|
16
|
-
* where
|
|
16
|
+
* where one status covers both, the honest
|
|
17
17
|
* code stays `connector_call_failed` or `auth_required` with a message that
|
|
18
18
|
* states the ambiguity (H11).
|
|
19
19
|
*/
|
|
@@ -89,7 +89,11 @@ export declare function echoedCallArgs(args: unknown, schema?: JsonSchema): {
|
|
|
89
89
|
};
|
|
90
90
|
/** Optional transport diagnostics; never a URL path or raw runtime message. */
|
|
91
91
|
interface UnavailableDetails {
|
|
92
|
-
/**
|
|
92
|
+
/**
|
|
93
|
+
* An error class label: a guest program's, or the class of the caller's own
|
|
94
|
+
* abort reason behind a direct write whose outcome is unknown. Returned to
|
|
95
|
+
* the agent, never operator records.
|
|
96
|
+
*/
|
|
93
97
|
name?: string;
|
|
94
98
|
line?: number | null;
|
|
95
99
|
hint?: string;
|
|
@@ -139,6 +143,8 @@ export declare class WithheldTextError extends Error {
|
|
|
139
143
|
}
|
|
140
144
|
/** Agent-visible recovery class for downstream credential failures. */
|
|
141
145
|
export type AuthRecoveryMode = "oauth" | "operator_config" | "unavailable";
|
|
146
|
+
/** Runtime membership in the closed connector taxonomy, checked against its exhaustive table. */
|
|
147
|
+
export declare function isConnectorCallErrorCode(value: unknown): value is ConnectorCallErrorCode;
|
|
142
148
|
/**
|
|
143
149
|
* Throw from `Connector.callTool` (or anything beneath it) to classify a
|
|
144
150
|
* failure exactly. Untyped errors are non-retryable unless a runtime errno
|
|
@@ -166,13 +172,24 @@ export declare class ConnectorCallError extends Error {
|
|
|
166
172
|
/** Bounded schema findings for `invalid_args`; never submitted values. */
|
|
167
173
|
readonly validation: ArgumentValidationDetails | undefined;
|
|
168
174
|
readonly repair: ArgumentRepairDetails | undefined;
|
|
169
|
-
/**
|
|
175
|
+
/**
|
|
176
|
+
* Sanitized transport diagnostics, for `unavailable` and for a write whose
|
|
177
|
+
* outcome is unknown (a timeout's errno, an abort's class).
|
|
178
|
+
*/
|
|
170
179
|
readonly details: UnavailableDetails | undefined;
|
|
171
180
|
/**
|
|
172
181
|
* For `conflict` only: where each thing the write touched stands now, e.g.
|
|
173
182
|
* `{ revision: 12, view: 7 }`. Bounded to 20 whole-number entries.
|
|
174
183
|
*/
|
|
175
184
|
readonly current: Readonly<Record<string, number>> | undefined;
|
|
185
|
+
/**
|
|
186
|
+
* `"unknown"` when the write this call sent may have taken effect, whatever
|
|
187
|
+
* `code` says: an authorization verdict reached after the downstream already
|
|
188
|
+
* had the write (a 401, unless the vendor's reviewed evidence says it
|
|
189
|
+
* authenticates first, or a renewal that failed after one) is still an
|
|
190
|
+
* unknown outcome (INV-9). Undefined when the code alone tells the outcome.
|
|
191
|
+
*/
|
|
192
|
+
readonly writeOutcome: "unknown" | undefined;
|
|
176
193
|
constructor(code: ConnectorCallErrorCode, message: string, opts?: {
|
|
177
194
|
retryable?: boolean;
|
|
178
195
|
retryAfterMs?: number;
|
|
@@ -181,6 +198,7 @@ export declare class ConnectorCallError extends Error {
|
|
|
181
198
|
repair?: ArgumentRepairDetails;
|
|
182
199
|
details?: UnavailableDetails;
|
|
183
200
|
current?: Readonly<Record<string, number>>;
|
|
201
|
+
writeOutcome?: "unknown";
|
|
184
202
|
});
|
|
185
203
|
}
|
|
186
204
|
/** Secret-free payload returned by authorize_connector and auth failures. */
|
|
@@ -218,10 +236,15 @@ export interface CallErrorDetails extends Partial<AuthorizationHandoff> {
|
|
|
218
236
|
connector?: string;
|
|
219
237
|
/** Canonical downstream address the agent may retry after recovery. */
|
|
220
238
|
operation?: string;
|
|
221
|
-
/**
|
|
239
|
+
/** Safe recovery path for this authentication failure. */
|
|
222
240
|
recovery?: AuthRecoveryMode;
|
|
223
241
|
/** An auth failure followed a write's downstream send. Reconcile before retry. */
|
|
224
242
|
reconciliationRequired?: true;
|
|
243
|
+
/**
|
|
244
|
+
* The write this call sent may have taken effect, whatever `code` says (see
|
|
245
|
+
* {@link ConnectorCallError.writeOutcome}). Check its target before repeating it.
|
|
246
|
+
*/
|
|
247
|
+
writeOutcome?: "unknown";
|
|
225
248
|
/** The single model-facing entry point for every credential class. */
|
|
226
249
|
nextAction?: {
|
|
227
250
|
tool: "authorize_connector";
|
|
@@ -282,7 +305,10 @@ export interface CallErrorDetails extends Partial<AuthorizationHandoff> {
|
|
|
282
305
|
args?: unknown;
|
|
283
306
|
argsOmitted?: true;
|
|
284
307
|
argsRedacted?: true;
|
|
285
|
-
/**
|
|
308
|
+
/**
|
|
309
|
+
* Facts the connector recorded before dispatch, such as a generated
|
|
310
|
+
* `idempotencyKey`: diagnostics. `retry` says when reusing the key is safe.
|
|
311
|
+
*/
|
|
286
312
|
recovery?: Readonly<Record<string, string>>;
|
|
287
313
|
};
|
|
288
314
|
/** Explicit retry guidance; recovery never retries or mutates by itself. */
|
|
@@ -290,7 +316,62 @@ export interface CallErrorDetails extends Partial<AuthorizationHandoff> {
|
|
|
290
316
|
}
|
|
291
317
|
/** Retryability of connecta framing depends only on its code. */
|
|
292
318
|
export declare function framingError(code: ClassificationCode, message: string): CallErrorDetails;
|
|
293
|
-
/**
|
|
319
|
+
/**
|
|
320
|
+
* Attach advice to send the call again (a rate limit's " Back off before
|
|
321
|
+
* retrying.", a token error's ", then retry authorization") to `error` as a
|
|
322
|
+
* segment of its own: `error.message` never contains it. It holds for a read
|
|
323
|
+
* and a known refusal, so output composes it ({@link withResendAdvice}) only
|
|
324
|
+
* there, after the outcome is decided. No redaction or rewording of the
|
|
325
|
+
* message can then hide it from removal on a write whose outcome is unknown
|
|
326
|
+
* (INV-9). A segment that opens a sentence (" Wait…") follows the message;
|
|
327
|
+
* any other is a clause, placed before the message's closing period.
|
|
328
|
+
*/
|
|
329
|
+
export declare function resendAdvice<T extends object>(error: T, advice: string): T;
|
|
330
|
+
/** The resend advice attached to `from`, if any. */
|
|
331
|
+
export declare function resendAdviceOf(from: unknown): string | undefined;
|
|
332
|
+
export interface KeyResendAdvice {
|
|
333
|
+
/** The key the advice names, as it was sent. */
|
|
334
|
+
key: string;
|
|
335
|
+
advice: string;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Attach advice that reusing `key` with the same arguments cannot repeat the
|
|
339
|
+
* write, a segment of its own like {@link resendAdvice}. It holds only where
|
|
340
|
+
* that key protects the whole logical call (`keyProtectsCall`): one
|
|
341
|
+
* boundary entered, one write sent, carrying `key`. Attach it only once the
|
|
342
|
+
* call's ledger shows a dispatched request carrying `key`: a key generated
|
|
343
|
+
* but never sent protects nothing. Two places compose it. The invocation
|
|
344
|
+
* sees the whole call and composes it for a served call once
|
|
345
|
+
* `keyProtectsCall` holds. {@link classifyCallError} composes it for a
|
|
346
|
+
* dispatched direct call, which has no invocation: only the one boundary that
|
|
347
|
+
* sent the keyed request attaches it, and any boundary above that one
|
|
348
|
+
* finalizes the write as unknown, which drops it. Either way the key stays in
|
|
349
|
+
* the message as a diagnostic.
|
|
350
|
+
*/
|
|
351
|
+
export declare function keyResendAdvice<T extends object>(error: T, key: string, advice: string): T;
|
|
352
|
+
/** The key-reuse advice attached to `from`, if any. */
|
|
353
|
+
export declare function keyResendAdviceOf(from: unknown): KeyResendAdvice | undefined;
|
|
354
|
+
/**
|
|
355
|
+
* Keep `from`'s resend advice, key-reuse advice included, on `to`, a copy or
|
|
356
|
+
* rewording of it (redaction, a provider's recovery words). A write already
|
|
357
|
+
* marked unknown never takes it.
|
|
358
|
+
*/
|
|
359
|
+
export declare function carryResendAdvice(from: unknown, to: unknown): void;
|
|
360
|
+
/** `message` with resend `advice` composed in. Only output calls this. */
|
|
361
|
+
export declare function withResendAdvice(message: string, advice: string | undefined): string;
|
|
362
|
+
/**
|
|
363
|
+
* Typed connector verdicts and runtime facts only. Prose never changes a
|
|
364
|
+
* verdict. The message carries the error's resend advice unless its write's
|
|
365
|
+
* outcome is unknown. This is a direct caller's view, outside any logical
|
|
366
|
+
* call: key-reuse advice is here only because the one boundary that sent the
|
|
367
|
+
* keyed request attached it to its own failure, and any boundary above it
|
|
368
|
+
* finalizes the write as unknown. An invocation composes advice itself.
|
|
369
|
+
*/
|
|
294
370
|
export declare function classifyCallError(err: unknown, fallbackCode?: ClassificationCode): CallErrorDetails;
|
|
371
|
+
/**
|
|
372
|
+
* {@link classifyCallError} without the resend advice, for a caller that
|
|
373
|
+
* decides the outcome first and composes the advice only where it holds.
|
|
374
|
+
*/
|
|
375
|
+
export declare function classifyWithoutAdvice(err: unknown, fallbackCode?: ClassificationCode): CallErrorDetails;
|
|
295
376
|
export declare function msg(err: unknown): string;
|
|
296
377
|
export {};
|
package/dist/errors.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Typed failure contract for connector tool calls. Web-API only — no node:
|
|
2
2
|
// imports here.
|
|
3
3
|
import { redactCallArguments } from "./argument-redaction.js";
|
|
4
|
+
import { followRedactedCopies } from "./redaction-identity.js";
|
|
4
5
|
const CLASSIFICATION_CODE_TABLE = {
|
|
5
6
|
timeout: true,
|
|
6
7
|
auth_required: true,
|
|
@@ -192,6 +193,8 @@ export const NETWORK_ERROR_CODES = new Set([
|
|
|
192
193
|
function networkCode(value) {
|
|
193
194
|
return typeof value === "string" && value.length <= 32 && NETWORK_ERROR_CODES.has(value) ? value : undefined;
|
|
194
195
|
}
|
|
196
|
+
/** An error class label, as `errorLabel` reports one. */
|
|
197
|
+
const ERROR_CLASS = /^[A-Z][A-Za-z]{0,63}$/;
|
|
195
198
|
function sanitizedUnavailableDetails(details) {
|
|
196
199
|
if (!details)
|
|
197
200
|
return undefined;
|
|
@@ -207,7 +210,10 @@ function sanitizedUnavailableDetails(details) {
|
|
|
207
210
|
}
|
|
208
211
|
}
|
|
209
212
|
const code = networkCode(details.code);
|
|
210
|
-
|
|
213
|
+
const name = typeof details.name === "string" && ERROR_CLASS.test(details.name) ? details.name : undefined;
|
|
214
|
+
return host || code || name
|
|
215
|
+
? { ...(name ? { name } : {}), ...(host ? { host } : {}), ...(code ? { code } : {}) }
|
|
216
|
+
: undefined;
|
|
211
217
|
}
|
|
212
218
|
/** Runtime fields only: provider prose cannot supply an errno or a deadline. */
|
|
213
219
|
export function networkErrorCode(error) {
|
|
@@ -282,6 +288,10 @@ const RETRYABLE_BY_CODE = {
|
|
|
282
288
|
input_required_limit: false,
|
|
283
289
|
connector_call_failed: false,
|
|
284
290
|
};
|
|
291
|
+
/** Runtime membership in the closed connector taxonomy, checked against its exhaustive table. */
|
|
292
|
+
export function isConnectorCallErrorCode(value) {
|
|
293
|
+
return typeof value === "string" && Object.hasOwn(RETRYABLE_BY_CODE, value);
|
|
294
|
+
}
|
|
285
295
|
/** Entries a conflict's `current` map may carry. */
|
|
286
296
|
const MAX_CURRENT_ENTRIES = 20;
|
|
287
297
|
const MAX_CURRENT_KEY_CHARS = 128;
|
|
@@ -337,23 +347,36 @@ export class ConnectorCallError extends Error {
|
|
|
337
347
|
/** Bounded schema findings for `invalid_args`; never submitted values. */
|
|
338
348
|
validation;
|
|
339
349
|
repair;
|
|
340
|
-
/**
|
|
350
|
+
/**
|
|
351
|
+
* Sanitized transport diagnostics, for `unavailable` and for a write whose
|
|
352
|
+
* outcome is unknown (a timeout's errno, an abort's class).
|
|
353
|
+
*/
|
|
341
354
|
details;
|
|
342
355
|
/**
|
|
343
356
|
* For `conflict` only: where each thing the write touched stands now, e.g.
|
|
344
357
|
* `{ revision: 12, view: 7 }`. Bounded to 20 whole-number entries.
|
|
345
358
|
*/
|
|
346
359
|
current;
|
|
360
|
+
/**
|
|
361
|
+
* `"unknown"` when the write this call sent may have taken effect, whatever
|
|
362
|
+
* `code` says: an authorization verdict reached after the downstream already
|
|
363
|
+
* had the write (a 401, unless the vendor's reviewed evidence says it
|
|
364
|
+
* authenticates first, or a renewal that failed after one) is still an
|
|
365
|
+
* unknown outcome (INV-9). Undefined when the code alone tells the outcome.
|
|
366
|
+
*/
|
|
367
|
+
writeOutcome;
|
|
347
368
|
constructor(code, message, opts = {}) {
|
|
348
369
|
super(message, opts.cause !== undefined ? { cause: opts.cause } : undefined);
|
|
349
370
|
this.name = "ConnectorCallError";
|
|
350
371
|
this.code = code;
|
|
351
372
|
this.retryable = opts.retryable ?? RETRYABLE_BY_CODE[code];
|
|
352
373
|
this.retryAfterMs = normalizeRetryAfterMs(opts.retryAfterMs);
|
|
353
|
-
this.details =
|
|
374
|
+
this.details =
|
|
375
|
+
code === "unavailable" || opts.writeOutcome === "unknown" ? sanitizedUnavailableDetails(opts.details) : undefined;
|
|
354
376
|
this.validation = code === "invalid_args" ? boundedValidation(opts.validation) : undefined;
|
|
355
377
|
this.repair = code === "invalid_args" ? boundedRepair(opts.repair) : undefined;
|
|
356
378
|
this.current = code === "conflict" ? boundedCurrent(opts.current) : undefined;
|
|
379
|
+
this.writeOutcome = opts.writeOutcome === "unknown" ? "unknown" : undefined;
|
|
357
380
|
}
|
|
358
381
|
}
|
|
359
382
|
/** Retryability of connecta framing depends only on its code. */
|
|
@@ -364,8 +387,94 @@ export function framingError(code, message) {
|
|
|
364
387
|
retryable: code === "timeout" || code === "unavailable" || code === "rate_limited",
|
|
365
388
|
};
|
|
366
389
|
}
|
|
367
|
-
|
|
390
|
+
// Advice to send a call again, kept beside its failure and never inside the
|
|
391
|
+
// failure's message. See resendAdvice.
|
|
392
|
+
const resendAdvices = followRedactedCopies(new WeakMap());
|
|
393
|
+
/**
|
|
394
|
+
* Attach advice to send the call again (a rate limit's " Back off before
|
|
395
|
+
* retrying.", a token error's ", then retry authorization") to `error` as a
|
|
396
|
+
* segment of its own: `error.message` never contains it. It holds for a read
|
|
397
|
+
* and a known refusal, so output composes it ({@link withResendAdvice}) only
|
|
398
|
+
* there, after the outcome is decided. No redaction or rewording of the
|
|
399
|
+
* message can then hide it from removal on a write whose outcome is unknown
|
|
400
|
+
* (INV-9). A segment that opens a sentence (" Wait…") follows the message;
|
|
401
|
+
* any other is a clause, placed before the message's closing period.
|
|
402
|
+
*/
|
|
403
|
+
export function resendAdvice(error, advice) {
|
|
404
|
+
resendAdvices.set(error, advice);
|
|
405
|
+
return error;
|
|
406
|
+
}
|
|
407
|
+
/** The resend advice attached to `from`, if any. */
|
|
408
|
+
export function resendAdviceOf(from) {
|
|
409
|
+
return from !== null && typeof from === "object" ? resendAdvices.get(from) : undefined;
|
|
410
|
+
}
|
|
411
|
+
// Advice that reusing an idempotency key cannot repeat the write, kept apart
|
|
412
|
+
// from the failure's message and its other resend advice. See keyResendAdvice.
|
|
413
|
+
const keyAdvices = followRedactedCopies(new WeakMap());
|
|
414
|
+
/**
|
|
415
|
+
* Attach advice that reusing `key` with the same arguments cannot repeat the
|
|
416
|
+
* write, a segment of its own like {@link resendAdvice}. It holds only where
|
|
417
|
+
* that key protects the whole logical call (`keyProtectsCall`): one
|
|
418
|
+
* boundary entered, one write sent, carrying `key`. Attach it only once the
|
|
419
|
+
* call's ledger shows a dispatched request carrying `key`: a key generated
|
|
420
|
+
* but never sent protects nothing. Two places compose it. The invocation
|
|
421
|
+
* sees the whole call and composes it for a served call once
|
|
422
|
+
* `keyProtectsCall` holds. {@link classifyCallError} composes it for a
|
|
423
|
+
* dispatched direct call, which has no invocation: only the one boundary that
|
|
424
|
+
* sent the keyed request attaches it, and any boundary above that one
|
|
425
|
+
* finalizes the write as unknown, which drops it. Either way the key stays in
|
|
426
|
+
* the message as a diagnostic.
|
|
427
|
+
*/
|
|
428
|
+
export function keyResendAdvice(error, key, advice) {
|
|
429
|
+
keyAdvices.set(error, { key, advice });
|
|
430
|
+
return error;
|
|
431
|
+
}
|
|
432
|
+
/** The key-reuse advice attached to `from`, if any. */
|
|
433
|
+
export function keyResendAdviceOf(from) {
|
|
434
|
+
return from !== null && typeof from === "object" ? keyAdvices.get(from) : undefined;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Keep `from`'s resend advice, key-reuse advice included, on `to`, a copy or
|
|
438
|
+
* rewording of it (redaction, a provider's recovery words). A write already
|
|
439
|
+
* marked unknown never takes it.
|
|
440
|
+
*/
|
|
441
|
+
export function carryResendAdvice(from, to) {
|
|
442
|
+
if (!(to instanceof Error) || to.writeOutcome === "unknown")
|
|
443
|
+
return;
|
|
444
|
+
const advice = resendAdviceOf(from);
|
|
445
|
+
const keyed = keyResendAdviceOf(from);
|
|
446
|
+
if (advice !== undefined && !resendAdvices.has(to))
|
|
447
|
+
resendAdvices.set(to, advice);
|
|
448
|
+
if (keyed !== undefined && !keyAdvices.has(to))
|
|
449
|
+
keyAdvices.set(to, keyed);
|
|
450
|
+
}
|
|
451
|
+
/** `message` with resend `advice` composed in. Only output calls this. */
|
|
452
|
+
export function withResendAdvice(message, advice) {
|
|
453
|
+
if (advice === undefined)
|
|
454
|
+
return message;
|
|
455
|
+
return /^ [A-Z]/.test(advice) || !message.endsWith(".") ? message + advice : `${message.slice(0, -1)}${advice}.`;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Typed connector verdicts and runtime facts only. Prose never changes a
|
|
459
|
+
* verdict. The message carries the error's resend advice unless its write's
|
|
460
|
+
* outcome is unknown. This is a direct caller's view, outside any logical
|
|
461
|
+
* call: key-reuse advice is here only because the one boundary that sent the
|
|
462
|
+
* keyed request attached it to its own failure, and any boundary above it
|
|
463
|
+
* finalizes the write as unknown. An invocation composes advice itself.
|
|
464
|
+
*/
|
|
368
465
|
export function classifyCallError(err, fallbackCode = "connector_call_failed") {
|
|
466
|
+
const details = classifyWithoutAdvice(err, fallbackCode);
|
|
467
|
+
if (details.writeOutcome !== "unknown") {
|
|
468
|
+
details.message = withResendAdvice(details.message, keyResendAdviceOf(err)?.advice);
|
|
469
|
+
details.message = withResendAdvice(details.message, resendAdviceOf(err));
|
|
470
|
+
}
|
|
471
|
+
return details;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* {@link classifyCallError} without the resend advice, for a caller that
|
|
475
|
+
* decides the outcome first and composes the advice only where it holds.
|
|
476
|
+
*/
|
|
477
|
+
export function classifyWithoutAdvice(err, fallbackCode = "connector_call_failed") {
|
|
369
478
|
if (err instanceof ConnectorCallError) {
|
|
370
479
|
return {
|
|
371
480
|
code: err.code,
|
|
@@ -376,6 +485,7 @@ export function classifyCallError(err, fallbackCode = "connector_call_failed") {
|
|
|
376
485
|
...(err.repair ? { repair: err.repair } : {}),
|
|
377
486
|
...(err.details ? { details: err.details } : {}),
|
|
378
487
|
...(err.current ? { current: err.current } : {}),
|
|
488
|
+
...(err.writeOutcome ? { writeOutcome: err.writeOutcome } : {}),
|
|
379
489
|
};
|
|
380
490
|
}
|
|
381
491
|
if (err instanceof WithheldTextError) {
|
package/dist/execute.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { authCall, authInvoke, authMethod } from "./auth/native.js";
|
|
2
|
+
import { nativeRecovery } from "./native-recovery.js";
|
|
1
3
|
import { GUEST_API_DECLARATION } from "./usage-guide.js";
|
|
2
4
|
import { bindMcpClient } from "./mcp-client-context.js";
|
|
3
5
|
import { CONFIG_DEFAULTS } from "./config-defaults.js";
|
|
4
6
|
import { Cause, Deferred, Duration, Effect, Exit } from "effect";
|
|
5
|
-
import
|
|
7
|
+
import * as z from "zod";
|
|
6
8
|
import { advertisedSchema } from "./advertised-schema.js";
|
|
7
9
|
import { boundedDiscoveryText, CatalogService, DiscoveryPolicyError, flatSearchResult, } from "./catalog-service.js";
|
|
8
10
|
import { createMetaTools, guardProgramReturn, jsonResult, pageProgramResult, } from "./meta-tools.js";
|
|
@@ -17,9 +19,10 @@ import { EXECUTE_OUTPUT } from "./meta-output.js";
|
|
|
17
19
|
import { normalizeProgramSource } from "./program-source.js";
|
|
18
20
|
import { readResource } from "./resource-read.js";
|
|
19
21
|
import { agentOutputOperations, redactAgentOutput, sentSecretsForRequest } from "./sent-secrets.js";
|
|
20
|
-
import { normalizeTimeoutMs
|
|
22
|
+
import { normalizeTimeoutMs } from "./timeout.js";
|
|
21
23
|
import { fromSignal, runEdge, withDeadlineEffect } from "./runtime/run.js";
|
|
22
24
|
import { closeScope } from "./runtime/connector-scope.js";
|
|
25
|
+
import { executorProgram } from "./runtime/executor.js";
|
|
23
26
|
import { connectorGuide, connectorGuideRequired, connectorSkillName, hasConnectorGuides, SkillsRegistry, } from "./skills.js";
|
|
24
27
|
/** Keep one model-written program from amplifying into an unbounded fan-out. */
|
|
25
28
|
const EXECUTE_MAX_HOST_CALLS = CONFIG_DEFAULTS.execute.maxHostCalls;
|
|
@@ -558,7 +561,8 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
|
|
|
558
561
|
unrecorded: true,
|
|
559
562
|
};
|
|
560
563
|
}
|
|
561
|
-
|
|
564
|
+
const budgeted = target.definition.classification !== "read";
|
|
565
|
+
if (budgeted && writes >= maxWrites) {
|
|
562
566
|
return {
|
|
563
567
|
kind: "refuse",
|
|
564
568
|
error: {
|
|
@@ -568,7 +572,8 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
|
|
|
568
572
|
},
|
|
569
573
|
};
|
|
570
574
|
}
|
|
571
|
-
|
|
575
|
+
if (budgeted)
|
|
576
|
+
writes++;
|
|
572
577
|
if (programWrites)
|
|
573
578
|
sending.settle = programWrites.begin();
|
|
574
579
|
return { kind: "dispatch" };
|
|
@@ -678,7 +683,7 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
|
|
|
678
683
|
};
|
|
679
684
|
const operations = {
|
|
680
685
|
call,
|
|
681
|
-
result: (id, options, signal) => Effect.tryPromise({
|
|
686
|
+
result: (id, options, signal, onStage) => Effect.tryPromise({
|
|
682
687
|
try: async () => {
|
|
683
688
|
const transfer = typeof id === "string" ? transfers.get(id) : undefined;
|
|
684
689
|
const transferId = id;
|
|
@@ -709,7 +714,10 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
|
|
|
709
714
|
}
|
|
710
715
|
// A page must fit every shipped bridge even when the connector cap is raised.
|
|
711
716
|
args.maxBytes = Math.min(args.maxBytes ?? PROGRAM_RESULT_PAGE_BYTES, PROGRAM_RESULT_PAGE_BYTES);
|
|
712
|
-
const page = await meta.readResult({ id, ...args }, {
|
|
717
|
+
const page = await meta.readResult({ id, ...args }, {
|
|
718
|
+
signal: signal,
|
|
719
|
+
onStage: onStage,
|
|
720
|
+
});
|
|
713
721
|
if (page.isError)
|
|
714
722
|
throw new InvocationFailure((page.structuredContent?.error ?? {
|
|
715
723
|
code: "not_found",
|
|
@@ -864,9 +872,12 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
|
|
|
864
872
|
hostCalls.admitted++;
|
|
865
873
|
const started = Date.now();
|
|
866
874
|
const utility = name === "result" || name === "skill";
|
|
875
|
+
let stage = name === "result" ? "result storage" : "skill lookup";
|
|
867
876
|
const invoke = Effect.suspend(() => operation(...args));
|
|
868
877
|
const guarded = utility
|
|
869
|
-
? withDeadlineEffect((utilitySignal) => Effect.suspend(() => operation(args[0], args[1], utilitySignal
|
|
878
|
+
? withDeadlineEffect((utilitySignal) => Effect.suspend(() => operation(args[0], args[1], utilitySignal, (current) => {
|
|
879
|
+
stage = current;
|
|
880
|
+
})), {
|
|
870
881
|
timeoutMs: hostCallTimeoutMs,
|
|
871
882
|
...(hostAccessSignal ? { signal: hostAccessSignal } : {}),
|
|
872
883
|
timeoutError: guestFailure("timeout", `connecta.${name} timed out.`),
|
|
@@ -877,14 +888,14 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
|
|
|
877
888
|
return typedFailure(guestFailure("cancelled", `connecta.${name} was cancelled because the run ended.`));
|
|
878
889
|
if (utility && error instanceof InvocationFailure && error.code === "timeout") {
|
|
879
890
|
const elapsedMs = Date.now() - started;
|
|
880
|
-
const message = `Operation "connecta.${name}" timed out during ${
|
|
891
|
+
const message = `Operation "connecta.${name}" timed out during ${stage} after ${elapsedMs}ms (effective deadline ${hostCallTimeoutMs}ms).`;
|
|
881
892
|
return typedFailure(new InvocationFailure({
|
|
882
893
|
code: "timeout",
|
|
883
894
|
message,
|
|
884
895
|
retryable: true,
|
|
885
896
|
details: {
|
|
886
897
|
operation: `connecta.${name}`,
|
|
887
|
-
stage
|
|
898
|
+
stage,
|
|
888
899
|
elapsedMs,
|
|
889
900
|
deadlineMs: hostCallTimeoutMs,
|
|
890
901
|
},
|
|
@@ -914,7 +925,7 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
|
|
|
914
925
|
};
|
|
915
926
|
}
|
|
916
927
|
/**
|
|
917
|
-
* Await
|
|
928
|
+
* Await executor work without trusting it to settle.
|
|
918
929
|
*
|
|
919
930
|
* An executor's deadline is its own business, and the Dynamic Worker's lives
|
|
920
931
|
* inside the sandbox: a wedged isolate never fires it, so the call never
|
|
@@ -927,28 +938,33 @@ function sandboxProvider(registry, baseUrl, activity, limits, requestScope = {})
|
|
|
927
938
|
* a ceiling of its own. Cancellation settles as the same `executor_cancelled`
|
|
928
939
|
* the QuickJS pool reports, unless the executor reports its own first; the
|
|
929
940
|
* ceiling as an untyped executor failure naming the key that sets it. Either
|
|
930
|
-
* way the handler
|
|
931
|
-
*
|
|
932
|
-
*
|
|
933
|
-
*
|
|
934
|
-
*
|
|
941
|
+
* way the handler releases the lease. Losing native programs are interrupted
|
|
942
|
+
* and their finalizers awaited, so native interruption cleanup must remain
|
|
943
|
+
* synchronous or bounded to avoid delaying the watchdog or terminal response.
|
|
944
|
+
* Custom Promise leaves may continue, with late settlements still observed;
|
|
945
|
+
* lease release recycles the QuickJS child or disposes Worker handles without
|
|
946
|
+
* waiting for the guest. A lease granted after its request gave up goes to
|
|
947
|
+
* `late`. The result contract is untouched — this only decides when to stop
|
|
948
|
+
* waiting for one.
|
|
935
949
|
*/
|
|
936
950
|
function awaitExecutor(start, signal, options = {}) {
|
|
937
951
|
const started = Date.now();
|
|
938
952
|
const contenders = [
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
953
|
+
typeof start !== "function"
|
|
954
|
+
? start
|
|
955
|
+
: Effect.suspend(() => {
|
|
956
|
+
let pending;
|
|
957
|
+
const settling = Effect.tryPromise({
|
|
958
|
+
try: () => (pending = Promise.resolve(start())),
|
|
959
|
+
catch: (err) => err,
|
|
960
|
+
});
|
|
961
|
+
const { late } = options;
|
|
962
|
+
return late
|
|
963
|
+
? settling.pipe(Effect.onInterrupt(() => Effect.sync(() => {
|
|
964
|
+
pending?.then(late, () => { });
|
|
965
|
+
})))
|
|
966
|
+
: settling;
|
|
967
|
+
}),
|
|
952
968
|
// An executor that honors the signal rejects in the abort event itself,
|
|
953
969
|
// with the logs it captured attached, and that report beats ours by one
|
|
954
970
|
// timer turn. (A 1ms sleep, not 0: Effect.sleep(0) waits a microtask,
|
|
@@ -1086,17 +1102,18 @@ export function createExecuteTool(registry, baseUrl, executor, logger, activity,
|
|
|
1086
1102
|
return yield* timed((elapsed) => {
|
|
1087
1103
|
if (diagnostics)
|
|
1088
1104
|
diagnostics.executorWallMs = elapsed;
|
|
1089
|
-
}, awaitExecutor(()
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1105
|
+
}, awaitExecutor(executorProgram(admitted ?? executor, wrapGuestProgram(program), [provider], {
|
|
1106
|
+
result: (outcome) => {
|
|
1107
|
+
executorLogs = sentSecrets.redact(outcome?.logs);
|
|
1108
|
+
},
|
|
1109
|
+
error: (err) => {
|
|
1110
|
+
if (err !== null && typeof err === "object" && "logs" in err)
|
|
1111
|
+
executorLogs = sentSecrets.redact(err.logs);
|
|
1112
|
+
},
|
|
1113
|
+
interrupted: (logs) => {
|
|
1114
|
+
executorLogs = sentSecrets.redact(logs);
|
|
1115
|
+
},
|
|
1116
|
+
}).pipe(Effect.map((outcome) => sentSecrets.redact(outcome)), Effect.mapError((error) => sentSecrets.redact(error))), signal, { watchdog, terminal: Deferred.await(terminal) }).pipe(Effect.ensuring(Effect.suspend(() => {
|
|
1100
1117
|
programWrites.close();
|
|
1101
1118
|
dispatchController.abort();
|
|
1102
1119
|
return programWrites.drain();
|
|
@@ -1141,7 +1158,7 @@ export function createExecuteTool(registry, baseUrl, executor, logger, activity,
|
|
|
1141
1158
|
}).pipe(Effect.map((result) => redactAgentOutput(sentSecrets, result)));
|
|
1142
1159
|
});
|
|
1143
1160
|
return agentOutputOperations((requestScope) => ({
|
|
1144
|
-
execute: ({ code, diagnostics }, options = {}) => {
|
|
1161
|
+
execute: authMethod(({ code, diagnostics }, options = {}) => {
|
|
1145
1162
|
// A code-unit count above the cap is already too large in UTF-8. Check
|
|
1146
1163
|
// that first so a huge direct-call string is never encoded in full.
|
|
1147
1164
|
if (code.length > EXECUTE_MAX_CODE_BYTES ||
|
|
@@ -1153,10 +1170,10 @@ export function createExecuteTool(registry, baseUrl, executor, logger, activity,
|
|
|
1153
1170
|
hostCalls: { attempted: 0, admitted: 0, succeeded: 0, failed: 0 },
|
|
1154
1171
|
};
|
|
1155
1172
|
response.content[0].text = JSON.stringify(response.structuredContent);
|
|
1156
|
-
return
|
|
1173
|
+
return Effect.succeed(response);
|
|
1157
1174
|
}
|
|
1158
|
-
return
|
|
1159
|
-
},
|
|
1175
|
+
return Effect.suspend(() => play(normalizeProgramSource(code), diagnostics, options.signal, requestScope));
|
|
1176
|
+
}),
|
|
1160
1177
|
}), config.requestScope).execute;
|
|
1161
1178
|
}
|
|
1162
1179
|
/** An execution that never produced an ExecuteResult, as the model sees it. */
|
|
@@ -1328,7 +1345,7 @@ function connectorInventory(connectors) {
|
|
|
1328
1345
|
return `${prefix}${shown.join(", ")}.`;
|
|
1329
1346
|
return `${prefix}${shown.join(", ")}${shown.length > 0 ? "; " : ""}+${omitted} more.`;
|
|
1330
1347
|
}
|
|
1331
|
-
const executeDescription = (emitBudgets, hostLimits, connectorGuides, connectors, maxWrites, readOnly) => `${readOnly ? "One known read: call_tool. Everything else: execute_code. Read-only endpoint: search and describe omit write tools, and every write call is refused." : "One known read: call_tool. One known write: call_destructive_tool. Everything else: execute_code. Writable endpoint: programs may read and write; the client approves."} Limits: ${hostLimits.maxHostCalls} host calls, ${readOnly ? "" : `${maxWrites} writes, `}${hostLimits.hostCallTimeoutMs / 1_000}s/host call.
|
|
1348
|
+
const executeDescription = (emitBudgets, hostLimits, connectorGuides, connectors, maxWrites, readOnly, native = false) => `${native ? `Call tools directly; combine work here using their program addresses. ${readOnly ? "Read-only endpoint: writes are omitted and refused." : "Writable endpoint: programs may read and write; the client approves."}` : readOnly ? "One known read: call_tool. Everything else: execute_code. Read-only endpoint: search and describe omit write tools, and every write call is refused." : "One known read: call_tool. One known write: call_destructive_tool. Everything else: execute_code. Writable endpoint: programs may read and write; the client approves."} Limits: ${hostLimits.maxHostCalls} host calls, ${readOnly ? "" : `${maxWrites} writes, `}${hostLimits.hostCallTimeoutMs / 1_000}s/host call.
|
|
1332
1349
|
${connectorInventory(connectors)}
|
|
1333
1350
|
|
|
1334
1351
|
Use async () => { ... }, no arguments. No portable ambient capabilities. API:
|
|
@@ -1383,7 +1400,7 @@ export function registerExecuteTool(server, registry, ctx) {
|
|
|
1383
1400
|
description: executeDescription(emitBudgets, {
|
|
1384
1401
|
...hostLimits,
|
|
1385
1402
|
hostCallTimeoutMs: normalizeTimeoutMs(ctx.defaultToolTimeoutMs) ?? hostLimits.hostCallTimeoutMs,
|
|
1386
|
-
}, hasConnectorGuides(connectors), connectors, maxWrites, ctx.readOnly === true),
|
|
1403
|
+
}, hasConnectorGuides(connectors), connectors, maxWrites, ctx.readOnly === true, ctx.native === true),
|
|
1387
1404
|
inputSchema: EXECUTE_INPUT,
|
|
1388
1405
|
outputSchema: EXECUTE_OUTPUT,
|
|
1389
1406
|
// The client sees execute_code as a write exactly when the endpoint writes.
|
|
@@ -1392,12 +1409,32 @@ export function registerExecuteTool(server, registry, ctx) {
|
|
|
1392
1409
|
destructiveHint: ctx.readOnly !== true,
|
|
1393
1410
|
openWorldHint: true,
|
|
1394
1411
|
},
|
|
1395
|
-
}, (args, extra) => {
|
|
1412
|
+
}, authMethod((args, extra) => Effect.gen(function* () {
|
|
1396
1413
|
if (ctx.client)
|
|
1397
1414
|
bindMcpClient(extra, ctx.client, ctx.activity);
|
|
1398
|
-
const run = () =>
|
|
1399
|
-
|
|
1415
|
+
const run = authMethod(() => Effect.suspend(() => {
|
|
1416
|
+
const controller = new AbortController();
|
|
1417
|
+
const forwarders = [extra.mcpReq.signal, ctx.requestSignal]
|
|
1418
|
+
.filter((signal) => signal !== undefined)
|
|
1419
|
+
.map((signal) => {
|
|
1420
|
+
const forward = () => controller.abort(signal.reason);
|
|
1421
|
+
if (signal.aborted)
|
|
1422
|
+
forward();
|
|
1423
|
+
else
|
|
1424
|
+
signal.addEventListener("abort", forward, { once: true });
|
|
1425
|
+
return { signal, forward };
|
|
1426
|
+
});
|
|
1427
|
+
return authCall(execute, [
|
|
1428
|
+
args,
|
|
1429
|
+
{ signal: controller.signal },
|
|
1430
|
+
]).pipe(Effect.ensuring(Effect.sync(() => {
|
|
1431
|
+
for (const { signal, forward } of forwarders)
|
|
1432
|
+
signal.removeEventListener("abort", forward);
|
|
1433
|
+
})));
|
|
1400
1434
|
}));
|
|
1401
|
-
|
|
1402
|
-
|
|
1435
|
+
const result = yield* ctx.authElicitation
|
|
1436
|
+
? authInvoke(ctx.authElicitation, "run", ["execute_code", args, extra, run])
|
|
1437
|
+
: authCall(run, []);
|
|
1438
|
+
return ctx.native ? nativeRecovery(result, true) : result;
|
|
1439
|
+
})));
|
|
1403
1440
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Deferred, Duration, Effect } from "effect";
|
|
2
2
|
import { admit, provideAdmissionProgram } from "./runtime/admission.js";
|
|
3
3
|
import { fromSignal, runEdge } from "./runtime/run.js";
|
|
4
|
+
import { keepErrorName } from "./redaction-identity.js";
|
|
4
5
|
/**
|
|
5
6
|
* A stable, machine-readable admission failure. Overload is retryable; caller
|
|
6
7
|
* cancellation and shutdown are terminal for this invocation.
|
|
@@ -19,6 +20,7 @@ export class ExecutorAdmissionError extends Error {
|
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
}
|
|
23
|
+
keepErrorName(ExecutorAdmissionError, "ExecutorAdmissionError");
|
|
22
24
|
/**
|
|
23
25
|
* A lifecycle failure after the sandbox started running. It keeps the stable
|
|
24
26
|
* admission-error envelope while letting response assembly distinguish work
|
|
@@ -30,6 +32,7 @@ export class ExecutorExecutionError extends ExecutorAdmissionError {
|
|
|
30
32
|
this.name = "ExecutorExecutionError";
|
|
31
33
|
}
|
|
32
34
|
}
|
|
35
|
+
keepErrorName(ExecutorExecutionError, "ExecutorExecutionError");
|
|
33
36
|
function positiveWhole(value, name) {
|
|
34
37
|
if (!Number.isFinite(value) || !Number.isInteger(value) || value < 1) {
|
|
35
38
|
throw new TypeError(`${name} must be a positive whole number.`);
|