humanish 0.114.0 → 0.116.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 +41 -0
- package/CONTEXT.md +1 -1
- package/README.md +7 -6
- package/TELEMETRY.md +6 -0
- package/dist/actors/closing-report-limits.d.ts +11 -0
- package/dist/actors/closing-report-limits.js +13 -0
- package/dist/actors/closing-report.d.ts +68 -0
- package/dist/actors/closing-report.js +55 -0
- package/dist/actors/codex/app-server-ui.js +11 -4
- package/dist/actors/codex/restricted-participant-policy.d.ts +4 -47
- package/dist/actors/codex/restricted-participant-policy.js +12 -40
- package/dist/actors/computer-use/loop/debrief.d.ts +1 -10
- package/dist/actors/computer-use/loop/debrief.js +68 -70
- package/dist/actors/computer-use/loop/impressions.d.ts +2 -2
- package/dist/actors/computer-use/loop/impressions.js +6 -1
- package/dist/actors/computer-use/loop.d.ts +0 -1
- package/dist/actors/computer-use/loop.js +3 -3
- package/dist/actors/computer-use/openai-conversation.d.ts +1 -1
- package/dist/actors/computer-use/openai-conversation.js +3 -29
- package/dist/actors/computer-use/openai-provider.js +11 -5
- package/dist/actors/contract.d.ts +2 -20
- package/dist/actors/contract.js +0 -13
- package/dist/actors/scripted-browser/steps.js +6 -5
- package/dist/analysis/admission.d.ts +14 -4
- package/dist/analysis/admission.js +14 -9
- package/dist/analysis/analysis-limits.d.ts +35 -0
- package/dist/analysis/analysis-limits.js +41 -0
- package/dist/analysis/execute.d.ts +5 -0
- package/dist/analysis/execute.js +3 -0
- package/dist/analysis/finding-lead.d.ts +27 -0
- package/dist/analysis/finding-lead.js +23 -0
- package/dist/analysis/service.js +5 -3
- package/dist/analysis/validation.js +14 -21
- package/dist/cli/commands/analyze.js +2 -1
- package/dist/cli/commands/notes.js +5 -3
- package/dist/cli/commands/run-signals.js +5 -1
- package/dist/cli/commands/runs.js +2 -1
- package/dist/cli/commands/setup.js +3 -3
- package/dist/cli/commands/study-format.d.ts +5 -2
- package/dist/cli/commands/study-format.js +29 -9
- package/dist/cli/commands/study-route-computer-use.js +2 -2
- package/dist/cli/commands/study-route-scripted.js +1 -1
- package/dist/cli/commands/tui.js +59 -17
- package/dist/cli/doctor.js +9 -2
- package/dist/cli/findings-text.d.ts +5 -0
- package/dist/cli/findings-text.js +169 -0
- package/dist/cli/findings.d.ts +0 -4
- package/dist/cli/findings.js +11 -195
- package/dist/cli/io.js +10 -8
- package/dist/cli/telemetry.js +10 -22
- package/dist/cli/update-check.js +10 -19
- package/dist/cli/user-config.d.ts +11 -0
- package/dist/cli/user-config.js +25 -0
- package/dist/comms/connections.js +4 -3
- package/dist/comms/email-catch.js +7 -31
- package/dist/comms/setup.js +18 -12
- package/dist/evidence/encoded-text.d.ts +12 -11
- package/dist/evidence/encoded-text.js +81 -70
- package/dist/evidence/redaction.d.ts +11 -0
- package/dist/evidence/redaction.js +30 -11
- package/dist/evidence/secret-scrub.d.ts +26 -3
- package/dist/evidence/secret-scrub.js +172 -38
- package/dist/feedback/draft.d.ts +1 -1
- package/dist/feedback/draft.js +13 -16
- package/dist/feedback/export-bundle.js +21 -17
- package/dist/feedback/export.js +32 -46
- package/dist/feedback/feedback.js +31 -26
- package/dist/guest/desktop-keys.js +59 -5
- package/dist/keys/key-resolution.d.ts +9 -0
- package/dist/keys/key-resolution.js +62 -55
- package/dist/keys/key-status.d.ts +2 -0
- package/dist/keys/key-status.js +9 -16
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/http.d.ts +7 -0
- package/dist/observer/http.js +19 -1
- package/dist/observer/notes-route.d.ts +0 -1
- package/dist/observer/notes-route.js +24 -44
- package/dist/observer/pinned-files.js +4 -19
- package/dist/observer/render.js +6 -4
- package/dist/observer/run-routes.js +13 -28
- package/dist/observer/serve.js +2 -1
- package/dist/observer-app.html +7 -7
- package/dist/routes/computer-use/bundle-parts.d.ts +4 -4
- package/dist/routes/computer-use/bundle-parts.js +2 -2
- package/dist/routes/computer-use/bundle.d.ts +4 -5
- package/dist/routes/computer-use/bundle.js +1 -3
- package/dist/routes/computer-use/fanout-records.js +10 -11
- package/dist/routes/computer-use/live-phase.d.ts +1 -1
- package/dist/routes/computer-use/live-phase.js +0 -1
- package/dist/routes/computer-use/participant-execution.d.ts +3 -2
- package/dist/routes/computer-use/participant-runs.d.ts +6 -2
- package/dist/routes/computer-use/participant-runs.js +9 -5
- package/dist/routes/computer-use/plan.d.ts +3 -0
- package/dist/routes/computer-use/plan.js +14 -11
- package/dist/routes/computer-use/rerun-selection.js +2 -2
- package/dist/routes/computer-use/result.js +3 -6
- package/dist/routes/computer-use/setup.d.ts +4 -6
- package/dist/routes/computer-use/setup.js +2 -6
- package/dist/routes/computer-use/single-bundle.d.ts +4 -5
- package/dist/routes/computer-use/single-bundle.js +22 -25
- package/dist/routes/computer-use/subject-projection.d.ts +4 -8
- package/dist/routes/computer-use/subject-projection.js +9 -31
- package/dist/routes/computer-use/types.d.ts +4 -41
- package/dist/routes/scripted/scenario.js +28 -12
- package/dist/routes/scripted/session-result.js +6 -3
- package/dist/routes/shared-world/bundle-records.js +2 -8
- package/dist/routes/shared-world/participant-specs.d.ts +0 -2
- package/dist/routes/shared-world/participant-specs.js +1 -20
- package/dist/routes/shared-world/plan.d.ts +3 -0
- package/dist/routes/shared-world/plan.js +23 -3
- package/dist/routes/shared-world/setup.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +9 -9
- package/dist/routes/terminal/ledger.js +63 -40
- package/dist/routes/terminal/live-finish.js +7 -10
- package/dist/routes/terminal/plan.d.ts +3 -0
- package/dist/routes/terminal/plan.js +8 -5
- package/dist/routes/terminal/token-usage.d.ts +1 -2
- package/dist/routes/terminal/token-usage.js +4 -6
- package/dist/routes/terminal/types.d.ts +9 -1
- package/dist/run/bundle-shape.js +6 -1
- package/dist/run/bundle.d.ts +5 -3
- package/dist/run/contained-output.d.ts +59 -10
- package/dist/run/contained-output.js +160 -68
- package/dist/run/detail.d.ts +2 -1
- package/dist/run/detail.js +12 -7
- package/dist/run/escape-sequences.d.ts +11 -0
- package/dist/run/escape-sequences.js +93 -0
- package/dist/run/evidence-files.d.ts +8 -1
- package/dist/run/evidence-files.js +24 -18
- package/dist/run/locate.d.ts +32 -3
- package/dist/run/locate.js +45 -40
- package/dist/run/note-files.d.ts +26 -45
- package/dist/run/note-files.js +86 -58
- package/dist/run/note-shape.d.ts +35 -0
- package/dist/run/note-shape.js +20 -0
- package/dist/run/notes.d.ts +3 -14
- package/dist/run/notes.js +23 -75
- package/dist/run/outcomes.d.ts +24 -0
- package/dist/run/outcomes.js +19 -0
- package/dist/run/participant-records.d.ts +2 -0
- package/dist/run/participant-records.js +17 -2
- package/dist/run/paths.d.ts +2 -0
- package/dist/run/paths.js +5 -1
- package/dist/run/preflight-receipts.js +13 -8
- package/dist/run/project.js +7 -4
- package/dist/run/reclaim-outcomes.d.ts +8 -6
- package/dist/run/reclaim-outcomes.js +10 -6
- package/dist/run/reclaim.d.ts +5 -0
- package/dist/run/reclaim.js +43 -16
- package/dist/run/run-clock.d.ts +50 -0
- package/dist/run/run-clock.js +66 -0
- package/dist/run/run.js +5 -2
- package/dist/run/sandbox-ids.d.ts +7 -2
- package/dist/run/sandbox-ids.js +27 -11
- package/dist/run/secrets.d.ts +2 -1
- package/dist/run/secrets.js +18 -22
- package/dist/run/stored-runs.js +14 -7
- package/dist/run/transient-comms-secrets.d.ts +6 -5
- package/dist/run/transient-comms-secrets.js +23 -39
- package/dist/run-study.js +22 -13
- package/dist/study/adapter-scorer-loader.js +6 -4
- package/dist/study/discover.js +9 -6
- package/dist/study/init-paths.js +7 -5
- package/dist/study/persona-resolve.d.ts +2 -2
- package/dist/study/persona-resolve.js +9 -5
- package/dist/study/plan-types.d.ts +2 -2
- package/dist/study/plan.d.ts +5 -3
- package/dist/study/plan.js +18 -9
- package/dist/study/preflight-probes.js +11 -3
- package/dist/study/preflight.js +9 -5
- package/dist/study/summary.d.ts +12 -7
- package/dist/study/summary.js +24 -24
- package/dist/study/warnings.d.ts +19 -12
- package/dist/study/warnings.js +39 -17
- package/dist/substrates/e2b/connection.d.ts +12 -0
- package/dist/substrates/e2b/connection.js +35 -0
- package/dist/substrates/e2b/desktop-executor.d.ts +1 -3
- package/dist/substrates/e2b/desktop-executor.js +42 -9
- package/dist/substrates/e2b/lifetime.d.ts +24 -4
- package/dist/substrates/e2b/lifetime.js +41 -4
- package/dist/substrates/e2b/sandbox.d.ts +4 -3
- package/dist/substrates/e2b/sandbox.js +13 -18
- package/dist/substrates/e2b/sdk.d.ts +20 -9
- package/dist/substrates/local/capacity.d.ts +18 -2
- package/dist/substrates/local/capacity.js +21 -2
- package/dist/substrates/local/runtime-host.js +21 -14
- package/dist/substrates/local/runtime.js +3 -11
- package/dist/tui/contract.d.ts +30 -5
- package/dist/tui/contract.js +4 -1
- package/dist/tui-app.js +149 -147
- package/dist/verify/artifacts.d.ts +9 -2
- package/dist/verify/artifacts.js +37 -13
- package/dist/verify/liveness.js +19 -5
- package/dist/verify/verify.js +54 -27
- package/docs/architecture/actor-contract.md +3 -3
- package/docs/architecture/guest-desktop.md +7 -2
- package/docs/architecture/restricted-codex-analysis.md +1 -1
- package/docs/architecture/state-driven-executor.md +5 -3
- package/docs/contracts/run-bundle.md +25 -13
- package/docs/contracts/schemas.md +38 -29
- package/docs/contracts/study-analysis.md +22 -5
- package/docs/product/automatic-analysis.md +7 -1
- package/package.json +8 -7
- package/skills/humanish/SKILL.md +1 -2
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,47 @@ The Unreleased section holds the full notes for the next version until it is tag
|
|
|
8
8
|
|
|
9
9
|
## Unreleased
|
|
10
10
|
|
|
11
|
+
## 0.116.0: Hosted keyboard input, E2B sandbox ceiling, bounded run reads, run header, TUI live starts (2026-10-09)
|
|
12
|
+
|
|
13
|
+
humanish 0.116.0 delivers a hosted participant's arrow keys and punctuation, lets the operator
|
|
14
|
+
raise the E2B sandbox lifetime, and reads run files within size limits. On hosted E2B desktops,
|
|
15
|
+
`ARROWDOWN`, Page Up, Page Down, `?`, `/` and other names missing from `@e2b/desktop`'s key table
|
|
16
|
+
reached xdotool unchanged, which ignored them while the run recorded the keypress as completed;
|
|
17
|
+
both desktops now translate key names through one table and refuse a name outside it.
|
|
18
|
+
`HUMANISH_E2B_MAX_SANDBOX_MINUTES` sets the longest sandbox lifetime the planners allow, 60 minutes
|
|
19
|
+
when unset and up to 1440 on E2B's Pro plan. A refusal names the value that admits the study, and
|
|
20
|
+
`humanish doctor` shows the ceiling. A route's sandbox kill, and the kills, checks and listings of
|
|
21
|
+
`humanish reclaim`, carry the run's E2B key. `verify` reads at most 32 MiB of a run file and lists
|
|
22
|
+
a larger file, or a run past 10,000 entries, as unscanned, and every contained read tells a missing
|
|
23
|
+
file from one it refused. A run whose analysis did not complete reads `live run finished; the
|
|
24
|
+
analysis did not complete`, a run refused before it was created prints no `analysis:` line, and a
|
|
25
|
+
`desktop-cli` run names its product on the `subject:` line and in run.json. In `humanish tui`, the
|
|
26
|
+
cursor follows the selected row through a refresh, a live start of a `mode: dry-run` file says
|
|
27
|
+
`needs mode: live`, Run again on a live run asks for a second Enter, the confirm prompt restates
|
|
28
|
+
the study's cost, and `c` lists every provider key. `NO_UPDATE_NOTIFIER` turns the update check
|
|
29
|
+
off.
|
|
30
|
+
|
|
31
|
+
[Release notes](https://github.com/danielgwilson/humanish/releases/tag/v0.116.0)
|
|
32
|
+
|
|
33
|
+
## 0.115.0: Closing report limits, admitted analysis cost, concurrent reviewer notes, known-value scrub (2026-10-08)
|
|
34
|
+
|
|
35
|
+
humanish 0.115.0 asks the OpenAI computer-use participant for its closing report and impressions
|
|
36
|
+
within the limits its reply is checked against, keeps every reviewer note added at the same time,
|
|
37
|
+
and finds more encoded forms of a registered secret. The participant's request schema now carries
|
|
38
|
+
the limits the parser already enforced: a summary of up to 4,000 characters, up to 8 friction
|
|
39
|
+
reports of up to 2,000 characters and up to 6 impressions of up to 500 characters, so a longer
|
|
40
|
+
reply is no longer requested and then dropped. `analyze --json` adds `admission.admittedCostUsd`,
|
|
41
|
+
the smallest `--max-cost` that admits the analysis, and `humanish analyze` names its refusal
|
|
42
|
+
command as `npx humanish analyze` where humanish is a dev dependency. A reviewer note is created
|
|
43
|
+
under its own name, so notes added together from the Observer and `humanish notes --add` are all
|
|
44
|
+
kept. `export --local-only` keeps a `blocked` run `blocked` when its analysis fails the export's
|
|
45
|
+
own check. The known-value scrub exempts only the markers humanish writes, reads text in the same
|
|
46
|
+
five ways as `verify`, and finds a value that overlaps itself in time linear in the text. The TUI's
|
|
47
|
+
study screen shows the expected analysis cost line that `study check` prints, telemetry reads
|
|
48
|
+
`CI=false` as off, and `humanish keys set constructor` is refused with the list of provider keys.
|
|
49
|
+
|
|
50
|
+
[Release notes](https://github.com/danielgwilson/humanish/releases/tag/v0.115.0)
|
|
51
|
+
|
|
11
52
|
## 0.114.0: Reviewer notes, expected analysis cost, percent-encoded UTF-8 in verify (2026-10-08)
|
|
12
53
|
|
|
13
54
|
humanish 0.114.0 lets a reviewer note a moment of a recorded run, admits post-run analysis on its
|
package/CONTEXT.md
CHANGED
|
@@ -41,7 +41,7 @@ bundle and output fields keep older spellings; the second table maps them.
|
|
|
41
41
|
| analysis | An independent model reading of a finished run's retained evidence, kept apart from participant feedback. Supported live runs request it automatically, and `humanish analyze` runs it on demand. It records findings and observations as `humanish.study-analysis.v1`. | `src/analysis/`; `runAutomaticAnalysis` in `src/analysis/automatic.ts`; `analyzeRun` in `src/analysis/service.ts`; `ANALYSIS_SCHEMA` in `src/analysis/types.ts` |
|
|
42
42
|
| finding | A result of analysis, with citations to evidence in the run. Each finding groups the observations that support it. | `src/analysis/` |
|
|
43
43
|
| observation | One claim in analysis with its basis, evidence ids and limitation. `concernReviews[]` gives each material concern's observation a disposition: `finding`, `context` or `unsupported`. | `src/analysis/` |
|
|
44
|
-
| reviewer note | Free text a person adds at a moment of a recorded run, for one participant or the whole run, kept in the run directory as its own file, `notes/<id>.json` (`humanish.run-note.v1`). It is not participant feedback or analysis. `humanish notes` and an Observer served on loopback add notes. | `addRunNote` in `src/run/notes.ts`; `readRunNotes` in `src/run/note-files.ts`; `createNotesWriter` in `src/observer/notes-route.ts`
|
|
44
|
+
| reviewer note | Free text a person adds at a moment of a recorded run, for one participant or the whole run, kept in the run directory as its own file, `notes/<id>.json` (`humanish.run-note.v1`). It is not participant feedback or analysis. `humanish notes` and an Observer served on loopback add notes. | `RunNote` and its limits in `src/run/note-shape.ts`; `addRunNote` in `src/run/notes.ts`; `readRunNotes` in `src/run/note-files.ts`; `createNotesWriter` in `src/observer/notes-route.ts` |
|
|
45
45
|
|
|
46
46
|
## Read these field spellings as the concept they name
|
|
47
47
|
|
package/README.md
CHANGED
|
@@ -276,9 +276,10 @@ sensitive to capture in the first place.
|
|
|
276
276
|
**What the automated gate enforces.** `humanish verify` scans public-bound
|
|
277
277
|
artifacts and fails closed on secret, key, and token shapes and on known local
|
|
278
278
|
path shapes. It reads text only, judged by a file's bytes rather than its name:
|
|
279
|
-
any file in the run folder that is not UTF-8 text
|
|
280
|
-
screenshot or recording, keeps the run `local_only`
|
|
281
|
-
matches after undoing escapes, percent-encoding, HTML
|
|
279
|
+
any file in the run folder that is not UTF-8 text or is larger than 32 MiB,
|
|
280
|
+
other than a stream screenshot or recording, keeps the run `local_only`
|
|
281
|
+
(`UNSCANNED_ARTIFACT`). It matches after undoing escapes, percent-encoding, HTML
|
|
282
|
+
entities and base64. It
|
|
282
283
|
does not yet detect free-form PII or PHI such as names, emails,
|
|
283
284
|
phone numbers, dates of birth, or medical identifiers. Keeping those out depends
|
|
284
285
|
on using synthetic data and on review, so `redaction: passed` means the
|
|
@@ -483,9 +484,9 @@ At most once a day, a command run at a terminal also asks the npm registry for
|
|
|
483
484
|
the latest humanish version, and a later command prints one line on stderr when
|
|
484
485
|
yours is older. That request is a plain `GET` of humanish's dist-tags with no
|
|
485
486
|
machine id, version, command or path. It is skipped in CI, without a terminal,
|
|
486
|
-
for `--json`, and with `DO_NOT_TRACK=1`, `HUMANISH_TELEMETRY_DISABLED=1
|
|
487
|
-
`HUMANISH_NO_UPDATE_CHECK=1
|
|
488
|
-
describes it.
|
|
487
|
+
for `--json`, and with `DO_NOT_TRACK=1`, `HUMANISH_TELEMETRY_DISABLED=1`,
|
|
488
|
+
`HUMANISH_NO_UPDATE_CHECK=1` or update-notifier's `NO_UPDATE_NOTIFIER=1`.
|
|
489
|
+
[TELEMETRY.md](TELEMETRY.md#the-update-check) describes it.
|
|
489
490
|
|
|
490
491
|
## Contribute
|
|
491
492
|
|
package/TELEMETRY.md
CHANGED
|
@@ -132,4 +132,10 @@ participant, and when any of these is set:
|
|
|
132
132
|
DO_NOT_TRACK=1
|
|
133
133
|
HUMANISH_TELEMETRY_DISABLED=1
|
|
134
134
|
HUMANISH_NO_UPDATE_CHECK=1
|
|
135
|
+
NO_UPDATE_NOTIFIER=1
|
|
135
136
|
```
|
|
137
|
+
|
|
138
|
+
`NO_UPDATE_NOTIFIER` is the variable the update-notifier package reads, so a
|
|
139
|
+
machine set up to silence the CLIs built on it gets no humanish notice either.
|
|
140
|
+
humanish reads it as update-notifier does: any value turns the check off,
|
|
141
|
+
including an empty one, `0` or `false`.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How much a participant's closing report may hold. Participants are asked for no more, and a
|
|
3
|
+
* reply that holds more is rejected. Characters are counted as `String.length` counts them.
|
|
4
|
+
*/
|
|
5
|
+
export declare const CLOSING_REPORT_LIMITS: Readonly<{
|
|
6
|
+
summaryChars: 4000;
|
|
7
|
+
frictionReports: 8;
|
|
8
|
+
frictionReportChars: 2000;
|
|
9
|
+
impressions: 6;
|
|
10
|
+
impressionChars: 500;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// The closing report's limits, kept apart from its zod schema in closing-report.ts so the
|
|
2
|
+
// Observer can read them: it bundles this module, and zod stays out of its page.
|
|
3
|
+
/**
|
|
4
|
+
* How much a participant's closing report may hold. Participants are asked for no more, and a
|
|
5
|
+
* reply that holds more is rejected. Characters are counted as `String.length` counts them.
|
|
6
|
+
*/
|
|
7
|
+
export const CLOSING_REPORT_LIMITS = Object.freeze({
|
|
8
|
+
summaryChars: 4000,
|
|
9
|
+
frictionReports: 8,
|
|
10
|
+
frictionReportChars: 2000,
|
|
11
|
+
impressions: 6,
|
|
12
|
+
impressionChars: 500,
|
|
13
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const impressionSchema: z.ZodObject<{
|
|
3
|
+
kind: z.ZodEnum<{
|
|
4
|
+
liked: "liked";
|
|
5
|
+
missing: "missing";
|
|
6
|
+
unclear: "unclear";
|
|
7
|
+
unfinished: "unfinished";
|
|
8
|
+
unlike_my_work: "unlike_my_work";
|
|
9
|
+
untrustworthy: "untrustworthy";
|
|
10
|
+
}>;
|
|
11
|
+
text: z.ZodString;
|
|
12
|
+
}, z.core.$strict>;
|
|
13
|
+
/** The impressions a participant gave; an empty list means it had none. */
|
|
14
|
+
export declare const participantImpressionsSchema: z.ZodArray<z.ZodObject<{
|
|
15
|
+
kind: z.ZodEnum<{
|
|
16
|
+
liked: "liked";
|
|
17
|
+
missing: "missing";
|
|
18
|
+
unclear: "unclear";
|
|
19
|
+
unfinished: "unfinished";
|
|
20
|
+
unlike_my_work: "unlike_my_work";
|
|
21
|
+
untrustworthy: "untrustworthy";
|
|
22
|
+
}>;
|
|
23
|
+
text: z.ZodString;
|
|
24
|
+
}, z.core.$strict>>;
|
|
25
|
+
/**
|
|
26
|
+
* A closing report. A report without impressions is still valid: third-party provider ports and
|
|
27
|
+
* stored traces do not have them.
|
|
28
|
+
*/
|
|
29
|
+
export declare const closingReportSchema: z.ZodObject<{
|
|
30
|
+
summary: z.ZodString;
|
|
31
|
+
frictionReports: z.ZodArray<z.ZodString>;
|
|
32
|
+
impressions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
33
|
+
kind: z.ZodEnum<{
|
|
34
|
+
liked: "liked";
|
|
35
|
+
missing: "missing";
|
|
36
|
+
unclear: "unclear";
|
|
37
|
+
unfinished: "unfinished";
|
|
38
|
+
unlike_my_work: "unlike_my_work";
|
|
39
|
+
untrustworthy: "untrustworthy";
|
|
40
|
+
}>;
|
|
41
|
+
text: z.ZodString;
|
|
42
|
+
}, z.core.$strict>>>;
|
|
43
|
+
}, z.core.$strict>;
|
|
44
|
+
/** The reply to an impressions-only request: the impressions and nothing else. */
|
|
45
|
+
export declare const impressionsReplySchema: z.ZodObject<{
|
|
46
|
+
impressions: z.ZodArray<z.ZodObject<{
|
|
47
|
+
kind: z.ZodEnum<{
|
|
48
|
+
liked: "liked";
|
|
49
|
+
missing: "missing";
|
|
50
|
+
unclear: "unclear";
|
|
51
|
+
unfinished: "unfinished";
|
|
52
|
+
unlike_my_work: "unlike_my_work";
|
|
53
|
+
untrustworthy: "untrustworthy";
|
|
54
|
+
}>;
|
|
55
|
+
text: z.ZodString;
|
|
56
|
+
}, z.core.$strict>>;
|
|
57
|
+
}, z.core.$strict>;
|
|
58
|
+
/** The participant's account, not an independently confirmed product diagnosis. */
|
|
59
|
+
export type ParticipantClosingReport = z.infer<typeof closingReportSchema>;
|
|
60
|
+
/** One first-person impression about something the participant saw in the session. */
|
|
61
|
+
export type ParticipantImpression = z.infer<typeof impressionSchema>;
|
|
62
|
+
/**
|
|
63
|
+
* The JSON Schema a strict structured-output request sends for `schema`. Strict mode needs every
|
|
64
|
+
* field, so optional ones become required. `$schema` is left out, so the request carries only
|
|
65
|
+
* keywords both providers' strict modes are known to accept.
|
|
66
|
+
*/
|
|
67
|
+
export declare function strictOutputSchema(schema: z.ZodObject): Record<string, unknown>;
|
|
68
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CLOSING_REPORT_LIMITS as LIMITS } from "./closing-report-limits.js";
|
|
3
|
+
// What a participant says at the end of a session: the closing report and its impressions. This
|
|
4
|
+
// schema is the one description of them. The providers send the JSON Schema made from it, and
|
|
5
|
+
// every reply is parsed with it, so a participant is asked for exactly what is accepted.
|
|
6
|
+
/**
|
|
7
|
+
* What a participant can say about the product at the end of a session, beyond friction.
|
|
8
|
+
* `unlike_my_work` compares the screen with how the persona does the same task in its own work or
|
|
9
|
+
* life.
|
|
10
|
+
*/
|
|
11
|
+
const PARTICIPANT_IMPRESSION_KINDS = [
|
|
12
|
+
"unclear",
|
|
13
|
+
"unfinished",
|
|
14
|
+
"untrustworthy",
|
|
15
|
+
"liked",
|
|
16
|
+
"missing",
|
|
17
|
+
"unlike_my_work",
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* Text the participant wrote. The JSON Schema carries the length limits; the check that it is not
|
|
21
|
+
* only whitespace runs on the reply.
|
|
22
|
+
*/
|
|
23
|
+
const said = (maxChars) => z
|
|
24
|
+
.string()
|
|
25
|
+
.min(1)
|
|
26
|
+
.max(maxChars)
|
|
27
|
+
.refine((text) => text.trim() !== "");
|
|
28
|
+
const impressionSchema = z.strictObject({
|
|
29
|
+
kind: z.enum(PARTICIPANT_IMPRESSION_KINDS),
|
|
30
|
+
text: said(LIMITS.impressionChars),
|
|
31
|
+
});
|
|
32
|
+
/** The impressions a participant gave; an empty list means it had none. */
|
|
33
|
+
export const participantImpressionsSchema = z.array(impressionSchema).max(LIMITS.impressions);
|
|
34
|
+
/**
|
|
35
|
+
* A closing report. A report without impressions is still valid: third-party provider ports and
|
|
36
|
+
* stored traces do not have them.
|
|
37
|
+
*/
|
|
38
|
+
export const closingReportSchema = z.strictObject({
|
|
39
|
+
summary: said(LIMITS.summaryChars),
|
|
40
|
+
frictionReports: z.array(said(LIMITS.frictionReportChars)).max(LIMITS.frictionReports),
|
|
41
|
+
impressions: participantImpressionsSchema.optional(),
|
|
42
|
+
});
|
|
43
|
+
/** The reply to an impressions-only request: the impressions and nothing else. */
|
|
44
|
+
export const impressionsReplySchema = z.strictObject({
|
|
45
|
+
impressions: participantImpressionsSchema,
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* The JSON Schema a strict structured-output request sends for `schema`. Strict mode needs every
|
|
49
|
+
* field, so optional ones become required. `$schema` is left out, so the request carries only
|
|
50
|
+
* keywords both providers' strict modes are known to accept.
|
|
51
|
+
*/
|
|
52
|
+
export function strictOutputSchema(schema) {
|
|
53
|
+
const { $schema: _dialect, ...json } = z.toJSONSchema(schema.required(), { io: "input" });
|
|
54
|
+
return json;
|
|
55
|
+
}
|
|
@@ -2,7 +2,7 @@ import { createServer } from "node:http";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { digestText } from "../../evidence/redaction.js";
|
|
4
4
|
import { CODEX_APP_SERVER_ARTIFACTS, CODEX_APP_SERVER_DIRECTORY, runCodexAppServerSessionInPreparedRoot, } from "./app-server.js";
|
|
5
|
-
import { prepareContainedOutputDirectory, prepareContainedOutputFile, prepareManagedHumanishOutputDirectory, prepareSelectedOutputDirectory, prepareSelectedOutputFile, readContainedRegularFile, writeContainedOutputFile, writePreparedSelectedOutputFile, } from "../../run/contained-output.js";
|
|
5
|
+
import { prepareContainedOutputDirectory, prepareContainedOutputFile, prepareManagedHumanishOutputDirectory, prepareSelectedOutputDirectory, prepareSelectedOutputFile, readContainedRegularFile, refusalText, RUN_ARTIFACT_MAX_BYTES, writeContainedOutputFile, writePreparedSelectedOutputFile, } from "../../run/contained-output.js";
|
|
6
6
|
const CODEX_APP_SERVER_UI_SCHEMA = "humanish.codex-app-server-ui.v1";
|
|
7
7
|
export async function startCodexAppServerUi(options) {
|
|
8
8
|
const cwd = path.resolve(options.cwd);
|
|
@@ -128,13 +128,20 @@ export async function startCodexAppServerUi(options) {
|
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
130
|
async function serveArtifact(args) {
|
|
131
|
-
const
|
|
132
|
-
if (
|
|
131
|
+
const read = await readContainedRegularFile(args.runRoot, args.requestPath, RUN_ARTIFACT_MAX_BYTES);
|
|
132
|
+
if (read.status === "read") {
|
|
133
133
|
args.response.writeHead(200, {
|
|
134
134
|
"cache-control": "no-store",
|
|
135
135
|
"content-type": contentTypeFor(args.requestPath),
|
|
136
136
|
});
|
|
137
|
-
args.response.end(
|
|
137
|
+
args.response.end(read.bytes);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// A file over the limit is there: a 404 would tell the page it does not exist. A link, or a
|
|
141
|
+
// path outside the run, is served as absent, as it always was.
|
|
142
|
+
if (read.status === "refused" && read.reason === "too-large") {
|
|
143
|
+
args.response.writeHead(403, { "content-type": "text/plain; charset=utf-8" });
|
|
144
|
+
args.response.end(`${refusalText(args.requestPath, read)}.`);
|
|
138
145
|
return;
|
|
139
146
|
}
|
|
140
147
|
args.response.writeHead(404);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import
|
|
1
|
+
import { type ParticipantClosingReport } from "../closing-report.js";
|
|
2
|
+
import type { CuaTurn } from "../computer-use/loop.js";
|
|
3
|
+
import type { ActorExecutionProfile } from "../contract.js";
|
|
3
4
|
/** The declared profile. A participant replaces cliVersion with its detected CLI release, or with
|
|
4
5
|
* this host's newest qualified release before its first launch. */
|
|
5
6
|
export declare const PARTICIPANT_PROFILE: Readonly<ActorExecutionProfile>;
|
|
@@ -16,51 +17,7 @@ export declare const PARTICIPANT_LIMITS: Readonly<{
|
|
|
16
17
|
}>;
|
|
17
18
|
export declare function participantToolSchema(speechEnabled?: boolean): Record<string, unknown>;
|
|
18
19
|
export declare const PARTICIPANT_TOOL_SCHEMA: Record<string, unknown>;
|
|
19
|
-
export declare const PARTICIPANT_FINAL_SCHEMA:
|
|
20
|
-
type: string;
|
|
21
|
-
additionalProperties: boolean;
|
|
22
|
-
required: string[];
|
|
23
|
-
properties: {
|
|
24
|
-
outcome: {
|
|
25
|
-
type: string;
|
|
26
|
-
enum: string[];
|
|
27
|
-
};
|
|
28
|
-
summary: {
|
|
29
|
-
type: string;
|
|
30
|
-
minLength: number;
|
|
31
|
-
maxLength: number;
|
|
32
|
-
};
|
|
33
|
-
frictionReports: {
|
|
34
|
-
type: string;
|
|
35
|
-
maxItems: number;
|
|
36
|
-
items: {
|
|
37
|
-
type: string;
|
|
38
|
-
minLength: number;
|
|
39
|
-
maxLength: number;
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
impressions: {
|
|
43
|
-
type: string;
|
|
44
|
-
maxItems: number;
|
|
45
|
-
items: {
|
|
46
|
-
type: string;
|
|
47
|
-
additionalProperties: boolean;
|
|
48
|
-
required: string[];
|
|
49
|
-
properties: {
|
|
50
|
-
kind: {
|
|
51
|
-
type: string;
|
|
52
|
-
enum: ("liked" | "missing" | "unclear" | "unfinished" | "unlike_my_work" | "untrustworthy")[];
|
|
53
|
-
};
|
|
54
|
-
text: {
|
|
55
|
-
type: string;
|
|
56
|
-
minLength: number;
|
|
57
|
-
maxLength: number;
|
|
58
|
-
};
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
};
|
|
20
|
+
export declare const PARTICIPANT_FINAL_SCHEMA: Record<string, unknown>;
|
|
64
21
|
/** humanish tool arguments, validated before the shared executor sees a batch. */
|
|
65
22
|
export declare function parseParticipantTool(value: unknown, speechEnabled?: boolean): CuaTurn;
|
|
66
23
|
export declare function parseParticipantFinal(value: unknown): CuaTurn & {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { BROWSER_CONTROL_LIMITS, browserControlActionSchema, browserOnlyControlActionSchema, validateBrowserControlAction, } from "../../browser-control/protocol.js";
|
|
3
|
-
import {
|
|
4
|
-
import { PARTICIPANT_IMPRESSION_KINDS, } from "../contract.js";
|
|
3
|
+
import { closingReportSchema, strictOutputSchema, } from "../closing-report.js";
|
|
5
4
|
/** The declared profile. A participant replaces cliVersion with its detected CLI release, or with
|
|
6
5
|
* this host's newest qualified release before its first launch. */
|
|
7
6
|
export const PARTICIPANT_PROFILE = Object.freeze({
|
|
@@ -38,33 +37,12 @@ export function participantToolSchema(speechEnabled = false) {
|
|
|
38
37
|
return z.toJSONSchema(toolInput(speechEnabled), { io: "input" });
|
|
39
38
|
}
|
|
40
39
|
export const PARTICIPANT_TOOL_SCHEMA = participantToolSchema();
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
summary: { type: "string", minLength: 1, maxLength: 4000 },
|
|
48
|
-
frictionReports: {
|
|
49
|
-
type: "array",
|
|
50
|
-
maxItems: 8,
|
|
51
|
-
items: { type: "string", minLength: 1, maxLength: 2000 },
|
|
52
|
-
},
|
|
53
|
-
impressions: {
|
|
54
|
-
type: "array",
|
|
55
|
-
maxItems: 6,
|
|
56
|
-
items: {
|
|
57
|
-
type: "object",
|
|
58
|
-
additionalProperties: false,
|
|
59
|
-
required: ["kind", "text"],
|
|
60
|
-
properties: {
|
|
61
|
-
kind: { type: "string", enum: [...PARTICIPANT_IMPRESSION_KINDS] },
|
|
62
|
-
text: { type: "string", minLength: 1, maxLength: 500 },
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
};
|
|
40
|
+
/** The participant's final account: how the task went, then its closing report. */
|
|
41
|
+
const participantFinal = z.strictObject({
|
|
42
|
+
outcome: z.enum(["reached", "not_reached", "blocked"]),
|
|
43
|
+
...closingReportSchema.shape,
|
|
44
|
+
});
|
|
45
|
+
export const PARTICIPANT_FINAL_SCHEMA = strictOutputSchema(participantFinal);
|
|
68
46
|
/**
|
|
69
47
|
* Shorten each wait longer than one browser-control request may wait. A failed tool call ends the
|
|
70
48
|
* native run, so a wait that asks too much would otherwise end the whole session.
|
|
@@ -107,22 +85,16 @@ export function parseParticipantTool(value, speechEnabled = false) {
|
|
|
107
85
|
};
|
|
108
86
|
}
|
|
109
87
|
export function parseParticipantFinal(value) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const { outcome, ...report } = value;
|
|
113
|
-
if ((outcome !== "reached" && outcome !== "not_reached" && outcome !== "blocked") ||
|
|
114
|
-
!validClosingReport(report))
|
|
88
|
+
const final = participantFinal.safeParse(value);
|
|
89
|
+
if (!final.success)
|
|
115
90
|
throw new Error("invalid_response");
|
|
91
|
+
const { outcome, ...closingReport } = final.data;
|
|
116
92
|
return {
|
|
117
93
|
actions: [],
|
|
118
94
|
pendingSafetyChecks: [],
|
|
119
95
|
done: true,
|
|
120
96
|
outcome,
|
|
121
|
-
message: [
|
|
122
|
-
closingReport
|
|
123
|
-
summary: report.summary,
|
|
124
|
-
frictionReports: [...report.frictionReports],
|
|
125
|
-
...(report.impressions === undefined ? {} : { impressions: [...report.impressions] }),
|
|
126
|
-
},
|
|
97
|
+
message: [closingReport.summary, ...closingReport.frictionReports].join("\n"),
|
|
98
|
+
closingReport,
|
|
127
99
|
};
|
|
128
100
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ActorTrace } from "../../contract.js";
|
|
2
2
|
import type { DebriefTrigger } from "./ending.js";
|
|
3
3
|
import type { LoopSession } from "./session.js";
|
|
4
4
|
import type { CuaTurnRequest } from "./types.js";
|
|
@@ -9,15 +9,6 @@ export interface DebriefContext {
|
|
|
9
9
|
readonly previousExecution: CuaTurnRequest["previousExecution"];
|
|
10
10
|
readonly acknowledgedSafetyChecks: CuaTurnRequest["acknowledgedSafetyChecks"];
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
13
|
-
* Runtime validation is also required for third-party provider ports. A report without
|
|
14
|
-
* impressions stays valid: older providers and stored traces do not have them.
|
|
15
|
-
*/
|
|
16
|
-
export declare function validClosingReport(value: unknown): value is ParticipantClosingReport;
|
|
17
|
-
/** The reply to an impressions-only request: an object with the impressions and nothing else. */
|
|
18
|
-
export declare function validImpressionsReply(value: unknown): value is {
|
|
19
|
-
impressions: ParticipantImpression[];
|
|
20
|
-
};
|
|
21
12
|
/**
|
|
22
13
|
* Ask the participant for its closing report after a structured stop, or for its impressions only
|
|
23
14
|
* after it ended the session itself, or record why the request was skipped. Either way the result
|