@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.
- package/LICENSE +201 -0
- package/README.md +141 -0
- package/bin/genbi.mjs +31 -0
- package/dist/assets/echarts-LTFC-ysd.js +40 -0
- package/dist/assets/index-Bo--QMUN.js +441 -0
- package/dist/assets/index-Xs4q7pNo.css +1 -0
- package/dist/index.html +14 -0
- package/dist/wrenai_logo.png +0 -0
- package/dist/wrenai_logo_white.png +0 -0
- package/dist-server/harness/auth/detect.d.ts +18 -0
- package/dist-server/harness/auth/detect.js +37 -0
- package/dist-server/harness/auth/index.d.ts +4 -0
- package/dist-server/harness/auth/index.js +2 -0
- package/dist-server/harness/auth/probe.d.ts +18 -0
- package/dist-server/harness/auth/probe.js +52 -0
- package/dist-server/harness/auth/types.d.ts +42 -0
- package/dist-server/harness/auth/types.js +9 -0
- package/dist-server/harness/bundle/loader.d.ts +32 -0
- package/dist-server/harness/bundle/loader.js +43 -0
- package/dist-server/harness/bundle/schema.d.ts +199 -0
- package/dist-server/harness/bundle/schema.js +127 -0
- package/dist-server/harness/bundle/version.d.ts +10 -0
- package/dist-server/harness/bundle/version.js +43 -0
- package/dist-server/harness/capability/gate.d.ts +6 -0
- package/dist-server/harness/capability/gate.js +29 -0
- package/dist-server/harness/capability/registry.d.ts +6 -0
- package/dist-server/harness/capability/registry.js +17 -0
- package/dist-server/harness/cli-args.d.ts +123 -0
- package/dist-server/harness/cli-args.js +247 -0
- package/dist-server/harness/cli.d.ts +2 -0
- package/dist-server/harness/cli.js +151 -0
- package/dist-server/harness/compile/cache.d.ts +23 -0
- package/dist-server/harness/compile/cache.js +109 -0
- package/dist-server/harness/compile/compose-profile.d.ts +34 -0
- package/dist-server/harness/compile/compose-profile.js +95 -0
- package/dist-server/harness/compile/errors.d.ts +22 -0
- package/dist-server/harness/compile/errors.js +41 -0
- package/dist-server/harness/compile/fingerprint.d.ts +22 -0
- package/dist-server/harness/compile/fingerprint.js +84 -0
- package/dist-server/harness/compile/index.d.ts +8 -0
- package/dist-server/harness/compile/index.js +7 -0
- package/dist-server/harness/compile/pipeline.d.ts +66 -0
- package/dist-server/harness/compile/pipeline.js +176 -0
- package/dist-server/harness/compile/resolve-binary.d.ts +55 -0
- package/dist-server/harness/compile/resolve-binary.js +133 -0
- package/dist-server/harness/compile/types.d.ts +107 -0
- package/dist-server/harness/compile/types.js +1 -0
- package/dist-server/harness/compile/warble-identity.d.ts +12 -0
- package/dist-server/harness/compile/warble-identity.js +33 -0
- package/dist-server/harness/compliance/gate.d.ts +35 -0
- package/dist-server/harness/compliance/gate.js +48 -0
- package/dist-server/harness/compliance/index.d.ts +2 -0
- package/dist-server/harness/compliance/index.js +1 -0
- package/dist-server/harness/compliance/types.d.ts +16 -0
- package/dist-server/harness/compliance/types.js +1 -0
- package/dist-server/harness/events/emitter.d.ts +34 -0
- package/dist-server/harness/events/emitter.js +25 -0
- package/dist-server/harness/events/index.d.ts +4 -0
- package/dist-server/harness/events/index.js +2 -0
- package/dist-server/harness/events/sse.d.ts +20 -0
- package/dist-server/harness/events/sse.js +48 -0
- package/dist-server/harness/events/types.d.ts +131 -0
- package/dist-server/harness/events/types.js +1 -0
- package/dist-server/harness/exec/errors.d.ts +16 -0
- package/dist-server/harness/exec/errors.js +29 -0
- package/dist-server/harness/exec/index.d.ts +5 -0
- package/dist-server/harness/exec/index.js +2 -0
- package/dist-server/harness/exec/local.d.ts +32 -0
- package/dist-server/harness/exec/local.js +134 -0
- package/dist-server/harness/exec/policy.d.ts +12 -0
- package/dist-server/harness/exec/policy.js +1 -0
- package/dist-server/harness/exec/types.d.ts +63 -0
- package/dist-server/harness/exec/types.js +1 -0
- package/dist-server/harness/guardrails/index.d.ts +2 -0
- package/dist-server/harness/guardrails/index.js +1 -0
- package/dist-server/harness/guardrails/policy.d.ts +45 -0
- package/dist-server/harness/guardrails/policy.js +57 -0
- package/dist-server/harness/index.d.ts +37 -0
- package/dist-server/harness/index.js +19 -0
- package/dist-server/harness/loop/errors.d.ts +53 -0
- package/dist-server/harness/loop/errors.js +72 -0
- package/dist-server/harness/loop/executor.d.ts +123 -0
- package/dist-server/harness/loop/executor.js +380 -0
- package/dist-server/harness/loop/guard.d.ts +16 -0
- package/dist-server/harness/loop/guard.js +1 -0
- package/dist-server/harness/loop/index.d.ts +5 -0
- package/dist-server/harness/loop/index.js +3 -0
- package/dist-server/harness/native-producer/index.d.ts +109 -0
- package/dist-server/harness/native-producer/index.js +302 -0
- package/dist-server/harness/npm-package-resolve.d.ts +28 -0
- package/dist-server/harness/npm-package-resolve.js +47 -0
- package/dist-server/harness/providers/adapters/anthropic.d.ts +7 -0
- package/dist-server/harness/providers/adapters/anthropic.js +6 -0
- package/dist-server/harness/providers/adapters/mock.d.ts +4 -0
- package/dist-server/harness/providers/adapters/mock.js +5 -0
- package/dist-server/harness/providers/adapters/openai-compatible.d.ts +10 -0
- package/dist-server/harness/providers/adapters/openai-compatible.js +10 -0
- package/dist-server/harness/providers/binding.d.ts +23 -0
- package/dist-server/harness/providers/binding.js +13 -0
- package/dist-server/harness/providers/errors.d.ts +6 -0
- package/dist-server/harness/providers/errors.js +12 -0
- package/dist-server/harness/providers/index.d.ts +18 -0
- package/dist-server/harness/providers/index.js +22 -0
- package/dist-server/harness/providers/registry.d.ts +16 -0
- package/dist-server/harness/providers/registry.js +24 -0
- package/dist-server/harness/render/envelope.d.ts +145 -0
- package/dist-server/harness/render/envelope.js +428 -0
- package/dist-server/harness/render/errors.d.ts +33 -0
- package/dist-server/harness/render/errors.js +46 -0
- package/dist-server/harness/render/index.d.ts +5 -0
- package/dist-server/harness/render/index.js +3 -0
- package/dist-server/harness/render/validate.d.ts +13 -0
- package/dist-server/harness/render/validate.js +88 -0
- package/dist-server/harness/route/adapter-spec.d.ts +40 -0
- package/dist-server/harness/route/adapter-spec.js +61 -0
- package/dist-server/harness/route/agent-sdk-cli.d.ts +30 -0
- package/dist-server/harness/route/agent-sdk-cli.js +86 -0
- package/dist-server/harness/route/agent-sdk-manifest.d.ts +31 -0
- package/dist-server/harness/route/agent-sdk-manifest.js +56 -0
- package/dist-server/harness/route/artifact-content.d.ts +53 -0
- package/dist-server/harness/route/artifact-content.js +83 -0
- package/dist-server/harness/route/chat-event-mapper.d.ts +95 -0
- package/dist-server/harness/route/chat-event-mapper.js +164 -0
- package/dist-server/harness/route/codex-ask-events.d.ts +25 -0
- package/dist-server/harness/route/codex-ask-events.js +395 -0
- package/dist-server/harness/route/codex-ask.d.ts +15 -0
- package/dist-server/harness/route/codex-ask.js +242 -0
- package/dist-server/harness/route/codex-local-cli.d.ts +20 -0
- package/dist-server/harness/route/codex-local-cli.js +78 -0
- package/dist-server/harness/route/codex-local-manifest.d.ts +22 -0
- package/dist-server/harness/route/codex-local-manifest.js +180 -0
- package/dist-server/harness/route/describe.d.ts +54 -0
- package/dist-server/harness/route/describe.js +84 -0
- package/dist-server/harness/route/dispatched.d.ts +138 -0
- package/dist-server/harness/route/dispatched.js +339 -0
- package/dist-server/harness/route/in-process.d.ts +43 -0
- package/dist-server/harness/route/in-process.js +106 -0
- package/dist-server/harness/route/index.d.ts +19 -0
- package/dist-server/harness/route/index.js +12 -0
- package/dist-server/harness/route/profile-source.d.ts +37 -0
- package/dist-server/harness/route/profile-source.js +76 -0
- package/dist-server/harness/route/route.d.ts +33 -0
- package/dist-server/harness/route/route.js +114 -0
- package/dist-server/harness/route/tier-binding.d.ts +36 -0
- package/dist-server/harness/route/tier-binding.js +63 -0
- package/dist-server/harness/route/types.d.ts +286 -0
- package/dist-server/harness/route/types.js +1 -0
- package/dist-server/harness/session/errors.d.ts +4 -0
- package/dist-server/harness/session/errors.js +7 -0
- package/dist-server/harness/session/gate.d.ts +11 -0
- package/dist-server/harness/session/gate.js +13 -0
- package/dist-server/harness/session/index.d.ts +5 -0
- package/dist-server/harness/session/index.js +3 -0
- package/dist-server/harness/session/run.d.ts +60 -0
- package/dist-server/harness/session/run.js +333 -0
- package/dist-server/harness/session/types.d.ts +29 -0
- package/dist-server/harness/session/types.js +1 -0
- package/dist-server/harness/setup/codex-events.d.ts +12 -0
- package/dist-server/harness/setup/codex-events.js +108 -0
- package/dist-server/harness/setup/runner.d.ts +497 -0
- package/dist-server/harness/setup/runner.js +1314 -0
- package/dist-server/harness/tools/errors.d.ts +107 -0
- package/dist-server/harness/tools/errors.js +141 -0
- package/dist-server/harness/tools/index.d.ts +13 -0
- package/dist-server/harness/tools/index.js +8 -0
- package/dist-server/harness/tools/mcp.d.ts +26 -0
- package/dist-server/harness/tools/mcp.js +15 -0
- package/dist-server/harness/tools/native.d.ts +179 -0
- package/dist-server/harness/tools/native.js +322 -0
- package/dist-server/harness/tools/parse.d.ts +14 -0
- package/dist-server/harness/tools/parse.js +18 -0
- package/dist-server/harness/tools/resolve-wren-binary.d.ts +12 -0
- package/dist-server/harness/tools/resolve-wren-binary.js +21 -0
- package/dist-server/harness/tools/resolve.d.ts +51 -0
- package/dist-server/harness/tools/resolve.js +79 -0
- package/dist-server/harness/tools/setup-native.d.ts +84 -0
- package/dist-server/harness/tools/setup-native.js +353 -0
- package/dist-server/harness/tools/wiring.d.ts +10 -0
- package/dist-server/harness/tools/wiring.js +16 -0
- package/dist-server/providers/setup.provider.yaml +31 -0
- package/dist-server/providers/wren.provider.yaml +33 -0
- package/dist-server/server/adopt.d.ts +87 -0
- package/dist-server/server/adopt.js +263 -0
- package/dist-server/server/app.d.ts +6 -0
- package/dist-server/server/app.js +2521 -0
- package/dist-server/server/auth-choice.d.ts +16 -0
- package/dist-server/server/auth-choice.js +36 -0
- package/dist-server/server/bin.d.ts +2 -0
- package/dist-server/server/bin.js +601 -0
- package/dist-server/server/bootstrap-project-binding.d.ts +31 -0
- package/dist-server/server/bootstrap-project-binding.js +71 -0
- package/dist-server/server/clarify.d.ts +10 -0
- package/dist-server/server/clarify.js +17 -0
- package/dist-server/server/codex-setup-mcp.d.ts +2 -0
- package/dist-server/server/codex-setup-mcp.js +147 -0
- package/dist-server/server/compose.d.ts +89 -0
- package/dist-server/server/compose.js +271 -0
- package/dist-server/server/conn-config.d.ts +30 -0
- package/dist-server/server/conn-config.js +253 -0
- package/dist-server/server/context-files.d.ts +12 -0
- package/dist-server/server/context-files.js +117 -0
- package/dist-server/server/context-map.d.ts +30 -0
- package/dist-server/server/context-map.js +95 -0
- package/dist-server/server/context-source.d.ts +68 -0
- package/dist-server/server/context-source.js +85 -0
- package/dist-server/server/db.d.ts +862 -0
- package/dist-server/server/db.js +1839 -0
- package/dist-server/server/enrichment-runner.d.ts +184 -0
- package/dist-server/server/enrichment-runner.js +213 -0
- package/dist-server/server/enrichment-verify.d.ts +73 -0
- package/dist-server/server/enrichment-verify.js +290 -0
- package/dist-server/server/enrichment.d.ts +232 -0
- package/dist-server/server/enrichment.js +199 -0
- package/dist-server/server/env-detect.d.ts +8 -0
- package/dist-server/server/env-detect.js +17 -0
- package/dist-server/server/env-field-hints.d.ts +46 -0
- package/dist-server/server/env-field-hints.js +48 -0
- package/dist-server/server/fold.d.ts +133 -0
- package/dist-server/server/fold.js +407 -0
- package/dist-server/server/harness-profile-sources.d.ts +3 -0
- package/dist-server/server/harness-profile-sources.js +24 -0
- package/dist-server/server/harness.d.ts +19 -0
- package/dist-server/server/harness.js +439 -0
- package/dist-server/server/impact.d.ts +18 -0
- package/dist-server/server/impact.js +85 -0
- package/dist-server/server/interactive-terminal.d.ts +175 -0
- package/dist-server/server/interactive-terminal.js +336 -0
- package/dist-server/server/native-artifacts.d.ts +1004 -0
- package/dist-server/server/native-artifacts.js +564 -0
- package/dist-server/server/native-dispatch-registry.d.ts +42 -0
- package/dist-server/server/native-dispatch-registry.js +45 -0
- package/dist-server/server/native-producer-fence.d.ts +14 -0
- package/dist-server/server/native-producer-fence.js +48 -0
- package/dist-server/server/native-session-resume.d.ts +6 -0
- package/dist-server/server/native-session-resume.js +103 -0
- package/dist-server/server/native-session-workspace.d.ts +40 -0
- package/dist-server/server/native-session-workspace.js +175 -0
- package/dist-server/server/native-sessions.d.ts +374 -0
- package/dist-server/server/native-sessions.js +1517 -0
- package/dist-server/server/native-wren-runtime.d.ts +20 -0
- package/dist-server/server/native-wren-runtime.js +259 -0
- package/dist-server/server/node-pty-host.d.ts +31 -0
- package/dist-server/server/node-pty-host.js +100 -0
- package/dist-server/server/route-intent.d.ts +40 -0
- package/dist-server/server/route-intent.js +23 -0
- package/dist-server/server/runtime-binding.d.ts +52 -0
- package/dist-server/server/runtime-binding.js +258 -0
- package/dist-server/server/source-catalog.d.ts +84 -0
- package/dist-server/server/source-catalog.js +221 -0
- package/dist-server/server/source-driver.d.ts +35 -0
- package/dist-server/server/source-driver.js +124 -0
- package/dist-server/server/spa.d.ts +2 -0
- package/dist-server/server/spa.js +51 -0
- package/dist-server/server/subscription-model-catalog.d.ts +27 -0
- package/dist-server/server/subscription-model-catalog.js +203 -0
- package/dist-server/server/turn.d.ts +249 -0
- package/dist-server/server/turn.js +1074 -0
- package/dist-server/server/wire-types.d.ts +799 -0
- package/dist-server/server/wire-types.js +1 -0
- package/dist-server/server/wren-home.d.ts +19 -0
- package/dist-server/server/wren-home.js +33 -0
- package/dist-server/server/wren-profiles.d.ts +43 -0
- package/dist-server/server/wren-profiles.js +123 -0
- package/package.json +93 -0
- package/profiles/genbi-default/context/binding.yml +9 -0
- package/profiles/genbi-default/ir.golden.json +506 -0
- package/profiles/genbi-default/profile.yml +16 -0
- package/profiles/genbi-enrich-context/components/apply_enrichment/component.yml +42 -0
- package/profiles/genbi-enrich-context/components/draft_enrichment/component.yml +30 -0
- package/profiles/genbi-enrich-context/components/draft_enrichment/steps/draft.md +34 -0
- package/profiles/genbi-enrich-context/components/inspect_context/component.yml +32 -0
- package/profiles/genbi-enrich-context/components/inspect_context/steps/inspect.md +13 -0
- package/profiles/genbi-enrich-context/context/binding.yml +4 -0
- package/profiles/genbi-enrich-context/ir.golden.json +302 -0
- package/profiles/genbi-enrich-context/profile.yml +15 -0
- package/profiles/genbi-monitor/context/binding.yml +7 -0
- package/profiles/genbi-monitor/ir.golden.json +188 -0
- package/profiles/genbi-monitor/profile.yml +27 -0
- package/profiles/genbi-setup/components/build_context/component.yml +44 -0
- package/profiles/genbi-setup/components/build_context/steps/build.md +14 -0
- package/profiles/genbi-setup/components/connect_source/component.yml +51 -0
- package/profiles/genbi-setup/components/connect_source/steps/connect.md +23 -0
- package/profiles/genbi-setup/context/binding.yml +8 -0
- package/profiles/genbi-setup/ir.golden.json +140 -0
- package/profiles/genbi-setup/profile.yml +18 -0
- 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, "/">;
|