@wrenai/genbi 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +141 -0
  3. package/bin/genbi.mjs +31 -0
  4. package/dist/assets/echarts-LTFC-ysd.js +40 -0
  5. package/dist/assets/index-Bo--QMUN.js +441 -0
  6. package/dist/assets/index-Xs4q7pNo.css +1 -0
  7. package/dist/index.html +14 -0
  8. package/dist/wrenai_logo.png +0 -0
  9. package/dist/wrenai_logo_white.png +0 -0
  10. package/dist-server/harness/auth/detect.d.ts +18 -0
  11. package/dist-server/harness/auth/detect.js +37 -0
  12. package/dist-server/harness/auth/index.d.ts +4 -0
  13. package/dist-server/harness/auth/index.js +2 -0
  14. package/dist-server/harness/auth/probe.d.ts +18 -0
  15. package/dist-server/harness/auth/probe.js +52 -0
  16. package/dist-server/harness/auth/types.d.ts +42 -0
  17. package/dist-server/harness/auth/types.js +9 -0
  18. package/dist-server/harness/bundle/loader.d.ts +32 -0
  19. package/dist-server/harness/bundle/loader.js +43 -0
  20. package/dist-server/harness/bundle/schema.d.ts +199 -0
  21. package/dist-server/harness/bundle/schema.js +127 -0
  22. package/dist-server/harness/bundle/version.d.ts +10 -0
  23. package/dist-server/harness/bundle/version.js +43 -0
  24. package/dist-server/harness/capability/gate.d.ts +6 -0
  25. package/dist-server/harness/capability/gate.js +29 -0
  26. package/dist-server/harness/capability/registry.d.ts +6 -0
  27. package/dist-server/harness/capability/registry.js +17 -0
  28. package/dist-server/harness/cli-args.d.ts +123 -0
  29. package/dist-server/harness/cli-args.js +247 -0
  30. package/dist-server/harness/cli.d.ts +2 -0
  31. package/dist-server/harness/cli.js +151 -0
  32. package/dist-server/harness/compile/cache.d.ts +23 -0
  33. package/dist-server/harness/compile/cache.js +109 -0
  34. package/dist-server/harness/compile/compose-profile.d.ts +34 -0
  35. package/dist-server/harness/compile/compose-profile.js +95 -0
  36. package/dist-server/harness/compile/errors.d.ts +22 -0
  37. package/dist-server/harness/compile/errors.js +41 -0
  38. package/dist-server/harness/compile/fingerprint.d.ts +22 -0
  39. package/dist-server/harness/compile/fingerprint.js +84 -0
  40. package/dist-server/harness/compile/index.d.ts +8 -0
  41. package/dist-server/harness/compile/index.js +7 -0
  42. package/dist-server/harness/compile/pipeline.d.ts +66 -0
  43. package/dist-server/harness/compile/pipeline.js +176 -0
  44. package/dist-server/harness/compile/resolve-binary.d.ts +55 -0
  45. package/dist-server/harness/compile/resolve-binary.js +133 -0
  46. package/dist-server/harness/compile/types.d.ts +107 -0
  47. package/dist-server/harness/compile/types.js +1 -0
  48. package/dist-server/harness/compile/warble-identity.d.ts +12 -0
  49. package/dist-server/harness/compile/warble-identity.js +33 -0
  50. package/dist-server/harness/compliance/gate.d.ts +35 -0
  51. package/dist-server/harness/compliance/gate.js +48 -0
  52. package/dist-server/harness/compliance/index.d.ts +2 -0
  53. package/dist-server/harness/compliance/index.js +1 -0
  54. package/dist-server/harness/compliance/types.d.ts +16 -0
  55. package/dist-server/harness/compliance/types.js +1 -0
  56. package/dist-server/harness/events/emitter.d.ts +34 -0
  57. package/dist-server/harness/events/emitter.js +25 -0
  58. package/dist-server/harness/events/index.d.ts +4 -0
  59. package/dist-server/harness/events/index.js +2 -0
  60. package/dist-server/harness/events/sse.d.ts +20 -0
  61. package/dist-server/harness/events/sse.js +48 -0
  62. package/dist-server/harness/events/types.d.ts +131 -0
  63. package/dist-server/harness/events/types.js +1 -0
  64. package/dist-server/harness/exec/errors.d.ts +16 -0
  65. package/dist-server/harness/exec/errors.js +29 -0
  66. package/dist-server/harness/exec/index.d.ts +5 -0
  67. package/dist-server/harness/exec/index.js +2 -0
  68. package/dist-server/harness/exec/local.d.ts +32 -0
  69. package/dist-server/harness/exec/local.js +134 -0
  70. package/dist-server/harness/exec/policy.d.ts +12 -0
  71. package/dist-server/harness/exec/policy.js +1 -0
  72. package/dist-server/harness/exec/types.d.ts +63 -0
  73. package/dist-server/harness/exec/types.js +1 -0
  74. package/dist-server/harness/guardrails/index.d.ts +2 -0
  75. package/dist-server/harness/guardrails/index.js +1 -0
  76. package/dist-server/harness/guardrails/policy.d.ts +45 -0
  77. package/dist-server/harness/guardrails/policy.js +57 -0
  78. package/dist-server/harness/index.d.ts +37 -0
  79. package/dist-server/harness/index.js +19 -0
  80. package/dist-server/harness/loop/errors.d.ts +53 -0
  81. package/dist-server/harness/loop/errors.js +72 -0
  82. package/dist-server/harness/loop/executor.d.ts +123 -0
  83. package/dist-server/harness/loop/executor.js +380 -0
  84. package/dist-server/harness/loop/guard.d.ts +16 -0
  85. package/dist-server/harness/loop/guard.js +1 -0
  86. package/dist-server/harness/loop/index.d.ts +5 -0
  87. package/dist-server/harness/loop/index.js +3 -0
  88. package/dist-server/harness/native-producer/index.d.ts +109 -0
  89. package/dist-server/harness/native-producer/index.js +302 -0
  90. package/dist-server/harness/npm-package-resolve.d.ts +28 -0
  91. package/dist-server/harness/npm-package-resolve.js +47 -0
  92. package/dist-server/harness/providers/adapters/anthropic.d.ts +7 -0
  93. package/dist-server/harness/providers/adapters/anthropic.js +6 -0
  94. package/dist-server/harness/providers/adapters/mock.d.ts +4 -0
  95. package/dist-server/harness/providers/adapters/mock.js +5 -0
  96. package/dist-server/harness/providers/adapters/openai-compatible.d.ts +10 -0
  97. package/dist-server/harness/providers/adapters/openai-compatible.js +10 -0
  98. package/dist-server/harness/providers/binding.d.ts +23 -0
  99. package/dist-server/harness/providers/binding.js +13 -0
  100. package/dist-server/harness/providers/errors.d.ts +6 -0
  101. package/dist-server/harness/providers/errors.js +12 -0
  102. package/dist-server/harness/providers/index.d.ts +18 -0
  103. package/dist-server/harness/providers/index.js +22 -0
  104. package/dist-server/harness/providers/registry.d.ts +16 -0
  105. package/dist-server/harness/providers/registry.js +24 -0
  106. package/dist-server/harness/render/envelope.d.ts +145 -0
  107. package/dist-server/harness/render/envelope.js +428 -0
  108. package/dist-server/harness/render/errors.d.ts +33 -0
  109. package/dist-server/harness/render/errors.js +46 -0
  110. package/dist-server/harness/render/index.d.ts +5 -0
  111. package/dist-server/harness/render/index.js +3 -0
  112. package/dist-server/harness/render/validate.d.ts +13 -0
  113. package/dist-server/harness/render/validate.js +88 -0
  114. package/dist-server/harness/route/adapter-spec.d.ts +40 -0
  115. package/dist-server/harness/route/adapter-spec.js +61 -0
  116. package/dist-server/harness/route/agent-sdk-cli.d.ts +30 -0
  117. package/dist-server/harness/route/agent-sdk-cli.js +86 -0
  118. package/dist-server/harness/route/agent-sdk-manifest.d.ts +31 -0
  119. package/dist-server/harness/route/agent-sdk-manifest.js +56 -0
  120. package/dist-server/harness/route/artifact-content.d.ts +53 -0
  121. package/dist-server/harness/route/artifact-content.js +83 -0
  122. package/dist-server/harness/route/chat-event-mapper.d.ts +95 -0
  123. package/dist-server/harness/route/chat-event-mapper.js +164 -0
  124. package/dist-server/harness/route/codex-ask-events.d.ts +25 -0
  125. package/dist-server/harness/route/codex-ask-events.js +395 -0
  126. package/dist-server/harness/route/codex-ask.d.ts +15 -0
  127. package/dist-server/harness/route/codex-ask.js +242 -0
  128. package/dist-server/harness/route/codex-local-cli.d.ts +20 -0
  129. package/dist-server/harness/route/codex-local-cli.js +78 -0
  130. package/dist-server/harness/route/codex-local-manifest.d.ts +22 -0
  131. package/dist-server/harness/route/codex-local-manifest.js +180 -0
  132. package/dist-server/harness/route/describe.d.ts +54 -0
  133. package/dist-server/harness/route/describe.js +84 -0
  134. package/dist-server/harness/route/dispatched.d.ts +138 -0
  135. package/dist-server/harness/route/dispatched.js +339 -0
  136. package/dist-server/harness/route/in-process.d.ts +43 -0
  137. package/dist-server/harness/route/in-process.js +106 -0
  138. package/dist-server/harness/route/index.d.ts +19 -0
  139. package/dist-server/harness/route/index.js +12 -0
  140. package/dist-server/harness/route/profile-source.d.ts +37 -0
  141. package/dist-server/harness/route/profile-source.js +76 -0
  142. package/dist-server/harness/route/route.d.ts +33 -0
  143. package/dist-server/harness/route/route.js +114 -0
  144. package/dist-server/harness/route/tier-binding.d.ts +36 -0
  145. package/dist-server/harness/route/tier-binding.js +63 -0
  146. package/dist-server/harness/route/types.d.ts +286 -0
  147. package/dist-server/harness/route/types.js +1 -0
  148. package/dist-server/harness/session/errors.d.ts +4 -0
  149. package/dist-server/harness/session/errors.js +7 -0
  150. package/dist-server/harness/session/gate.d.ts +11 -0
  151. package/dist-server/harness/session/gate.js +13 -0
  152. package/dist-server/harness/session/index.d.ts +5 -0
  153. package/dist-server/harness/session/index.js +3 -0
  154. package/dist-server/harness/session/run.d.ts +60 -0
  155. package/dist-server/harness/session/run.js +333 -0
  156. package/dist-server/harness/session/types.d.ts +29 -0
  157. package/dist-server/harness/session/types.js +1 -0
  158. package/dist-server/harness/setup/codex-events.d.ts +12 -0
  159. package/dist-server/harness/setup/codex-events.js +108 -0
  160. package/dist-server/harness/setup/runner.d.ts +497 -0
  161. package/dist-server/harness/setup/runner.js +1314 -0
  162. package/dist-server/harness/tools/errors.d.ts +107 -0
  163. package/dist-server/harness/tools/errors.js +141 -0
  164. package/dist-server/harness/tools/index.d.ts +13 -0
  165. package/dist-server/harness/tools/index.js +8 -0
  166. package/dist-server/harness/tools/mcp.d.ts +26 -0
  167. package/dist-server/harness/tools/mcp.js +15 -0
  168. package/dist-server/harness/tools/native.d.ts +179 -0
  169. package/dist-server/harness/tools/native.js +322 -0
  170. package/dist-server/harness/tools/parse.d.ts +14 -0
  171. package/dist-server/harness/tools/parse.js +18 -0
  172. package/dist-server/harness/tools/resolve-wren-binary.d.ts +12 -0
  173. package/dist-server/harness/tools/resolve-wren-binary.js +21 -0
  174. package/dist-server/harness/tools/resolve.d.ts +51 -0
  175. package/dist-server/harness/tools/resolve.js +79 -0
  176. package/dist-server/harness/tools/setup-native.d.ts +84 -0
  177. package/dist-server/harness/tools/setup-native.js +353 -0
  178. package/dist-server/harness/tools/wiring.d.ts +10 -0
  179. package/dist-server/harness/tools/wiring.js +16 -0
  180. package/dist-server/providers/setup.provider.yaml +31 -0
  181. package/dist-server/providers/wren.provider.yaml +33 -0
  182. package/dist-server/server/adopt.d.ts +87 -0
  183. package/dist-server/server/adopt.js +263 -0
  184. package/dist-server/server/app.d.ts +6 -0
  185. package/dist-server/server/app.js +2521 -0
  186. package/dist-server/server/auth-choice.d.ts +16 -0
  187. package/dist-server/server/auth-choice.js +36 -0
  188. package/dist-server/server/bin.d.ts +2 -0
  189. package/dist-server/server/bin.js +601 -0
  190. package/dist-server/server/bootstrap-project-binding.d.ts +31 -0
  191. package/dist-server/server/bootstrap-project-binding.js +71 -0
  192. package/dist-server/server/clarify.d.ts +10 -0
  193. package/dist-server/server/clarify.js +17 -0
  194. package/dist-server/server/codex-setup-mcp.d.ts +2 -0
  195. package/dist-server/server/codex-setup-mcp.js +147 -0
  196. package/dist-server/server/compose.d.ts +89 -0
  197. package/dist-server/server/compose.js +271 -0
  198. package/dist-server/server/conn-config.d.ts +30 -0
  199. package/dist-server/server/conn-config.js +253 -0
  200. package/dist-server/server/context-files.d.ts +12 -0
  201. package/dist-server/server/context-files.js +117 -0
  202. package/dist-server/server/context-map.d.ts +30 -0
  203. package/dist-server/server/context-map.js +95 -0
  204. package/dist-server/server/context-source.d.ts +68 -0
  205. package/dist-server/server/context-source.js +85 -0
  206. package/dist-server/server/db.d.ts +862 -0
  207. package/dist-server/server/db.js +1839 -0
  208. package/dist-server/server/enrichment-runner.d.ts +184 -0
  209. package/dist-server/server/enrichment-runner.js +213 -0
  210. package/dist-server/server/enrichment-verify.d.ts +73 -0
  211. package/dist-server/server/enrichment-verify.js +290 -0
  212. package/dist-server/server/enrichment.d.ts +232 -0
  213. package/dist-server/server/enrichment.js +199 -0
  214. package/dist-server/server/env-detect.d.ts +8 -0
  215. package/dist-server/server/env-detect.js +17 -0
  216. package/dist-server/server/env-field-hints.d.ts +46 -0
  217. package/dist-server/server/env-field-hints.js +48 -0
  218. package/dist-server/server/fold.d.ts +133 -0
  219. package/dist-server/server/fold.js +407 -0
  220. package/dist-server/server/harness-profile-sources.d.ts +3 -0
  221. package/dist-server/server/harness-profile-sources.js +24 -0
  222. package/dist-server/server/harness.d.ts +19 -0
  223. package/dist-server/server/harness.js +439 -0
  224. package/dist-server/server/impact.d.ts +18 -0
  225. package/dist-server/server/impact.js +85 -0
  226. package/dist-server/server/interactive-terminal.d.ts +175 -0
  227. package/dist-server/server/interactive-terminal.js +336 -0
  228. package/dist-server/server/native-artifacts.d.ts +1004 -0
  229. package/dist-server/server/native-artifacts.js +564 -0
  230. package/dist-server/server/native-dispatch-registry.d.ts +42 -0
  231. package/dist-server/server/native-dispatch-registry.js +45 -0
  232. package/dist-server/server/native-producer-fence.d.ts +14 -0
  233. package/dist-server/server/native-producer-fence.js +48 -0
  234. package/dist-server/server/native-session-resume.d.ts +6 -0
  235. package/dist-server/server/native-session-resume.js +103 -0
  236. package/dist-server/server/native-session-workspace.d.ts +40 -0
  237. package/dist-server/server/native-session-workspace.js +175 -0
  238. package/dist-server/server/native-sessions.d.ts +374 -0
  239. package/dist-server/server/native-sessions.js +1517 -0
  240. package/dist-server/server/native-wren-runtime.d.ts +20 -0
  241. package/dist-server/server/native-wren-runtime.js +259 -0
  242. package/dist-server/server/node-pty-host.d.ts +31 -0
  243. package/dist-server/server/node-pty-host.js +100 -0
  244. package/dist-server/server/route-intent.d.ts +40 -0
  245. package/dist-server/server/route-intent.js +23 -0
  246. package/dist-server/server/runtime-binding.d.ts +52 -0
  247. package/dist-server/server/runtime-binding.js +258 -0
  248. package/dist-server/server/source-catalog.d.ts +84 -0
  249. package/dist-server/server/source-catalog.js +221 -0
  250. package/dist-server/server/source-driver.d.ts +35 -0
  251. package/dist-server/server/source-driver.js +124 -0
  252. package/dist-server/server/spa.d.ts +2 -0
  253. package/dist-server/server/spa.js +51 -0
  254. package/dist-server/server/subscription-model-catalog.d.ts +27 -0
  255. package/dist-server/server/subscription-model-catalog.js +203 -0
  256. package/dist-server/server/turn.d.ts +249 -0
  257. package/dist-server/server/turn.js +1074 -0
  258. package/dist-server/server/wire-types.d.ts +799 -0
  259. package/dist-server/server/wire-types.js +1 -0
  260. package/dist-server/server/wren-home.d.ts +19 -0
  261. package/dist-server/server/wren-home.js +33 -0
  262. package/dist-server/server/wren-profiles.d.ts +43 -0
  263. package/dist-server/server/wren-profiles.js +123 -0
  264. package/package.json +93 -0
  265. package/profiles/genbi-default/context/binding.yml +9 -0
  266. package/profiles/genbi-default/ir.golden.json +506 -0
  267. package/profiles/genbi-default/profile.yml +16 -0
  268. package/profiles/genbi-enrich-context/components/apply_enrichment/component.yml +42 -0
  269. package/profiles/genbi-enrich-context/components/draft_enrichment/component.yml +30 -0
  270. package/profiles/genbi-enrich-context/components/draft_enrichment/steps/draft.md +34 -0
  271. package/profiles/genbi-enrich-context/components/inspect_context/component.yml +32 -0
  272. package/profiles/genbi-enrich-context/components/inspect_context/steps/inspect.md +13 -0
  273. package/profiles/genbi-enrich-context/context/binding.yml +4 -0
  274. package/profiles/genbi-enrich-context/ir.golden.json +302 -0
  275. package/profiles/genbi-enrich-context/profile.yml +15 -0
  276. package/profiles/genbi-monitor/context/binding.yml +7 -0
  277. package/profiles/genbi-monitor/ir.golden.json +188 -0
  278. package/profiles/genbi-monitor/profile.yml +27 -0
  279. package/profiles/genbi-setup/components/build_context/component.yml +44 -0
  280. package/profiles/genbi-setup/components/build_context/steps/build.md +14 -0
  281. package/profiles/genbi-setup/components/connect_source/component.yml +51 -0
  282. package/profiles/genbi-setup/components/connect_source/steps/connect.md +23 -0
  283. package/profiles/genbi-setup/context/binding.yml +8 -0
  284. package/profiles/genbi-setup/ir.golden.json +140 -0
  285. package/profiles/genbi-setup/profile.yml +18 -0
  286. package/profiles/genbi-setup/raw/schema.json +5 -0
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Verification for the setup wizard's "adopt an existing project" entry path
3
+ * (`POST /api/setup/adopt`) — points the wizard at a wren project directory
4
+ * that already exists on disk, instead of scaffolding a new one under the
5
+ * bootstrap workspace root (the create flow).
6
+ *
7
+ * Three-state contract: most real/pre-existing projects predate the
8
+ * `profile:` pin feature, so a missing pin is no longer treated as a hard
9
+ * error. `verifyAdoptProject` returns one of:
10
+ * - `{status: "ok", hasMdl, sourceType}` — already pinned (or just pinned by
11
+ * the caller, see below) AND the pinned profile's connection passes a live
12
+ * smoke query. The caller decides bind-now vs `needs_decision(build_context)`
13
+ * from `hasMdl`.
14
+ * - `{status: "needs_profile", sourceType, candidates}` — no `profile:` pin,
15
+ * but at least one profile in `~/.wren/profiles.yml` (`$WREN_HOME` override
16
+ * honored, see `server/wren-profiles.ts`) matches the project's
17
+ * `data_source`. `candidates` carries ONLY `{name, datasource}` per
18
+ * profile — never any other field off that profile (hosts, ports,
19
+ * credential material) — because this result crosses the wire verbatim as
20
+ * `SetupAdoptResponse.decision`'s payload; the route surfaces it as a
21
+ * `needs_decision` checkpoint (kind `"select_profile"`) rather than
22
+ * silently picking one, even when there's exactly one candidate — the user
23
+ * always confirms explicitly. The caller resolves this by re-POSTing
24
+ * `/api/setup/adopt` with the chosen profile name, which runs
25
+ * `wren context set-profile <name>` (see `runSetProfile`) to write the pin
26
+ * durably before calling back into this function. That re-POST path must
27
+ * go through `adoptWithChosenProfile`, not `runSetProfile` directly: it
28
+ * re-validates the chosen name against the candidate list before writing
29
+ * anything, and restores the pre-call `wren_project.yml` bytes if the
30
+ * profile passes that check but still fails the live connection probe —
31
+ * otherwise a bad choice would durably corrupt the project with no way
32
+ * back (see that function's doc comment).
33
+ * - `{status: "error", message}` — verification failed outright: bad path,
34
+ * no `wren_project.yml`, unsupported connector, no compatible profile at
35
+ * all (zero candidates), or a failed live smoke query. Nothing was bound.
36
+ *
37
+ * Reuses `wren context validate` for the connection check rather than
38
+ * inventing a new smoke-query mechanism. Confirmed by reading
39
+ * `context_cli.py` directly: `validate`'s connectivity probe
40
+ * (`_check_connection`) runs a trivial query through the resolved profile's
41
+ * connector, and it reads the project's declared YAML
42
+ * (`load_models`/`load_views`/`load_relationships`) rather than a compiled
43
+ * `target/mdl.json` — so it works whether or not the project has been built
44
+ * yet. That's exactly the shape adopt needs: the MDL-missing case must still
45
+ * be able to verify the connection before offering to build context.
46
+ *
47
+ * Never throws: every check that can fail returns a discriminated
48
+ * `AdoptVerifyResult` instead, so a route handler turns any failure into a
49
+ * clean `{status: "error"}` response without wrapping this whole module in a
50
+ * try/catch.
51
+ */
52
+ import { execFile } from "node:child_process";
53
+ import { existsSync, readFileSync, statSync, writeFileSync } from "node:fs";
54
+ import path from "node:path";
55
+ import { listCandidateProfiles, loadProfileStore } from "./wren-profiles.js";
56
+ /**
57
+ * Matches a `wren_project.yml` top-level `field: value` scalar line — same
58
+ * single-purpose-regex convention as `server/app.ts`'s `ENV_KEY_LINE`. Only
59
+ * ever reads a handful of known scalar fields (`profile`, `data_source`);
60
+ * never a general YAML parser (matches this repo's existing convention of
61
+ * avoiding a YAML dependency for single-field reads).
62
+ */
63
+ function readYamlScalarField(content, field) {
64
+ const re = new RegExp(`^${field}:\\s*(.+?)\\s*$`, "m");
65
+ const match = re.exec(content);
66
+ if (!match)
67
+ return undefined;
68
+ const raw = match[1];
69
+ // Strip one layer of matching quotes (wren_project.yml sometimes quotes scalars, e.g. `version: '1.0'`) — never unescape further, this only ever reads plain identifiers.
70
+ const unquoted = /^(['"])(.*)\1$/.exec(raw);
71
+ return unquoted ? unquoted[2] : raw;
72
+ }
73
+ function execWren(args, cwd) {
74
+ return new Promise((resolve) => {
75
+ execFile("wren", args, { cwd, maxBuffer: 32 * 1024 * 1024 }, (error, stdout, stderr) => {
76
+ resolve({ stdout, stderr, error: error });
77
+ });
78
+ });
79
+ }
80
+ /**
81
+ * Verifies an existing wren project directory is adoptable: exists, is a
82
+ * directory, has a `wren_project.yml` with a `data_source:` in
83
+ * `supportedSourceTypes`. If it also has a `profile:` pin, that profile's
84
+ * connection must pass `wren context validate`'s live smoke query. If it has
85
+ * no pin, looks for a compatible profile to propose (see the module doc
86
+ * comment's three-state contract). Never crashes the caller: a missing
87
+ * `wren` binary (ENOENT) is reported the same way as any other verification
88
+ * failure, not thrown.
89
+ */
90
+ export async function verifyAdoptProject(projectPath, options) {
91
+ const resolved = path.resolve(projectPath);
92
+ if (!existsSync(resolved)) {
93
+ return { status: "error", message: `no such directory: "${resolved}"` };
94
+ }
95
+ if (!statSync(resolved).isDirectory()) {
96
+ return { status: "error", message: `not a directory: "${resolved}"` };
97
+ }
98
+ const manifestPath = path.join(resolved, "wren_project.yml");
99
+ if (!existsSync(manifestPath)) {
100
+ return { status: "error", message: `"${resolved}" is not a wren project (no wren_project.yml)` };
101
+ }
102
+ let manifest;
103
+ try {
104
+ manifest = readFileSync(manifestPath, "utf-8");
105
+ }
106
+ catch (err) {
107
+ return { status: "error", message: `could not read wren_project.yml: ${err instanceof Error ? err.message : String(err)}` };
108
+ }
109
+ const sourceType = readYamlScalarField(manifest, "data_source");
110
+ if (!sourceType) {
111
+ return { status: "error", message: `wren_project.yml at "${resolved}" has no data_source: field` };
112
+ }
113
+ if (!options.supportedSourceTypes.has(sourceType)) {
114
+ return {
115
+ status: "error",
116
+ message: `data_source "${sourceType}" is not a supported connector — expected one of: ${[...options.supportedSourceTypes].join(", ")}`,
117
+ };
118
+ }
119
+ const profile = readYamlScalarField(manifest, "profile");
120
+ if (!profile) {
121
+ const store = loadProfileStore();
122
+ const candidates = listCandidateProfiles(store, sourceType, path.basename(resolved));
123
+ if (candidates.length === 0) {
124
+ return {
125
+ status: "error",
126
+ message: `wren_project.yml at "${resolved}" has no profile: pinned, and no compatible profile (data_source "${sourceType}") was found in ~/.wren/profiles.yml — run \`wren profile add\` to create one, then retry.`,
127
+ };
128
+ }
129
+ return { status: "needs_profile", sourceType, candidates };
130
+ }
131
+ const { stdout, stderr, error } = await execWren(["context", "validate"], resolved);
132
+ if (error && error.code === "ENOENT") {
133
+ return { status: "error", message: `could not find the "wren" binary while validating "${resolved}" — install wren and ensure it is on PATH.` };
134
+ }
135
+ if (error) {
136
+ const detail = [stdout, stderr].filter(Boolean).join("\n").trim();
137
+ return {
138
+ status: "error",
139
+ message: `connection check failed for profile "${profile}"${detail ? `: ${detail}` : " (wren context validate exited non-zero)"}`,
140
+ };
141
+ }
142
+ const hasMdl = existsSync(path.join(resolved, "target", "mdl.json"));
143
+ return { status: "ok", hasMdl, sourceType };
144
+ }
145
+ /**
146
+ * Writes a durable `profile:` (+ `data_source:`) pin into an adopted
147
+ * project's `wren_project.yml` by shelling out to `wren context set-profile
148
+ * <name>` in the project directory — reuses the CLI's own bind logic rather
149
+ * than hand-writing YAML here, so the pin ends up byte-for-byte what a user
150
+ * running the command themselves would get. Called by the adopt route when
151
+ * the caller resolves a `needs_profile` checkpoint by re-POSTing with a
152
+ * chosen `profile` name, before re-running `verifyAdoptProject` (which will
153
+ * now see the pin and proceed to the live smoke check).
154
+ */
155
+ export async function runSetProfile(projectPath, profileName) {
156
+ const resolved = path.resolve(projectPath);
157
+ const { stdout, stderr, error } = await execWren(["context", "set-profile", profileName], resolved);
158
+ if (error && error.code === "ENOENT") {
159
+ return { ok: false, message: `could not find the "wren" binary while binding profile "${profileName}" in "${resolved}" — install wren and ensure it is on PATH.` };
160
+ }
161
+ if (error) {
162
+ const detail = [stdout, stderr].filter(Boolean).join("\n").trim();
163
+ return {
164
+ ok: false,
165
+ message: `failed to bind profile "${profileName}" to "${resolved}"${detail ? `: ${detail}` : " (wren context set-profile exited non-zero)"}`,
166
+ };
167
+ }
168
+ return { ok: true };
169
+ }
170
+ /**
171
+ * Confirms `profileName` is actually one of the candidates `verifyAdoptProject`
172
+ * would have offered for this project — i.e. it exists in `~/.wren/profiles.yml`
173
+ * and its `datasource:` matches the project's `data_source:`. The route must
174
+ * call this before `runSetProfile`: a client-supplied `profile` that skipped
175
+ * this check would let `wren context set-profile` durably rewrite
176
+ * `data_source:` to whatever the chosen profile declares (see
177
+ * `context_cli.py`'s `set-profile`), with no compatibility check of its own.
178
+ * Recomputes the candidate list from disk rather than trusting a list the
179
+ * caller might have seen in an earlier response, so a hand-crafted request
180
+ * naming an incompatible or nonexistent profile is rejected here with zero
181
+ * mutation.
182
+ */
183
+ export async function validateChosenProfile(projectPath, profileName, options) {
184
+ const resolved = path.resolve(projectPath);
185
+ if (!existsSync(resolved) || !statSync(resolved).isDirectory()) {
186
+ return { ok: false, message: `no such directory: "${resolved}"` };
187
+ }
188
+ const manifestPath = path.join(resolved, "wren_project.yml");
189
+ if (!existsSync(manifestPath)) {
190
+ return { ok: false, message: `"${resolved}" is not a wren project (no wren_project.yml)` };
191
+ }
192
+ let manifest;
193
+ try {
194
+ manifest = readFileSync(manifestPath, "utf-8");
195
+ }
196
+ catch (err) {
197
+ return { ok: false, message: `could not read wren_project.yml: ${err instanceof Error ? err.message : String(err)}` };
198
+ }
199
+ const sourceType = readYamlScalarField(manifest, "data_source");
200
+ if (!sourceType || !options.supportedSourceTypes.has(sourceType)) {
201
+ return { ok: false, message: `wren_project.yml at "${resolved}" has no supported data_source: field` };
202
+ }
203
+ const store = loadProfileStore();
204
+ const candidates = listCandidateProfiles(store, sourceType, path.basename(resolved));
205
+ if (!candidates.some((candidate) => candidate.name === profileName)) {
206
+ const available = candidates.map((candidate) => candidate.name).join(", ");
207
+ return {
208
+ ok: false,
209
+ message: `profile "${profileName}" is not a compatible candidate for "${resolved}" (data_source "${sourceType}") — choose one of: ${available || "(no compatible profiles found)"}`,
210
+ };
211
+ }
212
+ return { ok: true };
213
+ }
214
+ /**
215
+ * Applies a client-chosen profile to an adopted project and re-verifies it,
216
+ * rolling back on any failure so the project never ends up durably worse off
217
+ * than before the call: `validateChosenProfile` rejects an incompatible or
218
+ * unknown profile before anything is written; if that passes but the
219
+ * subsequent `wren context validate` (inside `verifyAdoptProject`) still
220
+ * fails — dead host, bad credentials, a moved duckdb file — the pre-call
221
+ * `wren_project.yml` bytes are restored so the project falls back to its
222
+ * previous no-pin state. That matters because `save_project_config` drops
223
+ * YAML comments on rewrite, so the ORIGINAL bytes are restored rather than
224
+ * re-serialized, and because restoring to no-pin means the next adopt call
225
+ * naturally re-offers the candidate list (`needs_profile`) instead of
226
+ * re-validating a permanently broken pin forever.
227
+ */
228
+ export async function adoptWithChosenProfile(projectPath, profileName, options) {
229
+ const check = await validateChosenProfile(projectPath, profileName, options);
230
+ if (!check.ok) {
231
+ return { status: "error", message: check.message };
232
+ }
233
+ const resolved = path.resolve(projectPath);
234
+ const manifestPath = path.join(resolved, "wren_project.yml");
235
+ let manifestBackup;
236
+ try {
237
+ manifestBackup = readFileSync(manifestPath);
238
+ }
239
+ catch (err) {
240
+ return {
241
+ status: "error",
242
+ message: `could not snapshot wren_project.yml before applying profile "${profileName}": ${err instanceof Error ? err.message : String(err)}`,
243
+ };
244
+ }
245
+ const setResult = await runSetProfile(projectPath, profileName);
246
+ if (!setResult.ok) {
247
+ return { status: "error", message: setResult.message };
248
+ }
249
+ const verified = await verifyAdoptProject(projectPath, options);
250
+ if (verified.status === "error") {
251
+ try {
252
+ writeFileSync(manifestPath, manifestBackup);
253
+ }
254
+ catch (err) {
255
+ return {
256
+ status: "error",
257
+ message: `${verified.message} (additionally failed to restore wren_project.yml — manual recovery needed: ${err instanceof Error ? err.message : String(err)})`,
258
+ };
259
+ }
260
+ return { status: "error", message: verified.message };
261
+ }
262
+ return verified;
263
+ }
@@ -0,0 +1,6 @@
1
+ import { Hono } from "hono";
2
+ import type { InteractiveTerminalSession } from "./interactive-terminal.js";
3
+ import type { TurnDeps } from "./turn.js";
4
+ /** Applies only the narrow, size-bounded native-terminal WS wire contract. */
5
+ export declare function applyInteractiveTerminalFrame(session: Pick<InteractiveTerminalSession, "write" | "resize" | "close">, raw: string): void;
6
+ export declare function createApp(deps: TurnDeps): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;