@zackbart/connecta 0.24.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/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  All notable changes to this package are documented here.
4
4
 
5
+ ## 0.24.1 — 2026-09-08
6
+
7
+ ### Added
8
+
9
+ - `execute.maxHostCalls` and `execute.hostCallTimeoutMs` configure the
10
+ `execute_code` host-call budget and per-call deadline, previously fixed at
11
+ 20 calls and 15 seconds. The tool description advertises the configured
12
+ values. Analytics providers such as Mixpanel routinely need 15 to 35 seconds
13
+ for funnel and experiment queries.
14
+ - A `warn` log line for every failed connector call, carrying the connector,
15
+ tool, source, error code, attempts, duration, and a bounded downstream
16
+ message. Activity rows remain payload-free; the log is where the reason goes.
17
+
5
18
  ## 0.24.0 — 2026-09-07
6
19
 
7
20
  Deployments now select UI, encrypted credentials, activity history, and inbound
package/dist/execute.d.ts CHANGED
@@ -117,6 +117,8 @@ export declare function createExecuteTool(registry: RegistryView, baseUrl: strin
117
117
  probeTimeoutMs?: number | undefined;
118
118
  maxEmittedBytes?: number | undefined;
119
119
  maxEmittedBlocks?: number | undefined;
120
+ maxHostCalls?: number | undefined;
121
+ hostCallTimeoutMs?: number | undefined;
120
122
  defer?: DeferredWork | undefined;
121
123
  }): ({ code, diagnostics: diagnosticsRequested }: {
122
124
  code: string;
@@ -143,6 +145,10 @@ export declare function registerExecuteTool(server: McpServer, registry: Registr
143
145
  maxEmittedBytes?: number | undefined;
144
146
  /** Block-count budget for connecta.emit. Default 32. */
145
147
  maxEmittedBlocks?: number | undefined;
148
+ /** Host calls one program may make. Default 20. */
149
+ maxHostCalls?: number | undefined;
150
+ /** Deadline per host call in milliseconds. Default 15_000. */
151
+ hostCallTimeoutMs?: number | undefined;
146
152
  defer?: DeferredWork | undefined;
147
153
  }): void;
148
154
  export {};
package/dist/execute.js CHANGED
@@ -141,8 +141,8 @@ export class EmitCollector {
141
141
  this.diagnostics?.recordEmitted(this.blocks.length, this.bytes);
142
142
  }
143
143
  }
