@zackbart/connecta 0.10.5 → 0.11.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/AGENTS.md +8 -6
- package/CHANGELOG.md +150 -0
- package/README.md +5 -4
- package/bin/connecta.mjs +0 -7
- package/dist/activity.d.ts +11 -1
- package/dist/activity.d.ts.map +1 -1
- package/dist/activity.js +44 -3
- package/dist/activity.js.map +1 -1
- package/dist/catalog-service.d.ts +24 -0
- package/dist/catalog-service.d.ts.map +1 -1
- package/dist/catalog-service.js +68 -9
- package/dist/catalog-service.js.map +1 -1
- package/dist/connectors/api.d.ts +2 -2
- package/dist/connectors/remote-mcp.d.ts +1 -1
- package/dist/errors.d.ts +49 -4
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +68 -1
- package/dist/errors.js.map +1 -1
- package/dist/execute.d.ts +73 -3
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +161 -29
- package/dist/execute.js.map +1 -1
- package/dist/index.d.ts +28 -30
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -37
- package/dist/index.js.map +1 -1
- package/dist/invocation.d.ts +9 -2
- package/dist/invocation.d.ts.map +1 -1
- package/dist/invocation.js +61 -31
- package/dist/invocation.js.map +1 -1
- package/dist/meta-tools.d.ts +24 -59
- package/dist/meta-tools.d.ts.map +1 -1
- package/dist/meta-tools.js +107 -359
- package/dist/meta-tools.js.map +1 -1
- package/dist/operator-ui/generated.d.ts +1 -1
- package/dist/operator-ui/generated.d.ts.map +1 -1
- package/dist/operator-ui/generated.js +1 -1
- package/dist/operator-ui/generated.js.map +1 -1
- package/dist/registry.d.ts +12 -10
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +8 -17
- package/dist/registry.js.map +1 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +19 -21
- package/dist/routes/mcp.js.map +1 -1
- package/dist/routes/shared.d.ts +9 -11
- package/dist/routes/shared.d.ts.map +1 -1
- package/dist/routes/shared.js.map +1 -1
- package/dist/server.js +5 -4
- package/dist/server.js.map +1 -1
- package/dist/skills.d.ts +8 -18
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +13 -60
- package/dist/skills.js.map +1 -1
- package/dist/types.d.ts +6 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/code-first-exploration.md +16 -16
- package/documentation/code-mode.md +137 -63
- package/documentation/connectors.md +1 -1
- package/documentation/meta-tools.md +96 -33
- package/documentation/rich-output-design.md +212 -0
- package/ethos.md +17 -19
- package/examples/node/README.md +1 -2
- package/examples/node/src/index.ts +1 -3
- package/examples/worker/README.md +19 -16
- package/examples/worker/src/d1-activity-row.ts +40 -0
- package/examples/worker/src/d1-activity.ts +3 -2
- package/examples/worker/src/index.ts +6 -14
- package/examples/worker/wrangler.jsonc +3 -6
- package/package.json +1 -1
- package/src/activity.ts +69 -3
- package/src/catalog-service.ts +113 -20
- package/src/connectors/api.ts +2 -2
- package/src/connectors/remote-mcp.ts +1 -1
- package/src/errors.ts +104 -3
- package/src/execute.ts +237 -37
- package/src/index.ts +60 -67
- package/src/invocation.ts +61 -19
- package/src/meta-tools.ts +136 -482
- package/src/operator-ui/browser.ts +10 -2
- package/src/operator-ui/generated.ts +1 -1
- package/src/registry.ts +7 -35
- package/src/routes/mcp.ts +19 -21
- package/src/routes/shared.ts +8 -11
- package/src/server.ts +7 -7
- package/src/skills.ts +11 -74
- package/src/types.ts +6 -21
- package/src/version.ts +1 -1
- package/templates/node/README.md +2 -1
- package/templates/node/package.json +1 -1
- package/templates/node/src/index.ts +1 -1
package/src/index.ts
CHANGED
|
@@ -18,7 +18,6 @@ import type { ActivityReadGate, ActivityStore } from "./activity.js";
|
|
|
18
18
|
import type {
|
|
19
19
|
Connector,
|
|
20
20
|
ConnectaBranding,
|
|
21
|
-
ConnectaSurface,
|
|
22
21
|
Executor,
|
|
23
22
|
InboundAuth,
|
|
24
23
|
KVStorage,
|
|
@@ -77,10 +76,11 @@ export interface ConnectaDiscoveryConfig {
|
|
|
77
76
|
staleCatalogSeconds?: number;
|
|
78
77
|
/**
|
|
79
78
|
* Deadline (ms) for each downstream probe/catalog call fanned out by
|
|
80
|
-
* `
|
|
81
|
-
* 30_000. A timed-out connector degrades
|
|
82
|
-
* to tool calls. Catalog walks receive the
|
|
83
|
-
* aborts an in-flight page where supported and
|
|
79
|
+
* `search_tools` and by `connecta.search`/`connecta.describe` inside
|
|
80
|
+
* `execute_code`. Defaults to 30_000. A timed-out connector degrades
|
|
81
|
+
* independently; this does not apply to tool calls. Catalog walks receive the
|
|
82
|
+
* same cancellation signal, which aborts an in-flight page where supported and
|
|
83
|
+
* prevents another from starting.
|
|
84
84
|
*/
|
|
85
85
|
probeTimeoutMs?: number;
|
|
86
86
|
}
|
|
@@ -88,9 +88,9 @@ export interface ConnectaDiscoveryConfig {
|
|
|
88
88
|
/** Deployment-wide call deadlines and inline-result paging thresholds. */
|
|
89
89
|
export interface ConnectaCallsConfig {
|
|
90
90
|
/**
|
|
91
|
-
* Deadline (ms) for `call_tool`/`
|
|
92
|
-
* An explicit per-call value wins. Opt-in: unset by default, so
|
|
93
|
-
* long-running calls gain no surprise deadline.
|
|
91
|
+
* Deadline (ms) for `call_tool`/`call_destructive_tool` calls that pass no
|
|
92
|
+
* `timeoutMs`. An explicit per-call value wins. Opt-in: unset by default, so
|
|
93
|
+
* existing long-running calls gain no surprise deadline.
|
|
94
94
|
*
|
|
95
95
|
* This bounds one attempt, not all retries. `execute_code` host calls are
|
|
96
96
|
* unaffected because they already carry their own bound.
|
|
@@ -102,13 +102,19 @@ export interface ConnectaCallsConfig {
|
|
|
102
102
|
* 50_000. Connectors may override it individually.
|
|
103
103
|
*/
|
|
104
104
|
maxResultBytes?: number;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Budgets for rich output emitted by execute_code programs (`connecta.emit`). */
|
|
108
|
+
export interface ConnectaExecuteConfig {
|
|
105
109
|
/**
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* back to
|
|
110
|
+
* Aggregate serialized bytes `connecta.emit` accepts per run. Default
|
|
111
|
+
* 4_000_000 — a transport bound, not a context bound: emitted image/audio
|
|
112
|
+
* blocks reach the model as media, not base64 text. Invalid values fall
|
|
113
|
+
* back to the default.
|
|
110
114
|
*/
|
|
111
|
-
|
|
115
|
+
maxEmittedBytes?: number;
|
|
116
|
+
/** Content blocks `connecta.emit` accepts per run. Default 32. */
|
|
117
|
+
maxEmittedBlocks?: number;
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
export interface AdmissionPoolConfig {
|
|
@@ -164,6 +170,8 @@ export interface ConnectaConfig {
|
|
|
164
170
|
discovery?: ConnectaDiscoveryConfig;
|
|
165
171
|
/** Deployment-wide call deadlines and result paging threshold. */
|
|
166
172
|
calls?: ConnectaCallsConfig;
|
|
173
|
+
/** Budgets for the `connecta.emit` rich-output channel in execute_code. */
|
|
174
|
+
execute?: ConnectaExecuteConfig;
|
|
167
175
|
/** Bounded MCP and fallback code-mode admission. */
|
|
168
176
|
admission?: ConnectaAdmissionConfig;
|
|
169
177
|
/** Optional browser UI and OAuth result-page labels. */
|
|
@@ -182,22 +190,12 @@ export interface ConnectaConfig {
|
|
|
182
190
|
/** Deployment metadata exposed by /health (for example a Worker version). */
|
|
183
191
|
deploymentInfo?: Record<string, unknown>;
|
|
184
192
|
/**
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* "@zackbart/connecta/quickjs".
|
|
190
|
-
*/
|
|
191
|
-
executor?: Executor;
|
|
192
|
-
/**
|
|
193
|
-
* Override the surface the `executor` implies. The only reason to set it is
|
|
194
|
-
* `"classic"` alongside an executor — ten tools, the shape the eval gate's
|
|
195
|
-
* *incremental* arm measures ("does adding `execute_code` to classic help on
|
|
196
|
-
* its own?"). The gate's control arm is executor-free classic, which needs no
|
|
197
|
-
* override. `"code-first"` is the default wherever an executor exists and
|
|
198
|
-
* throws without one.
|
|
193
|
+
* Required sandbox for `execute_code`. Workers use
|
|
194
|
+
* `new DynamicWorkerExecutor({ loader: env.LOADER })` from
|
|
195
|
+
* `@cloudflare/codemode`; Node uses `quickJsExecutor()` from
|
|
196
|
+
* `@zackbart/connecta/quickjs`.
|
|
199
197
|
*/
|
|
200
|
-
|
|
198
|
+
executor: Executor;
|
|
201
199
|
}
|
|
202
200
|
|
|
203
201
|
export interface Connecta {
|
|
@@ -291,6 +289,20 @@ function assertNoLegacyConfig(config: ConnectaConfig): void {
|
|
|
291
289
|
"issue #179. Credentials now fail at use; see ethos.md.",
|
|
292
290
|
);
|
|
293
291
|
}
|
|
292
|
+
const calls = candidate.calls;
|
|
293
|
+
if (
|
|
294
|
+
typeof calls === "object" &&
|
|
295
|
+
calls !== null &&
|
|
296
|
+
hasOwn(calls, "maxBatchResultBytes")
|
|
297
|
+
) {
|
|
298
|
+
throw new Error(
|
|
299
|
+
"`calls.maxBatchResultBytes` was removed in issue #273 along with " +
|
|
300
|
+
"batch_call. Remove it; a program's batching is bounded by " +
|
|
301
|
+
"execute_code's own limits — connecta.batch's per-run call ceiling " +
|
|
302
|
+
"and the executor result cap — while each call inside it still honours " +
|
|
303
|
+
"calls.maxResultBytes and any per-connector override.",
|
|
304
|
+
);
|
|
305
|
+
}
|
|
294
306
|
const found: Array<readonly [string, string]> = [];
|
|
295
307
|
if (hasOwn(candidate, "activity")) {
|
|
296
308
|
const activity = candidate.activity;
|
|
@@ -429,43 +441,22 @@ function warnInsecureConfig(
|
|
|
429
441
|
}
|
|
430
442
|
}
|
|
431
443
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
* program to fold discovery and batching into, so it serves classic.
|
|
436
|
-
*
|
|
437
|
-
* Two mistakes are structural rather than recoverable, so neither is warned
|
|
438
|
-
* past: a surface name connecta does not implement, which would otherwise
|
|
439
|
-
* resolve to something the operator did not ask for; and `code-first` without
|
|
440
|
-
* an executor, which would advertise six tools and no program surface.
|
|
441
|
-
*/
|
|
442
|
-
function resolveSurface(config: ConnectaConfig): ConnectaSurface {
|
|
443
|
-
const surface = config.surface;
|
|
444
|
-
if (surface === undefined) {
|
|
445
|
-
return config.executor ? "code-first" : "classic";
|
|
446
|
-
}
|
|
447
|
-
if (surface !== "classic" && surface !== "code-first") {
|
|
444
|
+
export function createConnecta(config: ConnectaConfig): Connecta {
|
|
445
|
+
assertNoLegacyConfig(config);
|
|
446
|
+
if (Object.prototype.hasOwnProperty.call(config, "surface")) {
|
|
448
447
|
throw new Error(
|
|
449
|
-
|
|
450
|
-
|
|
448
|
+
"ConnectaConfig.surface was removed in issue #273. Remove it; connecta " +
|
|
449
|
+
"now serves one seven-tool surface.",
|
|
451
450
|
);
|
|
452
451
|
}
|
|
453
|
-
if (
|
|
452
|
+
if (!config.executor) {
|
|
454
453
|
throw new Error(
|
|
455
|
-
|
|
456
|
-
"
|
|
457
|
-
"
|
|
458
|
-
"
|
|
459
|
-
"one (quickJsExecutor() from \"@zackbart/connecta/quickjs\" on Node, " +
|
|
460
|
-
"new DynamicWorkerExecutor({ loader: env.LOADER }) on Workers).",
|
|
454
|
+
"ConnectaConfig.executor is required. Configure quickJsExecutor() from " +
|
|
455
|
+
'"@zackbart/connecta/quickjs" on Node, or ' +
|
|
456
|
+
"new DynamicWorkerExecutor({ loader: env.LOADER }) from " +
|
|
457
|
+
'"@cloudflare/codemode" on Workers.',
|
|
461
458
|
);
|
|
462
459
|
}
|
|
463
|
-
return surface;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
export function createConnecta(config: ConnectaConfig): Connecta {
|
|
467
|
-
assertNoLegacyConfig(config);
|
|
468
|
-
const surface = resolveSurface(config);
|
|
469
460
|
const storage = config.storage ?? memoryStorage();
|
|
470
461
|
const logger = config.logger ?? defaultLogger();
|
|
471
462
|
const credentialConnectors = config.connectors.filter((c) => c.credential);
|
|
@@ -509,9 +500,6 @@ export function createConnecta(config: ConnectaConfig): Connecta {
|
|
|
509
500
|
...(config.calls?.maxResultBytes !== undefined
|
|
510
501
|
? { maxResultBytes: config.calls.maxResultBytes }
|
|
511
502
|
: {}),
|
|
512
|
-
...(config.calls?.maxBatchResultBytes !== undefined
|
|
513
|
-
? { maxBatchResultBytes: config.calls.maxBatchResultBytes }
|
|
514
|
-
: {}),
|
|
515
503
|
});
|
|
516
504
|
const inboundAuth = normalizeAuth(
|
|
517
505
|
accessTokens ? [accessTokens.auth, ...configuredAuth] : configuredAuth,
|
|
@@ -527,10 +515,10 @@ export function createConnecta(config: ConnectaConfig): Connecta {
|
|
|
527
515
|
);
|
|
528
516
|
let codeAdmission: AdmissionController | undefined;
|
|
529
517
|
let executor = config.executor;
|
|
530
|
-
if (
|
|
518
|
+
if (!isAdmittingExecutor(executor)) {
|
|
531
519
|
codeAdmission = configuredCodeAdmission;
|
|
532
520
|
executor = withExecutorAdmission(executor, codeAdmission);
|
|
533
|
-
} else if (
|
|
521
|
+
} else if (config.admission?.code) {
|
|
534
522
|
logger.warn(
|
|
535
523
|
"[connecta] admission.code is ignored because the configured executor " +
|
|
536
524
|
"implements acquire() and owns its admission pool; configure that " +
|
|
@@ -556,8 +544,7 @@ export function createConnecta(config: ConnectaConfig): Connecta {
|
|
|
556
544
|
...(config.activity?.deploymentId !== undefined
|
|
557
545
|
? { activityDeploymentId: config.activity.deploymentId }
|
|
558
546
|
: {}),
|
|
559
|
-
|
|
560
|
-
surface,
|
|
547
|
+
executor,
|
|
561
548
|
requestAdmission,
|
|
562
549
|
...(config.calls?.defaultTimeoutMs !== undefined
|
|
563
550
|
? { defaultToolTimeoutMs: config.calls.defaultTimeoutMs }
|
|
@@ -568,6 +555,12 @@ export function createConnecta(config: ConnectaConfig): Connecta {
|
|
|
568
555
|
...(config.discovery?.concurrency !== undefined
|
|
569
556
|
? { discoveryConcurrency: config.discovery.concurrency }
|
|
570
557
|
: {}),
|
|
558
|
+
...(config.execute?.maxEmittedBytes !== undefined
|
|
559
|
+
? { maxEmittedBytes: config.execute.maxEmittedBytes }
|
|
560
|
+
: {}),
|
|
561
|
+
...(config.execute?.maxEmittedBlocks !== undefined
|
|
562
|
+
? { maxEmittedBlocks: config.execute.maxEmittedBlocks }
|
|
563
|
+
: {}),
|
|
571
564
|
...(credentialVault !== undefined ? { credentialVault } : {}),
|
|
572
565
|
...(accessTokens !== undefined ? { accessTokens } : {}),
|
|
573
566
|
...(config.deploymentInfo !== undefined
|
|
@@ -632,7 +625,6 @@ export type {
|
|
|
632
625
|
ConnectorCallAdmissionRule,
|
|
633
626
|
ConnectorRollingWindowBudget,
|
|
634
627
|
ConnectaBranding,
|
|
635
|
-
ConnectaSurface,
|
|
636
628
|
ConnectorCredentialAccess,
|
|
637
629
|
ConnectorCredentialConfig,
|
|
638
630
|
ConnectorCredentialFieldConfig,
|
|
@@ -667,6 +659,7 @@ export type {
|
|
|
667
659
|
ActivityReadPage,
|
|
668
660
|
ActivitySink,
|
|
669
661
|
ActivityStore,
|
|
662
|
+
AgentFriction,
|
|
670
663
|
ToolCallActivityEvent,
|
|
671
664
|
} from "./activity.js";
|
|
672
665
|
export { InvalidActivityCursorError } from "./activity.js";
|
package/src/invocation.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
recordToolActivity,
|
|
3
3
|
type ActivityCallSource,
|
|
4
4
|
type ActivityRequestContext,
|
|
5
|
+
type AgentFriction,
|
|
5
6
|
} from "./activity.js";
|
|
6
7
|
import { isCallAdmissionError } from "./call-admission.js";
|
|
7
8
|
import {
|
|
@@ -12,12 +13,13 @@ import {
|
|
|
12
13
|
import {
|
|
13
14
|
classifyCallError,
|
|
14
15
|
ConnectorCallError,
|
|
16
|
+
echoedCallArgs,
|
|
15
17
|
framingError,
|
|
16
18
|
type AuthRecoveryMode,
|
|
17
19
|
type CallErrorDetails,
|
|
18
20
|
} from "./errors.js";
|
|
19
21
|
import { unwrapMcpResult } from "./mcp-result.js";
|
|
20
|
-
import type
|
|
22
|
+
import { splitAddress, type RegistryView } from "./registry.js";
|
|
21
23
|
import { isExplicitlyReadOnly } from "./tool-safety.js";
|
|
22
24
|
import type { ToolDef } from "./types.js";
|
|
23
25
|
import { validateToolInput } from "./validate.js";
|
|
@@ -150,6 +152,13 @@ export interface InvocationContext<T> {
|
|
|
150
152
|
value: unknown,
|
|
151
153
|
resolved: ResolvedCatalogTool,
|
|
152
154
|
) => T | Promise<T>;
|
|
155
|
+
/**
|
|
156
|
+
* Optional payload-free friction class derived from a *successful* result —
|
|
157
|
+
* today only an oversized one that had to be paged. It is deliberately not an
|
|
158
|
+
* `errorCode`: the call succeeded, and a consumer that keys its dashboards on
|
|
159
|
+
* "has an error code" must not count a truncation as a failure.
|
|
160
|
+
*/
|
|
161
|
+
activityFriction?: (value: T) => AgentFriction | undefined;
|
|
153
162
|
/**
|
|
154
163
|
* Called after address/catalog/safety admission and before the first provider
|
|
155
164
|
* attempt. Code mode uses it for its host-call budget.
|
|
@@ -252,6 +261,10 @@ export class InvocationService {
|
|
|
252
261
|
let activityTarget:
|
|
253
262
|
| Pick<ResolvedCatalogTool, "connector" | "toolName">
|
|
254
263
|
| undefined;
|
|
264
|
+
// The address as written, used for activity when resolution never reached
|
|
265
|
+
// a connector. Only its two halves are recorded — the same fields activity
|
|
266
|
+
// has always carried — so no new class of payload enters the log.
|
|
267
|
+
const attempted = splitAddress(address);
|
|
255
268
|
const timing = (): InvocationTiming => ({
|
|
256
269
|
catalogMs,
|
|
257
270
|
admissionMs,
|
|
@@ -262,25 +275,56 @@ export class InvocationService {
|
|
|
262
275
|
});
|
|
263
276
|
const record = (
|
|
264
277
|
outcome: "success" | "error" | "timeout" | "cancelled",
|
|
265
|
-
errorCode?: string,
|
|
278
|
+
classification: { errorCode?: string; friction?: AgentFriction } = {},
|
|
266
279
|
) => {
|
|
267
|
-
|
|
280
|
+
const identity = activityTarget
|
|
281
|
+
? {
|
|
282
|
+
connectorId: activityTarget.connector.id,
|
|
283
|
+
toolName: activityTarget.toolName,
|
|
284
|
+
}
|
|
285
|
+
: attempted;
|
|
286
|
+
if (!identity) return;
|
|
268
287
|
recordToolActivity(this.activity, {
|
|
269
|
-
connectorId:
|
|
270
|
-
toolName:
|
|
271
|
-
address: `${
|
|
288
|
+
connectorId: identity.connectorId,
|
|
289
|
+
toolName: identity.toolName,
|
|
290
|
+
address: `${identity.connectorId}.${identity.toolName}`,
|
|
272
291
|
source: context.source,
|
|
273
292
|
outcome,
|
|
274
293
|
durationMs: Date.now() - started,
|
|
275
294
|
attempts,
|
|
276
|
-
...(errorCode
|
|
295
|
+
...(classification.errorCode
|
|
296
|
+
? { errorCode: classification.errorCode }
|
|
297
|
+
: {}),
|
|
298
|
+
...(classification.friction
|
|
299
|
+
? { friction: classification.friction }
|
|
300
|
+
: {}),
|
|
277
301
|
});
|
|
278
302
|
};
|
|
279
303
|
const failed = (error: CallErrorDetails): InvocationOutcome<T> => {
|
|
280
304
|
const diagnostics = timing();
|
|
281
305
|
const target = resolved ?? activityTarget;
|
|
306
|
+
const echoed =
|
|
307
|
+
error.code === "destructive_tool_requires_approval"
|
|
308
|
+
? echoedCallArgs(args)
|
|
309
|
+
: {};
|
|
282
310
|
const details =
|
|
283
|
-
error.code === "
|
|
311
|
+
error.code === "destructive_tool_requires_approval" && target
|
|
312
|
+
? {
|
|
313
|
+
...error,
|
|
314
|
+
nextAction: {
|
|
315
|
+
tool: "call_destructive_tool" as const,
|
|
316
|
+
arguments: {
|
|
317
|
+
address: `${target.connector.id}.${target.toolName}`,
|
|
318
|
+
...echoed,
|
|
319
|
+
},
|
|
320
|
+
purpose:
|
|
321
|
+
"Ask the MCP host to approve this consequential call. " +
|
|
322
|
+
("args" in echoed
|
|
323
|
+
? "Re-send these arguments and add a short reason for the human reviewer."
|
|
324
|
+
: "Re-send the arguments you just sent — they are too large to echo back — and add a short reason for the human reviewer."),
|
|
325
|
+
},
|
|
326
|
+
}
|
|
327
|
+
: error.code === "auth_required" && target
|
|
284
328
|
? {
|
|
285
329
|
...error,
|
|
286
330
|
connector: target.connector.id,
|
|
@@ -305,16 +349,13 @@ export class InvocationService {
|
|
|
305
349
|
...error,
|
|
306
350
|
connector: target.connector.id,
|
|
307
351
|
operation: `${target.connector.id}.${target.toolName}`,
|
|
308
|
-
nextAction:
|
|
309
|
-
|
|
310
|
-
arguments: {
|
|
352
|
+
nextAction: this.catalog.searchRecovery(
|
|
353
|
+
{
|
|
311
354
|
query: target.toolName,
|
|
312
355
|
connector: target.connector.id,
|
|
313
|
-
includeSchemas: "compact" as const,
|
|
314
356
|
},
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
},
|
|
357
|
+
"Inspect the current input shape if the validation findings are not sufficient.",
|
|
358
|
+
),
|
|
318
359
|
retry:
|
|
319
360
|
`Correct the listed arguments and retry ` +
|
|
320
361
|
`${target.connector.id}.${target.toolName}.`,
|
|
@@ -326,7 +367,7 @@ export class InvocationService {
|
|
|
326
367
|
: details.code === "cancelled"
|
|
327
368
|
? "cancelled"
|
|
328
369
|
: "error",
|
|
329
|
-
details.code,
|
|
370
|
+
{ errorCode: details.code },
|
|
330
371
|
);
|
|
331
372
|
return {
|
|
332
373
|
ok: false,
|
|
@@ -354,8 +395,8 @@ export class InvocationService {
|
|
|
354
395
|
// A connector whose catalog cannot be fetched is as unusable as one
|
|
355
396
|
// whose execution fails, so it feeds health accounting the same way the
|
|
356
397
|
// attempt catch below does — otherwise a connector every call fails
|
|
357
|
-
// against (a revoked downstream grant, say) still reads clean
|
|
358
|
-
//
|
|
398
|
+
// against (a revoked downstream grant, say) still reads clean in the
|
|
399
|
+
// deployment's health log.
|
|
359
400
|
//
|
|
360
401
|
// Recorded HERE rather than inside the registry's catalog fetch because
|
|
361
402
|
// a cache hit that avoids a live listTools call records nothing — it is
|
|
@@ -591,7 +632,8 @@ export class InvocationService {
|
|
|
591
632
|
: (result as T);
|
|
592
633
|
resultProcessingMs += Date.now() - processingStarted;
|
|
593
634
|
const diagnostics = timing();
|
|
594
|
-
|
|
635
|
+
const friction = context.activityFriction?.(value);
|
|
636
|
+
record("success", friction ? { friction } : {});
|
|
595
637
|
return {
|
|
596
638
|
ok: true,
|
|
597
639
|
value,
|