@zackbart/connecta 0.28.0 → 0.29.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 +961 -5
- package/README.md +62 -39
- package/bin/connecta.mjs +110 -139
- package/bin/meta-tool-names.d.mts +2 -0
- package/bin/meta-tool-names.mjs +9 -0
- package/bin/version.mjs +3 -0
- package/dist/access-tokens.js +53 -63
- package/dist/activity-request.js +8 -0
- package/dist/activity.d.ts +76 -42
- package/dist/activity.js +110 -42
- package/dist/auth/clerk-sdk/client.d.ts +65 -0
- package/dist/auth/clerk-sdk/client.js +5 -0
- package/dist/auth/clerk-sdk/generated.js +1845 -0
- package/dist/auth/clerk-transport.js +19 -0
- package/dist/auth/clerk.d.ts +17 -7
- package/dist/auth/clerk.js +189 -107
- package/dist/auth/cloudflare-access.js +25 -26
- package/dist/auth/downstream-client-metadata.d.ts +29 -0
- package/dist/auth/downstream-client-metadata.js +133 -0
- package/dist/auth/downstream-oauth.js +1632 -1509
- package/dist/auth/downstream-revocation.js +106 -0
- package/dist/auth/oauth-token-response.js +231 -0
- package/dist/auth/oauth-v2-migration.js +116 -0
- package/dist/auth/static-oauth.js +526 -0
- package/dist/auth-elicitation.js +283 -0
- package/dist/branding.d.ts +8 -16
- package/dist/branding.js +26 -59
- package/dist/byte-read-response.js +39 -0
- package/dist/call-admission.js +12 -16
- package/dist/catalog-cache.js +739 -0
- package/dist/catalog-drift.d.ts +50 -15
- package/dist/catalog-drift.js +365 -128
- package/dist/catalog-fingerprint.js +2 -4
- package/dist/catalog-freshness.js +13 -0
- package/dist/catalog-limits.js +2 -2
- package/dist/catalog-service.js +368 -224
- package/dist/catalog.js +43 -84
- package/dist/concurrency.js +3 -4
- package/dist/config-defaults.d.ts +39 -0
- package/dist/config-defaults.js +46 -0
- package/dist/config-schema.d.ts +181 -0
- package/dist/config-schema.js +435 -0
- package/dist/config-value-sources.js +102 -0
- package/dist/config.d.ts +631 -0
- package/dist/config.js +503 -0
- package/dist/connector-access.d.ts +1 -0
- package/dist/connector-access.js +13 -15
- package/dist/connector-caller.d.ts +8 -0
- package/dist/connector-caller.js +15 -6
- package/dist/connector-scope.js +1 -1
- package/dist/connectors/api-connector.d.ts +220 -0
- package/dist/connectors/api-connector.js +214 -0
- package/dist/connectors/api.d.ts +8 -71
- package/dist/connectors/api.js +13 -99
- package/dist/connectors/guarded-fetch.d.ts +144 -0
- package/dist/connectors/guarded-fetch.js +108 -25
- package/dist/connectors/negotiation-cache.js +46 -0
- package/dist/connectors/option-shapes.js +27 -0
- package/dist/connectors/remote-mcp.d.ts +30 -4
- package/dist/connectors/remote-mcp.js +1780 -351
- package/dist/connectors/resource-uri.js +335 -0
- package/dist/credential-contract.d.ts +10 -0
- package/dist/credential-rules.js +1 -3
- package/dist/credential-url.js +108 -0
- package/dist/credentials.d.ts +6 -1
- package/dist/credentials.js +27 -18
- package/dist/d1.d.ts +130 -0
- package/dist/d1.js +290 -0
- package/dist/describe-config.d.ts +165 -0
- package/dist/describe-config.js +315 -0
- package/dist/described.js +106 -0
- package/dist/downstream-input-context.js +119 -0
- package/dist/downstream-input.js +323 -0
- package/dist/errors.d.ts +97 -20
- package/dist/errors.js +158 -80
- package/dist/execute.js +453 -305
- package/dist/executor-admission.d.ts +1 -0
- package/dist/executor-admission.js +11 -15
- package/dist/executor-contract.d.ts +20 -0
- package/dist/executor-contract.js +48 -0
- package/dist/executor-result.js +24 -9
- package/dist/executors/quickjs-child.js +3 -4
- package/dist/executors/quickjs-runtime.js +147 -59
- package/dist/executors/quickjs.js +29 -35
- package/dist/favicon.js +1 -2
- package/dist/fix-prompt.js +1 -3
- package/dist/guest-runtime.js +188 -0
- package/dist/guest-types.d.ts +176 -0
- package/dist/guest-types.js +1 -0
- package/dist/html-security.js +24 -0
- package/dist/identity.js +1 -3
- package/dist/inbound-credential.js +52 -0
- package/dist/index.d.ts +25 -257
- package/dist/index.js +65 -478
- package/dist/invocation-auth.js +69 -0
- package/dist/invocation.js +230 -73
- package/dist/json-schema.d.ts +1 -1
- package/dist/mcp-client-context.js +35 -0
- package/dist/mcp-result.js +11 -7
- package/dist/meta-output.js +76 -0
- package/dist/meta-tool-names.d.ts +2 -0
- package/dist/meta-tool-names.js +3 -0
- package/dist/meta-tools.js +285 -209
- package/dist/module-contracts.d.ts +8 -23
- package/dist/node.d.ts +0 -2
- package/dist/node.js +2 -2
- package/dist/oauth-callback-outcome.js +1 -3
- package/dist/oauth-handoff.js +117 -0
- package/dist/oauth-partition.js +17 -0
- package/dist/oauth-sealing.js +20 -0
- package/dist/operator-record.d.ts +137 -0
- package/dist/operator-record.js +420 -0
- package/dist/operator-ui/assets.js +31 -0
- package/dist/operator-ui/contract.d.ts +72 -0
- package/dist/operator-ui/contract.js +1 -0
- package/dist/operator-ui/fix-prompts.d.ts +18 -0
- package/dist/operator-ui/generated.js +5 -4
- package/dist/operator-ui/model.d.ts +12 -87
- package/dist/operator-ui/model.js +2 -9
- package/dist/operator-ui/setup-commands.js +1 -3
- package/dist/operator-ui/view.d.ts +323 -0
- package/dist/operator-ui/view.js +62 -189
- package/dist/page-styles.js +2 -3
- package/dist/program-source.js +14 -2
- package/dist/{exempt-writes.js → program-writes.js} +55 -18
- package/dist/provider.d.ts +142 -0
- package/dist/provider.js +187 -0
- package/dist/providers/_shared/google/result-size.js +57 -0
- package/dist/providers/_shared/google/service-account.d.ts +58 -0
- package/dist/providers/_shared/google/service-account.js +500 -0
- package/dist/providers/_shared/google/workspace.d.ts +276 -0
- package/dist/providers/_shared/google/workspace.js +518 -0
- package/dist/providers/basecamp/index.d.ts +43 -0
- package/dist/providers/basecamp/index.js +997 -0
- package/dist/providers/basecamp/skill.generated.js +9 -0
- package/dist/providers/breeze/index.d.ts +34 -0
- package/dist/providers/breeze/index.js +1446 -0
- package/dist/providers/breeze/skill.generated.js +9 -0
- package/dist/providers/ccb/index.d.ts +103 -0
- package/dist/providers/ccb/index.js +1725 -0
- package/dist/providers/ccb/skill.generated.js +9 -0
- package/dist/providers/{cloudflare.d.ts → cloudflare/index.d.ts} +8 -7
- package/dist/providers/{cloudflare.js → cloudflare/index.js} +171 -738
- package/dist/providers/cloudflare/skill.generated.js +10 -0
- package/dist/providers/docs/index.d.ts +54 -0
- package/dist/providers/docs/index.js +1237 -0
- package/dist/providers/docs/skill.generated.js +9 -0
- package/dist/providers/drive/index.d.ts +53 -0
- package/dist/providers/drive/index.js +1523 -0
- package/dist/providers/drive/skill.generated.js +9 -0
- package/dist/providers/forms/index.d.ts +54 -0
- package/dist/providers/forms/index.js +1217 -0
- package/dist/providers/forms/skill.generated.js +11 -0
- package/dist/providers/github/auth.d.ts +32 -0
- package/dist/providers/github/auth.js +361 -0
- package/dist/providers/github/hosted.js +218 -0
- package/dist/providers/github/index.d.ts +13 -0
- package/dist/providers/github/index.js +140 -0
- package/dist/providers/github/key.js +100 -0
- package/dist/providers/github/rest.js +321 -0
- package/dist/providers/github/scope.d.ts +29 -0
- package/dist/providers/github/scope.js +124 -0
- package/dist/providers/github/skill.generated.js +8 -0
- package/dist/providers/gmail/index.d.ts +51 -0
- package/dist/providers/gmail/index.js +1436 -0
- package/dist/providers/gmail/skill.generated.js +9 -0
- package/dist/providers/{linear.d.ts → linear/index.d.ts} +11 -14
- package/dist/providers/linear/index.js +352 -0
- package/dist/providers/linear/skill.generated.js +8 -0
- package/dist/providers/{mixpanel.d.ts → mixpanel/index.d.ts} +5 -10
- package/dist/providers/mixpanel/index.js +416 -0
- package/dist/providers/mixpanel/skill.generated.js +9 -0
- package/dist/providers/{notion.d.ts → notion/index.d.ts} +8 -8
- package/dist/providers/{notion.js → notion/index.js} +226 -239
- package/dist/providers/notion/skill.generated.js +10 -0
- package/dist/providers/overflow/index.d.ts +60 -0
- package/dist/providers/overflow/index.js +1535 -0
- package/dist/providers/overflow/skill.generated.js +8 -0
- package/dist/providers/planning-center/index.d.ts +59 -0
- package/dist/providers/planning-center/index.js +2199 -0
- package/dist/providers/planning-center/skill.generated.js +10 -0
- package/dist/providers/{revenuecat.d.ts → revenuecat/index.d.ts} +5 -10
- package/dist/providers/revenuecat/index.js +557 -0
- package/dist/providers/revenuecat/skill.generated.js +11 -0
- package/dist/providers/sheets/index.d.ts +54 -0
- package/dist/providers/sheets/index.js +1237 -0
- package/dist/providers/sheets/skill.generated.js +10 -0
- package/dist/providers/slides/index.d.ts +53 -0
- package/dist/providers/slides/index.js +2645 -0
- package/dist/providers/slides/skill.generated.js +9 -0
- package/dist/providers/{stripe.d.ts → stripe/index.d.ts} +5 -12
- package/dist/providers/stripe/index.js +266 -0
- package/dist/providers/stripe/skill.generated.js +11 -0
- package/dist/providers/tithely/index.d.ts +49 -0
- package/dist/providers/tithely/index.js +1003 -0
- package/dist/providers/tithely/skill.generated.js +8 -0
- package/dist/providers/{vercel.d.ts → vercel/index.d.ts} +8 -8
- package/dist/providers/vercel/index.js +1038 -0
- package/dist/providers/vercel/mcp-ownership.js +212 -0
- package/dist/providers/vercel/skill.generated.js +11 -0
- package/dist/registry.d.ts +108 -171
- package/dist/registry.js +513 -925
- package/dist/request-state.js +21 -0
- package/dist/resource-read.js +100 -0
- package/dist/result-shapes.js +17 -49
- package/dist/retired-toolkits.js +1 -1
- package/dist/routes/access-tokens.js +3 -6
- package/dist/routes/activity-context.js +21 -0
- package/dist/routes/activity-disclosure.js +40 -0
- package/dist/routes/activity.js +59 -21
- package/dist/routes/actor-labels.js +3 -50
- package/dist/routes/connect.js +221 -0
- package/dist/routes/credentials.js +15 -27
- package/dist/routes/mcp.js +356 -130
- package/dist/routes/oauth-client-metadata.js +15 -0
- package/dist/routes/oauth-management.js +45 -107
- package/dist/routes/oauth.js +136 -57
- package/dist/routes/operator.js +3 -3
- package/dist/routes/shared.d.ts +25 -64
- package/dist/routes/shared.js +160 -80
- package/dist/routes/skills.js +30 -0
- package/dist/routes/ui-config.js +225 -0
- package/dist/routes/ui-data.js +40 -35
- package/dist/routes/ui.js +66 -56
- package/dist/runtime/admission.js +4 -2
- package/dist/runtime/call-admission.js +3 -1
- package/dist/runtime/connector-scope.js +1 -4
- package/dist/runtime/run.js +10 -39
- package/dist/runtime/services.js +12 -117
- package/dist/runtime/shared-read.js +1 -3
- package/dist/runtime/storage.js +8 -1
- package/dist/sent-secrets.d.ts +52 -0
- package/dist/sent-secrets.js +474 -0
- package/dist/server.js +28 -71
- package/dist/skills.js +406 -174
- package/dist/sqlite.d.ts +48 -0
- package/dist/sqlite.js +166 -0
- package/dist/storage/keys.js +428 -0
- package/dist/storage/memory.js +7 -0
- package/dist/storage/sql.d.ts +66 -0
- package/dist/storage/sql.js +534 -0
- package/dist/timeout.js +4 -2
- package/dist/tool-name.js +17 -0
- package/dist/tool-safety.d.ts +9 -35
- package/dist/tool-safety.js +20 -40
- package/dist/types.d.ts +320 -54
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +7 -19
- package/dist/ui.js +76 -90
- package/dist/url-safety.js +3 -6
- package/dist/usage-guide.js +137 -0
- package/dist/validate.d.ts +7 -0
- package/dist/validate.js +309 -47
- package/dist/version.d.ts +1 -7
- package/dist/version.js +3 -7
- package/dist/worker.d.ts +11 -0
- package/dist/worker.js +434 -0
- package/documentation/architecture.md +665 -230
- package/documentation/auth.md +962 -458
- package/documentation/code-mode.md +501 -312
- package/documentation/meta-tools.md +449 -200
- package/documentation/operator-tests.md +93 -0
- package/documentation/provider-migration-0.29.md +60 -0
- package/examples/worker/AGENTS.md +34 -12
- package/examples/worker/README.md +286 -255
- package/examples/worker/kv-to-d1.wrangler.jsonc +26 -0
- package/examples/worker/scripts/copy-kv-to-d1.mjs +162 -0
- package/examples/worker/src/connecta.config.ts +151 -0
- package/examples/worker/src/index.ts +14 -197
- package/examples/worker/wrangler.jsonc +15 -35
- package/package.json +125 -35
- package/templates/node/.dockerignore +1 -2
- package/templates/node/.env.example +20 -21
- package/templates/node/AGENTS.md +21 -17
- package/templates/node/Dockerfile +3 -5
- package/templates/node/README.md +133 -58
- package/templates/node/docker-compose.yml +11 -12
- package/templates/node/package.json +4 -2
- package/templates/node/src/connecta.config.ts +119 -0
- package/templates/node/src/index.ts +9 -154
- package/templates/node/src/provision-token.ts +17 -0
- package/AGENTS.md +0 -170
- package/dist/artifacts/connector.d.ts +0 -58
- package/dist/artifacts/connector.js +0 -730
- package/dist/artifacts/document.js +0 -86
- package/dist/artifacts/guide.js +0 -140
- package/dist/artifacts/html-scan.js +0 -329
- package/dist/artifacts/json.js +0 -78
- package/dist/artifacts/kv-store.d.ts +0 -20
- package/dist/artifacts/kv-store.js +0 -140
- package/dist/artifacts/markdown.js +0 -478
- package/dist/artifacts/module.d.ts +0 -37
- package/dist/artifacts/module.js +0 -66
- package/dist/artifacts/operations.d.ts +0 -197
- package/dist/artifacts/operations.js +0 -1002
- package/dist/artifacts/refresh.d.ts +0 -55
- package/dist/artifacts/refresh.js +0 -236
- package/dist/artifacts/routes.js +0 -206
- package/dist/artifacts/types.d.ts +0 -214
- package/dist/artifacts/types.js +0 -22
- package/dist/artifacts/validate.d.ts +0 -62
- package/dist/artifacts/validate.js +0 -651
- package/dist/artifacts.d.ts +0 -6
- package/dist/artifacts.js +0 -9
- package/dist/auth/bearer.d.ts +0 -11
- package/dist/auth/bearer.js +0 -50
- package/dist/providers/linear.js +0 -217
- package/dist/providers/mixpanel.js +0 -247
- package/dist/providers/revenuecat.js +0 -317
- package/dist/providers/stripe.js +0 -253
- package/dist/providers/vercel.js +0 -1253
- package/dist/storage/file.d.ts +0 -15
- package/dist/storage/file.js +0 -455
- package/ethos.md +0 -93
- package/examples/worker/src/cloudflare-kv.ts +0 -43
- package/examples/worker/src/d1-activity-row.ts +0 -155
- package/examples/worker/src/d1-activity.ts +0 -147
- package/examples/worker/src/d1-storage.ts +0 -138
- package/examples/worker/src/r2-artifact-blobs.ts +0 -29
- package/templates/node/src/file-activity.ts +0 -182
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
# Code mode — the guest API contract
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
names the reason; a third executor is implementable from this document alone.
|
|
12
|
-
[`ethos.md`](../ethos.md) carries the verdicts behind the shape,
|
|
3
|
+
The `execute_code` contract: capabilities, results, failures, retries, limits,
|
|
4
|
+
and activity. Specified in prose first, implemented second.
|
|
5
|
+
|
|
6
|
+
Two executors implement it: QuickJS in a Node child process and `workerExecutor()`
|
|
7
|
+
from `@zackbart/connecta/worker` around upstream `DynamicWorkerExecutor` on Workers.
|
|
8
|
+
Divergence is a bug unless explained in [Executor exceptions](#executor-exceptions);
|
|
9
|
+
a third executor is implementable from this document alone.
|
|
10
|
+
[`PRINCIPLES.md`](https://github.com/zackbart/connecta/blob/main/PRINCIPLES.md) states the invariants,
|
|
13
11
|
[`meta-tools.md`](./meta-tools.md) owns the top-level tool contract, and clause
|
|
14
12
|
identifiers (`A1`, `E3`, …) are stable and cited by [Verification](#verification).
|
|
15
13
|
|
|
16
14
|
## Deploy-time capability
|
|
17
15
|
|
|
18
16
|
The `executor` passed to `createConnecta()` is required. `tools/list` is exactly
|
|
19
|
-
|
|
20
|
-
`authorize_connector
|
|
17
|
+
six — `execute_code`, `search_tools`, `call_tool`, `call_destructive_tool`,
|
|
18
|
+
`authorize_connector` and `skills`. Construction fails when the
|
|
21
19
|
executor is missing, and the removed `surface` option is rejected rather than
|
|
22
20
|
ignored ([#273](https://github.com/zackbart/connecta/issues/273)), as are the
|
|
23
21
|
pause-only `execute.resumableWrites` and `execute.pausedRunTtlSeconds`
|
|
@@ -33,26 +31,37 @@ import { quickJsExecutor } from "@zackbart/connecta/quickjs";
|
|
|
33
31
|
createConnecta({ executor: quickJsExecutor() /* connectors, auth, storage… */ });
|
|
34
32
|
```
|
|
35
33
|
|
|
36
|
-
`quickJsExecutor()` runs each program in a disposable child
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
[Node template](../templates/node/README.md) carries the complete setup.
|
|
34
|
+
`quickJsExecutor()` runs each program in a disposable child process, with CPU,
|
|
35
|
+
wall-time, memory, stack, queue, result, log, and IPC bounds on the executor.
|
|
36
|
+
Keep `@zackbart/connecta/quickjs` external in server bundles so the child entry
|
|
37
|
+
stays on disk. The [Node template](../templates/node/README.md) has the full setup.
|
|
41
38
|
|
|
42
|
-
On
|
|
43
|
-
Workers require the Workers Paid plan:
|
|
39
|
+
On Workers the Worker Loader is the sandbox; Dynamic Workers require the Paid plan:
|
|
44
40
|
|
|
45
41
|
```ts
|
|
46
|
-
|
|
42
|
+
import { workerExecutor } from "@zackbart/connecta/worker";
|
|
43
|
+
|
|
44
|
+
createConnecta({ executor: workerExecutor({ loader: env.LOADER }) });
|
|
47
45
|
```
|
|
48
46
|
|
|
49
|
-
The
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
The adapter uses only `loader` and an optional `timeout`. Its admission defaults
|
|
48
|
+
are two active runs, eight queued runs, and a five-second queue deadline, settable
|
|
49
|
+
through `admission`. Lease release disposes RPC and loader handles independently
|
|
50
|
+
of guest settlement. `bindings`, `modules`, or `globalOutbound` violate `P2`.
|
|
51
|
+
The [Worker example](../examples/worker/README.md#code-mode) has the full setup.
|
|
52
|
+
|
|
53
|
+
Replace `import { DynamicWorkerExecutor } from "@cloudflare/codemode";` with
|
|
54
|
+
`import { workerExecutor } from "@zackbart/connecta/worker";` and use the wiring above.
|
|
55
|
+
Keep the peer. Unbranded executors throw, including bundled upstream copies.
|
|
56
|
+
Shipped executors carry a non-enumerable `Symbol.for("connecta.executor")` version/lifecycle brand.
|
|
57
|
+
Custom sandboxes import `customExecutor` from `@zackbart/connecta`, then configure
|
|
58
|
+
`executor: customExecutor(myExecutor, { lifecycle: "self-managed" })`. They own guest termination
|
|
59
|
+
and cleanup at budget exhaustion, cancellation, and deadlines; the wrapper only delegates methods.
|
|
52
60
|
|
|
53
61
|
## What an executor must implement
|
|
54
62
|
|
|
55
|
-
The
|
|
63
|
+
The Promise provider/result seam lives in `src/types.ts`. Custom implementations
|
|
64
|
+
also need the lifecycle wrapper above; structural compatibility alone is insufficient.
|
|
56
65
|
|
|
57
66
|
```ts
|
|
58
67
|
interface Executor {
|
|
@@ -70,6 +79,8 @@ interface ExecutorProvider {
|
|
|
70
79
|
interface ExecuteResult {
|
|
71
80
|
result: unknown; // the program's resolved value
|
|
72
81
|
error?: string; // set instead of result when the run failed
|
|
82
|
+
failure?: { name: string; line?: number; call?: CallErrorDetails;
|
|
83
|
+
timeout?: { elapsedMs: number; deadlineMs: number } };
|
|
73
84
|
logs?: string[]; // captured console output, in call order
|
|
74
85
|
}
|
|
75
86
|
```
|
|
@@ -78,34 +89,38 @@ Connecta passes exactly one provider, named `connecta`. An executor must:
|
|
|
78
89
|
|
|
79
90
|
1. **Expose each provider as a guest global** whose properties are its `fns`,
|
|
80
91
|
called with the program's arguments and awaited. Connecta supplies `search`,
|
|
81
|
-
`describe`, `call`, and `emit`.
|
|
92
|
+
`describe`, `call`, `read`, `result`, `skill`, and `emit`.
|
|
82
93
|
2. **Evaluate `prelude` after the provider globals exist and before the
|
|
83
|
-
program.** It is trusted host code
|
|
84
|
-
|
|
94
|
+
program.** It is trusted host code that installs the immutable namespace
|
|
95
|
+
and waits for emission acknowledgements. Capture runner intrinsics first;
|
|
96
|
+
privileged initialization must be single-use.
|
|
85
97
|
3. **Marshal values as JSON** both directions (`P3`), and reject a host call
|
|
86
98
|
whose function is not an own property of `fns` — the guest can ask for
|
|
87
99
|
inherited members too.
|
|
88
|
-
4. **Return, never throw, for a failed program
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
100
|
+
4. **Return, never throw, for a failed program.** Set `error` and leave
|
|
101
|
+
`result` undefined. Rebuild a rejected host `InvocationFailure` as a guest
|
|
102
|
+
Error with `code`, `retryable`, and `details`, and retain its identity in
|
|
103
|
+
executor-owned state. If that same Error escapes the program, return its
|
|
104
|
+
typed details in `failure.call`. A wrapped or copied Error is `program_error`.
|
|
105
|
+
Construct outcomes through the host-owned RPC return or QuickJS host bridge,
|
|
106
|
+
never by parsing guest stdout, prints, returned values, or thrown look-alikes.
|
|
107
|
+
No secret held in the guest realm authenticates anything. Guest module
|
|
108
|
+
specifiers must not resolve runner internals, including dynamic imports.
|
|
109
|
+
For compilation failures, return `failure: { name, line? }`. For a sandbox
|
|
110
|
+
timeout, add `failure.timeout: { elapsedMs, deadlineMs }`.
|
|
92
111
|
5. **Capture `console.log`, `console.warn`, and `console.error`** into `logs` in
|
|
93
112
|
call order (`R5`), bounding what it retains.
|
|
94
|
-
6. **Bound the guest**: wall clock, memory, stack, and CPU (`L3`, `L5`),
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
optional `name` — else a class's constructor name, which a minifier may rewrite
|
|
106
|
-
— is the executor name `/health` and `connecta doctor` report.
|
|
107
|
-
[Emitted output](#emitted-output) asks nothing of an executor: `connecta.emit`
|
|
108
|
-
is just another provider function (`M8`).
|
|
113
|
+
6. **Bound the guest**: wall clock, memory, stack, and CPU (`L3`, `L5`), within
|
|
114
|
+
`P2`/`X5`. Settle `execute()` on your own deadline; connecta stops waiting
|
|
115
|
+
at `execute.watchdogMs` and reports the sandbox unresponsive (`L3`).
|
|
116
|
+
7. **Grant no ambient authority.** Never use `eval` or `node:vm`: sandboxing
|
|
117
|
+
supplements connecta's boundary; every capability arrives through `fns`.
|
|
118
|
+
|
|
119
|
+
Optional `AdmittingExecutor.acquire()` returns a once-executed lease for bounded
|
|
120
|
+
admission (`L7`); otherwise connecta uses `withExecutorAdmission`. `close()` handles
|
|
121
|
+
shutdown. `/health` and `connecta doctor` report `name`, falling back to the
|
|
122
|
+
constructor name, which minifiers may rewrite. [Emission](#emitted-output) is
|
|
123
|
+
another provider function (`M8`).
|
|
109
124
|
|
|
110
125
|
## The program
|
|
111
126
|
|
|
@@ -120,7 +135,7 @@ statements, and bare statement bodies are outside host recovery. QuickJS may
|
|
|
120
135
|
wrap a bare body when driven directly; that is outside the portable contract.
|
|
121
136
|
|
|
122
137
|
**P2.** The only capabilities in the contract are `connecta.search`,
|
|
123
|
-
`connecta.describe`, `connecta.call`, `connecta.emit`, and `console.log` /
|
|
138
|
+
`connecta.describe`, `connecta.call`, `connecta.read`, `connecta.result`, `connecta.skill`, `connecta.emit`, and `console.log` /
|
|
124
139
|
`console.warn` / `console.error`, captured and returned. Anything else a runtime
|
|
125
140
|
exposes is outside the portable contract and must not be used. QuickJS grants
|
|
126
141
|
none of it. A loader-only Dynamic Worker denies external egress and filesystem
|
|
@@ -163,10 +178,10 @@ belonged to shortcut dispatch and stay retired; nothing reuses those ids.
|
|
|
163
178
|
|
|
164
179
|
## The surface
|
|
165
180
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
fails
|
|
181
|
+
Seven functions: `search`, `describe`, `call`, `read`, `result`, `skill`, and `emit`.
|
|
182
|
+
All return awaitable values; emission also works without `await`. The namespace
|
|
183
|
+
has no inherited members. Unknown properties are undefined, and calling them
|
|
184
|
+
fails as a guest `TypeError`. The host also dispatches only own members of `fns`.
|
|
170
185
|
|
|
171
186
|
### connecta.search
|
|
172
187
|
|
|
@@ -178,15 +193,17 @@ const page = await connecta.search({
|
|
|
178
193
|
limit: 8, // 1–100, default 8
|
|
179
194
|
offset: 0,
|
|
180
195
|
fullDescriptions: false,
|
|
181
|
-
includeSchemas: "
|
|
196
|
+
includeSchemas: "json", // default; or "compact" / "typescript"
|
|
182
197
|
includeSchemaKeys: true, // default true in code mode
|
|
183
198
|
});
|
|
184
199
|
```
|
|
185
200
|
|
|
186
|
-
**S1.** Returns
|
|
187
|
-
`
|
|
188
|
-
|
|
189
|
-
`
|
|
201
|
+
**S1.** Returns the same flat page as top-level `search_tools`:
|
|
202
|
+
`{ catalogErrors, tools, total, offset, limit, hasMore }`, plus `nextOffset`
|
|
203
|
+
when more remains and `matchMode: "partial"` when no tool matched every term.
|
|
204
|
+
Read `catalogErrors` and any `absence` before selecting a tool. Catalog failures
|
|
205
|
+
carry recovery actions at the top of the page; an absent service returns no
|
|
206
|
+
lookalikes. Both paths use only the caller's endpoint/pool and grants. Ranking is
|
|
190
207
|
[lexical discovery](./meta-tools.md#lexical-discovery)'s, and rows expose
|
|
191
208
|
neither lexical scores nor per-result coverage. An empty or whitespace-only
|
|
192
209
|
query browses; non-empty input with no ASCII lexical terms returns no tools plus
|
|
@@ -201,16 +218,20 @@ bounded `guideSummary`, requested or not. An output shape learned under `S9`
|
|
|
201
218
|
also carries `outputSchemaSource: "observed"`; provider declarations carry no
|
|
202
219
|
source marker.
|
|
203
220
|
|
|
221
|
+
Programs default to `includeSchemas: "json"`: `inputSchema` and available
|
|
222
|
+
`outputSchema` are JSON Schema values, labeled `schemaFormat: "json"`.
|
|
223
|
+
Explicit `includeSchemas: "compact"` returns strings labeled
|
|
224
|
+
`schemaFormat: "text"`; TypeScript signatures carry the same text label.
|
|
204
225
|
Compact shapes omit property prose and put required fields first, under these
|
|
205
226
|
bounds:
|
|
206
227
|
|
|
207
|
-
| Bound
|
|
208
|
-
|
|
|
209
|
-
| `execute_code` source | ≤ 65,536 UTF-8 bytes, checked before executor admission; over-limit source returns `invalid_args`
|
|
210
|
-
| Rendered shape
|
|
211
|
-
| Work per shape
|
|
212
|
-
| Each enum node
|
|
213
|
-
| Resolved `$ref` text
|
|
228
|
+
| Bound | Value |
|
|
229
|
+
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
230
|
+
| `execute_code` source | ≤ 65,536 UTF-8 bytes, checked before executor admission; over-limit source returns `invalid_args` |
|
|
231
|
+
| Rendered shape | 1,024 UTF-8 bytes each |
|
|
232
|
+
| Work per shape | 2,000 visits across schema nodes, property and required names, literal values, any constraint-free retry, and its key-only fallback |
|
|
233
|
+
| Each enum node | 256 of those bytes |
|
|
234
|
+
| Resolved `$ref` text | reused within one walk |
|
|
214
235
|
|
|
215
236
|
About three near-cap enum nodes therefore coexist while the final quarter stays
|
|
216
237
|
for surrounding syntax, and above 1,024 bytes the global fallback applies.
|
|
@@ -229,7 +250,7 @@ use `format: "json"` or JSON search.
|
|
|
229
250
|
`includeSchemas: "typescript"` spends those same bounds on a different
|
|
230
251
|
rendering: one `signature` string in place of `inputSchema` and
|
|
231
252
|
`outputSchema`, reading `(args: { runId: number }) => Promise<Run>` for the
|
|
232
|
-
value `connecta.call` returns. It is documentation for the program's author —
|
|
253
|
+
`data` value `connecta.call` returns. It is documentation for the program's author —
|
|
233
254
|
the program itself is still JavaScript, and a type annotation copied into it
|
|
234
255
|
is a syntax error (`P5`). Truncation keeps compact's flags and
|
|
235
256
|
turns what compact would print as a name or raw JSON into a marked `unknown`;
|
|
@@ -239,14 +260,10 @@ its degradation rules are specified once, under
|
|
|
239
260
|
signature is byte-identical to the one `search_tools` returns.
|
|
240
261
|
|
|
241
262
|
**S1a.** `connector` loads only the named catalog; omit it only when the
|
|
242
|
-
integration is ambiguous
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
whose calls a program has refused (`E4`) unless config exempts them (`W12`),
|
|
247
|
-
which a row marks with `approval: "exempt"` without moving it out of that
|
|
248
|
-
class; omitted or `"all"` preserves the complete catalog. These filters grant
|
|
249
|
-
no authority and change no admission decision.
|
|
263
|
+
integration is ambiguous. `safety: "readOnly"` selects stored read verdicts;
|
|
264
|
+
`"approvalRequired"` selects stored write verdicts; omitted or `"all"` selects
|
|
265
|
+
both. Search and describe rows carry `classification`. These filters grant no
|
|
266
|
+
authority and change no pool trust or call admission decision.
|
|
250
267
|
|
|
251
268
|
**S2.** A requested object schema carries `inputKeys`, `requiredInputKeys`
|
|
252
269
|
(declared properties only), and `outputKeys`: the names the rendered schema
|
|
@@ -278,12 +295,14 @@ hint and the stable `code`, `retryable`, and `details` fields (`E1`).
|
|
|
278
295
|
const one = await connecta.describe({ address: "ci.get_run" });
|
|
279
296
|
const many = await connecta.describe({
|
|
280
297
|
addresses: ["ci.get_run", "ci.get_job_logs"], // ≤ 100
|
|
281
|
-
format: "
|
|
298
|
+
format: "json", // default; or "compact" / "typescript"
|
|
282
299
|
fullDescriptions: false,
|
|
283
300
|
});
|
|
284
301
|
```
|
|
285
302
|
|
|
286
|
-
**S4.**
|
|
303
|
+
**S4.** Defaults to JSON Schema values with `schemaFormat: "json"`.
|
|
304
|
+
Explicit compact schemas and TypeScript signatures have `schemaFormat: "text"`.
|
|
305
|
+
Returns `{ tools }` in order, one entry per address; one bad address
|
|
287
306
|
never fails the whole call. An unknown address or failed catalog returns `error`
|
|
288
307
|
plus typed `errorDetails` (`code`, `message`, `retryable`). Misses carry a
|
|
289
308
|
route-aware `nextAction`, a close miss may add three canonical `suggestions`,
|
|
@@ -302,15 +321,22 @@ says so inside its `Promise<…>`.
|
|
|
302
321
|
|
|
303
322
|
### connecta.call
|
|
304
323
|
|
|
324
|
+
The published `GuestApi` type describes the supplied global for editors.
|
|
325
|
+
The executable usage guide checks its API notation against those declarations;
|
|
326
|
+
programs still use plain JavaScript.
|
|
327
|
+
|
|
305
328
|
```js
|
|
306
|
-
const run = await connecta.call("ci.get_run", { runId: 42 });
|
|
329
|
+
const { data: run, format } = await connecta.call("ci.get_run", { runId: 42 });
|
|
330
|
+
// Equivalent: connecta.call({ address: "ci.get_run", args: { runId: 42 }, timeoutMs: 30_000 })
|
|
307
331
|
```
|
|
308
332
|
|
|
309
|
-
**S5.** Takes a canonical address
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
is
|
|
333
|
+
**S5.** Takes a canonical address, optional arguments, and optional
|
|
334
|
+
`{ timeoutMs }`; the object form is `{ address, args?, timeoutMs? }`. A malformed
|
|
335
|
+
signature fails with `invalid_args` and both exact signatures, before discovery.
|
|
336
|
+
Returns `{ data, format: "json" | "text" }`. MCP `toolResult` or
|
|
337
|
+
`structuredContent` is JSON; all-text content is JSON when it parses, otherwise
|
|
338
|
+
text. API string values are text, other API values are JSON. Check `format`
|
|
339
|
+
before treating `data` as an object. A downstream `isError` throws.
|
|
314
340
|
|
|
315
341
|
**S6.** Every call goes through the same catalog, fail-closed read-only
|
|
316
342
|
predicate, admission, credential containment, timeout classification, health
|
|
@@ -320,6 +346,29 @@ program does decides it. The sandbox is an additional containment layer, not a
|
|
|
320
346
|
second implementation of the boundary, and nothing a program does widens what
|
|
321
347
|
it can reach.
|
|
322
348
|
|
|
349
|
+
### connecta.result and connecta.skill
|
|
350
|
+
|
|
351
|
+
`await connecta.result(id, { offset?, maxBytes? })` reads a stashed direct-call
|
|
352
|
+
result bound to the admitted subject, principal, endpoint/pool, request origin,
|
|
353
|
+
connector, and tool. It returns
|
|
354
|
+
`{ resultId, offset, bytes, totalBytes, hasMore, nextOffset?, format: "text", text }`.
|
|
355
|
+
Offsets and sizes are UTF-8 bytes; the page cap is the original call's inline cap.
|
|
356
|
+
Follow `nextOffset`, reassemble inside the program, and return a reduced value.
|
|
357
|
+
Before returning a page, the host rechecks current authentication, connector/tool
|
|
358
|
+
grants, pool membership, and endpoint trust against both the original and current
|
|
359
|
+
tool classification. A read-only endpoint cannot page a write result, so a
|
|
360
|
+
direct write there returns an inline truncation notice without stashing the
|
|
361
|
+
result or advertising a paging action. Binding
|
|
362
|
+
mismatches, revoked access, and old entries without bindings are `not_found`, as
|
|
363
|
+
are unknown or expired ids; a storage failure is `unavailable`. IDs are random UUIDs.
|
|
364
|
+
The `get_result` meta-tool is removed.
|
|
365
|
+
|
|
366
|
+
`await connecta.skill(name)` resolves the same URI or compatibility name as
|
|
367
|
+
top-level `skills`, within the admitted connector view. It reads the registry
|
|
368
|
+
behind native `skills/get` and `resources/read`, including opted-in downstream
|
|
369
|
+
skills. It returns
|
|
370
|
+
`{ name, format: "text", text }`; an unknown name is `not_found`.
|
|
371
|
+
|
|
323
372
|
### Parallel calls
|
|
324
373
|
|
|
325
374
|
**S7.** Use `Promise.all` for independent calls when any failure should fail the
|
|
@@ -331,7 +380,7 @@ as sequential calls. There is no separate batch size or result contract.
|
|
|
331
380
|
`details`. Project those fields before returning — an `Error` object is not a
|
|
332
381
|
JSON result contract.
|
|
333
382
|
|
|
334
|
-
**S9.** A successful
|
|
383
|
+
**S9.** A successful call classified as a read whose provider declared no
|
|
335
384
|
`outputSchema` passively learns one from the unwrapped result. The observation
|
|
336
385
|
keeps field names and broad JSON types only — no arguments, scalar values, raw
|
|
337
386
|
results, code, credentials, or errors — and property names may be user-authored.
|
|
@@ -350,6 +399,69 @@ successful call. No discovery read, timer, refresh, background job, or storage
|
|
|
350
399
|
adapter executes or persists work for this cache: the result-sampling refusal in
|
|
351
400
|
[#282](https://github.com/zackbart/connecta/issues/282) stands.
|
|
352
401
|
|
|
402
|
+
### connecta.read
|
|
403
|
+
|
|
404
|
+
```js
|
|
405
|
+
const resource = await connecta.read(
|
|
406
|
+
"resource://docs/" + encodeURIComponent("docs://manual/start"),
|
|
407
|
+
);
|
|
408
|
+
return resource.contents.map(content => content.text);
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
**S10.** Reads a downstream resource through a configured connector that
|
|
412
|
+
implements `readResource`. The routing URI is exactly
|
|
413
|
+
`resource://<connectorId>/<encodeURIComponent(downstreamUri)>`, at most 8,192
|
|
414
|
+
UTF-8 bytes. The downstream URI must have a scheme and no control characters.
|
|
415
|
+
Encode it once, including any path, query and fragment. Bare URLs, malformed
|
|
416
|
+
encoding, routing userinfo, ports and extra routing query or fragment fields
|
|
417
|
+
fail with `invalid_args`. Remote MCP connectors first load the complete,
|
|
418
|
+
paginated resources and URI-template inventories through the same host-auth
|
|
419
|
+
partitioned catalog cache. The decoded URI must exactly match an advertised
|
|
420
|
+
resource or match an advertised URI template. An unmatched URI fails with a
|
|
421
|
+
fixed `not_found` message before any downstream read. Template matching keeps
|
|
422
|
+
the scheme and authority fixed and supports bounded RFC 6570 scalar and list
|
|
423
|
+
expansions, including prefix modifiers and safe multi-segment `{+path}` and
|
|
424
|
+
`{/p*}` paths. Variables cannot supply authority, backslashes, dot segments,
|
|
425
|
+
a scheme change, query delimiters, controls or Unicode format characters,
|
|
426
|
+
including through repeated percent encoding. Initial percent encoding and
|
|
427
|
+
UTF-8 decoding stay strict. Later decoding layers preserve literal percent
|
|
428
|
+
signs produced by `%25` while checking every remaining `%HH` escape. The
|
|
429
|
+
matcher scans forward to the
|
|
430
|
+
leftmost following literal without backtracking. Adjacent expressions and
|
|
431
|
+
literals that the preceding expression can contain are refused with
|
|
432
|
+
`resource_template_ambiguous`. Matching all templates is capped at 262144
|
|
433
|
+
combined template and URI characters per read, with
|
|
434
|
+
`resource_match_budget_exceeded` beyond that bound. Operator status retains
|
|
435
|
+
each typed refusal once, without URI or template text. Mixed exploded
|
|
436
|
+
composites remain unsupported.
|
|
437
|
+
Connecta passes an admitted decoded URI as an opaque MCP `resources/read`
|
|
438
|
+
argument to the configured endpoint. It never fetches that
|
|
439
|
+
URI or creates a connector from it.
|
|
440
|
+
|
|
441
|
+
Resources are protocol reads in both `read-only` and `trusted` pools. A read
|
|
442
|
+
requires a grant to the whole connector through the endpoint/pool and identity
|
|
443
|
+
intersection. Exact-tool grants, including guarded grants, authorize no
|
|
444
|
+
resources. An absent, hidden, tool-restricted or resource-incapable connector
|
|
445
|
+
fails with `unknown_address`. The URI and extra arguments cannot select a
|
|
446
|
+
different credential owner or downstream subject. Personal credentials come
|
|
447
|
+
from the admitted principal, just as they do for tool calls.
|
|
448
|
+
|
|
449
|
+
The return is the downstream JSON `{ contents }` result, with text or base64
|
|
450
|
+
blob entries and available metadata. It is not unwrapped or JSON-parsed.
|
|
451
|
+
Every read spends one shared host call and uses the connector's call admission
|
|
452
|
+
with `toolName: "resources/read"` and `args: { uri: downstreamUri }`. One deadline
|
|
453
|
+
covers admission and dispatch; cancellation ends the wait and releases its
|
|
454
|
+
permit. Reads share the execution's downstream request scope. They make one
|
|
455
|
+
attempt, bypass response caching, and never start authorization. A downstream
|
|
456
|
+
resource miss is `not_found`; a mid-call input request is
|
|
457
|
+
`input_required_unsupported`. Other failures use the existing typed error
|
|
458
|
+
contract, including credential recovery. Values and failures cross the same
|
|
459
|
+
credential redaction boundary as `call`. Diagnostics use the fixed operation
|
|
460
|
+
name `read`; resource URIs and bodies enter no activity or diagnostic record.
|
|
461
|
+
This function exposes no resource listing, template discovery, subscriptions
|
|
462
|
+
or upward proxy to programs. Native upward skill resources are separate
|
|
463
|
+
[Phase 3](https://github.com/zackbart/connecta/issues/707) work.
|
|
464
|
+
|
|
353
465
|
### connecta.emit
|
|
354
466
|
|
|
355
467
|
```js
|
|
@@ -362,24 +474,24 @@ clauses are [Emitted output](#emitted-output) (`M1`–`M10`).
|
|
|
362
474
|
## Errors
|
|
363
475
|
|
|
364
476
|
**E1.** There are three error channels. Connecta failures are typed whether
|
|
365
|
-
caught or uncaught.
|
|
477
|
+
caught or uncaught. Host-call budget exhaustion ends the host run and blocks host
|
|
478
|
+
access (`L4`); Workers guest computation may continue briefly until teardown (`X3`).
|
|
366
479
|
|
|
367
|
-
| Channel
|
|
368
|
-
|
|
|
369
|
-
| A caught Connecta host failure
|
|
370
|
-
| An uncaught **tool or discovery** failure, as the model sees it | `{ error: { code, message, retryable, … } }` with `isError` | yes
|
|
371
|
-
| Program or execution failure (`E5`, `E6`, a bridge bound in `L6`)
|
|
480
|
+
| Channel | Shape | Typed? |
|
|
481
|
+
| ------------------------------------------------------------------------- | ----------------------------------------------------------- | ------ |
|
|
482
|
+
| A caught Connecta host failure | `Error` with `message`, `code`, `retryable`, and `details` | yes |
|
|
483
|
+
| An uncaught **tool, resource or discovery** failure, as the model sees it | `{ error: { code, message, retryable, … } }` with `isError` | yes |
|
|
484
|
+
| Program or execution failure (`E5`, `E6`, a bridge bound in `L6`) | `{ error: { code, message, retryable, details? } }` | yes |
|
|
372
485
|
|
|
373
|
-
Both executor bridges
|
|
374
|
-
|
|
375
|
-
authenticated frame (`X11`). `message` stays human text, capped at 2,000
|
|
486
|
+
Both executor bridges rebuild typed host rejections as guest Errors and retain
|
|
487
|
+
their identity in executor-owned state (`X11`). `message` stays human text, capped at 2,000
|
|
376
488
|
JSON-serialized characters including quotes and an `…` marker when clipped.
|
|
377
489
|
`code` and `retryable` are the stable branch fields; `details` carries the host
|
|
378
490
|
classification and fits 3,700 serialized characters. Optional recovery metadata
|
|
379
491
|
that would exceed that bound is omitted whole, preserving `code`, `message`,
|
|
380
492
|
`retryable`, and `retryAfterMs`, because a clipped recovery address or argument
|
|
381
|
-
describes a different call. This covers `call`, `search`, `describe`, `emit`, and
|
|
382
|
-
|
|
493
|
+
describes a different call. This covers `call`, `read`, `search`, `describe`, `result`, `skill`, `emit`, and
|
|
494
|
+
write and emitted-output budgets. Program-authored errors use `program_error`; code must never
|
|
383
495
|
parse error prose. An `unavailable` classification may add `details.host`, an
|
|
384
496
|
HTTP(S) origin of at most 253 UTF-8 bytes, and `details.code`, a validated
|
|
385
497
|
network errno, undici transport code, or `timeout` of at most 32 bytes; neither
|
|
@@ -389,26 +501,27 @@ enters activity.
|
|
|
389
501
|
may do. A provider maps each downstream failure to the code that tells the
|
|
390
502
|
caller what to do next, and never invents a cause it was not told.
|
|
391
503
|
|
|
392
|
-
| Code
|
|
393
|
-
|
|
|
394
|
-
| `unknown_address`
|
|
395
|
-
| `unknown_tool`
|
|
396
|
-
| `destructive_tool_requires_approval` |
|
|
397
|
-
| `auth_required`
|
|
398
|
-
| `invalid_args`
|
|
399
|
-
| `not_found`
|
|
400
|
-
| `conflict`
|
|
401
|
-
| `input_required_unsupported`
|
|
402
|
-
| `rate_limited`
|
|
403
|
-
| `unavailable`
|
|
404
|
-
| `timeout`
|
|
405
|
-
| `
|
|
406
|
-
| `
|
|
407
|
-
| `
|
|
408
|
-
| `
|
|
409
|
-
| `
|
|
410
|
-
| `
|
|
411
|
-
| `
|
|
504
|
+
| Code | Raised when | `retryable` |
|
|
505
|
+
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
|
|
506
|
+
| `unknown_address` | no visible connector owns the tool address or grants the resource reader | false |
|
|
507
|
+
| `unknown_tool` | the connector has no such tool | false |
|
|
508
|
+
| `destructive_tool_requires_approval` | a program in a read-only pool attempted a write (`E4`) | false |
|
|
509
|
+
| `auth_required` | the credential is missing, expired, or rejected | false |
|
|
510
|
+
| `invalid_args` | arguments or discovery bounds were rejected | false |
|
|
511
|
+
| `not_found` | the downstream answered and the resource is not there — the one code that says skip this id rather than stop, raised only where the provider tells absence from a permission gap | false |
|
|
512
|
+
| `conflict` | the write named a base version someone else already moved past; nothing changed. `details.current` says where things stand (at most 20 whole-number entries) — re-read, reapply, retry with that base | false |
|
|
513
|
+
| `input_required_unsupported` | a downstream asked for input; use `nextAction` for the equivalent direct call | false |
|
|
514
|
+
| `rate_limited` | the downstream reported a rate limit | true |
|
|
515
|
+
| `unavailable` | the downstream is down or unreachable; optional sanitized `details.host` and `details.code` describe the transport failure without paths, queries, credentials, or provider prose | true |
|
|
516
|
+
| `timeout` | a call or sandbox deadline expired; details name operation, stage, elapsedMs, and deadlineMs | per operation |
|
|
517
|
+
| `program_error` | guest JavaScript failed; `details.name`, `line`, and a fixed repair hint describe it | false |
|
|
518
|
+
| `cancelled` | the run ended while this call was in flight (`E5`) | false |
|
|
519
|
+
| `connector_call_failed` | anything else the connector threw | per message |
|
|
520
|
+
| `catalog_lookup_failed` | the connector's catalog could not be loaded | per cause |
|
|
521
|
+
| `result_processing_failed` | the result could not be prepared | per message |
|
|
522
|
+
| `result_too_large` | a discovery response exceeded its byte bound | false |
|
|
523
|
+
| `budget_exceeded` | the run exhausted a host-call, write, or emitted-output budget | false |
|
|
524
|
+
| `write_outcome_unknown` | a trusted-pool write was sent and no answer came back; it is never sent again (`W9`) | false |
|
|
412
525
|
|
|
413
526
|
**E3.** `auth_required` carries the same recovery envelope as `call_tool`:
|
|
414
527
|
`connector`, `operation`, `recovery` (`oauth`, `operator_config`, or
|
|
@@ -416,8 +529,8 @@ caller what to do next, and never invents a cause it was not told.
|
|
|
416
529
|
sentence. A program cannot recover credentials — only an operator can — so stop
|
|
417
530
|
and let the failure reach the model.
|
|
418
531
|
|
|
419
|
-
**E4.**
|
|
420
|
-
program unless
|
|
532
|
+
**E4.** A tool classified as a write never runs in a
|
|
533
|
+
program unless the pool is trusted (`W12`). It is refused with
|
|
421
534
|
`destructive_tool_requires_approval` before validation and before anything is
|
|
422
535
|
sent, `nextAction` carrying its canonical address to `call_destructive_tool`
|
|
423
536
|
plus the original arguments when they fit the 512-byte echo budget — whole or
|
|
@@ -426,7 +539,7 @@ call is the approval, and the only one: generated code can neither mint the
|
|
|
426
539
|
capability nor approve its own write, and the model's short `reason` grants no
|
|
427
540
|
authority and never goes downstream.
|
|
428
541
|
|
|
429
|
-
**E5.** Failures of the
|
|
542
|
+
**E5.** Failures of the _execution_, not of a call, never appear inside the
|
|
430
543
|
guest: admission rejection (`executor_overloaded`, retryable, with
|
|
431
544
|
`retryAfterMs`), cancellation (`executor_cancelled`), shutdown
|
|
432
545
|
(`executor_closed`), deadline expiry, an executor that never settles (`L3`),
|
|
@@ -436,19 +549,33 @@ is cancelled fails with `cancelled`, catchable on the way out but never worth
|
|
|
436
549
|
acting on (`Y3`). When shutdown tears down a program that had already started,
|
|
437
550
|
accepted blocks are reported as discarded under `M4`; a failure before execution
|
|
438
551
|
started carries no discard fields. A returned `error` field is a failure even
|
|
439
|
-
when empty
|
|
440
|
-
`Error: Execution failed without an error message.`
|
|
441
|
-
|
|
442
|
-
**E6.**
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
552
|
+
when empty. An empty string reports `program_error` with
|
|
553
|
+
`Program Error: Execution failed without an error message.`
|
|
554
|
+
|
|
555
|
+
**E6.** A guest `TypeError`, `ReferenceError`, syntax error, invented API, or
|
|
556
|
+
program-authored throw is `program_error`. `details.name` is a bounded engine
|
|
557
|
+
error name; `details.line` is the source line when the runtime supplies one,
|
|
558
|
+
otherwise null. Fixed hints repair imports/require/filesystem access, shadowed
|
|
559
|
+
`connecta`, and invented globals such as `callTool` and `mixpanel`.
|
|
560
|
+
|
|
561
|
+
An unchanged uncaught host error retains its classification through Error
|
|
562
|
+
identity. A new error containing its message is a new program error. Copied
|
|
563
|
+
public `code`/`details`, printed text, and returned outcome-shaped objects carry
|
|
564
|
+
no authority. Host-call counts stay in host state. The guest JSON codec, Object
|
|
565
|
+
prototype, and Promise prototype are immutable. Promise race and species are
|
|
566
|
+
protected too. Host completion uses captured intrinsics so guest edits cannot
|
|
567
|
+
change bridge decoding or async return adoption. Worker guest modules contain
|
|
568
|
+
only the user callback and an import helper limited to runtime builtins.
|
|
569
|
+
Relative and other guest module imports cannot reach runner code. Trusted
|
|
570
|
+
wrappers and preludes remain outside the guest's lexical scope, and privileged
|
|
571
|
+
initialization is single-use. A separate private runner module captures and
|
|
572
|
+
freezes its references before the guest module evaluates, including the guest
|
|
573
|
+
namespace initializer. The entrypoint imports that runner before its guest
|
|
574
|
+
dependency. Before loading, the adapter parses the assembled guest export and
|
|
575
|
+
requires exactly one expression with no additional statements. Normalized
|
|
576
|
+
multi-statement bodies remain one async arrow expression.
|
|
577
|
+
Program diagnostic fields are bounded before transport, including escaped text;
|
|
578
|
+
a large custom error name cannot turn a failure into a truncated success.
|
|
452
579
|
|
|
453
580
|
**E7.** `retryable` for `unknown_address`, `unknown_tool`, and
|
|
454
581
|
`destructive_tool_requires_approval` is pinned false, never inferred from an
|
|
@@ -495,15 +622,16 @@ The envelope is itself bounded as serialized, so `totalChars` is always the true
|
|
|
495
622
|
size of what the program returned and truncation happens exactly once no matter
|
|
496
623
|
how many hops the value takes.
|
|
497
624
|
|
|
498
|
-
**R3.** Truncation is a
|
|
625
|
+
**R3.** Truncation is a _successful_ result: the program ran but returned too
|
|
499
626
|
much. Run a program that returns less; that is why the envelope says so.
|
|
500
627
|
|
|
501
628
|
**R4 (verdict: no result paging for programs).** Program results have no
|
|
502
|
-
`
|
|
629
|
+
`connecta.result` handle. A program can shrink its return; paging would reward
|
|
503
630
|
unprojected data.
|
|
504
631
|
|
|
505
632
|
For non-repeatable writes, inspect and reduce the full result before return,
|
|
506
|
-
or page a direct `call_destructive_tool` result
|
|
633
|
+
or page a direct `call_destructive_tool` result on a trusted endpoint with
|
|
634
|
+
`connecta.result`. Sampling a
|
|
507
635
|
program result may discard the only copy.
|
|
508
636
|
|
|
509
637
|
**R5.** `console.log`, `console.warn`, and `console.error` are captured in call
|
|
@@ -512,18 +640,22 @@ truncation marker. Logs survive program failure through either a returned error
|
|
|
512
640
|
result or a thrown error carrying `logs: string[]`. QuickJS streams captured
|
|
513
641
|
entries to its parent and preserves the received prefix on cancellation,
|
|
514
642
|
shutdown, deadline termination, child crashes, and IPC failures (`X4`). How a
|
|
515
|
-
non-string argument renders is not contract (`X4`).
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
643
|
+
non-string argument renders is not contract (`X4`). At terminal host-call
|
|
644
|
+
budget exhaustion, QuickJS returns its streamed prefix; a Dynamic Worker
|
|
645
|
+
has no host log stream and cannot supply logs from its suspended guest (`L4`).
|
|
646
|
+
|
|
647
|
+
**R6.** Every run returns `hostCalls: { attempted, admitted, succeeded, failed }`,
|
|
648
|
+
including admission failure, cancellation, budget refusal, and code-size refusal.
|
|
649
|
+
Calls include search, describe, call, result, and skill. `emit` has separate budgets.
|
|
650
|
+
An abandoned host call counts as failed when the run ends; guest catches do not
|
|
651
|
+
change the counts. These numbers are outside the program's returned `result`.
|
|
652
|
+
`diagnostics: true` adds the existing payload-free timing block. Emitting adds
|
|
653
|
+
`emitted: N` and its content blocks.
|
|
522
654
|
|
|
523
655
|
**R7.** Diagnostic timing separates admission, provider setup, total executor
|
|
524
656
|
wall time, catalog work, and connector work. Catalog and connector values are
|
|
525
657
|
cumulative, so parallel work can exceed executor wall time. Each used operation
|
|
526
|
-
kind (`search`, `describe`, `call`) gets one aggregate with count, failures,
|
|
658
|
+
kind (`search`, `describe`, `call`, `read`) gets one aggregate with count, failures,
|
|
527
659
|
duration, returned serialized bytes, and catalog/connector time.
|
|
528
660
|
|
|
529
661
|
**R8.** Diagnostics contain measurements and fixed operation names only: no
|
|
@@ -533,9 +665,13 @@ request; it is not activity, a session, or a stream.
|
|
|
533
665
|
|
|
534
666
|
## Emitted output
|
|
535
667
|
|
|
668
|
+
Images accept only `image/png`, `image/jpeg`, `image/gif`, or `image/webp`
|
|
669
|
+
and nonempty canonical base64. Whitespace, URL-safe alphabets, bad padding,
|
|
670
|
+
and nonzero pad bits are rejected before collection. Size budgets still apply.
|
|
671
|
+
|
|
536
672
|
MCP-native output a return value cannot carry: base64 is not projectable, so a
|
|
537
673
|
block that survives intake uncapped (`S5`) must not die at the `R2` exit guard.
|
|
538
|
-
The
|
|
674
|
+
The earlier alternatives are in [decision history](https://github.com/zackbart/connecta/blob/main/decisions/0001-ethos-verdict-table.md)
|
|
539
675
|
([#267](https://github.com/zackbart/connecta/issues/267),
|
|
540
676
|
[#270](https://github.com/zackbart/connecta/issues/270)).
|
|
541
677
|
|
|
@@ -552,18 +688,25 @@ a successful result, appended to `content` after the JSON envelope, which gains
|
|
|
552
688
|
response (`R6`). `structuredContent` stays the envelope alone — emission is
|
|
553
689
|
presentation, not a second data channel.
|
|
554
690
|
|
|
555
|
-
**M3.**
|
|
556
|
-
|
|
557
|
-
|
|
691
|
+
**M3.** Text emission shares `R2`'s 24,000 serialized-character cap. Its
|
|
692
|
+
serialized block size reduces the return budget, and oversized text fails with
|
|
693
|
+
`result_too_large`. Image/audio blocks use the separate transport budget and
|
|
694
|
+
reach the model as real MCP media content, including when `emit` is not awaited.
|
|
695
|
+
The trusted runner waits for emission acknowledgments before returning success.
|
|
696
|
+
An unobserved emission failure fails the run; an awaited failure remains catchable.
|
|
697
|
+
Rejections propagated through `then` or `finally` can be caught later in that
|
|
698
|
+
chain. A separate unhandled branch still fails the run.
|
|
558
699
|
|
|
559
700
|
**M4.** A failed program delivers no blocks. The error result reports
|
|
560
|
-
`emittedDiscarded: N` when N > 0
|
|
561
|
-
trailing line on the plain-text paths — never silently.
|
|
701
|
+
`emittedDiscarded: N` when N > 0 as a field on the structured envelope.
|
|
562
702
|
|
|
563
703
|
**M5.** Two budgets (`ConnectaConfig.execute.maxEmittedBytes` /
|
|
564
704
|
`.maxEmittedBlocks`, defaults 4,000,000 serialized bytes and 32 blocks) fail
|
|
565
705
|
loudly at the `emit` call, naming the budget and the room remaining; nothing is
|
|
566
|
-
partially accepted and prior blocks stand.
|
|
706
|
+
partially accepted and prior blocks stand. Accepted and rejected emission attempts
|
|
707
|
+
also have a terminal limit of four times the configured block cap (at least 128),
|
|
708
|
+
which bounds retained host failures and guest acknowledgement state without
|
|
709
|
+
discarding an older error identity. No result stash for emitted blocks: the program
|
|
567
710
|
learns while it can still choose differently. The byte default is a transport
|
|
568
711
|
bound, not a context bound — emitted media reaches the model as media, not
|
|
569
712
|
base64 text.
|
|
@@ -573,13 +716,12 @@ exactly as much as the return value. Preservation is re-emission of the raw
|
|
|
573
716
|
downstream block, so `S5`'s uncapped fallthrough is contract.
|
|
574
717
|
|
|
575
718
|
**M7.** `emit` alone spends no host-call budget (`L4`); `search`, `describe`,
|
|
576
|
-
and `
|
|
719
|
+
`call`, `read`, `result`, and `skill` share it. Text also observes `R2`.
|
|
577
720
|
|
|
578
|
-
**M8.**
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
emission for free.
|
|
721
|
+
**M8.** `emit` is a provider function; blocks cross the guest boundary once as
|
|
722
|
+
an argument. `ExecuteResult` remains compatible with upstream codemode's types;
|
|
723
|
+
construction requires the Worker adapter or explicit custom opt-in. Any executor
|
|
724
|
+
that bridges provider calls gets emission for free.
|
|
583
725
|
|
|
584
726
|
**M9.** Request-local and unstreamed: blocks exist only in the finished
|
|
585
727
|
response, and `emit` resolving means "accepted," never "delivered."
|
|
@@ -607,7 +749,7 @@ host-call budget, so an unchecked loop converts a transient failure into
|
|
|
607
749
|
Dynamic-Worker-only wait would spend the run's wall clock on code that fails
|
|
608
750
|
on QuickJS. Return the failure and let the model, which can wait, re-issue
|
|
609
751
|
with `retryAfterMs` in hand.
|
|
610
|
-
- a cancelled or timed-out
|
|
752
|
+
- a cancelled or timed-out _execution_: it is already over (`L1`).
|
|
611
753
|
|
|
612
754
|
**Y4.** A provider's `retryAfterMs` is returned unchanged; the caller decides
|
|
613
755
|
whether and when to reissue, and a later call gets its own deadline and
|
|
@@ -620,14 +762,21 @@ poll, no cancellation exception to catch, and no guarantee that a `finally`
|
|
|
620
762
|
block runs — a cancelled QuickJS child is terminated outright. Write programs
|
|
621
763
|
that need no cleanup.
|
|
622
764
|
|
|
623
|
-
**L2.**
|
|
624
|
-
|
|
625
|
-
`
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
765
|
+
**L2.** Cancellation aborts in-flight host calls and admits no further calls,
|
|
766
|
+
including discovery. The response returns `executor_cancelled` without awaiting
|
|
767
|
+
a wedged executor or `acquire()` that ignores its signal. It releases the lease;
|
|
768
|
+
a late-granted lease releases on arrival. Nothing request-bound survives the
|
|
769
|
+
request. Whether guest computation stops is the executor's (`X3`).
|
|
770
|
+
|
|
771
|
+
Programs and direct calls use the same invocation deadline and stages. A call's
|
|
772
|
+
`timeoutMs` wins, then `calls.defaultTimeoutMs`, then `execute.hostCallTimeoutMs`
|
|
773
|
+
(default 15,000). A guest may request a longer individual call, but the sandbox
|
|
774
|
+
and request ceilings still bound the whole run. Timeout details are agent-facing;
|
|
775
|
+
INV-6 operator records retain only checked classifications and numeric facts.
|
|
776
|
+
A dispatched write timeout becomes `write_outcome_unknown` and retains its
|
|
777
|
+
deadline details even when the program catches the failure. The final program
|
|
778
|
+
error includes the first timeout in `details`; multiple write timeouts also
|
|
779
|
+
appear in `timeouts`, bounded to ten entries.
|
|
631
780
|
|
|
632
781
|
**L3.** Every execution runs under a wall-clock deadline that includes time
|
|
633
782
|
spent waiting on host calls. Expiry ends the run with an execution error and no
|
|
@@ -636,7 +785,7 @@ it sits a ceiling connecta enforces outside the sandbox, `execute.watchdogMs`
|
|
|
636
785
|
(120 s by default, above both executors' own deadlines), because an executor's
|
|
637
786
|
deadline may live inside the sandbox it is meant to stop: a wedged Dynamic
|
|
638
787
|
Worker never fires its in-isolate timer. A run whose executor has not settled
|
|
639
|
-
by the ceiling ends as a non-retryable `
|
|
788
|
+
by the ceiling ends as a non-retryable `timeout` whose message calls
|
|
640
789
|
the sandbox unresponsive, with no partial result, and its admission lease is
|
|
641
790
|
released, so wedged runs cannot fill the code pool. Raising an executor's
|
|
642
791
|
deadline past the ceiling means raising the ceiling too.
|
|
@@ -644,25 +793,38 @@ deadline past the ceiling means raising the ceiling too.
|
|
|
644
793
|
**L4.** Per-execution bounds that are contract, identical in both executors
|
|
645
794
|
because connecta enforces them above the sandbox:
|
|
646
795
|
|
|
647
|
-
| Bound
|
|
648
|
-
|
|
|
649
|
-
| Host calls per execution, shared by `search`, `describe`, and `
|
|
650
|
-
|
|
|
651
|
-
| Deadline per host call
|
|
652
|
-
| Discovery page
|
|
653
|
-
| `describe` addresses
|
|
654
|
-
| `describe` nearby suggestions
|
|
655
|
-
| Caller text echoed by `describe` recovery
|
|
656
|
-
| Result
|
|
657
|
-
| Logs presented to the model
|
|
658
|
-
|
|
659
|
-
Every `call`
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
`
|
|
664
|
-
|
|
665
|
-
|
|
796
|
+
| Bound | Value |
|
|
797
|
+
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
798
|
+
| Host calls per execution, shared by `search`, `describe`, `call`, and `read` | 20 by default, `execute.maxHostCalls` |
|
|
799
|
+
| Trusted-pool writes per run, on top of the host calls they also spend (`W10`) | 10 by default, `execute.maxWrites` |
|
|
800
|
+
| Deadline per host call | 15 s, `execute.hostCallTimeoutMs`; one deadline covers catalog resolution, admission, and the connector call |
|
|
801
|
+
| Discovery page | ≤ 100 tools, ≤ 256,000 serialized bytes |
|
|
802
|
+
| `describe` addresses | ≤ 100 |
|
|
803
|
+
| `describe` nearby suggestions | ≤ 3 canonical addresses per failed entry |
|
|
804
|
+
| Caller text echoed by `describe` recovery | ≤ 512 UTF-8 bytes per field, plus `…` |
|
|
805
|
+
| Result | 24,000 serialized characters |
|
|
806
|
+
| Logs presented to the model | 4,000 characters |
|
|
807
|
+
|
|
808
|
+
Every `call`, `read`, `search`, and `describe` spends one host call on entry, before
|
|
809
|
+
resolution, validation, or dispatch. Catching a local refusal refunds nothing.
|
|
810
|
+
The first call beyond the budget ends the host run with one non-retryable
|
|
811
|
+
`budget_exceeded` (`E2`). Its bridge stays pending until lease disposal so guest
|
|
812
|
+
`try/catch` cannot swallow it. Later host access, including `emit`, stops; pending
|
|
813
|
+
replies are withheld. The refusal reaches no connector, returns no partial result,
|
|
814
|
+
and discards accepted emits (`M4`). Calls still resolving or awaiting admission
|
|
815
|
+
are cancelled, including trusted-pool writes past their gate. Dispatched trusted-pool writes
|
|
816
|
+
drain under `W9`; unknown outcomes retain precedence. The lease then releases:
|
|
817
|
+
QuickJS terminates its child, and the Worker adapter disposes RPC and loader
|
|
818
|
+
handles independently of the guest deadline. Workers guest computation may
|
|
819
|
+
continue briefly, including a timer escaping the bridge (`X3`), with no host
|
|
820
|
+
access. The Promise executor contract carries typed failures separately from guest values.
|
|
821
|
+
|
|
822
|
+
The failure adds payload-free `hostCalls: { attempted, admitted, succeeded, failed }`
|
|
823
|
+
without diagnostics. `attempted` includes the first refusal, normally 21; `admitted`
|
|
824
|
+
counts the 20 calls past the gate, local refusals included. `succeeded` and `failed`
|
|
825
|
+
count outcomes at response time, the budget refusal and abandoned pending calls
|
|
826
|
+
as failed, so `succeeded + failed === attempted`. `emit` and later attempts are
|
|
827
|
+
excluded; no budget refills.
|
|
666
828
|
|
|
667
829
|
**L5.** The guest is memory-, stack-, and CPU-bounded, and a program that
|
|
668
830
|
exhausts a bound ends the run with an error instead of degrading the host. The
|
|
@@ -676,18 +838,19 @@ code safe to run at all.
|
|
|
676
838
|
bounded — QuickJS caps both at 256 KiB (`X10`) — and exceeding either fails that
|
|
677
839
|
call, not the execution, so a program can catch it and ask for less. The failure
|
|
678
840
|
is executor-owned untyped text, not a Connecta host failure (`E1`). An
|
|
679
|
-
over-bound
|
|
680
|
-
generic bridge function; an over-bound
|
|
841
|
+
over-bound _result_ names the address the program called rather than only the
|
|
842
|
+
generic bridge function; an over-bound _argument_ payload is refused before it
|
|
681
843
|
is parsed, so it names no address at all.
|
|
682
844
|
|
|
683
845
|
**L7.** Executions are admitted, not queued indefinitely: bounded concurrency
|
|
684
846
|
plus a bounded queue with a wait timeout. Overload is a retryable
|
|
685
847
|
`executor_overloaded` carrying `retryAfterMs`; cancellation and shutdown are
|
|
686
|
-
terminal. Admission happens
|
|
848
|
+
terminal. Admission happens _before_ any catalog or provider is built, so a
|
|
687
849
|
queued request holds no state.
|
|
688
850
|
|
|
689
|
-
**L8.**
|
|
690
|
-
|
|
851
|
+
**L8.** Result, log, host-call, and emission budgets are deployment configuration.
|
|
852
|
+
A call may request `timeoutMs` just as a direct call does; the guest deadline is
|
|
853
|
+
capped by the time remaining before the program watchdog. `execute_code`'s description states the host-call
|
|
691
854
|
budget and the per-call deadline — the ones a program must plan around before it
|
|
692
855
|
runs. The result and log caps live here and in the truncation notice itself
|
|
693
856
|
(`R2`, `R5`).
|
|
@@ -705,7 +868,7 @@ event.
|
|
|
705
868
|
|
|
706
869
|
**V2.** Each event carries `connectorId`, `toolName`, `address`, `source`,
|
|
707
870
|
`outcome` (`success`, `error`, `timeout`, `cancelled`), `durationMs`,
|
|
708
|
-
`attempts`, and `errorCode` when the call
|
|
871
|
+
`attempts`, and `errorCode` when the call _failed_ — plus request, actor, and
|
|
709
872
|
server identity. Rows written before
|
|
710
873
|
[#672](https://github.com/zackbart/connecta/issues/672) may also carry the
|
|
711
874
|
`paused` and `approved` outcomes, `source: "resume_execution"`, and an
|
|
@@ -719,65 +882,80 @@ is still recorded. `address` is canonical (`A1`) where a tool resolved,
|
|
|
719
882
|
otherwise the name the program used — the honest record of what was attempted.
|
|
720
883
|
|
|
721
884
|
**V3.** A call whose connector does not exist is recorded at the address as
|
|
722
|
-
written,
|
|
885
|
+
written, _provided_ it split into the two fields activity keeps — one with no
|
|
723
886
|
interior dot records nothing. An invented id is the address mistake an operator
|
|
724
887
|
most needs to see, but recording it as written puts caller-authored text in
|
|
725
888
|
fields that are otherwise operator- and connector-authored, so `connectorId`
|
|
726
889
|
and `toolName` clamp at 128 UTF-8 bytes (`address` at 257) with a `…` marker:
|
|
727
|
-
payload-free
|
|
890
|
+
payload-free _by construction_ means the event has nowhere to put a payload.
|
|
728
891
|
|
|
729
892
|
**V4.** The execution itself emits no event. It has no address, and its one
|
|
730
|
-
distinctive
|
|
893
|
+
distinctive output is the program source — exactly what a payload-free history
|
|
731
894
|
must never keep.
|
|
732
895
|
|
|
733
|
-
**V5.**
|
|
896
|
+
**V5.** A trusted-pool write a program issues after it has already returned is not
|
|
734
897
|
sent and records nothing: it was never an attempt (`W9`).
|
|
735
898
|
|
|
736
899
|
## Writes
|
|
737
900
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
`
|
|
779
|
-
|
|
780
|
-
|
|
901
|
+
Pool trust belongs to deployment code. The default `/mcp` endpoint uses
|
|
902
|
+
`trust: "read-only"`; each named pool has its own `trust`, also defaulting to
|
|
903
|
+
`"read-only"`. A trusted default endpoint does not make named pools trusted.
|
|
904
|
+
The default preserves refusal of ordinary program writes. A deployment must opt into program writes explicitly.
|
|
905
|
+
|
|
906
|
+
```ts
|
|
907
|
+
createConnecta({
|
|
908
|
+
connectors, executor,
|
|
909
|
+
trust: "read-only",
|
|
910
|
+
pools: {
|
|
911
|
+
automation: { tools: ["posthog"], trust: "trusted", grant },
|
|
912
|
+
},
|
|
913
|
+
classification: {
|
|
914
|
+
posthog: { exec: "read" }, // only for a deployment with a read-only exec contract
|
|
915
|
+
vendor: { mislabeled_update: "write" },
|
|
916
|
+
},
|
|
917
|
+
});
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
The registry computes one `classifyTool` verdict on each request-scoped
|
|
921
|
+
published catalog entry. It caches and persists only raw downstream facts.
|
|
922
|
+
Every caller consumes that stored verdict. Config cannot classify an individual
|
|
923
|
+
invocation's arguments: marking a mixed entry point read is an assertion about
|
|
924
|
+
all calls this deployment can make through it.
|
|
925
|
+
|
|
926
|
+
| Precedence | Evidence | Result |
|
|
927
|
+
| ---------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
928
|
+
| 1 | Exact deployment `classification[connectorId][toolName]` | `read` or `write`, even over a stale provider review |
|
|
929
|
+
| 2 | `Connector.classification` provider review | Reviewed writes remain writes; a stale schema digest makes a read a write; an explicit downstream contradiction also invalidates a reviewed read |
|
|
930
|
+
| 3 | Downstream annotations | Read only when `readOnlyHint === true && destructiveHint !== true`; otherwise write |
|
|
931
|
+
|
|
932
|
+
Unknown connector override keys fail construction. Unknown static tool keys
|
|
933
|
+
fail construction; unknown remote tool keys fail publication of the whole
|
|
934
|
+
catalog. Overrides are exact tool names, including names containing dots.
|
|
935
|
+
They are never inferred from descriptions or arguments.
|
|
936
|
+
|
|
937
|
+
**W9.** Programs in trusted pools may write. A dispatched write is awaited even
|
|
938
|
+
if the program does not await it, bounded by its host-call deadline. A write
|
|
939
|
+
that reaches accounting after the program settles is not sent. An unanswered
|
|
940
|
+
write makes the run fail `write_outcome_unknown` with
|
|
941
|
+
`writes: { succeeded, failed, unknown }`, regardless of its return value.
|
|
942
|
+
A failed program that already wrote carries those counts on its error. No
|
|
943
|
+
write is automatically retried, including an ambiguous timeout. A downstream
|
|
944
|
+
refusal or a tool's `isError` can establish failure; a timeout or an unanswered
|
|
945
|
+
transport failure leaves the outcome unknown.
|
|
946
|
+
|
|
947
|
+
**W10.** `execute.maxWrites`, default 10, bounds writes in trusted programs in
|
|
948
|
+
addition to the host-call budget. It is checked after argument validation and
|
|
949
|
+
before admission, so an over-budget write spends no permit.
|
|
950
|
+
|
|
951
|
+
**W12.** `trusted` endpoints annotate `execute_code` as a write and permit
|
|
952
|
+
program writes. `read-only` endpoints annotate it as read-only and refuse
|
|
953
|
+
program writes before validation, with `call_destructive_tool` as the recovery.
|
|
954
|
+
`call_tool` accepts only reads in either tier; `call_destructive_tool` may send
|
|
955
|
+
writes in either tier. Approval belongs to the host. Trust grants no tool or
|
|
956
|
+
connector access and cannot be set by guest code, request arguments, or a
|
|
957
|
+
downstream catalog. `execute.approval`, `Connector.approval`, and per-tool
|
|
958
|
+
approval exemptions are removed. `W1`–`W8` and `W11` remain retired.
|
|
781
959
|
|
|
782
960
|
## Executor exceptions
|
|
783
961
|
|
|
@@ -796,12 +974,13 @@ isolate limits apply untuned. A specific heap ceiling is a Node-only option.
|
|
|
796
974
|
`AbortSignal` and kills the child — SIGTERM, then SIGKILL if it has not exited
|
|
797
975
|
within a second — and releasing a lease whose child is still running recycles
|
|
798
976
|
that child, so a run the watchdog abandons (`L3`) ends too.
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
977
|
+
Upstream `execute()` takes no signal; its guest timeout may never settle after
|
|
978
|
+
the parent response ends. `workerExecutor()` owns each lease's RPC and loader
|
|
979
|
+
handles: release disposes them, detaches host functions, and settles the adapter's
|
|
980
|
+
promise independently of upstream evaluation. Guest computation may continue
|
|
981
|
+
briefly until platform teardown, but no late return, callback, `finally`, call,
|
|
982
|
+
or emit changes the finished host result. Disposal releases request resources;
|
|
983
|
+
it does not guarantee a synchronous guest-CPU kill.
|
|
805
984
|
|
|
806
985
|
**X4. Log rendering and capture.** QuickJS JSON-stringifies non-string arguments
|
|
807
986
|
and captures `log`, `info`, `warn`, `error`, and `debug`; the Dynamic Worker
|
|
@@ -820,14 +999,16 @@ starts has no guest logs to recover.
|
|
|
820
999
|
`process`, timers, `crypto`, or `WebSocket`, and its Node child starts with an
|
|
821
1000
|
explicit environment holding only `TZ=UTC`, so local time matches a Dynamic
|
|
822
1001
|
Worker's, rather than inheriting
|
|
823
|
-
deployment variables or `NODE_OPTIONS`. A Dynamic Worker
|
|
824
|
-
|
|
825
|
-
`node:
|
|
826
|
-
|
|
827
|
-
The
|
|
1002
|
+
deployment variables or `NODE_OPTIONS`. A Dynamic Worker exposes runtime-only
|
|
1003
|
+
builtins through `import()` and `process.getBuiltinModule()`, including `node:path`,
|
|
1004
|
+
`node:crypto`, `node:net`, `node:tls`, `node:dns`, and
|
|
1005
|
+
`cloudflare:workers`; the upstream set drifts, so that is not an allowlist.
|
|
1006
|
+
The adapter refuses `node:module` and `node:process` imports and removes their
|
|
1007
|
+
builtin lookup routes, so `createRequire` cannot resolve runner modules.
|
|
1008
|
+
The supported adapter uses `new DynamicWorkerExecutor({ loader, timeout })`.
|
|
828
1009
|
`bindings`, `modules`, and `globalOutbound` each grant ambient configuration,
|
|
829
|
-
code, or egress. Under it, `process.env
|
|
830
|
-
`
|
|
1010
|
+
code, or egress. Under it, `process.env` and `cloudflare:workers.env` are empty,
|
|
1011
|
+
and lexical `this.env` is undefined; `node:fs`, `node:http`, and `node:https` are
|
|
831
1012
|
unavailable through either access route; external `fetch`, `WebSocket`,
|
|
832
1013
|
`node:net`, and `node:tls` fail with workerd's outbound-denial error; DNS lookup
|
|
833
1014
|
ends unresolved; and `fetch("data:...")` resolves locally. `P2` is the portable
|
|
@@ -844,9 +1025,9 @@ reasonable demand on a platform sandbox.
|
|
|
844
1025
|
values through a tagged envelope, so a `Uint8Array` may survive there. `P3` is
|
|
845
1026
|
the contract: JSON-serializable values, or the program is Workers-only.
|
|
846
1027
|
|
|
847
|
-
**X8. Unknown
|
|
848
|
-
|
|
849
|
-
|
|
1028
|
+
**X8. Unknown properties.** The guest namespace exposes only the six documented
|
|
1029
|
+
functions. Unknown and inherited members are absent on both executors; calling
|
|
1030
|
+
one is a guest `TypeError` under `E6`. Engine message text is not contract.
|
|
850
1031
|
|
|
851
1032
|
**X9. Refusing a value outside JSON.** The Dynamic Worker ends the run with an
|
|
852
1033
|
error when a program returns something its codec cannot carry. QuickJS converts
|
|
@@ -867,70 +1048,78 @@ the program either way (`R1`).
|
|
|
867
1048
|
**X12** described a paused sandbox and left with pausing
|
|
868
1049
|
([#672](https://github.com/zackbart/connecta/issues/672)); the id stays retired.
|
|
869
1050
|
|
|
870
|
-
**X11. Typed host rejection.**
|
|
871
|
-
host
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1051
|
+
**X11. Typed host rejection.** QuickJS creates and retains guest Error handles
|
|
1052
|
+
in its host bridge and compares handles when the program rejects. The Worker
|
|
1053
|
+
adapter stores each typed failure in a per-run host map under a random UUID.
|
|
1054
|
+
Its private entrypoint associates that ID with the guest Error and returns only
|
|
1055
|
+
the ID through Worker Loader RPC. The host resolves it to its own record before
|
|
1056
|
+
upstream result shaping; unknown or forged IDs attach no typed details, and IDs
|
|
1057
|
+
from previous runs cannot resolve. Rethrowing an earlier call's Error retains
|
|
1058
|
+
that call's record. The guest receives a separate copy for catching errors.
|
|
1059
|
+
Both construct `failure.call` from host-retained values, never from a guest
|
|
1060
|
+
result, parsed guest-realm object, or printed text. The Worker codec checks own
|
|
1061
|
+
binary-envelope properties, and completion uses captured array iteration even
|
|
1062
|
+
when the executor runs without the Connecta guest prelude. Host failure details are
|
|
1063
|
+
bounded before bridging (`E1`), including JSON escapes. No frame parser or
|
|
1064
|
+
prose matching participates in classification. The guest cannot import runner
|
|
1065
|
+
modules or repeat privileged initialization. QuickJS checks host interrupt and
|
|
1066
|
+
deadline facts before describing a rejection. It retains a private native Error
|
|
1067
|
+
brand check and reads only own string data descriptors for diagnostics; guest
|
|
1068
|
+
accessors, serialization hooks, and Proxy traps do not run. Other thrown objects
|
|
1069
|
+
receive a fixed description.
|
|
878
1070
|
|
|
879
1071
|
## Verification
|
|
880
1072
|
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
`test/
|
|
890
|
-
|
|
891
|
-
|
|
|
892
|
-
|
|
|
893
|
-
| `
|
|
894
|
-
| `
|
|
895
|
-
| `
|
|
896
|
-
| `
|
|
897
|
-
| `
|
|
898
|
-
| `
|
|
899
|
-
| `
|
|
900
|
-
| `
|
|
901
|
-
| `
|
|
902
|
-
| `
|
|
903
|
-
| `
|
|
904
|
-
| `
|
|
905
|
-
| `
|
|
906
|
-
| `
|
|
907
|
-
| `
|
|
908
|
-
| `
|
|
909
|
-
| `
|
|
910
|
-
| `
|
|
911
|
-
| `
|
|
912
|
-
| `
|
|
913
|
-
| `
|
|
914
|
-
| `
|
|
915
|
-
| `
|
|
916
|
-
| `
|
|
917
|
-
| `
|
|
918
|
-
| `
|
|
919
|
-
| `
|
|
920
|
-
| `
|
|
921
|
-
| `
|
|
922
|
-
| `
|
|
923
|
-
| `
|
|
924
|
-
| `
|
|
925
|
-
| `
|
|
926
|
-
| `
|
|
927
|
-
| `
|
|
928
|
-
| `
|
|
929
|
-
| `
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
| `X7` | `P3`'s tests; the Workers superset is deliberately unused |
|
|
933
|
-
|
|
934
|
-
The surface itself is checked by `test/server.test.ts` (the exact seven-tool list),
|
|
1073
|
+
`test/guest-contract-cases.ts` runs on QuickJS in `test/guest-api-contract-quickjs.node.test.ts`
|
|
1074
|
+
and on the Worker adapter with a real Miniflare Loader in `test/guest-api-contract.test.ts`.
|
|
1075
|
+
Titles name clauses; executor-independent clauses run in both arms.
|
|
1076
|
+
`test/codemode-compat.test.ts` pins upstream shape compatibility, minified upstream
|
|
1077
|
+
rejection, and branded adapter acceptance across module copies.
|
|
1078
|
+
|
|
1079
|
+
| Clauses | Test |
|
|
1080
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1081
|
+
| `P1`, `P5` | both guest-contract executors (TypeScript syntax, trailing terminators, wrapper recovery), `test/program-source.test.ts` (which semicolons and wrappers are recovered), `test/quickjs-executor.node.test.ts` (`normalizeCode`) |
|
|
1082
|
+
| `P2`, `X5` | `test/guest-api-contract.test.ts` (Dynamic globals plus loader-only filesystem, HTTP, environment, egress, DNS, and local `data:` boundaries), `test/guest-api-contract-quickjs.node.test.ts` (exact absent globals and blocked imports), `test/quickjs-child-stderr.node.test.ts` (a child-process environment holding only `TZ=UTC`), `test/deployment-shapes.node.test.ts` (loader-only Worker construction) |
|
|
1083
|
+
| `P3`, `X9` | `test/guest-api-contract.test.ts`, `test/execute.test.ts` |
|
|
1084
|
+
| `P4` | `test/guest-api-contract.test.ts` (no cross-run leakage), `test/execute.test.ts` (one catalog load per connector per execution) |
|
|
1085
|
+
| `A1`, `A2` | `test/guest-api-contract.test.ts`, `test/execute.test.ts` (canonical addressing), `test/server.test.ts` (bounded live connector inventory) |
|
|
1086
|
+
| `S1`, `S1a`, `S2` | `test/guest-api-contract.test.ts` (flat page, connector guides, schema keys, unfiltered browse), `test/execute.test.ts` (guide pagination/partial/no-match behavior and `$ref`/`allOf`), `test/meta-tools-search.test.ts` (mixed complete/partial ranking, stable pagination, the two safety classes), `test/typescript-signatures.test.ts` (the TypeScript format over provider and pathological schemas, search/describe parity, observed labeling), `test/typescript-signatures-parse.node.test.ts` (every rendering parses) |
|
|
1087
|
+
| `S3` | `test/guest-api-contract.test.ts` (typed uncaught bound), `test/execute.test.ts` (count limits, fan-out bound) |
|
|
1088
|
+
| `S4` | both guest-contract executors (ordered mixed describe results with unknown-address, unknown-tool suggestion, and catalog-failure details), `test/meta-tools-search.test.ts` (top-level routing, no-suggestion, catalog-failure, and hostile-input bounds) |
|
|
1089
|
+
| `S5`, `S6` | `test/guest-api-contract.test.ts`, `test/execute.test.ts` (`unwrapMcpResult`, fail-closed annotations, activity parity) |
|
|
1090
|
+
| `S7` | `test/guest-api-contract.test.ts`, `test/execute.test.ts` (parallel calls and shared admission) |
|
|
1091
|
+
| `S8`, `E1`, `X11` | both guest-contract executors (caught call, discovery, utility, removed-function, and forgery cases; typed promise rejections), `test/quickjs-executor.node.test.ts` (oversized messages, private transport, forged outcomes) |
|
|
1092
|
+
| `S9` | `test/result-shapes.test.ts` (value exclusion, bounds, merging, LRU and time expiry, runtime isolation, read-only admission, declared precedence, definition invalidation, unwrapped MCP results, discovery provenance, copy isolation, failure isolation) |
|
|
1093
|
+
| `S10` | `test/resource-read.test.ts` (qualified routing, whole-connector grants, personal credentials, redaction, admission, timeout, cancellation and downstream MCP reads), both guest-contract executors (successful resource reads and caught/uncaught typed failures) |
|
|
1094
|
+
| `E2`, `E8` | `test/guest-api-contract.test.ts` (code → `retryable`, caught, parallel, and uncaught validation recovery, a conflict's bounded `current`), `test/meta-tools-call.test.ts` (direct, destructive, provider fallback), `test/validate.test.ts` (bounded payload-free findings), `test/errors.test.ts` |
|
|
1095
|
+
| `E3`, `E4` | `test/guest-api-contract.test.ts`, `test/execute.test.ts` (`auth_required`, destructive reroute), `test/program-writes.test.ts` (the refusal's `nextAction`, nothing sent, a caught refusal) |
|
|
1096
|
+
| `E5` | `test/guest-api-contract.test.ts` (execution-failure channel, in-flight `cancelled`), `test/execute.test.ts` (admission), `test/executor-admission.test.ts`, `test/quickjs-executor.node.test.ts` (mid-run shutdown) |
|
|
1097
|
+
| `E6`, `X8` | `test/guest-api-contract.test.ts` (unknown and inherited members, retained error identities), `test/quickjs-executor.node.test.ts` |
|
|
1098
|
+
| `E7` | `test/guest-api-contract.test.ts` (refusals about a `503`-named connector), `test/errors.test.ts` |
|
|
1099
|
+
| `R1`, `R2`, `R3` | `test/guest-api-contract.test.ts` (pass-through, truncation is success, envelope fits the cap and is idempotent) |
|
|
1100
|
+
| `R4`, `M6`, `M9` | verdicts; `R2`'s guard, `M1`'s strict typing, and `M2`'s collect-then-deliver are their enforcement |
|
|
1101
|
+
| `R5` | `test/guest-api-contract.test.ts`, `test/quickjs-log-limits.node.test.ts` |
|
|
1102
|
+
| `R6`–`R8` | `test/guest-api-contract.test.ts` (normal result keys), `test/execute.test.ts` (opt-in operation aggregates, failure paths, payload exclusion) |
|
|
1103
|
+
| `Y1`, `Y2`, `Y3` | `test/guest-api-contract.test.ts` (one attempt per call, retryable flags by code) |
|
|
1104
|
+
| `Y4` | `test/meta-tools-call.test.ts`, `test/call-admission.test.ts` (one attempt, retry hints, caller reissue) |
|
|
1105
|
+
| `L1`, `L2` | `test/guest-api-contract.test.ts` (in-flight call fails `cancelled`), `test/execute.test.ts` (cancels outstanding host calls, discovery included, and refuses discovery after the run; a cancelled wedged executor, or one whose `acquire()` ignores the signal, returns promptly and releases its lease) |
|
|
1106
|
+
| `L3`, `X1` | `test/guest-api-contract.test.ts` (short-deadline executors), `test/execute.test.ts` (the watchdog ends a never-settling executor, frees the default pool, spares a slow run, and falls back from an unusable value) |
|
|
1107
|
+
| `L4`, `L8` | `test/guest-api-contract.test.ts`, `test/execute.test.ts` (shared discovery/call budgets and terminal catch-and-continue loops and queued-write cancellation on both executors), `test/worker-budget-response.node.test.ts` (native handle disposal and admission recovery across completed HTTP responses) |
|
|
1108
|
+
| `L5`, `L7`, `X2` | `test/quickjs-executor.node.test.ts` (CPU, heap), `test/execute.test.ts` and `test/executor-admission.test.ts` (bounded admission and queue) |
|
|
1109
|
+
| `L6`, `X10` | `test/quickjs-executor.node.test.ts` (bridge and IPC bounds for arguments and result; the address in the over-bound message), `test/quickjs-child-stderr.node.test.ts` (outer reply serialization failure settles the call) |
|
|
1110
|
+
| `V1`–`V4` | `test/guest-api-contract.test.ts` (dispatched calls, every refusal class including an address no connector owns, the friction each derives, no event for the execution itself), `test/activity.test.ts` (the shared code → friction table, the identity clamp, the one-attempt floor), `test/operator-view.test.ts`, `test/sql-storage-contract.ts`, run by `test/d1-storage.node.test.ts` and `test/sqlite-storage.node.test.ts` (historical pause and approval rows still render and round-trip) |
|
|
1111
|
+
| `V5`, `W9` | `test/program-writes.test.ts` (an unawaited trusted-pool write finished and recorded, its unknown outcome reported, counts on a failed program, the classification table), `test/invocation-pipeline.test.ts` (the gate after validation, an unrecorded refusal) |
|
|
1112
|
+
| `W10`, `W12` | `test/program-writes.test.ts` (a trusted-pool write runs and every other write keeps `E4`, the write budget, pool trust and override precedence, `call_tool` still refusing, search and describe verdicts, construction refusals), `test/operator-ui-model.test.ts`, `test/browser/operator-ui.spec.ts` (the badge) |
|
|
1113
|
+
| `M1` | `test/guest-api-contract.test.ts` (invalid emits throw catchably, accept nothing), `test/execute-emit.test.ts` (every rejected shape) |
|
|
1114
|
+
| `M2`, `M3` | `test/guest-api-contract.test.ts` (delivery order, truncated return plus delivered blocks), `test/execute-emit.test.ts` (envelope, `structuredContent`, byte-for-byte no-emit path) |
|
|
1115
|
+
| `M4` | `test/guest-api-contract.test.ts` (discard is visible), `test/execute-emit.test.ts` (structured and plain paths), `test/quickjs-executor.node.test.ts` (mid-run shutdown) |
|
|
1116
|
+
| `M5`, `M7` | `test/execute-emit.test.ts` (both budgets fail the crossing block; host-call budget untouched) |
|
|
1117
|
+
| `M8` | two arms passing one case table, `test/codemode-compat.test.ts` |
|
|
1118
|
+
| `M10` | `test/execute-emit.test.ts` (aggregate present, numbers only, absent when nothing emitted) |
|
|
1119
|
+
| `X4` | `test/guest-api-contract.test.ts` (string logs only), `test/quickjs-executor.node.test.ts` (logs before cancellation), `test/quickjs-child-stderr.node.test.ts` (crash, shutdown, deadline, IPC failure, bounded parent retention), `test/quickjs-log-limits.node.test.ts` (unchanged successful logs) |
|
|
1120
|
+
| `X3`, `X6` | `test/quickjs-executor.node.test.ts` (cancels a running child, never-settling await), `test/execute.test.ts` (a wedged executor stops being awaited) |
|
|
1121
|
+
| `X7` | `P3`'s tests; the Workers superset is deliberately unused |
|
|
1122
|
+
|
|
1123
|
+
The surface itself is checked by `test/server.test.ts` (the exact six-tool list),
|
|
935
1124
|
`test/code-first-surface.test.ts` (construction, executor, removed tools, copy, and size),
|
|
936
1125
|
and `test/program-writes.test.ts` (the retired pause options refused at construction).
|