144
- /** A configured emit budget must be a finite number >= 1; anything else falls back. */
145
- function resolveEmitBudget(value, fallback) {
144
+ /** A positive whole-number budget, or the default when the value is unusable. */
145
+ function resolveBudget(value, fallback) {
146
146
  return typeof value === "number" && Number.isFinite(value) && value >= 1
147
147
  ? Math.trunc(value)
148
148
  : fallback;
@@ -349,7 +349,7 @@ export function createExecuteTool(registry, baseUrl, executor, logger, activity,
349
349
  let lease;
350
350
  let outcome;
351
351
  const diagnostics = diagnosticsRequested ? new ExecuteDiagnostics() : undefined;
352
- const emitted = new EmitCollector(resolveEmitBudget(config.maxEmittedBytes, EXECUTE_MAX_EMITTED_BYTES), resolveEmitBudget(config.maxEmittedBlocks, EXECUTE_MAX_EMITTED_BLOCKS), diagnostics);
352
+ const emitted = new EmitCollector(resolveBudget(config.maxEmittedBytes, EXECUTE_MAX_EMITTED_BYTES), resolveBudget(config.maxEmittedBlocks, EXECUTE_MAX_EMITTED_BLOCKS), diagnostics);
353
353
  const invocationFailures = [];
354
354
  try {
355
355
  // Admission comes before provider construction: queued calls retain no
@@ -382,6 +382,8 @@ export function createExecuteTool(registry, baseUrl, executor, logger, activity,
382
382
  ...(diagnostics ? { diagnostics } : {}),
383
383
  discoveryConcurrency: config.discoveryConcurrency,
384
384
  probeTimeoutMs: config.probeTimeoutMs,
385
+ maxHostCalls: config.maxHostCalls,
386
+ hostCallTimeoutMs: config.hostCallTimeoutMs,
385
387
  defer: config.defer,
386
388
  });
387
389
  }
@@ -585,7 +587,7 @@ function connectorInventory(connectors) {
585
587
  return `${prefix}${shown.join(", ")}.`;
586
588
  return `${prefix}${shown.join(", ")}${shown.length > 0 ? "; " : ""}+${omitted} more.`;
587
589
  }
588
- const executeDescription = (emitBudgets, connectorGuides, connectors) => `Use the configured services below to answer the task. A known address uses call_tool. Unknown-address and wider read-only work uses one execute_code program for discovery, calls, and reduction. Do not return catalog matches alone. Only readOnlyHint: true tools are available. Limits: ${EXECUTE_MAX_HOST_CALLS} host calls, ${EXECUTE_HOST_CALL_TIMEOUT_MS / 1_000}s/host call.
590
+ const executeDescription = (emitBudgets, hostLimits, connectorGuides, connectors) => `Use the configured services below to answer the task. A known address uses call_tool. Unknown-address and wider read-only work uses one execute_code program for discovery, calls, and reduction. Do not return catalog matches alone. Only readOnlyHint: true tools are available. Limits: ${hostLimits.maxHostCalls} host calls, ${hostLimits.hostCallTimeoutMs / 1_000}s/host call.
589
591
 
590
592
  ${connectorInventory(connectors)}
591
593
 
@@ -603,8 +605,14 @@ export function registerExecuteTool(server, registry, ctx) {
603
605
  // Resolved once so the description and the collector cannot disagree about
604
606
  // the budgets this deployment actually enforces.
605
607
  const emitBudgets = {
606
- maxBytes: resolveEmitBudget(ctx.maxEmittedBytes, EXECUTE_MAX_EMITTED_BYTES),
607
- maxBlocks: resolveEmitBudget(ctx.maxEmittedBlocks, EXECUTE_MAX_EMITTED_BLOCKS),
608
+ maxBytes: resolveBudget(ctx.maxEmittedBytes, EXECUTE_MAX_EMITTED_BYTES),
609
+ maxBlocks: resolveBudget(ctx.maxEmittedBlocks, EXECUTE_MAX_EMITTED_BLOCKS),
610
+ };
611
+ // Same rule for host-call limits: the description advertises exactly what
612
+ // the sandbox enforces, so a raised deadline is visible to the model.
613
+ const hostLimits = {
614
+ maxHostCalls: resolveBudget(ctx.maxHostCalls, EXECUTE_MAX_HOST_CALLS),
615
+ hostCallTimeoutMs: resolveBudget(ctx.hostCallTimeoutMs, EXECUTE_HOST_CALL_TIMEOUT_MS),
608
616
  };
609
617
  const connectors = registry.listConnectors();
610
618
  const handler = createExecuteTool(registry, ctx.baseUrl, ctx.executor, ctx.logger, ctx.activity, {
@@ -612,10 +620,12 @@ export function registerExecuteTool(server, registry, ctx) {
612
620
  probeTimeoutMs: ctx.probeTimeoutMs,
613
621
  maxEmittedBytes: emitBudgets.maxBytes,
614
622
  maxEmittedBlocks: emitBudgets.maxBlocks,
623
+ maxHostCalls: hostLimits.maxHostCalls,
624
+ hostCallTimeoutMs: hostLimits.hostCallTimeoutMs,
615
625
  defer: ctx.defer,
616
626
  });
617
627
  server.registerTool("execute_code", {
618
- description: executeDescription(emitBudgets, hasConnectorGuides(connectors), connectors),
628
+ description: executeDescription(emitBudgets, hostLimits, hasConnectorGuides(connectors), connectors),
619
629
  inputSchema: z.object({
620
630
  code: z
621
631
  .string()
package/dist/index.d.ts CHANGED
@@ -51,7 +51,7 @@ export interface ConnectaCallsConfig {
51
51
  */
52
52
  maxResultBytes?: number;
53
53
  }
54
- /** Budgets for rich output emitted by execute_code programs (`connecta.emit`). */
54
+ /** Budgets for execute_code programs: host calls and rich output (`connecta.emit`). */
55
55
  export interface ConnectaExecuteConfig {
56
56
  /**
57
57
  * Aggregate serialized bytes `connecta.emit` accepts per run. Default
@@ -62,6 +62,18 @@ export interface ConnectaExecuteConfig {
62
62
  maxEmittedBytes?: number;
63
63
  /** Content blocks `connecta.emit` accepts per run. Default 32. */
64
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;
65
77
  }
66
78
  export interface AdmissionPoolConfig {
67
79
  /** Simultaneous work admitted to this pool. */
package/dist/index.js CHANGED
@@ -75,6 +75,8 @@ const CONFIG_SCHEMA = {
75
75
  execute: {
76
76
  maxEmittedBytes: null,
77
77
  maxEmittedBlocks: null,
78
+ maxHostCalls: null,
79
+ hostCallTimeoutMs: null,
78
80
  },
79
81
  admission: {
80
82
  requests: admissionPoolSchema,
@@ -303,6 +305,8 @@ export function createConnecta(config) {
303
305
  discoveryConcurrency: config.discovery?.concurrency,
304
306
  maxEmittedBytes: config.execute?.maxEmittedBytes,
305
307
  maxEmittedBlocks: config.execute?.maxEmittedBlocks,
308
+ maxHostCalls: config.execute?.maxHostCalls,
309
+ hostCallTimeoutMs: config.execute?.hostCallTimeoutMs,
306
310
  credentialVault,
307
311
  ui: config.ui,
308
312
  deploymentInfo: config.deploymentInfo,
@@ -184,7 +184,23 @@ export class InvocationService {
184
184
  };
185
185
  const failed = (error) => {
186
186
  const diagnostics = timing();
187
- const details = enrich(error, resolved ?? activityTarget);
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
+ }
188
204
  record(details.code === "timeout"
189
205
  ? "timeout"
190
206
  : details.code === "cancelled"
@@ -215,6 +215,12 @@ async function serveMcp(request, opts, baseUrl, actor, registry, canManageAuth,
215
215
  ...(opts.maxEmittedBlocks !== undefined
216
216
  ? { maxEmittedBlocks: opts.maxEmittedBlocks }
217
217
  : {}),
218
+ ...(opts.maxHostCalls !== undefined
219
+ ? { maxHostCalls: opts.maxHostCalls }
220
+ : {}),
221
+ ...(opts.hostCallTimeoutMs !== undefined
222
+ ? { hostCallTimeoutMs: opts.hostCallTimeoutMs }
223
+ : {}),
218
224
  });
219
225
  return server;
220
226
  };
@@ -29,6 +29,10 @@ export interface ServerOptions {
29
29
  maxEmittedBytes?: number | undefined;
30
30
  /** Block-count budget for connecta.emit per run. Default 32. */
31
31
  maxEmittedBlocks?: number | undefined;
32
+ /** Host calls one execute_code program may make. Default 20. */
33
+ maxHostCalls?: number | undefined;
34
+ /** Deadline per execute_code host call. Default 15_000. */
35
+ hostCallTimeoutMs?: number | undefined;
32
36
  /** Required sandbox backing the execute_code meta-tool. */
33
37
  executor: Executor;
34
38
  /** Sanitized identity of the configured sandbox, when it has one. */
package/dist/version.d.ts CHANGED
@@ -4,4 +4,4 @@
4
4
  * a bump that forgets this file fails the build rather than shipping a stale
5
5
  * version to `/health` and to downstream MCP handshakes.
6
6
  */
7
- export declare const CONNECTA_VERSION = "0.24.0";
7
+ export declare const CONNECTA_VERSION = "0.24.1";
package/dist/version.js CHANGED
@@ -4,4 +4,4 @@
4
4
  * a bump that forgets this file fails the build rather than shipping a stale
5
5
  * version to `/health` and to downstream MCP handshakes.
6
6
  */
7
- export const CONNECTA_VERSION = "0.24.0";
7
+ export const CONNECTA_VERSION = "0.24.1";
@@ -302,7 +302,7 @@ Program-authored errors stay untyped, and code must never parse error prose.
302
302
  | `input_required_unsupported` | a downstream asked for mid-call input | false |
303
303
  | `rate_limited` | the downstream reported a rate limit | true |
304
304
  | `unavailable` | the downstream is down or unreachable | true |
305
- | `timeout` | the per-call 15-second deadline expired | true |
305
+ | `timeout` | the per-call deadline (`execute.hostCallTimeoutMs`, default 15 s) expired | true |
306
306
  | `cancelled` | the run ended while this call was in flight (`E5`) | false |
307
307
  | `connector_call_failed` | anything else the connector threw | per message |
308
308
  | `catalog_lookup_failed` | the connector's catalog could not be loaded | per cause |
@@ -492,7 +492,7 @@ because connecta enforces them above the sandbox:
492
492
  | Bound | Value |
493
493
  | --- | --- |
494
494
  | Host calls per execution | 20 |
495
- | Deadline per host call | 15 s |
495
+ | Deadline per host call | 15 s, `execute.hostCallTimeoutMs` |
496
496
  | Discovery page | ≤ 100 tools, ≤ 256,000 serialized bytes |
497
497
  | `describe` addresses | ≤ 100 |
498
498
  | `describe` nearby suggestions | ≤ 3 canonical addresses per failed entry |
@@ -101,6 +101,8 @@ optional.
101
101
  | `calls.maxResultBytes?` | 50_000 | inline result cap before truncation and `get_result` paging; a connector may override it. Invalid values warn and fall back |
102
102
  | `execute.maxEmittedBytes?` | 4_000_000 | aggregate `connecta.emit` bytes per run — a transport bound, not a context bound |
103
103
  | `execute.maxEmittedBlocks?` | 32 | content blocks `connecta.emit` accepts per run |
104
+ | `execute.maxHostCalls?` | 20 | connector calls one `execute_code` program may make |
105
+ | `execute.hostCallTimeoutMs?` | 15_000 | deadline per `execute_code` host call; raise it for providers whose legitimate calls run longer. `call_tool`'s `timeoutMs` is separate |
104
106
  | `admission.requests?` | 16 active / 32 queued / 5 s / 1 s | global FIFO `/mcp` capacity, taken before auth ([request admission](./request-admission.md)) |
105
107
  | `admission.code?` | 2 active / 8 queued / 5 s / 1 s | fallback pool for an executor that owns no `acquire()`; ignored with a warning when it does |
106
108
 
@@ -117,7 +117,7 @@ exist so far:
117
117
  | --- | --- | --- |
118
118
  | **pre-template** | before 0.10.2 | no `connecta init` existed; hand-written, or copied from the retired `examples/node` |
119
119
  | **A** | 0.10.2 – 0.15.1 | `.env.example`, `.gitignore`, `AGENTS.md`, `CLAUDE.md`, `README.md`, `package.json`, `src/index.ts`, `tsconfig.json` |
120
- | **B** | 0.16.0 – 0.24.0 | adds `.dockerignore`, `Dockerfile`, `docker-compose.yml`, and `src/file-activity.ts`; `src/index.ts` grows the four commented operator blocks; `.env.example` ships `CONNECTA_TOKEN=` empty |
120
+ | **B** | 0.16.0 – 0.24.1 | adds `.dockerignore`, `Dockerfile`, `docker-compose.yml`, and `src/file-activity.ts`; `src/index.ts` grows the four commented operator blocks; `.env.example` ships `CONNECTA_TOKEN=` empty |
121
121
 
122
122
  Generation A is a decade in template years and identifying it precisely does
123
123
  not matter, because you are about to reconstruct it exactly rather than guess
@@ -190,7 +190,7 @@ Generate the *current* template beside the base you already made, into the same
190
190
  `$SCRATCH`:
191
191
 
192
192
  ```sh
193
- (cd "$SCRATCH" && npx @zackbart/connecta@0.24.0 init current)
193
+ (cd "$SCRATCH" && npx @zackbart/connecta@0.24.1 init current)
194
194
  ```
195
195
 
196
196
  You now have a three-way merge with a real base: `$SCRATCH/base` is what this
@@ -246,7 +246,7 @@ A deployment older than 0.10.2 has no base to diff against. Do not try to
246
246
  manufacture one. Instead:
247
247
 
248
248
  1. `SCRATCH=$(mktemp -d)`, then
249
- `(cd "$SCRATCH" && npx @zackbart/connecta@0.24.0 init current)` — there is no
249
+ `(cd "$SCRATCH" && npx @zackbart/connecta@0.24.1 init current)` — there is no
250
250
  `base` leg here, only the current template to read from.
251
251
  2. Copy `$SCRATCH/current` into the deployment file by file, **skipping
252
252
  `src/index.ts`**.
@@ -267,11 +267,15 @@ first, so cross them bottom-up: start at the oldest one still above this
267
267
  deployment's pin and work back up the page, because each boundary assumes the
268
268
  older ones are already done.
269
269
 
270
- ### 0.23.0 → 0.24.0
270
+ ### 0.23.0 → 0.24.1
271
271
 
272
272
  Use the [optional-module migration](./optional-modules-upgrade.md) to select
273
273
  modules, grant auth-management permissions, and migrate issued-token clients.
274
- Preserve storage, encryption keys, and identity namespaces.
274
+ Preserve storage, encryption keys, and identity namespaces. 0.24.1 adds two
275
+ optional settings, `execute.maxHostCalls` and `execute.hostCallTimeoutMs`, for
276
+ deployments whose providers legitimately run past the 20-call and 15-second
277
+ `execute_code` defaults, and one bounded `warn` log line per failed connector
278
+ call; neither needs migration.
275
279
 
276
280
  ### 0.22.3 → 0.23.0
277
281
 
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@zackbart/connecta",
3
- "version": "0.24.0",
3
+ "version": "0.24.1",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
- "description": "One MCP to rule them all \u2014 a single MCP endpoint aggregating many downstream connectors behind a code-first surface of seven meta-tools.",
6
+ "description": "One MCP to rule them all a single MCP endpoint aggregating many downstream connectors behind a code-first surface of seven meta-tools.",
7
7
  "license": "MIT",
8
8
  "engines": {
9
9
  "node": ">=22.0.0"
@@ -15,7 +15,7 @@
15
15
  "typecheck": "tsc --noEmit"
16
16
  },
17
17
  "dependencies": {
18
- "@zackbart/connecta": "0.24.0",
18
+ "@zackbart/connecta": "0.24.1",
19
19
  "quickjs-emscripten": "0.32.0"
20
20
  },
21
21
  "devDependencies": {