humanish 0.110.0 → 0.110.2
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/ARCHITECTURE.md +15 -12
- package/CHANGELOG.md +26 -0
- package/CONTEXT.md +8 -6
- package/README.md +103 -53
- package/dist/actors/computer-use/loop/ending.js +4 -4
- package/dist/actors/local-agent/claude-participant.d.ts +74 -0
- package/dist/actors/local-agent/claude-participant.js +243 -0
- package/dist/actors/local-agent/claude-session.d.ts +16 -3
- package/dist/actors/local-agent/claude-session.js +64 -23
- package/dist/actors/local-agent/cli.d.ts +17 -0
- package/dist/actors/local-agent/cli.js +111 -24
- package/dist/actors/local-agent/readiness.d.ts +2 -2
- package/dist/actors/local-agent/readiness.js +20 -12
- package/dist/cli/commands/analyze.js +21 -5
- package/dist/cli/commands/observe.js +15 -2
- package/dist/cli/commands/run-signals.d.ts +2 -0
- package/dist/cli/commands/run-signals.js +106 -45
- package/dist/cli/commands/runs.d.ts +5 -0
- package/dist/cli/commands/runs.js +113 -74
- package/dist/cli/commands/setup.js +23 -14
- package/dist/cli/commands/study-route-computer-use.js +9 -3
- package/dist/cli/commands/study-route-open.js +1 -0
- package/dist/cli/commands/study-route-preview.js +1 -0
- package/dist/cli/commands/study-route-scripted.js +2 -0
- package/dist/cli/commands/study-route-shared-world.js +6 -2
- package/dist/cli/commands/study-route-terminal.js +2 -0
- package/dist/cli/commands/watch.js +14 -4
- package/dist/cli/doctor.d.ts +4 -1
- package/dist/cli/doctor.js +51 -10
- package/dist/cli/findings.d.ts +103 -0
- package/dist/cli/findings.js +317 -0
- package/dist/cli/first-run-path.d.ts +32 -11
- package/dist/cli/first-run-path.js +113 -69
- package/dist/cli/invocation.d.ts +7 -0
- package/dist/cli/invocation.js +32 -0
- package/dist/cli/io.d.ts +3 -1
- package/dist/cli/io.js +8 -15
- package/dist/cli/observer-follow.d.ts +20 -0
- package/dist/cli/observer-follow.js +36 -1
- package/dist/cli/orientation.js +16 -14
- package/dist/cli/product-sentence.d.ts +3 -3
- package/dist/cli/product-sentence.js +3 -3
- package/dist/cli/version.d.ts +1 -0
- package/dist/cli/version.js +11 -0
- package/dist/evidence/encoded-text.d.ts +9 -6
- package/dist/evidence/encoded-text.js +84 -19
- package/dist/evidence/redaction.d.ts +2 -0
- package/dist/evidence/redaction.js +123 -21
- package/dist/feedback/export-bundle.js +2 -2
- package/dist/keys/env-file.d.ts +4 -0
- package/dist/keys/env-file.js +17 -0
- package/dist/keys/key-resolution.js +6 -5
- package/dist/observer/data.d.ts +14 -1
- package/dist/observer/data.js +19 -9
- package/dist/observer/exposure.js +1 -1
- package/dist/observer/library.d.ts +4 -0
- package/dist/observer/library.js +21 -17
- package/dist/observer/render.js +10 -3
- package/dist/observer/run-routes.d.ts +2 -0
- package/dist/observer/run-routes.js +51 -35
- package/dist/observer/serve.js +2 -1
- package/dist/observer-app.html +3 -3
- package/dist/routes/computer-use/bundle.js +3 -1
- package/dist/routes/computer-use/fanout-records.js +1 -1
- package/dist/routes/computer-use/participant-execution.js +3 -1
- package/dist/routes/computer-use/participant-model.js +5 -2
- package/dist/routes/computer-use/plan.js +9 -4
- package/dist/routes/computer-use/preflight.js +1 -1
- package/dist/routes/computer-use/result.js +17 -28
- package/dist/routes/computer-use/single-bundle.js +7 -1
- package/dist/routes/scripted/bundle.js +4 -2
- package/dist/routes/scripted/plan.js +2 -2
- package/dist/routes/scripted/result.d.ts +3 -5
- package/dist/routes/scripted/result.js +16 -22
- package/dist/routes/scripted/scenario.js +4 -4
- package/dist/routes/shared-world/bundle-records.js +6 -1
- package/dist/routes/shared-world/bundle.js +2 -0
- package/dist/routes/shared-world/plan.js +6 -2
- package/dist/routes/shared-world/result.js +22 -22
- package/dist/routes/terminal/bundle.js +6 -3
- package/dist/routes/terminal/credentials.d.ts +5 -5
- package/dist/routes/terminal/credentials.js +14 -6
- package/dist/routes/terminal/dry-run.js +8 -12
- package/dist/routes/terminal/ledger.d.ts +3 -3
- package/dist/routes/terminal/ledger.js +6 -6
- package/dist/routes/terminal/live-finish.js +15 -13
- package/dist/routes/terminal/plan.js +12 -4
- package/dist/routes/terminal/result.d.ts +6 -7
- package/dist/routes/terminal/result.js +6 -22
- package/dist/routes/terminal/route.js +5 -4
- package/dist/routes/terminal/runtime-auth.d.ts +6 -0
- package/dist/routes/terminal/runtime-auth.js +5 -0
- package/dist/routes/terminal/session.js +1 -1
- package/dist/run/bundle-shape.d.ts +3 -1
- package/dist/run/bundle-shape.js +25 -1
- package/dist/run/bundle.d.ts +24 -0
- package/dist/run/display.d.ts +59 -0
- package/dist/run/display.js +106 -0
- package/dist/run/dry-run.js +13 -8
- package/dist/run/judge.d.ts +3 -2
- package/dist/run/judge.js +12 -1
- package/dist/run/local-only-files.d.ts +13 -0
- package/dist/run/local-only-files.js +35 -0
- package/dist/run/pricing.js +1 -1
- package/dist/run/projection.d.ts +0 -2
- package/dist/run/projection.js +0 -11
- package/dist/run/reclaim-outcomes.d.ts +89 -0
- package/dist/run/reclaim-outcomes.js +213 -0
- package/dist/run/reclaim.d.ts +23 -17
- package/dist/run/reclaim.js +213 -114
- package/dist/run/results.d.ts +10 -20
- package/dist/run/results.js +2 -2
- package/dist/run/run-index.d.ts +11 -1
- package/dist/run/run-index.js +11 -0
- package/dist/run/run-not-found.js +3 -2
- package/dist/run/run.d.ts +34 -18
- package/dist/run/run.js +166 -67
- package/dist/run/sandbox-creates.d.ts +59 -0
- package/dist/run/sandbox-creates.js +140 -0
- package/dist/run/sandbox-receipts.d.ts +20 -5
- package/dist/run/sandbox-receipts.js +56 -7
- package/dist/run/stats.d.ts +5 -0
- package/dist/run/stats.js +8 -4
- package/dist/run/status.d.ts +6 -9
- package/dist/run/status.js +7 -23
- package/dist/run/stored-runs.d.ts +5 -14
- package/dist/run/stored-runs.js +31 -146
- package/dist/run/streams.d.ts +3 -2
- package/dist/study/agents-section.d.ts +21 -0
- package/dist/study/agents-section.js +86 -0
- package/dist/study/doctor.d.ts +1 -1
- package/dist/study/doctor.js +8 -4
- package/dist/study/init-templates.js +0 -95
- package/dist/study/init.js +45 -37
- package/dist/study/keys.d.ts +12 -0
- package/dist/study/keys.js +32 -0
- package/dist/study/local-browser-host.d.ts +11 -0
- package/dist/study/local-browser-host.js +42 -0
- package/dist/study/parse/actors.js +9 -1
- package/dist/study/parse/subject.js +12 -0
- package/dist/study/parse/url-credentials.d.ts +9 -0
- package/dist/study/parse/url-credentials.js +50 -0
- package/dist/study/persona.d.ts +4 -0
- package/dist/study/persona.js +4 -2
- package/dist/study/preflight-probes.js +2 -1
- package/dist/study/types.d.ts +8 -6
- package/dist/study/url-credentials.d.ts +6 -0
- package/dist/study/url-credentials.js +34 -0
- package/dist/substrates/e2b/peer-install.d.ts +51 -0
- package/dist/substrates/e2b/peer-install.js +161 -0
- package/dist/substrates/e2b/sandbox.d.ts +34 -6
- package/dist/substrates/e2b/sandbox.js +141 -30
- package/dist/substrates/e2b/sdk.d.ts +33 -0
- package/dist/substrates/e2b/sdk.js +21 -21
- package/dist/substrates/local/firecracker-desktop.js +3 -2
- package/dist/substrates/local/runtime-host.js +5 -4
- package/dist/substrates/local/runtime.js +5 -4
- package/dist/substrates/shell.d.ts +2 -0
- package/dist/substrates/shell.js +4 -0
- package/dist/tui/contract.js +5 -4
- package/dist/tui-app.js +133 -133
- package/dist/verify/liveness.d.ts +19 -3
- package/dist/verify/liveness.js +47 -25
- package/dist/verify/verify.d.ts +3 -0
- package/dist/verify/verify.js +8 -3
- package/docs/architecture/actor-contract.md +2 -1
- package/docs/architecture/observer.md +22 -7
- package/docs/architecture/task-protocol-support.md +13 -13
- package/docs/architecture/terminal-product-route.md +15 -13
- package/docs/contracts/run-bundle.md +95 -10
- package/docs/contracts/schemas.md +44 -26
- package/docs/contracts/study-analysis.md +45 -0
- package/docs/contracts/study-costs.md +8 -0
- package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +3 -0
- package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +9 -3
- package/docs/principles/invariants-and-defaults.md +11 -8
- package/package.json +6 -3
- package/skills/humanish/SKILL.md +38 -20
|
@@ -5,27 +5,32 @@
|
|
|
5
5
|
// E2BDesktopSandbox is the command, file, stream, launch and input subset the participants use; `open` is
|
|
6
6
|
// optional because older SDKs lack it (the computer-use route then falls back to launch). It
|
|
7
7
|
// satisfies the executor's E2BDesktopLike port (src/substrates/e2b/desktop-executor.ts) as is.
|
|
8
|
-
import { sep } from "node:path";
|
|
9
|
-
import { fileURLToPath } from "node:url";
|
|
10
8
|
import { protectDesktopScreenshotCleanup } from "./desktop-screenshot-cleanup.js";
|
|
9
|
+
import { desktopPeerAdvice, humanishInstall } from "./peer-install.js";
|
|
11
10
|
export async function loadE2BDesktopModule() {
|
|
12
11
|
try {
|
|
13
12
|
return guardDesktopSandboxCreate((await import("@e2b/desktop")));
|
|
14
13
|
}
|
|
15
14
|
catch (error) {
|
|
16
15
|
if (isMissingE2BDesktopDependency(error)) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"in this project: `npm i -D @e2b/desktop`."
|
|
20
|
-
: "Live E2B desktop launch requires the optional peer @e2b/desktop, and humanish is running from an " +
|
|
21
|
-
"npx cache. Node resolves the peer relative to humanish itself, so a copy installed in this project " +
|
|
22
|
-
"is not found. Install both into the project and run it from there: " +
|
|
23
|
-
"`npm i -D humanish @e2b/desktop` then `npx humanish run <study>`.");
|
|
16
|
+
const { where, advice } = desktopPeerAdvice(humanishInstall());
|
|
17
|
+
throw new Error(`Live E2B desktop launch requires the optional peer @e2b/desktop${where}. ${advice}`);
|
|
24
18
|
}
|
|
25
19
|
throw error;
|
|
26
20
|
}
|
|
27
21
|
}
|
|
28
22
|
export const DESKTOP_CREATE_CLEANUP_TIMEOUT_MS = 10_000;
|
|
23
|
+
const allocationObservers = new WeakMap();
|
|
24
|
+
/**
|
|
25
|
+
* Call `observer` with the sandbox id as soon as the guarded SDK constructs the handle for a
|
|
26
|
+
* create made with this exact options object, before desktop startup runs. Startup can take
|
|
27
|
+
* seconds after E2B created the sandbox; this is the earliest point the id exists in this process.
|
|
28
|
+
* A module without the guard (a test fake) never calls it, and create's own result still reports
|
|
29
|
+
* the id.
|
|
30
|
+
*/
|
|
31
|
+
export function observeDesktopAllocation(options, observer) {
|
|
32
|
+
allocationObservers.set(options, observer);
|
|
33
|
+
}
|
|
29
34
|
/** Startup failed after this call acquired a handle. No credentials/options are included here. */
|
|
30
35
|
export class E2BDesktopStartupError extends Error {
|
|
31
36
|
cleanup;
|
|
@@ -67,6 +72,7 @@ export function guardDesktopSandboxCreate(module) {
|
|
|
67
72
|
: DESKTOP_CREATE_CLEANUP_TIMEOUT_MS;
|
|
68
73
|
let cleanupOwned;
|
|
69
74
|
let restoreKill;
|
|
75
|
+
const observeAllocation = createOptions === undefined ? undefined : allocationObservers.get(createOptions);
|
|
70
76
|
// oxlint-disable-next-line typescript/no-this-alias -- the attempt subclasses whichever SDK class was called
|
|
71
77
|
const CallingSandbox = this;
|
|
72
78
|
class AttemptSandbox extends CallingSandbox {
|
|
@@ -91,6 +97,12 @@ export function guardDesktopSandboxCreate(module) {
|
|
|
91
97
|
else
|
|
92
98
|
Reflect.deleteProperty(this, "kill");
|
|
93
99
|
};
|
|
100
|
+
try {
|
|
101
|
+
observeAllocation?.(this.sandboxId);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// An observer that throws must not fail the create; the resolved handle reports the id.
|
|
105
|
+
}
|
|
94
106
|
}
|
|
95
107
|
}
|
|
96
108
|
try {
|
|
@@ -144,18 +156,6 @@ async function reclaimFailedDesktopCreate(kill, timeoutMs) {
|
|
|
144
156
|
clearTimeout(timer);
|
|
145
157
|
}
|
|
146
158
|
}
|
|
147
|
-
/**
|
|
148
|
-
* Is humanish running from this project's node_modules, or from an npx cache?
|
|
149
|
-
*
|
|
150
|
-
* It decides which advice is true. `npx humanish@latest` resolves its optional peer relative to
|
|
151
|
-
* itself, so "install @e2b/desktop in this project" is advice that cannot work there, and that
|
|
152
|
-
* message cost two cold verification runs before the difference was noticed. A one-shot npx
|
|
153
|
-
* invocation cannot do a live desktop run at all; humanish has to be installed alongside the peer.
|
|
154
|
-
*/
|
|
155
|
-
function runningFromProject() {
|
|
156
|
-
const here = fileURLToPath(import.meta.url);
|
|
157
|
-
return here.startsWith(`${process.cwd()}${sep}node_modules${sep}`);
|
|
158
|
-
}
|
|
159
159
|
function isMissingE2BDesktopDependency(error) {
|
|
160
160
|
const value = error;
|
|
161
161
|
return value.code === "ERR_MODULE_NOT_FOUND" && value.message?.includes("@e2b/desktop") === true;
|
|
@@ -9,6 +9,7 @@ import { ownDesktopAllocation, } from "../desktop-session.js";
|
|
|
9
9
|
import { runtimeDocker, runtimeExec, usesLima } from "./runtime-host.js";
|
|
10
10
|
import { openLimaTunnel } from "./runtime-ssh.js";
|
|
11
11
|
import { guestMediaConfigSchema } from "../../guest/media-config.js";
|
|
12
|
+
import { cli } from "../../cli/invocation.js";
|
|
12
13
|
const docker = async (args) => (await runtimeDocker(args, {}, 60_000)).stdout.trim();
|
|
13
14
|
const readLogs = async (id) => {
|
|
14
15
|
const result = await runtimeDocker(["logs", "--tail", "100", id], {}, 10_000);
|
|
@@ -18,12 +19,12 @@ function checkDesktopOptions(options) {
|
|
|
18
19
|
if (options.media !== undefined) {
|
|
19
20
|
guestMediaConfigSchema.parse(options.media);
|
|
20
21
|
if (options.assets.media !== true)
|
|
21
|
-
throw new Error(
|
|
22
|
+
throw new Error(`This local runtime does not include media. Run ${cli("runtime setup --media")}.`);
|
|
22
23
|
}
|
|
23
24
|
if (options.recording !== undefined) {
|
|
24
25
|
desktopRecordingConfigSchema.parse(options.recording);
|
|
25
26
|
if (options.assets.media !== true)
|
|
26
|
-
throw new Error(
|
|
27
|
+
throw new Error(`This runtime does not include the recorder. Run ${cli("runtime setup --media")}.`);
|
|
27
28
|
}
|
|
28
29
|
let url;
|
|
29
30
|
try {
|
|
@@ -3,6 +3,7 @@ import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { promisify } from "node:util";
|
|
6
|
+
import { cli } from "../../cli/invocation.js";
|
|
6
7
|
const exec = promisify(execFile);
|
|
7
8
|
export const LIMA_INSTANCE = "humanish-runtime";
|
|
8
9
|
export const usesLima = (options = {}) => (options.platform ?? process.platform) === "darwin";
|
|
@@ -86,11 +87,11 @@ export async function limaStatus(options = {}) {
|
|
|
86
87
|
version = (await hostExec("limactl", ["--version"], options)).stdout;
|
|
87
88
|
}
|
|
88
89
|
catch {
|
|
89
|
-
throw new Error(
|
|
90
|
+
throw new Error(`Install Lima 2.2 or newer (brew install lima), then run ${cli("runtime setup")}. Docker Desktop is not required.`);
|
|
90
91
|
}
|
|
91
92
|
const match = /\b(\d+)\.(\d+)\.\d+/.exec(version);
|
|
92
93
|
if (!match || Number(match[1]) < 2 || (Number(match[1]) === 2 && Number(match[2]) < 2))
|
|
93
|
-
throw new Error(
|
|
94
|
+
throw new Error(`Update Lima to 2.2 or newer (brew upgrade lima), then run ${cli("runtime setup")}.`);
|
|
94
95
|
const output = (await hostExec("limactl", ["list", "--json"], options)).stdout.trim();
|
|
95
96
|
const instance = output
|
|
96
97
|
.split("\n")
|
|
@@ -104,8 +105,8 @@ export async function limaStatus(options = {}) {
|
|
|
104
105
|
ready: instance?.status === "Running",
|
|
105
106
|
exists: !!instance,
|
|
106
107
|
message: instance
|
|
107
|
-
?
|
|
108
|
-
:
|
|
108
|
+
? `The humanish Lima host is stopped. Run ${cli("runtime setup")} to start it.`
|
|
109
|
+
: `Run ${cli("runtime setup")} to create the humanish Lima host and install the browser runtime.`,
|
|
109
110
|
};
|
|
110
111
|
}
|
|
111
112
|
export async function prepareLima(options = {}, progress) {
|
|
@@ -7,6 +7,7 @@ import { Readable, Transform } from "node:stream";
|
|
|
7
7
|
import { pipeline } from "node:stream/promises";
|
|
8
8
|
import { LOCAL_MEDIA_RUNTIME_RELEASES, LOCAL_RUNTIME_RELEASES } from "./runtime-release.js";
|
|
9
9
|
import { limaStatus, loadRuntimeArchive, prepareLima, runtimeArchitecture, runtimeDocker, runtimeExec, usesLima, } from "./runtime-host.js";
|
|
10
|
+
import { cli } from "../../cli/invocation.js";
|
|
10
11
|
const docker = async (args, options) => (await runtimeDocker(args, options)).stdout.trim();
|
|
11
12
|
const runtimeRelease = (options) => options.release ??
|
|
12
13
|
(options.media ? LOCAL_MEDIA_RUNTIME_RELEASES : LOCAL_RUNTIME_RELEASES)[runtimeArchitecture(options) ?? "amd64"];
|
|
@@ -80,7 +81,7 @@ export async function localRuntimeStatus(options = {}) {
|
|
|
80
81
|
installed: false,
|
|
81
82
|
message: lima
|
|
82
83
|
? "Docker is unavailable inside the humanish Lima host. Check limactl shell humanish-runtime -- sudo systemctl status docker; Docker Desktop is not used."
|
|
83
|
-
:
|
|
84
|
+
: `Docker is unavailable. Install/start Docker Engine and give your account access, then run ${cli("runtime setup")}.`,
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
87
|
const release = runtimeRelease(options);
|
|
@@ -108,7 +109,7 @@ export async function localRuntimeStatus(options = {}) {
|
|
|
108
109
|
: {
|
|
109
110
|
ok: true,
|
|
110
111
|
installed: false,
|
|
111
|
-
message:
|
|
112
|
+
message: `Local runtime will download before the first live run. Run ${cli("runtime setup")} to prepare it now.`,
|
|
112
113
|
};
|
|
113
114
|
}
|
|
114
115
|
const image = images[0];
|
|
@@ -161,7 +162,7 @@ export async function prepareLocalRuntime(options = {}) {
|
|
|
161
162
|
try {
|
|
162
163
|
const response = await fetch(release.url, { signal });
|
|
163
164
|
if (!response.ok || !response.body)
|
|
164
|
-
throw new Error(`Runtime download failed (HTTP ${response.status}). Run
|
|
165
|
+
throw new Error(`Runtime download failed (HTTP ${response.status}). Run ${cli("runtime setup")} to retry.`);
|
|
165
166
|
let bytes = 0;
|
|
166
167
|
const hash = createHash("sha256");
|
|
167
168
|
await pipeline(Readable.fromWeb(response.body), new Transform({
|
|
@@ -181,7 +182,7 @@ export async function prepareLocalRuntime(options = {}) {
|
|
|
181
182
|
await loadRuntimeArchive(archive, { ...options, signal });
|
|
182
183
|
const after = await localRuntimeStatus(options);
|
|
183
184
|
if (!after.assets)
|
|
184
|
-
throw new Error(
|
|
185
|
+
throw new Error(`Downloaded runtime did not provide the expected image. Run ${cli("runtime setup")} to retry.`);
|
|
185
186
|
return after.assets;
|
|
186
187
|
}
|
|
187
188
|
finally {
|
|
@@ -39,6 +39,8 @@ export declare function runOrThrow(shell: Shell, command: string, options?: Shel
|
|
|
39
39
|
export declare function throwOnExit(result: ShellResult): ShellResult;
|
|
40
40
|
/** Single-quote a value for a Shell command line. */
|
|
41
41
|
export declare function shellQuote(value: string): string;
|
|
42
|
+
/** A command-line argument, single-quoted only when the shell would split or expand it. */
|
|
43
|
+
export declare function shellArg(value: string): string;
|
|
42
44
|
/** Sanitized, whitespace-collapsed, length-capped tail of command output. */
|
|
43
45
|
export declare function tailOf(value: string | undefined): string;
|
|
44
46
|
export {};
|
package/dist/substrates/shell.js
CHANGED
|
@@ -16,6 +16,10 @@ export function throwOnExit(result) {
|
|
|
16
16
|
export function shellQuote(value) {
|
|
17
17
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
18
18
|
}
|
|
19
|
+
/** A command-line argument, single-quoted only when the shell would split or expand it. */
|
|
20
|
+
export function shellArg(value) {
|
|
21
|
+
return /^[\w@%+=:,./-]+$/.test(value) ? value : shellQuote(value);
|
|
22
|
+
}
|
|
19
23
|
/** Sanitized, whitespace-collapsed, length-capped tail of command output. */
|
|
20
24
|
export function tailOf(value) {
|
|
21
25
|
return (value ?? "").trim().replace(/\s+/g, " ").slice(-240);
|
package/dist/tui/contract.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
//
|
|
13
13
|
// It also makes the UI testable without a terminal: a test hands `startTui` a fake index and reads
|
|
14
14
|
// the frames back.
|
|
15
|
+
import { cli } from "../cli/invocation.js";
|
|
15
16
|
/** Node version the Ink runtime requires (ink@7 declares `engines.node >= 22`). */
|
|
16
17
|
export const TUI_MIN_NODE_MAJOR = 22;
|
|
17
18
|
/**
|
|
@@ -41,12 +42,12 @@ export const TUI_BUNDLE_URL = new URL("../tui-app.js", import.meta.url);
|
|
|
41
42
|
*/
|
|
42
43
|
export function terminalSurfaceMessage(state) {
|
|
43
44
|
if (!state.supported) {
|
|
44
|
-
return
|
|
45
|
+
return `\`${cli("tui")}\` needs Node ${TUI_MIN_NODE_MAJOR}+ (this is ${state.nodeVersion}); every other command works here`;
|
|
45
46
|
}
|
|
46
47
|
if (!state.bundlePresent) {
|
|
47
|
-
return "
|
|
48
|
+
return `\`${cli("tui")}\` is not built in this checkout; run \`pnpm build\` (installed packages ship it prebuilt)`;
|
|
48
49
|
}
|
|
49
50
|
return state.interactive
|
|
50
|
-
? "
|
|
51
|
-
: "
|
|
51
|
+
? `\`${cli("tui")}\` opens the interactive surface for browsing studies and runs`
|
|
52
|
+
: `\`${cli("tui")}\` is the interactive screen a person uses to watch and start runs here. This shell is not a terminal, so pass it on to a person at one`;
|
|
52
53
|
}
|