@zackbart/connecta 0.23.0 → 0.24.1
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/AGENTS.md +5 -0
- package/CHANGELOG.md +53 -0
- package/README.md +18 -10
- package/dist/activity-friction.d.ts +3 -0
- package/dist/activity-friction.js +19 -0
- package/dist/activity.d.ts +11 -2
- package/dist/activity.js +15 -19
- package/dist/auth/downstream-oauth.d.ts +2 -1
- package/dist/auth/downstream-oauth.js +10 -1
- package/dist/branding.d.ts +67 -0
- package/dist/branding.js +176 -0
- package/dist/connectors/remote-mcp.js +3 -5
- package/dist/credential-contract.d.ts +24 -0
- package/dist/credential-contract.js +1 -0
- package/dist/credential-rules.d.ts +85 -0
- package/dist/credential-rules.js +107 -0
- package/dist/credentials.d.ts +4 -100
- package/dist/credentials.js +3 -107
- package/dist/execute.d.ts +6 -0
- package/dist/execute.js +17 -7
- package/dist/index.d.ts +35 -56
- package/dist/index.js +34 -58
- package/dist/invocation.js +19 -4
- package/dist/meta-tools.d.ts +4 -0
- package/dist/meta-tools.js +8 -4
- package/dist/module-contracts.d.ts +19 -0
- package/dist/module-contracts.js +1 -0
- package/dist/operator-ui/generated.js +2 -2
- package/dist/operator-ui/model.d.ts +6 -3
- package/dist/operator-ui/view.d.ts +2 -18
- package/dist/operator-ui/view.js +3 -20
- package/dist/registry.d.ts +4 -1
- package/dist/registry.js +4 -6
- package/dist/routes/activity.js +1 -1
- package/dist/routes/credentials.js +5 -2
- package/dist/routes/mcp.js +13 -3
- package/dist/routes/oauth-management.d.ts +2 -0
- package/dist/routes/oauth-management.js +108 -0
- package/dist/routes/oauth.d.ts +0 -1
- package/dist/routes/oauth.js +21 -121
- package/dist/routes/shared.d.ts +23 -17
- package/dist/routes/shared.js +48 -44
- package/dist/routes/ui.js +36 -33
- package/dist/server.js +6 -26
- package/dist/types.d.ts +2 -0
- package/dist/ui.d.ts +15 -70
- package/dist/ui.js +176 -317
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/architecture.md +26 -17
- package/documentation/auth.md +61 -106
- package/documentation/cloudflare.md +1 -1
- package/documentation/code-mode.md +2 -2
- package/documentation/connectors.md +1 -1
- package/documentation/linear.md +1 -1
- package/documentation/meta-tools.md +6 -4
- package/documentation/mixpanel.md +1 -1
- package/documentation/notion.md +2 -2
- package/documentation/operations.md +14 -14
- package/documentation/operator-ui.md +82 -104
- package/documentation/optional-modules-upgrade.md +243 -0
- package/documentation/provider-conventions.md +5 -3
- package/documentation/revenuecat.md +1 -1
- package/documentation/storage-and-credentials.md +59 -40
- package/documentation/stripe.md +1 -1
- package/documentation/upgrading.md +33 -4
- package/ethos.md +22 -30
- package/examples/worker/AGENTS.md +3 -1
- package/examples/worker/README.md +68 -84
- package/examples/worker/src/d1-activity.ts +1 -1
- package/examples/worker/src/index.ts +11 -6
- package/package.json +17 -1
- package/templates/node/AGENTS.md +8 -6
- package/templates/node/README.md +56 -67
- package/templates/node/package.json +1 -1
- package/templates/node/src/file-activity.ts +1 -1
- package/templates/node/src/index.ts +11 -12
- package/dist/access-tokens.d.ts +0 -31
- package/dist/access-tokens.js +0 -236
- package/dist/routes/access-tokens.d.ts +0 -6
- package/dist/routes/access-tokens.js +0 -83
package/dist/index.d.ts
CHANGED
|
@@ -1,34 +1,9 @@
|
|
|
1
|
+
import type { CredentialVault } from "./credential-contract.js";
|
|
1
2
|
import { Registry } from "./registry.js";
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Privacy-minimal downstream tool activity storage. Writes are best-effort
|
|
8
|
-
* and never change tool results. Implement `list` to enable the Activity UI.
|
|
9
|
-
*/
|
|
10
|
-
store: ActivityStore;
|
|
11
|
-
/**
|
|
12
|
-
* Optional authorization gate for the Activity read API. MCP authentication
|
|
13
|
-
* is still required first. Omit to admit every authenticated actor.
|
|
14
|
-
*/
|
|
15
|
-
readGate?: ActivityReadGate;
|
|
16
|
-
/** Stable deployment label included in activity events, e.g. "production". */
|
|
17
|
-
deploymentId?: string;
|
|
18
|
-
}
|
|
19
|
-
/** Operator-vault encryption. */
|
|
20
|
-
export interface ConnectaCredentialsConfig {
|
|
21
|
-
/**
|
|
22
|
-
* Base64-encoded 32-byte AES key for credentials managed on /credentials.
|
|
23
|
-
* Keep this in the runtime's secret store, never in KV or source control.
|
|
24
|
-
*/
|
|
25
|
-
encryptionKey?: string;
|
|
26
|
-
}
|
|
27
|
-
/** Operator-issued credentials for clients connecting to this deployment. */
|
|
28
|
-
export interface ConnectaAccessTokensConfig {
|
|
29
|
-
/** Maximum simultaneously active access tokens. Defaults to 100. */
|
|
30
|
-
maxActive?: number;
|
|
31
|
-
}
|
|
3
|
+
import type { ActivityModule, OperatorSurface } from "./module-contracts.js";
|
|
4
|
+
export type { ActivityModule, OperatorSurface } from "./module-contracts.js";
|
|
5
|
+
export type { CredentialVault, CredentialMetadata } from "./credential-contract.js";
|
|
6
|
+
import type { AuthenticatedIdentity, Connector, Executor, IdentityReference, InboundAuth, KVStorage, Logger } from "./types.js";
|
|
32
7
|
/** Tool-catalog caching, persistence, stale fallback, and probe deadlines. */
|
|
33
8
|
export interface ConnectaDiscoveryConfig {
|
|
34
9
|
/**
|
|
@@ -76,7 +51,7 @@ export interface ConnectaCallsConfig {
|
|
|
76
51
|
*/
|
|
77
52
|
maxResultBytes?: number;
|
|
78
53
|
}
|
|
79
|
-
/** Budgets for
|
|
54
|
+
/** Budgets for execute_code programs: host calls and rich output (`connecta.emit`). */
|
|
80
55
|
export interface ConnectaExecuteConfig {
|
|
81
56
|
/**
|
|
82
57
|
* Aggregate serialized bytes `connecta.emit` accepts per run. Default
|
|
@@ -87,6 +62,18 @@ export interface ConnectaExecuteConfig {
|
|
|
87
62
|
maxEmittedBytes?: number;
|
|
88
63
|
/** Content blocks `connecta.emit` accepts per run. Default 32. */
|
|
89
64
|
maxEmittedBlocks?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Host calls one program may make. Default 20. Invalid values fall back to
|
|
67
|
+
* the default.
|
|
68
|
+
*/
|
|
69
|
+
maxHostCalls?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Deadline for each host call a program makes, in milliseconds. Default
|
|
72
|
+
* 15_000. Raise it for providers whose legitimate calls run longer, such as
|
|
73
|
+
* analytics queries; `call_tool`'s own `timeoutMs` is unaffected. Invalid
|
|
74
|
+
* values fall back to the default.
|
|
75
|
+
*/
|
|
76
|
+
hostCallTimeoutMs?: number;
|
|
90
77
|
}
|
|
91
78
|
export interface AdmissionPoolConfig {
|
|
92
79
|
/** Simultaneous work admitted to this pool. */
|
|
@@ -116,22 +103,22 @@ export interface ConnectaAdmissionConfig {
|
|
|
116
103
|
code?: AdmissionPoolConfig;
|
|
117
104
|
}
|
|
118
105
|
/** Config-owned identity rules for one deployment and tenant. */
|
|
106
|
+
export type ConnectorPermission = "all" | "none" | readonly string[];
|
|
119
107
|
export interface ConnectaIdentityConfig {
|
|
120
108
|
/** Connector ids this admitted identity may discover and call. */
|
|
121
109
|
connectorAccess?(identity: Readonly<AuthenticatedIdentity>): "all" | readonly string[] | Promise<"all" | readonly string[]>;
|
|
122
|
-
/**
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
operatorAccess?(principal: Readonly<IdentityReference>): boolean | Promise<boolean>;
|
|
110
|
+
/** Global payload-free activity reads. Defaults to interactive humans. */
|
|
111
|
+
activityAccess?(principal: Readonly<IdentityReference>): boolean | Promise<boolean>;
|
|
112
|
+
/** Shared credential and OAuth administration. Defaults to none. */
|
|
113
|
+
credentialAdministration?(identity: Readonly<AuthenticatedIdentity>): ConnectorPermission | Promise<ConnectorPermission>;
|
|
114
|
+
/** Connecting or changing the caller's personal account. Defaults to none. */
|
|
115
|
+
personalConnection?(identity: Readonly<AuthenticatedIdentity>): ConnectorPermission | Promise<ConnectorPermission>;
|
|
129
116
|
}
|
|
130
117
|
export interface ConnectaConfig {
|
|
131
118
|
connectors: Connector[];
|
|
132
119
|
/** Inbound auth adapters. Includes bearerToken(...); omit for open (dev). */
|
|
133
120
|
auth?: InboundAuth | InboundAuth[];
|
|
134
|
-
/**
|
|
121
|
+
/** Code-derived connection visibility and independent management permissions. */
|
|
135
122
|
identity?: ConnectaIdentityConfig;
|
|
136
123
|
/** KVStorage impl. Defaults to memoryStorage(). */
|
|
137
124
|
storage?: KVStorage;
|
|
@@ -140,15 +127,12 @@ export interface ConnectaConfig {
|
|
|
140
127
|
* HTTPS URL also redirects matching inbound HTTP requests to HTTPS.
|
|
141
128
|
*/
|
|
142
129
|
publicUrl?: string;
|
|
143
|
-
/**
|
|
144
|
-
activity?:
|
|
145
|
-
/**
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
|
|
149
|
-
* require an eligible interactive operator; token secrets are returned once.
|
|
150
|
-
*/
|
|
151
|
-
accessTokens?: ConnectaAccessTokensConfig;
|
|
130
|
+
/** Optional recorder and reader, created by activityHistory() from /activity. */
|
|
131
|
+
activity?: ActivityModule;
|
|
132
|
+
/** Replaceable owner-partitioned credential storage. Omit for config-owned secrets. */
|
|
133
|
+
vault?: CredentialVault;
|
|
134
|
+
/** Optional connection UI, created by operatorUi() from /ui. */
|
|
135
|
+
ui?: OperatorSurface;
|
|
152
136
|
/** Tool-catalog caching, persistence, stale fallback, and probe deadlines. */
|
|
153
137
|
discovery?: ConnectaDiscoveryConfig;
|
|
154
138
|
/** Deployment-wide call deadlines and result paging threshold. */
|
|
@@ -157,9 +141,8 @@ export interface ConnectaConfig {
|
|
|
157
141
|
execute?: ConnectaExecuteConfig;
|
|
158
142
|
/** Bounded MCP and fallback code-mode admission. */
|
|
159
143
|
admission?: ConnectaAdmissionConfig;
|
|
160
|
-
/**
|
|
161
|
-
|
|
162
|
-
logger?: Logger;
|
|
144
|
+
/** Diagnostic output. Use "silent" to disable all diagnostic logging. */
|
|
145
|
+
logger?: Logger | "silent";
|
|
163
146
|
serverInfo?: {
|
|
164
147
|
name?: string;
|
|
165
148
|
version?: string;
|
|
@@ -198,14 +181,10 @@ export { ConnectorCallError } from "./errors.js";
|
|
|
198
181
|
export type { ConnectorCallErrorCode, CallErrorDetails } from "./errors.js";
|
|
199
182
|
export { validateToolInput } from "./validate.js";
|
|
200
183
|
export type { ValidateToolInputOptions } from "./validate.js";
|
|
201
|
-
export { bearerToken } from "./auth/bearer.js";
|
|
202
|
-
export type { BearerTokenOptions } from "./auth/bearer.js";
|
|
203
|
-
export type { AccessTokenMetadata, CreatedAccessToken, } from "./access-tokens.js";
|
|
204
184
|
export { memoryStorage } from "./storage/memory.js";
|
|
205
185
|
export { CONNECTA_VERSION } from "./version.js";
|
|
206
186
|
export type { Registry } from "./registry.js";
|
|
207
187
|
export type { RemoteMcpOptions, RemoteMcpAuth, RemoteMcpRedirectPolicy, } from "./connectors/remote-mcp.js";
|
|
208
188
|
export type { ApiOptions, ApiTool } from "./connectors/api.js";
|
|
209
|
-
export type { CatalogDriftCounts, CatalogDriftReport, Connector, ConnectorCallAdmissionInput, ConnectorCallAdmissionPolicy, ConnectorCallAdmissionRule, ConnectorRollingWindowBudget,
|
|
189
|
+
export type { CatalogDriftCounts, CatalogDriftReport, ConnectaBranding, Connector, ConnectorCallAdmissionInput, ConnectorCallAdmissionPolicy, ConnectorCallAdmissionRule, ConnectorRollingWindowBudget, ConnectorCredentialAccess, ConnectorCredentialConfig, ConnectorCredentialFieldConfig, ConnectorCredentialValues, ConnectorContext, ConnectorUsageGuide, ConnectorStatus, CredentialTestResult, AdmittingExecutor, AdmissionSnapshot, ExecuteResult, Executor, ExecutorLease, ExecutorProvider, InboundAuth, InboundAuthRuntimeContext, UiAuthConfig, AuthResult, AuthenticatedIdentity, IdentityReference, JsonSchema, KVStorage, Logger, ToolDef, ToolAnnotations, } from "./types.js";
|
|
210
190
|
export type { ActivityActor, ActivityCallSource, ActivityOutcome, ActivityPage, ActivityReadActor, ActivityReadEvent, ActivityReader, ActivityReadGate, ActivityReadPage, ActivitySink, ActivityStore, AgentFriction, CatalogDriftActivityEvent, ToolCallActivityEvent, } from "./activity.js";
|
|
211
|
-
export { InvalidActivityCursorError } from "./activity.js";
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AccessTokenManager } from "./access-tokens.js";
|
|
1
|
+
import { credentialTestRule, describeCredentialTestMismatch, } from "./credential-rules.js";
|
|
3
2
|
import { Registry } from "./registry.js";
|
|
4
3
|
import { createFetchHandler } from "./server.js";
|
|
5
|
-
import { droppedBrandingUrls, droppedUiAuthUrls } from "./
|
|
4
|
+
import { droppedBrandingUrls, droppedUiAuthUrls } from "./branding.js";
|
|
6
5
|
import { memoryStorage } from "./storage/memory.js";
|
|
7
6
|
import { CONNECTA_VERSION } from "./version.js";
|
|
8
7
|
import { AdmissionController, executorName, isAdmittingExecutor, withExecutorAdmission, } from "./executor-admission.js";
|
|
@@ -53,21 +52,15 @@ const CONFIG_SCHEMA = {
|
|
|
53
52
|
auth: null,
|
|
54
53
|
identity: {
|
|
55
54
|
connectorAccess: null,
|
|
56
|
-
|
|
55
|
+
activityAccess: null,
|
|
56
|
+
credentialAdministration: null,
|
|
57
|
+
personalConnection: null,
|
|
57
58
|
},
|
|
58
59
|
storage: null,
|
|
59
60
|
publicUrl: null,
|
|
60
|
-
activity:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
deploymentId: null,
|
|
64
|
-
},
|
|
65
|
-
credentials: {
|
|
66
|
-
encryptionKey: null,
|
|
67
|
-
},
|
|
68
|
-
accessTokens: {
|
|
69
|
-
maxActive: null,
|
|
70
|
-
},
|
|
61
|
+
activity: null,
|
|
62
|
+
vault: null,
|
|
63
|
+
ui: null,
|
|
71
64
|
discovery: {
|
|
72
65
|
concurrency: null,
|
|
73
66
|
catalogTtlSeconds: null,
|
|
@@ -82,25 +75,13 @@ const CONFIG_SCHEMA = {
|
|
|
82
75
|
execute: {
|
|
83
76
|
maxEmittedBytes: null,
|
|
84
77
|
maxEmittedBlocks: null,
|
|
78
|
+
maxHostCalls: null,
|
|
79
|
+
hostCallTimeoutMs: null,
|
|
85
80
|
},
|
|
86
81
|
admission: {
|
|
87
82
|
requests: admissionPoolSchema,
|
|
88
83
|
code: admissionPoolSchema,
|
|
89
84
|
},
|
|
90
|
-
branding: {
|
|
91
|
-
productName: null,
|
|
92
|
-
productUrl: null,
|
|
93
|
-
ownerName: null,
|
|
94
|
-
ownerUrl: null,
|
|
95
|
-
description: null,
|
|
96
|
-
pageTitle: null,
|
|
97
|
-
favicon: {
|
|
98
|
-
svg: null,
|
|
99
|
-
ico: null,
|
|
100
|
-
href: null,
|
|
101
|
-
},
|
|
102
|
-
themeColor: null,
|
|
103
|
-
},
|
|
104
85
|
logger: null,
|
|
105
86
|
serverInfo: {
|
|
106
87
|
name: null,
|
|
@@ -144,17 +125,24 @@ function rejectUnknownOptions(paths) {
|
|
|
144
125
|
if (paths.length === 0)
|
|
145
126
|
return;
|
|
146
127
|
throw new Error(`Unknown Connecta configuration option${paths.length === 1 ? "" : "s"}:\n` +
|
|
147
|
-
paths.map((path) => `- ${path}`).join("\n")
|
|
128
|
+
paths.map((path) => `- ${path}`).join("\n") +
|
|
129
|
+
(paths.includes("ConnectaConfig.credentials") ? "\nUse vault: encryptedCredentialVault(storage, key) from @zackbart/connecta/credentials." : "") +
|
|
130
|
+
(paths.includes("ConnectaConfig.accessTokens") ? "\nConnecta-issued tokens were removed. Configure an inbound auth adapter instead." : "") +
|
|
131
|
+
(paths.includes("ConnectaConfig.branding") ? "\nMove branding into ui: operatorUi({ branding }) from @zackbart/connecta/ui." : ""));
|
|
148
132
|
}
|
|
149
133
|
/** Reject JavaScript typos and removed options before construction does work. */
|
|
150
134
|
function assertKnownConfig(config) {
|
|
151
135
|
rejectUnknownOptions(unknownOptionPaths(config, "ConnectaConfig", CONFIG_SCHEMA));
|
|
136
|
+
if (config.vault && ["get", "getAll", "set", "setAll", "metadata", "delete"].some(key => typeof config.vault[key] !== "function"))
|
|
137
|
+
throw new Error("ConnectaConfig.vault must implement CredentialVault");
|
|
138
|
+
if (config.ui && (typeof config.ui.handle !== "function" || typeof config.ui.credentialHandoffUrl !== "function" || !Array.isArray(config.ui.reservedPaths)))
|
|
139
|
+
throw new Error("ConnectaConfig.ui must be created with operatorUi(...)");
|
|
152
140
|
const activity = config.activity;
|
|
153
141
|
if (activity !== undefined &&
|
|
154
142
|
(typeof activity !== "object" ||
|
|
155
143
|
activity === null ||
|
|
156
|
-
typeof activity.
|
|
157
|
-
throw new Error("ConnectaConfig.activity
|
|
144
|
+
typeof activity.recordTool !== "function")) {
|
|
145
|
+
throw new Error("ConnectaConfig.activity must be created with activityHistory(...)");
|
|
158
146
|
}
|
|
159
147
|
}
|
|
160
148
|
/**
|
|
@@ -171,7 +159,7 @@ function warnInsecureConfig(config, inboundAuth, logger) {
|
|
|
171
159
|
if (inboundAuth.length === 0 &&
|
|
172
160
|
(hasCredentialConnector || oauthConnectors.length > 0)) {
|
|
173
161
|
logger.warn("[connecta] running with no inbound authentication: any caller can " +
|
|
174
|
-
"invoke every connector
|
|
162
|
+
"invoke every shared connector. " +
|
|
175
163
|
"Configure `auth` (for example bearerToken(...) or Clerk) to gate access.");
|
|
176
164
|
}
|
|
177
165
|
// Unset publicUrl with OAuth connectors: the downstream redirect_uri is
|
|
@@ -186,7 +174,7 @@ function warnInsecureConfig(config, inboundAuth, logger) {
|
|
|
186
174
|
// Branding URLs that failed their scheme gate. Rendering silently falls back
|
|
187
175
|
// (a bad URL must not take the page down), so this warning is the only way an
|
|
188
176
|
// operator learns their value never reached the page.
|
|
189
|
-
const dropped = droppedBrandingUrls(config.branding);
|
|
177
|
+
const dropped = droppedBrandingUrls(config.ui?.branding);
|
|
190
178
|
if (dropped.length > 0) {
|
|
191
179
|
logger.warn(`[connecta] branding ${dropped.join(", ")} dropped: a branding URL is ` +
|
|
192
180
|
"used as an href, so it must be an absolute http(s) URL (favicon.href " +
|
|
@@ -250,26 +238,11 @@ export function createConnecta(config) {
|
|
|
250
238
|
'"@cloudflare/codemode" on Workers.');
|
|
251
239
|
}
|
|
252
240
|
const storage = config.storage ?? memoryStorage();
|
|
253
|
-
const logger = config.logger
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
logger.warn("Human-managed credentials are unavailable because " +
|
|
258
|
-
"credentials.encryptionKey is not configured for connectors: " +
|
|
259
|
-
credentialConnectors.map((c) => c.id).join(", "));
|
|
260
|
-
}
|
|
261
|
-
const credentialVault = encryptionKey
|
|
262
|
-
? new CredentialVault(storage, encryptionKey)
|
|
263
|
-
: undefined;
|
|
241
|
+
const logger = config.logger === "silent"
|
|
242
|
+
? { debug() { }, info() { }, warn() { }, error() { } }
|
|
243
|
+
: config.logger ?? defaultLogger();
|
|
244
|
+
const credentialVault = config.vault;
|
|
264
245
|
const configuredAuth = normalizeAuth(config.auth);
|
|
265
|
-
const accessTokens = config.accessTokens
|
|
266
|
-
? new AccessTokenManager(storage, config.accessTokens)
|
|
267
|
-
: undefined;
|
|
268
|
-
if (accessTokens &&
|
|
269
|
-
!configuredAuth.some((provider) => provider.interactiveOperator)) {
|
|
270
|
-
throw new Error("accessTokens requires an interactive operator auth provider: only an eligible " +
|
|
271
|
-
"operator may create, rename, or revoke deployment access tokens");
|
|
272
|
-
}
|
|
273
246
|
const serverInfo = {
|
|
274
247
|
...config.serverInfo,
|
|
275
248
|
name: config.serverInfo?.name ?? "connecta",
|
|
@@ -279,9 +252,11 @@ export function createConnecta(config) {
|
|
|
279
252
|
storage,
|
|
280
253
|
logger,
|
|
281
254
|
credentialVault,
|
|
255
|
+
credentialUi: Boolean(config.ui),
|
|
282
256
|
catalogDriftActivity: config.activity?.store
|
|
283
257
|
? {
|
|
284
258
|
sink: config.activity.store,
|
|
259
|
+
recordDrift: config.activity.recordDrift,
|
|
285
260
|
serverInfo,
|
|
286
261
|
...(config.activity.deploymentId !== undefined
|
|
287
262
|
? { deploymentId: config.activity.deploymentId }
|
|
@@ -293,7 +268,7 @@ export function createConnecta(config) {
|
|
|
293
268
|
toolCatalogStaleSeconds: config.discovery?.staleCatalogSeconds,
|
|
294
269
|
maxResultBytes: config.calls?.maxResultBytes,
|
|
295
270
|
});
|
|
296
|
-
const inboundAuth =
|
|
271
|
+
const inboundAuth = configuredAuth;
|
|
297
272
|
warnInsecureConfig(config, inboundAuth, logger);
|
|
298
273
|
const requestAdmission = admissionController(config.admission?.requests, REQUEST_ADMISSION_DEFAULTS);
|
|
299
274
|
const configuredCodeAdmission = admissionController(config.admission?.code, CODE_ADMISSION_DEFAULTS);
|
|
@@ -319,6 +294,7 @@ export function createConnecta(config) {
|
|
|
319
294
|
serverInfo,
|
|
320
295
|
logger,
|
|
321
296
|
activity: config.activity?.store,
|
|
297
|
+
activityModule: config.activity,
|
|
322
298
|
activityReadGate: config.activity?.readGate,
|
|
323
299
|
activityDeploymentId: config.activity?.deploymentId,
|
|
324
300
|
executor,
|
|
@@ -329,10 +305,12 @@ export function createConnecta(config) {
|
|
|
329
305
|
discoveryConcurrency: config.discovery?.concurrency,
|
|
330
306
|
maxEmittedBytes: config.execute?.maxEmittedBytes,
|
|
331
307
|
maxEmittedBlocks: config.execute?.maxEmittedBlocks,
|
|
308
|
+
maxHostCalls: config.execute?.maxHostCalls,
|
|
309
|
+
hostCallTimeoutMs: config.execute?.hostCallTimeoutMs,
|
|
332
310
|
credentialVault,
|
|
333
|
-
|
|
311
|
+
ui: config.ui,
|
|
334
312
|
deploymentInfo: config.deploymentInfo,
|
|
335
|
-
branding: config.branding,
|
|
313
|
+
branding: config.ui?.branding,
|
|
336
314
|
});
|
|
337
315
|
let closePromise;
|
|
338
316
|
return {
|
|
@@ -358,7 +336,5 @@ export { ConnectorCallError } from "./errors.js";
|
|
|
358
336
|
// implement the Connector interface directly. Returns the error rather than
|
|
359
337
|
// throwing so the caller decides what to do with it.
|
|
360
338
|
export { validateToolInput } from "./validate.js";
|
|
361
|
-
export { bearerToken } from "./auth/bearer.js";
|
|
362
339
|
export { memoryStorage } from "./storage/memory.js";
|
|
363
340
|
export { CONNECTA_VERSION } from "./version.js";
|
|
364
|
-
export { InvalidActivityCursorError } from "./activity.js";
|
package/dist/invocation.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { recordToolActivity, } from "./activity.js";
|
|
2
1
|
import { isCallAdmissionError } from "./call-admission.js";
|
|
3
2
|
import { classifyCallError, ConnectorCallError, echoedCallArgs, framingError, } from "./errors.js";
|
|
4
3
|
import { unwrapMcpResult } from "./mcp-result.js";
|
|
@@ -28,7 +27,7 @@ function callerCancelledDetails() {
|
|
|
28
27
|
function recoveryMode(registry, connector, baseUrl) {
|
|
29
28
|
if (connector.startAuth)
|
|
30
29
|
return "oauth";
|
|
31
|
-
if (connector.credential &&
|
|
30
|
+
if (registry.credentialUiAvailable() && connector.credential &&
|
|
32
31
|
registry.contextFor(connector.id, baseUrl).credential) {
|
|
33
32
|
return "operator_config";
|
|
34
33
|
}
|
|
@@ -116,7 +115,7 @@ export class InvocationService {
|
|
|
116
115
|
: attempted;
|
|
117
116
|
if (!identity)
|
|
118
117
|
return;
|
|
119
|
-
|
|
118
|
+
this.activity?.recordTool?.(this.activity, {
|
|
120
119
|
connectorId: identity.connectorId,
|
|
121
120
|
toolName: identity.toolName,
|
|
122
121
|
address: `${identity.connectorId}.${identity.toolName}`,
|
|
@@ -185,7 +184,23 @@ export class InvocationService {
|
|
|
185
184
|
};
|
|
186
185
|
const failed = (error) => {
|
|
187
186
|
const diagnostics = timing();
|
|
188
|
-
const
|
|
187
|
+
const target = resolved ?? activityTarget;
|
|
188
|
+
const details = enrich(error, target);
|
|
189
|
+
// Activity rows stay payload-free by construction; the operator's log is
|
|
190
|
+
// where the downstream reason goes, bounded and without arguments.
|
|
191
|
+
if (target && details.code !== "destructive_tool_requires_approval") {
|
|
192
|
+
this.registry
|
|
193
|
+
.contextFor(target.connector.id, this.catalog.baseUrl, this.catalog.requestScope)
|
|
194
|
+
.logger.warn("[connecta] call failed", {
|
|
195
|
+
connector: target.connector.id,
|
|
196
|
+
tool: target.toolName,
|
|
197
|
+
source: context.source,
|
|
198
|
+
code: details.code,
|
|
199
|
+
attempts,
|
|
200
|
+
durationMs: Date.now() - started,
|
|
201
|
+
message: String(details.message ?? "").slice(0, 300),
|
|
202
|
+
});
|
|
203
|
+
}
|
|
189
204
|
record(details.code === "timeout"
|
|
190
205
|
? "timeout"
|
|
191
206
|
: details.code === "cancelled"
|
package/dist/meta-tools.d.ts
CHANGED
|
@@ -94,6 +94,8 @@ export declare function createMetaTools(registry: RegistryView, baseUrl: string,
|
|
|
94
94
|
/** Maximum simultaneous connector discovery operations. Default 4. */
|
|
95
95
|
discoveryConcurrency?: number | undefined;
|
|
96
96
|
activity?: ActivityRequestContext | undefined;
|
|
97
|
+
canManageAuth?: ((id: string) => boolean) | undefined;
|
|
98
|
+
credentialHandoffUrl?: string | undefined;
|
|
97
99
|
/** Inbound request cancellation shared by every call this request makes. */
|
|
98
100
|
requestSignal?: AbortSignal | undefined;
|
|
99
101
|
/** Runtime-owned tail for stale catalog refreshes. */
|
|
@@ -120,6 +122,8 @@ export declare function registerMetaTools(server: McpServer, registry: RegistryV
|
|
|
120
122
|
probeTimeoutMs?: number | undefined;
|
|
121
123
|
discoveryConcurrency?: number | undefined;
|
|
122
124
|
activity?: ActivityRequestContext | undefined;
|
|
125
|
+
canManageAuth?: ((id: string) => boolean) | undefined;
|
|
126
|
+
credentialHandoffUrl?: string | undefined;
|
|
123
127
|
requestSignal?: AbortSignal | undefined;
|
|
124
128
|
defer?: DeferredWork | undefined;
|
|
125
129
|
}): void;
|
package/dist/meta-tools.js
CHANGED
|
@@ -448,12 +448,12 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
|
|
|
448
448
|
});
|
|
449
449
|
}
|
|
450
450
|
const ctx = registry.contextFor(connector.id, baseUrl, requestScope);
|
|
451
|
-
if (!ctx.credential) {
|
|
451
|
+
if (!ctx.credential || !opts.credentialHandoffUrl) {
|
|
452
452
|
return jsonResult({
|
|
453
453
|
connector: connector.id,
|
|
454
454
|
recovery: "unavailable",
|
|
455
|
-
message: "Credential
|
|
456
|
-
"
|
|
455
|
+
message: "Credential recovery needs both a vault and the optional UI. Configure " +
|
|
456
|
+
"vault and ui in deployment code, then call " +
|
|
457
457
|
"authorize_connector again.",
|
|
458
458
|
});
|
|
459
459
|
}
|
|
@@ -474,7 +474,7 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
|
|
|
474
474
|
label: connector.credential.label,
|
|
475
475
|
fields,
|
|
476
476
|
},
|
|
477
|
-
operatorUrl:
|
|
477
|
+
operatorUrl: opts.credentialHandoffUrl,
|
|
478
478
|
instructions: "Have the operator open operatorUrl, set and test the credential, " +
|
|
479
479
|
"then retry the original call. No redeploy is needed. " +
|
|
480
480
|
(connector.authScope === "personal"
|
|
@@ -482,6 +482,8 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
|
|
|
482
482
|
: "Shared credential mutation requires a signed-in human with access to this connector."),
|
|
483
483
|
});
|
|
484
484
|
}
|
|
485
|
+
if (!opts.canManageAuth?.(connector.id))
|
|
486
|
+
return jsonResult({ connector: connector.id, recovery: "unavailable", message: "Your identity is not permitted to manage authentication for this connection." });
|
|
485
487
|
const ctx = registry.contextFor(connector.id, baseUrl, requestScope);
|
|
486
488
|
try {
|
|
487
489
|
const status = await connector.startAuth(ctx, args.force !== undefined ? { force: args.force } : {});
|
|
@@ -581,6 +583,8 @@ export function registerMetaTools(server, registry, ctx) {
|
|
|
581
583
|
probeTimeoutMs: ctx.probeTimeoutMs,
|
|
582
584
|
discoveryConcurrency: ctx.discoveryConcurrency,
|
|
583
585
|
activity: ctx.activity,
|
|
586
|
+
canManageAuth: ctx.canManageAuth,
|
|
587
|
+
credentialHandoffUrl: ctx.credentialHandoffUrl,
|
|
584
588
|
requestSignal: ctx.requestSignal,
|
|
585
589
|
defer: ctx.defer,
|
|
586
590
|
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ConnectaBranding } from "./types.js";
|
|
2
|
+
import type { ActivityStore, ActivityReadGate, recordToolActivity, recordCatalogDriftActivity } from "./activity.js";
|
|
3
|
+
import type { RouteContext } from "./routes/shared.js";
|
|
4
|
+
/** Construction-time UI contract. Core never imports the implementation. */
|
|
5
|
+
export interface OperatorSurface {
|
|
6
|
+
readonly branding?: ConnectaBranding;
|
|
7
|
+
readonly reservedPaths: readonly string[];
|
|
8
|
+
credentialHandoffUrl(baseUrl: string): string;
|
|
9
|
+
handle(context: RouteContext): Promise<Response | null>;
|
|
10
|
+
}
|
|
11
|
+
/** Optional recording and reading callbacks supplied by /activity. */
|
|
12
|
+
export interface ActivityModule {
|
|
13
|
+
readonly store: ActivityStore;
|
|
14
|
+
readonly deploymentId?: string;
|
|
15
|
+
readonly readGate?: ActivityReadGate;
|
|
16
|
+
handle(context: RouteContext): Promise<Response | null>;
|
|
17
|
+
readonly recordTool: typeof recordToolActivity;
|
|
18
|
+
readonly recordDrift: typeof recordCatalogDriftActivity;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|