@zackbart/connecta 0.15.1 → 0.16.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.
Files changed (335) hide show
  1. package/AGENTS.md +40 -20
  2. package/CHANGELOG.md +653 -0
  3. package/README.md +25 -5
  4. package/bin/connecta.mjs +44 -3
  5. package/dist/access-tokens.d.ts +0 -1
  6. package/dist/access-tokens.js +0 -1
  7. package/dist/activity.d.ts +50 -2
  8. package/dist/activity.js +34 -1
  9. package/dist/apps-shell.d.ts +0 -1
  10. package/dist/apps-shell.js +0 -1
  11. package/dist/auth/bearer.d.ts +0 -1
  12. package/dist/auth/bearer.js +0 -1
  13. package/dist/auth/clerk.d.ts +0 -1
  14. package/dist/auth/clerk.js +45 -9
  15. package/dist/auth/downstream-oauth.d.ts +0 -1
  16. package/dist/auth/downstream-oauth.js +0 -1
  17. package/dist/call-admission.d.ts +0 -1
  18. package/dist/call-admission.js +0 -1
  19. package/dist/catalog-drift.d.ts +99 -0
  20. package/dist/catalog-drift.js +251 -0
  21. package/dist/catalog-fingerprint.d.ts +0 -1
  22. package/dist/catalog-fingerprint.js +0 -1
  23. package/dist/catalog-limits.d.ts +0 -1
  24. package/dist/catalog-limits.js +0 -1
  25. package/dist/catalog-service.d.ts +0 -1
  26. package/dist/catalog-service.js +41 -5
  27. package/dist/catalog.d.ts +11 -1
  28. package/dist/catalog.js +20 -1
  29. package/dist/concurrency.d.ts +0 -1
  30. package/dist/concurrency.js +0 -1
  31. package/dist/connector-scope.d.ts +0 -1
  32. package/dist/connector-scope.js +0 -1
  33. package/dist/connectors/api.d.ts +29 -21
  34. package/dist/connectors/api.js +45 -19
  35. package/dist/connectors/guarded-fetch.d.ts +106 -0
  36. package/dist/connectors/guarded-fetch.js +289 -0
  37. package/dist/connectors/remote-mcp.d.ts +0 -1
  38. package/dist/connectors/remote-mcp.js +0 -1
  39. package/dist/credentials.d.ts +0 -1
  40. package/dist/credentials.js +0 -1
  41. package/dist/errors.d.ts +30 -3
  42. package/dist/errors.js +1 -1
  43. package/dist/execute.d.ts +0 -1
  44. package/dist/execute.js +0 -1
  45. package/dist/executor-admission.d.ts +11 -1
  46. package/dist/executor-admission.js +28 -1
  47. package/dist/executor-result.d.ts +0 -1
  48. package/dist/executor-result.js +0 -1
  49. package/dist/executors/quickjs-child.d.ts +0 -1
  50. package/dist/executors/quickjs-child.js +0 -1
  51. package/dist/executors/quickjs-protocol.d.ts +0 -1
  52. package/dist/executors/quickjs-protocol.js +0 -1
  53. package/dist/executors/quickjs-runtime.d.ts +0 -1
  54. package/dist/executors/quickjs-runtime.js +0 -1
  55. package/dist/executors/quickjs.d.ts +0 -1
  56. package/dist/executors/quickjs.js +2 -1
  57. package/dist/favicon.d.ts +0 -1
  58. package/dist/favicon.js +0 -1
  59. package/dist/index.d.ts +2 -3
  60. package/dist/index.js +24 -7
  61. package/dist/invocation.d.ts +0 -1
  62. package/dist/invocation.js +0 -1
  63. package/dist/json-schema.d.ts +0 -1
  64. package/dist/json-schema.js +0 -1
  65. package/dist/mcp-result.d.ts +0 -1
  66. package/dist/mcp-result.js +0 -1
  67. package/dist/meta-tools.d.ts +0 -1
  68. package/dist/meta-tools.js +0 -1
  69. package/dist/node.d.ts +0 -1
  70. package/dist/node.js +0 -1
  71. package/dist/operator-ui/generated.d.ts +2 -3
  72. package/dist/operator-ui/generated.js +3 -4
  73. package/dist/operator-ui/model.d.ts +10 -1
  74. package/dist/operator-ui/model.js +0 -1
  75. package/dist/operator-ui/view.d.ts +167 -0
  76. package/dist/operator-ui/view.js +270 -0
  77. package/dist/providers/cloudflare.d.ts +0 -1
  78. package/dist/providers/cloudflare.js +261 -299
  79. package/dist/providers/linear.d.ts +26 -5
  80. package/dist/providers/linear.js +32 -61
  81. package/dist/providers/mixpanel.d.ts +35 -4
  82. package/dist/providers/mixpanel.js +53 -79
  83. package/dist/providers/notion.d.ts +0 -1
  84. package/dist/providers/notion.js +87 -42
  85. package/dist/providers/stripe.d.ts +13 -1
  86. package/dist/providers/stripe.js +31 -60
  87. package/dist/registry.d.ts +34 -2
  88. package/dist/registry.js +85 -5
  89. package/dist/retired-toolkits.d.ts +0 -1
  90. package/dist/retired-toolkits.js +0 -1
  91. package/dist/routes/access-tokens.d.ts +0 -1
  92. package/dist/routes/access-tokens.js +0 -1
  93. package/dist/routes/activity.d.ts +0 -1
  94. package/dist/routes/activity.js +0 -1
  95. package/dist/routes/credentials.d.ts +0 -1
  96. package/dist/routes/credentials.js +0 -1
  97. package/dist/routes/mcp.d.ts +0 -1
  98. package/dist/routes/mcp.js +0 -1
  99. package/dist/routes/oauth.d.ts +0 -1
  100. package/dist/routes/oauth.js +0 -1
  101. package/dist/routes/shared.d.ts +2 -1
  102. package/dist/routes/shared.js +0 -1
  103. package/dist/routes/ui.d.ts +0 -1
  104. package/dist/routes/ui.js +0 -1
  105. package/dist/server.d.ts +0 -1
  106. package/dist/server.js +11 -1
  107. package/dist/skills.d.ts +0 -1
  108. package/dist/skills.js +0 -1
  109. package/dist/storage/file.d.ts +0 -1
  110. package/dist/storage/file.js +0 -1
  111. package/dist/storage/memory.d.ts +0 -1
  112. package/dist/storage/memory.js +0 -1
  113. package/dist/timeout.d.ts +0 -1
  114. package/dist/timeout.js +0 -1
  115. package/dist/tool-safety.d.ts +0 -1
  116. package/dist/tool-safety.js +0 -1
  117. package/dist/types.d.ts +45 -1
  118. package/dist/types.js +0 -1
  119. package/dist/ui.d.ts +0 -1
  120. package/dist/ui.js +13 -137
  121. package/dist/validate.d.ts +13 -15
  122. package/dist/validate.js +24 -11
  123. package/dist/version.d.ts +1 -2
  124. package/dist/version.js +1 -2
  125. package/documentation/architecture.md +186 -5
  126. package/documentation/auth.md +11 -0
  127. package/documentation/call-admission.md +142 -6
  128. package/documentation/cloudflare.md +92 -10
  129. package/documentation/code-first-exploration.md +2 -2
  130. package/documentation/code-mode.md +14 -14
  131. package/documentation/connector-guides.md +172 -5
  132. package/documentation/connectors.md +89 -0
  133. package/documentation/linear.md +20 -2
  134. package/documentation/mcp-ui-design.md +2 -2
  135. package/documentation/meta-tools.md +7 -1
  136. package/documentation/mixpanel.md +42 -9
  137. package/documentation/notion.md +23 -2
  138. package/documentation/operations.md +325 -5
  139. package/documentation/operator-ui.md +120 -5
  140. package/documentation/provider-audit.md +160 -0
  141. package/documentation/provider-conventions.md +667 -0
  142. package/documentation/request-admission.md +167 -5
  143. package/documentation/rich-output-design.md +1 -2
  144. package/documentation/stripe.md +15 -0
  145. package/documentation/upgrading.md +454 -0
  146. package/ethos.md +14 -9
  147. package/examples/worker/README.md +102 -12
  148. package/examples/worker/src/index.ts +46 -1
  149. package/examples/worker/wrangler.jsonc +14 -1
  150. package/package.json +10 -6
  151. package/templates/node/.dockerignore +10 -0
  152. package/templates/node/.env.example +40 -3
  153. package/templates/node/AGENTS.md +16 -1
  154. package/templates/node/Dockerfile +49 -0
  155. package/templates/node/README.md +117 -2
  156. package/templates/node/docker-compose.yml +39 -0
  157. package/templates/node/package.json +1 -1
  158. package/templates/node/src/file-activity.ts +182 -0
  159. package/templates/node/src/index.ts +80 -4
  160. package/assets/connecta-clay-hero.png +0 -0
  161. package/dist/access-tokens.d.ts.map +0 -1
  162. package/dist/access-tokens.js.map +0 -1
  163. package/dist/activity.d.ts.map +0 -1
  164. package/dist/activity.js.map +0 -1
  165. package/dist/apps-shell.d.ts.map +0 -1
  166. package/dist/apps-shell.js.map +0 -1
  167. package/dist/auth/bearer.d.ts.map +0 -1
  168. package/dist/auth/bearer.js.map +0 -1
  169. package/dist/auth/clerk.d.ts.map +0 -1
  170. package/dist/auth/clerk.js.map +0 -1
  171. package/dist/auth/downstream-oauth.d.ts.map +0 -1
  172. package/dist/auth/downstream-oauth.js.map +0 -1
  173. package/dist/call-admission.d.ts.map +0 -1
  174. package/dist/call-admission.js.map +0 -1
  175. package/dist/catalog-fingerprint.d.ts.map +0 -1
  176. package/dist/catalog-fingerprint.js.map +0 -1
  177. package/dist/catalog-limits.d.ts.map +0 -1
  178. package/dist/catalog-limits.js.map +0 -1
  179. package/dist/catalog-service.d.ts.map +0 -1
  180. package/dist/catalog-service.js.map +0 -1
  181. package/dist/catalog.d.ts.map +0 -1
  182. package/dist/catalog.js.map +0 -1
  183. package/dist/concurrency.d.ts.map +0 -1
  184. package/dist/concurrency.js.map +0 -1
  185. package/dist/connector-scope.d.ts.map +0 -1
  186. package/dist/connector-scope.js.map +0 -1
  187. package/dist/connectors/api.d.ts.map +0 -1
  188. package/dist/connectors/api.js.map +0 -1
  189. package/dist/connectors/remote-mcp.d.ts.map +0 -1
  190. package/dist/connectors/remote-mcp.js.map +0 -1
  191. package/dist/credentials.d.ts.map +0 -1
  192. package/dist/credentials.js.map +0 -1
  193. package/dist/errors.d.ts.map +0 -1
  194. package/dist/errors.js.map +0 -1
  195. package/dist/execute.d.ts.map +0 -1
  196. package/dist/execute.js.map +0 -1
  197. package/dist/executor-admission.d.ts.map +0 -1
  198. package/dist/executor-admission.js.map +0 -1
  199. package/dist/executor-result.d.ts.map +0 -1
  200. package/dist/executor-result.js.map +0 -1
  201. package/dist/executors/quickjs-child.d.ts.map +0 -1
  202. package/dist/executors/quickjs-child.js.map +0 -1
  203. package/dist/executors/quickjs-protocol.d.ts.map +0 -1
  204. package/dist/executors/quickjs-protocol.js.map +0 -1
  205. package/dist/executors/quickjs-runtime.d.ts.map +0 -1
  206. package/dist/executors/quickjs-runtime.js.map +0 -1
  207. package/dist/executors/quickjs.d.ts.map +0 -1
  208. package/dist/executors/quickjs.js.map +0 -1
  209. package/dist/favicon.d.ts.map +0 -1
  210. package/dist/favicon.js.map +0 -1
  211. package/dist/index.d.ts.map +0 -1
  212. package/dist/index.js.map +0 -1
  213. package/dist/invocation.d.ts.map +0 -1
  214. package/dist/invocation.js.map +0 -1
  215. package/dist/json-schema.d.ts.map +0 -1
  216. package/dist/json-schema.js.map +0 -1
  217. package/dist/mcp-result.d.ts.map +0 -1
  218. package/dist/mcp-result.js.map +0 -1
  219. package/dist/meta-tools.d.ts.map +0 -1
  220. package/dist/meta-tools.js.map +0 -1
  221. package/dist/node.d.ts.map +0 -1
  222. package/dist/node.js.map +0 -1
  223. package/dist/operator-ui/generated.d.ts.map +0 -1
  224. package/dist/operator-ui/generated.js.map +0 -1
  225. package/dist/operator-ui/model.d.ts.map +0 -1
  226. package/dist/operator-ui/model.js.map +0 -1
  227. package/dist/providers/cloudflare.d.ts.map +0 -1
  228. package/dist/providers/cloudflare.js.map +0 -1
  229. package/dist/providers/linear.d.ts.map +0 -1
  230. package/dist/providers/linear.js.map +0 -1
  231. package/dist/providers/mixpanel.d.ts.map +0 -1
  232. package/dist/providers/mixpanel.js.map +0 -1
  233. package/dist/providers/notion.d.ts.map +0 -1
  234. package/dist/providers/notion.js.map +0 -1
  235. package/dist/providers/stripe.d.ts.map +0 -1
  236. package/dist/providers/stripe.js.map +0 -1
  237. package/dist/registry.d.ts.map +0 -1
  238. package/dist/registry.js.map +0 -1
  239. package/dist/retired-toolkits.d.ts.map +0 -1
  240. package/dist/retired-toolkits.js.map +0 -1
  241. package/dist/routes/access-tokens.d.ts.map +0 -1
  242. package/dist/routes/access-tokens.js.map +0 -1
  243. package/dist/routes/activity.d.ts.map +0 -1
  244. package/dist/routes/activity.js.map +0 -1
  245. package/dist/routes/credentials.d.ts.map +0 -1
  246. package/dist/routes/credentials.js.map +0 -1
  247. package/dist/routes/mcp.d.ts.map +0 -1
  248. package/dist/routes/mcp.js.map +0 -1
  249. package/dist/routes/oauth.d.ts.map +0 -1
  250. package/dist/routes/oauth.js.map +0 -1
  251. package/dist/routes/shared.d.ts.map +0 -1
  252. package/dist/routes/shared.js.map +0 -1
  253. package/dist/routes/ui.d.ts.map +0 -1
  254. package/dist/routes/ui.js.map +0 -1
  255. package/dist/server.d.ts.map +0 -1
  256. package/dist/server.js.map +0 -1
  257. package/dist/skills.d.ts.map +0 -1
  258. package/dist/skills.js.map +0 -1
  259. package/dist/storage/file.d.ts.map +0 -1
  260. package/dist/storage/file.js.map +0 -1
  261. package/dist/storage/memory.d.ts.map +0 -1
  262. package/dist/storage/memory.js.map +0 -1
  263. package/dist/timeout.d.ts.map +0 -1
  264. package/dist/timeout.js.map +0 -1
  265. package/dist/tool-safety.d.ts.map +0 -1
  266. package/dist/tool-safety.js.map +0 -1
  267. package/dist/types.d.ts.map +0 -1
  268. package/dist/types.js.map +0 -1
  269. package/dist/ui.d.ts.map +0 -1
  270. package/dist/ui.js.map +0 -1
  271. package/dist/validate.d.ts.map +0 -1
  272. package/dist/validate.js.map +0 -1
  273. package/dist/version.d.ts.map +0 -1
  274. package/dist/version.js.map +0 -1
  275. package/examples/node/README.md +0 -52
  276. package/examples/node/src/index.ts +0 -71
  277. package/src/access-tokens.ts +0 -289
  278. package/src/activity.ts +0 -234
  279. package/src/apps-shell.ts +0 -370
  280. package/src/auth/bearer.ts +0 -61
  281. package/src/auth/clerk.ts +0 -553
  282. package/src/auth/downstream-oauth.ts +0 -575
  283. package/src/call-admission.ts +0 -521
  284. package/src/catalog-fingerprint.ts +0 -52
  285. package/src/catalog-limits.ts +0 -11
  286. package/src/catalog-service.ts +0 -1153
  287. package/src/catalog.ts +0 -790
  288. package/src/concurrency.ts +0 -39
  289. package/src/connector-scope.ts +0 -66
  290. package/src/connectors/api.ts +0 -159
  291. package/src/connectors/remote-mcp.ts +0 -1090
  292. package/src/credentials.ts +0 -428
  293. package/src/errors.ts +0 -364
  294. package/src/execute.ts +0 -1406
  295. package/src/executor-admission.ts +0 -328
  296. package/src/executor-result.ts +0 -107
  297. package/src/executors/quickjs-child.ts +0 -172
  298. package/src/executors/quickjs-protocol.ts +0 -99
  299. package/src/executors/quickjs-runtime.ts +0 -470
  300. package/src/executors/quickjs.ts +0 -776
  301. package/src/favicon.ts +0 -53
  302. package/src/index.ts +0 -666
  303. package/src/invocation.ts +0 -655
  304. package/src/json-schema.ts +0 -11
  305. package/src/mcp-result.ts +0 -43
  306. package/src/meta-tools.ts +0 -1607
  307. package/src/node.ts +0 -206
  308. package/src/operator-ui/browser.css +0 -423
  309. package/src/operator-ui/browser.ts +0 -1281
  310. package/src/operator-ui/generated.ts +0 -4
  311. package/src/operator-ui/model.ts +0 -111
  312. package/src/providers/cloudflare.ts +0 -3999
  313. package/src/providers/linear.ts +0 -302
  314. package/src/providers/mixpanel.ts +0 -229
  315. package/src/providers/notion.ts +0 -1879
  316. package/src/providers/stripe.ts +0 -307
  317. package/src/registry.ts +0 -1085
  318. package/src/retired-toolkits.ts +0 -14
  319. package/src/routes/access-tokens.ts +0 -115
  320. package/src/routes/activity.ts +0 -215
  321. package/src/routes/credentials.ts +0 -254
  322. package/src/routes/mcp.ts +0 -429
  323. package/src/routes/oauth.ts +0 -322
  324. package/src/routes/shared.ts +0 -247
  325. package/src/routes/ui.ts +0 -152
  326. package/src/server.ts +0 -195
  327. package/src/skills.ts +0 -271
  328. package/src/storage/file.ts +0 -123
  329. package/src/storage/memory.ts +0 -44
  330. package/src/timeout.ts +0 -84
  331. package/src/tool-safety.ts +0 -15
  332. package/src/types.ts +0 -523
  333. package/src/ui.ts +0 -744
  334. package/src/validate.ts +0 -387
  335. package/src/version.ts +0 -7
