@zackbart/connecta 0.15.0 → 0.16.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 (332) hide show
  1. package/AGENTS.md +28 -15
  2. package/CHANGELOG.md +493 -0
  3. package/README.md +19 -4
  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 +0 -1
  27. package/dist/catalog.d.ts +0 -1
  28. package/dist/catalog.js +0 -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 +0 -1
  42. package/dist/errors.js +0 -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 +5 -2
  78. package/dist/providers/cloudflare.js +435 -328
  79. package/dist/providers/linear.d.ts +26 -5
  80. package/dist/providers/linear.js +32 -60
  81. package/dist/providers/mixpanel.d.ts +35 -4
  82. package/dist/providers/mixpanel.js +53 -78
  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 -59
  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 +95 -27
  129. package/documentation/code-mode.md +12 -12
  130. package/documentation/connector-guides.md +172 -5
  131. package/documentation/connectors.md +98 -7
  132. package/documentation/linear.md +26 -9
  133. package/documentation/mcp-ui-design.md +2 -2
  134. package/documentation/mixpanel.md +48 -16
  135. package/documentation/notion.md +16 -0
  136. package/documentation/operations.md +283 -5
  137. package/documentation/operator-ui.md +120 -5
  138. package/documentation/provider-audit.md +160 -0
  139. package/documentation/provider-conventions.md +631 -0
  140. package/documentation/request-admission.md +167 -5
  141. package/documentation/rich-output-design.md +1 -2
  142. package/documentation/stripe.md +27 -12
  143. package/ethos.md +14 -9
  144. package/examples/worker/README.md +96 -12
  145. package/examples/worker/src/index.ts +46 -1
  146. package/examples/worker/wrangler.jsonc +14 -1
  147. package/package.json +4 -5
  148. package/templates/node/.dockerignore +10 -0
  149. package/templates/node/.env.example +40 -3
  150. package/templates/node/AGENTS.md +11 -1
  151. package/templates/node/Dockerfile +49 -0
  152. package/templates/node/README.md +117 -2
  153. package/templates/node/docker-compose.yml +39 -0
  154. package/templates/node/package.json +1 -1
  155. package/templates/node/src/file-activity.ts +182 -0
  156. package/templates/node/src/index.ts +80 -4
  157. package/assets/connecta-clay-hero.png +0 -0
  158. package/dist/access-tokens.d.ts.map +0 -1
  159. package/dist/access-tokens.js.map +0 -1
  160. package/dist/activity.d.ts.map +0 -1
  161. package/dist/activity.js.map +0 -1
  162. package/dist/apps-shell.d.ts.map +0 -1
  163. package/dist/apps-shell.js.map +0 -1
  164. package/dist/auth/bearer.d.ts.map +0 -1
  165. package/dist/auth/bearer.js.map +0 -1
  166. package/dist/auth/clerk.d.ts.map +0 -1
  167. package/dist/auth/clerk.js.map +0 -1
  168. package/dist/auth/downstream-oauth.d.ts.map +0 -1
  169. package/dist/auth/downstream-oauth.js.map +0 -1
  170. package/dist/call-admission.d.ts.map +0 -1
  171. package/dist/call-admission.js.map +0 -1
  172. package/dist/catalog-fingerprint.d.ts.map +0 -1
  173. package/dist/catalog-fingerprint.js.map +0 -1
  174. package/dist/catalog-limits.d.ts.map +0 -1
  175. package/dist/catalog-limits.js.map +0 -1
  176. package/dist/catalog-service.d.ts.map +0 -1
  177. package/dist/catalog-service.js.map +0 -1
  178. package/dist/catalog.d.ts.map +0 -1
  179. package/dist/catalog.js.map +0 -1
  180. package/dist/concurrency.d.ts.map +0 -1
  181. package/dist/concurrency.js.map +0 -1
  182. package/dist/connector-scope.d.ts.map +0 -1
  183. package/dist/connector-scope.js.map +0 -1
  184. package/dist/connectors/api.d.ts.map +0 -1
  185. package/dist/connectors/api.js.map +0 -1
  186. package/dist/connectors/remote-mcp.d.ts.map +0 -1
  187. package/dist/connectors/remote-mcp.js.map +0 -1
  188. package/dist/credentials.d.ts.map +0 -1
  189. package/dist/credentials.js.map +0 -1
  190. package/dist/errors.d.ts.map +0 -1
  191. package/dist/errors.js.map +0 -1
  192. package/dist/execute.d.ts.map +0 -1
  193. package/dist/execute.js.map +0 -1
  194. package/dist/executor-admission.d.ts.map +0 -1
  195. package/dist/executor-admission.js.map +0 -1
  196. package/dist/executor-result.d.ts.map +0 -1
  197. package/dist/executor-result.js.map +0 -1
  198. package/dist/executors/quickjs-child.d.ts.map +0 -1
  199. package/dist/executors/quickjs-child.js.map +0 -1
  200. package/dist/executors/quickjs-protocol.d.ts.map +0 -1
  201. package/dist/executors/quickjs-protocol.js.map +0 -1
  202. package/dist/executors/quickjs-runtime.d.ts.map +0 -1
  203. package/dist/executors/quickjs-runtime.js.map +0 -1
  204. package/dist/executors/quickjs.d.ts.map +0 -1
  205. package/dist/executors/quickjs.js.map +0 -1
  206. package/dist/favicon.d.ts.map +0 -1
  207. package/dist/favicon.js.map +0 -1
  208. package/dist/index.d.ts.map +0 -1
  209. package/dist/index.js.map +0 -1
  210. package/dist/invocation.d.ts.map +0 -1
  211. package/dist/invocation.js.map +0 -1
  212. package/dist/json-schema.d.ts.map +0 -1
  213. package/dist/json-schema.js.map +0 -1
  214. package/dist/mcp-result.d.ts.map +0 -1
  215. package/dist/mcp-result.js.map +0 -1
  216. package/dist/meta-tools.d.ts.map +0 -1
  217. package/dist/meta-tools.js.map +0 -1
  218. package/dist/node.d.ts.map +0 -1
  219. package/dist/node.js.map +0 -1
  220. package/dist/operator-ui/generated.d.ts.map +0 -1
  221. package/dist/operator-ui/generated.js.map +0 -1
  222. package/dist/operator-ui/model.d.ts.map +0 -1
  223. package/dist/operator-ui/model.js.map +0 -1
  224. package/dist/providers/cloudflare.d.ts.map +0 -1
  225. package/dist/providers/cloudflare.js.map +0 -1
  226. package/dist/providers/linear.d.ts.map +0 -1
  227. package/dist/providers/linear.js.map +0 -1
  228. package/dist/providers/mixpanel.d.ts.map +0 -1
  229. package/dist/providers/mixpanel.js.map +0 -1
  230. package/dist/providers/notion.d.ts.map +0 -1
  231. package/dist/providers/notion.js.map +0 -1
  232. package/dist/providers/stripe.d.ts.map +0 -1
  233. package/dist/providers/stripe.js.map +0 -1
  234. package/dist/registry.d.ts.map +0 -1
  235. package/dist/registry.js.map +0 -1
  236. package/dist/retired-toolkits.d.ts.map +0 -1
  237. package/dist/retired-toolkits.js.map +0 -1
  238. package/dist/routes/access-tokens.d.ts.map +0 -1
  239. package/dist/routes/access-tokens.js.map +0 -1
  240. package/dist/routes/activity.d.ts.map +0 -1
  241. package/dist/routes/activity.js.map +0 -1
  242. package/dist/routes/credentials.d.ts.map +0 -1
  243. package/dist/routes/credentials.js.map +0 -1
  244. package/dist/routes/mcp.d.ts.map +0 -1
  245. package/dist/routes/mcp.js.map +0 -1
  246. package/dist/routes/oauth.d.ts.map +0 -1
  247. package/dist/routes/oauth.js.map +0 -1
  248. package/dist/routes/shared.d.ts.map +0 -1
  249. package/dist/routes/shared.js.map +0 -1
  250. package/dist/routes/ui.d.ts.map +0 -1
  251. package/dist/routes/ui.js.map +0 -1
  252. package/dist/server.d.ts.map +0 -1
  253. package/dist/server.js.map +0 -1
  254. package/dist/skills.d.ts.map +0 -1
  255. package/dist/skills.js.map +0 -1
  256. package/dist/storage/file.d.ts.map +0 -1
  257. package/dist/storage/file.js.map +0 -1
  258. package/dist/storage/memory.d.ts.map +0 -1
  259. package/dist/storage/memory.js.map +0 -1
  260. package/dist/timeout.d.ts.map +0 -1
  261. package/dist/timeout.js.map +0 -1
  262. package/dist/tool-safety.d.ts.map +0 -1
  263. package/dist/tool-safety.js.map +0 -1
  264. package/dist/types.d.ts.map +0 -1
  265. package/dist/types.js.map +0 -1
  266. package/dist/ui.d.ts.map +0 -1
  267. package/dist/ui.js.map +0 -1
  268. package/dist/validate.d.ts.map +0 -1
  269. package/dist/validate.js.map +0 -1
  270. package/dist/version.d.ts.map +0 -1
  271. package/dist/version.js.map +0 -1
  272. package/examples/node/README.md +0 -52
  273. package/examples/node/src/index.ts +0 -71
  274. package/src/access-tokens.ts +0 -289
  275. package/src/activity.ts +0 -234
  276. package/src/apps-shell.ts +0 -370
  277. package/src/auth/bearer.ts +0 -61
  278. package/src/auth/clerk.ts +0 -553
  279. package/src/auth/downstream-oauth.ts +0 -575
  280. package/src/call-admission.ts +0 -521
  281. package/src/catalog-fingerprint.ts +0 -52
  282. package/src/catalog-limits.ts +0 -11
  283. package/src/catalog-service.ts +0 -1153
  284. package/src/catalog.ts +0 -790
  285. package/src/concurrency.ts +0 -39
  286. package/src/connector-scope.ts +0 -66
  287. package/src/connectors/api.ts +0 -159
  288. package/src/connectors/remote-mcp.ts +0 -1090
  289. package/src/credentials.ts +0 -428
  290. package/src/errors.ts +0 -364
  291. package/src/execute.ts +0 -1406
  292. package/src/executor-admission.ts +0 -328
  293. package/src/executor-result.ts +0 -107
  294. package/src/executors/quickjs-child.ts +0 -172
  295. package/src/executors/quickjs-protocol.ts +0 -99
  296. package/src/executors/quickjs-runtime.ts +0 -470
  297. package/src/executors/quickjs.ts +0 -776
  298. package/src/favicon.ts +0 -53
  299. package/src/index.ts +0 -666
  300. package/src/invocation.ts +0 -655
  301. package/src/json-schema.ts +0 -11
  302. package/src/mcp-result.ts +0 -43
  303. package/src/meta-tools.ts +0 -1607
  304. package/src/node.ts +0 -206
  305. package/src/operator-ui/browser.css +0 -423
  306. package/src/operator-ui/browser.ts +0 -1281
  307. package/src/operator-ui/generated.ts +0 -4
  308. package/src/operator-ui/model.ts +0 -111
  309. package/src/providers/cloudflare.ts +0 -3803
  310. package/src/providers/linear.ts +0 -301
  311. package/src/providers/mixpanel.ts +0 -228
  312. package/src/providers/notion.ts +0 -1879
  313. package/src/providers/stripe.ts +0 -306
  314. package/src/registry.ts +0 -1085
  315. package/src/retired-toolkits.ts +0 -14
  316. package/src/routes/access-tokens.ts +0 -115
  317. package/src/routes/activity.ts +0 -215
  318. package/src/routes/credentials.ts +0 -254
  319. package/src/routes/mcp.ts +0 -429
  320. package/src/routes/oauth.ts +0 -322
  321. package/src/routes/shared.ts +0 -247
  322. package/src/routes/ui.ts +0 -152
  323. package/src/server.ts +0 -195
  324. package/src/skills.ts +0 -271
  325. package/src/storage/file.ts +0 -123
  326. package/src/storage/memory.ts +0 -44
  327. package/src/timeout.ts +0 -84
  328. package/src/tool-safety.ts +0 -15
  329. package/src/types.ts +0 -523
  330. package/src/ui.ts +0 -744
  331. package/src/validate.ts +0 -387
  332. package/src/version.ts +0 -7
