humanish 0.50.0 → 0.51.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/dist/cua-actor-lab.js +18 -1
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/lab-summary.d.ts +36 -0
- package/dist/lab-summary.js +86 -0
- package/dist/lab-summary.js.map +1 -0
- package/dist/program.js +5 -1
- package/dist/program.js.map +1 -1
- package/dist/tui-app.js +128 -128
- package/dist/tui-contract.d.ts +11 -0
- package/dist/tui-contract.js.map +1 -1
- package/dist/tui-project.d.ts +9 -0
- package/dist/tui-project.js +18 -0
- package/dist/tui-project.js.map +1 -0
- package/docs/contracts/schemas.md +1 -1
- package/docs/goals/current.md +2 -2
- package/docs/ramp/README.md +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare const LAB_SUMMARY_SCHEMA = "humanish.lab-summary.v1";
|
|
2
|
+
export interface LabCaps {
|
|
3
|
+
/** Per-lane blast-radius budget. */
|
|
4
|
+
laneUsd?: number;
|
|
5
|
+
/** Shared study budget across every lane. */
|
|
6
|
+
studyUsd?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface LabSummary {
|
|
9
|
+
schema: typeof LAB_SUMMARY_SCHEMA;
|
|
10
|
+
labId: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
/** "clone drawdb-io/drawdb", "app-url http://127.0.0.1:3000/", "this-repo". */
|
|
14
|
+
subject?: string;
|
|
15
|
+
/** How many participants and who they are: `1 × synthetic-new-user`. */
|
|
16
|
+
participants?: string;
|
|
17
|
+
/** The model that will actually run, override or default. */
|
|
18
|
+
model?: string;
|
|
19
|
+
caps: LabCaps;
|
|
20
|
+
/**
|
|
21
|
+
* Whether every key a LIVE run of this lab needs is resolvable right now. `undefined` when not
|
|
22
|
+
* checked. Names only — a value never leaves the key layer.
|
|
23
|
+
*/
|
|
24
|
+
keysReady?: boolean;
|
|
25
|
+
missingKeys?: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface ReadLabSummaryOptions {
|
|
28
|
+
/** Skip the key probe (it touches vendor stores); the screen then shows no keys line. */
|
|
29
|
+
checkKeys?: boolean;
|
|
30
|
+
env?: NodeJS.ProcessEnv;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Describe one lab. Returns null when the manifest cannot be resolved — the caller already knows
|
|
34
|
+
* the lab exists from the listing, so this failing means the file changed underneath them.
|
|
35
|
+
*/
|
|
36
|
+
export declare function readLabSummary(cwd: string, lab: string, options?: ReadLabSummaryOptions): Promise<LabSummary | null>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// What a lab IS, for the surface that has to describe it before you spend money (#455).
|
|
2
|
+
//
|
|
3
|
+
// The run index and run detail answer questions about runs. This answers a question about the LAB
|
|
4
|
+
// itself — what it drives, who is in it, which model, and what it is allowed to spend — which is
|
|
5
|
+
// what a stakeholder reads on the screen where they decide whether to press Start.
|
|
6
|
+
//
|
|
7
|
+
// Every field is optional and omitted when the manifest does not declare it. A cap that is not
|
|
8
|
+
// declared is not "unlimited" and not "$0"; it is a line the screen does not draw.
|
|
9
|
+
import { DEFAULT_OPENAI_CU_MODEL } from "./openai-responses-cu.js";
|
|
10
|
+
import { inspectLabManifest } from "./labs.js";
|
|
11
|
+
import { probeKeySources } from "./key-resolution.js";
|
|
12
|
+
export const LAB_SUMMARY_SCHEMA = "humanish.lab-summary.v1";
|
|
13
|
+
/** One short phrase for what the lab drives. */
|
|
14
|
+
function subjectOf(config) {
|
|
15
|
+
const subject = config.subject;
|
|
16
|
+
if (subject?.source === undefined)
|
|
17
|
+
return undefined;
|
|
18
|
+
const repo = subject.repos?.[0];
|
|
19
|
+
if (repo !== undefined)
|
|
20
|
+
return `${subject.source} ${repo}`;
|
|
21
|
+
if (subject.appUrl !== undefined)
|
|
22
|
+
return `${subject.source} ${subject.appUrl}`;
|
|
23
|
+
return subject.source;
|
|
24
|
+
}
|
|
25
|
+
/** How many participants, and who — collapsed when they are all the same persona. */
|
|
26
|
+
function participantsOf(config) {
|
|
27
|
+
const actors = config.actors;
|
|
28
|
+
const actor = actors?.[0];
|
|
29
|
+
if (actor === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
const lanePersonas = (actor.lanes ?? []).map((lane) => lane.persona).filter((persona) => typeof persona === "string");
|
|
32
|
+
const personas = lanePersonas.length > 0 ? lanePersonas : actor.persona === undefined ? [] : [actor.persona];
|
|
33
|
+
const count = actor.count ?? actor.lanes?.length ?? personas.length ?? 1;
|
|
34
|
+
const unique = [...new Set(personas)];
|
|
35
|
+
if (unique.length === 0)
|
|
36
|
+
return `${count} participant${count === 1 ? "" : "s"}`;
|
|
37
|
+
// Several lanes of ONE persona reads as "3 × skeptical-power-user"; genuinely different people
|
|
38
|
+
// are named, because which personas are in a study is the study's design.
|
|
39
|
+
return unique.length === 1 ? `${count} × ${unique[0]}` : unique.join(" · ");
|
|
40
|
+
}
|
|
41
|
+
function capsOf(config) {
|
|
42
|
+
const caps = config.policies?.caps
|
|
43
|
+
?? config.caps;
|
|
44
|
+
return {
|
|
45
|
+
...(typeof caps?.maxUsd === "number" ? { laneUsd: caps.maxUsd } : {}),
|
|
46
|
+
...(typeof caps?.maxTotalUsd === "number" ? { studyUsd: caps.maxTotalUsd } : {})
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Describe one lab. Returns null when the manifest cannot be resolved — the caller already knows
|
|
51
|
+
* the lab exists from the listing, so this failing means the file changed underneath them.
|
|
52
|
+
*/
|
|
53
|
+
export async function readLabSummary(cwd, lab, options = {}) {
|
|
54
|
+
const inspected = await inspectLabManifest(cwd, lab).catch(() => null);
|
|
55
|
+
if (inspected === null || !inspected.ok || inspected.config === undefined)
|
|
56
|
+
return null;
|
|
57
|
+
const config = inspected.config;
|
|
58
|
+
const actors = config.actors;
|
|
59
|
+
let keysReady;
|
|
60
|
+
let missingKeys;
|
|
61
|
+
if (options.checkKeys === true) {
|
|
62
|
+
// Only the keys a live run of THIS lab would need. Names only; no value is read or returned.
|
|
63
|
+
const needed = ["OPENAI_API_KEY", "E2B_API_KEY"];
|
|
64
|
+
const probes = await probeKeySources(needed, { cwd, env: options.env ?? process.env }).catch(() => []);
|
|
65
|
+
const missing = probes.filter((probe) => probe.source === null).map((probe) => probe.name);
|
|
66
|
+
keysReady = probes.length > 0 && missing.length === 0;
|
|
67
|
+
if (missing.length > 0)
|
|
68
|
+
missingKeys = missing;
|
|
69
|
+
}
|
|
70
|
+
// Computed once: a test-then-use pair reads as though the two calls could differ.
|
|
71
|
+
const subject = subjectOf(config);
|
|
72
|
+
const participants = participantsOf(config);
|
|
73
|
+
return {
|
|
74
|
+
schema: LAB_SUMMARY_SCHEMA,
|
|
75
|
+
labId: String(config.id ?? lab),
|
|
76
|
+
...(typeof config.title === "string" ? { title: config.title } : {}),
|
|
77
|
+
...(typeof config.description === "string" ? { description: config.description.trim() } : {}),
|
|
78
|
+
...(subject === undefined ? {} : { subject }),
|
|
79
|
+
...(participants === undefined ? {} : { participants }),
|
|
80
|
+
model: actors?.[0]?.model ?? DEFAULT_OPENAI_CU_MODEL,
|
|
81
|
+
caps: capsOf(config),
|
|
82
|
+
...(keysReady === undefined ? {} : { keysReady }),
|
|
83
|
+
...(missingKeys === undefined ? {} : { missingKeys })
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=lab-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lab-summary.js","sourceRoot":"","sources":["../src/lab-summary.ts"],"names":[],"mappings":"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"}
|
package/dist/program.js
CHANGED
|
@@ -25,6 +25,8 @@ import { cleanupOssMetaLabSandboxes, cleanupStaleOssMetaLabSandboxes, runOssMeta
|
|
|
25
25
|
import { cleanupRun, doctor, listRuns, readReview, runDryRun, verifyRun } from "./run.js";
|
|
26
26
|
import { reclaimRunSandboxes } from "./reclaim.js";
|
|
27
27
|
import { RunIndexCache, readRunIndex } from "./run-index.js";
|
|
28
|
+
import { readLabSummary } from "./lab-summary.js";
|
|
29
|
+
import { readProjectState } from "./tui-project.js";
|
|
28
30
|
import { readRunDetail } from "./run-detail.js";
|
|
29
31
|
import { launchRun, readLaunchLogTail } from "./tui-launch.js";
|
|
30
32
|
import { TUI_MIN_NODE_MAJOR, nodeSupportsTui, tuiBundleUrl } from "./tui-contract.js";
|
|
@@ -331,7 +333,9 @@ function registerTuiCommand(parent, io) {
|
|
|
331
333
|
listLabs: listLabManifests,
|
|
332
334
|
startRun: launchRun,
|
|
333
335
|
readLaunchLog: readLaunchLogTail,
|
|
334
|
-
readRunDetail
|
|
336
|
+
readRunDetail,
|
|
337
|
+
readLabSummary,
|
|
338
|
+
readProjectState
|
|
335
339
|
},
|
|
336
340
|
stdin,
|
|
337
341
|
stdout
|