@noodleseed/one 0.68.0 → 0.69.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 (278) hide show
  1. package/dist/agents.d.ts +8 -3
  2. package/dist/agents.d.ts.map +1 -1
  3. package/dist/agents.js +20 -14
  4. package/dist/agents.js.map +1 -1
  5. package/dist/cli.js +2 -2
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/analytics-ops.d.ts +3 -1
  8. package/dist/commands/analytics-ops.d.ts.map +1 -1
  9. package/dist/commands/analytics-ops.js +31 -5
  10. package/dist/commands/analytics-ops.js.map +1 -1
  11. package/dist/commands/catalog-data-resources.d.ts.map +1 -1
  12. package/dist/commands/catalog-data-resources.js +10 -0
  13. package/dist/commands/catalog-data-resources.js.map +1 -1
  14. package/dist/commands/envs-ops.d.ts +1 -0
  15. package/dist/commands/envs-ops.d.ts.map +1 -1
  16. package/dist/commands/envs-ops.js +49 -1
  17. package/dist/commands/envs-ops.js.map +1 -1
  18. package/dist/commands/project-setup.d.ts +3 -2
  19. package/dist/commands/project-setup.d.ts.map +1 -1
  20. package/dist/commands/project-setup.js +5 -5
  21. package/dist/commands/project-setup.js.map +1 -1
  22. package/dist/commands/resource-shared.d.ts +11 -0
  23. package/dist/commands/resource-shared.d.ts.map +1 -1
  24. package/dist/commands/resource-shared.js.map +1 -1
  25. package/dist/deploy.js +1 -1
  26. package/dist/deploy.js.map +1 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +1 -1
  30. package/dist/index.js.map +1 -1
  31. package/node_modules/@noodle-borg/agent-kit/dist/curated/error-fixes.d.ts.map +1 -1
  32. package/node_modules/@noodle-borg/agent-kit/dist/curated/error-fixes.js +4 -0
  33. package/node_modules/@noodle-borg/agent-kit/dist/curated/error-fixes.js.map +1 -1
  34. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.d.ts.map +1 -1
  35. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +8 -1
  36. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js.map +1 -1
  37. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.d.ts.map +1 -1
  38. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +10 -0
  39. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js.map +1 -1
  40. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.d.ts.map +1 -1
  41. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +7 -1
  42. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js.map +1 -1
  43. package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js +1 -1
  44. package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js.map +1 -1
  45. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  46. package/node_modules/@noodle-borg/authoring/dist/connection-types.d.ts +52 -0
  47. package/node_modules/@noodle-borg/authoring/dist/connection-types.d.ts.map +1 -0
  48. package/node_modules/@noodle-borg/authoring/dist/connection-types.js +35 -0
  49. package/node_modules/@noodle-borg/authoring/dist/connection-types.js.map +1 -0
  50. package/node_modules/@noodle-borg/authoring/dist/connections.d.ts +26 -0
  51. package/node_modules/@noodle-borg/authoring/dist/connections.d.ts.map +1 -0
  52. package/node_modules/@noodle-borg/authoring/dist/connections.js +63 -0
  53. package/node_modules/@noodle-borg/authoring/dist/connections.js.map +1 -0
  54. package/node_modules/@noodle-borg/authoring/dist/connectors.d.ts +18 -7
  55. package/node_modules/@noodle-borg/authoring/dist/connectors.d.ts.map +1 -1
  56. package/node_modules/@noodle-borg/authoring/dist/connectors.js +26 -4
  57. package/node_modules/@noodle-borg/authoring/dist/connectors.js.map +1 -1
  58. package/node_modules/@noodle-borg/authoring/dist/gmail.d.ts +7 -0
  59. package/node_modules/@noodle-borg/authoring/dist/gmail.d.ts.map +1 -0
  60. package/node_modules/@noodle-borg/authoring/dist/gmail.js +257 -0
  61. package/node_modules/@noodle-borg/authoring/dist/gmail.js.map +1 -0
  62. package/node_modules/@noodle-borg/authoring/dist/index.d.ts +2 -0
  63. package/node_modules/@noodle-borg/authoring/dist/index.d.ts.map +1 -1
  64. package/node_modules/@noodle-borg/authoring/dist/index.js +2 -0
  65. package/node_modules/@noodle-borg/authoring/dist/index.js.map +1 -1
  66. package/node_modules/@noodle-borg/authoring/dist/platform.d.ts +1 -1
  67. package/node_modules/@noodle-borg/authoring/dist/react/components.d.ts +2 -2
  68. package/node_modules/@noodle-borg/authoring/dist/react/native-components.d.ts +2 -2
  69. package/node_modules/@noodle-borg/authoring/dist/recording.d.ts +2 -0
  70. package/node_modules/@noodle-borg/authoring/dist/recording.d.ts.map +1 -1
  71. package/node_modules/@noodle-borg/authoring/dist/recording.js +6 -0
  72. package/node_modules/@noodle-borg/authoring/dist/recording.js.map +1 -1
  73. package/node_modules/@noodle-borg/authoring/dist/server.d.ts.map +1 -1
  74. package/node_modules/@noodle-borg/authoring/dist/server.js +4 -1
  75. package/node_modules/@noodle-borg/authoring/dist/server.js.map +1 -1
  76. package/node_modules/@noodle-borg/authoring/package.json +1 -1
  77. package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +43 -1
  78. package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts.map +1 -1
  79. package/node_modules/@noodle-borg/compiler/dist/artifact/types.js +4 -1
  80. package/node_modules/@noodle-borg/compiler/dist/artifact/types.js.map +1 -1
  81. package/node_modules/@noodle-borg/compiler/dist/catalog/types.d.ts +15 -0
  82. package/node_modules/@noodle-borg/compiler/dist/catalog/types.d.ts.map +1 -1
  83. package/node_modules/@noodle-borg/compiler/dist/compile.d.ts.map +1 -1
  84. package/node_modules/@noodle-borg/compiler/dist/compile.js +3 -1
  85. package/node_modules/@noodle-borg/compiler/dist/compile.js.map +1 -1
  86. package/node_modules/@noodle-borg/compiler/dist/confirmation-flow.d.ts +3 -3
  87. package/node_modules/@noodle-borg/compiler/dist/confirmation-flow.d.ts.map +1 -1
  88. package/node_modules/@noodle-borg/compiler/dist/confirmation-flow.js +16 -17
  89. package/node_modules/@noodle-borg/compiler/dist/confirmation-flow.js.map +1 -1
  90. package/node_modules/@noodle-borg/compiler/dist/context-compile.d.ts +2 -4
  91. package/node_modules/@noodle-borg/compiler/dist/context-compile.d.ts.map +1 -1
  92. package/node_modules/@noodle-borg/compiler/dist/context-compile.js.map +1 -1
  93. package/node_modules/@noodle-borg/compiler/dist/errors.d.ts +1 -1
  94. package/node_modules/@noodle-borg/compiler/dist/errors.d.ts.map +1 -1
  95. package/node_modules/@noodle-borg/compiler/dist/fulfilment-emit.d.ts +17 -5
  96. package/node_modules/@noodle-borg/compiler/dist/fulfilment-emit.d.ts.map +1 -1
  97. package/node_modules/@noodle-borg/compiler/dist/fulfilment-emit.js +89 -0
  98. package/node_modules/@noodle-borg/compiler/dist/fulfilment-emit.js.map +1 -1
  99. package/node_modules/@noodle-borg/compiler/dist/index.d.ts +3 -2
  100. package/node_modules/@noodle-borg/compiler/dist/index.d.ts.map +1 -1
  101. package/node_modules/@noodle-borg/compiler/dist/index.js +1 -0
  102. package/node_modules/@noodle-borg/compiler/dist/index.js.map +1 -1
  103. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +66 -16
  104. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts.map +1 -1
  105. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +47 -4
  106. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js.map +1 -1
  107. package/node_modules/@noodle-borg/connector-defs/dist/compile.d.ts.map +1 -1
  108. package/node_modules/@noodle-borg/connector-defs/dist/compile.js +3 -0
  109. package/node_modules/@noodle-borg/connector-defs/dist/compile.js.map +1 -1
  110. package/node_modules/@noodle-borg/connector-defs/dist/credential-profiles.d.ts +6 -0
  111. package/node_modules/@noodle-borg/connector-defs/dist/credential-profiles.d.ts.map +1 -0
  112. package/node_modules/@noodle-borg/connector-defs/dist/credential-profiles.js +25 -0
  113. package/node_modules/@noodle-borg/connector-defs/dist/credential-profiles.js.map +1 -0
  114. package/node_modules/@noodle-borg/connector-defs/dist/index.d.ts +1 -1
  115. package/node_modules/@noodle-borg/connector-defs/dist/index.d.ts.map +1 -1
  116. package/node_modules/@noodle-borg/connector-defs/dist/index.js.map +1 -1
  117. package/node_modules/@noodle-borg/connector-defs/dist/schema.d.ts +89 -0
  118. package/node_modules/@noodle-borg/connector-defs/dist/schema.d.ts.map +1 -1
  119. package/node_modules/@noodle-borg/connector-defs/dist/schema.js +42 -1
  120. package/node_modules/@noodle-borg/connector-defs/dist/schema.js.map +1 -1
  121. package/node_modules/@noodle-borg/connector-http/dist/http-connector.d.ts.map +1 -1
  122. package/node_modules/@noodle-borg/connector-http/dist/http-connector.js +5 -4
  123. package/node_modules/@noodle-borg/connector-http/dist/http-connector.js.map +1 -1
  124. package/node_modules/@noodle-borg/external-credential-provider/README.md +18 -0
  125. package/node_modules/@noodle-borg/external-credential-provider/dist/assertion.d.ts +36 -0
  126. package/node_modules/@noodle-borg/external-credential-provider/dist/assertion.d.ts.map +1 -0
  127. package/node_modules/@noodle-borg/external-credential-provider/dist/assertion.js +72 -0
  128. package/node_modules/@noodle-borg/external-credential-provider/dist/assertion.js.map +1 -0
  129. package/node_modules/@noodle-borg/external-credential-provider/dist/contract.d.ts +82 -0
  130. package/node_modules/@noodle-borg/external-credential-provider/dist/contract.d.ts.map +1 -0
  131. package/node_modules/@noodle-borg/external-credential-provider/dist/contract.js +126 -0
  132. package/node_modules/@noodle-borg/external-credential-provider/dist/contract.js.map +1 -0
  133. package/node_modules/@noodle-borg/external-credential-provider/dist/index.d.ts +4 -0
  134. package/node_modules/@noodle-borg/external-credential-provider/dist/index.d.ts.map +1 -0
  135. package/node_modules/@noodle-borg/external-credential-provider/dist/index.js +4 -0
  136. package/node_modules/@noodle-borg/external-credential-provider/dist/index.js.map +1 -0
  137. package/node_modules/@noodle-borg/external-credential-provider/dist/provider.d.ts +15 -0
  138. package/node_modules/@noodle-borg/external-credential-provider/dist/provider.d.ts.map +1 -0
  139. package/node_modules/@noodle-borg/external-credential-provider/dist/provider.js +24 -0
  140. package/node_modules/@noodle-borg/external-credential-provider/dist/provider.js.map +1 -0
  141. package/node_modules/@noodle-borg/external-credential-provider/package.json +33 -0
  142. package/node_modules/@noodle-borg/module/dist/contract.d.ts +14 -0
  143. package/node_modules/@noodle-borg/module/dist/contract.d.ts.map +1 -1
  144. package/node_modules/@noodle-borg/module/dist/contract.js.map +1 -1
  145. package/node_modules/@noodle-borg/protocol/dist/tool-interaction.d.ts.map +1 -1
  146. package/node_modules/@noodle-borg/protocol/dist/tool-interaction.js +1 -8
  147. package/node_modules/@noodle-borg/protocol/dist/tool-interaction.js.map +1 -1
  148. package/node_modules/@noodle-borg/runtime/dist/broker/map.d.ts +8 -4
  149. package/node_modules/@noodle-borg/runtime/dist/broker/map.d.ts.map +1 -1
  150. package/node_modules/@noodle-borg/runtime/dist/broker/map.js +35 -5
  151. package/node_modules/@noodle-borg/runtime/dist/broker/map.js.map +1 -1
  152. package/node_modules/@noodle-borg/runtime/dist/broker/types.d.ts +34 -1
  153. package/node_modules/@noodle-borg/runtime/dist/broker/types.d.ts.map +1 -1
  154. package/node_modules/@noodle-borg/runtime/dist/broker/types.js +38 -0
  155. package/node_modules/@noodle-borg/runtime/dist/broker/types.js.map +1 -1
  156. package/node_modules/@noodle-borg/runtime/dist/confirmation-analysis.d.ts +28 -0
  157. package/node_modules/@noodle-borg/runtime/dist/confirmation-analysis.d.ts.map +1 -0
  158. package/node_modules/@noodle-borg/runtime/dist/confirmation-analysis.js +143 -0
  159. package/node_modules/@noodle-borg/runtime/dist/confirmation-analysis.js.map +1 -0
  160. package/node_modules/@noodle-borg/runtime/dist/confirmation-continuation.d.ts +6 -0
  161. package/node_modules/@noodle-borg/runtime/dist/confirmation-continuation.d.ts.map +1 -0
  162. package/node_modules/@noodle-borg/runtime/dist/confirmation-continuation.js +56 -0
  163. package/node_modules/@noodle-borg/runtime/dist/confirmation-continuation.js.map +1 -0
  164. package/node_modules/@noodle-borg/runtime/dist/confirmation.d.ts.map +1 -1
  165. package/node_modules/@noodle-borg/runtime/dist/confirmation.js +71 -74
  166. package/node_modules/@noodle-borg/runtime/dist/confirmation.js.map +1 -1
  167. package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +3 -1
  168. package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts.map +1 -1
  169. package/node_modules/@noodle-borg/runtime/dist/connector/types.js.map +1 -1
  170. package/node_modules/@noodle-borg/runtime/dist/connector-snapshot.d.ts +8 -0
  171. package/node_modules/@noodle-borg/runtime/dist/connector-snapshot.d.ts.map +1 -0
  172. package/node_modules/@noodle-borg/runtime/dist/connector-snapshot.js +89 -0
  173. package/node_modules/@noodle-borg/runtime/dist/connector-snapshot.js.map +1 -0
  174. package/node_modules/@noodle-borg/runtime/dist/execute.d.ts +2 -0
  175. package/node_modules/@noodle-borg/runtime/dist/execute.d.ts.map +1 -1
  176. package/node_modules/@noodle-borg/runtime/dist/execute.js +24 -0
  177. package/node_modules/@noodle-borg/runtime/dist/execute.js.map +1 -1
  178. package/node_modules/@noodle-borg/runtime/dist/index.d.ts +1 -1
  179. package/node_modules/@noodle-borg/runtime/dist/index.d.ts.map +1 -1
  180. package/node_modules/@noodle-borg/runtime/dist/index.js +1 -1
  181. package/node_modules/@noodle-borg/runtime/dist/index.js.map +1 -1
  182. package/node_modules/@noodle-borg/runtime/dist/result.d.ts +8 -0
  183. package/node_modules/@noodle-borg/runtime/dist/result.d.ts.map +1 -1
  184. package/node_modules/@noodle-borg/runtime/dist/result.js.map +1 -1
  185. package/node_modules/@noodle-borg/service/dist/credential-binding-index.d.ts +15 -0
  186. package/node_modules/@noodle-borg/service/dist/credential-binding-index.d.ts.map +1 -0
  187. package/node_modules/@noodle-borg/service/dist/credential-binding-index.js +66 -0
  188. package/node_modules/@noodle-borg/service/dist/credential-binding-index.js.map +1 -0
  189. package/node_modules/@noodle-borg/service/dist/credential-broker-options.d.ts +13 -0
  190. package/node_modules/@noodle-borg/service/dist/credential-broker-options.d.ts.map +1 -0
  191. package/node_modules/@noodle-borg/service/dist/credential-broker-options.js +26 -0
  192. package/node_modules/@noodle-borg/service/dist/credential-broker-options.js.map +1 -0
  193. package/node_modules/@noodle-borg/service/dist/credential-broker.d.ts +5 -0
  194. package/node_modules/@noodle-borg/service/dist/credential-broker.d.ts.map +1 -1
  195. package/node_modules/@noodle-borg/service/dist/credential-broker.js +43 -45
  196. package/node_modules/@noodle-borg/service/dist/credential-broker.js.map +1 -1
  197. package/node_modules/@noodle-borg/service/dist/credential-probes.d.ts +13 -0
  198. package/node_modules/@noodle-borg/service/dist/credential-probes.d.ts.map +1 -0
  199. package/node_modules/@noodle-borg/service/dist/credential-probes.js +88 -0
  200. package/node_modules/@noodle-borg/service/dist/credential-probes.js.map +1 -0
  201. package/node_modules/@noodle-borg/service/dist/external-credential-binding-broker.d.ts +12 -0
  202. package/node_modules/@noodle-borg/service/dist/external-credential-binding-broker.d.ts.map +1 -0
  203. package/node_modules/@noodle-borg/service/dist/external-credential-binding-broker.js +111 -0
  204. package/node_modules/@noodle-borg/service/dist/external-credential-binding-broker.js.map +1 -0
  205. package/node_modules/@noodle-borg/service/dist/external-credential-exchange.d.ts +82 -0
  206. package/node_modules/@noodle-borg/service/dist/external-credential-exchange.d.ts.map +1 -0
  207. package/node_modules/@noodle-borg/service/dist/external-credential-exchange.js +184 -0
  208. package/node_modules/@noodle-borg/service/dist/external-credential-exchange.js.map +1 -0
  209. package/node_modules/@noodle-borg/service/dist/index.d.ts +1 -0
  210. package/node_modules/@noodle-borg/service/dist/index.d.ts.map +1 -1
  211. package/node_modules/@noodle-borg/service/dist/index.js +1 -0
  212. package/node_modules/@noodle-borg/service/dist/index.js.map +1 -1
  213. package/node_modules/@noodle-borg/service/dist/registry-state.d.ts +3 -1
  214. package/node_modules/@noodle-borg/service/dist/registry-state.d.ts.map +1 -1
  215. package/node_modules/@noodle-borg/service/dist/registry-state.js +27 -2
  216. package/node_modules/@noodle-borg/service/dist/registry-state.js.map +1 -1
  217. package/node_modules/@noodle-borg/service/dist/registry-types.d.ts +7 -0
  218. package/node_modules/@noodle-borg/service/dist/registry-types.d.ts.map +1 -1
  219. package/node_modules/@noodle-borg/service/dist/registry.d.ts +2 -1
  220. package/node_modules/@noodle-borg/service/dist/registry.d.ts.map +1 -1
  221. package/node_modules/@noodle-borg/service/dist/registry.js +23 -27
  222. package/node_modules/@noodle-borg/service/dist/registry.js.map +1 -1
  223. package/node_modules/@noodle-borg/service/dist/routes/contracts.d.ts +16 -0
  224. package/node_modules/@noodle-borg/service/dist/routes/contracts.d.ts.map +1 -1
  225. package/node_modules/@noodle-borg/service/dist/routes/contracts.js +16 -0
  226. package/node_modules/@noodle-borg/service/dist/routes/contracts.js.map +1 -1
  227. package/node_modules/@noodle-borg/service/dist/routes/environment-mutation-dispatch.d.ts +19 -0
  228. package/node_modules/@noodle-borg/service/dist/routes/environment-mutation-dispatch.d.ts.map +1 -0
  229. package/node_modules/@noodle-borg/service/dist/routes/environment-mutation-dispatch.js +16 -0
  230. package/node_modules/@noodle-borg/service/dist/routes/environment-mutation-dispatch.js.map +1 -0
  231. package/node_modules/@noodle-borg/service/dist/routes/environment-production.d.ts +8 -0
  232. package/node_modules/@noodle-borg/service/dist/routes/environment-production.d.ts.map +1 -0
  233. package/node_modules/@noodle-borg/service/dist/routes/environment-production.js +46 -0
  234. package/node_modules/@noodle-borg/service/dist/routes/environment-production.js.map +1 -0
  235. package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts +1 -0
  236. package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts.map +1 -1
  237. package/node_modules/@noodle-borg/service/dist/routes/paths.js +3 -0
  238. package/node_modules/@noodle-borg/service/dist/routes/paths.js.map +1 -1
  239. package/node_modules/@noodle-borg/service/dist/serve-options.d.ts +8 -0
  240. package/node_modules/@noodle-borg/service/dist/serve-options.d.ts.map +1 -1
  241. package/node_modules/@noodle-borg/service/dist/serve.d.ts.map +1 -1
  242. package/node_modules/@noodle-borg/service/dist/serve.js +3 -0
  243. package/node_modules/@noodle-borg/service/dist/serve.js.map +1 -1
  244. package/node_modules/@noodle-borg/service/dist/service.d.ts.map +1 -1
  245. package/node_modules/@noodle-borg/service/dist/service.js +13 -0
  246. package/node_modules/@noodle-borg/service/dist/service.js.map +1 -1
  247. package/node_modules/@noodle-borg/service/dist/store/environment-production.d.ts +9 -0
  248. package/node_modules/@noodle-borg/service/dist/store/environment-production.d.ts.map +1 -0
  249. package/node_modules/@noodle-borg/service/dist/store/environment-production.js +2 -0
  250. package/node_modules/@noodle-borg/service/dist/store/environment-production.js.map +1 -0
  251. package/node_modules/@noodle-borg/service/dist/store/in-memory.d.ts +2 -1
  252. package/node_modules/@noodle-borg/service/dist/store/in-memory.d.ts.map +1 -1
  253. package/node_modules/@noodle-borg/service/dist/store/in-memory.js +31 -2
  254. package/node_modules/@noodle-borg/service/dist/store/in-memory.js.map +1 -1
  255. package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts +2 -1
  256. package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts.map +1 -1
  257. package/node_modules/@noodle-borg/service/dist/store/json-file.js +64 -2
  258. package/node_modules/@noodle-borg/service/dist/store/json-file.js.map +1 -1
  259. package/node_modules/@noodle-borg/service/dist/store/postgres-envs.d.ts +2 -1
  260. package/node_modules/@noodle-borg/service/dist/store/postgres-envs.d.ts.map +1 -1
  261. package/node_modules/@noodle-borg/service/dist/store/postgres-envs.js +53 -7
  262. package/node_modules/@noodle-borg/service/dist/store/postgres-envs.js.map +1 -1
  263. package/node_modules/@noodle-borg/service/dist/store/postgres-schema.d.ts.map +1 -1
  264. package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js +48 -0
  265. package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js.map +1 -1
  266. package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts +2 -1
  267. package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts.map +1 -1
  268. package/node_modules/@noodle-borg/service/dist/store/postgres.js +8 -2
  269. package/node_modules/@noodle-borg/service/dist/store/postgres.js.map +1 -1
  270. package/node_modules/@noodle-borg/service/dist/store/records.d.ts +5 -2
  271. package/node_modules/@noodle-borg/service/dist/store/records.d.ts.map +1 -1
  272. package/node_modules/@noodle-borg/service/dist/store/records.js +18 -4
  273. package/node_modules/@noodle-borg/service/dist/store/records.js.map +1 -1
  274. package/node_modules/@noodle-borg/service/dist/store.d.ts +8 -2
  275. package/node_modules/@noodle-borg/service/dist/store.d.ts.map +1 -1
  276. package/node_modules/@noodle-borg/service/dist/store.js.map +1 -1
  277. package/node_modules/@noodle-borg/service/package.json +1 -0
  278. package/package.json +2 -1
