@zackbart/connecta 0.28.1 → 0.29.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 (319) hide show
  1. package/CHANGELOG.md +788 -5
  2. package/README.md +62 -42
  3. package/bin/connecta.mjs +110 -139
  4. package/bin/meta-tool-names.d.mts +2 -0
  5. package/bin/meta-tool-names.mjs +9 -0
  6. package/bin/version.mjs +3 -0
  7. package/dist/access-tokens.js +53 -63
  8. package/dist/activity-request.js +8 -0
  9. package/dist/activity.d.ts +76 -42
  10. package/dist/activity.js +110 -42
  11. package/dist/auth/clerk-sdk/client.d.ts +65 -0
  12. package/dist/auth/clerk-sdk/client.js +5 -0
  13. package/dist/auth/clerk-sdk/generated.js +1845 -0
  14. package/dist/auth/clerk-transport.js +19 -0
  15. package/dist/auth/clerk.d.ts +17 -7
  16. package/dist/auth/clerk.js +189 -107
  17. package/dist/auth/cloudflare-access.js +25 -26
  18. package/dist/auth/downstream-client-metadata.d.ts +29 -0
  19. package/dist/auth/downstream-client-metadata.js +133 -0
  20. package/dist/auth/downstream-oauth.js +1584 -1580
  21. package/dist/auth/downstream-revocation.js +106 -0
  22. package/dist/auth/oauth-token-response.js +231 -0
  23. package/dist/auth/oauth-v2-migration.js +116 -0
  24. package/dist/auth/static-oauth.js +93 -71
  25. package/dist/auth-elicitation.js +283 -0
  26. package/dist/branding.d.ts +8 -16
  27. package/dist/branding.js +26 -59
  28. package/dist/byte-read-response.js +39 -0
  29. package/dist/call-admission.js +12 -16
  30. package/dist/catalog-cache.js +739 -0
  31. package/dist/catalog-drift.d.ts +50 -15
  32. package/dist/catalog-drift.js +365 -128
  33. package/dist/catalog-fingerprint.js +2 -4
  34. package/dist/catalog-freshness.js +13 -0
  35. package/dist/catalog-limits.js +2 -2
  36. package/dist/catalog-service.js +368 -224
  37. package/dist/catalog.js +43 -84
  38. package/dist/concurrency.js +3 -4
  39. package/dist/config-defaults.d.ts +39 -0
  40. package/dist/config-defaults.js +46 -0
  41. package/dist/config-schema.d.ts +181 -0
  42. package/dist/config-schema.js +435 -0
  43. package/dist/config-value-sources.js +102 -0
  44. package/dist/config.d.ts +631 -0
  45. package/dist/config.js +503 -0
  46. package/dist/connector-access.d.ts +1 -0
  47. package/dist/connector-access.js +13 -15
  48. package/dist/connector-caller.d.ts +8 -0
  49. package/dist/connector-caller.js +15 -6
  50. package/dist/connector-scope.js +1 -1
  51. package/dist/connectors/api-connector.d.ts +59 -7
  52. package/dist/connectors/api-connector.js +106 -19
  53. package/dist/connectors/api.js +4 -1
  54. package/dist/connectors/guarded-fetch.d.ts +144 -0
  55. package/dist/connectors/guarded-fetch.js +84 -35
  56. package/dist/connectors/negotiation-cache.js +46 -0
  57. package/dist/connectors/option-shapes.js +27 -0
  58. package/dist/connectors/remote-mcp.d.ts +30 -4
  59. package/dist/connectors/remote-mcp.js +1774 -320
  60. package/dist/connectors/resource-uri.js +335 -0
  61. package/dist/credential-contract.d.ts +10 -0
  62. package/dist/credential-rules.js +1 -3
  63. package/dist/credential-url.js +108 -0
  64. package/dist/credentials.d.ts +6 -1
  65. package/dist/credentials.js +27 -18
  66. package/dist/d1.d.ts +130 -0
  67. package/dist/d1.js +290 -0
  68. package/dist/describe-config.d.ts +165 -0
  69. package/dist/describe-config.js +315 -0
  70. package/dist/described.js +106 -0
  71. package/dist/downstream-input-context.js +119 -0
  72. package/dist/downstream-input.js +323 -0
  73. package/dist/errors.d.ts +97 -20
  74. package/dist/errors.js +158 -80
  75. package/dist/execute.js +453 -305
  76. package/dist/executor-admission.d.ts +1 -0
  77. package/dist/executor-admission.js +11 -15
  78. package/dist/executor-contract.d.ts +20 -0
  79. package/dist/executor-contract.js +48 -0
  80. package/dist/executor-result.js +24 -9
  81. package/dist/executors/quickjs-child.js +3 -4
  82. package/dist/executors/quickjs-runtime.js +147 -59
  83. package/dist/executors/quickjs.js +29 -35
  84. package/dist/favicon.js +1 -2
  85. package/dist/fix-prompt.js +1 -3
  86. package/dist/guest-runtime.js +188 -0
  87. package/dist/guest-types.d.ts +176 -0
  88. package/dist/guest-types.js +1 -0
  89. package/dist/html-security.js +24 -0
  90. package/dist/identity.js +1 -3
  91. package/dist/inbound-credential.js +52 -0
  92. package/dist/index.d.ts +24 -256
  93. package/dist/index.js +65 -478
  94. package/dist/invocation-auth.js +69 -0
  95. package/dist/invocation.js +230 -73
  96. package/dist/json-schema.d.ts +1 -1
  97. package/dist/mcp-client-context.js +35 -0
  98. package/dist/mcp-result.js +11 -7
  99. package/dist/meta-output.js +76 -0
  100. package/dist/meta-tool-names.d.ts +2 -0
  101. package/dist/meta-tool-names.js +3 -0
  102. package/dist/meta-tools.js +285 -209
  103. package/dist/module-contracts.d.ts +8 -23
  104. package/dist/node.d.ts +0 -2
  105. package/dist/node.js +2 -2
  106. package/dist/oauth-callback-outcome.js +1 -3
  107. package/dist/oauth-handoff.js +117 -0
  108. package/dist/oauth-sealing.js +20 -0
  109. package/dist/operator-record.d.ts +137 -0
  110. package/dist/operator-record.js +420 -0
  111. package/dist/operator-ui/assets.js +31 -0
  112. package/dist/operator-ui/contract.d.ts +72 -0
  113. package/dist/operator-ui/contract.js +1 -0
  114. package/dist/operator-ui/fix-prompts.d.ts +18 -0
  115. package/dist/operator-ui/generated.js +5 -4
  116. package/dist/operator-ui/model.d.ts +12 -87
  117. package/dist/operator-ui/model.js +2 -9
  118. package/dist/operator-ui/setup-commands.js +1 -3
  119. package/dist/operator-ui/view.d.ts +323 -0
  120. package/dist/operator-ui/view.js +62 -189
  121. package/dist/page-styles.js +2 -3
  122. package/dist/program-source.js +14 -2
  123. package/dist/{exempt-writes.js → program-writes.js} +55 -18
  124. package/dist/provider.d.ts +142 -0
  125. package/dist/provider.js +187 -0
  126. package/dist/providers/_shared/google/result-size.js +57 -0
  127. package/dist/providers/_shared/google/service-account.d.ts +58 -0
  128. package/dist/providers/_shared/google/service-account.js +500 -0
  129. package/dist/providers/_shared/google/workspace.d.ts +276 -0
  130. package/dist/providers/_shared/google/workspace.js +518 -0
  131. package/dist/providers/{basecamp.d.ts → basecamp/index.d.ts} +6 -28
  132. package/dist/providers/basecamp/index.js +997 -0
  133. package/dist/providers/basecamp/skill.generated.js +9 -0
  134. package/dist/providers/{breeze.d.ts → breeze/index.d.ts} +2 -2
  135. package/dist/providers/{breeze.js → breeze/index.js} +184 -140
  136. package/dist/providers/breeze/skill.generated.js +9 -0
  137. package/dist/providers/{ccb.d.ts → ccb/index.d.ts} +2 -2
  138. package/dist/providers/{ccb.js → ccb/index.js} +271 -116
  139. package/dist/providers/ccb/skill.generated.js +9 -0
  140. package/dist/providers/{cloudflare.d.ts → cloudflare/index.d.ts} +8 -7
  141. package/dist/providers/{cloudflare.js → cloudflare/index.js} +171 -738
  142. package/dist/providers/cloudflare/skill.generated.js +10 -0
  143. package/dist/providers/docs/index.d.ts +54 -0
  144. package/dist/providers/docs/index.js +1237 -0
  145. package/dist/providers/docs/skill.generated.js +9 -0
  146. package/dist/providers/drive/index.d.ts +53 -0
  147. package/dist/providers/drive/index.js +1523 -0
  148. package/dist/providers/drive/skill.generated.js +9 -0
  149. package/dist/providers/forms/index.d.ts +54 -0
  150. package/dist/providers/forms/index.js +1217 -0
  151. package/dist/providers/forms/skill.generated.js +11 -0
  152. package/dist/providers/github/auth.d.ts +32 -0
  153. package/dist/providers/github/auth.js +361 -0
  154. package/dist/providers/github/hosted.js +218 -0
  155. package/dist/providers/github/index.d.ts +13 -0
  156. package/dist/providers/github/index.js +140 -0
  157. package/dist/providers/github/key.js +100 -0
  158. package/dist/providers/github/rest.js +321 -0
  159. package/dist/providers/github/scope.d.ts +29 -0
  160. package/dist/providers/github/scope.js +124 -0
  161. package/dist/providers/github/skill.generated.js +8 -0
  162. package/dist/providers/gmail/index.d.ts +51 -0
  163. package/dist/providers/gmail/index.js +1436 -0
  164. package/dist/providers/gmail/skill.generated.js +9 -0
  165. package/dist/providers/{linear.d.ts → linear/index.d.ts} +11 -14
  166. package/dist/providers/linear/index.js +352 -0
  167. package/dist/providers/linear/skill.generated.js +8 -0
  168. package/dist/providers/{mixpanel.d.ts → mixpanel/index.d.ts} +5 -10
  169. package/dist/providers/mixpanel/index.js +416 -0
  170. package/dist/providers/mixpanel/skill.generated.js +9 -0
  171. package/dist/providers/{notion.d.ts → notion/index.d.ts} +8 -8
  172. package/dist/providers/{notion.js → notion/index.js} +226 -239
  173. package/dist/providers/notion/skill.generated.js +10 -0
  174. package/dist/providers/{overflow.d.ts → overflow/index.d.ts} +2 -2
  175. package/dist/providers/{overflow.js → overflow/index.js} +74 -111
  176. package/dist/providers/overflow/skill.generated.js +8 -0
  177. package/dist/providers/{planning-center.d.ts → planning-center/index.d.ts} +2 -2
  178. package/dist/providers/{planning-center.js → planning-center/index.js} +264 -104
  179. package/dist/providers/planning-center/skill.generated.js +10 -0
  180. package/dist/providers/{revenuecat.d.ts → revenuecat/index.d.ts} +5 -10
  181. package/dist/providers/revenuecat/index.js +557 -0
  182. package/dist/providers/revenuecat/skill.generated.js +11 -0
  183. package/dist/providers/sheets/index.d.ts +54 -0
  184. package/dist/providers/sheets/index.js +1237 -0
  185. package/dist/providers/sheets/skill.generated.js +10 -0
  186. package/dist/providers/slides/index.d.ts +53 -0
  187. package/dist/providers/slides/index.js +2645 -0
  188. package/dist/providers/slides/skill.generated.js +9 -0
  189. package/dist/providers/{stripe.d.ts → stripe/index.d.ts} +5 -12
  190. package/dist/providers/stripe/index.js +266 -0
  191. package/dist/providers/stripe/skill.generated.js +11 -0
  192. package/dist/providers/{tithely.d.ts → tithely/index.d.ts} +2 -2
  193. package/dist/providers/{tithely.js → tithely/index.js} +60 -91
  194. package/dist/providers/tithely/skill.generated.js +8 -0
  195. package/dist/providers/{vercel.d.ts → vercel/index.d.ts} +8 -8
  196. package/dist/providers/vercel/index.js +1038 -0
  197. package/dist/providers/vercel/mcp-ownership.js +212 -0
  198. package/dist/providers/vercel/skill.generated.js +11 -0
  199. package/dist/registry.d.ts +108 -171
  200. package/dist/registry.js +513 -925
  201. package/dist/request-state.js +21 -0
  202. package/dist/resource-read.js +100 -0
  203. package/dist/result-shapes.js +17 -49
  204. package/dist/retired-toolkits.js +1 -1
  205. package/dist/routes/access-tokens.js +3 -6
  206. package/dist/routes/activity-context.js +21 -0
  207. package/dist/routes/activity-disclosure.js +40 -0
  208. package/dist/routes/activity.js +59 -21
  209. package/dist/routes/actor-labels.js +3 -50
  210. package/dist/routes/connect.js +221 -0
  211. package/dist/routes/credentials.js +15 -27
  212. package/dist/routes/mcp.js +356 -130
  213. package/dist/routes/oauth-client-metadata.js +15 -0
  214. package/dist/routes/oauth-management.js +45 -107
  215. package/dist/routes/oauth.js +110 -57
  216. package/dist/routes/operator.js +3 -3
  217. package/dist/routes/shared.d.ts +25 -64
  218. package/dist/routes/shared.js +160 -80
  219. package/dist/routes/skills.js +30 -0
  220. package/dist/routes/ui-config.js +225 -0
  221. package/dist/routes/ui-data.js +40 -35
  222. package/dist/routes/ui.js +66 -56
  223. package/dist/runtime/admission.js +4 -2
  224. package/dist/runtime/call-admission.js +3 -1
  225. package/dist/runtime/connector-scope.js +1 -4
  226. package/dist/runtime/run.js +10 -39
  227. package/dist/runtime/services.js +12 -117
  228. package/dist/runtime/shared-read.js +1 -3
  229. package/dist/runtime/storage.js +8 -1
  230. package/dist/sent-secrets.d.ts +52 -0
  231. package/dist/sent-secrets.js +474 -0
  232. package/dist/server.js +28 -71
  233. package/dist/skills.js +406 -174
  234. package/dist/sqlite.d.ts +48 -0
  235. package/dist/sqlite.js +166 -0
  236. package/dist/storage/keys.js +428 -0
  237. package/dist/storage/memory.js +7 -0
  238. package/dist/storage/sql.d.ts +66 -0
  239. package/dist/storage/sql.js +534 -0
  240. package/dist/timeout.js +4 -2
  241. package/dist/tool-name.js +17 -0
  242. package/dist/tool-safety.d.ts +9 -35
  243. package/dist/tool-safety.js +20 -40
  244. package/dist/types.d.ts +320 -54
  245. package/dist/types.js +0 -1
  246. package/dist/ui.d.ts +7 -19
  247. package/dist/ui.js +76 -90
  248. package/dist/url-safety.js +3 -6
  249. package/dist/usage-guide.js +137 -0
  250. package/dist/validate.d.ts +7 -0
  251. package/dist/validate.js +309 -47
  252. package/dist/version.d.ts +1 -7
  253. package/dist/version.js +3 -7
  254. package/dist/worker.d.ts +11 -0
  255. package/dist/worker.js +434 -0
  256. package/documentation/architecture.md +664 -231
  257. package/documentation/auth.md +936 -546
  258. package/documentation/code-mode.md +501 -312
  259. package/documentation/meta-tools.md +449 -200
  260. package/documentation/operator-tests.md +93 -0
  261. package/documentation/provider-migration-0.29.md +60 -0
  262. package/examples/worker/AGENTS.md +34 -12
  263. package/examples/worker/README.md +286 -255
  264. package/examples/worker/kv-to-d1.wrangler.jsonc +26 -0
  265. package/examples/worker/scripts/copy-kv-to-d1.mjs +162 -0
  266. package/examples/worker/src/connecta.config.ts +151 -0
  267. package/examples/worker/src/index.ts +14 -197
  268. package/examples/worker/wrangler.jsonc +15 -35
  269. package/package.json +120 -54
  270. package/templates/node/.dockerignore +1 -2
  271. package/templates/node/.env.example +20 -21
  272. package/templates/node/AGENTS.md +21 -17
  273. package/templates/node/Dockerfile +3 -5
  274. package/templates/node/README.md +133 -58
  275. package/templates/node/docker-compose.yml +11 -12
  276. package/templates/node/package.json +4 -2
  277. package/templates/node/src/connecta.config.ts +119 -0
  278. package/templates/node/src/index.ts +9 -154
  279. package/templates/node/src/provision-token.ts +17 -0
  280. package/AGENTS.md +0 -170
  281. package/dist/artifacts/connector.d.ts +0 -58
  282. package/dist/artifacts/connector.js +0 -730
  283. package/dist/artifacts/document.js +0 -86
  284. package/dist/artifacts/guide.js +0 -140
  285. package/dist/artifacts/html-scan.js +0 -329
  286. package/dist/artifacts/json.js +0 -78
  287. package/dist/artifacts/kv-store.d.ts +0 -20
  288. package/dist/artifacts/kv-store.js +0 -140
  289. package/dist/artifacts/markdown.js +0 -478
  290. package/dist/artifacts/module.d.ts +0 -37
  291. package/dist/artifacts/module.js +0 -66
  292. package/dist/artifacts/operations.d.ts +0 -197
  293. package/dist/artifacts/operations.js +0 -1002
  294. package/dist/artifacts/refresh.d.ts +0 -55
  295. package/dist/artifacts/refresh.js +0 -236
  296. package/dist/artifacts/routes.js +0 -206
  297. package/dist/artifacts/types.d.ts +0 -214
  298. package/dist/artifacts/types.js +0 -22
  299. package/dist/artifacts/validate.d.ts +0 -62
  300. package/dist/artifacts/validate.js +0 -651
  301. package/dist/artifacts.d.ts +0 -6
  302. package/dist/artifacts.js +0 -9
  303. package/dist/auth/bearer.d.ts +0 -11
  304. package/dist/auth/bearer.js +0 -50
  305. package/dist/providers/basecamp.js +0 -445
  306. package/dist/providers/linear.js +0 -217
  307. package/dist/providers/mixpanel.js +0 -247
  308. package/dist/providers/revenuecat.js +0 -317
  309. package/dist/providers/stripe.js +0 -253
  310. package/dist/providers/vercel.js +0 -1253
  311. package/dist/storage/file.d.ts +0 -15
  312. package/dist/storage/file.js +0 -455
  313. package/ethos.md +0 -93
  314. package/examples/worker/src/cloudflare-kv.ts +0 -43
  315. package/examples/worker/src/d1-activity-row.ts +0 -155
  316. package/examples/worker/src/d1-activity.ts +0 -147
  317. package/examples/worker/src/d1-storage.ts +0 -138
  318. package/examples/worker/src/r2-artifact-blobs.ts +0 -29
  319. package/templates/node/src/file-activity.ts +0 -182