package/src/errors.ts DELETED
@@ -1,364 +0,0 @@
1
- // Typed failure contract for connector tool calls. Web-API only — no node:
2
- // imports here.
3
-
4
- /** Machine-readable classification of a failed connector tool call. */
5
- export type ConnectorCallErrorCode =
6
- | "timeout"
7
- | "auth_required"
8
- | "rate_limited"
9
- | "unavailable"
10
- | "invalid_args"
11
- | "input_required_unsupported"
12
- | "connector_call_failed";
13
-
14
- /** One bounded, payload-free explanation of an input-schema mismatch. */
15
- export interface ArgumentValidationIssue {
16
- /** JSON Pointer into the submitted arguments; "/" means the root value. */
17
- path: string;
18
- /** JSON Schema keyword that rejected the argument. */
19
- code: string;
20
- /** Expected shape only — never the submitted value. */
21
- expected: string;
22
- }
23
-
24
- export interface ArgumentValidationDetails {
25
- issues: ArgumentValidationIssue[];
26
- /** More findings existed but were omitted from the bounded response. */
27
- truncated?: true;
28
- }
29
-
30
- export const MAX_ARGUMENT_VALIDATION_ISSUES = 3;
31
- const MAX_ARGUMENT_ISSUE_PATH_CHARS = 256;
32
- const MAX_ARGUMENT_ISSUE_CODE_CHARS = 64;
33
- const MAX_ARGUMENT_ISSUE_EXPECTED_CHARS = 128;
34
-
35
- function boundedIssueText(
36
- value: string,
37
- maxChars: number,
38
- ): { value: string; truncated: boolean } {
39
- if (value.length <= maxChars) return { value, truncated: false };
40
- return {
41
- value: `${value.slice(0, Math.max(0, maxChars - 1))}…`,
42
- truncated: true,
43
- };
44
- }
45
-
46
- /**
47
- * How many bytes of the caller's own arguments an error envelope will echo
48
- * back to it. Small on purpose: an error result is not size-guarded the way a
49
- * *result* is, so an unbounded echo turns a 50 KB argument object into a 100 KB
50
- * refusal against a deployment that capped results at 1 KB — twice over, since
51
- * the payload lands in both the text content and `structuredContent`. The agent
52
- * already holds what it sent; the echo is a convenience, never the record.
53
- */
54
- const MAX_ECHOED_ARGS_BYTES = 512;
55
-
56
- /**
57
- * The same budget spent on caller-authored *text* — the address it mistyped,
58
- * the discovery query derived from it — rather than on its arguments.
59
- *
60
- * Text is clamped where {@link echoedCallArgs} drops: an address is the thing
61
- * the refusal exists to correct, so a refusal that named nothing would be
62
- * useless, while a clipped one still carries the prefix that identifies the
63
- * mistake. The marker says it was clipped, so nothing reads a clamped address
64
- * as the address that was sent. Arguments get the opposite rule because they
65
- * end at a human approving one specific call.
66
- *
67
- * The number is not cosmetic. An error result is not size-guarded the way a
68
- * result is, and every echoed byte lands twice (text content *and*
69
- * `structuredContent`), so an unbounded address turned a 50 KB typo into a
70
- * 200 KB refusal against a deployment that capped results at 1 KB.
71
- */
72
- const MAX_ECHOED_TEXT_BYTES = 512;
73
-
74
- const echoEncoder = new TextEncoder();
75
- const echoDecoder = new TextDecoder();
76
-
77
- /**
78
- * Clamp a string to a UTF-8 byte budget, appending `…` when it clipped.
79
- * Short strings — the common case, and the one that has to stay exact — are
80
- * returned unchanged and untagged.
81
- */
82
- export function boundedEchoText(
83
- value: string,
84
- maxBytes: number = MAX_ECHOED_TEXT_BYTES,
85
- ): string {
86
- const bytes = echoEncoder.encode(value);
87
- if (bytes.length <= maxBytes) return value;
88
- // Never split a codepoint: walk back off UTF-8 continuation bytes (10xxxxxx)
89
- // so the clamp cannot manufacture a replacement character.
90
- let end = Math.max(0, maxBytes);
91
- while (end > 0 && ((bytes[end] ?? 0) & 0xc0) === 0x80) end--;
92
- return `${echoDecoder.decode(bytes.slice(0, end))}…`;
93
- }
94
-
95
- /**
96
- * `{ args }` when the caller's arguments fit {@link MAX_ECHOED_ARGS_BYTES},
97
- * `{}` when they do not. All or nothing: a clipped echo would be a *different*
98
- * call than the one that was refused, and the routes this feeds end at a human
99
- * approving one. Unserializable arguments are treated the same way as oversized
100
- * ones — there is nothing honest to put in the field.
101
- */
102
- export function echoedCallArgs(args: unknown): { args?: unknown } {
103
- if (args === undefined) return {};
104
- let text: string | undefined;
105
- try {
106
- text = JSON.stringify(args);
107
- } catch {
108
- return {};
109
- }
110
- if (text === undefined) return {};
111
- return echoEncoder.encode(text).length <= MAX_ECHOED_ARGS_BYTES
112
- ? { args }
113
- : {};
114
- }
115
-
116
- function boundedValidation(
117
- details: ArgumentValidationDetails | undefined,
118
- ): ArgumentValidationDetails | undefined {
119
- if (!details) return undefined;
120
- let truncated =
121
- details.truncated === true ||
122
- details.issues.length > MAX_ARGUMENT_VALIDATION_ISSUES;
123
- const issues = details.issues
124
- .slice(0, MAX_ARGUMENT_VALIDATION_ISSUES)
125
- .map((issue) => {
126
- const path = boundedIssueText(
127
- issue.path,
128
- MAX_ARGUMENT_ISSUE_PATH_CHARS,
129
- );
130
- const code = boundedIssueText(
131
- issue.code,
132
- MAX_ARGUMENT_ISSUE_CODE_CHARS,
133
- );
134
- const expected = boundedIssueText(
135
- issue.expected,
136
- MAX_ARGUMENT_ISSUE_EXPECTED_CHARS,
137
- );
138
- truncated ||= path.truncated || code.truncated || expected.truncated;
139
- return {
140
- path: path.value,
141
- code: code.value,
142
- expected: expected.value,
143
- };
144
- });
145
- return {
146
- issues,
147
- ...(truncated ? { truncated: true as const } : {}),
148
- };
149
- }
150
-
151
- /** Agent-visible recovery class attached only to `auth_required` failures. */
152
- export type AuthRecoveryMode =
153
- | "oauth"
154
- | "operator_config"
155
- | "unavailable";
156
-
157
- const RETRYABLE_BY_CODE: Record<ConnectorCallErrorCode, boolean> = {
158
- timeout: true,
159
- rate_limited: true,
160
- unavailable: true,
161
- auth_required: false,
162
- invalid_args: false,
163
- input_required_unsupported: false,
164
- connector_call_failed: false,
165
- };
166
-
167
- /** Non-negative integer milliseconds, or undefined for anything else. */
168
- function normalizeRetryAfterMs(value: number | undefined): number | undefined {
169
- if (value === undefined) return undefined;
170
- if (!Number.isFinite(value) || value < 0) return undefined;
171
- return Math.trunc(value);
172
- }
173
-
174
- /**
175
- * Throw from `Connector.callTool` (or anything beneath it) to classify a
176
- * failure exactly. Untyped errors fall back to a message-text heuristic, so a
177
- * connector whose legitimate error text mentions "timeout" is misread as a
178
- * retryable timeout — this class is the escape hatch. `retryable` defaults per
179
- * code (timeout, rate_limited, and unavailable retry; the rest do not) and may
180
- * be overridden.
181
- *
182
- * `retryAfterMs` carries a wait window the connector already knows — a
183
- * `Retry-After` header, say — so the engine can wait that long instead of
184
- * guessing, and so an agent that receives the failure can decide when to
185
- * re-issue.
186
- */
187
- export class ConnectorCallError extends Error {
188
- readonly code: ConnectorCallErrorCode;
189
- readonly retryable: boolean;
190
- /**
191
- * Connector-known wait window in ms before this call is worth repeating,
192
- * or undefined when the connector reported none. Always an own property —
193
- * under ES2022 class fields the declaration itself defines it, so guarding
194
- * the assignment would not keep it off the instance. Keeping the window out
195
- * of the wire format is `classifyCallError`'s job, not this constructor's.
196
- */
197
- readonly retryAfterMs: number | undefined;
198
- /** Bounded schema findings for `invalid_args`; never submitted values. */
199
- readonly validation: ArgumentValidationDetails | undefined;
200
-
201
- constructor(
202
- code: ConnectorCallErrorCode,
203
- message: string,
204
- opts: {
205
- retryable?: boolean;
206
- retryAfterMs?: number;
207
- cause?: unknown;
208
- validation?: ArgumentValidationDetails;
209
- } = {},
210
- ) {
211
- super(
212
- message,
213
- opts.cause !== undefined ? { cause: opts.cause } : undefined,
214
- );
215
- this.name = "ConnectorCallError";
216
- this.code = code;
217
- this.retryable = opts.retryable ?? RETRYABLE_BY_CODE[code];
218
- this.retryAfterMs = normalizeRetryAfterMs(opts.retryAfterMs);
219
- this.validation =
220
- code === "invalid_args" ? boundedValidation(opts.validation) : undefined;
221
- }
222
- }
223
-
224
- /** The `error` object surfaced in value-mode call results and connecta.batch entries. */
225
- export interface CallErrorDetails {
226
- code: string;
227
- message: string;
228
- retryable: boolean;
229
- /**
230
- * Connector-reported wait window in ms, when known. Reported verbatim — the
231
- * engine bounds how long it will itself wait, but the caller sees the real
232
- * window so it can schedule a re-issue.
233
- */
234
- retryAfterMs?: number;
235
- /** Bounded input-schema findings; paths and expectations, never values. */
236
- validation?: ArgumentValidationDetails;
237
- /** Connector whose failed operation needs recovery. */
238
- connector?: string;
239
- /** Canonical downstream address the agent may retry after recovery. */
240
- operation?: string;
241
- /** Which safe recovery path `authorize_connector` will return. */
242
- recovery?: AuthRecoveryMode;
243
- /** The single model-facing entry point for every credential class. */
244
- nextAction?: {
245
- tool: "authorize_connector";
246
- arguments: { connector: string };
247
- operatorHandoff: string;
248
- } | {
249
- tool: "search_tools";
250
- arguments: {
251
- query: string;
252
- connector?: string;
253
- includeSchemas: "compact";
254
- };
255
- purpose: string;
256
- } | {
257
- tool: "call_destructive_tool";
258
- arguments: {
259
- address: string;
260
- /**
261
- * The caller's own arguments, echoed only when they fit
262
- * {@link MAX_ECHOED_ARGS_BYTES} — and then whole, never clipped. Absent
263
- * means "re-send exactly what you sent": a half-copied argument object
264
- * routed into a human approval prompt would describe a call nobody made.
265
- */
266
- args?: unknown;
267
- };
268
- purpose: string;
269
- } | {
270
- /**
271
- * The same scoped discovery as the `search_tools` route above, addressed to
272
- * a caller inside `execute_code`, which cannot call a tool. Which of the two
273
- * a routing failure emits follows the route the caller took, not the
274
- * deployment's advertised surface.
275
- */
276
- function: "connecta.search";
277
- arguments: {
278
- query: string;
279
- connector?: string;
280
- includeSchemas: "compact";
281
- };
282
- purpose: string;
283
- } | {
284
- function: "connecta.call";
285
- addresses: string[];
286
- purpose: string;
287
- };
288
- /** Explicit retry guidance; recovery never retries or mutates by itself. */
289
- retry?: string;
290
- }
291
-
292
- /**
293
- * Codes whose retryability is a fact about connecta's own framing, never a
294
- * guess from text. The message embeds the address the caller asked for, so a
295
- * connector named `svc-503` or `temporary-export` would otherwise flip a policy
296
- * refusal into `retryable: true` through the heuristic below — and a caller that
297
- * trusts the flag would cheerfully retry a refusal forever.
298
- */
299
- const NEVER_RETRYABLE_FRAMING = new Set([
300
- "unknown_address",
301
- "unknown_tool",
302
- "ambiguous_tool_alias",
303
- "destructive_tool_requires_approval",
304
- ]);
305
-
306
- /**
307
- * Details for a failure connecta itself framed — an address it could not
308
- * resolve, a tool it refuses to run — rather than one a connector threw.
309
- */
310
- export function framingError(code: string, message: string): CallErrorDetails {
311
- return {
312
- code,
313
- message,
314
- retryable: NEVER_RETRYABLE_FRAMING.has(code)
315
- ? false
316
- : messageLooksRetryable(message),
317
- };
318
- }
319
-
320
- const RETRYABLE_MESSAGE_RE =
321
- /timeout|timed out|econnreset|econnrefused|temporar|rate.?limit|429|502|503|504|refcountedcanceler|different request/i;
322
- const TIMEOUT_MESSAGE_RE = /timed out|timeout/i;
323
-
324
- /** Message-text fallback used when an error carries no typed classification. */
325
- function messageLooksRetryable(message: string): boolean {
326
- return RETRYABLE_MESSAGE_RE.test(message);
327
- }
328
-
329
- /**
330
- * Classify a value thrown by a connector call. A `ConnectorCallError` is
331
- * authoritative; anything else falls back to the historical message-text
332
- * heuristic.
333
- */
334
- export function classifyCallError(
335
- err: unknown,
336
- fallbackCode = "connector_call_failed",
337
- ): CallErrorDetails {
338
- if (err instanceof ConnectorCallError) {
339
- return {
340
- code: err.code,
341
- message: err.message,
342
- retryable: err.retryable,
343
- ...(err.retryAfterMs !== undefined
344
- ? { retryAfterMs: err.retryAfterMs }
345
- : {}),
346
- ...(err.validation ? { validation: err.validation } : {}),
347
- };
348
- }
349
- // An aborted fetch rejects with a DOMException named "AbortError" whose
350
- // message ("The operation was aborted", and variants across runtimes) matches
351
- // neither heuristic below — so a call the engine itself cancelled would read
352
- // as a non-retryable failure, the opposite of the truth. Note this also
353
- // covers an abort the connector triggered for its own reasons; running out of
354
- // time is by far the likelier cause and retryable/timeout is the safer read.
355
- if (err instanceof Error && err.name === "AbortError") {
356
- return { code: "timeout", message: err.message, retryable: true };
357
- }
358
- const message = err instanceof Error ? err.message : String(err);
359
- return {
360
- code: TIMEOUT_MESSAGE_RE.test(message) ? "timeout" : fallbackCode,
361
- message,
362
- retryable: RETRYABLE_MESSAGE_RE.test(message),
363
- };
364
- }