@@ -1,123 +0,0 @@
1
- import {
2
- chmodSync,
3
- existsSync,
4
- mkdirSync,
5
- readFileSync,
6
- renameSync,
7
- writeFileSync,
8
- } from "node:fs";
9
- import { dirname } from "node:path";
10
- import type { KVStorage, Logger } from "../types.js";
11
-
12
- interface Entry {
13
- value: string;
14
- exp?: number; // epoch ms
15
- }
16
-
17
- export interface FileStorageOptions {
18
- /** Destination for the corrupt-state-file recovery report. Default console. */
19
- logger?: Logger;
20
- }
21
-
22
- /**
23
- * JSON-file-backed KVStorage for Node. Loads once, persists on every write via
24
- * a temp-file + rename (atomic-ish). Only reachable via the "@zackbart/connecta/node"
25
- * subpath so the main entry stays Workers-clean.
26
- */
27
- export function fileStorage(
28
- path: string,
29
- opts: FileStorageOptions = {},
30
- ): KVStorage {
31
- const logger: Logger = opts.logger ?? console;
32
- // The state file holds downstream OAuth access/refresh tokens in cleartext,
33
- // so keep it owner-only. Repair is best-effort: chmod is a no-op or throws on
34
- // non-POSIX filesystems, and a loose mode must never keep the store from
35
- // starting.
36
- const tighten = () => {
37
- try {
38
- chmodSync(path, 0o600);
39
- } catch {
40
- // Non-POSIX filesystem or a race on the file — leave the mode as-is.
41
- }
42
- };
43
- let data: Record<string, Entry> = {};
44
- if (existsSync(path)) {
45
- tighten();
46
- try {
47
- data = JSON.parse(readFileSync(path, "utf8")) as Record<string, Entry>;
48
- } catch (error) {
49
- // Never let a damaged state file be silently replaced by an empty one:
50
- // the next set() would persist {} over irreplaceable downstream OAuth
51
- // tokens and credential-vault entries. Quarantine the bytes so they
52
- // survive for manual recovery, and refuse to start if even that fails —
53
- // losing the file loudly beats losing it quietly.
54
- const quarantine = `${path}.corrupt-${Date.now()}`;
55
- try {
56
- renameSync(path, quarantine);
57
- } catch (renameError) {
58
- throw new Error(
59
- `[connecta] state file ${path} is not valid JSON and could not be ` +
60
- `moved aside (${String(renameError)}). Refusing to start rather ` +
61
- `than overwrite it. Move or repair the file, then restart.`,
62
- );
63
- }
64
- logger.error(
65
- `[connecta] state file ${path} is not valid JSON ` +
66
- `(${error instanceof Error ? error.message : String(error)}) — ` +
67
- `moved to ${quarantine}, starting from empty state. Downstream ` +
68
- `OAuth connectors must be re-authorized and stored credentials ` +
69
- `re-entered.`,
70
- );
71
- data = {};
72
- }
73
- }
74
- const persist = () => {
75
- // Physical expiry rides on an operation that was already going to write.
76
- // A read must not flush this instance's load-once snapshot: another live
77
- // instance may have written newer unrelated values since we loaded it.
78
- const now = Date.now();
79
- for (const [key, entry] of Object.entries(data)) {
80
- if (entry.exp && now > entry.exp) delete data[key];
81
- }
82
- const dir = dirname(path);
83
- if (dir) mkdirSync(dir, { recursive: true, mode: 0o700 });
84
- const tmp = `${path}.tmp`;
85
- // 0o600 on the tmp file; the atomic rename below preserves it, so the live
86
- // state file is never briefly world-readable.
87
- writeFileSync(tmp, JSON.stringify(data), { mode: 0o600 });
88
- renameSync(tmp, path);
89
- tighten();
90
- };
91
- const fresh = (key: string): Entry | null => {
92
- const e = data[key];
93
- if (!e) return null;
94
- if (e.exp && Date.now() > e.exp) {
95
- delete data[key];
96
- return null;
97
- }
98
- return e;
99
- };
100
- return {
101
- async get(key) {
102
- return fresh(key)?.value ?? null;
103
- },
104
- async set(key, value, opts) {
105
- data[key] = {
106
- value,
107
- ...(opts?.ttlSeconds
108
- ? { exp: Date.now() + opts.ttlSeconds * 1000 }
109
- : {}),
110
- };
111
- persist();
112
- },
113
- async delete(key) {
114
- delete data[key];
115
- persist();
116
- },
117
- async list(prefix) {
118
- return Object.keys(data)
119
- .filter((key) => Boolean(fresh(key)) && key.startsWith(prefix))
120
- .sort();
121
- },
122
- };
123
- }
@@ -1,44 +0,0 @@
1
- import type { KVStorage } from "../types.js";
2
-
3
- interface Entry {
4
- value: string;
5
- exp?: number; // epoch ms
6
- }
7
-
8
- /** In-memory KV store with expiry. The default for dev and Node. */
9
- export function memoryStorage(): KVStorage {
10
- const map = new Map<string, Entry>();
11
- const fresh = (key: string): Entry | null => {
12
- const e = map.get(key);
13
- if (!e) return null;
14
- if (e.exp && Date.now() > e.exp) {
15
- map.delete(key);
16
- return null;
17
- }
18
- return e;
19
- };
20
- return {
21
- async get(key) {
22
- return fresh(key)?.value ?? null;
23
- },
24
- async set(key, value, opts) {
25
- map.set(key, {
26
- value,
27
- ...(opts?.ttlSeconds
28
- ? { exp: Date.now() + opts.ttlSeconds * 1000 }
29
- : {}),
30
- });
31
- },
32
- async delete(key) {
33
- map.delete(key);
34
- },
35
- async list(prefix) {
36
- return [...map.keys()]
37
- .filter((key) => {
38
- fresh(key);
39
- return key.startsWith(prefix) && map.has(key);
40
- })
41
- .sort();
42
- },
43
- };
44
- }
package/src/timeout.ts DELETED
@@ -1,84 +0,0 @@
1
- // The deadline vocabulary shared by downstream discovery probes and tool calls.
2
- // One definition keeps those waits bounded consistently.
3
-
4
- /**
5
- * Generous default bound for a single downstream probe/catalog call. High enough
6
- * to trip only on a pathological hang, not a realistically slow probe.
7
- */
8
- export const DEFAULT_PROBE_TIMEOUT_MS = 30_000;
9
-
10
- /** A finite, positive integer number of milliseconds, or undefined. */
11
- export function normalizeTimeoutMs(
12
- value: number | undefined,
13
- ): number | undefined {
14
- if (value === undefined || !Number.isFinite(value) || !(value > 0)) {
15
- return undefined;
16
- }
17
- return Math.max(1, Math.trunc(value));
18
- }
19
-
20
- /**
21
- * Reject `promise` after `ms` if it has not settled, so one hung downstream
22
- * cannot stall a whole fan-out. This form bounds only the caller-facing wait;
23
- * use `withAbortableTimeout` when the operation accepts an AbortSignal and the
24
- * underlying work must stop too.
25
- */
26
- export function withTimeout<T>(
27
- promise: Promise<T>,
28
- ms: number,
29
- label: string,
30
- ): Promise<T> {
31
- return new Promise<T>((resolve, reject) => {
32
- const timer = setTimeout(() => {
33
- reject(new Error(`${label} timed out after ${ms}ms`));
34
- }, ms);
35
- promise.then(
36
- (value) => {
37
- clearTimeout(timer);
38
- resolve(value);
39
- },
40
- (err) => {
41
- clearTimeout(timer);
42
- reject(err);
43
- },
44
- );
45
- });
46
- }
47
-
48
- /**
49
- * Give one operation a caller-facing deadline and the matching cancellation
50
- * signal. The timeout rejects with the stable, labelled error while aborting
51
- * any in-flight work that honors the signal.
52
- */
53
- export function withAbortableTimeout<T>(
54
- operation: (signal: AbortSignal) => Promise<T>,
55
- ms: number,
56
- label: string,
57
- ): Promise<T> {
58
- const controller = new AbortController();
59
- return new Promise<T>((resolve, reject) => {
60
- const timeoutError = new Error(`${label} timed out after ${ms}ms`);
61
- const timer = setTimeout(() => {
62
- controller.abort(timeoutError);
63
- reject(timeoutError);
64
- }, ms);
65
- let promise: Promise<T>;
66
- try {
67
- promise = operation(controller.signal);
68
- } catch (err) {
69
- clearTimeout(timer);
70
- reject(err);
71
- return;
72
- }
73
- promise.then(
74
- (value) => {
75
- clearTimeout(timer);
76
- resolve(value);
77
- },
78
- (err) => {
79
- clearTimeout(timer);
80
- reject(err);
81
- },
82
- );
83
- });
84
- }
@@ -1,15 +0,0 @@
1
- import type { ToolDef } from "./types.js";
2
-
3
- /**
4
- * The one fail-closed classification shared by discovery and invocation.
5
- *
6
- * A tool is read-only only when it says so without also saying it is
7
- * destructive. Missing, false, and contradictory annotations all require the
8
- * approval-visible call path.
9
- */
10
- export function isExplicitlyReadOnly(definition: ToolDef): boolean {
11
- return (
12
- definition.annotations?.readOnlyHint === true &&
13
- definition.annotations?.destructiveHint !== true
14
- );
15
- }