@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.
Files changed (45) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +3 -1
  3. package/bin/connecta.mjs +23 -6
  4. package/dist/auth/bearer.d.ts +2 -2
  5. package/dist/auth/bearer.js +2 -2
  6. package/dist/auth/clerk.js +1 -0
  7. package/dist/auth/cloudflare-access.d.ts +8 -0
  8. package/dist/auth/cloudflare-access.js +66 -0
  9. package/dist/execute.js +12 -6
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.js +2 -2
  12. package/dist/meta-tools.js +3 -3
  13. package/dist/operator-ui/generated.js +1 -1
  14. package/dist/operator-ui/model.d.ts +3 -3
  15. package/dist/operator-ui/view.d.ts +1 -1
  16. package/dist/operator-ui/view.js +6 -3
  17. package/dist/routes/access-tokens.d.ts +1 -1
  18. package/dist/routes/access-tokens.js +2 -2
  19. package/dist/routes/activity.js +2 -2
  20. package/dist/routes/credentials.js +1 -1
  21. package/dist/routes/mcp.js +1 -1
  22. package/dist/routes/oauth.js +1 -1
  23. package/dist/routes/shared.d.ts +4 -4
  24. package/dist/routes/shared.js +10 -10
  25. package/dist/routes/ui.js +12 -9
  26. package/dist/skills.d.ts +1 -1
  27. package/dist/skills.js +7 -4
  28. package/dist/types.d.ts +37 -22
  29. package/dist/ui.d.ts +1 -1
  30. package/dist/ui.js +3 -3
  31. package/dist/version.d.ts +1 -1
  32. package/dist/version.js +1 -1
  33. package/documentation/architecture.md +7 -4
  34. package/documentation/auth.md +71 -7
  35. package/documentation/code-mode.md +4 -4
  36. package/documentation/meta-tools.md +22 -20
  37. package/documentation/operations.md +23 -8
  38. package/documentation/operator-ui.md +21 -5
  39. package/documentation/upgrading.md +76 -4
  40. package/ethos.md +2 -3
  41. package/examples/worker/README.md +52 -32
  42. package/examples/worker/src/index.ts +32 -38
  43. package/examples/worker/wrangler.jsonc +12 -4
  44. package/package.json +5 -1
  45. 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 a bearer token over remote plaintext HTTP. Use HTTPS.",
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
- if (!token) {
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 CONNECTA_TOKEN so doctor can inspect the MCP surface.",
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
- Authorization: `Bearer ${token}`,
226
+ ...authHeaders,
210
227
  "Content-Type": "application/json",
211
228
  Accept: "application/json, text/event-stream",
212
229
  },
@@ -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 BEFORE the Clerk gate in the server; a mismatch
9
- * falls through so a co-configured Clerk provider can still admit the request.
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;
@@ -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 BEFORE the Clerk gate in the server; a mismatch
20
- * falls through so a co-configured Clerk provider can still admit the request.
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);
@@ -366,6 +366,7 @@ export function clerkAuth(opts) {
366
366
  };
367
367
  return {
368
368
  kind: "clerk",
369
+ interactiveOperator: true,
369
370
  activityActorNamespace: frontendApiUrl,
370
371
  activityActorLabel: resolveActivityLabel,
371
372
  uiAuth: {
@@ -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
- return shortcut === connector.id
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. Exactly one unknown-address read uses top-level search_tools then call_tool. execute_code is the primary surface for everything wider: make exactly one execute_code call that searches, selects, calls, and reduces. A discovery-only program wastes its round trip: finish here, 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.
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), connecta.describe(args), and connecta.batch(calls) for discovery and independent read-only calls.
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
- Programs have no portable ambient capabilities. Return JSON and reduce large results before they truncate. Fetch skills({ name: "usage" }) once for selection rules, exact result shapes, repair, examples, guide handling${connectorGuides ? ", connector-guide rules" : ""}, and runtime differences.`;
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 Clerk operator; token secrets are returned once.
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.uiAuth?.kind === "clerk")) {
266
- throw new Error("accessTokens requires a Clerk auth provider: only an eligible Clerk " +
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 = {
@@ -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 one unknown-address read before call_tool, or for approval-required work before call_destructive_tool. 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. For multiple, dependent, or reduced read-only calls, use one execute_code program instead. Empty query browses.`;
519
- const CALL_DESC = 'Call one tool explicitly annotated readOnlyHint: true. Use execute_code for multiple, dependent, or reduced read-only calls. Unannotated or write-capable tools fail closed to call_destructive_tool. A truncated result carries a get_result action.';
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 once per task for program syntax, selection, repair, examples, and runtime details.';
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,