@zackbart/connecta 0.37.0 → 0.38.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 +80 -0
- package/README.md +2 -2
- package/bin/connecta.mjs +1 -39
- package/bin/version.mjs +1 -1
- package/dist/access-tokens.js +2 -4
- package/dist/agent-identity.js +1 -1
- package/dist/auth/clerk-sdk/generated.js +2 -1
- package/dist/auth/cloudflare-access.d.ts +3 -1
- package/dist/auth/cloudflare-access.js +22 -11
- package/dist/auth/downstream-oauth.js +195 -270
- package/dist/auth/downstream-revocation.js +1 -1
- package/dist/auth/oauth-grant.js +11 -0
- package/dist/auth/oauth-token-response.js +1 -1
- package/dist/auth/vercel-agent.js +2 -1
- package/dist/auth-elicitation.js +2 -2
- package/dist/branding.d.ts +1 -15
- package/dist/branding.js +2 -2
- package/dist/bytes.js +42 -0
- package/dist/call-admission-context.js +2 -5
- package/dist/call-admission.js +5 -0
- package/dist/call-recovery.js +0 -3
- package/dist/catalog-cache.js +26 -7
- package/dist/catalog-fingerprint.js +2 -18
- package/dist/catalog-revision.js +9 -0
- package/dist/catalog-service.js +51 -20
- package/dist/config-defaults.d.ts +1 -0
- package/dist/config-defaults.js +1 -0
- package/dist/config-schema.d.ts +1 -1
- package/dist/config-schema.js +6 -2
- package/dist/config.d.ts +41 -14
- package/dist/config.js +21 -71
- package/dist/connector-caller.js +1 -1
- package/dist/connectors/api-connector.js +4 -3
- package/dist/connectors/guarded-fetch.d.ts +0 -6
- package/dist/connectors/guarded-fetch.js +1 -11
- package/dist/connectors/remote-mcp.js +93 -69
- package/dist/connectors/resource-uri.js +0 -4
- package/dist/credentials.js +3 -0
- package/dist/d1.d.ts +0 -89
- package/dist/d1.js +0 -34
- package/dist/downstream-input.js +2 -2
- package/dist/execute.js +161 -116
- package/dist/executor-result.js +2 -1
- package/dist/executors/quickjs-runtime.js +2 -25
- package/dist/executors/quickjs.js +1 -1
- package/dist/guest-runtime.js +5 -3
- package/dist/guest-types.d.ts +5 -5
- package/dist/http/client.js +1 -1
- package/dist/http/errors.js +2 -2
- package/dist/http/json-schema.js +1 -1
- package/dist/http/node-transport.js +0 -1
- package/dist/http/oauth.js +1 -1
- package/dist/http/paging.js +6 -9
- package/dist/http/provider.js +1 -1
- package/dist/http/safety.js +1 -1
- package/dist/http/services.js +1 -8
- package/dist/http/tools.js +1 -7
- package/dist/http/vendor.js +7 -7
- package/dist/identity.js +2 -6
- package/dist/index.js +1 -2
- package/dist/invocation-auth.js +2 -1
- package/dist/invocation.js +8 -2
- package/dist/meta-tools.js +27 -27
- package/dist/native-tools.js +2 -1
- package/dist/oauth-handoff.js +2 -2
- package/dist/operation-vocabulary.js +1 -1
- package/dist/operator-record.d.ts +8 -2
- package/dist/operator-record.js +18 -50
- package/dist/operator-ui/contract.d.ts +4 -2
- package/dist/operator-ui/generated.js +3 -3
- package/dist/operator-ui/model.d.ts +7 -2
- package/dist/program-writes.js +3 -8
- package/dist/provider-call.js +0 -7
- package/dist/provider.d.ts +1 -1
- package/dist/providers/_shared/google/kit.js +1 -6
- package/dist/providers/_shared/google/service-account.js +1 -3
- package/dist/providers/_shared/google/workspace.d.ts +1 -1
- package/dist/providers/_shared/guide.js +3 -0
- package/dist/providers/_shared/json.js +12 -0
- package/dist/providers/_shared/rest/compact-index.js +1 -1
- package/dist/providers/_shared/rest/kit.js +1 -3
- package/dist/providers/_shared/rest/operation-index.js +1 -3
- package/dist/providers/_shared/rest/value-safety.js +26 -28
- package/dist/providers/breeze/api.js +2 -7
- package/dist/providers/breeze/index.js +4 -2
- package/dist/providers/breeze/tools.js +3 -4
- package/dist/providers/ccb/api.js +1 -6
- package/dist/providers/ccb/index.js +2 -1
- package/dist/providers/ccb/tools.js +1 -6
- package/dist/providers/cloudflare/api.js +2 -2
- package/dist/providers/cloudflare/index.js +2 -1
- package/dist/providers/cloudflare/safety.js +3 -3
- package/dist/providers/docs/tools.js +2 -10
- package/dist/providers/drive/tools.js +12 -25
- package/dist/providers/forms/tools.js +1 -9
- package/dist/providers/gmail/tools.js +5 -21
- package/dist/providers/overflow/api.js +1 -3
- package/dist/providers/overflow/index.js +2 -1
- package/dist/providers/overflow/tools.js +3 -7
- package/dist/providers/planning-center/api.js +2 -1
- package/dist/providers/planning-center/lib/constants.d.ts +1 -1
- package/dist/providers/planning-center/lib/json-api.js +1 -9
- package/dist/providers/planning-center/tools.js +2 -1
- package/dist/providers/sheets/tools.js +1 -9
- package/dist/providers/slides/tools.js +4 -13
- package/dist/providers/stripe/index.js +2 -1
- package/dist/providers/stripe/safety.js +2 -2
- package/dist/providers/tithely/api.js +2 -7
- package/dist/providers/tithely/index.js +3 -2
- package/dist/providers/tithely/tools.js +7 -5
- package/dist/providers/vercel/api.js +1 -6
- package/dist/providers/vercel/lib/pin.js +1 -1
- package/dist/providers/vercel/safety.js +1 -1
- package/dist/providers/vercel/tools.js +2 -1
- package/dist/redaction-marker.js +2 -2
- package/dist/registry.d.ts +4 -1
- package/dist/registry.js +35 -22
- package/dist/request-principal.js +15 -2
- package/dist/request-state.js +2 -2
- package/dist/routes/access-tokens.js +1 -1
- package/dist/routes/activity-disclosure.js +1 -1
- package/dist/routes/connect.js +2 -2
- package/dist/routes/credentials.js +1 -1
- package/dist/routes/dispatch.js +10 -0
- package/dist/routes/mcp.js +23 -21
- package/dist/routes/oauth-management.js +1 -1
- package/dist/routes/operator.js +53 -7
- package/dist/routes/shared.d.ts +8 -8
- package/dist/routes/shared.js +22 -15
- package/dist/routes/ui-config.js +6 -6
- package/dist/routes/ui-data.js +2 -2
- package/dist/routes/ui.js +9 -4
- package/dist/runtime/call-admission.js +1 -1
- package/dist/runtime/call.js +1 -1
- package/dist/runtime/settlement.js +1 -1
- package/dist/runtime/shared-read.js +2 -15
- package/dist/sent-secrets.d.ts +14 -6
- package/dist/sent-secrets.js +231 -85
- package/dist/server.js +4 -4
- package/dist/skills.js +8 -35
- package/dist/sqlite.d.ts +0 -19
- package/dist/sqlite.js +2 -83
- package/dist/storage/keys.js +29 -124
- package/dist/storage/sql-native.js +14 -111
- package/dist/storage/sql.d.ts +1 -24
- package/dist/storage/sql.js +1 -12
- package/dist/tool-error.js +4 -0
- package/dist/types.d.ts +4 -3
- package/dist/ui.js +3 -0
- package/dist/url-safety.js +0 -4
- package/dist/usage-guide.js +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker.js +1 -1
- package/documentation/README.md +6 -42
- package/documentation/architecture.md +190 -507
- package/documentation/auth.md +172 -58
- package/documentation/code-mode.md +98 -66
- package/documentation/deploying.md +19 -40
- package/documentation/integrating.md +8 -19
- package/documentation/meta-tools.md +23 -6
- package/documentation/migration-0.33.md +5 -5
- package/documentation/migration-0.34.md +2 -4
- package/documentation/migration-retired-layouts.md +74 -0
- package/documentation/operator-tests.md +19 -119
- package/documentation/operator-ui.md +46 -8
- package/documentation/provider-auth-migration.md +4 -10
- package/documentation/provider-migration-0.29.md +4 -15
- package/examples/worker/AGENTS.md +4 -6
- package/examples/worker/README.md +20 -115
- package/guides/connecting-agents.md +7 -30
- package/guides/how-it-works.md +2 -2
- package/guides/safety-and-trust.md +4 -1
- package/package.json +19 -19
- package/templates/node/README.md +9 -26
- package/templates/node/package.json +1 -1
- package/dist/auth/oauth-v2-migration.js +0 -135
- package/dist/provider-call-facts.d.ts +0 -115
- package/dist/provider-call.d.ts +0 -112
- package/dist/storage/d1-copy.js +0 -255
- package/dist/storage/sql-schema.d.ts +0 -6
- package/examples/worker/kv-to-d1.wrangler.jsonc +0 -26
- package/examples/worker/scripts/copy-kv-to-d1.mjs +0 -162
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { utf8Length } from "../bytes.js";
|
|
1
2
|
// QuickJS-in-WebAssembly runtime used inside the disposable child process.
|
|
2
3
|
//
|
|
3
4
|
// Model-written code runs inside a QuickJS interpreter compiled to WASM:
|
|
@@ -37,30 +38,6 @@ function logTransportBytes(entry) {
|
|
|
37
38
|
// encoded into ChildToParentMessage. Measure the units the IPC cap sees.
|
|
38
39
|
return serializedBytes(JSON.stringify(JSON.stringify(entry)));
|
|
39
40
|
}
|
|
40
|
-
function exceedsUtf8ByteLimit(value, limit) {
|
|
41
|
-
let bytes = 0;
|
|
42
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
43
|
-
const code = value.charCodeAt(index);
|
|
44
|
-
if (code <= 0x7f)
|
|
45
|
-
bytes += 1;
|
|
46
|
-
else if (code <= 0x7ff)
|
|
47
|
-
bytes += 2;
|
|
48
|
-
else if (code >= 0xd800 &&
|
|
49
|
-
code <= 0xdbff &&
|
|
50
|
-
index + 1 < value.length &&
|
|
51
|
-
value.charCodeAt(index + 1) >= 0xdc00 &&
|
|
52
|
-
value.charCodeAt(index + 1) <= 0xdfff) {
|
|
53
|
-
bytes += 4;
|
|
54
|
-
index += 1;
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
bytes += 3;
|
|
58
|
-
}
|
|
59
|
-
if (bytes > limit)
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
41
|
/** Normalize model output into an async-arrow expression: strip markdown fences, wrap bare bodies. */
|
|
65
42
|
export function normalizeCode(code) {
|
|
66
43
|
let c = code.trim();
|
|
@@ -216,7 +193,7 @@ function installBridge(ctx, providers, logs, onLog) {
|
|
|
216
193
|
catch (err) {
|
|
217
194
|
throw new Error(`Host result from ${label} could not be serialized: ${msg(err)}`);
|
|
218
195
|
}
|
|
219
|
-
if (
|
|
196
|
+
if (utf8Length(json, MAX_HOST_RESULT_BYTES) > MAX_HOST_RESULT_BYTES) {
|
|
220
197
|
throw new Error(`Host result from ${label} exceeds the ${MAX_HOST_RESULT_BYTES}-byte serialized bridge limit.`);
|
|
221
198
|
}
|
|
222
199
|
return { json };
|
|
@@ -119,7 +119,7 @@ function terminate(child) {
|
|
|
119
119
|
}
|
|
120
120
|
let providePoolProgram;
|
|
121
121
|
class QuickJsChildPool {
|
|
122
|
-
/** What `/health` and `connecta doctor` call this sandbox
|
|
122
|
+
/** What `/health` and `connecta doctor` call this sandbox. */
|
|
123
123
|
name = "QuickJS";
|
|
124
124
|
admission;
|
|
125
125
|
slots;
|
package/dist/guest-runtime.js
CHANGED
|
@@ -160,6 +160,8 @@ export function guestInitializer() {
|
|
|
160
160
|
read: provider.read,
|
|
161
161
|
result: provider.result,
|
|
162
162
|
skill: provider.skill,
|
|
163
|
+
// Undeclared alias: models write connecta.skills, the top-level tool's name.
|
|
164
|
+
skills: provider.skill,
|
|
163
165
|
emit(block) {
|
|
164
166
|
const ref = block && typeof block === "object" ? weakGet(nativeRefs, block) : undefined;
|
|
165
167
|
return trackEmission(emit(ref || block));
|
|
@@ -224,10 +226,10 @@ export function programError(raw, code) {
|
|
|
224
226
|
/(?:const|let|var|function|\()\s*connecta\b/.test(code)) {
|
|
225
227
|
hint = "Do not shadow connecta. Use the host-provided connecta global.";
|
|
226
228
|
}
|
|
227
|
-
else if (/callTool|\bskills\b|connecta\.
|
|
228
|
-
(["TypeError", "ReferenceError"].includes(name) && /connecta\.
|
|
229
|
+
else if (/callTool|\bskills\b|connecta\.guide/.test(message) ||
|
|
230
|
+
(["TypeError", "ReferenceError"].includes(name) && /connecta\.guide\b/.test(code))) {
|
|
229
231
|
hint =
|
|
230
|
-
|
|
232
|
+
'Use connecta.call(address, args), connecta.search, connecta.describe, connecta.result, and connecta.skill("usage"). Services are addressed by connector.tool, never guest globals.';
|
|
231
233
|
}
|
|
232
234
|
return {
|
|
233
235
|
code: "program_error",
|
package/dist/guest-types.d.ts
CHANGED
|
@@ -103,7 +103,7 @@ export type GuestBlock = {
|
|
|
103
103
|
mimeType: string;
|
|
104
104
|
};
|
|
105
105
|
type SchemaFormat = "json" | "compact" | "typescript";
|
|
106
|
-
|
|
106
|
+
interface CatalogSearchArgs {
|
|
107
107
|
query?: string;
|
|
108
108
|
connector?: string;
|
|
109
109
|
safety?: "readOnly" | "approvalRequired" | "all";
|
|
@@ -113,7 +113,7 @@ export interface CatalogSearchArgs {
|
|
|
113
113
|
includeSchemas?: SchemaFormat;
|
|
114
114
|
includeSchemaKeys?: boolean;
|
|
115
115
|
}
|
|
116
|
-
|
|
116
|
+
interface CatalogDescribeArgs {
|
|
117
117
|
address?: unknown;
|
|
118
118
|
addresses?: unknown;
|
|
119
119
|
format?: SchemaFormat;
|
|
@@ -140,7 +140,7 @@ interface CatalogSearchFailure extends CatalogFailureDetail {
|
|
|
140
140
|
}>;
|
|
141
141
|
retry?: string;
|
|
142
142
|
}
|
|
143
|
-
|
|
143
|
+
interface CatalogSearchPage {
|
|
144
144
|
catalogErrors: CatalogSearchFailure[];
|
|
145
145
|
absence?: {
|
|
146
146
|
service: string;
|
|
@@ -170,14 +170,14 @@ export interface CatalogSearchPage {
|
|
|
170
170
|
guidance?: string;
|
|
171
171
|
};
|
|
172
172
|
}
|
|
173
|
-
|
|
173
|
+
type CatalogSearchResult = CatalogSearchPage & {
|
|
174
174
|
tools: Array<CatalogSearchTool & {
|
|
175
175
|
connectorTitle?: string;
|
|
176
176
|
guide?: string;
|
|
177
177
|
guideSummary?: string;
|
|
178
178
|
}>;
|
|
179
179
|
};
|
|
180
|
-
|
|
180
|
+
interface CatalogDescription {
|
|
181
181
|
address: string;
|
|
182
182
|
schemaFormat?: "json" | "text";
|
|
183
183
|
name?: string;
|
package/dist/http/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { confinementBase, REDIRECT_STATUSES, BODILESS_STATUSES } from "../http-policy.js";
|
|
2
2
|
import { guardedTransport, sendGuarded } from "../guarded-transport.js";
|
|
3
|
-
// Guarded HTTP transport
|
|
3
|
+
// Guarded HTTP transport. Unreachable from src/index.ts.
|
|
4
4
|
//
|
|
5
5
|
// The guarded transport as an Effect `HttpClient`, with the behaviour of
|
|
6
6
|
// src/connectors/guarded-fetch.ts: requests confined beneath one base URL,
|
package/dist/http/errors.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Internal HTTP failure contract
|
|
1
|
+
// Internal HTTP failure contract. Unreachable from src/index.ts.
|
|
2
2
|
//
|
|
3
3
|
// Every way a kit request can fail, as a tagged error, and the one mapping
|
|
4
4
|
// from those to the wire `ConnectorCallError`. A provider supplies meaning
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
// refusing status counts only for the request that received it. Advice to
|
|
27
27
|
// send a call again is a segment of its own (`resendAdvice`), never part of
|
|
28
28
|
// the message, so output composes it only where the outcome allows.
|
|
29
|
-
// Q8 policy is decided once by the core's `settleWrite
|
|
29
|
+
// Q8 policy is decided once by the core's `settleWrite`, from the
|
|
30
30
|
// ledger entries this kit forwards its matched proof and renewals to. A
|
|
31
31
|
// write answered 401 stays unknown; only renewal removes its handoff, and
|
|
32
32
|
// only a reviewed authentication-before-execution declaration proves refusal.
|
package/dist/http/json-schema.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Provider kit
|
|
1
|
+
// Provider kit. Unreachable from src/index.ts.
|
|
2
2
|
//
|
|
3
3
|
// One Schema is a tool's type, its argument decoder, and its catalog JSON
|
|
4
4
|
// Schema. Effect's generator is correct but spells some things differently
|
package/dist/http/oauth.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Refresh-once middleware
|
|
1
|
+
// Refresh-once middleware. Unreachable from src/index.ts.
|
|
2
2
|
//
|
|
3
3
|
// Refresh-once for a connection that authenticates with a token it can
|
|
4
4
|
// renew: a downstream OAuth grant, a service-account assertion, a machine
|
package/dist/http/paging.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { bytesToHex, decodeBase64url } from "../bytes.js";
|
|
2
|
+
// Provider kit. Unreachable from src/index.ts.
|
|
2
3
|
//
|
|
3
4
|
// List tools take one page at a time. Lookahead detects an extra row; bound
|
|
4
5
|
// cursors authenticate the tool, arguments, connection and credential owner.
|
|
@@ -52,7 +53,7 @@ async function signingKey(storage) {
|
|
|
52
53
|
return cached;
|
|
53
54
|
let raw = await storage.get(continuationKeys.signingKey);
|
|
54
55
|
if (raw === null) {
|
|
55
|
-
const candidate =
|
|
56
|
+
const candidate = bytesToHex(crypto.getRandomValues(new Uint8Array(32)));
|
|
56
57
|
raw = (await storage.compareAndSet(continuationKeys.signingKey, null, candidate))
|
|
57
58
|
? candidate
|
|
58
59
|
: await storage.get(continuationKeys.signingKey);
|
|
@@ -92,7 +93,7 @@ export const boundCursor = {
|
|
|
92
93
|
const expected = yield* digest(tool, args);
|
|
93
94
|
let parsed;
|
|
94
95
|
try {
|
|
95
|
-
parsed = JSON.parse(new TextDecoder().decode(
|
|
96
|
+
parsed = JSON.parse(new TextDecoder().decode(decodeBase64url(token)));
|
|
96
97
|
}
|
|
97
98
|
catch {
|
|
98
99
|
parsed = undefined;
|
|
@@ -108,7 +109,7 @@ export const boundCursor = {
|
|
|
108
109
|
if (token !== base64url(JSON.stringify({ v: record.v, d: record.d, c: record.c, m: record.m })))
|
|
109
110
|
return yield* Effect.fail(new Refusal({ error: new ConnectorCallError("invalid_args", STRAY_CURSOR) }));
|
|
110
111
|
const key = yield* keyForCall;
|
|
111
|
-
const mac =
|
|
112
|
+
const mac = decodeBase64url(record.m);
|
|
112
113
|
const binding = yield* ContinuationBinding;
|
|
113
114
|
const claims = new TextEncoder().encode(canonicalJson([record.v, binding.connection, binding.principal, record.d, record.c]));
|
|
114
115
|
const valid = yield* Effect.promise(() => crypto.subtle.verify("HMAC", key, mac, claims));
|
|
@@ -125,7 +126,7 @@ function digest(tool, args) {
|
|
|
125
126
|
.sort()
|
|
126
127
|
.map((key) => [key, args[key]]);
|
|
127
128
|
const bytes = new TextEncoder().encode(canonicalJson([tool, shape]));
|
|
128
|
-
return Effect.promise(() => crypto.subtle.digest("SHA-256", bytes)).pipe(Effect.map((hash) =>
|
|
129
|
+
return Effect.promise(() => crypto.subtle.digest("SHA-256", bytes)).pipe(Effect.map((hash) => bytesToHex(new Uint8Array(hash).slice(0, 16))));
|
|
129
130
|
}
|
|
130
131
|
function base64url(text) {
|
|
131
132
|
return base64urlBytes(new TextEncoder().encode(text));
|
|
@@ -136,7 +137,3 @@ function base64urlBytes(bytes) {
|
|
|
136
137
|
binary += String.fromCharCode(byte);
|
|
137
138
|
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
138
139
|
}
|
|
139
|
-
function fromBase64url(token) {
|
|
140
|
-
const binary = atob(token.replace(/-/g, "+").replace(/_/g, "/"));
|
|
141
|
-
return Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
|
142
|
-
}
|
package/dist/http/provider.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Internal provider kit
|
|
1
|
+
// Internal provider kit. Unreachable from src/index.ts.
|
|
2
2
|
import { Context, Effect, Option } from "effect";
|
|
3
3
|
import { api } from "../connectors/api.js";
|
|
4
4
|
import { OAUTH_CHALLENGE_MAX_BYTES } from "../auth/renewable-grant.js";
|
package/dist/http/safety.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Provider kit
|
|
1
|
+
// Provider kit. Unreachable from src/index.ts.
|
|
2
2
|
//
|
|
3
3
|
// The one value-safety boundary of a kit connection. `connect` requires it,
|
|
4
4
|
// and `Send` hands a provider nothing it has not passed: a named tool, a
|
package/dist/http/services.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Context, Effect } from "effect";
|
|
|
3
3
|
import { dispatchProviderRequest, providerRequest } from "../provider-call.js";
|
|
4
4
|
import { callClassification } from "../call-classification.js";
|
|
5
5
|
import { fromSignal } from "../runtime/run.js";
|
|
6
|
-
import { callFromContext, ContinuationBinding, ContinuationStorage,
|
|
6
|
+
import { callFromContext, ContinuationBinding, ContinuationStorage, serviceFor, Signal } from "../runtime/call.js";
|
|
7
7
|
import { RequestRefused, ResendRefused } from "./errors.js";
|
|
8
8
|
export { writeRequestKey } from "./write-request.js";
|
|
9
9
|
export { Caller, Credentials, Secrets, RequestSecrets, Budget, Recovery, Signal, Classification, Ledger, } from "../runtime/call.js";
|
|
@@ -70,10 +70,3 @@ export function fromConnectorContext(ctx, fallback) {
|
|
|
70
70
|
services: lease.services.pipe(Context.add(ContinuationStorage, serviceFor(ctx, ContinuationStorage) ?? ctx.storage), Context.add(ContinuationBinding, serviceFor(ctx, ContinuationBinding) ?? { connection: "", principal: null }), Context.add(Dispatches, []), Context.add(WriteCapacity, new Map([["write", new Map([[undefined, undefined]])]]))),
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
|
-
export function openCall(inputs) {
|
|
74
|
-
const lease = openCoreCall(inputs);
|
|
75
|
-
return {
|
|
76
|
-
...lease,
|
|
77
|
-
services: lease.services.pipe(Context.add(Dispatches, []), Context.add(WriteCapacity, new Map([["write", new Map([[undefined, undefined]])]]))),
|
|
78
|
-
};
|
|
79
|
-
}
|
package/dist/http/tools.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Provider kit
|
|
1
|
+
// Provider kit. Unreachable from src/index.ts.
|
|
2
2
|
//
|
|
3
3
|
// Tool builders. A tool is a name, a description, an input Schema, an output
|
|
4
4
|
// Schema, and a program; the builder renders both Schemas as catalog JSON
|
|
@@ -24,7 +24,6 @@ import { fieldsInput, fieldsProblem, selectFields } from "./fields.js";
|
|
|
24
24
|
import { catalogSchema, Integer } from "./json-schema.js";
|
|
25
25
|
import { boundCursor, Cursor, StandardPage } from "./paging.js";
|
|
26
26
|
import { Classification, Dispatches, IdempotencyKey, Recovery, ReadTool, WriteCapacity, writeRequestKey, fromConnectorContext, } from "./services.js";
|
|
27
|
-
const inputs = new WeakMap();
|
|
28
27
|
const keyed = new WeakSet();
|
|
29
28
|
/** Whether a kit write builder declared an idempotency key for this tool. */
|
|
30
29
|
export function takesIdempotencyKey(tool) {
|
|
@@ -62,10 +61,6 @@ function originalOrder(decoded, original) {
|
|
|
62
61
|
};
|
|
63
62
|
return copy(decoded, original);
|
|
64
63
|
}
|
|
65
|
-
/** The input Schema a kit tool decodes with, for the catalog/decoder agreement check. */
|
|
66
|
-
export function kitInput(tool) {
|
|
67
|
-
return inputs.get(tool);
|
|
68
|
-
}
|
|
69
64
|
/** A Struct's own property names, for `fields`. */
|
|
70
65
|
function propertyNames(schema, what) {
|
|
71
66
|
const fields = schema.fields;
|
|
@@ -350,7 +345,6 @@ rendered) {
|
|
|
350
345
|
})));
|
|
351
346
|
});
|
|
352
347
|
registerToolEntry(tool, (args, ctx) => program(args, ctx, inLogicalCall(ctx)));
|
|
353
|
-
inputs.set(tool, spec.input);
|
|
354
348
|
if (idempotency)
|
|
355
349
|
keyed.add(tool);
|
|
356
350
|
return tool;
|
package/dist/http/vendor.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Provider kit
|
|
1
|
+
// Provider kit. Unreachable from src/index.ts.
|
|
2
2
|
//
|
|
3
3
|
// A vendor is an `HttpApi`: endpoints with Schemas for path params, query,
|
|
4
4
|
// and payload, from which requests are encoded and the endpoint manifest is
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
// empty 200. Every answer, from a declared operation or a hatch's path, takes
|
|
14
14
|
// one route: bounded read, JSON, closed public classifier facts captured,
|
|
15
15
|
// the request's sent secrets redacted from
|
|
16
|
-
// every value of the whole body before anything can cut or extract from it
|
|
17
|
-
//
|
|
16
|
+
// every value of the whole body before anything can cut or extract from it,
|
|
17
|
+
// its keys kept for value safety to match by name, status (with
|
|
18
18
|
// its operation, so value safety decides what a failure may quote), the
|
|
19
19
|
// vendor's `result` hook, then the connection's ResultSafety. A provider
|
|
20
20
|
// cannot reach a body earlier. A Content-Type redaction altered selects the
|
|
21
21
|
// format the vendor reads as JSON, so no altered type routes a body around
|
|
22
|
-
// ResultSafety as text or bytes
|
|
22
|
+
// ResultSafety as text or bytes.
|
|
23
23
|
import { Context, Effect } from "effect";
|
|
24
24
|
import * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
25
25
|
import * as HttpApi from "effect/http-api/HttpApi";
|
|
@@ -233,12 +233,12 @@ export function connect(vendor, guarded, options) {
|
|
|
233
233
|
: defect)));
|
|
234
234
|
});
|
|
235
235
|
// Header-derived format decisions see only redacted Content-Type. Names are protocol
|
|
236
|
-
// constants `Headers` must accept, so only the values are redacted, together
|
|
236
|
+
// constants `Headers` must accept, so only the values are redacted, together.
|
|
237
237
|
const entries = [...reply.headers];
|
|
238
238
|
const values = secrets.redact(entries.map(([, value]) => value));
|
|
239
239
|
const headers = new Headers(entries.map(([name], index) => [name, values[index]]));
|
|
240
240
|
// Whole, before a detail line trims it or a projection extracts from it. Values only:
|
|
241
|
-
// result safety and projections match fields by their vendor names
|
|
241
|
+
// result safety and projections match fields by their vendor names.
|
|
242
242
|
let classifierFacts;
|
|
243
243
|
const parsed = reply.bytes !== undefined
|
|
244
244
|
? {
|
|
@@ -400,7 +400,7 @@ export function connect(vendor, guarded, options) {
|
|
|
400
400
|
/**
|
|
401
401
|
* The Content-Type a format decision reads. One redaction altered reads as
|
|
402
402
|
* `application/json`: a vendor's text or binary choice for it would hand
|
|
403
|
-
* result safety a body it cannot read field by field
|
|
403
|
+
* result safety a body it cannot read field by field.
|
|
404
404
|
*/
|
|
405
405
|
function formatType(redacted) {
|
|
406
406
|
return redactionAltered(redacted) ? "application/json" : redacted.toLowerCase();
|
package/dist/identity.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { sha256Hex } from "./bytes.js";
|
|
1
2
|
const IDENTITY_PART_RE = /^[\x21-\x7e]{1,256}$/;
|
|
2
|
-
const encoder = new TextEncoder();
|
|
3
3
|
export function validIdentityReference(value) {
|
|
4
4
|
return Boolean(value &&
|
|
5
5
|
typeof value.namespace === "string" &&
|
|
@@ -7,11 +7,7 @@ export function validIdentityReference(value) {
|
|
|
7
7
|
IDENTITY_PART_RE.test(value.namespace) &&
|
|
8
8
|
IDENTITY_PART_RE.test(value.id));
|
|
9
9
|
}
|
|
10
|
-
function bytesToHex(bytes) {
|
|
11
|
-
return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
12
|
-
}
|
|
13
10
|
/** Deterministic pseudonymous partition; raw emails and ids do not enter keys. */
|
|
14
11
|
export async function identityStorageKey(identity) {
|
|
15
|
-
|
|
16
|
-
return bytesToHex(new Uint8Array(digest));
|
|
12
|
+
return sha256Hex(`${identity.namespace}\n${identity.id}`);
|
|
17
13
|
}
|
package/dist/index.js
CHANGED
|
@@ -177,8 +177,7 @@ function warnInsecureConfig(config) {
|
|
|
177
177
|
logger.warn(`[connecta] connector "${connector.id}" has an OAuth callback with no ` +
|
|
178
178
|
`state/CSRF check: /oauth/callback/${connector.id} refuses every ` +
|
|
179
179
|
"callback rather than exchange an unverified code. Implement " +
|
|
180
|
-
"`verifyState` to complete authorization
|
|
181
|
-
"connector already does).");
|
|
180
|
+
"`verifyState` to complete authorization.");
|
|
182
181
|
}
|
|
183
182
|
}
|
|
184
183
|
}
|
package/dist/invocation-auth.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bytesToHex } from "./bytes.js";
|
|
1
2
|
import { authCall, authFlow, registerAuth } from "./auth/native.js";
|
|
2
3
|
import { upwardStep } from "./upward.js";
|
|
3
4
|
import { runEdge } from "./runtime/run.js";
|
|
@@ -34,7 +35,7 @@ export async function classificationDigest(definition) {
|
|
|
34
35
|
annotations,
|
|
35
36
|
schema,
|
|
36
37
|
}));
|
|
37
|
-
return
|
|
38
|
+
return bytesToHex(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes)));
|
|
38
39
|
}
|
|
39
40
|
catch {
|
|
40
41
|
// A digest refusal blocks recovery, not an ordinary call.
|
package/dist/invocation.js
CHANGED
|
@@ -766,7 +766,13 @@ export class InvocationService {
|
|
|
766
766
|
: Effect.succeed(result);
|
|
767
767
|
const processed = yield* Effect.exit(timed((elapsed) => {
|
|
768
768
|
resultProcessingMs += elapsed;
|
|
769
|
-
}, Effect.tap(
|
|
769
|
+
}, Effect.tap(withDeadlineEffect(() => processing, {
|
|
770
|
+
...defined({
|
|
771
|
+
timeoutMs: context.timeoutMs === undefined ? undefined : Math.max(1, context.timeoutMs - (Date.now() - started)),
|
|
772
|
+
signal: context.requestSignal,
|
|
773
|
+
}),
|
|
774
|
+
timeoutError: new ConnectorCallError("timeout", "Result processing exceeded the tool call deadline."),
|
|
775
|
+
}), () => Effect.sync(() => {
|
|
770
776
|
if (inputRequiredValue)
|
|
771
777
|
return;
|
|
772
778
|
try {
|
|
@@ -777,7 +783,7 @@ export class InvocationService {
|
|
|
777
783
|
}
|
|
778
784
|
}))));
|
|
779
785
|
// Past this point the call has happened, so nothing may invite a retry.
|
|
780
|
-
const unprocessable = () => failed(framingError("result_processing_failed", "The downstream call completed, but its result could not be processed. Do not repeat the call to recover its result."));
|
|
786
|
+
const unprocessable = () => failed(framingError("result_processing_failed", "The downstream call completed, but its result could not be processed. Any write already happened. Do not repeat the call to recover its result."));
|
|
781
787
|
if (Exit.isFailure(processed))
|
|
782
788
|
return unprocessable();
|
|
783
789
|
try {
|
package/dist/meta-tools.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { toolError } from "./tool-error.js";
|
|
1
2
|
import { upwardStep } from "./upward.js";
|
|
2
3
|
import { authCall, authInvoke, authFlow, authMethod, authStorage, registerAuth } from "./auth/native.js";
|
|
3
4
|
import { registryProgram } from "./runtime/registry.js";
|
|
@@ -20,7 +21,7 @@ import { AUTHORIZE_OUTPUT, SEARCH_OUTPUT, SKILLS_OUTPUT } from "./meta-output.js
|
|
|
20
21
|
import { RESULT_TTL_SECONDS, resultKeys } from "./storage/keys.js";
|
|
21
22
|
import { agentOutputOperations, sentSecretsForRequest } from "./sent-secrets.js";
|
|
22
23
|
import { captureDownstreamInput } from "./downstream-input.js";
|
|
23
|
-
import { PROGRAM_RESULT_WIRE_BYTES } from "./program-result.js";
|
|
24
|
+
import { PROGRAM_RESULT_PAGE_BYTES, PROGRAM_RESULT_WIRE_BYTES } from "./program-result.js";
|
|
24
25
|
export { MAX_DESCRIBE_ADDRESSES, MAX_DISCOVERY_RESULT_BYTES, MAX_SEARCH_LIMIT };
|
|
25
26
|
const enc = new TextEncoder();
|
|
26
27
|
// Each page is a slice of payload bytes, so a leading U+FEFF is data.
|
|
@@ -37,15 +38,7 @@ function errorResult(message) {
|
|
|
37
38
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
38
39
|
}
|
|
39
40
|
function discoveryErrorResult(error) {
|
|
40
|
-
|
|
41
|
-
error: {
|
|
42
|
-
code: error.code,
|
|
43
|
-
message: error.message,
|
|
44
|
-
retryable: false,
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
result.isError = true;
|
|
48
|
-
return result;
|
|
41
|
+
return toolError({ code: error.code, message: error.message, retryable: false });
|
|
49
42
|
}
|
|
50
43
|
const discoveryResult = function (operation, hint) {
|
|
51
44
|
return authFlow(function* () {
|
|
@@ -86,8 +79,8 @@ function isValidResultOffset(value) {
|
|
|
86
79
|
* Backwards, never forwards: re-serving a few bytes the caller already has is
|
|
87
80
|
* recoverable, silently skipping the rest of a character is not. Offsets the
|
|
88
81
|
* server itself produced (`nextOffset`) are already boundaries and come back
|
|
89
|
-
* unchanged, so this only moves an offset a client computed on its own
|
|
90
|
-
*
|
|
82
|
+
* unchanged, so this only moves an offset a client computed on its own.
|
|
83
|
+
* An offset at or past `bytes.length` is left alone — there is no
|
|
91
84
|
* character there to split.
|
|
92
85
|
*/
|
|
93
86
|
function alignStartToCharBoundary(bytes, offset) {
|
|
@@ -149,6 +142,15 @@ function base64Of(bytes) {
|
|
|
149
142
|
}
|
|
150
143
|
return out;
|
|
151
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* The page a notice's nextAction asks a program to read: it fits the program's
|
|
147
|
+
* return even if every byte escapes to six JSON characters, with room for the
|
|
148
|
+
* page envelope, and never asks for more than the stash or bridge will serve.
|
|
149
|
+
*/
|
|
150
|
+
function programPageBytes(results) {
|
|
151
|
+
const fits = Math.floor(((results.programChars ?? MAX_EXECUTE_RESULT_CHARS) - 1024) / 6);
|
|
152
|
+
return Math.max(4, Math.min(fits, results.cap, PROGRAM_RESULT_PAGE_BYTES));
|
|
153
|
+
}
|
|
152
154
|
/** Opens a write's notice, ahead of any paging instruction. */
|
|
153
155
|
const WRITE_ALREADY_RAN = "This write already ran: do not call it again to see its result.";
|
|
154
156
|
/** UTF-8 cannot represent lone UTF-16 surrogates without changing them. */
|
|
@@ -229,7 +231,7 @@ const stashResult = function (bytes, results, preview, rawText) {
|
|
|
229
231
|
try {
|
|
230
232
|
// Base64 permits byte-range decoding, and splitting the envelope across
|
|
231
233
|
// keys keeps a page's storage read proportional to the page instead of to
|
|
232
|
-
// the whole result
|
|
234
|
+
// the whole result. Chunk 0 carries the header; the connecta.result
|
|
233
235
|
// reader below maps a byte offset back to chunk index and base64 quad.
|
|
234
236
|
const chunkBytes = resultChunkBytes(totalBytes);
|
|
235
237
|
const binding = base64Of(enc.encode(JSON.stringify(results.binding)));
|
|
@@ -280,7 +282,7 @@ const stashResult = function (bytes, results, preview, rawText) {
|
|
|
280
282
|
// A byte may cost six JSON characters when escaped. Leave room for the
|
|
281
283
|
// result id, page counters, and continuation metadata in the returned page.
|
|
282
284
|
arguments: {
|
|
283
|
-
code: `async () => await connecta.result(${JSON.stringify(id)}, { offset: ${preview.kind === "prefix" ? preview.bytes : 0}, maxBytes: ${
|
|
285
|
+
code: `async () => await connecta.result(${JSON.stringify(id)}, { offset: ${preview.kind === "prefix" ? preview.bytes : 0}, maxBytes: ${programPageBytes(results)} })`,
|
|
284
286
|
},
|
|
285
287
|
},
|
|
286
288
|
};
|
|
@@ -325,10 +327,10 @@ const pageProgramResultNative = /* @__PURE__ */ registerAuth(pageProgramResult,
|
|
|
325
327
|
});
|
|
326
328
|
});
|
|
327
329
|
/** Program returns share the direct stash, with all host-admitted call dependencies. */
|
|
328
|
-
export function guardProgramReturn(value, registry, baseUrl, dependencies, secrets, logger, maxChars, completedWrite) {
|
|
329
|
-
return runEdge(guardProgramReturnNative(value, registry, baseUrl, dependencies, secrets, logger, maxChars, completedWrite));
|
|
330
|
+
export function guardProgramReturn(value, registry, baseUrl, dependencies, secrets, logger, maxChars, completedWrite, programChars) {
|
|
331
|
+
return runEdge(guardProgramReturnNative(value, registry, baseUrl, dependencies, secrets, logger, maxChars, completedWrite, programChars));
|
|
330
332
|
}
|
|
331
|
-
const guardProgramReturnNative = /* @__PURE__ */ registerAuth(guardProgramReturn, function (value, registry, baseUrl, dependencies, secrets, logger, maxChars, completedWrite) {
|
|
333
|
+
const guardProgramReturnNative = /* @__PURE__ */ registerAuth(guardProgramReturn, function (value, registry, baseUrl, dependencies, secrets, logger, maxChars, completedWrite, programChars) {
|
|
332
334
|
return authFlow(function* () {
|
|
333
335
|
const serialized = serializeResultText(value);
|
|
334
336
|
if (serialized.length <= maxChars)
|
|
@@ -347,6 +349,7 @@ const guardProgramReturnNative = /* @__PURE__ */ registerAuth(guardProgramReturn
|
|
|
347
349
|
},
|
|
348
350
|
write: completedWrite,
|
|
349
351
|
cap,
|
|
352
|
+
...(programChars !== undefined ? { programChars } : {}),
|
|
350
353
|
set: authMethod((id, chunks, ttl) => registryProgram(registry, "stashResult", id, chunks, ttl)),
|
|
351
354
|
warn: () => logFailure(logger, "result paging unavailable", failureRecord({})),
|
|
352
355
|
};
|
|
@@ -453,16 +456,11 @@ function escapedHeadOf(bytes, cap) {
|
|
|
453
456
|
* Bound a downstream MCP `content` array by `cap`.
|
|
454
457
|
*
|
|
455
458
|
* A lone text block is measured, stashed, previewed, and paged as its text:
|
|
456
|
-
* its envelope adds nothing but a wrapper and a second layer of JSON escaping
|
|
457
|
-
* which made a JSON payload's preview unreadable and inflated every page.
|
|
459
|
+
* its envelope adds nothing but a wrapper and a second layer of JSON escaping.
|
|
458
460
|
*
|
|
459
461
|
* Anything else is measured as the serialized envelope — the same string that
|
|
460
462
|
* gets stashed and paged, and the one that counts every block rather than only
|
|
461
|
-
* the text ones.
|
|
462
|
-
* meant an oversized all-image result scored zero bytes and was returned inline
|
|
463
|
-
* unbounded, with no `resultId` to page from; and measuring one string while
|
|
464
|
-
* truncating another left `totalBytes` describing something the cap was never
|
|
465
|
-
* compared against.
|
|
463
|
+
* the text ones. Measure the same representation that gets truncated and paged.
|
|
466
464
|
*
|
|
467
465
|
* Over the cap, what a client gets depends on whether a preview is usable.
|
|
468
466
|
* Several text blocks preview as their text joined by newlines, while
|
|
@@ -624,6 +622,7 @@ function metaToolsForRequest(registry, baseUrl, opts = {}) {
|
|
|
624
622
|
write: resolved.definition.classification !== "read",
|
|
625
623
|
cap,
|
|
626
624
|
...(opts.pagingTool ? { pagingTool: opts.pagingTool } : {}),
|
|
625
|
+
...(opts.maxProgramResultChars !== undefined ? { programChars: opts.maxProgramResultChars } : {}),
|
|
627
626
|
set: authMethod((id, value, ttlSeconds) => registryProgram(registry, "stashResult", id, value, ttlSeconds)),
|
|
628
627
|
// The catalog entry, never `toolName`: a record names a tool
|
|
629
628
|
// only through the grammar check (src/operator-record.ts).
|
|
@@ -670,7 +669,7 @@ function metaToolsForRequest(registry, baseUrl, opts = {}) {
|
|
|
670
669
|
const structuredRecovery = outcome.error.nextAction !== undefined;
|
|
671
670
|
const recoveryRequired = structuredRecovery ||
|
|
672
671
|
// Sanitized `unavailable` diagnostics ride the structured shape too;
|
|
673
|
-
// the plain-text path would drop them
|
|
672
|
+
// the plain-text path would drop them.
|
|
674
673
|
outcome.error.details !== undefined ||
|
|
675
674
|
// So does a conflict's `current`: where things stand is the retry.
|
|
676
675
|
outcome.error.current !== undefined ||
|
|
@@ -733,7 +732,7 @@ function metaToolsForRequest(registry, baseUrl, opts = {}) {
|
|
|
733
732
|
content: [
|
|
734
733
|
{
|
|
735
734
|
type: "text",
|
|
736
|
-
text:
|
|
735
|
+
text: "Available skills. Fetch one by exact name with this tool.\n\n" +
|
|
737
736
|
listing.map((skill) => `- \`${skill.name}\` — ${skill.description}`).join("\n"),
|
|
738
737
|
},
|
|
739
738
|
],
|
|
@@ -949,7 +948,7 @@ function metaToolsForRequest(registry, baseUrl, opts = {}) {
|
|
|
949
948
|
// client that computes its own offsets can land inside a multi-byte
|
|
950
949
|
// character, which would decode as U+FFFD; the offset actually served is
|
|
951
950
|
// the boundary at or before it, and it is what the response reports back
|
|
952
|
-
// as `offset
|
|
951
|
+
// as `offset`.
|
|
953
952
|
const offset = start + alignStartToCharBoundary(bytes, requestedOffset - start);
|
|
954
953
|
// Both sides of `maxBytes` are validated by now — the argument above, the
|
|
955
954
|
// cap at intake — so `offset + maxBytes` always reaches past `offset`.
|
|
@@ -1084,6 +1083,7 @@ const AUTHORIZE_INPUT = advertisedSchema(z.object({
|
|
|
1084
1083
|
*/
|
|
1085
1084
|
export function registerMetaTools(server, registry, ctx) {
|
|
1086
1085
|
const mt = createMetaTools(registry, ctx.baseUrl, {
|
|
1086
|
+
maxProgramResultChars: ctx.maxProgramResultChars,
|
|
1087
1087
|
...(ctx.native && !ctx.native.executeCode ? { pagingTool: "read_result" } : {}),
|
|
1088
1088
|
...(ctx.native ? { activitySource: "native" } : {}),
|
|
1089
1089
|
downstreamInput: Boolean(ctx.authElicitation),
|
package/dist/native-tools.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bytesToHex } from "./bytes.js";
|
|
1
2
|
import { duringViewEffect } from "./runtime/call.js";
|
|
2
3
|
import { RequestScope, requestOwner } from "./runtime/request-scope.js";
|
|
3
4
|
import { Effect } from "effect";
|
|
@@ -35,7 +36,7 @@ function shortHash(text) {
|
|
|
35
36
|
const shortHashNative = /* @__PURE__ */ registerAuth(shortHash, function (text) {
|
|
36
37
|
return authFlow(function* () {
|
|
37
38
|
const digest = new Uint8Array(yield* upwardStep(authInvoke(crypto.subtle, "digest", ["SHA-256", enc.encode(text)])));
|
|
38
|
-
return
|
|
39
|
+
return bytesToHex(digest.subarray(0, HASH_CHARS / 2));
|
|
39
40
|
});
|
|
40
41
|
});
|
|
41
42
|
/**
|
package/dist/oauth-handoff.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { decodeBase64url } from "./bytes.js";
|
|
1
2
|
import { upwardStep } from "./upward.js";
|
|
2
3
|
import { authCall, authInvoke, authFlow, authStorage, registerAuth } from "./auth/native.js";
|
|
3
4
|
import { runEdge } from "./runtime/run.js";
|
|
@@ -58,8 +59,7 @@ function encodeSegment(value) {
|
|
|
58
59
|
function decodeSegment(value) {
|
|
59
60
|
if (!/^[A-Za-z0-9_-]+$/.test(value))
|
|
60
61
|
throw new Error("Invalid handoff encoding");
|
|
61
|
-
const
|
|
62
|
-
const decoded = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(Uint8Array.from(binary, (char) => char.charCodeAt(0)));
|
|
62
|
+
const decoded = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(decodeBase64url(value));
|
|
63
63
|
if (encodeSegment(decoded) !== value)
|
|
64
64
|
throw new Error("Noncanonical handoff encoding");
|
|
65
65
|
return decoded;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { lexicalSearchContent, lexicalQueryTerms } from "./catalog.js";
|
|
3
3
|
const tools = new WeakMap();
|
|
4
4
|
const connectors = new WeakMap();
|
|
5
|
-
|
|
5
|
+
const OPERATION_VOCABULARY_BOUNDS = {
|
|
6
6
|
operations: 8192,
|
|
7
7
|
rowChars: 1024,
|
|
8
8
|
chars: 2_097_152,
|