package/dist/catalog.js CHANGED
@@ -29,8 +29,7 @@ class SchemaWork {
29
29
  }
30
30
  text(value) {
31
31
  // Check code units first so encoding a hostile scalar is itself bounded.
32
- if (value.length > this.byteLimit ||
33
- schemaEncoder.encode(value).length > this.byteLimit) {
32
+ if (value.length > this.byteLimit || schemaEncoder.encode(value).length > this.byteLimit) {
34
33
  throw schemaSizeExceeded;
35
34
  }
36
35
  return value;
@@ -206,12 +205,7 @@ function inflectionVariants(base) {
206
205
  `${base}es`,
207
206
  `${base}ed`,
208
207
  ...(base.endsWith("e") ? [`${base}d`] : []),
209
- ...(base.endsWith("y")
210
- ? [
211
- `${base.slice(0, -1)}ies`,
212
- `${base.slice(0, -1)}ied`,
213
- ]
214
- : []),
208
+ ...(base.endsWith("y") ? [`${base.slice(0, -1)}ies`, `${base.slice(0, -1)}ied`] : []),
215
209
  ];
216
210
  }
217
211
  function matchingTokenCandidates(term) {
@@ -221,12 +215,8 @@ function matchingTokenCandidates(term) {
221
215
  ...(term.endsWith("es") ? [term.slice(0, -2)] : []),
222
216
  ...(term.endsWith("ed") ? [term.slice(0, -2)] : []),
223
217
  ...(term.endsWith("d") ? [term.slice(0, -1)] : []),
224
- ...(term.endsWith("ies")
225
- ? [`${term.slice(0, -3)}y`]
226
- : []),
227
- ...(term.endsWith("ied")
228
- ? [`${term.slice(0, -3)}y`]
229
- : []),
218
+ ...(term.endsWith("ies") ? [`${term.slice(0, -3)}y`] : []),
219
+ ...(term.endsWith("ied") ? [`${term.slice(0, -3)}y`] : []),
230
220
  ];
231
221
  for (const base of possibleBases) {
232
222
  if (base && inflectionVariants(base).includes(term)) {
@@ -292,10 +282,7 @@ export function lexicalCorpusStatistics(toolSets, query) {
292
282
  }
293
283
  const documentFrequency = new Map(terms.map((term) => [
294
284
  term,
295
- new Set([
296
- ...(nameMatches.get(term) ?? []),
297
- ...(descriptionMatches.get(term) ?? []),
298
- ]).size,
285
+ new Set([...(nameMatches.get(term) ?? []), ...(descriptionMatches.get(term) ?? [])]).size,
299
286
  ]));
300
287
  return {
301
288
  documentCount: toolSets.reduce((total, tools) => total + tools.length, 0),
@@ -306,15 +293,12 @@ export function lexicalCorpusStatistics(toolSets, query) {
306
293
  }
307
294
  function inverseDocumentFrequency(term, statistics) {
308
295
  const frequency = statistics.documentFrequency.get(term) ?? 0;
309
- return Math.log(1 +
310
- (statistics.documentCount - frequency + 0.5) /
311
- (frequency + 0.5));
296
+ return Math.log(1 + (statistics.documentCount - frequency + 0.5) / (frequency + 0.5));
312
297
  }
313
298
  function scoreDocument(doc, phrase, terms, mode, statistics) {
314
299
  if (!phrase)
315
300
  return { score: 0, matchedTermCount: 0 };
316
- const matchedTerms = terms.filter((term) => statistics.nameMatches.get(term)?.has(doc.tool) ||
317
- statistics.descriptionMatches.get(term)?.has(doc.tool));
301
+ const matchedTerms = terms.filter((term) => statistics.nameMatches.get(term)?.has(doc.tool) || statistics.descriptionMatches.get(term)?.has(doc.tool));
318
302
  if (mode === "all" && matchedTerms.length !== terms.length)
319
303
  return null;
320
304
  if (matchedTerms.length === 0)
@@ -349,7 +333,7 @@ function scoreDocument(doc, phrase, terms, mode, statistics) {
349
333
  function queryContainsExactName(doc, phrase) {
350
334
  if (!doc.name || !phrase)
351
335
  return false;
352
- return (` ${phrase} `).includes(` ${doc.name} `);
336
+ return ` ${phrase} `.includes(` ${doc.name} `);
353
337
  }
354
338
  /**
355
339
  * Rank a connector's tools while caching its normalized plain-data index.
@@ -497,16 +481,13 @@ function renderConstraints(base, schema, byteLimit, onTruncated) {
497
481
  const kept = [];
498
482
  for (const entry of entries) {
499
483
  const candidate = ` /* ${[...kept, entry].join("; ")} */`;
500
- if (byteLimit !== undefined &&
501
- schemaEncoder.encode(candidate).length > byteLimit) {
484
+ if (byteLimit !== undefined && schemaEncoder.encode(candidate).length > byteLimit) {
502
485
  onTruncated?.();
503
486
  continue;
504
487
  }
505
488
  kept.push(entry);
506
489
  }
507
- return kept.length === 0
508
- ? base
509
- : `${grouped(base)} /* ${kept.join("; ")} */`;
490
+ return kept.length === 0 ? base : `${grouped(base)} /* ${kept.join("; ")} */`;
510
491
  }
511
492
  /**
512
493
  * `grouped` for the TypeScript dialect, whose JSDoc prose and string literals
@@ -535,8 +516,7 @@ function groupedType(part) {
535
516
  else if (char === "}" || char === ")" || char === "]" || char === ">") {
536
517
  nesting -= 1;
537
518
  }
538
- else if (nesting === 0 &&
539
- (part.startsWith(" | ", i) || part.startsWith(" & ", i))) {
519
+ else if (nesting === 0 && (part.startsWith(" | ", i) || part.startsWith(" & ", i))) {
540
520
  return `(${part})`;
541
521
  }
542
522
  }
@@ -557,9 +537,7 @@ function typescriptPrimitive(type) {
557
537
  return "unknown[]";
558
538
  if (type === "object")
559
539
  return "Record<string, unknown>";
560
- return ["string", "number", "boolean", "null"].includes(type)
561
- ? type
562
- : "unknown";
540
+ return ["string", "number", "boolean", "null"].includes(type) ? type : "unknown";
563
541
  }
564
542
  function boundedParts(work, separator, prefix, suffix) {
565
543
  // Check each addition before joining so a rejected schema never creates a
@@ -594,9 +572,7 @@ function renderSchemaNode(schema, defs, seen, depth, options) {
594
572
  const ungrouped = options.work.ungrouped;
595
573
  // A `[]` suffix binds tighter than `|` and `&`, so an element rendered at
596
574
  // operator level needs parentheses or it reads as its last member's array.
597
- const element = (rendered) => ts
598
- ? groupedType(rendered)
599
- : ungrouped.has(rendered) ? `(${rendered})` : rendered;
575
+ const element = (rendered) => ts ? groupedType(rendered) : ungrouped.has(rendered) ? `(${rendered})` : rendered;
600
576
  if (depth > 4) {
601
577
  if (!ts)
602
578
  return "…";
@@ -617,9 +593,7 @@ function renderSchemaNode(schema, defs, seen, depth, options) {
617
593
  if (key !== "nullable")
618
594
  base[key] = s[key];
619
595
  }
620
- const rendered = declaresShape(base)
621
- ? renderSchema(base, defs, seen, depth, options)
622
- : "unknown";
596
+ const rendered = declaresShape(base) ? renderSchema(base, defs, seen, depth, options) : "unknown";
623
597
  return rendered === "unknown" ? rendered : `${rendered} | null`;
624
598
  }
625
599
  const constrain = (rendered) => {
@@ -635,17 +609,14 @@ function renderSchemaNode(schema, defs, seen, depth, options) {
635
609
  };
636
610
  // Conditions cannot be expressed by a single static shape. Preserve the
637
611
  // base and send callers to the exact schema instead of hiding the rules.
638
- if (s.dependentSchemas !== undefined || s.if !== undefined ||
639
- s.then !== undefined || s.else !== undefined) {
612
+ if (s.dependentSchemas !== undefined || s.if !== undefined || s.then !== undefined || s.else !== undefined) {
640
613
  options.work.truncated = true;
641
614
  const base = Object.create(null);
642
615
  for (const key of propertyNames(s, options.work)) {
643
616
  if (!["dependentSchemas", "if", "then", "else"].includes(key))
644
617
  base[key] = s[key];
645
618
  }
646
- const rendered = declaresShape(base)
647
- ? renderSchema(base, defs, seen, depth, options)
648
- : "unknown";
619
+ const rendered = declaresShape(base) ? renderSchema(base, defs, seen, depth, options) : "unknown";
649
620
  const result = `${rendered} /* conditional */`;
650
621
  if (ungrouped.has(rendered))
651
622
  ungrouped.add(result);
@@ -666,9 +637,7 @@ function renderSchemaNode(schema, defs, seen, depth, options) {
666
637
  own[key] = s[key];
667
638
  }
668
639
  const parts = boundedParts(options.work, " & ", "", "");
669
- const groupParts = declaresShape(own)
670
- ? s.allOf.length > 0
671
- : s.allOf.length > 1;
640
+ const groupParts = declaresShape(own) ? s.allOf.length > 0 : s.allOf.length > 1;
672
641
  if (declaresShape(own)) {
673
642
  const rendered = renderSchema(own, defs, seen, depth, options);
674
643
  parts.add(groupParts ? group(rendered) : rendered);
@@ -771,17 +740,13 @@ function renderSchemaNode(schema, defs, seen, depth, options) {
771
740
  parts.add(renderSchema(item, defs, seen, depth + 1, options));
772
741
  }
773
742
  if (s.items !== false) {
774
- const rest = s.items === undefined || s.items === true
775
- ? "unknown"
776
- : renderSchema(s.items, defs, seen, depth + 1, options);
743
+ const rest = s.items === undefined || s.items === true ? "unknown" : renderSchema(s.items, defs, seen, depth + 1, options);
777
744
  parts.add(`...${element(rest)}[]`);
778
745
  }
779
746
  return parts.finish();
780
747
  }
781
748
  if (type === "array" || s.items) {
782
- const items = s.items
783
- ? renderSchema(s.items, defs, seen, depth + 1, options)
784
- : "unknown";
749
+ const items = s.items ? renderSchema(s.items, defs, seen, depth + 1, options) : "unknown";
785
750
  return `${element(items)}[]`;
786
751
  }
787
752
  if (type === "object" || s.properties) {
@@ -789,10 +754,7 @@ function renderSchemaNode(schema, defs, seen, depth, options) {
789
754
  const required = new Set(schemaRequired(s, options.work));
790
755
  const declaredKeys = propertyNames(props, options.work);
791
756
  const keys = options.requiredFirst
792
- ? [
793
- ...declaredKeys.filter((key) => required.has(key)),
794
- ...declaredKeys.filter((key) => !required.has(key)),
795
- ]
757
+ ? [...declaredKeys.filter((key) => required.has(key)), ...declaredKeys.filter((key) => !required.has(key))]
796
758
  : declaredKeys;
797
759
  const additional = s.additionalProperties;
798
760
  const index = ts && additional !== null && typeof additional === "object"
@@ -813,16 +775,13 @@ function renderSchemaNode(schema, defs, seen, depth, options) {
813
775
  }
814
776
  options.work.text(key);
815
777
  if (ts) {
816
- const doc = options.propertyDescriptions && typeof description === "string" &&
817
- description.trim()
778
+ const doc = options.propertyDescriptions && typeof description === "string" && description.trim()
818
779
  ? `/** ${typescriptDoc(description)} */ `
819
780
  : "";
820
781
  parts.add(`${doc}${typescriptKey(key)}${optional}: ${rendered}`);
821
782
  continue;
822
783
  }
823
- const comment = options.propertyDescriptions && typeof description === "string"
824
- ? ` // ${description}`
825
- : "";
784
+ const comment = options.propertyDescriptions && typeof description === "string" ? ` // ${description}` : "";
826
785
  parts.add(`${key}${optional}: ${rendered}${comment}`);
827
786
  }
828
787
  if (index !== undefined)
@@ -855,7 +814,9 @@ function resolveDefinition(schema, name) {
855
814
  const defs = schema.$defs;
856
815
  return definitions && Object.hasOwn(definitions, name)
857
816
  ? definitions[name]
858
- : defs && Object.hasOwn(defs, name) ? defs[name] : undefined;
817
+ : defs && Object.hasOwn(defs, name)
818
+ ? defs[name]
819
+ : undefined;
859
820
  }
860
821
  /** Render and cache a compact TypeScript-like representation of JSON Schema. */
861
822
  export function compactSchema(schema) {
@@ -884,7 +845,9 @@ function truncatedDiscoverySchema(schema, work) {
884
845
  try {
885
846
  keys = objectKeys(schema, schema, new Set(), 0, work);
886
847
  }
887
- catch { /* An exhausted walk has no reliable key inventory. */ }
848
+ catch {
849
+ /* An exhausted walk has no reliable key inventory. */
850
+ }
888
851
  if (!keys)
889
852
  return `unknown${COMPACT_DISCOVERY_TRUNCATION}`;
890
853
  const required = new Set(keys.required);
@@ -896,8 +859,7 @@ function truncatedDiscoverySchema(schema, work) {
896
859
  for (const key of ordered) {
897
860
  const part = `${JSON.stringify(key)}${required.has(key) ? "" : "?"}: unknown`;
898
861
  const candidate = `{ ${[...parts, part].join(", ")} }${COMPACT_DISCOVERY_TRUNCATION}`;
899
- if (schemaEncoder.encode(candidate).length >
900
- MAX_COMPACT_DISCOVERY_SCHEMA_BYTES) {
862
+ if (schemaEncoder.encode(candidate).length > MAX_COMPACT_DISCOVERY_SCHEMA_BYTES) {
901
863
  break;
902
864
  }
903
865
  parts.push(part);
@@ -954,16 +916,11 @@ const OBSERVED_OUTPUT_MARKER = "/* observed, not declared */ ";
954
916
  */
955
917
  export function typescriptSignature(input, output, options) {
956
918
  const renderedInput = typescriptType(input, options.description);
957
- const renderedOutput = output
958
- ? typescriptType(output, options.description)
959
- : undefined;
960
- const args = renderedInput.text === "{}" ||
961
- renderedInput.text === "Record<string, unknown>"
919
+ const renderedOutput = output ? typescriptType(output, options.description) : undefined;
920
+ const args = renderedInput.text === "{}" || renderedInput.text === "Record<string, unknown>"
962
921
  ? "args?: {}"
963
922
  : `args: ${renderedInput.text}`;
964
- const result = renderedOutput
965
- ? `${options.observed ? OBSERVED_OUTPUT_MARKER : ""}${renderedOutput.text}`
966
- : "unknown";
923
+ const result = renderedOutput ? `${options.observed ? OBSERVED_OUTPUT_MARKER : ""}${renderedOutput.text}` : "unknown";
967
924
  return {
968
925
  text: `(${args}) => Promise<${result}>`,
969
926
  inputTruncated: renderedInput.truncated,
@@ -978,10 +935,14 @@ function boundedCompactSchema(schema, description, typescript = false) {
978
935
  propertyDescriptions: description,
979
936
  requiredFirst: !description,
980
937
  enumByteLimit: description ? work.byteLimit : MAX_COMPACT_DISCOVERY_ENUM_BYTES,
981
- onEnumTruncated: () => { work.truncated = true; },
938
+ onEnumTruncated: () => {
939
+ work.truncated = true;
940
+ },
982
941
  renderConstraints: true,
983
942
  constraintByteLimit: description ? work.byteLimit : MAX_COMPACT_DISCOVERY_CONSTRAINT_BYTES,
984
- onConstraintTruncated: () => { work.truncated = true; },
943
+ onConstraintTruncated: () => {
944
+ work.truncated = true;
945
+ },
985
946
  };
986
947
  try {
987
948
  const text = renderSchema(schema, schema, new Set(), 0, options);
@@ -1002,7 +963,9 @@ function boundedCompactSchema(schema, description, typescript = false) {
1002
963
  truncated: true,
1003
964
  };
1004
965
  }
1005
- catch { /* Fall through to a bounded key-only shape. */ }
966
+ catch {
967
+ /* Fall through to a bounded key-only shape. */
968
+ }
1006
969
  }
1007
970
  return { text: truncatedDiscoverySchema(schema, work), truncated: true };
1008
971
  }
@@ -1054,9 +1017,7 @@ function objectKeys(schema, defs, seen, depth, work) {
1054
1017
  if (key !== "allOf")
1055
1018
  own[key] = s[key];
1056
1019
  }
1057
- const parts = declaresShape(own)
1058
- ? [objectKeys(own, defs, seen, depth, work)]
1059
- : [];
1020
+ const parts = declaresShape(own) ? [objectKeys(own, defs, seen, depth, work)] : [];
1060
1021
  for (const member of s.allOf) {
1061
1022
  const keys = objectKeys(member, defs, seen, depth + 1, work);
1062
1023
  if (!keys)
@@ -1065,9 +1026,7 @@ function objectKeys(schema, defs, seen, depth, work) {
1065
1026
  }
1066
1027
  // An allOf whose members are not all object shapes renders as an
1067
1028
  // intersection with a non-object half; no single key list describes it.
1068
- return parts.every((part) => part !== undefined)
1069
- ? mergedKeys(parts)
1070
- : undefined;
1029
+ return parts.every((part) => part !== undefined) ? mergedKeys(parts) : undefined;
1071
1030
  }
1072
1031
  const reference = s.$ref ?? s.$dynamicRef;
1073
1032
  if (typeof reference === "string") {
@@ -1,10 +1,9 @@
1
+ import { CONFIG_DEFAULTS } from "./config-defaults.js";
1
2
  import { Effect } from "effect";
2
3
  import { runEdge } from "./runtime/run.js";
3
- const DEFAULT_DISCOVERY_CONCURRENCY = 4;
4
+ const DEFAULT_DISCOVERY_CONCURRENCY = CONFIG_DEFAULTS.discovery.concurrency;
4
5
  export function resolveDiscoveryConcurrency(value) {
5
- return value !== undefined && Number.isInteger(value) && value > 0
6
- ? value
7
- : DEFAULT_DISCOVERY_CONCURRENCY;
6
+ return value !== undefined && Number.isInteger(value) && value > 0 ? value : DEFAULT_DISCOVERY_CONCURRENCY;
8
7
  }
9
8
  /**
10
9
  * Run `fn` over `items` with at most `limit` operations in flight, settling
@@ -0,0 +1,39 @@
1
+ export declare const CONFIG_DEFAULTS: {
2
+ readonly discovery: {
3
+ readonly concurrency: 4;
4
+ readonly catalogTtlSeconds: 300;
5
+ readonly catalogMinTtlSeconds: 0;
6
+ readonly catalogMaxTtlSeconds: 86400;
7
+ readonly probeTimeoutMs: 30000;
8
+ };
9
+ readonly calls: {
10
+ readonly maxResultBytes: 24000;
11
+ };
12
+ readonly results: {
13
+ readonly maxStashBytes: number;
14
+ readonly maxStashEntries: 64;
15
+ };
16
+ readonly execute: {
17
+ readonly maxEmittedBytes: 4000000;
18
+ readonly maxEmittedBlocks: 32;
19
+ readonly maxHostCalls: 20;
20
+ readonly hostCallTimeoutMs: 15000;
21
+ readonly watchdogMs: 120000;
22
+ readonly maxWrites: 10;
23
+ };
24
+ readonly admission: {
25
+ readonly requests: {
26
+ readonly concurrency: 16;
27
+ readonly maxQueueSize: 32;
28
+ readonly queueTimeoutMs: 5000;
29
+ readonly retryAfterMs: 1000;
30
+ readonly maxDurationMs: 300000;
31
+ };
32
+ readonly code: {
33
+ readonly concurrency: 2;
34
+ readonly maxQueueSize: 8;
35
+ readonly queueTimeoutMs: 5000;
36
+ readonly retryAfterMs: 1000;
37
+ };
38
+ };
39
+ };
@@ -0,0 +1,46 @@
1
+ // Every configuration default, defined once.
2
+ //
3
+ // The schema in src/config.ts applies these when a deployment omits a value,
4
+ // and `describeConfig()` reports them as `source: "default"`. The modules that
5
+ // enforce each bound read the same numbers for the fallbacks their own
6
+ // constructors keep, so a test that builds a Registry or an execute tool
7
+ // directly sees the deployment's defaults rather than a second copy of them.
8
+ export const CONFIG_DEFAULTS = {
9
+ discovery: {
10
+ concurrency: 4,
11
+ catalogTtlSeconds: 300,
12
+ catalogMinTtlSeconds: 0,
13
+ catalogMaxTtlSeconds: 86_400,
14
+ probeTimeoutMs: 30_000,
15
+ },
16
+ calls: {
17
+ maxResultBytes: 24_000,
18
+ },
19
+ results: {
20
+ maxStashBytes: 8 * 1024 * 1024,
21
+ maxStashEntries: 64,
22
+ },
23
+ execute: {
24
+ maxEmittedBytes: 4_000_000,
25
+ maxEmittedBlocks: 32,
26
+ maxHostCalls: 20,
27
+ hostCallTimeoutMs: 15_000,
28
+ watchdogMs: 120_000,
29
+ maxWrites: 10,
30
+ },
31
+ admission: {
32
+ requests: {
33
+ concurrency: 16,
34
+ maxQueueSize: 32,
35
+ queueTimeoutMs: 5_000,
36
+ retryAfterMs: 1_000,
37
+ maxDurationMs: 300_000,
38
+ },
39
+ code: {
40
+ concurrency: 2,
41
+ maxQueueSize: 8,
42
+ queueTimeoutMs: 5_000,
43
+ retryAfterMs: 1_000,
44
+ },
45
+ },
46
+ };
@@ -0,0 +1,181 @@
1
+ /** One configuration field: its input type, resolved type, and optionality. */
2
+ export interface Field<In, Out, Opt extends boolean = boolean> {
3
+ /** Whether a deployment may omit the field. */
4
+ readonly optional: Opt;
5
+ /** Resolve a present (own, not `undefined`) value or throw. */
6
+ readonly parse: (value: unknown, path: string) => Out;
7
+ /** Resolve an omitted value: its default, `undefined`, or a throw. */
8
+ readonly absent: (path: string) => Out;
9
+ /** Child fields of a closed object, walked for unknown keys. */
10
+ readonly shape?: Shape;
11
+ /** Element field of an array or record, walked for unknown keys. */
12
+ readonly element?: Field<unknown, unknown>;
13
+ /** Whether `element` describes record values rather than array items. */
14
+ readonly keyed?: boolean;
15
+ /** Closed object shapes chosen by the string at one key, walked for unknown keys. */
16
+ readonly variants?: Variants;
17
+ /** Whether a closed object carries behaviour, so the walk returns it as given. */
18
+ readonly instance?: boolean;
19
+ /** Whether a record's values must be strings: header values, extra parameters. */
20
+ readonly strings?: boolean;
21
+ /** Phantom input type; never set. */
22
+ readonly __in?: In;
23
+ }
24
+ type AnyField = Field<any, any, boolean>;
25
+ export type Shape = {
26
+ readonly [key: string]: AnyField;
27
+ };
28
+ /** A discriminated union of closed objects: `cases[value[key]]`, else `cases[otherwise]`. */
29
+ interface Variants {
30
+ readonly key: string;
31
+ readonly cases: Readonly<Record<string, Shape>>;
32
+ readonly otherwise?: string;
33
+ }
34
+ type InputOf<F> = F extends Field<infer In, unknown, boolean> ? In : never;
35
+ type OutputOf<F> = F extends Field<unknown, infer Out, boolean> ? Out : never;
36
+ type Simplify<T> = {
37
+ [K in keyof T]: T[K];
38
+ } & {};
39
+ /**
40
+ * What a deployment writes for an object schema. Optional fields also accept
41
+ * an explicit `undefined`, so an optional module can be wired as
42
+ * `vault: key ? encryptedCredentialVault(storage, key) : undefined`.
43
+ */
44
+ export type ConfigInput<S extends Shape> = Simplify<{
45
+ -readonly [K in keyof S as S[K]["optional"] extends true ? K : never]?: InputOf<S[K]> | undefined;
46
+ } & {
47
+ -readonly [K in keyof S as S[K]["optional"] extends true ? never : K]: InputOf<S[K]>;
48
+ }>;
49
+ /** What core reads for an object schema: every default already applied. */
50
+ export type ConfigOutput<S extends Shape> = Simplify<{
51
+ readonly [K in keyof S]: OutputOf<S[K]>;
52
+ }>;
53
+ /** A structural configuration mistake, thrown before construction does work. */
54
+ export declare class ConfigError extends TypeError {
55
+ readonly name = "ConfigError";
56
+ }
57
+ interface WholeOptions {
58
+ /** Smallest accepted value. */
59
+ min: 0 | 1;
60
+ /** Largest accepted value, when there is one. */
61
+ max?: number;
62
+ /** Unit named in the `max` refusal, e.g. "milliseconds". */
63
+ unit?: string;
64
+ }
65
+ /** A safe integer at or above `min`; the default applies only when omitted. */
66
+ export declare function whole(options: WholeOptions & {
67
+ default: number;
68
+ }): Field<number, number, true>;
69
+ export declare function whole(options: WholeOptions): Field<number, number | undefined, true>;
70
+ /** A non-negative finite number, fractions allowed. */
71
+ export declare function seconds(options: {
72
+ default: number;
73
+ }): Field<number, number, true>;
74
+ export declare function text(): Field<string, string | undefined, true>;
75
+ /**
76
+ * A value core checks by shape and passes through untouched: a connector, a
77
+ * module, an executor. `check` throws its own message for a wrong value;
78
+ * `resolve` maps the accepted value (or `undefined`, when omitted) to what
79
+ * core reads.
80
+ */
81
+ export declare function opaque<In, Out = In | undefined>(options?: {
82
+ check?: (value: unknown, path: string) => void;
83
+ resolve?: (value: In | undefined) => Out;
84
+ }): Field<In, Out, true>;
85
+ /** A function, never called, read, or serialized by configuration. */
86
+ export declare function fn<F extends (...args: never[]) => unknown>(): Field<F, F | undefined, true>;
87
+ /** The same field, but a deployment must supply it. */
88
+ export declare function required<In, Out>(field: Field<In, Out, boolean>, message?: (path: string) => string): Field<In, Exclude<Out, undefined>, false>;
89
+ /**
90
+ * A closed object. Its keys are the shape's keys; anything else is refused
91
+ * by the unknown-key walk before any value is read. An omitted object
92
+ * resolves to its children's defaults.
93
+ */
94
+ export declare function object<S extends Shape>(shape: S): Field<ConfigInput<S>, ConfigOutput<S>, true> & {
95
+ readonly shape: S;
96
+ };
97
+ /** A list whose items each satisfy `item`. */
98
+ export declare function array<In, Out>(item: Field<In, Out, boolean>): Field<In[], readonly Exclude<Out, undefined>[] | undefined, true>;
99
+ /** An object keyed by caller-chosen names, each value satisfying `value`. */
100
+ export declare function record<In, Out>(value: Field<In, Out, boolean>): Field<Record<string, In>, Readonly<Record<string, Exclude<Out, undefined>>> | undefined, true>;
101
+ /**
102
+ * A map of caller-chosen names to strings, such as static headers or extra
103
+ * OAuth parameters. The walk copies it through property descriptors, so an
104
+ * accessor is refused by path unrun and a non-string value by path unechoed.
105
+ */
106
+ export declare function strings(): Field<Record<string, string>, Readonly<Record<string, string>> | undefined, true>;
107
+ /**
108
+ * A closed object that carries behaviour, such as an `api()` tool. The walk
109
+ * checks it like any closed object (own keys declared, no own accessor, and
110
+ * no inherited accessor at a declared key) but returns the original rather
111
+ * than a copy, so a prototype method keeps its receiver and a handler that
112
+ * reads `#private` fields still finds them. It may be a class instance.
113
+ */
114
+ export declare function instance<F extends AnyField>(field: F): F & {
115
+ readonly instance: true;
116
+ };
117
+ /**
118
+ * A closed object whose allowed keys depend on a discriminant, such as
119
+ * `remoteMcp({ auth: { type: "headers", headers } })`. An omitted
120
+ * discriminant selects `otherwise` when given; an omitted one without it, an
121
+ * unrecognized one, or a value that is not an object throws with its path and
122
+ * the valid values, so no union falls through to "no case". Only the walk
123
+ * reads variants; the factory validates the remaining values itself.
124
+ */
125
+ export declare function variants(key: string, cases: Readonly<Record<string, Shape>>, otherwise?: string): Field<unknown, unknown, true>;
126
+ /**
127
+ * A closed object for the unknown-key walk only: each named key may hold
128
+ * anything, which its factory validates. For the options of a built-in
129
+ * factory, where `object()` would resolve values the factory already owns.
130
+ */
131
+ export declare function keys<const K extends string>(...names: K[]): {
132
+ readonly [P in K]: Field<unknown, unknown, true>;
133
+ };
134
+ /** Every key of every member of a union, so a shape can be checked against it. */
135
+ type KeysOfUnion<T> = T extends unknown ? keyof T : never;
136
+ /**
137
+ * The closed options of a built-in factory, checked against its options type:
138
+ * a key the type declares but the shape omits, or the reverse, fails to
139
+ * compile, so the runtime walk cannot drift from the published type.
140
+ */
141
+ export declare function optionsOf<T>(): <S extends { readonly [K in Exclude<KeysOfUnion<T>, symbol>]-?: AnyField; }>(shape: S & Record<Exclude<keyof S, KeysOfUnion<T>>, never>) => Field<unknown, unknown, true> & {
142
+ readonly shape: S;
143
+ };
144
+ /**
145
+ * Refuse a factory's unknown options and accessors before it reads any value,
146
+ * naming each path: `api("crm").maxResultByte`. Returns the options as a
147
+ * plain copy read through property descriptors, which the factory reads in
148
+ * place of what it was given, so no getter or Proxy trap of the caller's runs
149
+ * later either. Custom implementations a factory accepts (stores, handlers,
150
+ * executors) are `opaque()` in its shape and pass through untouched; an
151
+ * object that carries behaviour (an `api()` tool) is `instance()`, checked in
152
+ * place and passed through as given.
153
+ */
154
+ export declare function assertKnownOptions<T>(value: T, path: string, field: AnyField): T;
155
+ /**
156
+ * Read a configuration value the way the schema sees it: every own key it
157
+ * does not declare, as paths, and the value as a plain copy built only from
158
+ * the property descriptors this walk inspected. Callers resolve that copy,
159
+ * never the original, so no property is read through `[[Get]]` twice or at
160
+ * all: no getter runs, a Proxy's `get` trap never fires, and no value is
161
+ * echoed.
162
+ *
163
+ * Unknown keys anywhere are reported first. With none, a declared key holding
164
+ * an accessor is refused by path, since a plain configuration object has no
165
+ * reason to compute a value, and a getter that throws or changes between
166
+ * reads would break the one-read guarantee. Only own string keys count, so a
167
+ * prototype contributes nothing. A closed object or record slot takes a
168
+ * plain object only; an array or class instance there is refused by path.
169
+ * Arrays are walked by the same rules, the items of an `opaque()` array
170
+ * included (`allowedOrigins`, `auth`); an `instance()` object (an `api()`
171
+ * tool) is checked the same way but returned as given; any other `opaque()`
172
+ * value (a connector, module, executor, storage, or logger) is never entered
173
+ * and passes through as configured. Configuration is operator-authored and
174
+ * trusted: the walk refuses mistakes by path without echoing a value; it is
175
+ * not a sandbox for hostile objects.
176
+ */
177
+ export declare function readPlain(value: unknown, path: string, field: AnyField): {
178
+ unknown: string[];
179
+ value: unknown;
180
+ };
181
+ export {};