@zackbart/connecta 0.28.1 → 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 +788 -5
- package/README.md +62 -42
- 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 +1584 -1580
- 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 +93 -71
- 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 +59 -7
- package/dist/connectors/api-connector.js +106 -19
- package/dist/connectors/api.js +4 -1
- package/dist/connectors/guarded-fetch.d.ts +144 -0
- package/dist/connectors/guarded-fetch.js +84 -35
- 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 +1774 -320
- 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 +24 -256
- 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-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.d.ts → basecamp/index.d.ts} +6 -28
- package/dist/providers/basecamp/index.js +997 -0
- package/dist/providers/basecamp/skill.generated.js +9 -0
- package/dist/providers/{breeze.d.ts → breeze/index.d.ts} +2 -2
- package/dist/providers/{breeze.js → breeze/index.js} +184 -140
- package/dist/providers/breeze/skill.generated.js +9 -0
- package/dist/providers/{ccb.d.ts → ccb/index.d.ts} +2 -2
- package/dist/providers/{ccb.js → ccb/index.js} +271 -116
- 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.d.ts → overflow/index.d.ts} +2 -2
- package/dist/providers/{overflow.js → overflow/index.js} +74 -111
- package/dist/providers/overflow/skill.generated.js +8 -0
- package/dist/providers/{planning-center.d.ts → planning-center/index.d.ts} +2 -2
- package/dist/providers/{planning-center.js → planning-center/index.js} +264 -104
- 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.d.ts → tithely/index.d.ts} +2 -2
- package/dist/providers/{tithely.js → tithely/index.js} +60 -91
- 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 +110 -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 +664 -231
- package/documentation/auth.md +936 -546
- 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 +120 -54
- 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/basecamp.js +0 -445
- 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
|
@@ -15,8 +15,10 @@ import { fork } from "node:child_process";
|
|
|
15
15
|
import { existsSync } from "node:fs";
|
|
16
16
|
import { fileURLToPath } from "node:url";
|
|
17
17
|
import { Deferred, Duration, Effect, Exit, Schedule, Scope } from "effect";
|
|
18
|
-
import { AdmissionController, ExecutorAdmissionError, ExecutorExecutionError
|
|
18
|
+
import { AdmissionController, ExecutorAdmissionError, ExecutorExecutionError } from "../executor-admission.js";
|
|
19
19
|
import { msg } from "../errors.js";
|
|
20
|
+
import { InvocationFailure } from "../invocation.js";
|
|
21
|
+
import { brandExecutor } from "../executor-contract.js";
|
|
20
22
|
import { MAX_EXECUTE_LOG_CHARS } from "../executor-result.js";
|
|
21
23
|
import { detach, fromSignal, runEdge } from "../runtime/run.js";
|
|
22
24
|
import { hostCallLabel, MAX_QUICKJS_IPC_BYTES, MAX_QUICKJS_HOST_RPC_BYTES, serializedBytes, stringifyBounded, } from "./quickjs-protocol.js";
|
|
@@ -36,10 +38,7 @@ const MAX_CHILD_STDERR_BYTES = 8 * 1024;
|
|
|
36
38
|
const MAX_ERROR_CHARS = 4_000;
|
|
37
39
|
// Respawn backoff after consecutive crashes: 100 ms, doubling, capped at 5 s.
|
|
38
40
|
// A value, not a running effect: stepping it happens inside a request's fiber.
|
|
39
|
-
const CRASH_BACKOFF = Schedule.min([
|
|
40
|
-
Schedule.exponential(Duration.millis(100)),
|
|
41
|
-
Schedule.spaced(Duration.seconds(5)),
|
|
42
|
-
]);
|
|
41
|
+
const CRASH_BACKOFF = Schedule.min([Schedule.exponential(Duration.millis(100)), Schedule.spaced(Duration.seconds(5))]);
|
|
43
42
|
const crashBackoff = Effect.map(Schedule.toStep(CRASH_BACKOFF), (step) => (crashedAt) => step(crashedAt, undefined).pipe(Effect.map(([, delay]) => crashedAt + Duration.toMillis(delay)),
|
|
44
43
|
// Neither schedule ever halts; a halt here would be a broken invariant.
|
|
45
44
|
Effect.orDie));
|
|
@@ -56,36 +55,27 @@ function retainStderrTail(current, chunk) {
|
|
|
56
55
|
function childExitError(message, stderrTail) {
|
|
57
56
|
if (stderrTail.length === 0)
|
|
58
57
|
return new Error(message);
|
|
59
|
-
return new Error(`${message}\nRecent child stderr (last ${stderrTail.length} bytes):\n` +
|
|
60
|
-
stderrTail.toString("utf8"));
|
|
58
|
+
return new Error(`${message}\nRecent child stderr (last ${stderrTail.length} bytes):\n` + stderrTail.toString("utf8"));
|
|
61
59
|
}
|
|
62
60
|
function positiveWhole(value, fallback, name) {
|
|
63
61
|
const resolved = value ?? fallback;
|
|
64
|
-
if (!Number.isFinite(resolved) ||
|
|
65
|
-
!Number.isInteger(resolved) ||
|
|
66
|
-
resolved < 1) {
|
|
62
|
+
if (!Number.isFinite(resolved) || !Number.isInteger(resolved) || resolved < 1) {
|
|
67
63
|
throw new TypeError(`${name} must be a positive whole number.`);
|
|
68
64
|
}
|
|
69
65
|
return resolved;
|
|
70
66
|
}
|
|
71
67
|
function nonNegativeWhole(value, fallback, name) {
|
|
72
68
|
const resolved = value ?? fallback;
|
|
73
|
-
if (!Number.isFinite(resolved) ||
|
|
74
|
-
!Number.isInteger(resolved) ||
|
|
75
|
-
resolved < 0) {
|
|
69
|
+
if (!Number.isFinite(resolved) || !Number.isInteger(resolved) || resolved < 0) {
|
|
76
70
|
throw new TypeError(`${name} must be a non-negative whole number.`);
|
|
77
71
|
}
|
|
78
72
|
return resolved;
|
|
79
73
|
}
|
|
80
74
|
function errorPayload(error) {
|
|
81
|
-
// X11: a partial authenticated frame exposes its secret instead of decoding.
|
|
82
|
-
// Refuse it whole if a host ever bypasses execute.ts's framing bound.
|
|
83
|
-
const message = error.length > MAX_ERROR_CHARS && error.includes("\u001econnecta-error:")
|
|
84
|
-
? `Host failure exceeded the ${MAX_ERROR_CHARS}-character bridge limit.`
|
|
85
|
-
: error.slice(0, MAX_ERROR_CHARS);
|
|
86
75
|
return JSON.stringify({
|
|
87
76
|
ok: false,
|
|
88
|
-
error:
|
|
77
|
+
error: msg(error).slice(0, MAX_ERROR_CHARS),
|
|
78
|
+
...(error instanceof InvocationFailure ? { call: error.details } : {}),
|
|
89
79
|
});
|
|
90
80
|
}
|
|
91
81
|
function cancelled(message) {
|
|
@@ -104,10 +94,7 @@ function unlessCancelled(effect, signal, message) {
|
|
|
104
94
|
return effect;
|
|
105
95
|
if (signal.aborted)
|
|
106
96
|
return Effect.fail(cancelled(message));
|
|
107
|
-
return Effect.raceAllFirst([
|
|
108
|
-
effect,
|
|
109
|
-
fromSignal(signal).pipe(Effect.mapError(() => cancelled(message))),
|
|
110
|
-
]);
|
|
97
|
+
return Effect.raceAllFirst([effect, fromSignal(signal).pipe(Effect.mapError(() => cancelled(message)))]);
|
|
111
98
|
}
|
|
112
99
|
/**
|
|
113
100
|
* The child's release: SIGTERM, then wait for the exit, bounded — a child
|
|
@@ -282,9 +269,19 @@ class QuickJsChildPool {
|
|
|
282
269
|
this.rejectActive(slot, error);
|
|
283
270
|
this.recycle(slot);
|
|
284
271
|
}).pipe(Effect.andThen(Effect.never));
|
|
272
|
+
const started = Date.now();
|
|
285
273
|
const contenders = [
|
|
286
274
|
Deferred.await(active.outcome),
|
|
287
|
-
Effect.sleep(Duration.millis(this.runtimeOptions.timeoutMs + CHILD_EXIT_GRACE_MS)).pipe(Effect.andThen(
|
|
275
|
+
Effect.sleep(Duration.millis(this.runtimeOptions.timeoutMs + CHILD_EXIT_GRACE_MS)).pipe(Effect.andThen(Effect.suspend(() => {
|
|
276
|
+
const elapsedMs = Date.now() - started;
|
|
277
|
+
const deadlineMs = this.runtimeOptions.timeoutMs;
|
|
278
|
+
return endWith(new InvocationFailure({
|
|
279
|
+
code: "timeout",
|
|
280
|
+
message: `Operation "execute_code" timed out during sandbox termination after ${elapsedMs}ms (effective deadline ${deadlineMs}ms).`,
|
|
281
|
+
retryable: false,
|
|
282
|
+
details: { operation: "execute_code", stage: "sandbox termination", elapsedMs, deadlineMs },
|
|
283
|
+
}));
|
|
284
|
+
}))),
|
|
288
285
|
];
|
|
289
286
|
if (signal) {
|
|
290
287
|
contenders.push(fromSignal(signal).pipe(Effect.catch(() => endWith(cancelled("Execution was cancelled.")))));
|
|
@@ -448,7 +445,9 @@ class QuickJsChildPool {
|
|
|
448
445
|
active.logs.push(retained);
|
|
449
446
|
active.logChars += separator + retained.length;
|
|
450
447
|
}
|
|
451
|
-
catch {
|
|
448
|
+
catch {
|
|
449
|
+
/* Malformed log messages carry no output. */
|
|
450
|
+
}
|
|
452
451
|
return;
|
|
453
452
|
}
|
|
454
453
|
if (message.type === "host-call") {
|
|
@@ -487,8 +486,7 @@ class QuickJsChildPool {
|
|
|
487
486
|
async handleHostCall(slot, child, active, message) {
|
|
488
487
|
let payloadJson;
|
|
489
488
|
try {
|
|
490
|
-
if (serializedBytes(message.payloadJson) >
|
|
491
|
-
MAX_QUICKJS_HOST_RPC_BYTES) {
|
|
489
|
+
if (serializedBytes(message.payloadJson) > MAX_QUICKJS_HOST_RPC_BYTES) {
|
|
492
490
|
// Refused before parsing, so there is no address to name here: parsing
|
|
493
491
|
// an over-limit payload to improve its error message would spend the
|
|
494
492
|
// work the limit exists to refuse.
|
|
@@ -496,9 +494,7 @@ class QuickJsChildPool {
|
|
|
496
494
|
}
|
|
497
495
|
const payload = JSON.parse(message.payloadJson);
|
|
498
496
|
const provider = active.providers.get(payload.namespace);
|
|
499
|
-
const fn = provider && Object.hasOwn(provider.fns, payload.functionName)
|
|
500
|
-
? provider.fns[payload.functionName]
|
|
501
|
-
: undefined;
|
|
497
|
+
const fn = provider && Object.hasOwn(provider.fns, payload.functionName) ? provider.fns[payload.functionName] : undefined;
|
|
502
498
|
if (!fn) {
|
|
503
499
|
throw new Error(`Unknown function ${payload.namespace}.${payload.functionName}`);
|
|
504
500
|
}
|
|
@@ -517,7 +513,7 @@ class QuickJsChildPool {
|
|
|
517
513
|
}
|
|
518
514
|
}
|
|
519
515
|
catch (err) {
|
|
520
|
-
payloadJson = errorPayload(
|
|
516
|
+
payloadJson = errorPayload(err);
|
|
521
517
|
}
|
|
522
518
|
if (!child.connected || slot.active !== active)
|
|
523
519
|
return;
|
|
@@ -554,9 +550,7 @@ class QuickJsChildPool {
|
|
|
554
550
|
return;
|
|
555
551
|
// Never concatenate the stream with the final reply: those entries are
|
|
556
552
|
// the same logs. A normal reply retains its existing full log contract.
|
|
557
|
-
const resolved = outcome.logs === undefined && active.logs.length > 0
|
|
558
|
-
? { ...outcome, logs: active.logs }
|
|
559
|
-
: outcome;
|
|
553
|
+
const resolved = outcome.logs === undefined && active.logs.length > 0 ? { ...outcome, logs: active.logs } : outcome;
|
|
560
554
|
this.clearActive(slot);
|
|
561
555
|
Deferred.doneUnsafe(active.outcome, Exit.succeed(resolved));
|
|
562
556
|
}
|
|
@@ -621,5 +615,5 @@ class QuickJsChildPool {
|
|
|
621
615
|
* double-acquire deadlock at concurrency 1.
|
|
622
616
|
*/
|
|
623
617
|
export function quickJsExecutor(options = {}) {
|
|
624
|
-
return new QuickJsChildPool(options);
|
|
618
|
+
return brandExecutor(new QuickJsChildPool(options), "leased");
|
|
625
619
|
}
|
package/dist/favicon.js
CHANGED
|
@@ -32,8 +32,7 @@ function buildIco() {
|
|
|
32
32
|
const dx = x - 15.5;
|
|
33
33
|
const dy = y - 15.5;
|
|
34
34
|
const radius = Math.sqrt(dx * dx + dy * dy);
|
|
35
|
-
const opaque = radius >= 8 && radius <= 13 &&
|
|
36
|
-
(x <= 18 || Math.abs(dy) >= 7);
|
|
35
|
+
const opaque = radius >= 8 && radius <= 13 && (x <= 18 || Math.abs(dy) >= 7);
|
|
37
36
|
const row = size - 1 - y;
|
|
38
37
|
const pixel = pixels + (row * size + x) * 4;
|
|
39
38
|
ico[pixel + 3] = opaque ? 255 : 0;
|
package/dist/fix-prompt.js
CHANGED
|
@@ -18,9 +18,7 @@ const CONNECTOR_ID_RE = /^[a-z0-9_-]+$/;
|
|
|
18
18
|
* than escaped, since a value that is not a connector id is not config.
|
|
19
19
|
*/
|
|
20
20
|
export function renderFixPrompt(spec, connectorId) {
|
|
21
|
-
const id = connectorId !== undefined && CONNECTOR_ID_RE.test(connectorId)
|
|
22
|
-
? connectorId
|
|
23
|
-
: undefined;
|
|
21
|
+
const id = connectorId !== undefined && CONNECTOR_ID_RE.test(connectorId) ? connectorId : undefined;
|
|
24
22
|
return [
|
|
25
23
|
"Diagnose and fix a problem in this connecta deployment (the @zackbart/connecta package). " +
|
|
26
24
|
"It is configured as code: connectors, credential slots, OAuth clients, pools, and inbound auth " +
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/** Capture the single-use runner before evaluating the guest expression. */
|
|
2
|
+
export function wrapGuestProgram(code) {
|
|
3
|
+
return `async () => globalThis.__connecta_run()(async (connecta) => await (\n${code}\n)())`;
|
|
4
|
+
}
|
|
5
|
+
/** Separate user source from the trusted wrapper before publishing Worker modules. */
|
|
6
|
+
export function isolateGuestProgram(code) {
|
|
7
|
+
const prefix = "async () => globalThis.__connecta_run()(";
|
|
8
|
+
const callback = "async (connecta) => await (\n";
|
|
9
|
+
const suffix = "\n)())";
|
|
10
|
+
if (!code.startsWith(prefix + callback) || !code.endsWith(suffix))
|
|
11
|
+
return undefined;
|
|
12
|
+
return {
|
|
13
|
+
program: code.slice(prefix.length, -1),
|
|
14
|
+
// Only this fixed wrapper enters the private runner module. Matching text
|
|
15
|
+
// inside an arbitrary body/string is guest data, never a trusted wrapper.
|
|
16
|
+
wrapper: `${prefix}__connecta_user_program)`,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Emissions are acknowledged before success, even when the guest omits await.
|
|
21
|
+
* Capture intrinsics before user code can replace them.
|
|
22
|
+
*/
|
|
23
|
+
export function guestPrelude() {
|
|
24
|
+
return `${guestInitializer()}(connecta);`;
|
|
25
|
+
}
|
|
26
|
+
/** Protect completion promises before any Worker or QuickJS guest runs. */
|
|
27
|
+
export function guestPromiseInitializer() {
|
|
28
|
+
return `(() => {
|
|
29
|
+
const NativePromise = Promise;
|
|
30
|
+
const nativeResolve = Function.prototype.call.bind(NativePromise.resolve);
|
|
31
|
+
const nativeRace = Function.prototype.call.bind(NativePromise.race);
|
|
32
|
+
const isArray = Array.isArray;
|
|
33
|
+
const iteratorKey = Symbol.iterator;
|
|
34
|
+
const arrayValues = Function.prototype.call.bind(Array.prototype.values);
|
|
35
|
+
const arrayNext = Function.prototype.call.bind(Object.getPrototypeOf([][Symbol.iterator]()).next);
|
|
36
|
+
function safeRace(values) {
|
|
37
|
+
// Upstream constructs its completion array after the program starts.
|
|
38
|
+
// Use captured array iteration, with private own methods, so neither a
|
|
39
|
+
// replaced iterator factory nor iterator.next can observe its promises.
|
|
40
|
+
if (isArray(values)) {
|
|
41
|
+
const iterator = arrayValues(values);
|
|
42
|
+
values = { __proto__: null, [iteratorKey]: () => ({ __proto__: null,
|
|
43
|
+
next: () => arrayNext(iterator) }) };
|
|
44
|
+
}
|
|
45
|
+
return nativeRace(HostPromise, values);
|
|
46
|
+
}
|
|
47
|
+
// The upstream Worker starts its Promise.race after invoking the program.
|
|
48
|
+
// Its deadline must not use a resolve function replaced during that invocation.
|
|
49
|
+
class HostPromise extends NativePromise {}
|
|
50
|
+
Object.defineProperties(HostPromise, {
|
|
51
|
+
resolve: { value: value => nativeResolve(HostPromise, value) },
|
|
52
|
+
[Symbol.species]: { value: HostPromise }
|
|
53
|
+
});
|
|
54
|
+
Object.freeze(HostPromise.prototype);
|
|
55
|
+
Object.freeze(HostPromise);
|
|
56
|
+
Object.defineProperties(NativePromise, {
|
|
57
|
+
race: { value: safeRace, writable: false, configurable: false },
|
|
58
|
+
[Symbol.species]: { value: NativePromise, configurable: false }
|
|
59
|
+
});
|
|
60
|
+
// Async return values are adopted through their prototype's then method.
|
|
61
|
+
// Guest callbacks must not change host completion.
|
|
62
|
+
Object.freeze(NativePromise.prototype);
|
|
63
|
+
})()`;
|
|
64
|
+
}
|
|
65
|
+
/** Capture a private initializer before a Worker evaluates its guest module. */
|
|
66
|
+
export function guestInitializer() {
|
|
67
|
+
return `(() => {
|
|
68
|
+
${guestPromiseInitializer()};
|
|
69
|
+
const NativePromise = Promise;
|
|
70
|
+
const freeze = Object.freeze;
|
|
71
|
+
const defineProperties = Object.defineProperties;
|
|
72
|
+
// Protect the bridge codec and its object prototypes from guest hooks.
|
|
73
|
+
freeze(JSON);
|
|
74
|
+
freeze(Object.prototype);
|
|
75
|
+
defineProperties(globalThis, {
|
|
76
|
+
JSON: { value: JSON, writable: false, configurable: false },
|
|
77
|
+
Promise: { value: NativePromise, writable: false, configurable: false }
|
|
78
|
+
});
|
|
79
|
+
const promiseThen = Function.prototype.call.bind(NativePromise.prototype.then);
|
|
80
|
+
const promiseCatch = Function.prototype.call.bind(NativePromise.prototype.catch);
|
|
81
|
+
const promiseFinally = Function.prototype.call.bind(NativePromise.prototype.finally);
|
|
82
|
+
const push = Function.prototype.call.bind(Array.prototype.push);
|
|
83
|
+
const NativeError = Error;
|
|
84
|
+
return freeze((provider) => {
|
|
85
|
+
const pending = [];
|
|
86
|
+
const emit = provider.emit;
|
|
87
|
+
function trackEmission(task) {
|
|
88
|
+
const entry = { handled: false, settled: promiseThen(task,
|
|
89
|
+
() => ({ ok: true }), error => ({ ok: false, error })) };
|
|
90
|
+
push(pending, entry);
|
|
91
|
+
// Every derived promise owns propagated rejection; only an unhandled
|
|
92
|
+
// leaf fails the run, so a later catch also handles its ancestors.
|
|
93
|
+
return freeze({
|
|
94
|
+
then(resolve, reject) {
|
|
95
|
+
entry.handled = true;
|
|
96
|
+
return trackEmission(promiseThen(task, resolve, reject));
|
|
97
|
+
},
|
|
98
|
+
catch(reject) {
|
|
99
|
+
entry.handled = true;
|
|
100
|
+
return trackEmission(promiseCatch(task, reject));
|
|
101
|
+
},
|
|
102
|
+
finally(callback) {
|
|
103
|
+
entry.handled = true;
|
|
104
|
+
return trackEmission(promiseFinally(task, callback));
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const namespace = freeze({
|
|
109
|
+
__proto__: null,
|
|
110
|
+
search: provider.search,
|
|
111
|
+
describe: provider.describe,
|
|
112
|
+
call: provider.call,
|
|
113
|
+
read: provider.read,
|
|
114
|
+
result: provider.result,
|
|
115
|
+
skill: provider.skill,
|
|
116
|
+
emit(block) { return trackEmission(emit(block)); }
|
|
117
|
+
});
|
|
118
|
+
globalThis.connecta = namespace;
|
|
119
|
+
defineProperties(globalThis, {
|
|
120
|
+
Error: { value: NativeError, writable: false, configurable: false },
|
|
121
|
+
__connecta_run: { configurable: true, value: () => {
|
|
122
|
+
delete globalThis.__connecta_run;
|
|
123
|
+
let used = false;
|
|
124
|
+
return async (program) => {
|
|
125
|
+
if (used) throw new NativeError("Guest runner initialization is single-use.");
|
|
126
|
+
used = true;
|
|
127
|
+
const result = await program(namespace);
|
|
128
|
+
for (let i = 0; i < pending.length; i++) {
|
|
129
|
+
const report = await pending[i].settled;
|
|
130
|
+
if (!report.ok && !pending[i].handled) throw report.error;
|
|
131
|
+
}
|
|
132
|
+
return result;
|
|
133
|
+
};
|
|
134
|
+
}}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
})()`;
|
|
138
|
+
}
|
|
139
|
+
const ERROR_NAMES = new Set([
|
|
140
|
+
"Error",
|
|
141
|
+
"TypeError",
|
|
142
|
+
"SyntaxError",
|
|
143
|
+
"ReferenceError",
|
|
144
|
+
"RangeError",
|
|
145
|
+
"EvalError",
|
|
146
|
+
"URIError",
|
|
147
|
+
"AggregateError",
|
|
148
|
+
]);
|
|
149
|
+
/** Fixed repair guidance, used only in agent-facing results. */
|
|
150
|
+
export function programError(raw, code) {
|
|
151
|
+
const message = typeof raw.message === "string" ? raw.message : "Program failed.";
|
|
152
|
+
const name = typeof raw.name === "string" && ERROR_NAMES.has(raw.name) ? raw.name : "Error";
|
|
153
|
+
const stack = typeof raw.stack === "string" ? raw.stack : "";
|
|
154
|
+
// Compare QuickJS/V8 locations to the wrapper baseline after the source.
|
|
155
|
+
const location = /:(\d+)(?::\d+)?\)?(?:\n|$)/.exec(stack);
|
|
156
|
+
const baseline = typeof raw.baseline === "string" ? /:(\d+)(?::\d+)?\)?(?:\n|$)/.exec(raw.baseline) : null;
|
|
157
|
+
// Workers publish only the user callback in this module, with one prefix line.
|
|
158
|
+
// Its trusted wrapper and baseline live in a separate, private module scope.
|
|
159
|
+
const workerLocation = /connecta-guest\.js:(\d+):\d+/.exec(stack);
|
|
160
|
+
const line = typeof raw.line === "number" && Number.isFinite(raw.line)
|
|
161
|
+
? Math.max(1, raw.line)
|
|
162
|
+
: workerLocation
|
|
163
|
+
? Math.max(1, Number(workerLocation[1]) - 1)
|
|
164
|
+
: location && baseline
|
|
165
|
+
? Math.max(1, Number(location[1]) - Number(baseline[1]) + code.split("\n").length + 1)
|
|
166
|
+
: null;
|
|
167
|
+
let hint = "Use plain JavaScript in one async () => { ... } expression and the connecta global.";
|
|
168
|
+
if (/\brequire\b|\b[Ii]mports?\b|\bfs\b|filesystem|node:/.test(message) ||
|
|
169
|
+
(name === "SyntaxError" && /\bimport\b/.test(code))) {
|
|
170
|
+
hint =
|
|
171
|
+
"Imports, require, and filesystem access are outside the guest API. Use connecta.call to access configured services.";
|
|
172
|
+
}
|
|
173
|
+
else if (["TypeError", "ReferenceError"].includes(name) &&
|
|
174
|
+
/(?:const|let|var|function|\()\s*connecta\b/.test(code)) {
|
|
175
|
+
hint = "Do not shadow connecta. Use the host-provided connecta global.";
|
|
176
|
+
}
|
|
177
|
+
else if (/callTool|mixpanel|\bskills\b|connecta\.(?:guide|skills)/.test(message) ||
|
|
178
|
+
(["TypeError", "ReferenceError"].includes(name) && /connecta\.(?:guide|skills)\b/.test(code))) {
|
|
179
|
+
hint =
|
|
180
|
+
"Use connecta.call(address, args), connecta.search, connecta.describe, connecta.result, and connecta.skill(name). Services are addressed by connector.tool, never guest globals.";
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
code: "program_error",
|
|
184
|
+
message: `Program ${name}: ${message}`,
|
|
185
|
+
retryable: false,
|
|
186
|
+
details: { name, line, hint },
|
|
187
|
+
};
|
|
188
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import type { ToolDef } from "./types.js";
|
|
2
|
+
import type { CallErrorDetails } from "./errors.js";
|
|
3
|
+
/** TypeScript notation for the JavaScript guest global; programs receive no arguments. */
|
|
4
|
+
export interface GuestApi {
|
|
5
|
+
search(args?: CatalogSearchArgs): Promise<CatalogSearchResult>;
|
|
6
|
+
describe(args?: CatalogDescribeArgs): Promise<{
|
|
7
|
+
tools: CatalogDescription[];
|
|
8
|
+
}>;
|
|
9
|
+
call(address: string, args?: unknown, options?: {
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}): Promise<GuestResult>;
|
|
12
|
+
call(request: {
|
|
13
|
+
address: string;
|
|
14
|
+
args?: unknown;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
}): Promise<GuestResult>;
|
|
17
|
+
read(uri: string): Promise<GuestResourceResult>;
|
|
18
|
+
result(id: string, options?: {
|
|
19
|
+
offset?: number;
|
|
20
|
+
maxBytes?: number;
|
|
21
|
+
}): Promise<GuestResultPage>;
|
|
22
|
+
skill(name: string): Promise<{
|
|
23
|
+
name: string;
|
|
24
|
+
text: string;
|
|
25
|
+
format: "text";
|
|
26
|
+
}>;
|
|
27
|
+
emit(block: GuestBlock): PromiseLike<void>;
|
|
28
|
+
}
|
|
29
|
+
export interface GuestResourceResult {
|
|
30
|
+
contents: Array<{
|
|
31
|
+
uri: string;
|
|
32
|
+
mimeType?: string;
|
|
33
|
+
} & ({
|
|
34
|
+
text: string;
|
|
35
|
+
} | {
|
|
36
|
+
blob: string;
|
|
37
|
+
})>;
|
|
38
|
+
}
|
|
39
|
+
export type GuestResult = {
|
|
40
|
+
data: unknown;
|
|
41
|
+
format: "json";
|
|
42
|
+
} | {
|
|
43
|
+
data: string;
|
|
44
|
+
format: "text";
|
|
45
|
+
};
|
|
46
|
+
export interface GuestResultPage {
|
|
47
|
+
resultId: string;
|
|
48
|
+
offset: number;
|
|
49
|
+
bytes: number;
|
|
50
|
+
totalBytes: number;
|
|
51
|
+
hasMore: boolean;
|
|
52
|
+
nextOffset?: number;
|
|
53
|
+
format: "text";
|
|
54
|
+
text: string;
|
|
55
|
+
}
|
|
56
|
+
export type GuestBlock = {
|
|
57
|
+
type: "text";
|
|
58
|
+
text: string;
|
|
59
|
+
} | {
|
|
60
|
+
type: "image" | "audio";
|
|
61
|
+
data: string;
|
|
62
|
+
mimeType: string;
|
|
63
|
+
};
|
|
64
|
+
type SchemaFormat = "json" | "compact" | "typescript";
|
|
65
|
+
export interface CatalogSearchArgs {
|
|
66
|
+
query?: string;
|
|
67
|
+
connector?: string;
|
|
68
|
+
safety?: "readOnly" | "approvalRequired" | "all";
|
|
69
|
+
limit?: number;
|
|
70
|
+
offset?: number;
|
|
71
|
+
fullDescriptions?: boolean;
|
|
72
|
+
includeSchemas?: SchemaFormat;
|
|
73
|
+
includeSchemaKeys?: boolean;
|
|
74
|
+
}
|
|
75
|
+
export interface CatalogDescribeArgs {
|
|
76
|
+
address?: unknown;
|
|
77
|
+
addresses?: unknown;
|
|
78
|
+
format?: SchemaFormat;
|
|
79
|
+
fullDescriptions?: boolean;
|
|
80
|
+
}
|
|
81
|
+
type GuideRequiredReason = "connector_required" | "approval_required" | "schema_truncated";
|
|
82
|
+
interface CatalogFailureDetail {
|
|
83
|
+
code: string;
|
|
84
|
+
message: string;
|
|
85
|
+
retryable: boolean;
|
|
86
|
+
retryAfterMs?: number;
|
|
87
|
+
}
|
|
88
|
+
interface CatalogDescriptionFailureDetail extends CatalogFailureDetail {
|
|
89
|
+
configuredConnectors?: string[];
|
|
90
|
+
nextAction?: NonNullable<CallErrorDetails["nextAction"]>;
|
|
91
|
+
suggestions?: string[];
|
|
92
|
+
}
|
|
93
|
+
interface CatalogSearchFailure extends CatalogFailureDetail {
|
|
94
|
+
connector: string;
|
|
95
|
+
recovery?: CallErrorDetails["recovery"];
|
|
96
|
+
nextAction?: Extract<NonNullable<CallErrorDetails["nextAction"]>, {
|
|
97
|
+
tool: "authorize_connector";
|
|
98
|
+
}>;
|
|
99
|
+
retry?: string;
|
|
100
|
+
}
|
|
101
|
+
export interface CatalogSearchPage {
|
|
102
|
+
catalogErrors: CatalogSearchFailure[];
|
|
103
|
+
absence?: {
|
|
104
|
+
service: string;
|
|
105
|
+
message: string;
|
|
106
|
+
configuredConnectors: string[];
|
|
107
|
+
};
|
|
108
|
+
total: number;
|
|
109
|
+
offset: number;
|
|
110
|
+
limit: number;
|
|
111
|
+
hasMore: boolean;
|
|
112
|
+
nextOffset?: number;
|
|
113
|
+
matchMode?: "partial";
|
|
114
|
+
queryAnalysis?: {
|
|
115
|
+
representedTerms: string[];
|
|
116
|
+
otherResultTerms: string[];
|
|
117
|
+
unmatchedTerms: string[];
|
|
118
|
+
truncated?: true;
|
|
119
|
+
connectorScope?: string;
|
|
120
|
+
unknownConnector?: true;
|
|
121
|
+
configuredConnectors?: string[];
|
|
122
|
+
unavailableConnectorCount?: number;
|
|
123
|
+
catalogError?: CatalogFailureDetail;
|
|
124
|
+
guide?: string;
|
|
125
|
+
guideSummary?: string;
|
|
126
|
+
guideRequired?: true;
|
|
127
|
+
guideRequiredReasons?: GuideRequiredReason[];
|
|
128
|
+
guidance?: string;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export type CatalogSearchResult = CatalogSearchPage & {
|
|
132
|
+
tools: Array<CatalogSearchTool & {
|
|
133
|
+
connectorTitle?: string;
|
|
134
|
+
guide?: string;
|
|
135
|
+
guideSummary?: string;
|
|
136
|
+
}>;
|
|
137
|
+
};
|
|
138
|
+
export interface CatalogDescription {
|
|
139
|
+
address: string;
|
|
140
|
+
schemaFormat?: "json" | "text";
|
|
141
|
+
name?: string;
|
|
142
|
+
description?: string;
|
|
143
|
+
guide?: string;
|
|
144
|
+
guideSummary?: string;
|
|
145
|
+
guideRequired?: true;
|
|
146
|
+
guideRequiredReasons?: GuideRequiredReason[];
|
|
147
|
+
inputSchema?: unknown;
|
|
148
|
+
outputSchema?: unknown;
|
|
149
|
+
signature?: string;
|
|
150
|
+
outputSchemaSource?: "observed";
|
|
151
|
+
inputSchemaTruncated?: true;
|
|
152
|
+
outputSchemaTruncated?: true;
|
|
153
|
+
annotations?: ToolDef["annotations"];
|
|
154
|
+
error?: string;
|
|
155
|
+
errorDetails?: CatalogDescriptionFailureDetail;
|
|
156
|
+
}
|
|
157
|
+
type CatalogSearchTool = {
|
|
158
|
+
name: string;
|
|
159
|
+
address: string;
|
|
160
|
+
description?: string;
|
|
161
|
+
inputSchema?: unknown;
|
|
162
|
+
outputSchema?: unknown;
|
|
163
|
+
signature?: string;
|
|
164
|
+
schemaFormat?: "json" | "text";
|
|
165
|
+
outputSchemaSource?: "observed";
|
|
166
|
+
inputSchemaTruncated?: true;
|
|
167
|
+
outputSchemaTruncated?: true;
|
|
168
|
+
inputKeys?: string[];
|
|
169
|
+
requiredInputKeys?: string[];
|
|
170
|
+
outputKeys?: string[];
|
|
171
|
+
annotations?: ToolDef["annotations"];
|
|
172
|
+
classification?: ToolDef["classification"];
|
|
173
|
+
guideRequired?: true;
|
|
174
|
+
guideRequiredReasons?: GuideRequiredReason[];
|
|
175
|
+
};
|
|
176
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Common headers for HTML, including script-free status and error pages. */
|
|
2
|
+
export function htmlSecurityHeaders(initial, options = {}) {
|
|
3
|
+
const headers = new Headers(initial);
|
|
4
|
+
const { clerkOrigin, nonce } = options;
|
|
5
|
+
// Clerk's CAPTCHA host is exact and only admitted with a validated loader
|
|
6
|
+
// origin. No wildcard or general HTTPS script permission is needed.
|
|
7
|
+
const scripts = `${nonce ? `'nonce-${nonce}' ` : ""}'self'` +
|
|
8
|
+
(clerkOrigin ? ` ${clerkOrigin} https://challenges.cloudflare.com` : "");
|
|
9
|
+
if (!headers.has("Content-Security-Policy")) {
|
|
10
|
+
headers.set("Content-Security-Policy", `script-src ${scripts}; object-src 'none'; base-uri 'none'; frame-ancestors 'none'` +
|
|
11
|
+
(clerkOrigin
|
|
12
|
+
? `; connect-src 'self' ${clerkOrigin}; img-src 'self' https://img.clerk.com; worker-src 'self' blob:; style-src 'self' 'unsafe-inline'`
|
|
13
|
+
: "") +
|
|
14
|
+
(clerkOrigin ? "; frame-src https://challenges.cloudflare.com" : ""));
|
|
15
|
+
}
|
|
16
|
+
if (headers.get("Content-Security-Policy").includes("frame-ancestors 'none'")) {
|
|
17
|
+
headers.set("X-Frame-Options", "DENY");
|
|
18
|
+
}
|
|
19
|
+
headers.set("X-Content-Type-Options", "nosniff");
|
|
20
|
+
headers.set("Referrer-Policy", "no-referrer");
|
|
21
|
+
if (!headers.has("Cache-Control"))
|
|
22
|
+
headers.set("Cache-Control", "no-store");
|
|
23
|
+
return headers;
|
|
24
|
+
}
|
package/dist/identity.js
CHANGED
|
@@ -8,9 +8,7 @@ export function validIdentityReference(value) {
|
|
|
8
8
|
IDENTITY_PART_RE.test(value.id));
|
|
9
9
|
}
|
|
10
10
|
function bytesToHex(bytes) {
|
|
11
|
-
return [...bytes]
|
|
12
|
-
.map((byte) => byte.toString(16).padStart(2, "0"))
|
|
13
|
-
.join("");
|
|
11
|
+
return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
14
12
|
}
|
|
15
13
|
/** Deterministic pseudonymous partition; raw emails and ids do not enter keys. */
|
|
16
14
|
export async function identityStorageKey(identity) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const parsed = new WeakMap();
|
|
2
|
+
/** One strict parse shared by recognition and verification. Schemes ignore case. */
|
|
3
|
+
export function authorizationCredential(request) {
|
|
4
|
+
const header = request.headers.get("authorization");
|
|
5
|
+
const cached = parsed.get(request);
|
|
6
|
+
if (cached?.header === header)
|
|
7
|
+
return cached.credential;
|
|
8
|
+
// Exactly one separator and one token68 value. Reject combined duplicate
|
|
9
|
+
// headers and malformed spacing rather than letting an SDK repair them.
|
|
10
|
+
const match = header === null ? null : /^Bearer ([A-Za-z0-9._~+/-]+=*)$/i.exec(header);
|
|
11
|
+
const credential = header === null
|
|
12
|
+
? { kind: "absent" }
|
|
13
|
+
: match
|
|
14
|
+
? { kind: "bearer", token: match[1], value: `Bearer ${match[1]}` }
|
|
15
|
+
: { kind: "invalid" };
|
|
16
|
+
parsed.set(request, { header, credential });
|
|
17
|
+
return credential;
|
|
18
|
+
}
|
|
19
|
+
/** Explicit headers exclude cookies and Clerk's browser handshake credentials. */
|
|
20
|
+
export function authorizationRequest(request) {
|
|
21
|
+
const credential = authorizationCredential(request);
|
|
22
|
+
if (credential.kind === "absent")
|
|
23
|
+
return request;
|
|
24
|
+
const headers = new Headers(request.headers);
|
|
25
|
+
headers.delete("cookie");
|
|
26
|
+
if (credential.kind === "bearer")
|
|
27
|
+
headers.set("authorization", credential.value);
|
|
28
|
+
const url = new URL(request.url);
|
|
29
|
+
for (const key of new Set(url.searchParams.keys())) {
|
|
30
|
+
if (key.startsWith("__clerk") || key === "__session" || key === "__dev_session")
|
|
31
|
+
url.searchParams.delete(key);
|
|
32
|
+
}
|
|
33
|
+
if (url.href === request.url &&
|
|
34
|
+
!request.headers.has("cookie") &&
|
|
35
|
+
headers.get("authorization") === request.headers.get("authorization"))
|
|
36
|
+
return request;
|
|
37
|
+
// Share the body without cloning/teeing or transferring the original
|
|
38
|
+
// request: the route must still be able to read it after authentication.
|
|
39
|
+
const normalized = new Request(url, {
|
|
40
|
+
method: request.method,
|
|
41
|
+
headers,
|
|
42
|
+
signal: request.signal,
|
|
43
|
+
...(request.body ? { body: request.body, duplex: "half" } : {}),
|
|
44
|
+
});
|
|
45
|
+
parsed.set(normalized, { header: headers.get("authorization"), credential });
|
|
46
|
+
return normalized;
|
|
47
|
+
}
|
|
48
|
+
/** Reserved machine syntax, even when the optional verifier is not installed. */
|
|
49
|
+
export function isMachineCredential(request) {
|
|
50
|
+
const credential = authorizationCredential(request);
|
|
51
|
+
return credential.kind === "bearer" && credential.token.startsWith("cta_");
|
|
52
|
+
}
|