@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,5 @@
|
|
|
1
|
+
import { asRecord, asArray, compact } from "../_shared/json.js";
|
|
2
|
+
import { decodeBase64, decodeBase64url } from "../../bytes.js";
|
|
1
3
|
// Google Drive named workflows, bounded projections and bound continuation on the provider kit.
|
|
2
4
|
import { Effect, Option, Schema } from "effect";
|
|
3
5
|
import { ConnectorCallError } from "../../errors.js";
|
|
@@ -83,15 +85,6 @@ const DETAIL_FIELDS = `${SUMMARY_FIELDS},description,createdTime,lastModifyingUs
|
|
|
83
85
|
const PERMISSION_FIELDS = "id,type,role,emailAddress,domain,displayName,allowFileDiscovery,expirationTime,deleted,permissionDetails(inherited,inheritedFrom)";
|
|
84
86
|
/** Every file request reaches shared drives as well as My Drive. */
|
|
85
87
|
const ALL_DRIVES = { supportsAllDrives: true };
|
|
86
|
-
function asRecord(value) {
|
|
87
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
88
|
-
}
|
|
89
|
-
function asArray(value) {
|
|
90
|
-
return Array.isArray(value) ? value : [];
|
|
91
|
-
}
|
|
92
|
-
function compact(value) {
|
|
93
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
94
|
-
}
|
|
95
88
|
function text(value) {
|
|
96
89
|
return typeof value === "string" && value !== "" ? value : undefined;
|
|
97
90
|
}
|
|
@@ -260,8 +253,7 @@ function encodeCursor(ctx, resume) {
|
|
|
260
253
|
const FINGERPRINT = /^[A-Za-z0-9_-]{16}$/;
|
|
261
254
|
function decodeCursor(cursor) {
|
|
262
255
|
try {
|
|
263
|
-
const
|
|
264
|
-
const json = new TextDecoder().decode(fromBase64(base + "=".repeat((4 - (base.length % 4)) % 4)));
|
|
256
|
+
const json = new TextDecoder().decode(decodeBase64url(cursor, true));
|
|
265
257
|
const [token, skip, size, scope, page, last] = JSON.parse(json);
|
|
266
258
|
const midPage = typeof page === "string" && FINGERPRINT.test(page) && typeof last === "string" && FINGERPRINT.test(last);
|
|
267
259
|
if ((token === null || (typeof token === "string" && token !== "")) &&
|
|
@@ -471,19 +463,6 @@ function base64(bytes) {
|
|
|
471
463
|
}
|
|
472
464
|
return btoa(binary);
|
|
473
465
|
}
|
|
474
|
-
function fromBase64(value) {
|
|
475
|
-
let binary;
|
|
476
|
-
try {
|
|
477
|
-
binary = atob(value);
|
|
478
|
-
}
|
|
479
|
-
catch {
|
|
480
|
-
throw new ConnectorCallError("invalid_args", "contentBase64 is not valid base64.");
|
|
481
|
-
}
|
|
482
|
-
const bytes = new Uint8Array(binary.length);
|
|
483
|
-
for (let index = 0; index < binary.length; index += 1)
|
|
484
|
-
bytes[index] = binary.charCodeAt(index);
|
|
485
|
-
return bytes;
|
|
486
|
-
}
|
|
487
466
|
/**
|
|
488
467
|
* Why the content tool returns no content for a file, as the note says it.
|
|
489
468
|
* Only a well-formed id or media type is interpolated; anything else Drive
|
|
@@ -681,7 +660,7 @@ function media(args) {
|
|
|
681
660
|
};
|
|
682
661
|
}
|
|
683
662
|
if (hasBinary) {
|
|
684
|
-
const bytes =
|
|
663
|
+
const bytes = contentBytes(args["contentBase64"]);
|
|
685
664
|
if (bytes.length > BINARY_INLINE_BYTES) {
|
|
686
665
|
throw new ConnectorCallError("invalid_args", `contentBase64 decodes to ${bytes.length} bytes, past this connection's ${BINARY_INLINE_BYTES}-byte upload cap.`);
|
|
687
666
|
}
|
|
@@ -1288,3 +1267,11 @@ function decisionInputs(file, keys) {
|
|
|
1288
1267
|
}
|
|
1289
1268
|
}
|
|
1290
1269
|
}
|
|
1270
|
+
function contentBytes(value) {
|
|
1271
|
+
try {
|
|
1272
|
+
return decodeBase64(value);
|
|
1273
|
+
}
|
|
1274
|
+
catch {
|
|
1275
|
+
throw new ConnectorCallError("invalid_args", "contentBase64 is not valid base64.");
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { asRecord, asArray, compact } from "../_shared/json.js";
|
|
1
2
|
// Forms projections and revision-checked workflows on the standard provider kit.
|
|
2
3
|
import { Effect, Option, Schema } from "effect";
|
|
3
4
|
import { ConnectorCallError } from "../../errors.js";
|
|
@@ -40,15 +41,6 @@ const MAX_REQUESTS = 100;
|
|
|
40
41
|
* cursor included, is measured before it is returned.
|
|
41
42
|
*/
|
|
42
43
|
const PAGE_RESERVE_BYTES = 4 * 1024;
|
|
43
|
-
function asRecord(value) {
|
|
44
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
45
|
-
}
|
|
46
|
-
function asArray(value) {
|
|
47
|
-
return Array.isArray(value) ? value : [];
|
|
48
|
-
}
|
|
49
|
-
function compact(value) {
|
|
50
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
51
|
-
}
|
|
52
44
|
function text(value) {
|
|
53
45
|
return typeof value === "string" && value !== "" ? value : undefined;
|
|
54
46
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { asRecord, asArray, compact } from "../_shared/json.js";
|
|
2
|
+
import { decodeBase64url } from "../../bytes.js";
|
|
1
3
|
// Curated Gmail workflows over real Effect declarations and the standard kit boundary.
|
|
2
4
|
import { Effect, Option } from "effect";
|
|
3
5
|
import { defined } from "../../connectors/api-connector.js";
|
|
@@ -31,15 +33,6 @@ const MAX_RECIPIENTS = 100;
|
|
|
31
33
|
const MAX_ATTACHMENT_BYTES = 1024 * 1024;
|
|
32
34
|
/** Same direct-call ceiling and minimum result budget as Drive content reads. */
|
|
33
35
|
const MAX_ATTACHMENT_RESULT_BYTES = 4 * 1024 * 1024;
|
|
34
|
-
function asRecord(value) {
|
|
35
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
36
|
-
}
|
|
37
|
-
function asArray(value) {
|
|
38
|
-
return Array.isArray(value) ? value : [];
|
|
39
|
-
}
|
|
40
|
-
function compact(value) {
|
|
41
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
42
|
-
}
|
|
43
36
|
function text(value) {
|
|
44
37
|
return typeof value === "string" && value !== "" ? value : undefined;
|
|
45
38
|
}
|
|
@@ -83,15 +76,6 @@ function htmlToText(ctx, html) {
|
|
|
83
76
|
.replace(/\n{3,}/g, "\n\n")
|
|
84
77
|
.trim();
|
|
85
78
|
}
|
|
86
|
-
function base64UrlBytes(data) {
|
|
87
|
-
const base64 = data.replace(/-/g, "+").replace(/_/g, "/");
|
|
88
|
-
const binary = atob(base64 + "=".repeat((4 - (base64.length % 4)) % 4));
|
|
89
|
-
const bytes = new Uint8Array(binary.length);
|
|
90
|
-
for (let index = 0; index < binary.length; index += 1) {
|
|
91
|
-
bytes[index] = binary.charCodeAt(index);
|
|
92
|
-
}
|
|
93
|
-
return bytes;
|
|
94
|
-
}
|
|
95
79
|
function charsetOf(ctx, part) {
|
|
96
80
|
const type = header(part, "Content-Type") ?? "";
|
|
97
81
|
if (redactBeforeCut(ctx, type) !== type)
|
|
@@ -113,7 +97,7 @@ function charsetOf(ctx, part) {
|
|
|
113
97
|
function decodeIn(ctx, part, data) {
|
|
114
98
|
let bytes;
|
|
115
99
|
try {
|
|
116
|
-
bytes =
|
|
100
|
+
bytes = decodeBase64url(data, true);
|
|
117
101
|
}
|
|
118
102
|
catch {
|
|
119
103
|
return { text: "" };
|
|
@@ -346,7 +330,7 @@ function attachmentBytes(client, ctx, messageId, part) {
|
|
|
346
330
|
validateSize(provenance.originalLength);
|
|
347
331
|
let bytes;
|
|
348
332
|
try {
|
|
349
|
-
bytes =
|
|
333
|
+
bytes = decodeBase64url(data, true);
|
|
350
334
|
}
|
|
351
335
|
catch {
|
|
352
336
|
throw new ConnectorCallError("connector_call_failed", "Gmail returned invalid base64url attachment data.", {
|
|
@@ -605,7 +589,7 @@ function openCursor(cursor, tool, call) {
|
|
|
605
589
|
return undefined;
|
|
606
590
|
let claims;
|
|
607
591
|
try {
|
|
608
|
-
const parsed = JSON.parse(new TextDecoder().decode(
|
|
592
|
+
const parsed = JSON.parse(new TextDecoder().decode(decodeBase64url(String(cursor), true)));
|
|
609
593
|
if (parsed && typeof parsed === "object" && parsed.v === 1)
|
|
610
594
|
claims = parsed;
|
|
611
595
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { asRecord } from "../_shared/json.js";
|
|
1
2
|
// Overflow v3: reviewed vendor declarations, derived operation index and paging contracts.
|
|
2
3
|
// Public input: staging OpenAPI 3.0; exact retrieval and known upstream drift are in evidence/review.md.
|
|
3
4
|
import { Effect, Schema } from "effect";
|
|
@@ -1003,6 +1004,3 @@ export const probe = {
|
|
|
1003
1004
|
return `Overflow ${options.environment} accepted the client id and API key.${where}`;
|
|
1004
1005
|
},
|
|
1005
1006
|
};
|
|
1006
|
-
function asRecord(value) {
|
|
1007
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1008
|
-
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readOnlyNotice } from "../_shared/guide.js";
|
|
1
2
|
import { skill } from "./skill.generated.js";
|
|
2
3
|
import { keys, optionsOf } from "../../config-schema.js";
|
|
3
4
|
import { PROVIDER_COMMON } from "../../connectors/option-shapes.js";
|
|
@@ -81,7 +82,7 @@ export const overflow = defineApiProvider({
|
|
|
81
82
|
: "Overflow staging: a sandbox with separate credentials and data.",
|
|
82
83
|
`Nonprofit purpose: ${options.purpose}`,
|
|
83
84
|
"Named reads minimize contact data; get_donor is the full-contact lookup. Webhook signing secrets are always removed.",
|
|
84
|
-
...(options.readOnly
|
|
85
|
+
...readOnlyNotice(options.readOnly),
|
|
85
86
|
...(options.defaultPageSize !== undefined
|
|
86
87
|
? [`Paged lists return ${options.defaultPageSize} items by default on this connection.`]
|
|
87
88
|
: []),
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { compact as compactDefined } from "../_shared/json.js";
|
|
2
|
+
import { asRecord, asArray } from "../_shared/json.js";
|
|
1
3
|
// Overflow's curated kit tools: standard pages, safe projections and narrowing fields.
|
|
2
4
|
import { Effect, Schema } from "effect";
|
|
3
5
|
import { ConnectorCallError } from "../../errors.js";
|
|
@@ -5,14 +7,8 @@ import { Refusal } from "../../http/errors.js";
|
|
|
5
7
|
import { Integer, isMinChars } from "../../http/json-schema.js";
|
|
6
8
|
import { read, list } from "../../http/tools.js";
|
|
7
9
|
import * as api from "./api.js";
|
|
8
|
-
function asRecord(value) {
|
|
9
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
10
|
-
}
|
|
11
|
-
function asArray(value) {
|
|
12
|
-
return Array.isArray(value) ? value : [];
|
|
13
|
-
}
|
|
14
10
|
function compact(value) {
|
|
15
|
-
return
|
|
11
|
+
return compactDefined(value);
|
|
16
12
|
}
|
|
17
13
|
/** A `{ id, name }` reference, or undefined when Overflow sent none. */
|
|
18
14
|
function reference(value) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { asArray, asRecord } from "../_shared/json.js";
|
|
1
2
|
import { Effect, Schema } from "effect";
|
|
2
3
|
import { ConnectorCallError } from "../../errors.js";
|
|
3
4
|
import { Refusal } from "../../http/errors.js";
|
|
@@ -11,7 +12,7 @@ import { PlanningCenterIndex } from "./lib/discovery.js";
|
|
|
11
12
|
import { PCO_REFUSALS } from "./lib/verdicts.js";
|
|
12
13
|
import { TABLE } from "./safety.js";
|
|
13
14
|
import { excludedApps, series } from "./lib/guide.js";
|
|
14
|
-
import {
|
|
15
|
+
import { resources, attribute, pageOf } from "./lib/json-api.js";
|
|
15
16
|
import { PLANNING_CENTER_API_BASE_URL, PLANNING_CENTER_APPS, PLANNING_CENTER_API_VERSIONS, DEFAULT_USER_AGENT, } from "./lib/constants.js";
|
|
16
17
|
export { PLANNING_CENTER_API_BASE_URL, PLANNING_CENTER_APPS, PLANNING_CENTER_API_VERSIONS, MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, PLANNING_CENTER_MAX_RESPONSE_BYTES, PLANNING_CENTER_ADMISSION, } from "./lib/constants.js";
|
|
17
18
|
export const CREDENTIAL = {
|
|
@@ -55,4 +55,4 @@ export declare const PLANNING_CENTER_MAX_RESPONSE_BYTES: number;
|
|
|
55
55
|
*/
|
|
56
56
|
export declare const PLANNING_CENTER_ADMISSION: ConnectorCallAdmissionPolicy;
|
|
57
57
|
/** Planning Center refuses a request without a descriptive one (HTTP 403). */
|
|
58
|
-
export declare const DEFAULT_USER_AGENT = "connecta/0.
|
|
58
|
+
export declare const DEFAULT_USER_AGENT = "connecta/0.38.0 (+https://github.com/zackbart/connecta)";
|
|
@@ -1,13 +1,5 @@
|
|
|
1
|
+
import { asRecord, asArray, compact } from "../../_shared/json.js";
|
|
1
2
|
import { ConnectorCallError } from "../../../errors.js";
|
|
2
|
-
export function asRecord(value) {
|
|
3
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
4
|
-
}
|
|
5
|
-
export function asArray(value) {
|
|
6
|
-
return Array.isArray(value) ? value : [];
|
|
7
|
-
}
|
|
8
|
-
export function compact(value) {
|
|
9
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
10
|
-
}
|
|
11
3
|
function isResource(value) {
|
|
12
4
|
const record = asRecord(value);
|
|
13
5
|
return typeof record["id"] === "string" && typeof record["type"] === "string";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { asRecord, compact } from "../_shared/json.js";
|
|
1
2
|
// Curated Planning Center workflows over the standard provider kit.
|
|
2
3
|
import { Effect, Schema } from "effect";
|
|
3
4
|
import { ConnectorCallError } from "../../errors.js";
|
|
@@ -6,7 +7,7 @@ import { Integer, isMinChars, emptyRequired } from "../../http/json-schema.js";
|
|
|
6
7
|
import { read, write, list as standardList } from "../../http/tools.js";
|
|
7
8
|
import { PLANNING_CENTER_APPS, MAX_PAGE_SIZE, planningCenterCall } from "./api.js";
|
|
8
9
|
import { excludedApps } from "./lib/guide.js";
|
|
9
|
-
import {
|
|
10
|
+
import { resources, indexIncluded, relId, related, relatedMany, pick, attribute, writeDocument, pageOf, } from "./lib/json-api.js";
|
|
10
11
|
const fail = (code, message, options) => Effect.fail(new Refusal({ error: new ConnectorCallError(code, message, options) }));
|
|
11
12
|
const pattern = (source) => Schema.makeFilter((value) => typeof value !== "string" || new RegExp(source).test(value), {
|
|
12
13
|
toJsonSchema: () => ({ pattern: source }),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { asRecord, asArray, compact } from "../_shared/json.js";
|
|
1
2
|
// Google Sheets named projections, bounded cell reads and guarded writes.
|
|
2
3
|
import { Effect, Option, Schema } from "effect";
|
|
3
4
|
import { ConnectorCallError } from "../../errors.js";
|
|
@@ -38,15 +39,6 @@ const MAX_CELL_CHARS = 50_000;
|
|
|
38
39
|
const MAX_WRITE_CELLS = 50_000;
|
|
39
40
|
/** Named ranges a metadata read lists before reporting a size cut. */
|
|
40
41
|
const MAX_NAMED_RANGES = 200;
|
|
41
|
-
function asRecord(value) {
|
|
42
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
43
|
-
}
|
|
44
|
-
function asArray(value) {
|
|
45
|
-
return Array.isArray(value) ? value : [];
|
|
46
|
-
}
|
|
47
|
-
function compact(value) {
|
|
48
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
49
|
-
}
|
|
50
42
|
function text(value) {
|
|
51
43
|
return typeof value === "string" && value !== "" ? value : undefined;
|
|
52
44
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { asRecord, asArray, compact } from "../_shared/json.js";
|
|
2
|
+
import { decodeBase64url } from "../../bytes.js";
|
|
1
3
|
// Google Slides named workflows on real kit schemas, with bound content continuation.
|
|
2
4
|
import { Effect, Option, Schema } from "effect";
|
|
3
5
|
import { ConnectorCallError } from "../../errors.js";
|
|
@@ -52,7 +54,7 @@ const MAX_ECHO_CHARS = 100;
|
|
|
52
54
|
/**
|
|
53
55
|
* The comment kinds of Slides' Request. A batch carrying any of them has
|
|
54
56
|
* comment changes Slides saves apart from the deck's, and only `ALL_SAVED`
|
|
55
|
-
* says they all landed
|
|
57
|
+
* says they all landed.
|
|
56
58
|
*/
|
|
57
59
|
/** The comment save states that say every comment change in a batch landed, or none was asked for. */
|
|
58
60
|
const COMMENTS_SETTLED = new Set(["NO_UPDATES_REQUESTED", "ALL_SAVED"]);
|
|
@@ -121,15 +123,6 @@ const COMMENT_DECK_FIELDS = "presentationId,revisionId,commentsViewMode,comments
|
|
|
121
123
|
"slides(objectId,commentAnchors,slideProperties(notesPage(objectId,commentAnchors)))," +
|
|
122
124
|
"layouts(objectId,commentAnchors),masters(objectId,commentAnchors),notesMaster(objectId,commentAnchors)";
|
|
123
125
|
const COMMENT_PAGE_FIELDS = "objectId,revisionId,commentsViewMode,comments,commentAnchors";
|
|
124
|
-
function asRecord(value) {
|
|
125
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
126
|
-
}
|
|
127
|
-
function asArray(value) {
|
|
128
|
-
return Array.isArray(value) ? value : [];
|
|
129
|
-
}
|
|
130
|
-
function compact(value) {
|
|
131
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
132
|
-
}
|
|
133
126
|
function text(value) {
|
|
134
127
|
return typeof value === "string" && value !== "" ? value : undefined;
|
|
135
128
|
}
|
|
@@ -226,9 +219,7 @@ function decodeCursor(value, expected) {
|
|
|
226
219
|
const refuse = (why) => new ConnectorCallError("invalid_args", `${why} Omit cursor to start from the beginning.`);
|
|
227
220
|
let cursor;
|
|
228
221
|
try {
|
|
229
|
-
|
|
230
|
-
const binary = atob(base64 + "=".repeat((4 - (base64.length % 4)) % 4));
|
|
231
|
-
cursor = JSON.parse(new TextDecoder().decode(Uint8Array.from(binary, (character) => character.charCodeAt(0))));
|
|
222
|
+
cursor = JSON.parse(new TextDecoder().decode(decodeBase64url(String(value), true)));
|
|
232
223
|
}
|
|
233
224
|
catch {
|
|
234
225
|
throw refuse("cursor is not one this connection issued; pass page.nextCursor back unchanged.");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readOnlyNotice } from "../_shared/guide.js";
|
|
1
2
|
import { keys, optionsOf, variants } from "../../config-schema.js";
|
|
2
3
|
import { defineApiProvider } from "../../http/provider.js";
|
|
3
4
|
import { authenticate, connectedAccount, MAX_RESPONSE_BYTES, READ_CAP_MS, MODE_COPY, probe, safety, stripeErrors, StripeApi, stripeIndex, stripeBinding, STRIPE_PAGES, STRIPE_VERDICTS, } from "./api.js";
|
|
@@ -63,7 +64,7 @@ function usageGuide(options) {
|
|
|
63
64
|
`Connected account: ${account}. Every call acts as this Connect account; the platform account's own objects are out of reach here.`,
|
|
64
65
|
]
|
|
65
66
|
: []),
|
|
66
|
-
...(options.readOnly === true
|
|
67
|
+
...readOnlyNotice(options.readOnly === true),
|
|
67
68
|
],
|
|
68
69
|
required: true,
|
|
69
70
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Stripe's reviewed value-safety table
|
|
1
|
+
// Stripe's reviewed value-safety table, on the shared mechanism in
|
|
2
2
|
// `../_shared/rest/value-safety.ts`: every operation the detector flags in the
|
|
3
3
|
// pinned spec (`evidence/value-safety.json`) has one verdict here, and
|
|
4
4
|
// `provider.safety.node.test.ts` runs the shared harness over it.
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
// - Issuing card numbers and CVCs come back only as expansions, which the
|
|
49
49
|
// connector refuses on every Issuing path (`api.ts`); the card operations
|
|
50
50
|
// also redact both fields.
|
|
51
|
-
// Embedded URL verdict
|
|
51
|
+
// Embedded URL verdict: reviewed paths + global signing parameters.
|
|
52
52
|
// Evidence: digest-verified Stripe v2555, components/schemas/charge's
|
|
53
53
|
// failure_message ("Message to user further explaining reason for charge
|
|
54
54
|
// failure") and charge_outcome.seller_message (Stripe's human-readable
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { asRecord, asArray } from "../_shared/json.js";
|
|
2
|
+
// Tithe.ly's giving API (v1) as a kit vendor: the operations,
|
|
2
3
|
// what its statuses mean, its credential, its in-band refusal, the probe, and
|
|
3
4
|
// the value-safety review. Facts from the per-operation reference at
|
|
4
5
|
// https://docs.tithe.ly/reference/introduction, each marked where it is
|
|
@@ -509,12 +510,6 @@ export function tithelySafety(sensitiveFields) {
|
|
|
509
510
|
}
|
|
510
511
|
// --- Shared readers ------------------------------------------------------------------
|
|
511
512
|
const failed = (error) => Effect.fail(new Refusal({ error }));
|
|
512
|
-
export function asRecord(value) {
|
|
513
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
514
|
-
}
|
|
515
|
-
export function asArray(value) {
|
|
516
|
-
return Array.isArray(value) ? value : [];
|
|
517
|
-
}
|
|
518
513
|
export function text(value) {
|
|
519
514
|
return typeof value === "string" && value !== "" ? value : undefined;
|
|
520
515
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { readOnlyNotice } from "../_shared/guide.js";
|
|
1
2
|
import { skill } from "./skill.generated.js";
|
|
2
3
|
/**
|
|
3
|
-
* Tithe.ly's giving API (v1) on the provider kit
|
|
4
|
+
* Tithe.ly's giving API (v1) on the provider kit. No SDK
|
|
4
5
|
* exists to depend on, and none would be welcome: this is a payments API, and
|
|
5
6
|
* every tool was chosen and written, not generated (decision record 0001:
|
|
6
7
|
* hand-authored tools). The vendor lives in `api.ts` and the tools in
|
|
@@ -67,7 +68,7 @@ function usageGuide(options) {
|
|
|
67
68
|
sensitiveFields(options) === "return"
|
|
68
69
|
? "This connection returns organizations' payout bank and legal-contact details through tithely_api_read; the named reads still omit them."
|
|
69
70
|
: "This connection withholds organizations' payout bank and legal-contact details from every result.",
|
|
70
|
-
...(options.readOnly === true
|
|
71
|
+
...readOnlyNotice(options.readOnly === true),
|
|
71
72
|
...(options.defaultPageSize !== undefined
|
|
72
73
|
? [`List tools return ${options.defaultPageSize} rows by default on this connection.`]
|
|
73
74
|
: []),
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { compact as compactDefined } from "../_shared/json.js";
|
|
2
|
+
import { asArray, asRecord } from "../_shared/json.js";
|
|
3
|
+
// Tithe.ly's curated tools on the provider kit and their
|
|
2
4
|
// projections. Decision 0011's step 2: standard lists ({ items, page } with
|
|
3
5
|
// limit, cursor and fields), fields on every named read, and no `raw`: what a
|
|
4
6
|
// projection drops stays reachable through the standard hatch, which the kit
|
|
5
|
-
// builds from `api.ts`'s index and verdicts
|
|
7
|
+
// builds from `api.ts`'s index and verdicts. Each named read
|
|
6
8
|
// earns its place against the hatch with paging Tithe.ly cannot report
|
|
7
9
|
// (lookahead), units (cents, ISO dates), joins (donor, organization and
|
|
8
10
|
// payment method inline) or reconciliation of a known id after a write.
|
|
@@ -13,7 +15,7 @@ import { Refusal } from "../../http/errors.js";
|
|
|
13
15
|
import { Integer } from "../../http/json-schema.js";
|
|
14
16
|
import { lookahead } from "../../http/paging.js";
|
|
15
17
|
import { get as getTool, list } from "../../http/tools.js";
|
|
16
|
-
import {
|
|
18
|
+
import { entity, getCharge, getRecurring, listAccounts, listAllAccounts, listCharges, listOrganizations, listPaymentMethods, listRecurring, MAX_PAGE_SIZE, PAYOUT_CURRENCY, text, } from "./api.js";
|
|
17
19
|
// --- Schemas ---------------------------------------------------------------------
|
|
18
20
|
const Id = Schema.String.check(Schema.isMinLength(1));
|
|
19
21
|
const Text = Schema.optionalKey(Schema.String);
|
|
@@ -267,7 +269,7 @@ function seconds(value, name) {
|
|
|
267
269
|
return Effect.succeed(Math.floor(parsed / 1000));
|
|
268
270
|
}
|
|
269
271
|
function compact(value) {
|
|
270
|
-
return
|
|
272
|
+
return compactDefined(value);
|
|
271
273
|
}
|
|
272
274
|
/** Integer cents from Tithe.ly's string-or-number amounts. */
|
|
273
275
|
function cents(value) {
|
|
@@ -325,7 +327,7 @@ function projectOrganization(value) {
|
|
|
325
327
|
return compact({
|
|
326
328
|
organizationId: text(organization["organization_id"]),
|
|
327
329
|
name: text(organization["name"]),
|
|
328
|
-
// The giving widget id embeds Tithe.ly's giving form; the step-2 eval showed agents need it
|
|
330
|
+
// The giving widget id embeds Tithe.ly's giving form; the step-2 eval showed agents need it.
|
|
329
331
|
widgetId: text(organization["widget_id"]),
|
|
330
332
|
ownerAccountId: text(organization["account_id"]),
|
|
331
333
|
website: text(organization["website"]),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRecord } from "../_shared/json.js";
|
|
1
2
|
// Vercel's pinned contract, authentication, failures and value-safety boundary.
|
|
2
3
|
import { Effect, Schema } from "effect";
|
|
3
4
|
import { ConnectorCallError } from "../../errors.js";
|
|
@@ -24,9 +25,6 @@ const READ_POSTS = [
|
|
|
24
25
|
["POST", "/v1/registrar/domains/search", "Searches domain availability and pricing; buys nothing."],
|
|
25
26
|
["POST", "/v8/artifacts", "Reads Remote Cache metadata for a list of artifact hashes; uploads nothing."],
|
|
26
27
|
];
|
|
27
|
-
export function isRecord(value) {
|
|
28
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29
|
-
}
|
|
30
28
|
export function record(value) {
|
|
31
29
|
return isRecord(value) ? value : {};
|
|
32
30
|
}
|
|
@@ -36,9 +34,6 @@ export function text(value) {
|
|
|
36
34
|
export function invalid(message) {
|
|
37
35
|
throw new ConnectorCallError("invalid_args", message);
|
|
38
36
|
}
|
|
39
|
-
export function compact(value) {
|
|
40
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
41
|
-
}
|
|
42
37
|
function truthy(value) {
|
|
43
38
|
return value === true || value === 1 || (typeof value === "string" && /^(?:1|true)$/i.test(value.trim()));
|
|
44
39
|
}
|
|
@@ -4,7 +4,7 @@ import { ConnectorCallError } from "../../../errors.js";
|
|
|
4
4
|
import { Refusal } from "../../../http/errors.js";
|
|
5
5
|
import { Budget } from "../../../http/services.js";
|
|
6
6
|
import { checked } from "../../_shared/rest/kit.js";
|
|
7
|
-
|
|
7
|
+
const MAX_PIN_LOOKUPS = 8;
|
|
8
8
|
export const PIN_WRITE_STEPS = Object.freeze({
|
|
9
9
|
write: "once",
|
|
10
10
|
lookup1: "once",
|
|
@@ -214,7 +214,7 @@ const absent = {
|
|
|
214
214
|
//
|
|
215
215
|
// Residual risk: a secret a person typed into a free-text
|
|
216
216
|
// name, description, log line, or identifier is out of scope.
|
|
217
|
-
// Embedded URL verdict
|
|
217
|
+
// Embedded URL verdict: reviewed paths + global signing parameters.
|
|
218
218
|
// Evidence: pinned index/candidates sha256:5a702fd2dc76 identify deployment
|
|
219
219
|
// reads/creation/listing, build events and runtime logs; the operation/path
|
|
220
220
|
// list below scans errorMessage, deployments.errorMessage, payload.text/text
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { compact, isRecord } from "../_shared/json.js";
|
|
1
2
|
// Curated Vercel metadata and bounded logs through kit-owned call services.
|
|
2
3
|
import { Effect, Schema } from "effect";
|
|
3
4
|
import { ConnectorCallError } from "../../errors.js";
|
|
@@ -9,7 +10,7 @@ import { schema, typedParams } from "../_shared/rest/kit.js";
|
|
|
9
10
|
import { refuseWithheldUpload } from "../_shared/rest/value-safety.js";
|
|
10
11
|
import { rowStop } from "./lib/logs.js";
|
|
11
12
|
import { checked } from "../_shared/rest/kit.js";
|
|
12
|
-
import { admit,
|
|
13
|
+
import { admit, defaultTeam, invalid, named, queryOf, queryPairs, record, reviewedCode, restCall, text, vercelIndex, refuse, checkServer, } from "./api.js";
|
|
13
14
|
import { pinOptions, readPinnedTeam, PIN_WRITE_STEPS } from "./lib/pin.js";
|
|
14
15
|
const MAX_LOG_BYTES = 1024 * 1024;
|
|
15
16
|
const MAX_LOG_TEXT = 4_000;
|
package/dist/redaction-marker.js
CHANGED
|
@@ -7,7 +7,7 @@ export const REDACTED = "[redacted]";
|
|
|
7
7
|
* secrets from every value of a vendor body before result safety reads it, so a rule that decides
|
|
8
8
|
* on a value (a type discriminator, a record's label or type, a URL's scheme or parameter names,
|
|
9
9
|
* a Content-Type) can find the placeholder where the vendor wrote what the rule matches.
|
|
10
|
-
* Such a decision takes its most protective outcome
|
|
10
|
+
* Such a decision takes its most protective outcome.
|
|
11
11
|
*/
|
|
12
12
|
export function redactionAltered(value) {
|
|
13
13
|
return typeof value === "string" && value.includes(REDACTED);
|
|
@@ -92,7 +92,7 @@ function credentialUnit(code) {
|
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
94
|
* The text right after the placeholder at `at` that may be the rest of a credential whose public
|
|
95
|
-
* prefix redaction took
|
|
95
|
+
* prefix redaction took: up to the first unit `ends` accepts, reading later placeholders
|
|
96
96
|
* whole so none is split. Redaction can take `sk_live_`, `whsec_`, `Bearer `, or a signing
|
|
97
97
|
* parameter's name and `=`, leaving what follows; with that prefix known, any remainder rebuilds
|
|
98
98
|
* the credential, however short or encoded, so `readable` holds whenever it carries any base64 or
|
package/dist/registry.d.ts
CHANGED
|
@@ -155,6 +155,8 @@ export interface RegistryScope {
|
|
|
155
155
|
currentResultAccess?: RegistryView["recheckResultAccess"];
|
|
156
156
|
/** The admitted caller, readable only by built-in connectors; see connector-caller.ts. */
|
|
157
157
|
caller?: ConnectorCaller;
|
|
158
|
+
/** Operator admission, forwarded only to principal-forwarding remote MCP connectors. */
|
|
159
|
+
operatorCaller?: ConnectorCaller;
|
|
158
160
|
}
|
|
159
161
|
/**
|
|
160
162
|
* Holds the connector set, resolves addresses, and coalesces tool listings
|
|
@@ -238,7 +240,7 @@ export declare class Registry implements RegistryView {
|
|
|
238
240
|
*
|
|
239
241
|
* `chunks[n]` lands on `resultKeys.chunk(id, n)` inside `partition` — the
|
|
240
242
|
* layout connecta.result reads back, so a page fetches only the chunks it covers
|
|
241
|
-
* instead of the whole stored result
|
|
243
|
+
* instead of the whole stored result. Chunking is a read-cost
|
|
242
244
|
* decision, not a capacity one: however many keys an envelope occupies, it
|
|
243
245
|
* is one stash entry charged its total ASCII length.
|
|
244
246
|
*
|
|
@@ -246,6 +248,7 @@ export declare class Registry implements RegistryView {
|
|
|
246
248
|
* row in one ledger record in storage, booked by compare-and-set before any
|
|
247
249
|
* chunk is written, so every isolate and process sharing the store sees the
|
|
248
250
|
* same entries and bytes. A pending write keeps its finite charge reserved.
|
|
251
|
+
* The whole operation, including reservation, stops after 45 seconds.
|
|
249
252
|
* Writes stop after 30 seconds; absolute chunk expiries cannot pass the
|
|
250
253
|
* booked deadline even on late commit. Rejected responses leave writes
|
|
251
254
|
* unconfirmed and retain their charge. Cleanup/release and settlement each
|