@wrenai/genbi 0.0.4 → 0.0.5
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/README.md +64 -2
- package/dist/assets/{echarts-LTFC-ysd.js → echarts-DYM4hjvk.js} +2 -2
- package/dist/assets/index-A_Wrq7Ey.css +1 -0
- package/dist/assets/{index-Bo--QMUN.js → index-DsH129tV.js} +18 -17
- package/dist/index.html +2 -2
- package/dist-server/harness/bundle/schema.d.ts +38 -0
- package/dist-server/harness/bundle/schema.js +18 -10
- package/dist-server/harness/bundle/version.js +1 -1
- package/dist-server/harness/cli-args.d.ts +10 -2
- package/dist-server/harness/cli-args.js +24 -8
- package/dist-server/harness/cli.js +75 -9
- package/dist-server/harness/compile/cache.js +4 -4
- package/dist-server/harness/compile/compose-profile.d.ts +51 -14
- package/dist-server/harness/compile/compose-profile.js +85 -19
- package/dist-server/harness/compile/context-loader.d.ts +56 -0
- package/dist-server/harness/compile/context-loader.js +237 -0
- package/dist-server/harness/compile/errors.d.ts +19 -0
- package/dist-server/harness/compile/errors.js +35 -0
- package/dist-server/harness/compile/index.d.ts +4 -3
- package/dist-server/harness/compile/index.js +4 -3
- package/dist-server/harness/compile/pipeline.d.ts +15 -7
- package/dist-server/harness/compile/pipeline.js +62 -14
- package/dist-server/harness/compile/resolve-binary.d.ts +2 -2
- package/dist-server/harness/compile/resolve-binary.js +3 -3
- package/dist-server/harness/compile/types.d.ts +29 -0
- package/dist-server/harness/compile/warble-identity.d.ts +11 -0
- package/dist-server/harness/compile/warble-identity.js +13 -0
- package/dist-server/harness/components/ai-step.d.ts +4 -0
- package/dist-server/harness/components/ai-step.js +40 -0
- package/dist-server/harness/components/broker.d.ts +60 -0
- package/dist-server/harness/components/broker.js +117 -0
- package/dist-server/harness/components/capability-card.d.ts +98 -0
- package/dist-server/harness/components/capability-card.js +169 -0
- package/dist-server/harness/components/context.d.ts +2 -0
- package/dist-server/harness/components/context.js +30 -0
- package/dist-server/harness/components/display.d.ts +6 -0
- package/dist-server/harness/components/display.js +29 -0
- package/dist-server/harness/components/egress-judge.d.ts +12 -0
- package/dist-server/harness/components/egress-judge.js +27 -0
- package/dist-server/harness/components/egress.d.ts +142 -0
- package/dist-server/harness/components/egress.js +469 -0
- package/dist-server/harness/components/in-process.d.ts +7 -0
- package/dist-server/harness/components/in-process.js +245 -0
- package/dist-server/harness/components/normalize.d.ts +35 -0
- package/dist-server/harness/components/normalize.js +245 -0
- package/dist-server/harness/components/plan.d.ts +31 -0
- package/dist-server/harness/components/plan.js +184 -0
- package/dist-server/harness/components/report.d.ts +207 -0
- package/dist-server/harness/components/report.js +309 -0
- package/dist-server/harness/components/runner.d.ts +193 -0
- package/dist-server/harness/components/runner.js +492 -0
- package/dist-server/harness/components/semantic-guards.d.ts +20 -0
- package/dist-server/harness/components/semantic-guards.js +42 -0
- package/dist-server/harness/components/terminal-json.d.ts +18 -0
- package/dist-server/harness/components/terminal-json.js +82 -0
- package/dist-server/harness/components/usage.d.ts +14 -0
- package/dist-server/harness/components/usage.js +19 -0
- package/dist-server/harness/components/wren-access.d.ts +29 -0
- package/dist-server/harness/components/wren-access.js +233 -0
- package/dist-server/harness/components/zone-dry-run.d.ts +43 -0
- package/dist-server/harness/components/zone-dry-run.js +107 -0
- package/dist-server/harness/components/zone-gate.d.ts +76 -0
- package/dist-server/harness/components/zone-gate.js +144 -0
- package/dist-server/harness/events/index.d.ts +1 -1
- package/dist-server/harness/events/types.d.ts +52 -0
- package/dist-server/harness/index.d.ts +9 -2
- package/dist-server/harness/index.js +5 -1
- package/dist-server/harness/loop/executor.d.ts +1 -0
- package/dist-server/harness/loop/executor.js +37 -15
- package/dist-server/harness/npm-package-resolve.d.ts +2 -0
- package/dist-server/harness/npm-package-resolve.js +16 -4
- package/dist-server/harness/providers/adapters/openai-compatible.d.ts +13 -0
- package/dist-server/harness/providers/adapters/openai-compatible.js +17 -0
- package/dist-server/harness/providers/adapters/openai.d.ts +7 -0
- package/dist-server/harness/providers/adapters/openai.js +6 -0
- package/dist-server/harness/providers/adapters/pi-ai.d.ts +48 -0
- package/dist-server/harness/providers/adapters/pi-ai.js +518 -0
- package/dist-server/harness/providers/binding.d.ts +45 -4
- package/dist-server/harness/providers/binding.js +44 -8
- package/dist-server/harness/providers/index.d.ts +9 -3
- package/dist-server/harness/providers/index.js +10 -3
- package/dist-server/harness/providers/zone.d.ts +96 -0
- package/dist-server/harness/providers/zone.js +112 -0
- package/dist-server/harness/render/answering-query.d.ts +29 -0
- package/dist-server/harness/render/answering-query.js +62 -0
- package/dist-server/harness/render/envelope.d.ts +6 -0
- package/dist-server/harness/render/envelope.js +10 -3
- package/dist-server/harness/route/adapter-spec.d.ts +8 -9
- package/dist-server/harness/route/adapter-spec.js +13 -14
- package/dist-server/harness/route/codex-ask-events.js +2 -1
- package/dist-server/harness/route/codex-ask.d.ts +4 -0
- package/dist-server/harness/route/codex-ask.js +69 -30
- package/dist-server/harness/route/codex-host-query.d.ts +52 -0
- package/dist-server/harness/route/codex-host-query.js +191 -0
- package/dist-server/harness/route/codex-local-manifest.d.ts +9 -1
- package/dist-server/harness/route/codex-local-manifest.js +96 -15
- package/dist-server/harness/route/codex-wren-proxy.d.ts +33 -0
- package/dist-server/harness/route/codex-wren-proxy.js +227 -0
- package/dist-server/harness/route/describe.js +45 -6
- package/dist-server/harness/route/in-process.d.ts +22 -1
- package/dist-server/harness/route/in-process.js +54 -4
- package/dist-server/harness/route/route.js +5 -2
- package/dist-server/harness/route/types.d.ts +30 -1
- package/dist-server/harness/session/run.js +30 -10
- package/dist-server/harness/setup/runner.d.ts +2 -0
- package/dist-server/harness/setup/runner.js +38 -17
- package/dist-server/harness/setup/yaml-scalar.d.ts +23 -0
- package/dist-server/harness/setup/yaml-scalar.js +62 -0
- package/dist-server/server/adopt.js +1 -17
- package/dist-server/server/app.d.ts +1 -0
- package/dist-server/server/app.js +163 -14
- package/dist-server/server/auth-choice.d.ts +13 -1
- package/dist-server/server/auth-choice.js +66 -1
- package/dist-server/server/bin.js +177 -25
- package/dist-server/server/codex-local-grounding.d.ts +18 -0
- package/dist-server/server/codex-local-grounding.js +92 -0
- package/dist-server/server/codex-native-session.d.ts +25 -0
- package/dist-server/server/codex-native-session.js +1 -0
- package/dist-server/server/codex-runtime-composition.d.ts +34 -0
- package/dist-server/server/codex-runtime-composition.js +250 -0
- package/dist-server/server/codex-structured-ask.d.ts +23 -0
- package/dist-server/server/codex-structured-ask.js +102 -0
- package/dist-server/server/conn-config.js +4 -16
- package/dist-server/server/conversation-socket.d.ts +16 -0
- package/dist-server/server/conversation-socket.js +65 -0
- package/dist-server/server/db.d.ts +46 -0
- package/dist-server/server/db.js +88 -9
- package/dist-server/server/env-detect.d.ts +6 -0
- package/dist-server/server/env-detect.js +7 -0
- package/dist-server/server/fold.d.ts +22 -4
- package/dist-server/server/fold.js +37 -5
- package/dist-server/server/harness.d.ts +2 -2
- package/dist-server/server/harness.js +33 -7
- package/dist-server/server/interactive-terminal.d.ts +10 -6
- package/dist-server/server/interactive-terminal.js +33 -8
- package/dist-server/server/managed-wren-runtime.d.ts +116 -0
- package/dist-server/server/managed-wren-runtime.js +670 -0
- package/dist-server/server/native-artifacts.d.ts +23 -7
- package/dist-server/server/native-artifacts.js +43 -12
- package/dist-server/server/native-component-context.d.ts +19 -0
- package/dist-server/server/native-component-context.js +76 -0
- package/dist-server/server/native-component-preparation.d.ts +20 -0
- package/dist-server/server/native-component-preparation.js +129 -0
- package/dist-server/server/native-component-runtime.d.ts +36 -0
- package/dist-server/server/native-component-runtime.js +92 -0
- package/dist-server/server/native-components.d.ts +84 -0
- package/dist-server/server/native-components.js +160 -0
- package/dist-server/server/native-dispatch-process.d.ts +8 -0
- package/dist-server/server/native-dispatch-process.js +65 -0
- package/dist-server/server/native-runtime-spec.d.ts +89 -0
- package/dist-server/server/native-runtime-spec.js +169 -0
- package/dist-server/server/native-sessions.d.ts +172 -19
- package/dist-server/server/native-sessions.js +839 -244
- package/dist-server/server/native-shutdown.d.ts +6 -0
- package/dist-server/server/native-shutdown.js +28 -0
- package/dist-server/server/native-wren-home.d.ts +18 -0
- package/dist-server/server/native-wren-home.js +262 -0
- package/dist-server/server/node-pty-host.d.ts +2 -1
- package/dist-server/server/node-pty-host.js +3 -2
- package/dist-server/server/profile-registry.d.ts +139 -0
- package/dist-server/server/profile-registry.js +620 -0
- package/dist-server/server/runtime-binding.d.ts +4 -1
- package/dist-server/server/runtime-binding.js +50 -2
- package/dist-server/server/runtime-host/claude-component-step.d.ts +25 -0
- package/dist-server/server/runtime-host/claude-component-step.js +186 -0
- package/dist-server/server/runtime-host/codex-app-server.d.ts +75 -0
- package/dist-server/server/runtime-host/codex-app-server.js +239 -0
- package/dist-server/server/runtime-host/codex-compatibility.d.ts +110 -0
- package/dist-server/server/runtime-host/codex-compatibility.js +162 -0
- package/dist-server/server/runtime-host/codex-component-step.d.ts +19 -0
- package/dist-server/server/runtime-host/codex-component-step.js +308 -0
- package/dist-server/server/runtime-host/codex-conversation.d.ts +109 -0
- package/dist-server/server/runtime-host/codex-conversation.js +295 -0
- package/dist-server/server/runtime-host/codex-direct-tools.d.ts +23 -0
- package/dist-server/server/runtime-host/codex-direct-tools.js +59 -0
- package/dist-server/server/runtime-host/codex-events.d.ts +647 -0
- package/dist-server/server/runtime-host/codex-events.js +66 -0
- package/dist-server/server/runtime-host/codex-policy.d.ts +16 -0
- package/dist-server/server/runtime-host/codex-policy.js +151 -0
- package/dist-server/server/runtime-host/codex-process.d.ts +8 -0
- package/dist-server/server/runtime-host/codex-process.js +96 -0
- package/dist-server/server/runtime-host/codex-rpc.d.ts +47 -0
- package/dist-server/server/runtime-host/codex-rpc.js +182 -0
- package/dist-server/server/runtime-host/codex-session.d.ts +74 -0
- package/dist-server/server/runtime-host/codex-session.js +492 -0
- package/dist-server/server/runtime-host/codex-terminal-protocol.d.ts +35 -0
- package/dist-server/server/runtime-host/codex-terminal-protocol.js +243 -0
- package/dist-server/server/runtime-host/codex-terminal.d.ts +16 -0
- package/dist-server/server/runtime-host/codex-terminal.js +120 -0
- package/dist-server/server/runtime-host/index.d.ts +5 -0
- package/dist-server/server/runtime-host/index.js +3 -0
- package/dist-server/server/runtime-host/local.d.ts +29 -0
- package/dist-server/server/runtime-host/local.js +90 -0
- package/dist-server/server/runtime-host/policy.d.ts +8 -0
- package/dist-server/server/runtime-host/policy.js +78 -0
- package/dist-server/server/runtime-host/types.d.ts +52 -0
- package/dist-server/server/runtime-host/types.js +62 -0
- package/dist-server/server/structured-query-evidence.d.ts +7 -0
- package/dist-server/server/structured-query-evidence.js +47 -0
- package/dist-server/server/structured-runtime.d.ts +52 -0
- package/dist-server/server/structured-runtime.js +130 -0
- package/dist-server/server/structured-scope.d.ts +4 -0
- package/dist-server/server/structured-scope.js +12 -0
- package/dist-server/server/turn.d.ts +6 -1
- package/dist-server/server/turn.js +82 -25
- package/dist-server/server/wire-types.d.ts +67 -3
- package/dist-server/server/wren-profiles.js +1 -1
- package/managed-wren/README.md +60 -0
- package/managed-wren/dependency-wheels.json +282 -0
- package/managed-wren/manifest.json +373 -0
- package/managed-wren/release-inputs.json +45 -0
- package/managed-wren/runtime-tree.cjs +115 -0
- package/managed-wren/source-inputs.json +40 -0
- package/package.json +15 -6
- package/profiles/genbi-default/context/binding.yml +17 -7
- package/profiles/genbi-default/context/context.json +146 -0
- package/profiles/genbi-default/ir.golden.json +39 -43
- package/profiles/genbi-default/profile.yml +31 -0
- package/profiles/genbi-enrich-context/context/binding.yml +14 -3
- package/profiles/genbi-enrich-context/context/context.json +146 -0
- package/profiles/genbi-enrich-context/ir.golden.json +4 -5
- package/profiles/genbi-monitor/context/binding.yml +13 -5
- package/profiles/genbi-monitor/context/context.json +146 -0
- package/profiles/genbi-monitor/ir.golden.json +13 -7
- package/profiles/genbi-report/context/binding.yml +19 -0
- package/profiles/genbi-report/context/context.json +223 -0
- package/profiles/genbi-report/ir.golden.json +328 -0
- package/profiles/genbi-report/profile.yml +38 -0
- package/profiles/genbi-setup/ir.golden.json +3 -1
- package/dist/assets/index-Xs4q7pNo.css +0 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Drain every owned resource and report cleanup failures without process details. */
|
|
2
|
+
export async function shutdownNativeResources(options) {
|
|
3
|
+
let failed = false;
|
|
4
|
+
// Calling the session fence before other cleanup closes new admission immediately.
|
|
5
|
+
let cleanup = Promise.resolve();
|
|
6
|
+
try {
|
|
7
|
+
cleanup = options.shutdownSessions();
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
failed = true;
|
|
11
|
+
}
|
|
12
|
+
// Attach the rejection observer before synchronous cleanup can throw.
|
|
13
|
+
const settled = cleanup.catch(() => { failed = true; });
|
|
14
|
+
try {
|
|
15
|
+
options.closeTerminals();
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
failed = true;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
options.closeServer();
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
failed = true;
|
|
25
|
+
}
|
|
26
|
+
await settled;
|
|
27
|
+
return failed ? 1 : 0;
|
|
28
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { NativeWrenRuntime } from "./native-wren-runtime.js";
|
|
2
|
+
export interface CodexWrenHome {
|
|
3
|
+
readonly home: string;
|
|
4
|
+
readonly dataRoots: readonly string[];
|
|
5
|
+
readonly active?: () => boolean;
|
|
6
|
+
readonly assertActive?: () => void;
|
|
7
|
+
readonly cleanup?: () => void;
|
|
8
|
+
}
|
|
9
|
+
/** Setup has no bound profile yet, but still receives a fresh private WREN_HOME. */
|
|
10
|
+
export declare function createEmptyCodexWrenHome(cwd: string): CodexWrenHome;
|
|
11
|
+
export declare function materializeCodexWrenHome(input: {
|
|
12
|
+
readonly runtime: NativeWrenRuntime;
|
|
13
|
+
readonly projectPath: string;
|
|
14
|
+
readonly cwd: string;
|
|
15
|
+
readonly sourceWrenHome: string;
|
|
16
|
+
readonly home: string;
|
|
17
|
+
readonly toolDirectories: readonly string[];
|
|
18
|
+
}): CodexWrenHome;
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { buildNativeChildEnvironment, nativeProcessEnvironment } from "./native-runtime-spec.js";
|
|
6
|
+
import { InteractiveLaunchError } from "./native-session-workspace.js";
|
|
7
|
+
const MATERIALIZE_WREN_HOME_SCRIPT = String.raw `
|
|
8
|
+
import json
|
|
9
|
+
import os
|
|
10
|
+
import pathlib
|
|
11
|
+
import re
|
|
12
|
+
import sys
|
|
13
|
+
import yaml
|
|
14
|
+
from dotenv import dotenv_values
|
|
15
|
+
from wren.profile import resolve_profile_for_project
|
|
16
|
+
|
|
17
|
+
project = pathlib.Path(sys.argv[1]).resolve(strict=True)
|
|
18
|
+
destination = pathlib.Path(sys.argv[2])
|
|
19
|
+
source_home = pathlib.Path(sys.argv[3]).resolve(strict=True)
|
|
20
|
+
|
|
21
|
+
def regular(path, required=True):
|
|
22
|
+
if not path.exists():
|
|
23
|
+
if required:
|
|
24
|
+
raise SystemExit(2)
|
|
25
|
+
return None
|
|
26
|
+
if path.is_symlink() or not path.is_file() or path.resolve(strict=True) != path:
|
|
27
|
+
raise SystemExit(3)
|
|
28
|
+
return path
|
|
29
|
+
|
|
30
|
+
regular(project / "wren_project.yml")
|
|
31
|
+
regular(source_home / "profiles.yml")
|
|
32
|
+
name, profile = resolve_profile_for_project(project, strict=True)
|
|
33
|
+
if not name or not isinstance(profile, dict):
|
|
34
|
+
raise SystemExit(4)
|
|
35
|
+
|
|
36
|
+
pattern = re.compile(r"\$\{([_A-Z][_A-Z0-9]*)\}")
|
|
37
|
+
keys = set()
|
|
38
|
+
def collect(value):
|
|
39
|
+
if isinstance(value, str):
|
|
40
|
+
keys.update(pattern.findall(value))
|
|
41
|
+
elif isinstance(value, dict):
|
|
42
|
+
for item in value.values(): collect(item)
|
|
43
|
+
elif isinstance(value, list):
|
|
44
|
+
for item in value: collect(item)
|
|
45
|
+
collect(profile)
|
|
46
|
+
|
|
47
|
+
project_env_path = regular(project / ".env", required=False)
|
|
48
|
+
home_env_path = regular(source_home / ".env", required=False)
|
|
49
|
+
project_values = dotenv_values(project_env_path) if project_env_path else {}
|
|
50
|
+
home_values = dotenv_values(home_env_path) if home_env_path else {}
|
|
51
|
+
selected = {}
|
|
52
|
+
for key in sorted(keys):
|
|
53
|
+
value = project_values.get(key)
|
|
54
|
+
if value is None:
|
|
55
|
+
value = home_values.get(key)
|
|
56
|
+
if value is None:
|
|
57
|
+
raise SystemExit(5)
|
|
58
|
+
selected[key] = str(value)
|
|
59
|
+
|
|
60
|
+
def expand(value):
|
|
61
|
+
if isinstance(value, str):
|
|
62
|
+
return pattern.sub(lambda match: selected[match.group(1)], value)
|
|
63
|
+
if isinstance(value, dict):
|
|
64
|
+
return {key: expand(item) for key, item in value.items()}
|
|
65
|
+
if isinstance(value, list):
|
|
66
|
+
return [expand(item) for item in value]
|
|
67
|
+
return value
|
|
68
|
+
|
|
69
|
+
destination.mkdir(mode=0o700, parents=False, exist_ok=False)
|
|
70
|
+
os.chmod(destination, 0o700)
|
|
71
|
+
def private_write(path, content):
|
|
72
|
+
descriptor = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
|
73
|
+
with os.fdopen(descriptor, "w", encoding="utf-8") as output:
|
|
74
|
+
output.write(content)
|
|
75
|
+
os.chmod(path, 0o600)
|
|
76
|
+
|
|
77
|
+
profile_path = destination / "profiles.yml"
|
|
78
|
+
private_write(profile_path, yaml.safe_dump({"active": name, "profiles": {name: profile}}, sort_keys=False))
|
|
79
|
+
if selected:
|
|
80
|
+
session_env = destination / ".env"
|
|
81
|
+
private_write(session_env, "".join(f"{key}={json.dumps(value)}\n" for key, value in selected.items()))
|
|
82
|
+
|
|
83
|
+
expanded = expand(profile)
|
|
84
|
+
data_source = expanded.get("datasource")
|
|
85
|
+
data_root = None
|
|
86
|
+
if data_source in ("duckdb", "local_file"):
|
|
87
|
+
data_root = expanded.get("url")
|
|
88
|
+
elif data_source == "datafusion":
|
|
89
|
+
data_root = expanded.get("source")
|
|
90
|
+
if data_root:
|
|
91
|
+
root = pathlib.Path(data_root).expanduser()
|
|
92
|
+
if not root.is_absolute():
|
|
93
|
+
root = project / root
|
|
94
|
+
print(root.resolve(strict=True))
|
|
95
|
+
`;
|
|
96
|
+
function unavailable() {
|
|
97
|
+
throw new InteractiveLaunchError("native Wren session home is unavailable");
|
|
98
|
+
}
|
|
99
|
+
function privateDirectoryIdentity(directory) {
|
|
100
|
+
try {
|
|
101
|
+
const metadata = lstatSync(directory);
|
|
102
|
+
const canonical = realpathSync(directory);
|
|
103
|
+
if (!metadata.isDirectory() || metadata.isSymbolicLink() || canonical !== directory || (metadata.mode & 0o777) !== 0o700)
|
|
104
|
+
return unavailable();
|
|
105
|
+
return { canonical, dev: metadata.dev, ino: metadata.ino, mode: metadata.mode & 0o777 };
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (error instanceof InteractiveLaunchError)
|
|
109
|
+
throw error;
|
|
110
|
+
return unavailable();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function privateFileIdentity(file) {
|
|
114
|
+
try {
|
|
115
|
+
const metadata = lstatSync(file);
|
|
116
|
+
const canonical = realpathSync(file);
|
|
117
|
+
if (!metadata.isFile() || metadata.isSymbolicLink() || canonical !== file || (metadata.mode & 0o777) !== 0o600)
|
|
118
|
+
return unavailable();
|
|
119
|
+
return {
|
|
120
|
+
canonical,
|
|
121
|
+
dev: metadata.dev,
|
|
122
|
+
ino: metadata.ino,
|
|
123
|
+
mode: metadata.mode & 0o777,
|
|
124
|
+
size: metadata.size,
|
|
125
|
+
mtimeMs: metadata.mtimeMs,
|
|
126
|
+
ctimeMs: metadata.ctimeMs,
|
|
127
|
+
digest: createHash("sha256").update(readFileSync(file)).digest("hex"),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (error instanceof InteractiveLaunchError)
|
|
132
|
+
throw error;
|
|
133
|
+
return unavailable();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function samePathIdentity(left, right) {
|
|
137
|
+
return left.canonical === right.canonical && left.dev === right.dev && left.ino === right.ino && left.mode === right.mode;
|
|
138
|
+
}
|
|
139
|
+
function sameFileIdentity(left, right) {
|
|
140
|
+
return samePathIdentity(left, right)
|
|
141
|
+
&& left.size === right.size
|
|
142
|
+
&& left.mtimeMs === right.mtimeMs
|
|
143
|
+
&& left.ctimeMs === right.ctimeMs
|
|
144
|
+
&& left.digest === right.digest;
|
|
145
|
+
}
|
|
146
|
+
function captureWrenHome(destination, fileNames) {
|
|
147
|
+
try {
|
|
148
|
+
const actualNames = readdirSync(destination).sort();
|
|
149
|
+
const expectedNames = [...fileNames].sort();
|
|
150
|
+
if (JSON.stringify(actualNames) !== JSON.stringify(expectedNames))
|
|
151
|
+
return unavailable();
|
|
152
|
+
return {
|
|
153
|
+
directory: privateDirectoryIdentity(destination),
|
|
154
|
+
files: Object.freeze(Object.fromEntries(expectedNames.map((name) => [name, privateFileIdentity(path.join(destination, name))]))),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
if (error instanceof InteractiveLaunchError)
|
|
159
|
+
throw error;
|
|
160
|
+
return unavailable();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function assertWrenHome(destination, expected) {
|
|
164
|
+
const current = captureWrenHome(destination, Object.keys(expected.files));
|
|
165
|
+
if (!samePathIdentity(current.directory, expected.directory))
|
|
166
|
+
return unavailable();
|
|
167
|
+
for (const [name, identity] of Object.entries(expected.files)) {
|
|
168
|
+
const observed = current.files[name];
|
|
169
|
+
if (!observed || !sameFileIdentity(observed, identity))
|
|
170
|
+
return unavailable();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function retirementMarker(cwd) {
|
|
174
|
+
return path.join(cwd, ".wren-retired");
|
|
175
|
+
}
|
|
176
|
+
function retire(destination, marker) {
|
|
177
|
+
rmSync(destination, { recursive: true, force: true });
|
|
178
|
+
writeFileSync(marker, "retired\n", { encoding: "utf8", mode: 0o600, flag: "wx" });
|
|
179
|
+
privateFileIdentity(marker);
|
|
180
|
+
}
|
|
181
|
+
/** Setup has no bound profile yet, but still receives a fresh private WREN_HOME. */
|
|
182
|
+
export function createEmptyCodexWrenHome(cwd) {
|
|
183
|
+
const destination = path.join(cwd, ".wren");
|
|
184
|
+
const marker = retirementMarker(cwd);
|
|
185
|
+
let active = false;
|
|
186
|
+
try {
|
|
187
|
+
if (existsSync(marker))
|
|
188
|
+
throw new Error("retired");
|
|
189
|
+
mkdirSync(destination, { mode: 0o700 });
|
|
190
|
+
chmodSync(destination, 0o700);
|
|
191
|
+
const identity = captureWrenHome(destination, []);
|
|
192
|
+
active = true;
|
|
193
|
+
return Object.freeze({
|
|
194
|
+
home: destination,
|
|
195
|
+
dataRoots: Object.freeze([]),
|
|
196
|
+
active: () => active,
|
|
197
|
+
assertActive: () => {
|
|
198
|
+
if (!active)
|
|
199
|
+
return unavailable();
|
|
200
|
+
assertWrenHome(destination, identity);
|
|
201
|
+
},
|
|
202
|
+
cleanup: () => {
|
|
203
|
+
if (!active)
|
|
204
|
+
return;
|
|
205
|
+
active = false;
|
|
206
|
+
retire(destination, marker);
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
rmSync(destination, { recursive: true, force: true });
|
|
212
|
+
throw new InteractiveLaunchError("native Wren session home is unavailable");
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
export function materializeCodexWrenHome(input) {
|
|
216
|
+
const destination = path.join(input.cwd, ".wren");
|
|
217
|
+
const marker = retirementMarker(input.cwd);
|
|
218
|
+
let active = false;
|
|
219
|
+
try {
|
|
220
|
+
if (existsSync(marker))
|
|
221
|
+
throw new Error("retired");
|
|
222
|
+
const environment = buildNativeChildEnvironment({
|
|
223
|
+
toolDirectories: input.toolDirectories,
|
|
224
|
+
home: input.home,
|
|
225
|
+
projectPath: input.projectPath,
|
|
226
|
+
wrenHome: input.sourceWrenHome,
|
|
227
|
+
python: true,
|
|
228
|
+
});
|
|
229
|
+
const output = execFileSync(input.runtime.venv_python, ["-c", MATERIALIZE_WREN_HOME_SCRIPT, input.projectPath, destination, input.sourceWrenHome], {
|
|
230
|
+
cwd: input.projectPath,
|
|
231
|
+
env: nativeProcessEnvironment(environment),
|
|
232
|
+
encoding: "utf8",
|
|
233
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
234
|
+
timeout: 10_000,
|
|
235
|
+
});
|
|
236
|
+
const envFile = path.join(destination, ".env");
|
|
237
|
+
const identity = captureWrenHome(destination, ["profiles.yml", ...(existsSync(envFile) ? [".env"] : [])]);
|
|
238
|
+
active = true;
|
|
239
|
+
const assertActive = () => {
|
|
240
|
+
if (!active)
|
|
241
|
+
return unavailable();
|
|
242
|
+
assertWrenHome(destination, identity);
|
|
243
|
+
};
|
|
244
|
+
return Object.freeze({
|
|
245
|
+
home: destination,
|
|
246
|
+
dataRoots: Object.freeze(output.trim() ? [output.trim()] : []),
|
|
247
|
+
active: () => active,
|
|
248
|
+
assertActive,
|
|
249
|
+
cleanup: () => {
|
|
250
|
+
if (!active)
|
|
251
|
+
return;
|
|
252
|
+
active = false;
|
|
253
|
+
retire(destination, marker);
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
active = false;
|
|
259
|
+
rmSync(destination, { recursive: true, force: true });
|
|
260
|
+
throw new InteractiveLaunchError("native Wren project profile is unavailable");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type PtyFactory, type PtyProcess } from "./interactive-terminal.js";
|
|
2
|
+
import { type NativeChildEnvironment } from "./native-runtime-spec.js";
|
|
2
3
|
interface NodePtyModule {
|
|
3
4
|
spawn(file: string, args: string[], options: {
|
|
4
5
|
cwd: string;
|
|
@@ -10,7 +11,7 @@ interface NodePtyModule {
|
|
|
10
11
|
}
|
|
11
12
|
export interface PtyHostOptions {
|
|
12
13
|
readonly cwd?: string;
|
|
13
|
-
readonly env?: NodeJS.ProcessEnv;
|
|
14
|
+
readonly env?: NodeJS.ProcessEnv | NativeChildEnvironment;
|
|
14
15
|
readonly probeExecutable?: string;
|
|
15
16
|
readonly probeTimeoutMs?: number;
|
|
16
17
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { closeSync, constants, fchmodSync, fstatSync, lstatSync, openSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { nativeTerminalEnvironment } from "./interactive-terminal.js";
|
|
4
|
+
import { nativeProcessEnvironment } from "./native-runtime-spec.js";
|
|
4
5
|
/**
|
|
5
6
|
* node-pty 1.1 ships a small spawn-helper for prebuilt macOS binaries. Some
|
|
6
7
|
* package managers restore that regular file without its executable mode,
|
|
@@ -62,7 +63,7 @@ export async function createProbedPtyFactory(nodePty, options = {}) {
|
|
|
62
63
|
cols: 80,
|
|
63
64
|
rows: 24,
|
|
64
65
|
name: "xterm-256color",
|
|
65
|
-
env,
|
|
66
|
+
env: nativeProcessEnvironment(env),
|
|
66
67
|
});
|
|
67
68
|
}
|
|
68
69
|
catch {
|
|
@@ -94,7 +95,7 @@ export async function createProbedPtyFactory(nodePty, options = {}) {
|
|
|
94
95
|
name: "xterm-256color",
|
|
95
96
|
// Defend this lower adapter too: future PTY callers cannot bypass the
|
|
96
97
|
// server-owned native-terminal color contract by supplying an env.
|
|
97
|
-
env: nativeTerminalEnvironment(spawnOptions.env ?? env),
|
|
98
|
+
env: nativeProcessEnvironment(nativeTerminalEnvironment(spawnOptions.env ?? env)),
|
|
98
99
|
}),
|
|
99
100
|
};
|
|
100
101
|
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { Store, WarbleProfileAdmissionStatus, WarbleProfileEntryKind, WarbleProfileKind, WarbleProfileRole, WarbleProfileRow } from "./db.js";
|
|
2
|
+
import type { WarbleProfileDto } from "./wire-types.js";
|
|
3
|
+
export type { WarbleProfileAdmissionStatus, WarbleProfileEntryKind, WarbleProfileKind, WarbleProfileRole, WarbleProfileRow };
|
|
4
|
+
/** The shipped profiles and the role each plays. Anything else under `profiles/` is ignored. */
|
|
5
|
+
export declare const BUILTIN_PROFILE_ROLES: Readonly<Record<string, WarbleProfileRole>>;
|
|
6
|
+
/** The profile whose compiled IR defines the host ceiling. */
|
|
7
|
+
export declare const CEILING_PROFILE_ID = "genbi-default";
|
|
8
|
+
/** The persisted runtime tier rows come from the analysis profile and name exactly these two tiers. */
|
|
9
|
+
export declare const HOST_TIERS: ReadonlySet<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Bump when an admission rule is added, tightened or withdrawn. A stored verdict computed under an
|
|
12
|
+
* older rule set is stale even when the profile bytes and the warble binary are unchanged — the
|
|
13
|
+
* rules are the third input to the verdict. 1: rules 1–6. 2: a pinned entry must not compose.
|
|
14
|
+
* 3: that rule withdrawn (the dispatcher refuses every composing profile without a host, so it
|
|
15
|
+
* never separated anything); composition is recorded on the component summary instead.
|
|
16
|
+
*/
|
|
17
|
+
export declare const ADMISSION_RULES_VERSION = 3;
|
|
18
|
+
export declare class ProfileRegistryError extends Error {
|
|
19
|
+
readonly status: 400 | 404 | 409 | 503;
|
|
20
|
+
constructor(status: 400 | 404 | 409 | 503, message: string);
|
|
21
|
+
}
|
|
22
|
+
export interface HostCeiling {
|
|
23
|
+
readonly capabilities: ReadonlySet<string>;
|
|
24
|
+
readonly tiers: ReadonlySet<string>;
|
|
25
|
+
}
|
|
26
|
+
export interface AdmissionComponentSummary {
|
|
27
|
+
readonly id: string;
|
|
28
|
+
readonly type: string;
|
|
29
|
+
readonly trigger: string;
|
|
30
|
+
readonly outcome: string;
|
|
31
|
+
readonly realizationKind: string;
|
|
32
|
+
readonly entrypoint: boolean;
|
|
33
|
+
readonly tiers: readonly string[];
|
|
34
|
+
readonly capabilities: readonly string[];
|
|
35
|
+
readonly hasDescription: boolean;
|
|
36
|
+
readonly nativeEligible: boolean;
|
|
37
|
+
/** `alias → component` edges this component's steps authorize; non-empty means it composes. */
|
|
38
|
+
readonly composes: readonly string[];
|
|
39
|
+
}
|
|
40
|
+
export interface AdmissionVerdict {
|
|
41
|
+
readonly status: WarbleProfileAdmissionStatus;
|
|
42
|
+
/** Every failed rule, in rule order; empty when admitted. */
|
|
43
|
+
readonly reasons: readonly string[];
|
|
44
|
+
readonly entry?: {
|
|
45
|
+
readonly kind: WarbleProfileEntryKind;
|
|
46
|
+
readonly verb?: string;
|
|
47
|
+
};
|
|
48
|
+
readonly irVersion?: string;
|
|
49
|
+
readonly components: readonly AdmissionComponentSummary[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The capability ceiling is whatever the shipped analysis profile already requires, read from its
|
|
53
|
+
* compiled IR. Listing the names by hand would let the ceiling drift from the profile it describes.
|
|
54
|
+
*/
|
|
55
|
+
export declare function deriveHostCeiling(ceilingIr: unknown): HostCeiling;
|
|
56
|
+
/** Rules 2–5 over a compiled IR. Pure: rule 1 (compiling) and rule 6 (staleness) live in the registry. */
|
|
57
|
+
export declare function admitCompiledProfile(ir: unknown, options: {
|
|
58
|
+
readonly expectedId: string;
|
|
59
|
+
readonly ceiling: HostCeiling;
|
|
60
|
+
}): AdmissionVerdict;
|
|
61
|
+
/** The `profile:` scalar of a profile.yml. Flat YAML, read the same way `composeUserProfile` does. */
|
|
62
|
+
export declare function readProfileId(profileYamlText: string): string | undefined;
|
|
63
|
+
export type SourcePathCheck = {
|
|
64
|
+
readonly ok: true;
|
|
65
|
+
readonly resolved: string;
|
|
66
|
+
readonly real: string;
|
|
67
|
+
} | {
|
|
68
|
+
readonly ok: false;
|
|
69
|
+
readonly message: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* A user profile is handed to the server as a directory path on this machine, the same way the
|
|
73
|
+
* adopt flow receives a project path. The path is checked, not trusted: it must be absolute, be a
|
|
74
|
+
* real directory rather than a link, hold a `profile.yml`, and sit outside the roots the registry
|
|
75
|
+
* itself owns, so a request can never register the package tree or the user-data tree as "new".
|
|
76
|
+
*/
|
|
77
|
+
export declare function validateUserProfileSourcePath(sourcePath: unknown, options: {
|
|
78
|
+
readonly forbiddenRoots: readonly string[];
|
|
79
|
+
}): SourcePathCheck;
|
|
80
|
+
export declare function toWarbleProfileDto(row: WarbleProfileRow): WarbleProfileDto;
|
|
81
|
+
export interface ProfileRegistryOptions {
|
|
82
|
+
readonly store: Store;
|
|
83
|
+
/** The package's own `profiles/` tree (the directory the analysis profile source lives in). */
|
|
84
|
+
readonly builtinProfilesDir: string;
|
|
85
|
+
/** Where user-added profiles are copied: `<workspaceRoot>/profiles`. Created on first add. */
|
|
86
|
+
readonly userProfilesDir: string;
|
|
87
|
+
/** Rule 1: compile a raw profile directory with the pinned warble. Throws on failure. */
|
|
88
|
+
readonly compileRaw: (profileSource: string) => Promise<{
|
|
89
|
+
readonly irPath: string;
|
|
90
|
+
}>;
|
|
91
|
+
/** Identity of the warble binary admission ran against; part of the staleness key (rule 6). */
|
|
92
|
+
readonly warbleIdentity: () => Promise<string>;
|
|
93
|
+
readonly now?: () => Date;
|
|
94
|
+
}
|
|
95
|
+
export declare class ProfileRegistry {
|
|
96
|
+
private readonly options;
|
|
97
|
+
private ready;
|
|
98
|
+
private ceiling;
|
|
99
|
+
private ceilingFailure;
|
|
100
|
+
private readonly now;
|
|
101
|
+
constructor(options: ProfileRegistryOptions);
|
|
102
|
+
/** Registers the shipped profiles once and re-checks stored rows whose inputs changed. Idempotent. */
|
|
103
|
+
ensureReady(): Promise<void>;
|
|
104
|
+
private initialize;
|
|
105
|
+
private registerBuiltins;
|
|
106
|
+
private registerBuiltin;
|
|
107
|
+
private readmitIfStale;
|
|
108
|
+
/**
|
|
109
|
+
* Runs rules 1–5 for one directory and persists the verdict. The ceiling profile's own verdict
|
|
110
|
+
* also fixes the ceiling; while it fails to compile no conversation profile can be admitted,
|
|
111
|
+
* and each row says so rather than silently inheriting an empty ceiling.
|
|
112
|
+
*/
|
|
113
|
+
private admitAndStore;
|
|
114
|
+
/**
|
|
115
|
+
* `warble compile` re-derives its fetched Hub cache on every run and documents that two
|
|
116
|
+
* concurrent runs can collide on the rename, failing one of them loudly and transiently. A BFF
|
|
117
|
+
* compiles for readiness and sessions while this registry is admitting, so one bounded retry
|
|
118
|
+
* keeps a shipped profile from being recorded as unavailable over that collision. A profile that
|
|
119
|
+
* fails twice is recorded with the second failure.
|
|
120
|
+
*/
|
|
121
|
+
private compileOnceWithRetry;
|
|
122
|
+
list(): Promise<readonly WarbleProfileRow[]>;
|
|
123
|
+
get(id: string): Promise<WarbleProfileRow | undefined>;
|
|
124
|
+
/**
|
|
125
|
+
* Copies a profile directory from `sourcePath` into the user-data tree and admits it. The copy is
|
|
126
|
+
* what the registry owns from then on; the original is never read again.
|
|
127
|
+
*/
|
|
128
|
+
add(sourcePath: unknown): Promise<WarbleProfileRow>;
|
|
129
|
+
/** Removes a user profile and its copy. A profile any native session has run inside stays. */
|
|
130
|
+
remove(id: string): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* The directory a conversation session compiles from, for an id the browser selected. Refuses
|
|
133
|
+
* anything that is not an admitted conversation profile, with the stored reason.
|
|
134
|
+
*/
|
|
135
|
+
resolveConversationProfileSource(id: string): Promise<{
|
|
136
|
+
readonly sourceDir: string;
|
|
137
|
+
readonly row: WarbleProfileRow;
|
|
138
|
+
}>;
|
|
139
|
+
}
|