@@ -10,6 +10,7 @@ export const BUNDLED_EXAMPLE_NAMES = [
10
10
  "acme-tasks",
11
11
  "acme-bistro",
12
12
  "customer-auth",
13
+ "gmail-multi-account",
13
14
  ];
14
15
  /** Real example sources vendored from `examples/<name>`, written under `examples/` in the skill tree. */
15
16
  export const BUNDLED_EXAMPLE_FILES = [
@@ -47,7 +48,7 @@ export const BUNDLED_EXAMPLE_FILES = [
47
48
  { relPath: "examples/acme-tasks/src/views/widget-style.css", content: ":root {\n color-scheme: light dark;\n font-family:\n Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n --nw-bg: #ffffff;\n --nw-surface: #f7f5ff;\n --nw-text: #1c1830;\n --nw-muted: #635d80;\n --nw-border: #e2ddf5;\n --nw-accent: #7c3aed;\n --nw-accent-strong: #6d28d9;\n --nw-accent-soft: #efe9ff;\n --nw-high: #dc2626;\n --nw-medium: #b45309;\n --nw-low: #2563eb;\n --nw-radius: 10px;\n --nw-shadow: 0 18px 50px rgb(30 20 60 / 12%);\n}\n\n.dark,\n[data-theme=\"dark\"] {\n --nw-bg: #161228;\n --nw-surface: #1d1735;\n --nw-text: #f2eeff;\n --nw-muted: #a99fce;\n --nw-border: #342a54;\n --nw-accent: #a78bfa;\n --nw-accent-strong: #8b5cf6;\n --nw-accent-soft: #2a2148;\n --nw-high: #f87171;\n --nw-medium: #fbbf24;\n --nw-low: #60a5fa;\n --nw-shadow: 0 18px 50px rgb(0 0 0 / 32%);\n}\n\n* {\n box-sizing: border-box;\n}\n\nbody {\n margin: 0;\n background: var(--nw-bg);\n color: var(--nw-text);\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\n.nw-shell {\n min-height: 100vh;\n padding: 14px;\n background: var(--nw-bg);\n color: var(--nw-text);\n}\n\n.nw-card {\n max-width: 620px;\n margin: 0 auto;\n background: var(--nw-surface);\n border: 1px solid var(--nw-border);\n border-radius: var(--nw-radius);\n box-shadow: var(--nw-shadow);\n overflow: hidden;\n}\n\n.nw-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n border-bottom: 1px solid var(--nw-border);\n}\n\n.nw-icon svg {\n width: 24px;\n height: 24px;\n fill: none;\n stroke: var(--nw-accent);\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n.nw-title-block {\n flex: 1;\n min-width: 0;\n}\n\n.nw-title {\n margin: 0;\n font-size: 17px;\n font-weight: 700;\n}\n\n.nw-subtitle {\n margin: 2px 0 0;\n font-size: 13px;\n color: var(--nw-muted);\n}\n\n.nw-chip {\n padding: 4px 10px;\n border-radius: 999px;\n background: var(--nw-accent-soft);\n color: var(--nw-accent-strong);\n font-size: 12px;\n font-weight: 600;\n}\n\n.nw-capture {\n display: flex;\n gap: 8px;\n padding: 14px 16px 4px;\n}\n\n.nw-input {\n flex: 1;\n padding: 9px 12px;\n border: 1px solid var(--nw-border);\n border-radius: 10px;\n background: var(--nw-bg);\n color: var(--nw-text);\n}\n\n.nw-button {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 9px 14px;\n border: 1px solid var(--nw-border);\n border-radius: 10px;\n background: var(--nw-bg);\n color: var(--nw-text);\n cursor: pointer;\n}\n\n.nw-button-primary {\n background: var(--nw-accent);\n border-color: var(--nw-accent);\n color: #ffffff;\n font-weight: 600;\n}\n\n.nw-button-primary:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n.nw-list {\n list-style: none;\n margin: 0;\n padding: 8px 16px 4px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.nw-task {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border: 1px solid var(--nw-border);\n border-radius: 12px;\n background: var(--nw-bg);\n}\n\n.nw-task-title {\n flex: 1;\n min-width: 0;\n}\n\n.nw-task-done {\n opacity: 0.55;\n}\n\n.nw-task-done .nw-task-title {\n text-decoration: line-through;\n}\n\n.nw-check {\n width: 22px;\n height: 22px;\n border: 1.5px solid var(--nw-border);\n border-radius: 999px;\n background: transparent;\n color: #ffffff;\n cursor: pointer;\n flex: none;\n}\n\n.nw-check-on {\n background: var(--nw-accent);\n border-color: var(--nw-accent);\n}\n\n.nw-priority {\n padding: 5px 8px;\n border: 1px solid var(--nw-border);\n border-radius: 8px;\n background: var(--nw-bg);\n color: var(--nw-text);\n font-size: 12px;\n font-weight: 600;\n}\n\n.nw-priority-high {\n color: var(--nw-high);\n}\n\n.nw-priority-medium {\n color: var(--nw-medium);\n}\n\n.nw-priority-low {\n color: var(--nw-low);\n}\n\n.nw-note {\n margin: 0;\n padding: 8px 16px 16px;\n font-size: 12px;\n color: var(--nw-muted);\n}\n" },
48
49
  { relPath: "examples/acme-tasks/test/server.test.ts", content: "import { describe, expect, it } from 'vitest';\nimport app from '../src/server.js';\n\ndescribe('acme-tasks example', () => {\n it('exports a Noodle server definition', () => {\n expect(typeof app.toManifest).toBe('function');\n });\n\n it('exposes a tool for each of the top-3 prioritized flows', async () => {\n // Capture → add_task, Prioritize → list_today (+ set_priority helper), Complete → complete_task.\n const text = JSON.stringify(await app.toManifest());\n expect(text).toContain('add_task');\n expect(text).toContain('list_today');\n expect(text).toContain('complete_task');\n expect(text).toContain('set_priority');\n });\n\n it('seeds today’s list highest-priority first', async () => {\n const text = JSON.stringify(await app.toManifest());\n expect(text).toMatch(/\"tasks\":\\[\\{\"id\":\"email_vendor\".*\"priority\":\"high\"/);\n });\n\n it('opts the conversational completion action into runtime confirmation', async () => {\n const manifest = await app.toManifest();\n const completeTask = manifest.tools.find((candidate) => candidate.name === 'complete_task');\n const addTask = manifest.tools.find((candidate) => candidate.name === 'add_task');\n\n expect(completeTask?.annotations?.confirm).toBe(true);\n expect(addTask?.annotations).not.toHaveProperty('confirm');\n });\n});\n" },
49
50
  { relPath: "examples/acme-tasks/vitest.config.ts", content: "import { defineConfig } from 'vitest/config';\n\n// Local config so `npm test` (vitest run) discovers this example's own tests instead of inheriting a\n// parent monorepo config's include globs.\nexport default defineConfig({\n test: { include: ['test/**/*.test.ts'] },\n});\n" },
50
- { relPath: "examples/customer-auth/README.md", content: "# Customer Auth - NoodleSeed.com Firebase customer identity\n\nThis curated example owns the customer/end-user authentication with Firebase bridge capability slot. It is\nthe NoodleSeed.com dogfood app for proving that a SaaS app can protect an MCP endpoint with its own customer\nidentity provider while still using the generic Noodle Seed authoring API.\n\nIt also owns the embedded-assistant showcase: the same authenticated MCP surface can be dropped into the\nSaaS web application as a fully customer-branded assistant with independent light and dark themes. The\nassistant loads the active deployment's instructions and model-visible tools rather than installing a stale\nsecond skill bundle. The standard embedded element also hosts linked MCP Apps behind its sandbox bridge.\n\nThe public developer entrypoint is [`src/server.ts`](src/server.ts). It declares `customerAuth.firebase(...)` with\nthe NoodleSeed.com Firebase project and Firebase Web App public config. It exposes a deliberately small MCP\nsurface for org discovery:\n\n- `list_my_organizations` lists the NoodleSeed.com organizations the signed-in customer belongs to (no\n arguments — the org set comes from the verified customer session).\n- `list_org_apps` lists apps for one of those organizations through the dev app API.\n\nThe two tools chain: `list_my_organizations` surfaces the `org_id`s the customer can act on, and\n`list_org_apps` takes one of those `org_id`s. There is no NoodleSeed-specific SDK helper. The downstream API\nis an ordinary authored HTTP connector.\n\nDuring MCP OAuth login, Noodle Cloud hosts the Firebase bridge page at\n`https://cloud.noodleseed.dev/oauth/customer/firebase/authorize`. The customer app does not add an\nauthorization route. The SaaS operator only configures Firebase Auth to allow the Noodle Cloud origin, and\nNoodle Cloud signs the customer in with Firebase before posting the Firebase ID token back to its own bridge\ncallback.\n\n## How delegated customer credentials are used\n\nThe example has two declarations that work together:\n\n```ts\nauth: customerAuth.firebase({\n projectId: variable('FIREBASE_PROJECT_ID'),\n apiKey: variable('FIREBASE_WEB_API_KEY'),\n authDomain: variable('FIREBASE_AUTH_DOMAIN'),\n user: {\n id: 'sub',\n email: 'email',\n name: 'name',\n tenant: 'firebase.tenant',\n orgs: 'claims.orgs',\n roles: 'claims.roles',\n },\n}),\n```\n\nThat protects the MCP endpoint with the SaaS customer's Firebase identity. The connector then opts into\ndelegated customer credentials:\n\n```ts\nauth: {\n kind: 'delegatedSessionCookie',\n provider: 'firebase',\n sessionUrl: `${noodleseedApiOrigin}/api/auth/session`,\n tokenField: 'idToken',\n},\n```\n\nTool code calls the connector normally:\n\n```ts\nfulfil({ input, connectors }) {\n const apps = connectors.app_api.listOrgApps({\n org_id: input.org_id,\n skip: input.skip,\n limit: input.limit,\n });\n\n return { result: apps.result };\n}\n```\n\nAt runtime, Noodle Seed verifies the Firebase customer during MCP OAuth, stores that customer's delegated\nFirebase refresh token in the credential broker, and refreshes a short-lived Firebase ID token only when a\nconnector-backed tool calls the NoodleSeed.com API. For this app API, the broker exchanges that ID token at\nthe existing Next.js `/api/auth/session` route and sends the resulting session cookie to the API. The MCP\naccess token remains a Noodle-issued resource-bound token and is never sent to the downstream API.\n\n## Delegated downstream auth for your own API (token exchange)\n\nThe Firebase path above only works for Firebase-session downstreams. When the downstream is **your own\nAPI** with its own token issuance, use `delegatedTokenExchange` instead\n([ADR 0152](../../docs/decisions/0152-delegated-token-exchange-connector-auth.md)): the platform signs a\nshort-lived, JWKS-verifiable assertion of the signed-in user and exchanges it (RFC 8693) at a token\nendpoint you implement, which mints your own user-scoped token — so your API enforces its own per-user\nauthorization on every call. It works for verified direct/federated OIDC, built-in provider identities, and\nembedded assistant sessions, with no per-user OAuth enrollment.\n\n```ts\nauth: {\n kind: 'delegatedTokenExchange',\n tokenUrl: 'https://app.example.com/api/assistant/oauth/token', // origin must be in allowedOrigins\n clientId: variable('EXAMPLE_DELEG_CLIENT_ID'),\n clientSecret: secret('EXAMPLE_DELEG_CLIENT_SECRET'),\n scopes: ['time_off'],\n},\n```\n\nYour endpoint authenticates the broker's client credential, verifies the `subject_token` JWT against the\nplatform issuer JWKS (claims include the verified `sub`, `email`, `name`, declared session `claims`,\n`tenant`, and `deployment`), mints a short-lived user-scoped token, and returns the standard\n`{ access_token, token_type, expires_in }` response. The exact wire contract and a copyable endpoint\nimplementation live in [docs/spec/connectors.md](../../docs/spec/connectors.md) and the Agent Kit\nauthoring-workflow reference (\"Delegated downstream auth\"). `noodle auth doctor` reports each declared\nexchange endpoint.\n\n## Validate\n\n```bash\nnoodle auth doctor examples/customer-auth/src/server.ts\nnoodle validate examples/customer-auth/src/server.ts\n```\n\nAgainst a deployed customer-protected environment, set a short-lived real customer token only in\n`NOODLE_CUSTOMER_TOKEN` and add `--live --org <org> --app <app> --env <env>`. The live doctor performs\ncredential exchanges without invoking either business tool.\n\n## Run locally\n\n```bash\nnoodle dev examples/customer-auth/src/server.ts --app noodleseed-customer-auth\n```\n\n## Configuration\n\nThe embedded assistant uses a customer-supplied OpenAI Chat Completions-compatible endpoint. Configure its\nmanaged values at the Noodle deployment environment; none of these values belongs in the customer web\napplication environment, and the API key never reaches the browser:\n\n```bash\nnoodle variables set ASSISTANT_MODEL_BASE_URL https://model.example.com/v1 --scope env\nnoodle variables set ASSISTANT_MODEL your-model --scope env\nnoodle secrets set ASSISTANT_MODEL_API_KEY --scope env\nnoodle variables set FIREBASE_PROJECT_ID your-firebase-project --scope env\nnoodle variables set FIREBASE_WEB_API_KEY your-firebase-web-api-key --scope env\nnoodle variables set FIREBASE_AUTH_DOMAIN your-firebase-project.firebaseapp.com --scope env\nnoodle check --target embedded-assistant src/server.ts\n```\n\nAssistant origins are exact. Production embedding origins must use HTTPS; plain HTTP is accepted only for\nloopback development origins such as `http://localhost:3000`, `http://127.0.0.1:3000`, or\n`http://[::1]:3000`. `noodle dev` serves the MCP project, not that separate embedding application.\n\nThe assistant's panel, launcher, status header, composer, and message treatment are configured through the\nbounded `presentation` object in `src/server.ts`. The Atlas-style product treatment is the supported\ncustomization ceiling. These primitives derive their colors from the shared server `branding` block and\nrequire no edits to `@noodleseed/assistant`; raw HTML, CSS, inline SVG, renderer class names, and callbacks\nare intentionally not accepted in deployment configuration.\n\nCreate the backend credential after deployment. The CLI writes it to a mode-0600 file and never prints the\nsecret:\n\n```bash\nnoodle assistant clients create --name web --org noodleseed --app customer-auth --env prod\n```\n\nOnly the Noodle service URL, assistant client ID, and assistant client secret belong in the authenticated\ncustomer backend. The model URL, model name, and model API key remain managed by the Noodle deployment.\n\nThe customer's authenticated backend calls `createAssistantSession(...)` from\n`@noodleseed/assistant/server`, passing the already-verified user and browser origin. The browser then uses\nthe returned short-lived session through the Web Component or React wrapper:\n\n```bash\npnpm add @noodleseed/assistant\n```\n\n```tsx\nimport { NoodleAssistant } from '@noodleseed/assistant/react';\n\n<NoodleAssistant\n sessionEndpoint=\"/api/noodle-assistant/session\"\n theme=\"auto\"\n onSessionExpired={() => console.info('Assistant session renewed')}\n/>;\n```\n\n`theme=\"auto\"` follows the SaaS application. The server-level `branding` block is inherited by both MCP App\nwidgets and the assistant; documented `--ns-assistant-*` semantic CSS variables remain the final integration\nescape hatch. There is no second assistant branding declaration.\nThe end-user UI contains only customer branding.\nText streams progressively. Expired turns re-exchange through the authenticated backend and retry once;\nconsent-bound tool confirmations never replay automatically.\n\nThe Firebase project ID is required because Firebase ID tokens use the project ID as the token audience and\nissuer suffix. The runtime verifies `aud` against the project ID and `iss` against\n`https://securetoken.google.com/<projectId>`.\n\nThe Firebase Web API key and auth domain are public Firebase browser configuration. They let the Noodle\nCloud-hosted bridge initialize Firebase Auth for this customer project; they are not server secrets. Keep\nthem out of source with `variable(...)`, restrict the Firebase key to the expected browser origins and APIs,\nand use `secret(...)` only for credentials that must never reach a browser.\n\nThe `noodleseed_app_api` connector currently points at the NoodleSeed.com dev app surface:\n\n```text\nhttps://dev.noodleseed.com\n```\n\nWhen the customer app moves from `dev.noodleseed.com` to `app.noodleseed.com`, update the connector's\n`noodleseedApiOrigin` constant to the production API origin that serves the same paths.\n\nThe connector uses delegated Firebase customer credentials. During the customer OAuth bridge, Noodle Seed\nverifies the Firebase ID token, stores the Firebase refresh token through the credential broker, and refreshes\na Firebase ID token when the connector calls the NoodleSeed.com app API. The broker then exchanges that ID\ntoken for the app's existing Next.js session cookie. There is no shared `NOODLESEED_APP_API_TOKEN` for this\nexample.\n\nFirebase Auth must list `cloud.noodleseed.dev` as an authorized domain before browser sign-in works in\nproduction.\n\n## Deploy customer-protected to Noodle Seed Cloud\n\n```bash\nnoodle deploy examples/customer-auth/src/server.ts \\\n --org noodleseed \\\n --app customer-auth \\\n --env prod \\\n --access customers\n```\n\nEndpoint:\n\n```text\nhttps://cloud.noodleseed.dev/o/noodleseed/customer-auth/mcp\n```\n\n## MCP Primitives\n\n- Tool `list_my_organizations`: calls `GET /api/organizations` and returns the organizations the signed-in\n customer is a member of. Takes no arguments; the org set is scoped by the verified customer session.\n- Tool `list_org_apps`: calls `GET /api/organizations/{org_id}/apps` for one organization `org_id`.\n\n## Auth boundary\n\nFirebase ID-token verification is handled by Noodle Seed's generic Firebase bridge adapter during OAuth\nissuance. The MCP client receives a Noodle-issued, resource-bound access token marked as a Firebase customer\nidentity; raw Firebase tokens and inbound MCP bearer tokens are never forwarded to tools, connectors,\nwidgets, or downstream systems.\n\nThe connector-backed tools use the credential broker to turn the signed-in Firebase customer session into the\nsame session-cookie credential that the existing NoodleSeed.com Next.js API already expects. The inbound MCP\nbearer token is never used as an app API credential.\n" },
51
+ { relPath: "examples/customer-auth/README.md", content: "# Customer Auth - NoodleSeed.com Firebase customer identity\n\nThis curated example owns the customer/end-user authentication with Firebase bridge capability slot. It is\nthe NoodleSeed.com dogfood app for proving that a SaaS app can protect an MCP endpoint with its own customer\nidentity provider while still using the generic Noodle Seed authoring API.\n\nIt also owns the embedded-assistant showcase: the same authenticated MCP surface can be dropped into the\nSaaS web application as a fully customer-branded assistant with independent light and dark themes. The\nassistant loads the active deployment's instructions and model-visible tools rather than installing a stale\nsecond skill bundle. The standard embedded element also hosts linked MCP Apps behind its sandbox bridge.\n\nThe public developer entrypoint is [`src/server.ts`](src/server.ts). It declares `customerAuth.firebase(...)` with\nthe NoodleSeed.com Firebase project and Firebase Web App public config. It exposes a deliberately small MCP\nsurface for org discovery:\n\n- `list_my_organizations` lists the NoodleSeed.com organizations the signed-in customer belongs to (no\n arguments — the org set comes from the verified customer session).\n- `list_org_apps` lists apps for one of those organizations through the dev app API.\n\nThe two tools chain: `list_my_organizations` surfaces the `org_id`s the customer can act on, and\n`list_org_apps` takes one of those `org_id`s. There is no NoodleSeed-specific SDK helper. The downstream API\nis an ordinary authored HTTP connector.\n\nDuring MCP OAuth login, Noodle Cloud hosts the Firebase bridge page at\n`https://cloud.noodleseed.dev/oauth/customer/firebase/authorize`. The customer app does not add an\nauthorization route. The SaaS operator only configures Firebase Auth to allow the Noodle Cloud origin, and\nNoodle Cloud signs the customer in with Firebase before posting the Firebase ID token back to its own bridge\ncallback.\n\n## How delegated customer credentials are used\n\nThis flagship uses the legacy Firebase provider bridge because it is runnable today. That is distinct from\nCore-v2 account-selecting connector aliases: those declare catalog `credentialProfiles` and bind each alias\nwith `bind(connector, { profile, connection })`. Hosted bound `managedSecret(...)` connections are runnable;\nbound `externalExchange()` and `clientCredentials(...)` currently compile as portable metadata but fail\nclosed before secret or network access until their provider slice lands. Do not replace this example's\nworking delegated-session-cookie path with either unsupported bound exchange source.\n\nThe example has two declarations that work together:\n\n```ts\nauth: customerAuth.firebase({\n projectId: variable('FIREBASE_PROJECT_ID'),\n apiKey: variable('FIREBASE_WEB_API_KEY'),\n authDomain: variable('FIREBASE_AUTH_DOMAIN'),\n user: {\n id: 'sub',\n email: 'email',\n name: 'name',\n tenant: 'firebase.tenant',\n orgs: 'claims.orgs',\n roles: 'claims.roles',\n },\n}),\n```\n\nThat protects the MCP endpoint with the SaaS customer's Firebase identity. The connector then opts into\ndelegated customer credentials:\n\n```ts\nauth: {\n kind: 'delegatedSessionCookie',\n provider: 'firebase',\n sessionUrl: `${noodleseedApiOrigin}/api/auth/session`,\n tokenField: 'idToken',\n},\n```\n\nTool code calls the connector normally:\n\n```ts\nfulfil({ input, connectors }) {\n const apps = connectors.app_api.listOrgApps({\n org_id: input.org_id,\n skip: input.skip,\n limit: input.limit,\n });\n\n return { result: apps.result };\n}\n```\n\nAt runtime, Noodle Seed verifies the Firebase customer during MCP OAuth, stores that customer's delegated\nFirebase refresh token in the credential broker, and refreshes a short-lived Firebase ID token only when a\nconnector-backed tool calls the NoodleSeed.com API. For this app API, the broker exchanges that ID token at\nthe existing Next.js `/api/auth/session` route and sends the resulting session cookie to the API. The MCP\naccess token remains a Noodle-issued resource-bound token and is never sent to the downstream API.\n\n## Delegated downstream auth for your own API (token exchange)\n\nThe Firebase path above only works for Firebase-session downstreams. When the downstream is **your own\nAPI** with its own token issuance, use `delegatedTokenExchange` instead\n([ADR 0152](../../docs/decisions/0152-delegated-token-exchange-connector-auth.md)): the platform signs a\nshort-lived, JWKS-verifiable assertion of the signed-in user and exchanges it (RFC 8693) at a token\nendpoint you implement, which mints your own user-scoped token — so your API enforces its own per-user\nauthorization on every call. It works for verified direct/federated OIDC, built-in provider identities, and\nembedded assistant sessions, with no per-user OAuth enrollment.\n\n```ts\nauth: {\n kind: 'delegatedTokenExchange',\n tokenUrl: 'https://app.example.com/api/assistant/oauth/token', // origin must be in allowedOrigins\n clientId: variable('EXAMPLE_DELEG_CLIENT_ID'),\n clientSecret: secret('EXAMPLE_DELEG_CLIENT_SECRET'),\n scopes: ['time_off'],\n},\n```\n\nYour endpoint authenticates the broker's client credential, verifies the `subject_token` JWT against the\nplatform issuer JWKS (claims include the verified `sub`, `email`, `name`, declared session `claims`,\n`tenant`, and `deployment`), mints a short-lived user-scoped token, and returns the standard\n`{ access_token, token_type, expires_in }` response. The exact wire contract and a copyable endpoint\nimplementation live in [docs/spec/connectors.md](../../docs/spec/connectors.md) and the Agent Kit\nauthoring-workflow reference (\"Delegated downstream auth\"). `noodle auth doctor` reports each declared\nexchange endpoint.\n\n## Validate\n\n```bash\nnoodle auth doctor examples/customer-auth/src/server.ts\nnoodle validate examples/customer-auth/src/server.ts\n```\n\nAgainst a deployed customer-protected environment, set a short-lived real customer token only in\n`NOODLE_CUSTOMER_TOKEN` and add `--live --org <org> --app <app> --env <env>`. The live doctor performs\ncredential exchanges without invoking either business tool.\n\n## Run locally\n\n```bash\nnoodle dev examples/customer-auth/src/server.ts --app noodleseed-customer-auth\n```\n\n## Configuration\n\nThe embedded assistant uses a customer-supplied OpenAI Chat Completions-compatible endpoint. Configure its\nmanaged values at the Noodle deployment environment; none of these values belongs in the customer web\napplication environment, and the API key never reaches the browser:\n\n```bash\nnoodle variables set ASSISTANT_MODEL_BASE_URL https://model.example.com/v1 --scope env\nnoodle variables set ASSISTANT_MODEL your-model --scope env\nnoodle secrets set ASSISTANT_MODEL_API_KEY --scope env\nnoodle variables set FIREBASE_PROJECT_ID your-firebase-project --scope env\nnoodle variables set FIREBASE_WEB_API_KEY your-firebase-web-api-key --scope env\nnoodle variables set FIREBASE_AUTH_DOMAIN your-firebase-project.firebaseapp.com --scope env\nnoodle check --target embedded-assistant src/server.ts\n```\n\nAssistant origins are exact. Production embedding origins must use HTTPS; plain HTTP is accepted only for\nloopback development origins such as `http://localhost:3000`, `http://127.0.0.1:3000`, or\n`http://[::1]:3000`. `noodle dev` serves the MCP project, not that separate embedding application.\n\nThe assistant's panel, launcher, status header, composer, and message treatment are configured through the\nbounded `presentation` object in `src/server.ts`. The Atlas-style product treatment is the supported\ncustomization ceiling. These primitives derive their colors from the shared server `branding` block and\nrequire no edits to `@noodleseed/assistant`; raw HTML, CSS, inline SVG, renderer class names, and callbacks\nare intentionally not accepted in deployment configuration.\n\nCreate the backend credential after deployment. The CLI writes it to a mode-0600 file and never prints the\nsecret:\n\n```bash\nnoodle assistant clients create --name web --org noodleseed --app customer-auth --env prod\n```\n\nOnly the Noodle service URL, assistant client ID, and assistant client secret belong in the authenticated\ncustomer backend. The model URL, model name, and model API key remain managed by the Noodle deployment.\n\nThe customer's authenticated backend calls `createAssistantSession(...)` from\n`@noodleseed/assistant/server`, passing the already-verified user and browser origin. The browser then uses\nthe returned short-lived session through the Web Component or React wrapper:\n\n```bash\npnpm add @noodleseed/assistant\n```\n\n```tsx\nimport { NoodleAssistant } from '@noodleseed/assistant/react';\n\n<NoodleAssistant\n sessionEndpoint=\"/api/noodle-assistant/session\"\n theme=\"auto\"\n onSessionExpired={() => console.info('Assistant session renewed')}\n/>;\n```\n\n`theme=\"auto\"` follows the SaaS application. The server-level `branding` block is inherited by both MCP App\nwidgets and the assistant; documented `--ns-assistant-*` semantic CSS variables remain the final integration\nescape hatch. There is no second assistant branding declaration.\nThe end-user UI contains only customer branding.\nText streams progressively. Expired turns re-exchange through the authenticated backend and retry once;\nconsent-bound tool confirmations never replay automatically.\n\nThe Firebase project ID is required because Firebase ID tokens use the project ID as the token audience and\nissuer suffix. The runtime verifies `aud` against the project ID and `iss` against\n`https://securetoken.google.com/<projectId>`.\n\nThe Firebase Web API key and auth domain are public Firebase browser configuration. They let the Noodle\nCloud-hosted bridge initialize Firebase Auth for this customer project; they are not server secrets. Keep\nthem out of source with `variable(...)`, restrict the Firebase key to the expected browser origins and APIs,\nand use `secret(...)` only for credentials that must never reach a browser.\n\nThe `noodleseed_app_api` connector currently points at the NoodleSeed.com dev app surface:\n\n```text\nhttps://dev.noodleseed.com\n```\n\nWhen the customer app moves from `dev.noodleseed.com` to `app.noodleseed.com`, update the connector's\n`noodleseedApiOrigin` constant to the production API origin that serves the same paths.\n\nThe connector uses delegated Firebase customer credentials. During the customer OAuth bridge, Noodle Seed\nverifies the Firebase ID token, stores the Firebase refresh token through the credential broker, and refreshes\na Firebase ID token when the connector calls the NoodleSeed.com app API. The broker then exchanges that ID\ntoken for the app's existing Next.js session cookie. There is no shared `NOODLESEED_APP_API_TOKEN` for this\nexample.\n\nFirebase Auth must list `cloud.noodleseed.dev` as an authorized domain before browser sign-in works in\nproduction.\n\n## Deploy customer-protected to Noodle Seed Cloud\n\n```bash\nnoodle deploy examples/customer-auth/src/server.ts \\\n --org noodleseed \\\n --app customer-auth \\\n --env prod \\\n --access customers\n```\n\nEndpoint:\n\n```text\nhttps://cloud.noodleseed.dev/o/noodleseed/customer-auth/mcp\n```\n\n## MCP Primitives\n\n- Tool `list_my_organizations`: calls `GET /api/organizations` and returns the organizations the signed-in\n customer is a member of. Takes no arguments; the org set is scoped by the verified customer session.\n- Tool `list_org_apps`: calls `GET /api/organizations/{org_id}/apps` for one organization `org_id`.\n\n## Auth boundary\n\nFirebase ID-token verification is handled by Noodle Seed's generic Firebase bridge adapter during OAuth\nissuance. The MCP client receives a Noodle-issued, resource-bound access token marked as a Firebase customer\nidentity; raw Firebase tokens and inbound MCP bearer tokens are never forwarded to tools, connectors,\nwidgets, or downstream systems.\n\nThe connector-backed tools use the credential broker to turn the signed-in Firebase customer session into the\nsame session-cookie credential that the existing NoodleSeed.com Next.js API already expects. The inbound MCP\nbearer token is never used as an app API credential.\n" },
51
52
  { relPath: "examples/customer-auth/noodle.json", content: "{\n \"entrypoint\": \"src/server.ts\",\n \"name\": \"customer-auth\"\n}\n" },
52
53
  { relPath: "examples/customer-auth/package.json", content: "{\n \"name\": \"customer-auth\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"test\": \"vitest run\",\n \"validate\": \"noodle validate\",\n \"dev\": \"noodle dev\",\n \"deploy\": \"noodle deploy\"\n },\n \"devDependencies\": {\n \"@noodleseed/one\": \"latest\",\n \"vitest\": \"latest\"\n }\n}\n" },
53
54
  { relPath: "examples/customer-auth/src/server.ts", content: "import {\n annotations,\n connector,\n customerAuth,\n embeddedAssistant,\n openAICompatible,\n secret,\n server,\n tool,\n variable,\n z,\n} from '@noodleseed/one';\n\nconst noodleseedApiOrigin = 'https://dev.noodleseed.com';\n\nconst noodleseedApi = connector('noodleseed_app_api')\n .version('1.0.0')\n .http({\n baseUrl: noodleseedApiOrigin,\n allowedOrigins: [noodleseedApiOrigin],\n auth: {\n kind: 'delegatedSessionCookie',\n provider: 'firebase',\n sessionUrl: `${noodleseedApiOrigin}/api/auth/session`,\n tokenField: 'idToken',\n },\n operations: {\n list_org_apps: {\n type: 'read',\n method: 'GET',\n path: '/api/organizations/${args.org_id}/apps',\n query: ['skip', 'limit'],\n input: z.object({\n org_id: z.string(),\n skip: z.number().optional(),\n limit: z.number().optional(),\n }),\n output: z.object({ result: z.unknown().optional() }),\n response: {\n result: '${response}',\n },\n },\n list_organizations: {\n type: 'read',\n method: 'GET',\n path: '/api/organizations',\n output: z.object({ organizations: z.array(z.unknown()).optional() }),\n response: {\n organizations: '${response.organizations}',\n },\n },\n },\n });\n\nexport default server(\n 'noodleseed_customer_auth',\n {\n title: 'NoodleSeed.com Customer Auth',\n version: '1.0.0',\n branding: {\n name: 'Noodle Seed Assistant',\n accent: '#E85D24',\n surface: '#FFFFFF',\n surfaceDark: '#171310',\n colorScheme: 'auto',\n theme: {\n light: { accentText: '#FFFFFF', text: '#1C1714' },\n dark: { accent: '#FF8A4C', accentText: '#1C100A', text: '#FFF8F2' },\n },\n },\n use: { app_api: noodleseedApi },\n auth: customerAuth.firebase({\n projectId: variable('FIREBASE_PROJECT_ID'),\n apiKey: variable('FIREBASE_WEB_API_KEY'),\n authDomain: variable('FIREBASE_AUTH_DOMAIN'),\n user: {\n id: 'sub',\n email: 'email',\n name: 'name',\n tenant: 'firebase.tenant',\n orgs: 'claims.orgs',\n roles: 'claims.roles',\n },\n }),\n instructions:\n 'Customer-authenticated demo. Firebase proves the customer identity, while read-only NoodleSeed.com API calls use broker-managed delegated Firebase customer credentials.',\n assistant: embeddedAssistant({\n model: openAICompatible({\n baseUrl: variable('ASSISTANT_MODEL_BASE_URL'),\n model: variable('ASSISTANT_MODEL'),\n apiKey: secret('ASSISTANT_MODEL_API_KEY'),\n }),\n // Production origins are exact HTTPS; http://localhost:<port> is allowed for local development.\n allowedOrigins: [\n 'https://app.noodleseed.com',\n 'https://dev.noodleseed.com',\n 'http://localhost:3000',\n ],\n layout: { mode: 'floating', position: 'bottom-right', panelWidth: 420 },\n labels: {\n welcomeHeading: 'How can I help with Noodle Seed?',\n composerPlaceholder: 'Ask about your apps…',\n },\n presentation: {\n panel: { surface: 'glass', elevation: 'soft', border: 'subtle' },\n launcher: { icon: 'brand-mark', status: 'session', effect: 'pulse' },\n header: {\n mark: 'status',\n badge: { text: 'Workspace online', tone: 'success', indicator: true },\n },\n composer: { leadingIcon: 'brand-mark', shape: 'pill' },\n },\n suggestedPrompts: ['Show my organizations', 'List the apps in my organization'],\n }),\n },\n [\n tool('list_org_apps', {\n title: 'List organization apps',\n description: 'List NoodleSeed.com apps for an organization from the dev app API.',\n input: z.object({\n org_id: z.string().meta({ title: 'Organization' }),\n skip: z.number().int().min(0).optional().meta({ title: 'Starting item' }),\n limit: z.number().int().min(1).max(100).optional().meta({ title: 'Maximum results' }),\n }),\n output: z.object({\n result: z.unknown(),\n }),\n annotations: annotations.readOnly(),\n fulfil({ input, connectors }) {\n const apps = connectors.app_api.listOrgApps({\n org_id: input.org_id,\n skip: input.skip,\n limit: input.limit,\n });\n return {\n result: apps.result,\n };\n },\n }),\n tool('list_my_organizations', {\n title: 'List my organizations',\n description: 'List the NoodleSeed.com organizations the signed-in customer belongs to.',\n contextProvider: true,\n input: z.object({}),\n output: z.object({\n organizations: z.array(z.unknown()),\n }),\n annotations: annotations.readOnly(),\n fulfil({ connectors }) {\n const organizations = connectors.app_api.listOrganizations();\n return {\n organizations: organizations.organizations,\n };\n },\n }),\n ],\n);\n" },
@@ -62,6 +63,12 @@ export const BUNDLED_EXAMPLE_FILES = [
62
63
  { relPath: "examples/food-ordering/src/views/widget-style.css", content: ":root {\n color-scheme: light dark;\n font-family:\n Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n --nw-bg: #ffffff;\n --nw-surface: #f7f7f5;\n --nw-surface-strong: #ffffff;\n --nw-text: #1f2328;\n --nw-muted: #677079;\n --nw-border: #d9dee3;\n --nw-accent: #0f8f5f;\n --nw-accent-strong: #047857;\n --nw-accent-soft: #e8f7ef;\n --nw-info: #1d6feb;\n --nw-info-soft: #eaf2ff;\n --nw-warn: #b7791f;\n --nw-danger: #c2410c;\n --nw-shadow: 0 18px 50px rgb(15 23 42 / 12%);\n --nw-radius: 8px;\n}\n\n.dark,\n[data-theme=\"dark\"] {\n --nw-bg: #111820;\n --nw-surface: #16212a;\n --nw-surface-strong: #101820;\n --nw-text: #f4f7f8;\n --nw-muted: #a4b0ba;\n --nw-border: #33414c;\n --nw-accent: #25c385;\n --nw-accent-strong: #19a974;\n --nw-accent-soft: #123a2b;\n --nw-info: #4c9aff;\n --nw-info-soft: #132b4d;\n --nw-warn: #f0b35b;\n --nw-danger: #fb7b54;\n --nw-shadow: 0 18px 50px rgb(0 0 0 / 28%);\n}\n\n* {\n box-sizing: border-box;\n}\n\nbody {\n margin: 0;\n background: var(--nw-bg);\n color: var(--nw-text);\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\n.nw-shell {\n min-height: 100vh;\n padding: 14px;\n background: var(--nw-bg);\n color: var(--nw-text);\n}\n\n.nw-card {\n width: min(100%, 560px);\n margin: 0 auto;\n border: 1px solid var(--nw-border);\n border-radius: var(--nw-radius);\n background: var(--nw-surface-strong);\n box-shadow: var(--nw-shadow);\n overflow: hidden;\n}\n\n.nw-card-wide {\n width: min(100%, 720px);\n}\n\n.nsr-card {\n width: min(100%, 560px);\n margin: 0 auto;\n border: 1px solid var(--nw-border);\n border-radius: var(--nw-radius);\n background: var(--nw-surface-strong);\n box-shadow: var(--nw-shadow);\n overflow: hidden;\n}\n\n.nsr-card-wide {\n width: min(100%, 720px);\n}\n\n.nw-header {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px;\n border-bottom: 1px solid var(--nw-border);\n}\n\n.nsr-header {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px;\n border-bottom: 1px solid var(--nw-border);\n}\n\n.nw-icon {\n display: inline-grid;\n width: 32px;\n height: 32px;\n flex: 0 0 auto;\n place-items: center;\n border-radius: 8px;\n background: linear-gradient(145deg, var(--nw-accent), var(--nw-accent-strong));\n color: white;\n}\n\n.nsr-icon {\n display: inline-grid;\n width: 32px;\n height: 32px;\n flex: 0 0 auto;\n place-items: center;\n border-radius: 8px;\n background: linear-gradient(145deg, var(--nw-accent), var(--nw-accent-strong));\n color: white;\n}\n\n.nw-icon svg,\n.nsr-icon svg,\n.nw-button svg,\n.nw-meta svg {\n width: 16px;\n height: 16px;\n stroke: currentColor;\n stroke-width: 2;\n fill: none;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n.nw-title-block {\n min-width: 0;\n flex: 1;\n}\n\n.nsr-title-block {\n min-width: 0;\n flex: 1;\n}\n\n.nw-title {\n margin: 0;\n font-size: 16px;\n line-height: 1.2;\n font-weight: 700;\n letter-spacing: 0;\n}\n\n.nsr-title {\n margin: 0;\n font-size: 16px;\n line-height: 1.2;\n font-weight: 700;\n letter-spacing: 0;\n}\n\n.nw-subtitle {\n margin: 4px 0 0;\n color: var(--nw-muted);\n font-size: 12px;\n line-height: 1.35;\n}\n\n.nsr-subtitle {\n margin: 4px 0 0;\n color: var(--nw-muted);\n font-size: 12px;\n line-height: 1.35;\n}\n\n.nw-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-height: 24px;\n padding: 3px 9px;\n border: 1px solid var(--nw-border);\n border-radius: 999px;\n background: var(--nw-surface);\n color: var(--nw-text);\n font-size: 12px;\n font-weight: 600;\n white-space: nowrap;\n}\n\n.nsr-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-height: 24px;\n padding: 3px 9px;\n border: 1px solid var(--nw-border);\n border-radius: 999px;\n background: var(--nw-surface);\n color: var(--nw-text);\n font-size: 12px;\n font-weight: 600;\n white-space: nowrap;\n}\n\n.nw-chip::before {\n width: 7px;\n height: 7px;\n border-radius: 99px;\n background: var(--nw-accent);\n content: \"\";\n}\n\n.nsr-chip::before {\n width: 7px;\n height: 7px;\n border-radius: 99px;\n background: var(--nw-accent);\n content: \"\";\n}\n\n.nw-tabs {\n display: grid;\n grid-template-columns: repeat(5, minmax(0, 1fr));\n gap: 1px;\n border-bottom: 1px solid var(--nw-border);\n background: var(--nw-border);\n}\n\n.nsr-tabs {\n display: grid;\n grid-template-columns: repeat(5, minmax(0, 1fr));\n gap: 1px;\n border-bottom: 1px solid var(--nw-border);\n background: var(--nw-border);\n}\n\n.nw-tab {\n min-width: 0;\n min-height: 34px;\n border: 0;\n background: var(--nw-surface-strong);\n color: var(--nw-muted);\n font-size: 12px;\n font-weight: 700;\n text-transform: capitalize;\n cursor: pointer;\n}\n\n.nsr-tab {\n min-width: 0;\n min-height: 34px;\n border: 0;\n background: var(--nw-surface-strong);\n color: var(--nw-muted);\n font-size: 12px;\n font-weight: 700;\n text-transform: capitalize;\n cursor: pointer;\n}\n\n.nw-tab[aria-current=\"step\"] {\n color: var(--nw-text);\n background: var(--nw-accent-soft);\n}\n\n.nsr-tab[aria-current=\"step\"] {\n color: var(--nw-text);\n background: var(--nw-accent-soft);\n}\n\n.nw-body {\n display: grid;\n gap: 14px;\n padding: 14px;\n}\n\n.nw-grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(180px, 0.75fr);\n gap: 14px;\n}\n\n.nw-section-title {\n margin: 0 0 8px;\n font-size: 12px;\n font-weight: 700;\n}\n\n.nw-section-head {\n display: grid;\n gap: 2px;\n}\n\n.nw-section-detail {\n margin: 0;\n color: var(--nw-muted);\n font-size: 12px;\n}\n\n.nw-menu-list,\n.nw-summary-list,\n.nw-feature-list {\n display: grid;\n gap: 8px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.nw-menu-item {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 10px;\n width: 100%;\n padding: 10px;\n border: 1px solid var(--nw-border);\n border-radius: var(--nw-radius);\n background: var(--nw-bg);\n color: var(--nw-text);\n text-align: left;\n cursor: pointer;\n}\n\n.nw-menu-item[aria-pressed=\"true\"] {\n border-color: var(--nw-accent);\n background: var(--nw-accent-soft);\n}\n\n.nw-menu-name,\n.nw-feature-name {\n display: block;\n font-size: 13px;\n font-weight: 700;\n}\n\n.nw-menu-desc,\n.nw-feature-desc {\n display: block;\n margin-top: 3px;\n color: var(--nw-muted);\n font-size: 12px;\n line-height: 1.35;\n}\n\n.nw-price {\n align-self: center;\n color: var(--nw-text);\n font-size: 13px;\n font-weight: 700;\n}\n\n.nw-status {\n align-self: center;\n color: var(--nw-muted);\n font-size: 12px;\n font-weight: 800;\n white-space: nowrap;\n}\n\n.nw-status-ok {\n color: var(--nw-accent-strong);\n}\n\n.nw-field-grid {\n display: grid;\n grid-template-columns: 1fr 120px;\n gap: 10px;\n}\n\n.nw-field {\n display: grid;\n gap: 5px;\n color: var(--nw-muted);\n font-size: 12px;\n font-weight: 650;\n}\n\n.nsr-field-label {\n color: var(--nw-muted);\n}\n\n.nsr-stepper {\n display: grid;\n grid-template-columns: 34px minmax(42px, 1fr) 34px;\n width: 100%;\n min-height: 34px;\n border: 1px solid var(--nw-border);\n border-radius: 7px;\n overflow: hidden;\n background: var(--nw-bg);\n}\n\n.nsr-stepper button {\n border: 0;\n background: var(--nw-surface);\n color: var(--nw-text);\n cursor: pointer;\n}\n\n.nsr-stepper button:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.nsr-stepper-value {\n display: grid;\n place-items: center;\n color: var(--nw-text);\n font-size: 13px;\n font-weight: 800;\n}\n\n.nw-input,\n.nw-select {\n min-width: 0;\n width: 100%;\n min-height: 34px;\n padding: 7px 9px;\n border: 1px solid var(--nw-border);\n border-radius: 7px;\n background: var(--nw-bg);\n color: var(--nw-text);\n outline: none;\n}\n\n.nw-input:focus,\n.nw-select:focus,\n.nw-button:focus-visible,\n.nw-menu-item:focus-visible {\n border-color: var(--nw-info);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--nw-info) 24%, transparent);\n}\n\n.nw-modifier-grid {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 8px;\n}\n\n.nw-option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 9px;\n border: 1px solid var(--nw-border);\n border-radius: 7px;\n background: var(--nw-bg);\n color: var(--nw-text);\n font-size: 12px;\n font-weight: 650;\n}\n\n.nsr-choice {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 9px;\n border: 1px solid var(--nw-border);\n border-radius: 7px;\n background: var(--nw-bg);\n color: var(--nw-text);\n font-size: 12px;\n font-weight: 650;\n}\n\n.nw-summary {\n display: grid;\n gap: 8px;\n padding: 10px;\n border: 1px solid var(--nw-border);\n border-radius: var(--nw-radius);\n background: var(--nw-surface);\n}\n\n.nw-summary-compact {\n align-self: end;\n}\n\n.nw-summary-row {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid color-mix(in srgb, var(--nw-border) 70%, transparent);\n}\n\n.nw-summary-row:last-child {\n padding-bottom: 0;\n border-bottom: 0;\n}\n\n.nw-summary-row dt {\n color: var(--nw-muted);\n font-size: 12px;\n}\n\n.nw-line-note {\n display: block;\n margin-top: 2px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.nw-summary-row dd {\n margin: 0;\n text-align: right;\n font-size: 13px;\n font-weight: 700;\n}\n\n.nw-total dd {\n font-size: 18px;\n}\n\n.nw-actions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.nsr-actions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.nw-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n min-height: 36px;\n padding: 8px 12px;\n border: 1px solid var(--nw-border);\n border-radius: 7px;\n background: var(--nw-bg);\n color: var(--nw-text);\n font-size: 13px;\n font-weight: 700;\n cursor: pointer;\n}\n\n.nw-button-primary {\n border-color: var(--nw-accent-strong);\n background: linear-gradient(145deg, var(--nw-accent), var(--nw-accent-strong));\n color: white;\n}\n\n.nw-button-info {\n border-color: var(--nw-info);\n background: var(--nw-info);\n color: white;\n}\n\n.nw-button:disabled {\n cursor: wait;\n opacity: 0.65;\n}\n\n.nw-note {\n margin: 0;\n padding: 10px;\n border: 1px solid var(--nw-border);\n border-radius: var(--nw-radius);\n background: var(--nw-surface);\n color: var(--nw-muted);\n font-size: 12px;\n line-height: 1.45;\n}\n\n.nw-footer {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 10px 14px;\n border-top: 1px solid var(--nw-border);\n color: var(--nw-muted);\n font-size: 12px;\n}\n\n.nsr-footer {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 10px 14px;\n border-top: 1px solid var(--nw-border);\n color: var(--nw-muted);\n font-size: 12px;\n}\n\n.nw-meta {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.nw-feature {\n display: grid;\n grid-template-columns: 24px minmax(0, 1fr);\n gap: 10px;\n padding: 10px;\n border: 1px solid var(--nw-border);\n border-radius: var(--nw-radius);\n background: var(--nw-bg);\n}\n\n.nw-check {\n display: inline-grid;\n width: 22px;\n height: 22px;\n place-items: center;\n border-radius: 6px;\n background: var(--nw-accent);\n color: white;\n font-size: 13px;\n font-weight: 800;\n}\n\n.nw-check svg {\n width: 14px;\n height: 14px;\n stroke: currentColor;\n stroke-width: 3;\n fill: none;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n@media (max-width: 560px) {\n .nw-shell {\n padding: 10px;\n }\n\n .nw-grid,\n .nw-field-grid,\n .nw-modifier-grid {\n grid-template-columns: 1fr;\n }\n\n .nw-tabs {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n\n .nsr-tabs {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n\n .nw-header {\n align-items: flex-start;\n }\n\n .nsr-header {\n align-items: flex-start;\n }\n\n .nw-chip {\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .nsr-chip {\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .nw-button {\n flex: 1 1 140px;\n }\n}\n" },
63
64
  { relPath: "examples/food-ordering/test/server.test.ts", content: "import { describe, expect, it } from 'vitest';\nimport app from '../src/server.js';\n\ndescribe('food-ordering example', () => {\n it('exports a Noodle server definition', () => {\n expect(typeof app.toManifest).toBe('function');\n });\n\n it('emits a complete ordering app manifest with cart state and app-only helpers', async () => {\n const manifest = (await app.toManifest()) as {\n server: {\n name: string;\n context?: {\n defaults?: { locale?: string; timeZone?: string };\n ambient?: {\n outputSchema?: unknown;\n fulfilment?: { output?: unknown };\n };\n };\n };\n handoff?: { allowedDomains?: string[] };\n state?: { handles?: Record<string, { kind: string; scope: string }> };\n connectors?: Record<string, { id: string; version: string }>;\n tools: Array<{\n name: string;\n visibility?: string[];\n annotations?: Record<string, unknown>;\n output?: unknown;\n fulfilment?: { steps?: unknown[]; output?: unknown };\n }>;\n widgets?: Array<{\n name: string;\n tool: string;\n view?: { component?: string; entry?: string };\n }>;\n };\n\n expect(manifest.server.name).toBe('food_ordering');\n expect(manifest.server.context).toMatchObject({\n defaults: { locale: 'en-US', timeZone: 'America/New_York' },\n ambient: {\n fulfilment: {\n output: {\n serviceArea: 'Harbor District',\n orderingDate: '${context.temporal.localDate}',\n },\n },\n },\n });\n expect(manifest.state?.handles?.cart).toMatchObject({\n kind: 'cart',\n scope: 'caller',\n });\n expect(manifest.handoff?.allowedDomains).toEqual(['https://orders.example.com']);\n expect(manifest.connectors?.state).toEqual({ id: 'noodle_state', version: '1.0.0' });\n\n const tools = new Map(manifest.tools.map((tool) => [tool.name, tool]));\n expect(manifest.widgets?.find((widget) => widget.tool === 'open_ordering')?.view).toMatchObject(\n {\n component: 'ordering-flow',\n entry: './views/ordering-flow.tsx',\n },\n );\n for (const helper of [\n 'search_stores',\n 'load_menu',\n 'load_item',\n 'read_cart',\n 'sync_cart',\n 'prepare_checkout',\n ]) {\n expect(tools.get(helper)?.visibility).toEqual(['app']);\n }\n expect(JSON.stringify(tools.get('open_ordering'))).toContain('featuredItems');\n expect(JSON.stringify(tools.get('open_ordering'))).toContain('${context.temporal.localDate}');\n expect(JSON.stringify(tools.get('open_ordering'))).toContain('${context.ambient.serviceArea}');\n expect(JSON.stringify(tools.get('sync_cart'))).toContain('revision');\n expect(tools.get('sync_cart')?.annotations?.confirm).toBe(false);\n expect(tools.get('prepare_checkout')?.annotations?.confirm).toBe(false);\n expect(tools.get('plan_order')?.fulfilment).toMatchObject({\n steps: [\n {\n id: 'choose_fulfilment',\n elicit: {\n message: 'How should we fulfil this order?',\n requestedSchema: {\n type: 'object',\n properties: {\n method: { type: 'string', enum: ['pickup', 'delivery'] },\n requestedDate: { type: 'string', format: 'date' },\n },\n required: ['method', 'requestedDate'],\n },\n },\n },\n ],\n output: {\n method: '${steps.choose_fulfilment.method}',\n requestedDate: '${steps.choose_fulfilment.requestedDate}',\n },\n });\n expect(manifest.widgets?.map((widget) => widget.name)).toContain('capabilities_card');\n });\n});\n" },
64
65
  { relPath: "examples/food-ordering/vitest.config.ts", content: "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n resolve: {\n alias: {\n '@noodleseed/one': new URL('../../packages/authoring/src/index.ts', import.meta.url).pathname,\n '@noodle-borg/capabilities': new URL(\n '../../packages/capabilities/src/index.ts',\n import.meta.url,\n ).pathname,\n '@noodle-borg/compiler': new URL('../../packages/compiler/src/index.ts', import.meta.url)\n .pathname,\n '@noodle-borg/compute': new URL('../../packages/compute/src/index.ts', import.meta.url)\n .pathname,\n '@noodle-borg/connector-defs': new URL(\n '../../packages/connector-defs/src/index.ts',\n import.meta.url,\n ).pathname,\n '@noodle-borg/connector-http': new URL(\n '../../packages/connector-http/src/index.ts',\n import.meta.url,\n ).pathname,\n '@noodle-borg/runtime': new URL('../../packages/runtime/src/index.ts', import.meta.url)\n .pathname,\n },\n },\n test: {\n include: ['test/**/*.test.ts'],\n },\n});\n" },
66
+ { relPath: "examples/gmail-multi-account/README.md", content: "# Gmail multi-account automation\n\n**Owns:** The flagship proof that one reusable connector can be bound to multiple independently\nauthenticated accounts inside one MCP server.\n\nThis fictional example binds `gmailConnector()` twice through separate `externalExchange()` logical\nconnections. Public tools always accept `accounts: [...]`; reads accept either account or the canonical\npersonal-then-work pair, while mutations accept exactly one account and require runtime confirmation.\n\nCapability slot: **reusable connector + independently authenticated multi-account bindings**. It is distinct\nfrom `customer-auth`, which owns authentication of the MCP caller rather than downstream connector accounts.\n\nThe labels `personal@example.com` and `work@example.com` are static display labels, not provider identities.\nThe deployment-owned credential provider maps each logical connection to its real Google authorization.\nNo Google client, provider account id, token, or real email address belongs in this project.\n\n## Safety and API boundary\n\n- Search, message/thread reads, draft reads, and vacation-setting reads may target one or both accounts.\n- Draft creation/update/send, label changes, archive, raw send, trash, and vacation updates target one account.\n- Every mutation is prepared against the exact selected binding and must be confirmed before dispatch.\n- `send_message.raw` and draft `raw` are RFC 2822 MIME bytes encoded with base64url. This example does not\n pretend that `to`/`subject`/`body` strings are sufficient to encode Unicode MIME correctly.\n- Vacation `startTime`/`endTime` schemas enforce only digit-shaped 1–19 character epoch-millisecond strings.\n When both are supplied, Gmail's backend remains authoritative for the required `startTime < endTime`\n relationship; this example does not claim cross-field JSON Schema validation.\n- Trash is reversible. Permanent message/thread/draft deletion, delegation, forwarding/sharing settings,\n and unrestricted raw HTTP requests are intentionally absent.\n\n## Local checks\n\n```sh\nnoodle validate\nnoodle test\n```\n\nThe committed tests compile hermetic fake connector responses. They never contact Gmail or load OAuth\ncredentials. A real deployment additionally needs an operator-provided external credential exchange\nendpoint for each logical connection.\n\n## Personal automation skill\n\nThe source skill is [`skills/personal-email-automation/SKILL.md`](skills/personal-email-automation/SKILL.md).\nValidate it with the standard skill validator before distribution. The source skill is shipped as part of\nthis example; canonical export of an app and its skill as an installable Codex plugin remains roadmap work\nand is not currently provided by Noodle Seed.\n" },
67
+ { relPath: "examples/gmail-multi-account/noodle.json", content: "{\n \"entrypoint\": \"src/server.ts\",\n \"name\": \"gmail-multi-account\"\n}\n" },
68
+ { relPath: "examples/gmail-multi-account/package.json", content: "{\n \"name\": \"gmail-multi-account\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"test\": \"vitest run\",\n \"validate\": \"noodle validate\",\n \"dev\": \"noodle dev\",\n \"deploy\": \"noodle deploy\"\n },\n \"devDependencies\": {\n \"@noodleseed/one\": \"latest\",\n \"vitest\": \"latest\"\n }\n}\n" },
69
+ { relPath: "examples/gmail-multi-account/src/server.ts", content: "import {\n annotations,\n bind,\n connection,\n connector,\n externalExchange,\n gmailConnector,\n server,\n tool,\n when,\n z,\n} from '@noodleseed/one';\n\nexport const PERSONAL_ACCOUNT = 'personal@example.com';\nexport const WORK_ACCOUNT = 'work@example.com';\n\nconst readAccounts = z.union([\n z.tuple([z.literal(PERSONAL_ACCOUNT)]).and(z.array(z.literal(PERSONAL_ACCOUNT)).length(1)),\n z.tuple([z.literal(WORK_ACCOUNT)]).and(z.array(z.literal(WORK_ACCOUNT)).length(1)),\n z\n .tuple([z.literal(PERSONAL_ACCOUNT), z.literal(WORK_ACCOUNT)])\n .and(z.array(z.enum([PERSONAL_ACCOUNT, WORK_ACCOUNT])).length(2)),\n]);\nconst writeAccounts = z.union([\n z.tuple([z.literal(PERSONAL_ACCOUNT)]).and(z.array(z.literal(PERSONAL_ACCOUNT)).length(1)),\n z.tuple([z.literal(WORK_ACCOUNT)]).and(z.array(z.literal(WORK_ACCOUNT)).length(1)),\n]);\nconst identifier = z.string().min(1);\nconst rawMessage = z.string().min(1);\nconst labelIds = z.array(identifier).min(1).max(100);\nconst epochMillis = z.string().regex(/^\\d{1,19}$/);\nconst vacationOptionalFields = {\n restrict_to_contacts: z.boolean().optional(),\n restrict_to_domain: z.boolean().optional(),\n start_time: epochMillis.optional(),\n end_time: epochMillis.optional(),\n};\nconst output = z.object({\n results: z.array(\n z.object({ account: z.enum([PERSONAL_ACCOUNT, WORK_ACCOUNT]), data: z.unknown() }),\n ),\n});\n\nconst gmail = gmailConnector();\nconst personal = connection('personal_gmail', externalExchange());\nconst work = connection('work_gmail', externalExchange());\n\nconst merge = connector('gmail_account_results')\n .version('1.0.0')\n .compute('merge', {\n type: 'read',\n input: z.object({\n personal: z.unknown().optional(),\n work_first: z.unknown().optional(),\n work_second: z.unknown().optional(),\n }),\n output,\n run: (input) => {\n const results: Array<{ account: string; data: unknown }> = [];\n if (input.personal !== undefined) {\n results.push({ account: 'personal@example.com', data: input.personal });\n }\n const workData = input.work_first ?? input.work_second;\n if (workData !== undefined) {\n results.push({ account: 'work@example.com', data: workData });\n }\n return { results };\n },\n });\n\nconst confirmedWrite = annotations.openAction({ destructive: false, confirm: true });\nconst confirmedTrash = annotations.openAction({ destructive: true, confirm: true });\n\nexport default server(\n 'gmail_multi_account',\n {\n title: 'Gmail Multi-Account Automation',\n version: '1.0.0',\n use: {\n personal_gmail: bind(gmail, { profile: 'user_oauth', connection: personal }),\n work_gmail: bind(gmail, { profile: 'user_oauth', connection: work }),\n gmail_results: merge,\n },\n },\n [\n tool('search_messages', {\n description: 'Search one connected Gmail account or the canonical personal-and-work pair.',\n input: z.object({\n accounts: readAccounts,\n query: z.string(),\n max_results: z.number().int().min(1).max(500).optional(),\n }),\n output,\n fulfil: ({ input, connectors }) => {\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.search_messages({\n q: input.query,\n maxResults: input.max_results,\n }),\n );\n const workFirst = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.search_messages({\n q: input.query,\n maxResults: input.max_results,\n }),\n );\n const workSecond = when(input.accounts.at(1).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.search_messages({\n q: input.query,\n maxResults: input.max_results,\n }),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: workFirst.data.optional(),\n work_second: workSecond.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('get_message', {\n description: 'Get one Gmail message from one connected account or both canonical accounts.',\n input: z.object({\n accounts: readAccounts,\n message_id: identifier,\n format: z.enum(['minimal', 'full', 'raw', 'metadata']).optional(),\n }),\n output,\n fulfil: ({ input, connectors }) => {\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.get_message({\n message_id: input.message_id,\n format: input.format,\n }),\n );\n const workFirst = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.get_message({\n message_id: input.message_id,\n format: input.format,\n }),\n );\n const workSecond = when(input.accounts.at(1).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.get_message({\n message_id: input.message_id,\n format: input.format,\n }),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: workFirst.data.optional(),\n work_second: workSecond.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('get_thread', {\n description: 'Get one Gmail thread from one connected account or both canonical accounts.',\n input: z.object({\n accounts: readAccounts,\n thread_id: identifier,\n format: z.enum(['minimal', 'full', 'metadata']).optional(),\n }),\n output,\n fulfil: ({ input, connectors }) => {\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.get_thread({\n thread_id: input.thread_id,\n format: input.format,\n }),\n );\n const workFirst = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.get_thread({\n thread_id: input.thread_id,\n format: input.format,\n }),\n );\n const workSecond = when(input.accounts.at(1).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.get_thread({\n thread_id: input.thread_id,\n format: input.format,\n }),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: workFirst.data.optional(),\n work_second: workSecond.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('list_drafts', {\n description: 'List drafts from one connected Gmail account or both canonical accounts.',\n input: z.object({\n accounts: readAccounts,\n query: z.string().optional(),\n max_results: z.number().int().min(1).max(500).optional(),\n }),\n output,\n fulfil: ({ input, connectors }) => {\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.list_drafts({\n q: input.query,\n maxResults: input.max_results,\n }),\n );\n const workFirst = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.list_drafts({\n q: input.query,\n maxResults: input.max_results,\n }),\n );\n const workSecond = when(input.accounts.at(1).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.list_drafts({\n q: input.query,\n maxResults: input.max_results,\n }),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: workFirst.data.optional(),\n work_second: workSecond.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('get_draft', {\n description: 'Get one draft from one connected Gmail account or both canonical accounts.',\n input: z.object({\n accounts: readAccounts,\n draft_id: identifier,\n format: z.enum(['minimal', 'full', 'raw', 'metadata']).optional(),\n }),\n output,\n fulfil: ({ input, connectors }) => {\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.get_draft({\n draft_id: input.draft_id,\n format: input.format,\n }),\n );\n const workFirst = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.get_draft({\n draft_id: input.draft_id,\n format: input.format,\n }),\n );\n const workSecond = when(input.accounts.at(1).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.get_draft({\n draft_id: input.draft_id,\n format: input.format,\n }),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: workFirst.data.optional(),\n work_second: workSecond.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('get_vacation', {\n description: 'Read vacation-responder settings from one connected account or both accounts.',\n input: z.object({ accounts: readAccounts }),\n output,\n fulfil: ({ input, connectors }) => {\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.get_vacation({}),\n );\n const workFirst = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.get_vacation({}),\n );\n const workSecond = when(input.accounts.at(1).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.get_vacation({}),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: workFirst.data.optional(),\n work_second: workSecond.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('create_draft', {\n description:\n 'Create a Gmail draft in exactly one selected account from a base64url MIME message.',\n annotations: confirmedWrite,\n input: z.object({ accounts: writeAccounts, raw: rawMessage }),\n output,\n fulfil: ({ input, connectors }) => {\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.create_draft({ raw: input.raw }),\n );\n const work = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.create_draft({ raw: input.raw }),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: work.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('update_draft', {\n description:\n 'Replace a Gmail draft in exactly one selected account with a base64url MIME message.',\n annotations: confirmedWrite,\n input: z.object({ accounts: writeAccounts, draft_id: identifier, raw: rawMessage }),\n output,\n fulfil: ({ input, connectors }) => {\n const args = { draft_id: input.draft_id, raw: input.raw };\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.update_draft(args),\n );\n const work = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.update_draft(args),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: work.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('send_draft', {\n description: 'Send an existing Gmail draft from exactly one selected account.',\n annotations: confirmedWrite,\n input: z.object({ accounts: writeAccounts, draft_id: identifier }),\n output,\n fulfil: ({ input, connectors }) => {\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.send_draft({ draft_id: input.draft_id }),\n );\n const work = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.send_draft({ draft_id: input.draft_id }),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: work.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('modify_message_labels', {\n description: 'Add or remove Gmail label ids on one message in exactly one selected account.',\n annotations: confirmedWrite,\n input: z.object({\n accounts: writeAccounts,\n message_id: identifier,\n add_label_ids: labelIds.optional(),\n remove_label_ids: labelIds.optional(),\n }),\n output,\n fulfil: ({ input, connectors }) => {\n const args = {\n message_id: input.message_id,\n addLabelIds: input.add_label_ids,\n removeLabelIds: input.remove_label_ids,\n };\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.modify_message_labels(args),\n );\n const work = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.modify_message_labels(args),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: work.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('archive_message', {\n description: 'Archive one Gmail message in exactly one account by removing INBOX.',\n annotations: confirmedWrite,\n input: z.object({ accounts: writeAccounts, message_id: identifier }),\n output,\n fulfil: ({ input, connectors }) => {\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.archive_message({ message_id: input.message_id }),\n );\n const work = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.archive_message({ message_id: input.message_id }),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: work.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('send_message', {\n description: 'Send one base64url MIME message from exactly one selected Gmail account.',\n annotations: confirmedWrite,\n input: z.object({\n accounts: writeAccounts,\n raw: rawMessage,\n thread_id: identifier.optional(),\n }),\n output,\n fulfil: ({ input, connectors }) => {\n const args = { raw: input.raw, threadId: input.thread_id };\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.send_message(args),\n );\n const work = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.send_message(args),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: work.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('trash_message', {\n description: 'Move one Gmail message to trash in exactly one account. This is reversible.',\n annotations: confirmedTrash,\n input: z.object({ accounts: writeAccounts, message_id: identifier }),\n output,\n fulfil: ({ input, connectors }) => {\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.trash_message({ message_id: input.message_id }),\n );\n const work = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.trash_message({ message_id: input.message_id }),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: work.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n tool('update_vacation', {\n description: 'Update vacation-responder settings on exactly one selected Gmail account.',\n annotations: confirmedWrite,\n input: z.object({\n accounts: writeAccounts,\n settings: z.union([\n z.object({\n enable_auto_reply: z.literal(false),\n response_subject: z.string().min(1).optional(),\n response_body_plain_text: z.string().min(1).optional(),\n ...vacationOptionalFields,\n }),\n z.object({\n enable_auto_reply: z.literal(true),\n response_subject: z.string().min(1),\n response_body_plain_text: z.string().min(1).optional(),\n ...vacationOptionalFields,\n }),\n z.object({\n enable_auto_reply: z.literal(true),\n response_subject: z.string().min(1).optional(),\n response_body_plain_text: z.string().min(1),\n ...vacationOptionalFields,\n }),\n ]),\n }),\n output,\n fulfil: ({ input, connectors }) => {\n const args = {\n enableAutoReply: input.settings.enable_auto_reply,\n responseSubject: input.settings.response_subject,\n responseBodyPlainText: input.settings.response_body_plain_text,\n restrictToContacts: input.settings.restrict_to_contacts,\n restrictToDomain: input.settings.restrict_to_domain,\n startTime: input.settings.start_time,\n endTime: input.settings.end_time,\n };\n const personal = when(input.accounts.at(0).equals(PERSONAL_ACCOUNT), () =>\n connectors.personal_gmail.update_vacation(args),\n );\n const work = when(input.accounts.at(0).equals(WORK_ACCOUNT), () =>\n connectors.work_gmail.update_vacation(args),\n );\n const merged = connectors.gmail_results.merge({\n personal: personal.data.optional(),\n work_first: work.data.optional(),\n });\n return { results: merged.results };\n },\n }),\n ],\n);\n" },
70
+ { relPath: "examples/gmail-multi-account/test/server.test.ts", content: "import { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { describe, expect, it } from 'vitest';\nimport {\n compileManifest,\n InMemoryCatalog,\n validateJsonSchemaWithDefaults,\n} from '../../../packages/compiler/src/index.js';\nimport { compileConnectors } from '../../../packages/connector-defs/src/index.js';\nimport {\n type CredentialBroker,\n type CredentialRequest,\n type DownstreamCredential,\n executePreparedTool,\n executeTool,\n InMemoryConnectorRegistry,\n isConfirmationRequired,\n prepareToolForConfirmation,\n} from '../../../packages/runtime/src/index.js';\nimport app, { PERSONAL_ACCOUNT, WORK_ACCOUNT } from '../src/server.js';\n\nconst here = dirname(fileURLToPath(import.meta.url));\n\nasync function compiledFixture() {\n const catalog = structuredClone(app.toConnectorCatalog());\n if (catalog === undefined) throw new Error('expected connector catalog');\n for (const connector of catalog.connectors) {\n if ('http' in connector) {\n for (const [name, operation] of Object.entries(connector.operations)) {\n operation.fake = {\n response: {\n id: `${name}-fixture`,\n messages: [{ id: `${name}-message` }],\n drafts: [{ id: `${name}-draft` }],\n },\n };\n }\n }\n }\n const connectors = compileConnectors(JSON.stringify(catalog), { mode: 'fake' });\n if (!connectors.ok) throw new Error(JSON.stringify(connectors.errors));\n const manifest = await app.toManifest();\n const compiled = compileManifest(manifest, {\n catalog: new InMemoryCatalog(connectors.catalog),\n });\n if (!compiled.ok) throw new Error(JSON.stringify(compiled.errors));\n const requests: CredentialRequest[] = [];\n const broker: CredentialBroker = {\n getCredential(request): Promise<DownstreamCredential> {\n requests.push(request);\n return Promise.resolve({ token: `${request.bindingId}-fixture-token` });\n },\n };\n return {\n artifact: compiled.artifact,\n deps: { connectors: new InMemoryConnectorRegistry(connectors.connectors), broker },\n requests,\n };\n}\n\ndescribe('multi-account Gmail flagship', () => {\n it('binds the same curated connector twice without provider ids, credentials, or real labels', async () => {\n const manifest = await app.toManifest();\n expect(manifest.connectors).toMatchObject({\n personal_gmail: {\n id: 'gmail',\n binding: {\n profile: 'user_oauth',\n connection: { id: 'personal_gmail', source: { kind: 'externalExchange' } },\n },\n },\n work_gmail: {\n id: 'gmail',\n binding: {\n profile: 'user_oauth',\n connection: { id: 'work_gmail', source: { kind: 'externalExchange' } },\n },\n },\n });\n const wire = JSON.stringify({ manifest, catalog: app.toConnectorCatalog() });\n expect(wire).not.toMatch(/access[_-]?token|client[_-]?secret/i);\n });\n\n it('emits enforceable canonical account arrays on every tool', async () => {\n const manifest = await app.toManifest();\n for (const tool of manifest.tools) {\n expect(tool.inputSchema.properties).toHaveProperty('accounts');\n expect(JSON.stringify(tool.inputSchema.properties.accounts)).toContain(PERSONAL_ACCOUNT);\n expect(JSON.stringify(tool.inputSchema.properties.accounts)).toContain(WORK_ACCOUNT);\n }\n const read = manifest.tools.find((tool) => tool.name === 'search_messages');\n const write = manifest.tools.find((tool) => tool.name === 'trash_message');\n const readAccountsSchema = JSON.stringify(read?.inputSchema.properties.accounts);\n const writeAccountsSchema = JSON.stringify(write?.inputSchema.properties.accounts);\n expect(readAccountsSchema).toContain(PERSONAL_ACCOUNT);\n expect(readAccountsSchema).toContain(WORK_ACCOUNT);\n expect(readAccountsSchema).toContain('\"maxItems\":2');\n expect(writeAccountsSchema).not.toContain('\"maxItems\":2');\n });\n\n it('allows subject-only or plain-body-only vacation replies but rejects an empty enabled reply', async () => {\n const manifest = await app.toManifest();\n const schema = manifest.tools.find((tool) => tool.name === 'update_vacation')?.inputSchema;\n if (schema === undefined) throw new Error('expected update_vacation schema');\n const base = { accounts: [PERSONAL_ACCOUNT], settings: { enable_auto_reply: true } };\n\n expect(\n validateJsonSchemaWithDefaults(schema, {\n ...base,\n settings: { ...base.settings, response_subject: 'Away' },\n }).issues,\n ).toHaveLength(0);\n expect(\n validateJsonSchemaWithDefaults(schema, {\n ...base,\n settings: { ...base.settings, response_body_plain_text: 'Back soon' },\n }).issues,\n ).toHaveLength(0);\n expect(validateJsonSchemaWithDefaults(schema, base).issues).not.toHaveLength(0);\n });\n\n it.each([\n [],\n ['unknown@example.com'],\n [PERSONAL_ACCOUNT, PERSONAL_ACCOUNT],\n [WORK_ACCOUNT, PERSONAL_ACCOUNT],\n ])('rejects invalid read accounts %j before connector dispatch', async (accounts) => {\n const setup = await compiledFixture();\n const schema = setup.artifact.tools.find(\n (candidate) => candidate.name === 'search_messages',\n )?.inputSchema;\n if (!schema) throw new Error('expected search schema');\n const result = validateJsonSchemaWithDefaults(schema, { accounts, query: '' });\n expect(result.issues).not.toHaveLength(0);\n expect(setup.requests).toHaveLength(0);\n });\n\n it('rejects multi-account mutations at the write schema boundary', async () => {\n const setup = await compiledFixture();\n const schema = setup.artifact.tools.find(\n (candidate) => candidate.name === 'trash_message',\n )?.inputSchema;\n if (!schema) throw new Error('expected trash schema');\n\n const result = validateJsonSchemaWithDefaults(schema, {\n accounts: [PERSONAL_ACCOUNT, WORK_ACCOUNT],\n message_id: 'fixture-message',\n });\n\n expect(result.issues).not.toHaveLength(0);\n expect(setup.requests).toHaveLength(0);\n });\n\n it('rejects a no-op label mutation before confirmation or credential lookup', async () => {\n const setup = await compiledFixture();\n\n await expect(\n prepareToolForConfirmation(\n setup.artifact,\n 'modify_message_labels',\n { accounts: [PERSONAL_ACCOUNT], message_id: 'fixture-message' },\n setup.deps,\n ),\n ).resolves.toMatchObject({ status: 'failed', error: { code: 'arg_invalid' } });\n expect(setup.requests).toHaveLength(0);\n });\n\n it('routes personal, work, and combined reads to isolated bindings and preserves account labels', async () => {\n const personal = await compiledFixture();\n const personalResult = await executeTool(\n personal.artifact,\n 'search_messages',\n { accounts: [PERSONAL_ACCOUNT], query: 'is:unread' },\n personal.deps,\n );\n expect(personal.requests.flatMap((request) => request.bindingId ?? [])).toEqual([\n 'personal_gmail',\n ]);\n expect(personalResult).toMatchObject({\n ok: true,\n output: { results: [{ account: PERSONAL_ACCOUNT }] },\n });\n\n const work = await compiledFixture();\n const workResult = await executeTool(\n work.artifact,\n 'search_messages',\n { accounts: [WORK_ACCOUNT], query: 'is:unread' },\n work.deps,\n );\n expect(work.requests.flatMap((request) => request.bindingId ?? [])).toEqual(['work_gmail']);\n expect(workResult).toMatchObject({\n ok: true,\n output: { results: [{ account: WORK_ACCOUNT }] },\n });\n\n const both = await compiledFixture();\n const bothResult = await executeTool(\n both.artifact,\n 'search_messages',\n { accounts: [PERSONAL_ACCOUNT, WORK_ACCOUNT], query: 'is:unread' },\n both.deps,\n );\n expect(both.requests.flatMap((request) => request.bindingId ?? [])).toEqual([\n 'personal_gmail',\n 'work_gmail',\n ]);\n expect(bothResult).toMatchObject({\n ok: true,\n output: {\n results: [{ account: PERSONAL_ACCOUNT }, { account: WORK_ACCOUNT }],\n },\n });\n });\n\n it('prepares the exact selected write binding, dispatches only after confirmation, and rejects replay drift', async () => {\n const setup = await compiledFixture();\n const prepared = await prepareToolForConfirmation(\n setup.artifact,\n 'trash_message',\n { accounts: [WORK_ACCOUNT], message_id: 'fixture-message' },\n setup.deps,\n );\n expect(isConfirmationRequired(prepared)).toBe(true);\n if (!isConfirmationRequired(prepared)) throw new Error('expected confirmation');\n expect(setup.requests).toHaveLength(0);\n expect(prepared.review.action).toMatchObject({\n bindingId: 'work_gmail',\n connectionId: 'work_gmail',\n operation: 'trash_message',\n });\n\n await expect(\n executePreparedTool(setup.artifact, prepared.continuation, setup.deps),\n ).resolves.toMatchObject({ status: 'completed' });\n expect(setup.requests.flatMap((request) => request.bindingId ?? [])).toEqual(['work_gmail']);\n\n const personalPrepared = structuredClone(prepared.continuation);\n if (personalPrepared.reviewedAction) {\n (personalPrepared.reviewedAction as { bindingId?: string }).bindingId = 'personal_gmail';\n }\n await expect(\n executePreparedTool(setup.artifact, personalPrepared, setup.deps),\n ).resolves.toMatchObject({ status: 'failed' });\n });\n\n it('makes every mutation confirmable and keeps the personal-email skill concise and safe', async () => {\n const manifest = await app.toManifest();\n const catalog = app.toConnectorCatalog();\n const actionNames = new Set(\n catalog?.connectors.flatMap((connector) =>\n Object.entries(connector.operations)\n .filter(([, operation]) => operation.type === 'action')\n .map(([name]) => name),\n ),\n );\n for (const tool of manifest.tools.filter((candidate) => actionNames.has(candidate.name))) {\n expect(tool.annotations?.confirm, tool.name).toBe(true);\n }\n\n const skill = readFileSync(join(here, '../skills/personal-email-automation/SKILL.md'), 'utf8');\n expect(skill).toMatch(/^---\\nname: personal-email-automation\\ndescription:/);\n expect(skill.split('\\n').length).toBeLessThan(140);\n expect(skill).toContain('accounts');\n expect(skill).toMatch(/draft/i);\n expect(skill).toMatch(/confirm/i);\n expect(skill).toMatch(/permanent delete/i);\n expect(skill).not.toMatch(/client[_-]?secret|access[_-]?token/i);\n });\n});\n" },
71
+ { relPath: "examples/gmail-multi-account/vitest.config.ts", content: "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n resolve: {\n alias: {\n '@noodleseed/one': new URL('../../packages/authoring/src/index.ts', import.meta.url).pathname,\n '@noodle-borg/capabilities': new URL(\n '../../packages/capabilities/src/index.ts',\n import.meta.url,\n ).pathname,\n '@noodle-borg/compiler': new URL('../../packages/compiler/src/index.ts', import.meta.url)\n .pathname,\n '@noodle-borg/compute': new URL('../../packages/compute/src/index.ts', import.meta.url)\n .pathname,\n '@noodle-borg/connector-defs': new URL(\n '../../packages/connector-defs/src/index.ts',\n import.meta.url,\n ).pathname,\n '@noodle-borg/connector-http': new URL(\n '../../packages/connector-http/src/index.ts',\n import.meta.url,\n ).pathname,\n '@noodle-borg/runtime': new URL('../../packages/runtime/src/index.ts', import.meta.url)\n .pathname,\n },\n },\n test: { include: ['test/**/*.test.ts'] },\n});\n" },
65
72
  { relPath: "examples/hello/README.md", content: "# hello — minimal TypeScript quickstart\n\nThe smallest deployable Noodle app: a single `greet` tool authored in TypeScript with no\nconnectors, secrets, flows, widgets, or handoff policy. It still uses the current server options form\nso new authors see where server-level branding belongs. Use it to smoke the author loop\n(`noodle validate` / `noodle dev`) or a first deploy.\n\nWhen an installed Noodle Developer plugin drives this example, its skill runs these logical\n`noodle` commands through the plugin-managed, version-pinned launcher and isolated host profile.\nDo not install or update a global CLI: the coding agent writes and tests this source while Noodle\nguides and operates the validate, preview, deploy, inspect, and debug workflow.\n\n```sh\nnoodle dev examples/hello/src/server.ts --app hello\nnoodle deploy examples/hello/src/server.ts --org acme --app hello\n```\n\n`noodle export manifest examples/hello/src/server.ts` compiles the same entrypoint locally and prints\nthe portable, vendor-neutral manifest JSON — the eject path: your `server.ts` plus this manifest is\nthe whole app, yours to read, diff, and keep.\n\nIt is also the fixture for `pnpm smoke:dev` and the e2e harness, so keep its tool surface stable.\n" },
66
73
  { relPath: "examples/hello/noodle.json", content: "{\n \"entrypoint\": \"src/server.ts\",\n \"name\": \"hello\",\n \"template\": \"hello\"\n}\n" },
67
74
  { relPath: "examples/hello/package.json", content: "{\n \"name\": \"hello\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"test\": \"vitest run\",\n \"validate\": \"noodle validate\",\n \"dev\": \"noodle dev\",\n \"deploy\": \"noodle deploy\"\n },\n \"devDependencies\": {\n \"@noodleseed/one\": \"latest\",\n \"vitest\": \"latest\"\n }\n}\n" },
@@ -1 +1 @@
1
- {"version":3,"file":"example-files.js","sourceRoot":"","sources":["../../src/generated/example-files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"example-files.js","sourceRoot":"","sources":["../../src/generated/example-files.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,kFAAkF;AAClF,iGAAiG;AAQjG,uGAAuG;AACvG,MAAM,CAAC,MAAM,qBAAqB,GAAsB;IACtD,OAAO;IACP,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,YAAY;IACZ,aAAa;IACb,eAAe;IACf,qBAAqB;CACtB,CAAC;AAEF,yGAAyG;AACzG,MAAM,CAAC,MAAM,qBAAqB,GAAkC;IAClE,EAAE,OAAO,EAAE,gCAAgC,EAAE,OAAO,EAAE,4oEAA4oE,EAAE;IACpsE,EAAE,OAAO,EAAE,4CAA4C,EAAE,OAAO,EAAE,u/wBAAu/wB,EAAE;IAC3jxB,EAAE,OAAO,EAAE,6CAA6C,EAAE,OAAO,EAAE,kkQAAkkQ,EAAE;IACvoQ,EAAE,OAAO,EAAE,4CAA4C,EAAE,OAAO,EAAE,klqDAAklqD,EAAE;IACtpqD,EAAE,OAAO,EAAE,kCAAkC,EAAE,OAAO,EAAE,wGAAwG,EAAE;IAClK,EAAE,OAAO,EAAE,mCAAmC,EAAE,OAAO,EAAE,mfAAmf,EAAE;IAC9iB,EAAE,OAAO,EAAE,qCAAqC,EAAE,OAAO,EAAE,yRAAyR,EAAE;IACtV,EAAE,OAAO,EAAE,oCAAoC,EAAE,OAAO,EAAE,i+LAAi+L,EAAE;IAC7hM,EAAE,OAAO,EAAE,8CAA8C,EAAE,OAAO,EAAE,okLAAokL,EAAE;IAC1oL,EAAE,OAAO,EAAE,iDAAiD,EAAE,OAAO,EAAE,8zHAA8zH,EAAE;IACv4H,EAAE,OAAO,EAAE,0CAA0C,EAAE,OAAO,EAAE,wyBAAwyB,EAAE;IAC12B,EAAE,OAAO,EAAE,uCAAuC,EAAE,OAAO,EAAE,uRAAuR,EAAE;IACtV,EAAE,OAAO,EAAE,mCAAmC,EAAE,OAAO,EAAE,2tIAA2tI,EAAE;IACtxI,EAAE,OAAO,EAAE,+CAA+C,EAAE,OAAO,EAAE,mrhCAAmrhC,EAAE;IAC1vhC,EAAE,OAAO,EAAE,+CAA+C,EAAE,OAAO,EAAE,g4sDAAg4sD,EAAE;IACv8sD,EAAE,OAAO,EAAE,qCAAqC,EAAE,OAAO,EAAE,2GAA2G,EAAE;IACxK,EAAE,OAAO,EAAE,sCAAsC,EAAE,OAAO,EAAE,sfAAsf,EAAE;IACpjB,EAAE,OAAO,EAAE,wCAAwC,EAAE,OAAO,EAAE,yRAAyR,EAAE;IACzV,EAAE,OAAO,EAAE,uCAAuC,EAAE,OAAO,EAAE,grOAAgrO,EAAE;IAC/uO,EAAE,OAAO,EAAE,0DAA0D,EAAE,OAAO,EAAE,4jLAA4jL,EAAE;IAC9oL,EAAE,OAAO,EAAE,oDAAoD,EAAE,OAAO,EAAE,ijHAAijH,EAAE;IAC7nH,EAAE,OAAO,EAAE,6CAA6C,EAAE,OAAO,EAAE,8/BAA8/B,EAAE;IACnkC,EAAE,OAAO,EAAE,0CAA0C,EAAE,OAAO,EAAE,uRAAuR,EAAE;IACzV,EAAE,OAAO,EAAE,+BAA+B,EAAE,OAAO,EAAE,w9LAAw9L,EAAE;IAC/gM,EAAE,OAAO,EAAE,2CAA2C,EAAE,OAAO,EAAE,o8nBAAo8nB,EAAE;IACvgoB,EAAE,OAAO,EAAE,2CAA2C,EAAE,OAAO,EAAE,k1nDAAk1nD,EAAE;IACr5nD,EAAE,OAAO,EAAE,iCAAiC,EAAE,OAAO,EAAE,uGAAuG,EAAE;IAChK,EAAE,OAAO,EAAE,kCAAkC,EAAE,OAAO,EAAE,kfAAkf,EAAE;IAC5iB,EAAE,OAAO,EAAE,oCAAoC,EAAE,OAAO,EAAE,qQAAqQ,EAAE;IACjU,EAAE,OAAO,EAAE,mCAAmC,EAAE,OAAO,EAAE,mqLAAmqL,EAAE;IAC9tL,EAAE,OAAO,EAAE,6CAA6C,EAAE,OAAO,EAAE,yrNAAyrN,EAAE;IAC9vN,EAAE,OAAO,EAAE,gDAAgD,EAAE,OAAO,EAAE,o6HAAo6H,EAAE;IAC5+H,EAAE,OAAO,EAAE,yCAAyC,EAAE,OAAO,EAAE,y0CAAy0C,EAAE;IAC14C,EAAE,OAAO,EAAE,sCAAsC,EAAE,OAAO,EAAE,uRAAuR,EAAE;IACrV,EAAE,OAAO,EAAE,kCAAkC,EAAE,OAAO,EAAE,i/XAAi/X,EAAE;IAC3iY,EAAE,OAAO,EAAE,oCAAoC,EAAE,OAAO,EAAE,6EAA6E,EAAE;IACzI,EAAE,OAAO,EAAE,qCAAqC,EAAE,OAAO,EAAE,mXAAmX,EAAE;IAChb,EAAE,OAAO,EAAE,sCAAsC,EAAE,OAAO,EAAE,48JAA48J,EAAE;IAC1gK,EAAE,OAAO,EAAE,4CAA4C,EAAE,OAAO,EAAE,uyCAAuyC,EAAE;IAC32C,EAAE,OAAO,EAAE,kCAAkC,EAAE,OAAO,EAAE,26KAA26K,EAAE;IACr+K,EAAE,OAAO,EAAE,oCAAoC,EAAE,OAAO,EAAE,0GAA0G,EAAE;IACtK,EAAE,OAAO,EAAE,qCAAqC,EAAE,OAAO,EAAE,mlBAAmlB,EAAE;IAChpB,EAAE,OAAO,EAAE,uCAAuC,EAAE,OAAO,EAAE,gqBAAgqB,EAAE;IAC/tB,EAAE,OAAO,EAAE,sCAAsC,EAAE,OAAO,EAAE,22cAA22c,EAAE;IACz6c,EAAE,OAAO,EAAE,wDAAwD,EAAE,OAAO,EAAE,yzJAAyzJ,EAAE;IACz4J,EAAE,OAAO,EAAE,oDAAoD,EAAE,OAAO,EAAE,qytBAAqytB,EAAE;IACj3tB,EAAE,OAAO,EAAE,mDAAmD,EAAE,OAAO,EAAE,ynYAAynY,EAAE;IACpsY,EAAE,OAAO,EAAE,4CAA4C,EAAE,OAAO,EAAE,osHAAosH,EAAE;IACxwH,EAAE,OAAO,EAAE,yCAAyC,EAAE,OAAO,EAAE,6iCAA6iC,EAAE;IAC9mC,EAAE,OAAO,EAAE,wCAAwC,EAAE,OAAO,EAAE,4sFAA4sF,EAAE;IAC5wF,EAAE,OAAO,EAAE,0CAA0C,EAAE,OAAO,EAAE,mFAAmF,EAAE;IACrJ,EAAE,OAAO,EAAE,2CAA2C,EAAE,OAAO,EAAE,yXAAyX,EAAE;IAC5b,EAAE,OAAO,EAAE,4CAA4C,EAAE,OAAO,EAAE,ollBAAollB,EAAE;IACxplB,EAAE,OAAO,EAAE,kDAAkD,EAAE,OAAO,EAAE,sgVAAsgV,EAAE;IAChlV,EAAE,OAAO,EAAE,+CAA+C,EAAE,OAAO,EAAE,oiCAAoiC,EAAE;IAC3mC,EAAE,OAAO,EAAE,0BAA0B,EAAE,OAAO,EAAE,2tCAA2tC,EAAE;IAC7wC,EAAE,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,iGAAiG,EAAE;IACrJ,EAAE,OAAO,EAAE,6BAA6B,EAAE,OAAO,EAAE,2WAA2W,EAAE;IACha,EAAE,OAAO,EAAE,8BAA8B,EAAE,OAAO,EAAE,s1BAAs1B,EAAE;IAC54B,EAAE,OAAO,EAAE,oCAAoC,EAAE,OAAO,EAAE,msBAAmsB,EAAE;IAC/vB,EAAE,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,q3JAAq3J,EAAE;IACz6J,EAAE,OAAO,EAAE,8BAA8B,EAAE,OAAO,EAAE,uEAAuE,EAAE;IAC7H,EAAE,OAAO,EAAE,+BAA+B,EAAE,OAAO,EAAE,6WAA6W,EAAE;IACpa,EAAE,OAAO,EAAE,gCAAgC,EAAE,OAAO,EAAE,kmTAAkmT,EAAE;IAC1pT,EAAE,OAAO,EAAE,sCAAsC,EAAE,OAAO,EAAE,gzCAAgzC,EAAE;CAC/2C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/generated/surface.ts"],"names":[],"mappings":"AAIA,qGAAqG;AACrG,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EA2DzC,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAgBxC,CAAC;AAEF,iGAAiG;AACjG,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAiDhD,CAAC;AAEF,oGAAoG;AACpG,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAaxC,CAAC"}
1
+ {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/generated/surface.ts"],"names":[],"mappings":"AAIA,qGAAqG;AACrG,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EA2DzC,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAsBxC,CAAC;AAEF,iGAAiG;AACjG,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAqDhD,CAAC;AAEF,oGAAoG;AACpG,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAaxC,CAAC"}
@@ -66,10 +66,16 @@ export const CLI_COMMANDS = [
66
66
  export const SDK_EXPORTS = [
67
67
  'annotations',
68
68
  'asset',
69
+ 'bind',
70
+ 'clientCredentials',
71
+ 'connection',
69
72
  'connector',
70
73
  'customerAuth',
71
74
  'embeddedAssistant',
75
+ 'externalExchange',
76
+ 'gmailConnector',
72
77
  'handoffSession',
78
+ 'managedSecret',
73
79
  'openAICompatible',
74
80
  'prompt',
75
81
  'resource',
@@ -128,6 +134,10 @@ export const COMPILE_ERROR_CODES = [
128
134
  'unknown_connector_alias',
129
135
  'connector_not_in_catalog',
130
136
  'unknown_operation',
137
+ 'connector_binding_required',
138
+ 'unsupported_credential_profile',
139
+ 'credential_scope_mismatch',
140
+ 'credential_audience_mismatch',
131
141
  'unused_connector_alias',
132
142
  'arg_mismatch',
133
143
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"surface.js","sourceRoot":"","sources":["../../src/generated/surface.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,6EAA6E;AAC7E,iGAAiG;AAEjG,qGAAqG;AACrG,MAAM,CAAC,MAAM,YAAY,GAAsB;IAC7C,MAAM;IACN,SAAS;IACT,UAAU;IACV,UAAU;IACV,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,MAAM;IACN,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,OAAO;IACP,MAAM;IACN,OAAO;IACP,WAAW;IACX,SAAS;IACT,KAAK;IACL,UAAU;IACV,OAAO;IACP,SAAS;IACT,MAAM;IACN,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,eAAe;IACf,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,SAAS;IACT,OAAO;IACP,UAAU;IACV,SAAS;IACT,SAAS;IACT,QAAQ;IACR,MAAM;IACN,MAAM;IACN,aAAa;IACb,SAAS;IACT,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,MAAM;IACN,MAAM;IACN,SAAS;IACT,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,SAAS;IACT,WAAW;CACZ,CAAC;AAEF,8FAA8F;AAC9F,MAAM,CAAC,MAAM,WAAW,GAAsB;IAC5C,aAAa;IACb,OAAO;IACP,WAAW;IACX,cAAc;IACd,mBAAmB;IACnB,gBAAgB;IAChB,kBAAkB;IAClB,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,UAAU;IACV,MAAM;IACN,GAAG;CACJ,CAAC;AAEF,iGAAiG;AACjG,MAAM,CAAC,MAAM,mBAAmB,GAAsB;IACpD,0BAA0B;IAC1B,kBAAkB;IAClB,eAAe;IACf,cAAc;IACd,gBAAgB;IAChB,eAAe;IACf,8BAA8B;IAC9B,6BAA6B;IAC7B,uBAAuB;IACvB,cAAc;IACd,oBAAoB;IACpB,oBAAoB;IACpB,qBAAqB;IACrB,oBAAoB;IACpB,mBAAmB;IACnB,uBAAuB;IACvB,2BAA2B;IAC3B,qBAAqB;IACrB,kBAAkB;IAClB,kBAAkB;IAClB,eAAe;IACf,mBAAmB;IACnB,oBAAoB;IACpB,4BAA4B;IAC5B,0BAA0B;IAC1B,2BAA2B;IAC3B,mBAAmB;IACnB,wBAAwB;IACxB,oBAAoB;IACpB,kBAAkB;IAClB,wBAAwB;IACxB,0BAA0B;IAC1B,kBAAkB;IAClB,qBAAqB;IACrB,4BAA4B;IAC5B,uBAAuB;IACvB,wBAAwB;IACxB,6BAA6B;IAC7B,uBAAuB;IACvB,6BAA6B;IAC7B,eAAe;IACf,gCAAgC;IAChC,oBAAoB;IACpB,yBAAyB;IACzB,0BAA0B;IAC1B,mBAAmB;IACnB,wBAAwB;IACxB,cAAc;CACf,CAAC;AAEF,oGAAoG;AACpG,MAAM,CAAC,MAAM,WAAW,GAAsB;IAC5C,aAAa;IACb,aAAa;IACb,cAAc;IACd,WAAW;IACX,aAAa;IACb,uBAAuB;IACvB,iBAAiB;IACjB,wBAAwB;IACxB,uBAAuB;IACvB,oBAAoB;IACpB,YAAY;IACZ,YAAY;CACb,CAAC"}
1
+ {"version":3,"file":"surface.js","sourceRoot":"","sources":["../../src/generated/surface.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,6EAA6E;AAC7E,iGAAiG;AAEjG,qGAAqG;AACrG,MAAM,CAAC,MAAM,YAAY,GAAsB;IAC7C,MAAM;IACN,SAAS;IACT,UAAU;IACV,UAAU;IACV,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,MAAM;IACN,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,OAAO;IACP,MAAM;IACN,OAAO;IACP,WAAW;IACX,SAAS;IACT,KAAK;IACL,UAAU;IACV,OAAO;IACP,SAAS;IACT,MAAM;IACN,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,eAAe;IACf,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,SAAS;IACT,OAAO;IACP,UAAU;IACV,SAAS;IACT,SAAS;IACT,QAAQ;IACR,MAAM;IACN,MAAM;IACN,aAAa;IACb,SAAS;IACT,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,MAAM;IACN,MAAM;IACN,SAAS;IACT,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,SAAS;IACT,WAAW;CACZ,CAAC;AAEF,8FAA8F;AAC9F,MAAM,CAAC,MAAM,WAAW,GAAsB;IAC5C,aAAa;IACb,OAAO;IACP,MAAM;IACN,mBAAmB;IACnB,YAAY;IACZ,WAAW;IACX,cAAc;IACd,mBAAmB;IACnB,kBAAkB;IAClB,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,kBAAkB;IAClB,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,UAAU;IACV,MAAM;IACN,GAAG;CACJ,CAAC;AAEF,iGAAiG;AACjG,MAAM,CAAC,MAAM,mBAAmB,GAAsB;IACpD,0BAA0B;IAC1B,kBAAkB;IAClB,eAAe;IACf,cAAc;IACd,gBAAgB;IAChB,eAAe;IACf,8BAA8B;IAC9B,6BAA6B;IAC7B,uBAAuB;IACvB,cAAc;IACd,oBAAoB;IACpB,oBAAoB;IACpB,qBAAqB;IACrB,oBAAoB;IACpB,mBAAmB;IACnB,uBAAuB;IACvB,2BAA2B;IAC3B,qBAAqB;IACrB,kBAAkB;IAClB,kBAAkB;IAClB,eAAe;IACf,mBAAmB;IACnB,oBAAoB;IACpB,4BAA4B;IAC5B,0BAA0B;IAC1B,2BAA2B;IAC3B,mBAAmB;IACnB,wBAAwB;IACxB,oBAAoB;IACpB,kBAAkB;IAClB,wBAAwB;IACxB,0BAA0B;IAC1B,kBAAkB;IAClB,qBAAqB;IACrB,4BAA4B;IAC5B,uBAAuB;IACvB,wBAAwB;IACxB,6BAA6B;IAC7B,uBAAuB;IACvB,6BAA6B;IAC7B,eAAe;IACf,gCAAgC;IAChC,oBAAoB;IACpB,yBAAyB;IACzB,0BAA0B;IAC1B,mBAAmB;IACnB,4BAA4B;IAC5B,gCAAgC;IAChC,2BAA2B;IAC3B,8BAA8B;IAC9B,wBAAwB;IACxB,cAAc;CACf,CAAC;AAEF,oGAAoG;AACpG,MAAM,CAAC,MAAM,WAAW,GAAsB;IAC5C,aAAa;IACb,aAAa;IACb,cAAc;IACd,WAAW;IACX,aAAa;IACb,uBAAuB;IACvB,iBAAiB;IACjB,wBAAwB;IACxB,uBAAuB;IACvB,oBAAoB;IACpB,YAAY;IACZ,YAAY;CACb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"skill-authoring-refs.d.ts","sourceRoot":"","sources":["../src/skill-authoring-refs.ts"],"names":[],"mappings":"AAgBA,wBAAgB,gCAAgC,IAAI,MAAM,CAqUzD;AAWD,wBAAgB,6BAA6B,IAAI,MAAM,CAoPtD;AA2CD,wBAAgB,uBAAuB,IAAI,MAAM,CA0DhD"}
1
+ {"version":3,"file":"skill-authoring-refs.d.ts","sourceRoot":"","sources":["../src/skill-authoring-refs.ts"],"names":[],"mappings":"AAgBA,wBAAgB,gCAAgC,IAAI,MAAM,CAuUzD;AAWD,wBAAgB,6BAA6B,IAAI,MAAM,CAoPtD;AA+CD,wBAAgB,uBAAuB,IAAI,MAAM,CA0DhD"}
@@ -57,6 +57,8 @@ export function renderAuthoringWorkflowReference() {
57
57
  '',
58
58
  'HTTP connector auth variants: `bearer` (`{ kind: "bearer", secret: secret("API_TOKEN") }`), `apiKey` (`{ kind: "apiKey", header: "X-API-Key", secret: secret("API_KEY") }`), `clientCredentials`, `delegatedOAuth`, `delegatedSessionCookie`, and `delegatedTokenExchange` (per-user calls to your own API — see "Delegated downstream auth" below). Use managed `secret(...)` / `variable(...)` refs for all values that differ by org/app/env.',
59
59
  '',
60
+ 'When one connector needs independently selectable accounts, declare catalog `credentialProfiles` plus each operation’s accepted `credentials.profiles`, then bind each `server.use` alias with `bind(connector, { profile, connection: connection("logical_id", managedSecret(secret("NAME"), { scopes, audience })) })`. The alias is the stable account boundary; never put provider account ids, labels, or credential values in it. `gmailConnector()` is the curated Gmail catalog helper; reuse it under independent aliases and accept canonical `accounts` arrays in tools (one account for writes, or an explicitly ordered supported combination for reads). See the bundled `gmail-multi-account` flagship. Bound managed secrets are supported by hosted execution. `externalExchange()` is runnable only when the deployment operator injects an exact HTTPS provider endpoint/origin/audience and durable shared subject-pin store through service ports; Noodle sends a short-lived platform-signed deployment workload assertion and accepts only a bounded bearer response. Provider implementations must consume assertion replay ids through durable shared atomic storage across instances and restarts. There is intentionally no hosted enrollment or provider CRUD surface yet. The provider wire contract is public, but its conformance kit is workspace/source-only and is not an installable npm package. Bound `clientCredentials(...)` remains fail-closed until its provider slice lands.',
61
+ '',
60
62
  '## HTTP connector example (full server)',
61
63
  '',
62
64
  'Declare the API as data, bind it with `use`, then record calls in tools. The operation mapping in detail: `request` builds the JSON request body, `query: [...]` names the input args sent as URL query parameters, and `response` maps the parsed HTTP body (bound to `${response}`) into your typed `output`. `auth` reads a managed `secret(...)` — never inline a key. This whole example is compile-verified on every `pnpm test`.',
@@ -289,7 +291,7 @@ export function renderAuthoringWorkflowReference() {
289
291
  '});',
290
292
  '```',
291
293
  '',
292
- 'Use a stable lowercase/number/underscore id and a flat form of string/number/integer/boolean, string choices or multi-select, with optional `email`, `uri`, `date`, or `date-time` formats. Nested objects and credential-shaped fields fail with `invalid_elicitation_schema`. Every interactive flow must place all `ctx.elicit` calls before its first connector operation or compilation fails with `invalid_elicitation_flow`. Embedded/headless clients receive `input_requested`; bidirectional MCP transports map the primitive to standard form `elicitation/create`. On stateless hosts, the adapter returns a structured non-executing `interaction_unavailable` result; linked Apps render its business-user form and retry in request `_meta`, while models can use the advertised reserved retry field. Accept validates and replays only the operation-free input prefix; invalid content returns `arg_invalid`, and decline/cancel stop. Elicitation gathers missing input and does not replace confirmation. In a flow marked `confirm: true`, every eligible `input_requested` precedes `tool_proposed`; the final proposal reviews the original input, elicited values, and sole exact connector action. Accept is bound to that action and only then may execution start. A confirmable flow may contain at most one connector operation; additional operations fail with `invalid_confirmation_flow`. MCP uses final standard form confirmation on capable bidirectional transports and fails closed otherwise. Setting `interactions: { confirmationFallback: "host" }` in the server options explicitly trusts native host approval only when confirmation transport is unavailable and after every elicited field is collected; it is never inferred from client name and does not replace authorization. Omitted or `false` annotations execute directly; hints alone never gate. `annotations.action({ confirm: true })` explicitly enables confirmation; `annotations.action({ confirm: false })` explicitly preserves direct execution.',
294
+ 'Use a stable lowercase/number/underscore id and a flat form of string/number/integer/boolean, string choices or multi-select, with optional `email`, `uri`, `date`, or `date-time` formats. Nested objects and credential-shaped fields fail with `invalid_elicitation_schema`. Every interactive flow must place all `ctx.elicit` calls before its first connector operation or compilation fails with `invalid_elicitation_flow`. Embedded/headless clients receive `input_requested`; bidirectional MCP transports map the primitive to standard form `elicitation/create`. On stateless hosts, the adapter returns a structured non-executing `interaction_unavailable` result; linked Apps render its business-user form and retry in request `_meta`, while models can use the advertised reserved retry field. Accept validates and replays only the operation-free input prefix; invalid content returns `arg_invalid`, and decline/cancel stop. Elicitation gathers missing input and does not replace confirmation. In a flow marked `confirm: true`, every eligible `input_requested` precedes `tool_proposed`; the final proposal reviews the original input, elicited values, and sole exact eligible connector action. Conditional branches may declare multiple candidate actions only when preparation resolves exactly one eligible action from input/context or completed pure steps; zero or multiple actions fail with `invalid_confirmation_flow` before I/O. Acceptance is bound to that exact action. Later read-only operations and pure compute may assemble output, but a second eligible action fails closed. Use `ref.at(index)` for array access in recorded expressions. MCP uses final standard form confirmation on capable bidirectional transports and fails closed otherwise. Setting `interactions: { confirmationFallback: "host" }` in the server options explicitly trusts native host approval only when confirmation transport is unavailable and after every elicited field is collected; it still uses preparation and prepared execution, is never inferred from client name, and does not replace authorization. Omitted or `false` annotations execute directly; hints alone never gate. `annotations.action({ confirm: true })` explicitly enables confirmation; `annotations.action({ confirm: false })` explicitly preserves direct execution.',
293
295
  '',
294
296
  '## Compute connector example',
295
297
  '',
@@ -623,6 +625,10 @@ const FLAGSHIP_EXAMPLES = [
623
625
  ['stateful-draft', 'Durable, caller-scoped widget state handles with optimistic revisions.'],
624
626
  ['perplexity', 'A real SaaS API with bearer auth and a managed `secret`.'],
625
627
  ['bitcoin', 'API-key HTTP connector, custom auth header, and compute normalization.'],
628
+ [
629
+ 'gmail-multi-account',
630
+ 'One curated Gmail connector reused by two account bindings, canonical account arrays, exact mutation confirmation, and an accompanying personal-automation skill.',
631
+ ],
626
632
  ['sharepoint', 'Microsoft SharePoint delegated Microsoft Entra auth and Graph tools.'],
627
633
  [
628
634
  'internal-ops-demo',
@@ -1 +1 @@
1
- {"version":3,"file":"skill-authoring-refs.js","sourceRoot":"","sources":["../src/skill-authoring-refs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skill-authoring-refs.js","sourceRoot":"","sources":["../src/skill-authoring-refs.ts"],"names":[],"mappings":"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"}
@@ -187,7 +187,7 @@ export function renderEmbeddedAssistantReference() {
187
187
  '',
188
188
  '## Structured missing input',
189
189
  '',
190
- 'A tool authored with `ctx.elicit({ id, message, input })` produces `input_requested` when it reaches missing input. Built-in and headless renderers present it and call `respond(id, { action: "accept", content })`; decline/cancel stop. Accepted content is schema-validated and completed steps are not rerun; invalid content returns `arg_invalid` and keeps the interaction pending. Elicitation gathers an input and does not approve a later write. Every interactive flow collects elicited input before its first connector operation; every eligible `input_requested` precedes `tool_proposed`. In a `confirm: true` flow, the final proposal reviews original input, elicited values, and the sole exact connector action; a confirmable flow has at most one connector operation. Accept is bound to that action. Bidirectional MCP maps missing input to standard `elicitation/create`. On a stateless host, a linked MCP App presents the same normal-user form and re-calls the tool through standard `tools/call`, carrying replay answers in request `_meta` so approval copy contains only business fields; without Apps, the model receives the exact structured schema and an advertised reserved retry field. Both paths replay only the operation-free input prefix and never expose runtime continuation or environment state. Setting `interactions: { confirmationFallback: "host" }` explicitly trusts native host approval only after every elicited field is collected and only when confirmation transport is unavailable; embedded/headless confirmation remains Noodle-owned. Omitted or false annotations execute directly; hints never gate.',
190
+ 'A tool authored with `ctx.elicit({ id, message, input })` produces `input_requested` when it reaches missing input. Built-in and headless renderers present it and call `respond(id, { action: "accept", content })`; decline/cancel stop. Accepted content is schema-validated and completed steps are not rerun; invalid content returns `arg_invalid` and keeps the interaction pending. Elicitation gathers an input and does not approve a later write. Every interactive flow collects elicited input before its first connector operation; every eligible `input_requested` precedes `tool_proposed`. In a `confirm: true` flow, the final proposal reviews original input, elicited values, and the sole exact eligible connector action. Conditional branches may declare candidate actions and later reads only when preparation resolves exactly one action, discloses later eligible operations, and fails with `invalid_confirmation_flow` for zero or multiple actions. Accept is bound to that action. Bidirectional MCP maps missing input to standard `elicitation/create`. On a stateless host, a linked MCP App presents the same normal-user form and re-calls the tool through standard `tools/call`, carrying replay answers in request `_meta` so approval copy contains only business fields; without Apps, the model receives the exact structured schema and an advertised reserved retry field. Both paths replay only the operation-free input prefix and never expose runtime continuation or environment state. Setting `interactions: { confirmationFallback: "host" }` explicitly trusts native host approval only after every elicited field is collected and only when confirmation transport is unavailable; it still uses the same prepared-action safety path. Embedded/headless confirmation remains Noodle-owned. Omitted or false annotations execute directly; hints never gate.',
191
191
  '',
192
192
  '## Verified session context (identity and claims)',
193
193
  '',
@@ -1 +1 @@
1
- {"version":3,"file":"skill-embedded-assistant-ref.js","sourceRoot":"","sources":["../src/skill-embedded-assistant-ref.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skill-embedded-assistant-ref.js","sourceRoot":"","sources":["../src/skill-embedded-assistant-ref.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noodle-borg/agent-kit",
3
- "version": "0.34.0",
3
+ "version": "0.35.0",
4
4
  "private": true,
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -0,0 +1,52 @@
1
+ import type { ConfigRef } from './config.js';
2
+ declare const connectionSourceBrand: unique symbol;
3
+ /** Credential source descriptors carry managed reference names only, never credential values. */
4
+ type ConnectionSourceShape = {
5
+ readonly kind: 'externalExchange';
6
+ } | {
7
+ readonly kind: 'managedSecret';
8
+ readonly secret: string;
9
+ readonly scopes?: readonly string[];
10
+ readonly audience?: string;
11
+ } | {
12
+ readonly kind: 'clientCredentials';
13
+ readonly tokenUrl: string;
14
+ readonly clientId: string;
15
+ readonly clientSecret: string;
16
+ readonly scopes?: readonly string[];
17
+ readonly audience?: string;
18
+ readonly authMethod?: 'client_secret_basic' | 'client_secret_post';
19
+ };
20
+ /**
21
+ * An opaque credential source created by one of the canonical source factories. The private brand keeps
22
+ * raw structural objects (and therefore accidental credential literals) out of `connection(...)`.
23
+ */
24
+ export type ConnectionSource = ConnectionSourceShape & {
25
+ readonly [connectionSourceBrand]: true;
26
+ };
27
+ /** A deployment-owned external exchange connection. Provider lifecycle stays outside Core. */
28
+ export declare function externalExchange(): ConnectionSource;
29
+ /** A connection backed by one managed secret reference and any capabilities known for that secret. */
30
+ export declare function managedSecret(secret: ConfigRef, capabilities?: {
31
+ readonly scopes?: readonly string[];
32
+ readonly audience?: string;
33
+ }): ConnectionSource;
34
+ /** A connection whose short-lived bearer is minted from managed client-credentials references. */
35
+ export declare function clientCredentials(options: {
36
+ readonly tokenUrl: ConfigRef;
37
+ readonly clientId: ConfigRef;
38
+ readonly clientSecret: ConfigRef;
39
+ readonly scopes?: readonly string[];
40
+ readonly audience?: string;
41
+ readonly authMethod?: 'client_secret_basic' | 'client_secret_post';
42
+ }): ConnectionSource;
43
+ export interface ConnectionRef {
44
+ readonly id: string;
45
+ readonly source: ConnectionSource;
46
+ }
47
+ export interface ConnectionBinding<ProfileKey extends string = string> {
48
+ readonly profile: ProfileKey;
49
+ readonly connection: ConnectionRef;
50
+ }
51
+ export {};
52
+ //# sourceMappingURL=connection-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-types.d.ts","sourceRoot":"","sources":["../src/connection-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,QAAA,MAAM,qBAAqB,EAAE,OAAO,MAA0C,CAAC;AAE/E,iGAAiG;AACjG,KAAK,qBAAqB,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAA;CAAE,GACrC;IACE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,qBAAqB,GAAG,oBAAoB,CAAC;CACpE,CAAC;AAEN;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,qBAAqB,GAAG;IACrD,QAAQ,CAAC,CAAC,qBAAqB,CAAC,EAAE,IAAI,CAAC;CACxC,CAAC;AAiBF,8FAA8F;AAC9F,wBAAgB,gBAAgB,IAAI,gBAAgB,CAEnD;AAED,sGAAsG;AACtG,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,EACjB,YAAY,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACrF,gBAAgB,CAOlB;AAED,kGAAkG;AAClG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,qBAAqB,GAAG,oBAAoB,CAAC;CACpE,GAAG,gBAAgB,CAUnB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CACnC;AAED,MAAM,WAAW,iBAAiB,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM;IACnE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;CACpC"}
@@ -0,0 +1,35 @@
1
+ import { serializeSecretRef, serializeVariableRef } from './config.js';
2
+ const connectionSourceBrand = Symbol('noodle.connectionSource');
3
+ function markConnectionSource(source) {
4
+ brandConnectionSource(source);
5
+ return source;
6
+ }
7
+ function brandConnectionSource(source) {
8
+ Object.defineProperty(source, connectionSourceBrand, { value: true });
9
+ }
10
+ /** A deployment-owned external exchange connection. Provider lifecycle stays outside Core. */
11
+ export function externalExchange() {
12
+ return markConnectionSource({ kind: 'externalExchange' });
13
+ }
14
+ /** A connection backed by one managed secret reference and any capabilities known for that secret. */
15
+ export function managedSecret(secret, capabilities = {}) {
16
+ return markConnectionSource({
17
+ kind: 'managedSecret',
18
+ secret: serializeSecretRef(secret, 'connection.source.secret'),
19
+ ...(capabilities.scopes !== undefined ? { scopes: [...capabilities.scopes] } : {}),
20
+ ...(capabilities.audience !== undefined ? { audience: capabilities.audience } : {}),
21
+ });
22
+ }
23
+ /** A connection whose short-lived bearer is minted from managed client-credentials references. */
24
+ export function clientCredentials(options) {
25
+ return markConnectionSource({
26
+ kind: 'clientCredentials',
27
+ tokenUrl: serializeVariableRef(options.tokenUrl, 'connection.source.tokenUrl'),
28
+ clientId: serializeVariableRef(options.clientId, 'connection.source.clientId'),
29
+ clientSecret: serializeSecretRef(options.clientSecret, 'connection.source.clientSecret'),
30
+ ...(options.scopes !== undefined ? { scopes: [...options.scopes] } : {}),
31
+ ...(options.audience !== undefined ? { audience: options.audience } : {}),
32
+ ...(options.authMethod !== undefined ? { authMethod: options.authMethod } : {}),
33
+ });
34
+ }
35
+ //# sourceMappingURL=connection-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-types.js","sourceRoot":"","sources":["../src/connection-types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,qBAAqB,GAAkB,MAAM,CAAC,yBAAyB,CAAC,CAAC;AA+B/E,SAAS,oBAAoB,CAC3B,MAAa;IAEb,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,qBAAqB,CAC5B,MAAa;IAEb,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,qBAAqB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,gBAAgB;IAC9B,OAAO,oBAAoB,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,aAAa,CAC3B,MAAiB,EACjB,eAAoF,EAAE;IAEtF,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,kBAAkB,CAAC,MAAM,EAAE,0BAA0B,CAAC;QAC9D,GAAG,CAAC,YAAY,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,GAAG,CAAC,YAAY,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpF,CAAC,CAAC;AACL,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,iBAAiB,CAAC,OAOjC;IACC,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,mBAAmB;QACzB,QAAQ,EAAE,oBAAoB,CAAC,OAAO,CAAC,QAAQ,EAAE,4BAA4B,CAAC;QAC9E,QAAQ,EAAE,oBAAoB,CAAC,OAAO,CAAC,QAAQ,EAAE,4BAA4B,CAAC;QAC9E,YAAY,EAAE,kBAAkB,CAAC,OAAO,CAAC,YAAY,EAAE,gCAAgC,CAAC;QACxF,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ConnectionBinding, ConnectionRef, ConnectionSource } from './connection-types.js';
2
+ import type { ConnectorRef } from './connectors.js';
3
+ export { clientCredentials, externalExchange, managedSecret } from './connection-types.js';
4
+ /** Name one logical connection. The id is stable app configuration, not a provider account id. */
5
+ export declare function connection(id: string, source: ConnectionSource): ConnectionRef;
6
+ /** Bind a connector ref to one credential profile and logical connection. */
7
+ export interface BoundConnectorRef<ProfileKey extends string = string> extends ConnectorRef<ProfileKey> {
8
+ readonly binding: ConnectionBinding<ProfileKey>;
9
+ }
10
+ export declare function bind<ProfileKey extends string>(connector: ConnectorRef<ProfileKey>, options: {
11
+ readonly profile: NoInfer<ProfileKey>;
12
+ readonly connection: ConnectionRef;
13
+ }): BoundConnectorRef<ProfileKey>;
14
+ export type { ConnectionBinding, ConnectionRef, ConnectionSource } from './connection-types.js';
15
+ type ManifestV2ConnectorBinding = NonNullable<NonNullable<Extract<Manifest, {
16
+ manifestVersion: '2';
17
+ }>['connectors']>[string]['binding']>;
18
+ /** Internal manifest projection: clone readonly author inputs to the mutable generated schema shape. */
19
+ export declare function toManifestConnectionBinding(binding: ConnectionBinding): ManifestV2ConnectorBinding;
20
+ export declare function toManifestConnectorRef(connector: ConnectorRef): {
21
+ readonly id: string;
22
+ readonly version: string;
23
+ readonly binding?: ManifestV2ConnectorBinding;
24
+ };
25
+ import type { Manifest } from '@noodle-borg/compiler';
26
+ //# sourceMappingURL=connections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../src/connections.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI3F,kGAAkG;AAClG,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,aAAa,CAK9E;AAED,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM,CACnE,SAAQ,YAAY,CAAC,UAAU,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC;CACjD;AAED,wBAAgB,IAAI,CAAC,UAAU,SAAS,MAAM,EAC5C,SAAS,EAAE,YAAY,CAAC,UAAU,CAAC,EACnC,OAAO,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAA;CAAE,GACrF,iBAAiB,CAAC,UAAU,CAAC,CAiB/B;AAED,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEhG,KAAK,0BAA0B,GAAG,WAAW,CAC3C,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE;IAAE,eAAe,EAAE,GAAG,CAAA;CAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAC1F,CAAC;AAEF,wGAAwG;AACxG,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,iBAAiB,GACzB,0BAA0B,CA2B5B;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,YAAY,GAAG;IAC/D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,0BAA0B,CAAC;CAC/C,CAQA;AAED,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}