humanish 0.111.4 → 0.113.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/README.md +11 -0
- package/TELEMETRY.md +21 -0
- package/dist/actors/codex/restricted-participant-policy.d.ts +21 -1
- package/dist/actors/codex/restricted-participant-policy.js +20 -2
- package/dist/actors/codex/restricted-participant.d.ts +1 -1
- package/dist/actors/codex/restricted-participant.js +2 -1
- package/dist/actors/computer-use/loop/debrief.d.ts +12 -4
- package/dist/actors/computer-use/loop/debrief.js +57 -20
- package/dist/actors/computer-use/loop/ending.d.ts +5 -2
- package/dist/actors/computer-use/loop/impressions.d.ts +14 -0
- package/dist/actors/computer-use/loop/impressions.js +40 -0
- package/dist/actors/computer-use/loop/session.d.ts +3 -1
- package/dist/actors/computer-use/loop/session.js +2 -0
- package/dist/actors/computer-use/loop/trace.js +2 -0
- package/dist/actors/computer-use/loop/types.d.ts +8 -1
- package/dist/actors/computer-use/loop.d.ts +2 -1
- package/dist/actors/computer-use/loop.js +15 -3
- package/dist/actors/computer-use/openai-conversation.d.ts +96 -0
- package/dist/actors/computer-use/openai-conversation.js +238 -0
- package/dist/actors/computer-use/openai-provider.js +38 -48
- package/dist/actors/contract.d.ts +45 -3
- package/dist/actors/contract.js +13 -0
- package/dist/analysis/diagnostics.js +7 -12
- package/dist/analysis/evidence-sources.d.ts +3 -1
- package/dist/analysis/evidence-sources.js +10 -1
- package/dist/analysis/evidence.js +2 -2
- package/dist/analysis/execute.d.ts +1 -1
- package/dist/analysis/execute.js +37 -5
- package/dist/analysis/service.js +7 -1
- package/dist/analysis/types.d.ts +23 -0
- package/dist/analysis/validation.d.ts +80 -35
- package/dist/analysis/validation.js +58 -11
- package/dist/cli/commands/runs.js +37 -20
- package/dist/cli/commands/setup.js +95 -6
- package/dist/cli/commands/study-format.js +7 -4
- package/dist/cli/commands/study.js +1 -1
- package/dist/cli/commands/tui.js +1 -1
- package/dist/cli/doctor.d.ts +2 -0
- package/dist/cli/doctor.js +18 -0
- package/dist/cli/findings.d.ts +34 -3
- package/dist/cli/findings.js +136 -18
- package/dist/cli/io.d.ts +4 -1
- package/dist/cli/io.js +3 -2
- package/dist/cli/program.js +35 -1
- package/dist/cli/secret-prompt.d.ts +5 -1
- package/dist/cli/secret-prompt.js +6 -2
- package/dist/cli/update-check-worker.d.ts +1 -0
- package/dist/cli/update-check-worker.js +5 -0
- package/dist/cli/update-check.d.ts +46 -0
- package/dist/cli/update-check.js +203 -0
- package/dist/feedback/draft.js +32 -4
- package/dist/keys/key-resolution.js +2 -0
- package/dist/keys/key-status.d.ts +37 -0
- package/dist/keys/key-status.js +68 -0
- package/dist/observer/run-routes.js +8 -4
- package/dist/observer-app.html +4 -4
- package/dist/routes/computer-use/bundle.d.ts +1 -1
- package/dist/routes/computer-use/bundle.js +6 -16
- package/dist/routes/computer-use/fanout-bundle.js +40 -37
- package/dist/routes/computer-use/fanout-records.d.ts +2 -0
- package/dist/routes/computer-use/fanout-records.js +18 -26
- package/dist/routes/computer-use/local-vm.js +9 -2
- package/dist/routes/computer-use/participant-desktop.d.ts +6 -0
- package/dist/routes/computer-use/participant-execution.js +13 -12
- package/dist/routes/computer-use/participant-facts.d.ts +2 -2
- package/dist/routes/computer-use/participant-facts.js +10 -1
- package/dist/routes/computer-use/rerun-selection.js +23 -21
- package/dist/routes/computer-use/result.js +10 -17
- package/dist/routes/computer-use/self-report.js +7 -1
- package/dist/routes/computer-use/setup.js +14 -0
- package/dist/routes/computer-use/single-bundle.d.ts +2 -0
- package/dist/routes/computer-use/single-bundle.js +81 -37
- package/dist/routes/computer-use/types.d.ts +4 -1
- package/dist/routes/scripted/bundle.d.ts +1 -1
- package/dist/routes/scripted/bundle.js +9 -19
- package/dist/routes/scripted/surface-records.d.ts +0 -1
- package/dist/routes/scripted/surface-records.js +27 -13
- package/dist/routes/shared-world/bundle-records.d.ts +2 -2
- package/dist/routes/shared-world/bundle-records.js +24 -30
- package/dist/routes/shared-world/bundle.d.ts +1 -1
- package/dist/routes/shared-world/bundle.js +71 -79
- package/dist/routes/shared-world/participant-specs.d.ts +1 -2
- package/dist/routes/shared-world/participant-specs.js +0 -8
- package/dist/routes/shared-world/result.js +8 -12
- package/dist/routes/terminal/bundle.d.ts +1 -1
- package/dist/routes/terminal/bundle.js +10 -19
- package/dist/routes/terminal/dry-run.js +1 -0
- package/dist/routes/terminal/live-sandbox.js +9 -2
- package/dist/routes/terminal/plan.js +1 -0
- package/dist/routes/terminal/runtime.d.ts +1 -0
- package/dist/routes/terminal/runtime.js +1 -0
- package/dist/routes/terminal/session.js +1 -0
- package/dist/run/costs.js +9 -20
- package/dist/run/detail.d.ts +1 -1
- package/dist/run/detail.js +13 -4
- package/dist/run/display.d.ts +2 -2
- package/dist/run/display.js +15 -18
- package/dist/run/dry-run.js +10 -25
- package/dist/run/judge.d.ts +24 -0
- package/dist/run/judge.js +54 -0
- package/dist/run/liveness.d.ts +18 -0
- package/dist/run/liveness.js +24 -0
- package/dist/run/outcomes.d.ts +8 -1
- package/dist/run/outcomes.js +58 -12
- package/dist/run/participant-caption.d.ts +31 -0
- package/dist/run/participant-caption.js +60 -0
- package/dist/run/participant-records.d.ts +4 -2
- package/dist/run/participant-records.js +6 -0
- package/dist/run/review-markdown.d.ts +11 -0
- package/dist/run/review-markdown.js +22 -0
- package/dist/run/run-cost.d.ts +7 -0
- package/dist/run/run-cost.js +25 -5
- package/dist/run/run-index.d.ts +4 -50
- package/dist/run/run-index.js +57 -87
- package/dist/run/run.d.ts +2 -2
- package/dist/run/run.js +5 -3
- package/dist/run/stats.js +2 -12
- package/dist/run/transient-comms-secrets.d.ts +8 -3
- package/dist/run/transient-comms-secrets.js +21 -1
- package/dist/run-study.js +17 -1
- package/dist/study/discover.js +6 -1
- package/dist/study/doctor.d.ts +2 -0
- package/dist/study/doctor.js +45 -7
- package/dist/study/init-templates.js +10 -5
- package/dist/study/keys.d.ts +1 -0
- package/dist/study/keys.js +1 -1
- package/dist/study/parse/execution.js +7 -1
- package/dist/study/plan-types.d.ts +1 -0
- package/dist/study/plan.js +3 -2
- package/dist/study/preflight-result.d.ts +1 -0
- package/dist/study/preflight-result.js +1 -1
- package/dist/study/preflight.d.ts +2 -0
- package/dist/study/preflight.js +54 -14
- package/dist/study/types.d.ts +4 -1
- package/dist/study/warnings.d.ts +7 -1
- package/dist/study/warnings.js +82 -4
- package/dist/substrates/local/capacity.d.ts +75 -0
- package/dist/substrates/local/capacity.js +143 -0
- package/dist/substrates/local/firecracker-desktop.d.ts +8 -0
- package/dist/substrates/local/firecracker-desktop.js +34 -3
- package/dist/substrates/local/runtime-host.d.ts +16 -3
- package/dist/substrates/local/runtime-host.js +49 -4
- package/dist/substrates/local/runtime.d.ts +10 -0
- package/dist/substrates/local/runtime.js +44 -5
- package/dist/tui-app.js +75 -75
- package/dist/verify/liveness.d.ts +2 -2
- package/dist/verify/liveness.js +7 -4
- package/docs/architecture/actor-contract.md +20 -6
- package/docs/architecture/terminal-product-route.md +14 -0
- package/docs/contracts/feedback.md +8 -1
- package/docs/contracts/run-bundle.md +10 -0
- package/docs/contracts/schemas.md +65 -34
- package/docs/contracts/study-analysis.md +86 -22
- package/package.json +2 -1
- package/skills/humanish/SKILL.md +21 -10
- package/dist/actors/computer-use/openai-requests.d.ts +0 -62
- package/dist/actors/computer-use/openai-requests.js +0 -144
|
@@ -4,6 +4,8 @@ import { tmpdir } from "node:os";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { promisify } from "node:util";
|
|
6
6
|
import { cli } from "../../cli/invocation.js";
|
|
7
|
+
import { defaultVmSize, machineSize, vmSizeProblem, } from "./capacity.js";
|
|
8
|
+
import { plural } from "../../run/text.js";
|
|
7
9
|
const exec = promisify(execFile);
|
|
8
10
|
export const LIMA_INSTANCE = "humanish-runtime";
|
|
9
11
|
export const usesLima = (options = {}) => (options.platform ?? process.platform) === "darwin";
|
|
@@ -44,12 +46,12 @@ export async function runtimeDocker(args, options = {}, timeout = 15_000) {
|
|
|
44
46
|
}
|
|
45
47
|
// No host mounts, agent forwarding or automatic app-port discovery. Per-study
|
|
46
48
|
// OpenSSH forwards grant just the selected app and browser-control sockets.
|
|
47
|
-
const
|
|
49
|
+
const limaTemplate = (size) => `minimumLimaVersion: 2.2.0
|
|
48
50
|
vmType: vz
|
|
49
51
|
arch: aarch64
|
|
50
52
|
nestedVirtualization: true
|
|
51
|
-
cpus:
|
|
52
|
-
memory:
|
|
53
|
+
cpus: ${size.cpus}
|
|
54
|
+
memory: ${size.memoryGiB}GiB
|
|
53
55
|
disk: 80GiB
|
|
54
56
|
images:
|
|
55
57
|
- location: https://cloud.debian.org/images/cloud/trixie/20260712-2537/debian-13-genericcloud-arm64-20260712-2537.qcow2
|
|
@@ -101,16 +103,44 @@ export async function limaStatus(options = {}) {
|
|
|
101
103
|
if (instance &&
|
|
102
104
|
(instance.name !== LIMA_INSTANCE || instance.vmType !== "vz" || instance.arch !== "aarch64"))
|
|
103
105
|
throw new Error(`The existing ${LIMA_INSTANCE} Lima instance is incompatible. humanish will not replace it.`);
|
|
106
|
+
// `limactl list --json` reports the instance's configured memory in bytes.
|
|
107
|
+
const size = Number.isInteger(instance?.cpus) && Number.isFinite(instance?.memory)
|
|
108
|
+
? { cpus: instance.cpus, memoryBytes: instance.memory }
|
|
109
|
+
: undefined;
|
|
104
110
|
return {
|
|
105
111
|
ready: instance?.status === "Running",
|
|
106
112
|
exists: !!instance,
|
|
113
|
+
...(size === undefined ? {} : { size }),
|
|
107
114
|
message: instance
|
|
108
115
|
? `The humanish Lima host is stopped. Run ${cli("runtime setup")} to start it.`
|
|
109
116
|
: `Run ${cli("runtime setup")} to create the humanish Lima host and install the browser runtime.`,
|
|
110
117
|
};
|
|
111
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Start the humanish Lima VM, creating it at `size` (or the default size) when it does not exist.
|
|
121
|
+
* An existing VM keeps its size unless `size` differs, in which case it is stopped, resized and
|
|
122
|
+
* started again.
|
|
123
|
+
*/
|
|
112
124
|
export async function prepareLima(options = {}, progress) {
|
|
113
125
|
const status = await limaStatus(options);
|
|
126
|
+
const mac = machineSize(options.machine);
|
|
127
|
+
const current = status.size === undefined
|
|
128
|
+
? defaultVmSize(mac)
|
|
129
|
+
: { memoryGiB: status.size.memoryBytes / 1024 ** 3, cpus: status.size.cpus };
|
|
130
|
+
const size = { ...current, ...options.size };
|
|
131
|
+
if (options.size !== undefined) {
|
|
132
|
+
const problem = vmSizeProblem(size, mac);
|
|
133
|
+
if (problem !== undefined)
|
|
134
|
+
throw new Error(problem);
|
|
135
|
+
}
|
|
136
|
+
// An existing VM whose size Lima did not list gets the asked-for size without a comparison.
|
|
137
|
+
const differs = status.size === undefined
|
|
138
|
+
? options.size !== undefined
|
|
139
|
+
: size.cpus !== current.cpus || size.memoryGiB !== current.memoryGiB;
|
|
140
|
+
if (status.exists && differs) {
|
|
141
|
+
await resizeLima(size, status.ready, options, progress);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
114
144
|
if (status.ready)
|
|
115
145
|
return;
|
|
116
146
|
progress?.(status.exists
|
|
@@ -123,7 +153,7 @@ export async function prepareLima(options = {}, progress) {
|
|
|
123
153
|
const work = await mkdtemp(path.join(tmpdir(), "humanish-lima-"));
|
|
124
154
|
try {
|
|
125
155
|
const file = path.join(work, "host.yaml");
|
|
126
|
-
await writeFile(file,
|
|
156
|
+
await writeFile(file, limaTemplate(size), { mode: 0o600 });
|
|
127
157
|
await hostExec("limactl", ["start", "--tty=false", "--name", LIMA_INSTANCE, file], options, 15 * 60_000);
|
|
128
158
|
}
|
|
129
159
|
finally {
|
|
@@ -131,6 +161,21 @@ export async function prepareLima(options = {}, progress) {
|
|
|
131
161
|
}
|
|
132
162
|
}
|
|
133
163
|
}
|
|
164
|
+
/** Lima changes the memory and CPUs of a stopped instance only. Running desktops keep it running. */
|
|
165
|
+
async function resizeLima(size, running, options, progress) {
|
|
166
|
+
if (running) {
|
|
167
|
+
const desktops = (await runtimeDocker(["ps", "--quiet", "--filter", "label=to.humanish.runtime.api=1"], options)).stdout
|
|
168
|
+
.split("\n")
|
|
169
|
+
.filter((line) => line.trim() !== "");
|
|
170
|
+
if (desktops.length > 0)
|
|
171
|
+
throw new Error(`${plural(desktops.length, "participant desktop")} ${desktops.length === 1 ? "is" : "are"} running in the humanish Lima VM, so it was not resized. Wait for the study to finish, then run ${cli(`runtime setup --memory ${size.memoryGiB} --cpus ${size.cpus}`)} again.`);
|
|
172
|
+
progress?.("Stopping the humanish Lima VM to resize it…");
|
|
173
|
+
await hostExec("limactl", ["stop", LIMA_INSTANCE], options, 5 * 60_000);
|
|
174
|
+
}
|
|
175
|
+
progress?.(`Resizing the humanish Lima VM to ${size.memoryGiB} GiB and ${size.cpus} CPUs…`);
|
|
176
|
+
await hostExec("limactl", ["edit", "--cpus", String(size.cpus), "--memory", String(size.memoryGiB), LIMA_INSTANCE], options);
|
|
177
|
+
await hostExec("limactl", ["start", "--tty=false", LIMA_INSTANCE], options, 15 * 60_000);
|
|
178
|
+
}
|
|
134
179
|
/** Copy across the OS boundary explicitly; shared folders cannot carry sockets. */
|
|
135
180
|
export async function loadRuntimeArchive(archive, options) {
|
|
136
181
|
if (!usesLima(options)) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { LocalFirecrackerAssets } from "./firecracker-desktop.js";
|
|
2
|
+
import { type LocalCapacity, type VmSize } from "./capacity.js";
|
|
2
3
|
import { type RuntimeHostOptions } from "./runtime-host.js";
|
|
3
4
|
export interface LocalRuntimeRelease {
|
|
4
5
|
url: string;
|
|
@@ -11,13 +12,22 @@ export interface LocalRuntimeStatus {
|
|
|
11
12
|
installed: boolean;
|
|
12
13
|
message: string;
|
|
13
14
|
assets?: LocalFirecrackerAssets;
|
|
15
|
+
/** How many desktops fit, when the VM or this machine could be read. */
|
|
16
|
+
capacity?: LocalCapacity;
|
|
14
17
|
}
|
|
15
18
|
interface RuntimeOptions extends RuntimeHostOptions {
|
|
16
19
|
media?: boolean;
|
|
20
|
+
/** The Lima VM size `runtime setup --memory --cpus` asks for. Macs only. */
|
|
21
|
+
size?: Partial<VmSize>;
|
|
17
22
|
progress?: (message: string) => void;
|
|
18
23
|
/** Explicit source-build/test override; never provided by a participant. */
|
|
19
24
|
release?: LocalRuntimeRelease;
|
|
20
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* How many desktops the local runtime holds, read without starting anything. Undefined when the
|
|
28
|
+
* host cannot be read, such as a Mac without Lima: preparing the runtime reports that.
|
|
29
|
+
*/
|
|
30
|
+
export declare function localRuntimeCapacity(options?: RuntimeHostOptions): Promise<LocalCapacity | undefined>;
|
|
21
31
|
/** Read-only host and cache inspection. Never pulls an image or starts a container. */
|
|
22
32
|
export declare function localRuntimeStatus(options?: RuntimeOptions): Promise<LocalRuntimeStatus>;
|
|
23
33
|
/** Docker owns the installed image/cache. The archive is verified before docker load. */
|
|
@@ -6,30 +6,67 @@ import path from "node:path";
|
|
|
6
6
|
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
|
+
import { defaultVmSize, localCapacity, machineSize, } from "./capacity.js";
|
|
9
10
|
import { limaStatus, loadRuntimeArchive, prepareLima, runtimeArchitecture, runtimeDocker, runtimeExec, usesLima, } from "./runtime-host.js";
|
|
10
11
|
import { cli } from "../../cli/invocation.js";
|
|
11
12
|
const docker = async (args, options) => (await runtimeDocker(args, options)).stdout.trim();
|
|
12
13
|
const runtimeRelease = (options) => options.release ??
|
|
13
14
|
(options.media ? LOCAL_MEDIA_RUNTIME_RELEASES : LOCAL_RUNTIME_RELEASES)[runtimeArchitecture(options) ?? "amd64"];
|
|
15
|
+
/** Desktops the existing Lima VM holds, the VM setup would create, or this Linux machine. */
|
|
16
|
+
function runtimeCapacity(options, lima) {
|
|
17
|
+
if (lima === undefined)
|
|
18
|
+
return localCapacity("linux-host", machineSize(options.machine));
|
|
19
|
+
const machine = machineSize(options.machine);
|
|
20
|
+
if (lima.size !== undefined)
|
|
21
|
+
return localCapacity("lima-vm", lima.size, { machine });
|
|
22
|
+
// An existing VM whose size Lima did not list has an unknown size, which no default replaces.
|
|
23
|
+
if (lima.exists)
|
|
24
|
+
return undefined;
|
|
25
|
+
const planned = defaultVmSize(machine);
|
|
26
|
+
return localCapacity("lima-vm", { memoryBytes: planned.memoryGiB * 1024 ** 3, cpus: planned.cpus }, { planned: true, machine });
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* How many desktops the local runtime holds, read without starting anything. Undefined when the
|
|
30
|
+
* host cannot be read, such as a Mac without Lima: preparing the runtime reports that.
|
|
31
|
+
*/
|
|
32
|
+
export async function localRuntimeCapacity(options = {}) {
|
|
33
|
+
if (runtimeArchitecture(options) === undefined)
|
|
34
|
+
return undefined;
|
|
35
|
+
if (!usesLima(options))
|
|
36
|
+
return runtimeCapacity(options, undefined);
|
|
37
|
+
try {
|
|
38
|
+
return runtimeCapacity(options, await limaStatus(options));
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
14
44
|
/** Read-only host and cache inspection. Never pulls an image or starts a container. */
|
|
15
45
|
export async function localRuntimeStatus(options = {}) {
|
|
16
|
-
const architecture = runtimeArchitecture(options)
|
|
46
|
+
const architecture = runtimeArchitecture(options);
|
|
17
47
|
if (!architecture)
|
|
18
48
|
return {
|
|
19
49
|
ok: false,
|
|
20
50
|
installed: false,
|
|
21
51
|
message: "Local browsers need Linux x64 or an M3-or-newer Mac with Lima.",
|
|
22
52
|
};
|
|
23
|
-
|
|
53
|
+
let lima;
|
|
54
|
+
if (usesLima(options)) {
|
|
24
55
|
try {
|
|
25
|
-
|
|
26
|
-
if (!status.ready)
|
|
27
|
-
return { ok: true, installed: false, message: status.message };
|
|
56
|
+
lima = await limaStatus(options);
|
|
28
57
|
}
|
|
29
58
|
catch (error) {
|
|
30
59
|
return { ok: false, installed: false, message: error.message };
|
|
31
60
|
}
|
|
32
61
|
}
|
|
62
|
+
const capacity = runtimeCapacity(options, lima);
|
|
63
|
+
const sized = capacity === undefined ? {} : { capacity };
|
|
64
|
+
if (lima !== undefined && !lima.ready)
|
|
65
|
+
return { ok: true, installed: false, message: lima.message, ...sized };
|
|
66
|
+
return { ...(await engineStatus(options, architecture, lima !== undefined)), ...sized };
|
|
67
|
+
}
|
|
68
|
+
/** The Docker engine, devices and cached image the desktops run on. */
|
|
69
|
+
async function engineStatus(options, architecture, lima) {
|
|
33
70
|
const env = options.env ?? process.env;
|
|
34
71
|
if (!lima && env.DOCKER_HOST && !env.DOCKER_HOST.startsWith("unix://")) {
|
|
35
72
|
return {
|
|
@@ -142,6 +179,8 @@ export async function localRuntimeStatus(options = {}) {
|
|
|
142
179
|
export async function prepareLocalRuntime(options = {}) {
|
|
143
180
|
if (!runtimeArchitecture(options))
|
|
144
181
|
throw new Error((await localRuntimeStatus(options)).message);
|
|
182
|
+
if (options.size !== undefined && !usesLima(options))
|
|
183
|
+
throw new Error("--memory and --cpus size the humanish Lima VM, which runs only on a Mac. On Linux, desktops use this machine's memory and CPUs directly.");
|
|
145
184
|
if (usesLima(options))
|
|
146
185
|
await prepareLima(options, options.progress);
|
|
147
186
|
const before = await localRuntimeStatus(options);
|