humanish 0.117.0 → 0.119.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 +42 -0
- package/dist/analysis/admission.d.ts +23 -4
- package/dist/analysis/admission.js +47 -9
- package/dist/analysis/analysis-limits.d.ts +32 -0
- package/dist/analysis/analysis-limits.js +41 -3
- package/dist/analysis/automatic-config.d.ts +11 -1
- package/dist/analysis/automatic-config.js +26 -11
- package/dist/analysis/cohorts.d.ts +103 -0
- package/dist/analysis/cohorts.js +80 -0
- package/dist/analysis/evidence.d.ts +5 -10
- package/dist/analysis/evidence.js +37 -34
- package/dist/analysis/execute.d.ts +24 -7
- package/dist/analysis/execute.js +290 -307
- package/dist/analysis/responses.d.ts +19 -0
- package/dist/analysis/responses.js +201 -0
- package/dist/analysis/store.js +2 -1
- package/dist/analysis/validation.js +13 -7
- package/dist/cli/commands/analyze.js +10 -4
- package/dist/cli/commands/study-format.js +8 -11
- package/dist/cli/commands/study-route-shared-world.js +3 -1
- package/dist/cli/commands/study-run.js +1 -1
- package/dist/cli/doctor.js +11 -1
- package/dist/comms/lease-store.d.ts +1 -1
- package/dist/comms/lease-store.js +3 -2
- package/dist/comms/receiving-types.d.ts +2 -0
- package/dist/comms/receiving-types.js +2 -0
- package/dist/observer-app.html +2 -2
- package/dist/routes/computer-use/fanout-bundle.js +4 -2
- package/dist/routes/computer-use/fanout-records.js +6 -1
- package/dist/routes/computer-use/participant-execution.d.ts +6 -4
- package/dist/routes/computer-use/participant-execution.js +42 -14
- package/dist/routes/computer-use/participant-model.js +18 -8
- package/dist/routes/computer-use/participant-runs.js +15 -9
- package/dist/routes/computer-use/plan.d.ts +3 -1
- package/dist/routes/computer-use/plan.js +38 -12
- package/dist/routes/computer-use/rerun-selection.js +14 -3
- package/dist/routes/computer-use/single-bundle.js +7 -4
- package/dist/routes/computer-use/subject-projection.js +2 -0
- package/dist/routes/computer-use/types.d.ts +13 -1
- package/dist/routes/scripted/plan.d.ts +4 -1
- package/dist/routes/scripted/plan.js +25 -2
- package/dist/routes/scripted/setup.js +1 -4
- package/dist/routes/scripted/types.d.ts +1 -1
- package/dist/routes/shared-world/bundle-records.js +14 -0
- package/dist/routes/shared-world/bundle.js +2 -1
- package/dist/routes/shared-world/external-public.js +15 -3
- package/dist/routes/shared-world/handoff.d.ts +2 -2
- package/dist/routes/shared-world/participant-specs.js +2 -2
- package/dist/routes/shared-world/plan.d.ts +10 -1
- package/dist/routes/shared-world/plan.js +86 -10
- package/dist/routes/shared-world/provisioned.js +15 -8
- package/dist/routes/shared-world/route.js +7 -4
- package/dist/routes/shared-world/types.d.ts +2 -0
- package/dist/run/bundle-shape.js +12 -2
- package/dist/run/bundle.d.ts +20 -3
- package/dist/run/participant-records.js +1 -0
- package/dist/run/projection.js +7 -2
- package/dist/run/run.js +4 -2
- package/dist/run/subject-name.d.ts +11 -0
- package/dist/run/subject-name.js +11 -0
- package/dist/study/arrivals.d.ts +114 -0
- package/dist/study/arrivals.js +204 -0
- package/dist/study/composition-rules.js +1 -1
- package/dist/study/config.js +6 -20
- package/dist/study/doctor.js +2 -1
- package/dist/study/keys.d.ts +1 -0
- package/dist/study/keys.js +2 -0
- package/dist/study/migrate/v2.js +3 -2
- package/dist/study/parse/actors.d.ts +2 -2
- package/dist/study/parse/actors.js +10 -4
- package/dist/study/parse/front.d.ts +1 -1
- package/dist/study/parse/front.js +36 -2
- package/dist/study/plan-base.d.ts +1 -1
- package/dist/study/plan-participants.d.ts +2 -0
- package/dist/study/plan-participants.js +3 -5
- package/dist/study/plan-types.d.ts +13 -3
- package/dist/study/plan.d.ts +4 -4
- package/dist/study/plan.js +21 -12
- package/dist/study/preflight.d.ts +2 -1
- package/dist/study/preflight.js +24 -3
- package/dist/study/routing.d.ts +5 -4
- package/dist/study/routing.js +16 -7
- package/dist/study/types.d.ts +14 -0
- package/dist/study/validation.d.ts +2 -2
- package/dist/study/validation.js +27 -14
- package/dist/study/warnings.js +11 -3
- package/dist/substrates/e2b/lifetime.d.ts +75 -4
- package/dist/substrates/e2b/lifetime.js +134 -10
- package/dist/substrates/e2b/subject-sandbox.js +2 -6
- package/dist/tui-app.js +112 -112
- package/dist/verify/artifacts.d.ts +19 -4
- package/dist/verify/artifacts.js +39 -8
- package/dist/verify/verify.js +6 -15
- package/docs/contracts/run-bundle.md +8 -7
- package/docs/contracts/schemas.md +33 -9
- package/docs/contracts/study-analysis.md +61 -8
- package/docs/principles/invariants-and-defaults.md +14 -14
- package/docs/product/automatic-analysis.md +10 -3
- package/package.json +1 -1
|
@@ -8,15 +8,8 @@ import { ACTION_CAPTURE_VERSION, } from "./types.js";
|
|
|
8
8
|
import { digestAnalysisInput, hashAnalysisValue, validateAnalysisInputMetadata, } from "./validation.js";
|
|
9
9
|
import { boundedText, fairShares, hasUnmappedCaptures, participantAssignment, participantSource, sourceEntries, sourceOrder, impressionEventIds, } from "./evidence-sources.js";
|
|
10
10
|
import { readBoundedFile, readBoundedFileResult } from "../run/evidence-files.js";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
evidence: 800,
|
|
14
|
-
captures: 40,
|
|
15
|
-
textBytes: 160 * 1024,
|
|
16
|
-
imageBytes: 8 * 1024 * 1024,
|
|
17
|
-
totalImageBytes: 20 * 1024 * 1024,
|
|
18
|
-
sourceBytes: 16 * 1024 * 1024,
|
|
19
|
-
});
|
|
11
|
+
import { analysisCohortCount, analysisCohorts, EVIDENCE_LIMITS } from "./analysis-limits.js";
|
|
12
|
+
export { EVIDENCE_LIMITS };
|
|
20
13
|
// A second guard for direct callers. The analysis service already requires every stream to be in
|
|
21
14
|
// TERMINAL_SIMULATION_STATUSES; this refuses only statuses that mean still running, so a dry-run
|
|
22
15
|
// bundle's contract_proof_only streams stay capturable. The source is not shape-guarded here, so
|
|
@@ -39,7 +32,7 @@ function parseSource(prepared, bytes) {
|
|
|
39
32
|
value.schema !== "humanish.run-bundle.v1" ||
|
|
40
33
|
value.runId !== runIdOf(prepared) ||
|
|
41
34
|
!Array.isArray(value.streams) ||
|
|
42
|
-
value.streams.length >
|
|
35
|
+
value.streams.length > EVIDENCE_LIMITS.participants ||
|
|
43
36
|
!Array.isArray(value.events) ||
|
|
44
37
|
value.events.length > 100000 ||
|
|
45
38
|
(value.commsReceiving !== undefined && !isCommsReceivingEvidence(value.commsReceiving)))
|
|
@@ -108,7 +101,7 @@ export async function captureEvidence(prepared, bundleBytes, requested = {}) {
|
|
|
108
101
|
const evidence = [];
|
|
109
102
|
const images = [];
|
|
110
103
|
const omissions = new Set();
|
|
111
|
-
|
|
104
|
+
const contextBytes = new Map();
|
|
112
105
|
const participants = selected.map((stream) => {
|
|
113
106
|
const participant = participantSource(stream, captureVersion);
|
|
114
107
|
const assignment = participantAssignment(stream, captureVersion);
|
|
@@ -118,30 +111,38 @@ export async function captureEvidence(prepared, bundleBytes, requested = {}) {
|
|
|
118
111
|
participant.assignment !== assignment ||
|
|
119
112
|
participant.recordedReason !== (stream.actor?.reason ?? null))
|
|
120
113
|
omissions.add("Participant context exceeded the text limit.");
|
|
121
|
-
|
|
114
|
+
contextBytes.set(stream, Buffer.byteLength(JSON.stringify(participant)));
|
|
122
115
|
return participant;
|
|
123
116
|
});
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
117
|
+
// Each cohort is one request's packet, selected under the full limits on its own.
|
|
118
|
+
const packings = [];
|
|
119
|
+
const textByEntry = new Map();
|
|
120
|
+
for (const cohort of analysisCohorts(selected)) {
|
|
121
|
+
const textBytes = cohort.reduce((total, stream) => total + contextBytes.get(stream), 0);
|
|
122
|
+
if (textBytes > limits.textBytes)
|
|
123
|
+
throw new Error("ANALYSIS_PARTICIPANT_CONTEXT_TOO_LARGE");
|
|
124
|
+
// Tie-breaking uses stable participant IDs, not the order of streams in a bundle.
|
|
125
|
+
// The emitted packet still preserves participant and source event order.
|
|
126
|
+
const cohortPackings = cohort
|
|
127
|
+
.map((stream) => ({
|
|
128
|
+
stream,
|
|
129
|
+
entries: sourceEntries(bundle, stream, captureVersion),
|
|
130
|
+
captures: new Map(),
|
|
131
|
+
admitted: new Set(),
|
|
132
|
+
captureCursor: 0,
|
|
133
|
+
attempts: 0,
|
|
134
|
+
readBytes: 0,
|
|
135
|
+
imageBytes: 0,
|
|
136
|
+
reservationBlocked: false,
|
|
137
|
+
}))
|
|
138
|
+
.sort((a, b) => (a.stream.id < b.stream.id ? -1 : a.stream.id > b.stream.id ? 1 : 0));
|
|
139
|
+
const sel = planCaptureSelection(cohortPackings, limits);
|
|
140
|
+
await selectCaptures(prepared, cohortPackings, sel, omissions);
|
|
141
|
+
recordCaptureOmissions(cohortPackings, sel, omissions);
|
|
142
|
+
for (const [entry, text] of boundEvidenceText(cohortPackings, limits.textBytes - textBytes, omissions))
|
|
143
|
+
textByEntry.set(entry, text);
|
|
144
|
+
packings.push(...cohortPackings);
|
|
145
|
+
}
|
|
145
146
|
packEvidence(selected, packings, textByEntry, evidence, images);
|
|
146
147
|
const omittedStreamIds = bundle.streams.slice(limits.participants).map((stream) => stream.id);
|
|
147
148
|
const coverage = {
|
|
@@ -425,6 +426,8 @@ export async function validateAnalysisEvidence(prepared, artifact, bundleBytes)
|
|
|
425
426
|
}
|
|
426
427
|
const sourceKeys = new Set();
|
|
427
428
|
const checkedCaptures = new Map();
|
|
429
|
+
// Each cohort's packet holds at most totalImageBytes.
|
|
430
|
+
const imageByteLimit = analysisCohortCount(included.size) * EVIDENCE_LIMITS.totalImageBytes;
|
|
428
431
|
let checkedImageBytes = 0;
|
|
429
432
|
for (const entry of artifact.evidence) {
|
|
430
433
|
const matches = sourceByStream
|
|
@@ -462,7 +465,7 @@ export async function validateAnalysisEvidence(prepared, artifact, bundleBytes)
|
|
|
462
465
|
if (!bytes || screenshotEvidenceError(source.capturePath, bytes) !== null)
|
|
463
466
|
throw new Error("ANALYSIS_CAPTURE_UNAVAILABLE");
|
|
464
467
|
checkedImageBytes += bytes.length;
|
|
465
|
-
if (checkedImageBytes >
|
|
468
|
+
if (checkedImageBytes > imageByteLimit)
|
|
466
469
|
throw new Error("ANALYSIS_IMAGE_LIMIT_EXCEEDED");
|
|
467
470
|
hash = sha256(bytes);
|
|
468
471
|
checkedCaptures.set(source.capturePath, hash);
|
|
@@ -23,6 +23,9 @@ export interface AnalysisAdmission {
|
|
|
23
23
|
admittedCostUsd: number | null;
|
|
24
24
|
maxCostUsd: number | null;
|
|
25
25
|
ratesAsOf: string | null;
|
|
26
|
+
/** The provider requests the costs cover: one per cohort, and the merge request for more than
|
|
27
|
+
* one cohort. Null when the input or configuration was refused. */
|
|
28
|
+
requests: number | null;
|
|
26
29
|
}
|
|
27
30
|
export interface AnalysisProgress {
|
|
28
31
|
phase: "admitted" | "requesting" | "validating" | "finished";
|
|
@@ -43,14 +46,28 @@ export interface AnalysisProgress {
|
|
|
43
46
|
*/
|
|
44
47
|
export declare function estimateAnalysisAdmission(input: AnalysisInput, config: AnalysisConfig): AnalysisAdmission;
|
|
45
48
|
/**
|
|
46
|
-
* The expected cost of
|
|
47
|
-
* packet with no evidence to
|
|
48
|
-
*
|
|
49
|
+
* The expected cost of the analysis admission would start, before any evidence exists: from a
|
|
50
|
+
* packet with no evidence to the largest packet admission admits. When admission refuses even a
|
|
51
|
+
* packet with no evidence, `refusedFromUsd` is that packet's expected cost.
|
|
49
52
|
*/
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
export type AnalysisCostRange = {
|
|
54
|
+
expectedCostUsd: {
|
|
55
|
+
low: number;
|
|
56
|
+
high: number;
|
|
57
|
+
};
|
|
58
|
+
} | {
|
|
59
|
+
refusedFromUsd: number;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* The expected cost of the analysis admission would start for this many participants, before any
|
|
63
|
+
* evidence exists. Packets grow from no evidence toward the evidence limits with every capture at
|
|
64
|
+
* the image-token ceiling, and the range ends at the largest one admission admits, so it never
|
|
65
|
+
* passes the cap. There is one packet per cohort, each a share of its own limits, and the merge
|
|
66
|
+
* request when there is more than one cohort. With `preferLargerOutput` each request gets the
|
|
67
|
+
* output allowance dispatch would give it (preferLargerAnalysisOutput). Undefined for Codex and
|
|
68
|
+
* for a model without rates.
|
|
69
|
+
*/
|
|
70
|
+
export declare function analysisCostRange(config: AnalysisConfig, participants: number, preferLargerOutput?: boolean): AnalysisCostRange | undefined;
|
|
54
71
|
/** Only for an omitted output limit. Preserve the established allowance when
|
|
55
72
|
* more reasoning/report space would refuse a study its declared budget admits.
|
|
56
73
|
* This is one pre-dispatch choice, never a fallback request or a budget increase. */
|