humanish 0.140.0 → 0.141.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 +12 -0
- package/dist/actors/codex/restricted-participant.js +1 -1
- package/dist/actors/computer-use/external-handoff.d.ts +22 -0
- package/dist/actors/computer-use/external-handoff.js +83 -0
- package/dist/actors/computer-use/loop/observation.d.ts +7 -0
- package/dist/actors/computer-use/loop/observation.js +17 -1
- package/dist/actors/computer-use/loop/types.d.ts +6 -0
- package/dist/analysis/analysis-limits.d.ts +6 -0
- package/dist/analysis/analysis-limits.js +6 -0
- package/dist/analysis/analysis-lock.d.ts +8 -0
- package/dist/analysis/analysis-lock.js +129 -0
- package/dist/analysis/automatic-completion.js +7 -0
- package/dist/analysis/execute.js +1 -1
- package/dist/analysis/job.d.ts +1 -0
- package/dist/analysis/job.js +6 -2
- package/dist/analysis/recording-ended.d.ts +16 -0
- package/dist/analysis/recording-ended.js +29 -0
- package/dist/analysis/service.d.ts +1 -3
- package/dist/analysis/service.js +23 -50
- package/dist/analysis/source.d.ts +1 -1
- package/dist/browser-control/protocol.d.ts +8 -0
- package/dist/browser-control/protocol.js +21 -0
- package/dist/cli/commands/analysis-signals.d.ts +10 -4
- package/dist/cli/commands/analysis-signals.js +28 -6
- package/dist/cli/commands/runs.js +8 -2
- package/dist/cli/commands/study-route-computer-use.js +2 -2
- package/dist/cli/commands/study-route-scripted.js +2 -2
- package/dist/cli/commands/study-route-shared-world.js +2 -2
- package/dist/cli/commands/study-route-terminal.js +2 -2
- package/dist/cli/findings.d.ts +23 -0
- package/dist/cli/findings.js +80 -4
- package/dist/cli/io.js +1 -0
- package/dist/evidence/browser-hygiene.d.ts +12 -1
- package/dist/evidence/browser-hygiene.js +45 -2
- package/dist/feedback/export-bundle.js +1 -1
- package/dist/guest/external-links.d.ts +14 -0
- package/dist/guest/external-links.js +48 -0
- package/dist/guest/runtime-desktop.js +5 -2
- package/dist/observer/data.d.ts +4 -0
- package/dist/observer/run-routes.js +12 -3
- package/dist/observer-app.html +2 -2
- package/dist/routes/computer-use/e2b-desktop/desktop.js +27 -17
- package/dist/routes/computer-use/e2b-desktop/teardown.js +1 -1
- package/dist/routes/computer-use/in-process-desktop.js +2 -2
- package/dist/routes/computer-use/live-phase.js +1 -1
- package/dist/routes/computer-use/setup.js +2 -2
- package/dist/routes/shared-world/route.js +1 -1
- package/dist/run/display.d.ts +6 -1
- package/dist/run/display.js +11 -0
- package/dist/run/host-suspension.js +4 -1
- package/dist/run/preflight-receipts.d.ts +3 -12
- package/dist/run/preflight-receipts.js +7 -67
- package/dist/run/process-owner.d.ts +28 -0
- package/dist/run/process-owner.js +83 -0
- package/dist/run/projection.js +1 -1
- package/dist/run/reclaim.d.ts +6 -0
- package/dist/run/reclaim.js +32 -2
- package/dist/run/route-shell.js +1 -1
- package/dist/run/run-index.d.ts +3 -1
- package/dist/run/run-index.js +23 -11
- package/dist/run/run.d.ts +16 -5
- package/dist/run/run.js +25 -10
- package/dist/run/status.d.ts +57 -2
- package/dist/run/status.js +87 -1
- package/dist/run/stored-runs.d.ts +3 -0
- package/dist/run/stored-runs.js +9 -4
- package/dist/study/run-study-events.d.ts +7 -1
- package/dist/substrates/e2b/desktop-browser.js +3 -1
- package/dist/substrates/e2b/desktop-executor.d.ts +7 -0
- package/dist/substrates/e2b/desktop-executor.js +3 -0
- package/dist/substrates/e2b/desktop-handoff.d.ts +22 -0
- package/dist/substrates/e2b/desktop-handoff.js +86 -0
- package/dist/substrates/local/runtime-release.js +8 -8
- package/dist/tui-app.js +115 -115
- package/docs/architecture/observer.md +7 -3
- package/docs/contracts/schemas.md +24 -3
- package/docs/contracts/study-analysis.md +1 -1
- package/docs/product/automatic-analysis.md +29 -7
- package/package.json +1 -1
- package/skills/humanish/SKILL.md +108 -5
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CuaExecutor } from "../actors/computer-use/loop.js";
|
|
2
|
+
/** Where the image keeps the stand-ins. */
|
|
3
|
+
export declare const GUEST_EXTERNAL_LINK_BIN = "/opt/humanish/control/bin";
|
|
4
|
+
/**
|
|
5
|
+
* Write the browser profile's Preferences before the first launch, so the initial app's origin
|
|
6
|
+
* opens tel:, sms: and the other app schemes without Chromium's prompt. No initial URL, no file.
|
|
7
|
+
*/
|
|
8
|
+
export declare function prepareGuestBrowserProfile(profileDir: string, initialUrl: string | undefined): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* The executor with each observation carrying the links appended to `log` since the previous
|
|
11
|
+
* observation, at most EXTERNAL_HANDOFF_LIMITS.perObservation. A line still being written waits
|
|
12
|
+
* for the next observation. Every other property of the executor is kept.
|
|
13
|
+
*/
|
|
14
|
+
export declare function withExternalHandoffs(executor: CuaExecutor, log: string): CuaExecutor;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Links the guest browser hands to another app (mailto:, tel:, sms:). The guest has no email,
|
|
2
|
+
// phone or messaging app. The image's stand-ins for xdg-open and xdg-email, first on the guest's
|
|
3
|
+
// search path, append each such link to a log in the runtime directory, and every observation the
|
|
4
|
+
// executor returns carries the links appended since the previous one.
|
|
5
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
6
|
+
import { EXTERNAL_HANDOFF_LIMITS, externalHandoffOf, } from "../actors/computer-use/external-handoff.js";
|
|
7
|
+
import { externalAppPreferences } from "../evidence/browser-hygiene.js";
|
|
8
|
+
/** Where the image keeps the stand-ins. */
|
|
9
|
+
export const GUEST_EXTERNAL_LINK_BIN = "/opt/humanish/control/bin";
|
|
10
|
+
/**
|
|
11
|
+
* Write the browser profile's Preferences before the first launch, so the initial app's origin
|
|
12
|
+
* opens tel:, sms: and the other app schemes without Chromium's prompt. No initial URL, no file.
|
|
13
|
+
*/
|
|
14
|
+
export async function prepareGuestBrowserProfile(profileDir, initialUrl) {
|
|
15
|
+
const preferences = externalAppPreferences(initialUrl);
|
|
16
|
+
if (preferences === undefined)
|
|
17
|
+
return;
|
|
18
|
+
await mkdir(`${profileDir}/Default`, { recursive: true, mode: 0o700 });
|
|
19
|
+
await writeFile(`${profileDir}/Default/Preferences`, JSON.stringify(preferences), {
|
|
20
|
+
mode: 0o600,
|
|
21
|
+
flag: "wx",
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The executor with each observation carrying the links appended to `log` since the previous
|
|
26
|
+
* observation, at most EXTERNAL_HANDOFF_LIMITS.perObservation. A line still being written waits
|
|
27
|
+
* for the next observation. Every other property of the executor is kept.
|
|
28
|
+
*/
|
|
29
|
+
export function withExternalHandoffs(executor, log) {
|
|
30
|
+
let consumed = 0;
|
|
31
|
+
return {
|
|
32
|
+
...executor,
|
|
33
|
+
observe: async () => {
|
|
34
|
+
const observation = await executor.observe();
|
|
35
|
+
const text = await readFile(log, "utf8").catch(() => "");
|
|
36
|
+
const lines = text
|
|
37
|
+
.split("\n")
|
|
38
|
+
.slice(0, -1)
|
|
39
|
+
.slice(consumed, consumed + EXTERNAL_HANDOFF_LIMITS.perObservation);
|
|
40
|
+
consumed += lines.length;
|
|
41
|
+
const externalHandoffs = lines.flatMap((line) => {
|
|
42
|
+
const handoff = externalHandoffOf(line);
|
|
43
|
+
return handoff === undefined ? [] : [handoff];
|
|
44
|
+
});
|
|
45
|
+
return externalHandoffs.length === 0 ? observation : { ...observation, externalHandoffs };
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -14,6 +14,7 @@ import { GUEST_BOOTSTRAP_LIMITS, validateGuestInitialUrl } from "./bootstrap.js"
|
|
|
14
14
|
import { startDesktopMedia, } from "./desktop-media.js";
|
|
15
15
|
import { startDesktopRecorder } from "../evidence/desktop-recorder.js";
|
|
16
16
|
import { createGuestProcesses, setupFailed } from "./runtime-processes.js";
|
|
17
|
+
import { GUEST_EXTERNAL_LINK_BIN, prepareGuestBrowserProfile, withExternalHandoffs, } from "./external-links.js";
|
|
17
18
|
/** The guest image's fixed layout. Tests derive guest paths from it rather than spelling them. */
|
|
18
19
|
export const GUEST_RUNTIME_PATHS = Object.freeze({
|
|
19
20
|
root: "/opt/humanish/control",
|
|
@@ -21,7 +22,8 @@ export const GUEST_RUNTIME_PATHS = Object.freeze({
|
|
|
21
22
|
home: "/home/humanish",
|
|
22
23
|
});
|
|
23
24
|
const GUEST_RUNTIME_ENV = Object.freeze({
|
|
24
|
-
|
|
25
|
+
// The stand-ins come first, so the browser hands a mailto: or tel: link to them.
|
|
26
|
+
PATH: `${GUEST_EXTERNAL_LINK_BIN}:/usr/bin:/bin`,
|
|
25
27
|
HOME: "/home/humanish",
|
|
26
28
|
USER: "humanish",
|
|
27
29
|
LOGNAME: "humanish",
|
|
@@ -390,6 +392,7 @@ export async function createGuestRuntimeDesktop(options) {
|
|
|
390
392
|
progress("layout");
|
|
391
393
|
check();
|
|
392
394
|
await verifyGuestLayout(check);
|
|
395
|
+
await prepareGuestBrowserProfile(`${GUEST_RUNTIME_PATHS.home}/browser`, options.initialUrl);
|
|
393
396
|
progress("xauthority");
|
|
394
397
|
await authorizeDisplay(processes, check);
|
|
395
398
|
progress("display");
|
|
@@ -434,7 +437,7 @@ export async function createGuestRuntimeDesktop(options) {
|
|
|
434
437
|
await openGuestFixture(browser.page, check);
|
|
435
438
|
}
|
|
436
439
|
return {
|
|
437
|
-
executor: state.media?.wrap(executor) ?? executor,
|
|
440
|
+
executor: withExternalHandoffs(state.media?.wrap(executor) ?? executor, `${GUEST_RUNTIME_ENV.XDG_RUNTIME_DIR}/humanish-links.log`),
|
|
438
441
|
close,
|
|
439
442
|
...(options.recording === undefined
|
|
440
443
|
? {}
|
package/dist/observer/data.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ export interface ObserverData {
|
|
|
23
23
|
state: "running" | "finished" | "interrupted" | "unknown";
|
|
24
24
|
observedAt: string;
|
|
25
25
|
source: "local-run-status";
|
|
26
|
+
/** Present while the run's own process analyzes it after the run ended: when it started. */
|
|
27
|
+
analysis?: {
|
|
28
|
+
startedAt: string;
|
|
29
|
+
};
|
|
26
30
|
};
|
|
27
31
|
run: {
|
|
28
32
|
runId: string;
|
|
@@ -15,7 +15,7 @@ import { displayedTraces, loadStreamTraces, } from "../run/stream-trace.js";
|
|
|
15
15
|
import { isNodeError, isRecord } from "../run/type-guards.js";
|
|
16
16
|
import { MAX_NOTE_FILE_BYTES, readRunNotes, RUN_NOTES_DIR, } from "../run/note-files.js";
|
|
17
17
|
import { analysisCostOf, runCost, runCostLabel } from "../run/run-cost.js";
|
|
18
|
-
import { RUN_STATUS_FILE, RUN_STATUS_STALE_MS, isRunStatusRecord, } from "../run/status.js";
|
|
18
|
+
import { RUN_STATUS_FILE, RUN_STATUS_STALE_MS, runAnalysisPhase, isRunStatusRecord, } from "../run/status.js";
|
|
19
19
|
import { renderObserverHtml } from "./artifact.js";
|
|
20
20
|
import { parseFeedCursors } from "./feed-cursors.js";
|
|
21
21
|
import { observerFeedBody } from "./page-data.js";
|
|
@@ -98,7 +98,9 @@ export async function serveRunPath(runRoot, relativePath, response, runtimeStrea
|
|
|
98
98
|
const derivedRoot = cleanedRelativePath.split("/")[0];
|
|
99
99
|
const derivedLeaf = path.posix.basename(cleanedRelativePath);
|
|
100
100
|
// Local-only files (raw sandbox ids, the recording pid) are read in process, never served.
|
|
101
|
-
if (
|
|
101
|
+
if (
|
|
102
|
+
// `.analysis-lock-stale-*` is a lock whose dead owner's next writer moved it aside.
|
|
103
|
+
derivedRoot?.startsWith(".analysis-lock") === true ||
|
|
102
104
|
derivedLeaf.startsWith(".humanish-write-") ||
|
|
103
105
|
isAnalysisRecordPath(cleanedRelativePath) ||
|
|
104
106
|
isLocalOnlyRunFile(cleanedRelativePath)) {
|
|
@@ -330,9 +332,16 @@ function withLocalRunStatus(record, input, outcome) {
|
|
|
330
332
|
state = "running";
|
|
331
333
|
}
|
|
332
334
|
}
|
|
335
|
+
// The run's own process analyzes it after the run ended; the bundle outcome does not say so.
|
|
336
|
+
const analysis = timestampsValid ? runAnalysisPhase(record, now) : undefined;
|
|
333
337
|
return {
|
|
334
338
|
...data,
|
|
335
|
-
runtime: {
|
|
339
|
+
runtime: {
|
|
340
|
+
state,
|
|
341
|
+
observedAt: new Date(now).toISOString(),
|
|
342
|
+
source: "local-run-status",
|
|
343
|
+
...(analysis?.state === "running" ? { analysis: { startedAt: analysis.startedAt } } : {}),
|
|
344
|
+
},
|
|
336
345
|
};
|
|
337
346
|
}
|
|
338
347
|
/** internal: exported for the stream lifecycle tests. */
|