@zackbart/connecta 0.20.0 → 0.21.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 +49 -0
- package/README.md +3 -1
- package/bin/connecta.mjs +23 -6
- package/dist/auth/bearer.d.ts +2 -2
- package/dist/auth/bearer.js +2 -2
- package/dist/auth/clerk.js +1 -0
- package/dist/auth/cloudflare-access.d.ts +8 -0
- package/dist/auth/cloudflare-access.js +66 -0
- package/dist/execute.js +12 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/meta-tools.js +3 -3
- package/dist/operator-ui/generated.js +1 -1
- package/dist/operator-ui/model.d.ts +3 -3
- package/dist/operator-ui/view.d.ts +1 -1
- package/dist/operator-ui/view.js +6 -3
- package/dist/routes/access-tokens.d.ts +1 -1
- package/dist/routes/access-tokens.js +2 -2
- package/dist/routes/activity.js +2 -2
- package/dist/routes/credentials.js +1 -1
- package/dist/routes/mcp.js +1 -1
- package/dist/routes/oauth.js +1 -1
- package/dist/routes/shared.d.ts +4 -4
- package/dist/routes/shared.js +10 -10
- package/dist/routes/ui.js +12 -9
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +7 -4
- package/dist/types.d.ts +37 -22
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +3 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/architecture.md +7 -4
- package/documentation/auth.md +71 -7
- package/documentation/code-mode.md +4 -4
- package/documentation/meta-tools.md +22 -20
- package/documentation/operations.md +23 -8
- package/documentation/operator-ui.md +21 -5
- package/documentation/upgrading.md +76 -4
- package/ethos.md +2 -3
- package/examples/worker/README.md +52 -32
- package/examples/worker/src/index.ts +32 -38
- package/examples/worker/wrangler.jsonc +12 -4
- package/package.json +5 -1
- package/templates/node/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,55 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this package are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.21.0 — 2026-08-28
|
|
6
|
+
|
|
7
|
+
Cloudflare Access becomes the canonical interactive-auth path for Worker
|
|
8
|
+
deployments. It authenticates both MCP clients and human operators before the
|
|
9
|
+
Worker runs, while connecta consumes only the trusted runtime identity. Clerk
|
|
10
|
+
is unchanged and remains supported: existing deployments can add Access,
|
|
11
|
+
verify the edge cutover, and remove Clerk later, with no storage migration or
|
|
12
|
+
token conversion. Node deployments can ignore this release beyond the version
|
|
13
|
+
pin.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **Direct Worker Access auth.** `cloudflareAccessAuth()` ships from
|
|
18
|
+
`@zackbart/connecta/auth/cloudflare-access` with no dependency and no JWT
|
|
19
|
+
verifier. Human `ctx.access` identities may use MCP and operator routes;
|
|
20
|
+
service-token identities may use MCP but cannot mutate operator state. Since
|
|
21
|
+
Cloudflare exposes no user identity for a service token, its Access
|
|
22
|
+
application audience is the shared activity subject. The same suite runs
|
|
23
|
+
under Node and workerd (#506).
|
|
24
|
+
- **Ambient operator sessions.** The operator shell selects Cloudflare Access
|
|
25
|
+
when the current invocation carries it, sends no browser-readable token, and
|
|
26
|
+
signs out through Cloudflare. A co-configured Clerk provider remains the
|
|
27
|
+
shell before Access is attached and the rollback path after it is detached
|
|
28
|
+
(#506).
|
|
29
|
+
- **Access-aware doctor.** `connecta doctor` accepts
|
|
30
|
+
`CF_ACCESS_CLIENT_ID`/`CF_ACCESS_CLIENT_SECRET` and sends the pair to health
|
|
31
|
+
and MCP requests. A partial pair fails before network access (#506).
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- **Cold reads stay in code mode.** One known canonical address still uses
|
|
36
|
+
`call_tool`, while an unknown-address read now starts with one
|
|
37
|
+
`execute_code` program and keeps discovery results off the model-facing
|
|
38
|
+
route. The current-version benchmark is reset to four deterministic
|
|
39
|
+
whole-agent cases covering both routes, exact provider semantics, private
|
|
40
|
+
pagination, forwarding bytes, tokens, and latency.
|
|
41
|
+
- **Worker deployment path.** The shipped Worker example uses Access and
|
|
42
|
+
Managed OAuth through a Worker-level `worker` destination, carries a local
|
|
43
|
+
`access.dev` identity, and documents service tokens for unattended callers.
|
|
44
|
+
A hostname-only Access application gates the URL but does not supply
|
|
45
|
+
`ctx.access`. The Clerk shape stays beside the provider as the reversible
|
|
46
|
+
migration seam. Static connecta and operator-issued bearers remain supported
|
|
47
|
+
by core but are not standalone credentials through a whole-Worker Access
|
|
48
|
+
gate (#506).
|
|
49
|
+
- **Operator capability is vendor-neutral.** Inbound auth providers now declare
|
|
50
|
+
interactive-operator capability explicitly, and runtime context reaches
|
|
51
|
+
their authorization hook as an optional third argument. Existing custom
|
|
52
|
+
providers with the two-argument hook remain source-compatible (#506).
|
|
53
|
+
|
|
5
54
|
## 0.20.0 — 2026-08-26
|
|
6
55
|
|
|
7
56
|
This release removes the two side languages that had grown around the seven
|
package/README.md
CHANGED
|
@@ -78,7 +78,9 @@ Fifty issues in, one small object out. Your context window notices.
|
|
|
78
78
|
|
|
79
79
|
There is also an operator surface, off until you turn it on: sign-in, an
|
|
80
80
|
encrypted credential vault with rotation, revocable per-client tokens, and a
|
|
81
|
-
payload-free activity log.
|
|
81
|
+
payload-free activity log. Worker deployments can use Cloudflare Access for
|
|
82
|
+
both MCP and operator identity; Node deployments and existing Workers can use
|
|
83
|
+
Clerk.
|
|
82
84
|
|
|
83
85
|
Connecta is not a platform, a marketplace, a policy engine, or a multi-tenant
|
|
84
86
|
service. Those are decisions, and the [ethos](./ethos.md) records each one
|
package/bin/connecta.mjs
CHANGED
|
@@ -27,7 +27,8 @@ function shellCd(path) {
|
|
|
27
27
|
function usage() {
|
|
28
28
|
console.log(`Usage:
|
|
29
29
|
connecta init [directory]
|
|
30
|
-
CONNECTA_TOKEN=<bearer> connecta doctor [--url http://localhost:8787]
|
|
30
|
+
CONNECTA_TOKEN=<bearer> connecta doctor [--url http://localhost:8787]
|
|
31
|
+
CF_ACCESS_CLIENT_ID=<id> CF_ACCESS_CLIENT_SECRET=<secret> connecta doctor --url https://worker.example`);
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
async function init() {
|
|
@@ -169,19 +170,35 @@ async function doctor() {
|
|
|
169
170
|
!loopbackHosts.has(parsedUrl.hostname)
|
|
170
171
|
) {
|
|
171
172
|
throw new Error(
|
|
172
|
-
"Refusing to send
|
|
173
|
+
"Refusing to send authentication credentials over remote plaintext HTTP. Use HTTPS.",
|
|
173
174
|
);
|
|
174
175
|
}
|
|
175
176
|
const baseUrl = requestedUrl.replace(/\/+$/, "");
|
|
176
177
|
const token = process.env.CONNECTA_TOKEN;
|
|
177
|
-
|
|
178
|
+
const accessClientId = process.env.CF_ACCESS_CLIENT_ID;
|
|
179
|
+
const accessClientSecret = process.env.CF_ACCESS_CLIENT_SECRET;
|
|
180
|
+
if (Boolean(accessClientId) !== Boolean(accessClientSecret)) {
|
|
178
181
|
throw new Error(
|
|
179
|
-
"Set
|
|
182
|
+
"Set both CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET.",
|
|
180
183
|
);
|
|
181
184
|
}
|
|
185
|
+
if (!token && !accessClientId) {
|
|
186
|
+
throw new Error(
|
|
187
|
+
"Set CONNECTA_TOKEN or a CF_ACCESS_CLIENT_ID/CF_ACCESS_CLIENT_SECRET pair so doctor can inspect the MCP surface.",
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
const authHeaders = {
|
|
191
|
+
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
192
|
+
...(accessClientId && accessClientSecret
|
|
193
|
+
? {
|
|
194
|
+
"CF-Access-Client-Id": accessClientId,
|
|
195
|
+
"CF-Access-Client-Secret": accessClientSecret,
|
|
196
|
+
}
|
|
197
|
+
: {}),
|
|
198
|
+
};
|
|
182
199
|
|
|
183
200
|
const health = await jsonResponse(
|
|
184
|
-
await doctorFetch(`${baseUrl}/health
|
|
201
|
+
await doctorFetch(`${baseUrl}/health`, { headers: authHeaders }),
|
|
185
202
|
);
|
|
186
203
|
if (health.status !== "ok") {
|
|
187
204
|
throw new Error(`Unexpected health status: ${String(health.status)}`);
|
|
@@ -206,7 +223,7 @@ async function doctor() {
|
|
|
206
223
|
await doctorFetch(`${baseUrl}/mcp`, {
|
|
207
224
|
method: "POST",
|
|
208
225
|
headers: {
|
|
209
|
-
|
|
226
|
+
...authHeaders,
|
|
210
227
|
"Content-Type": "application/json",
|
|
211
228
|
Accept: "application/json, text/event-stream",
|
|
212
229
|
},
|
package/dist/auth/bearer.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface BearerTokenOptions {
|
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
7
|
* Static bearer-token inbound auth. Constant-time compares the Bearer token
|
|
8
|
-
* against `secret`. Checked
|
|
9
|
-
* falls through so
|
|
8
|
+
* against `secret`. Checked before interactive providers in the server; a
|
|
9
|
+
* mismatch falls through so another configured provider can admit the request.
|
|
10
10
|
*/
|
|
11
11
|
export declare function bearerToken(secret: string, options?: BearerTokenOptions): InboundAuth;
|
package/dist/auth/bearer.js
CHANGED
|
@@ -16,8 +16,8 @@ function timingSafeEqual(a, b) {
|
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* Static bearer-token inbound auth. Constant-time compares the Bearer token
|
|
19
|
-
* against `secret`. Checked
|
|
20
|
-
* falls through so
|
|
19
|
+
* against `secret`. Checked before interactive providers in the server; a
|
|
20
|
+
* mismatch falls through so another configured provider can admit the request.
|
|
21
21
|
*/
|
|
22
22
|
export function bearerToken(secret, options = {}) {
|
|
23
23
|
assertNoRetiredToolkitOptions("bearerToken", options);
|
package/dist/auth/clerk.js
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { InboundAuth } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Trust the identity Cloudflare Access attached to this direct Worker
|
|
4
|
+
* invocation. Access has already validated the browser session, Managed OAuth
|
|
5
|
+
* token, or service-token headers before the Worker runs; this adapter does
|
|
6
|
+
* not accept or parse a caller-supplied JWT.
|
|
7
|
+
*/
|
|
8
|
+
export declare function cloudflareAccessAuth(): InboundAuth;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
function identityString(identity, field) {
|
|
2
|
+
const value = identity[field];
|
|
3
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
4
|
+
}
|
|
5
|
+
function unauthorized() {
|
|
6
|
+
return {
|
|
7
|
+
ok: false,
|
|
8
|
+
response: Response.json({ error: "Cloudflare Access authentication required" }, { status: 401 }),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Trust the identity Cloudflare Access attached to this direct Worker
|
|
13
|
+
* invocation. Access has already validated the browser session, Managed OAuth
|
|
14
|
+
* token, or service-token headers before the Worker runs; this adapter does
|
|
15
|
+
* not accept or parse a caller-supplied JWT.
|
|
16
|
+
*/
|
|
17
|
+
export function cloudflareAccessAuth() {
|
|
18
|
+
return {
|
|
19
|
+
kind: "cloudflare-access",
|
|
20
|
+
interactiveOperator: true,
|
|
21
|
+
activityActorNamespace: "cloudflare-access",
|
|
22
|
+
uiAuth: { kind: "cloudflare-access" },
|
|
23
|
+
async authorize(_request, _baseUrl, runtimeContext) {
|
|
24
|
+
const access = runtimeContext?.access;
|
|
25
|
+
if (!access)
|
|
26
|
+
return unauthorized();
|
|
27
|
+
let identity;
|
|
28
|
+
try {
|
|
29
|
+
identity = await access.getIdentity();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return unauthorized();
|
|
33
|
+
}
|
|
34
|
+
if (!identity) {
|
|
35
|
+
// Access service-token policies authenticate the request and attach
|
|
36
|
+
// ctx.access, but getIdentity() is a user-identity API and returns
|
|
37
|
+
// undefined. Cloudflare strips the service-token headers before the
|
|
38
|
+
// Worker, so the Access application audience is the only trusted,
|
|
39
|
+
// stable service attribution available without parsing a JWT.
|
|
40
|
+
return { ok: true, subjectId: access.aud };
|
|
41
|
+
}
|
|
42
|
+
const userId = identityString(identity, "user_uuid") ??
|
|
43
|
+
identityString(identity, "email");
|
|
44
|
+
const commonName = identityString(identity, "common_name");
|
|
45
|
+
const serviceTokenId = identityString(identity, "service_token_id");
|
|
46
|
+
if (identity.service_token_status === true ||
|
|
47
|
+
serviceTokenId ||
|
|
48
|
+
(!userId && commonName)) {
|
|
49
|
+
const subjectId = serviceTokenId ?? commonName;
|
|
50
|
+
return subjectId
|
|
51
|
+
? { ok: true, subjectId }
|
|
52
|
+
: {
|
|
53
|
+
ok: false,
|
|
54
|
+
response: Response.json({ error: "Cloudflare Access service identity required" }, { status: 403 }),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (!userId) {
|
|
58
|
+
return {
|
|
59
|
+
ok: false,
|
|
60
|
+
response: Response.json({ error: "Cloudflare Access user identity required" }, { status: 403 }),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return { ok: true, userId, subjectId: userId };
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
package/dist/execute.js
CHANGED
|
@@ -6,7 +6,7 @@ import { guardExecuteResultValue, MAX_EXECUTE_LOG_CHARS, truncateExecuteText, }
|
|
|
6
6
|
import { ExecutorAdmissionError, ExecutorExecutionError, isAdmittingExecutor, } from "./executor-admission.js";
|
|
7
7
|
import { boundedEchoText, classifyCallError, msg } from "./errors.js";
|
|
8
8
|
import { InvocationFailure, InvocationService, } from "./invocation.js";
|
|
9
|
-
import { hasConnectorGuides } from "./skills.js";
|
|
9
|
+
import { connectorGuide, connectorGuideRequired, connectorSkillName, hasConnectorGuides, } from "./skills.js";
|
|
10
10
|
/** Keep one model-written program from amplifying into an unbounded fan-out. */
|
|
11
11
|
const EXECUTE_MAX_HOST_CALLS = 20;
|
|
12
12
|
export const EXECUTE_MAX_BATCH_CALLS = 10;
|
|
@@ -856,9 +856,15 @@ function connectorInventory(connectors) {
|
|
|
856
856
|
return `${prefix}none.`;
|
|
857
857
|
const entries = connectors.map((connector) => {
|
|
858
858
|
const shortcut = sanitizeIdentifier(connector.id);
|
|
859
|
-
|
|
859
|
+
const address = shortcut === connector.id
|
|
860
860
|
? connector.id
|
|
861
861
|
: `${connector.id} (shortcut ${shortcut})`;
|
|
862
|
+
if (!connectorGuide(connector))
|
|
863
|
+
return address;
|
|
864
|
+
const requirement = connectorGuideRequired(connector)
|
|
865
|
+
? "required guide"
|
|
866
|
+
: "guide";
|
|
867
|
+
return `${address} (${requirement} ${connectorSkillName(connector.id)})`;
|
|
862
868
|
});
|
|
863
869
|
const shown = [];
|
|
864
870
|
for (let index = 0; index < entries.length; index++) {
|
|
@@ -879,18 +885,18 @@ function connectorInventory(connectors) {
|
|
|
879
885
|
return `${prefix}${shown.join(", ")}.`;
|
|
880
886
|
return `${prefix}${shown.join(", ")}${shown.length > 0 ? "; " : ""}+${omitted} more.`;
|
|
881
887
|
}
|
|
882
|
-
const executeDescription = (emitBudgets, connectorGuides, connectors) => `Choose the route before discovery.
|
|
888
|
+
const executeDescription = (emitBudgets, connectorGuides, connectors) => `Choose the route before discovery. A known address uses call_tool. Unknown-address and wider read-only work use exactly one execute_code call that discovers, calls, and returns the answer. Finish in that program; don't return catalog matches for a later call. Only readOnlyHint: true tools are available. Limits: ${EXECUTE_MAX_HOST_CALLS} host calls per run, ${EXECUTE_MAX_BATCH_CALLS} per batch, ${EXECUTE_HOST_CALL_TIMEOUT_MS / 1_000}-second host deadline.
|
|
883
889
|
|
|
884
890
|
${connectorInventory(connectors)}
|
|
885
891
|
|
|
886
|
-
Write one plain-JavaScript async arrow function. Use only:
|
|
892
|
+
Fetch required guides named above before executing. Write one plain-JavaScript async arrow function. Use only:
|
|
887
893
|
- <connectorId>.<toolName>(args) for a sanitized shortcut, or connecta.call(address, args) for a canonical address.
|
|
888
|
-
- connecta.search(args)
|
|
894
|
+
- connecta.search(args) returns { tools }; connecta.describe(args) returns { tools }; use entry key lists. connecta.batch(calls) accepts canonical connector addresses only.
|
|
889
895
|
- connecta.emit(block) — { type: "text", text } or { type: "image" | "audio", data (base64), mimeType }. Success-only; ${emitBudgets.maxBlocks} blocks/${emitBudgets.maxBytes} bytes; invalid/over-budget throws.
|
|
890
896
|
- connecta.ui(html) for one display-only, success-only view; return the same summary the HTML renders.
|
|
891
897
|
- console.log(...) — captured.
|
|
892
898
|
|
|
893
|
-
|
|
899
|
+
No portable ambient capabilities. Return JSON; reduce large results before truncation. Build arguments from required input keys and schemas, never descriptions or output keys. Fetch skills({ name: "usage" }) only when this is insufficient or repair is needed; it has full rules, examples${connectorGuides ? ", guide handling" : ""}, and runtime details.`;
|
|
894
900
|
/** Register the execute_code meta-tool. Only called when an executor is configured. */
|
|
895
901
|
export function registerExecuteTool(server, registry, ctx) {
|
|
896
902
|
// Resolved once so the description and the collector cannot disagree about
|
package/dist/index.d.ts
CHANGED
|
@@ -132,7 +132,7 @@ export interface ConnectaConfig {
|
|
|
132
132
|
credentials?: ConnectaCredentialsConfig;
|
|
133
133
|
/**
|
|
134
134
|
* Named, revocable Bearer tokens for MCP clients. Creation and mutation
|
|
135
|
-
* require an eligible
|
|
135
|
+
* require an eligible interactive operator; token secrets are returned once.
|
|
136
136
|
*/
|
|
137
137
|
accessTokens?: ConnectaAccessTokensConfig;
|
|
138
138
|
/** Tool-catalog caching, persistence, stale fallback, and probe deadlines. */
|
|
@@ -192,6 +192,6 @@ export { CONNECTA_VERSION } from "./version.js";
|
|
|
192
192
|
export type { Registry } from "./registry.js";
|
|
193
193
|
export type { RemoteMcpOptions, RemoteMcpAuth, RemoteMcpRedirectPolicy, } from "./connectors/remote-mcp.js";
|
|
194
194
|
export type { ApiOptions, ApiTool } from "./connectors/api.js";
|
|
195
|
-
export type { CatalogDriftCounts, CatalogDriftReport, Connector, ConnectorCallAdmissionInput, ConnectorCallAdmissionPolicy, ConnectorCallAdmissionRule, ConnectorRollingWindowBudget, ConnectaBranding, ConnectorCredentialAccess, ConnectorCredentialConfig, ConnectorCredentialFieldConfig, ConnectorCredentialValues, ConnectorContext, ConnectorUsageGuide, ConnectorStatus, CredentialTestResult, AdmittingExecutor, AdmissionSnapshot, ExecuteResult, Executor, ExecutorLease, ExecutorProvider, InboundAuth, UiAuthConfig, AuthResult, JsonSchema, KVStorage, Logger, ToolDef, ToolAnnotations, } from "./types.js";
|
|
195
|
+
export type { CatalogDriftCounts, CatalogDriftReport, Connector, ConnectorCallAdmissionInput, ConnectorCallAdmissionPolicy, ConnectorCallAdmissionRule, ConnectorRollingWindowBudget, ConnectaBranding, ConnectorCredentialAccess, ConnectorCredentialConfig, ConnectorCredentialFieldConfig, ConnectorCredentialValues, ConnectorContext, ConnectorUsageGuide, ConnectorStatus, CredentialTestResult, AdmittingExecutor, AdmissionSnapshot, ExecuteResult, Executor, ExecutorLease, ExecutorProvider, InboundAuth, InboundAuthRuntimeContext, UiAuthConfig, AuthResult, JsonSchema, KVStorage, Logger, ToolDef, ToolAnnotations, } from "./types.js";
|
|
196
196
|
export type { ActivityActor, ActivityCallSource, ActivityOutcome, ActivityPage, ActivityReadActor, ActivityReadEvent, ActivityReader, ActivityReadGate, ActivityReadPage, ActivitySink, ActivityStore, AgentFriction, CatalogDriftActivityEvent, ToolCallActivityEvent, } from "./activity.js";
|
|
197
197
|
export { InvalidActivityCursorError } from "./activity.js";
|
package/dist/index.js
CHANGED
|
@@ -262,8 +262,8 @@ export function createConnecta(config) {
|
|
|
262
262
|
? new AccessTokenManager(storage, config.accessTokens)
|
|
263
263
|
: undefined;
|
|
264
264
|
if (accessTokens &&
|
|
265
|
-
!configuredAuth.some((provider) => provider.
|
|
266
|
-
throw new Error("accessTokens requires
|
|
265
|
+
!configuredAuth.some((provider) => provider.interactiveOperator)) {
|
|
266
|
+
throw new Error("accessTokens requires an interactive operator auth provider: only an eligible " +
|
|
267
267
|
"operator may create, rename, or revoke deployment access tokens");
|
|
268
268
|
}
|
|
269
269
|
const serverInfo = {
|
package/dist/meta-tools.js
CHANGED
|
@@ -515,12 +515,12 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
|
|
|
515
515
|
},
|
|
516
516
|
};
|
|
517
517
|
}
|
|
518
|
-
const SEARCH_DESC = `Use top-level search for
|
|
519
|
-
const CALL_DESC = 'Call one tool explicitly annotated readOnlyHint: true. Use execute_code for multiple, dependent, or reduced read-only
|
|
518
|
+
const SEARCH_DESC = `Use top-level search for catalog inspection or approval-required work before call_destructive_tool. Unknown-address read-only work belongs in one execute_code program that searches, calls, and returns the answer. Use 2–4 action/object terms and includeSchemas="compact"; the default limit is ${DEFAULT_SEARCH_LIMIT}. Set connector when known. safety="readOnly" finds direct or program calls; "approvalRequired" finds the fail-closed complement. These filters grant no authority. Empty query browses.`;
|
|
519
|
+
const CALL_DESC = 'Call one known-address tool explicitly annotated readOnlyHint: true. Use execute_code for unknown-address, multiple, dependent, or reduced read-only work. Unannotated or write-capable tools fail closed to call_destructive_tool. A truncated result carries a get_result action.';
|
|
520
520
|
const CALL_DESTRUCTIVE_DESC = "Call any tool not explicitly annotated readOnlyHint: true. Include a short reason for the human reviewer after checking the schema and consequences. The reason grants no authority and is not sent downstream.";
|
|
521
521
|
const GET_RESULT_DESC = "Page a truncated direct-call result by id and byte offset. A program result is never paged; reduce it inside execute_code. Returns text, offset, nextOffset when more remains, and totalBytes.";
|
|
522
522
|
const AUTHORIZE_DESC = "Use after auth_required. Returns an OAuth or operator-credential handoff, or reports required deployment configuration. force=true restarts OAuth only; this tool never accepts credentials.";
|
|
523
|
-
const SKILLS_DESC = 'List or fetch on-demand guidance. Fetch usage
|
|
523
|
+
const SKILLS_DESC = 'List or fetch on-demand guidance. Fetch usage only when the always-loaded instructions are insufficient or a program needs repair.';
|
|
524
524
|
/**
|
|
525
525
|
* Sentences appended to a meta-tool description only when this connection
|
|
526
526
|
* actually has connector guides. Tool descriptions are always-loaded context,
|