humanish 0.17.0 → 0.18.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/README.md +32 -21
- package/dist/actor-contract.d.ts +1 -1
- package/dist/actor-contract.js.map +1 -1
- package/dist/computer-use.js +33 -5
- package/dist/computer-use.js.map +1 -1
- package/dist/cua-actor-lab.d.ts +1 -1
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/observer-library.d.ts +1 -1
- package/dist/observer-library.js +1 -6
- package/dist/observer-library.js.map +1 -1
- package/dist/observer-serve.d.ts +11 -23
- package/dist/observer-serve.js +12 -92
- package/dist/observer-serve.js.map +1 -1
- package/dist/observer.d.ts +3 -0
- package/dist/observer.js +47 -0
- package/dist/observer.js.map +1 -1
- package/dist/program.js +294 -122
- package/dist/program.js.map +1 -1
- package/dist/serve-exposure.d.ts +62 -0
- package/dist/serve-exposure.js +129 -0
- package/dist/serve-exposure.js.map +1 -0
- package/dist/serve-http.d.ts +8 -0
- package/dist/serve-http.js +37 -0
- package/dist/serve-http.js.map +1 -0
- package/dist/serve-tunnel.d.ts +6 -2
- package/dist/serve-tunnel.js +9 -0
- package/dist/serve-tunnel.js.map +1 -1
- package/docs/architecture/actor-contract.md +29 -3
- package/docs/architecture/observer.md +30 -0
- package/docs/architecture/serve.md +138 -82
- package/docs/contracts/schemas.md +24 -15
- package/docs/goals/current.md +1 -1
- package/docs/principles/invariants-and-defaults.md +2 -1
- package/docs/ramp/README.md +1 -1
- package/package.json +1 -1
- package/dist/observer-auth.d.ts +0 -21
- package/dist/observer-auth.js +0 -92
- package/dist/observer-auth.js.map +0 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Date: 2026-06-02 (current-state note updated 2026-07-14)
|
|
4
4
|
|
|
5
5
|
Status: reference map for the major contracts shipped through source version
|
|
6
|
-
`0.
|
|
6
|
+
`0.18.0`; it is not an exhaustive inventory of command/result envelopes. Exported types,
|
|
7
7
|
schema constants, parsers, and validators in `src/` are authoritative. Rows
|
|
8
8
|
marked "reserved" name layering intent only — no code emits or validates them
|
|
9
9
|
yet. Do not emit a reserved schema.
|
|
@@ -601,7 +601,11 @@ Core-owned fields:
|
|
|
601
601
|
- `startedAt` / `completedAt` / `durationMs`
|
|
602
602
|
- `status` / `completionReason` / `reason` (`completionReason` includes
|
|
603
603
|
`step_failed`: a deterministic scripted step/expectation evaluated false —
|
|
604
|
-
the subject failed the script while the harness executed faithfully
|
|
604
|
+
the subject failed the script while the harness executed faithfully; and
|
|
605
|
+
`budget_reached`: an open-ended watch session that hit the wall-clock time
|
|
606
|
+
budget AFTER productive activity — status `passed`, a NON-FAILURE completion,
|
|
607
|
+
distinct from `timed_out`, which stays reserved for a zero-progress deadline
|
|
608
|
+
hit and remains a failure)
|
|
605
609
|
- `ids`, `counts`, `items[]`, optional `tokenUsage`, `capabilities`
|
|
606
610
|
|
|
607
611
|
Unexpected actor-loop diagnostics live inside `items[]` as
|
|
@@ -652,19 +656,24 @@ inside run bundles (per-stream transport and status) and lab execution config
|
|
|
652
656
|
|
|
653
657
|
`humanish serve` reports `humanish.serve-result.v1`. The exported `ServeResult`
|
|
654
658
|
type and `SERVE_SCHEMA` constant in `src/observer-serve.ts` are authoritative:
|
|
655
|
-
mode (`loopback |
|
|
656
|
-
|
|
657
|
-
`
|
|
658
|
-
operator's
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
659
|
+
mode (`loopback | exposed | share-safe-open`), the loopback host/port,
|
|
660
|
+
`publicUrl`, the `tunnel` provider/url, an `oauth` echo (`provider`,
|
|
661
|
+
`allowEmails`, `allowDomains` — operator-supplied allow rules, public-safe to
|
|
662
|
+
echo to the operator's own stdout, never persisted into any bundle), runs
|
|
663
|
+
listed, computed warnings, and the `ServeErrorCode` union. Exposure auth is
|
|
664
|
+
tunnel-edge only — as of 0.18.0 there are no `capabilityUrl`/`publicCapabilityUrl`
|
|
665
|
+
/`ttlMinutes` fields, no `--auth`/`--ttl` flags, and no `capability-link` mode
|
|
666
|
+
(the in-process `observer-auth.ts` capability-link was removed as a pre-1.0
|
|
667
|
+
breaking change).
|
|
668
|
+
|
|
669
|
+
Reserved: `/_humanish/api/*` is the serve control-plane namespace. Any request
|
|
670
|
+
under it answers `501` with error code `HUMANISH_SERVE_CONTROL_PLANE_DISABLED`.
|
|
671
|
+
Because the in-process auth gate is gone, a request that clears the edge (or a
|
|
672
|
+
loopback caller) reaches the `501` directly — there is no `401`-first anymore.
|
|
673
|
+
The typed `ServeControlPlane` parameter exists in the handler options and is
|
|
674
|
+
always `undefined` in v1; no code dispatches into it yet. Do not build against
|
|
675
|
+
the namespace; the reservation guarantees only that no run artifact or observer
|
|
676
|
+
asset will ever be served under it. See
|
|
668
677
|
[`docs/architecture/serve.md`](../architecture/serve.md) for the v2 seam
|
|
669
678
|
contract.
|
|
670
679
|
|
package/docs/goals/current.md
CHANGED
|
@@ -16,7 +16,7 @@ Humanish should be the open-source CLI that lets a maintainer ask:
|
|
|
16
16
|
The answer should be observable, verifiable, public-safe, and easy to turn into
|
|
17
17
|
actionable feedback.
|
|
18
18
|
|
|
19
|
-
## Current Program Truth (source `0.
|
|
19
|
+
## Current Program Truth (source `0.18.0`)
|
|
20
20
|
|
|
21
21
|
The package source and repository implementation in this tree agree on these
|
|
22
22
|
points:
|
|
@@ -74,7 +74,8 @@ silently drifting from one is not.
|
|
|
74
74
|
| Single lane | Cost + evidence simplicity | Declared fan-out where the backend supports it — `actors[0].count: N` (homogeneous), explicit `actors[0].lanes[]` (differentiated persona/device/instruction), or compact `actors[0].roster[]` groups that normalize into lanes on the computer-use E2B route (per-lane worlds, cap 16; `execution.concurrency` bounds concurrent paid lanes) |
|
|
75
75
|
| Stock `desktop` template | The stock E2B desktop image is right for most subjects; absent `execution.desktop.template` keeps `Sandbox.create(opts)` byte-stable | `execution.desktop.template` names a custom E2B desktop image (any name/id, no allowlist) for a subject needing baked-in runtimes the stock image lacks (e.g. node/bun/a local Postgres) — threaded to `Sandbox.create(template, opts)` on every desktop-creating route and recorded in the bundle as `desktopTemplate` (public-safe) |
|
|
76
76
|
| Desktop default URL opener | Preserve the route/image's historical browser/default opener behavior when unset | `execution.desktop.browser: chrome | chromium | firefox` makes hosted CUA/shared-world browser choice explicit, fail-closed, and recorded as `desktopBrowser` in the run bundle |
|
|
77
|
-
| Loopback-only observer serving | Run bundles are local by default (public-safety plank 3); the serve
|
|
77
|
+
| Loopback-only observer serving | Run bundles are local by default (public-safety plank 3); the serve/watch surfaces bind `127.0.0.1` unconditionally, and exposing them is publishing-adjacent, so exposure is fail-closed and carries declared friction | `humanish serve --expose` behind TUNNEL-EDGE auth — ngrok `--oauth google` (`--allow-email`/`--allow-domain` allow rules) or an operator `--public-url` you secure — OR `--expose --safe` (open, gated on verify-`share_ready` runs only). `watch --expose` streams a live run behind edge auth (a live run is never `share_ready`, so `--safe` alone is refused). humanish carries no in-process auth; both print computed warnings naming exactly what became reachable |
|
|
78
|
+
| Generous wall-clock safety cap | `execution.timeoutMs` bounds runaway spend, not a goal; ~30 min is reasonable for open-ended "watch it play" | A session that reaches the cap AFTER productive activity is recorded as `budget_reached` (status `passed`, a NON-FAILURE completion, exit `0`), distinct from a zero-progress `timed_out` (a failure, exit `2`). Goal-directed labs set a tight `timeoutMs` and read `completionReason` to confirm the goal, not the cap |
|
|
78
79
|
|
|
79
80
|
## The placement rule (worked example)
|
|
80
81
|
|
package/docs/ramp/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Status: public-safe contributor and agent ramp.
|
|
4
4
|
|
|
5
|
-
Package/source version in this tree: `0.
|
|
5
|
+
Package/source version in this tree: `0.18.0` (2026-08-02). The containment boundary introduced in
|
|
6
6
|
`0.15.1` remains in force: managed run and output paths bind to validated
|
|
7
7
|
physical filesystem identities, and stored provider IDs are evidence, not
|
|
8
8
|
cleanup authority. The bundled OSS meta-lab is dry-run only until
|
package/package.json
CHANGED
package/dist/observer-auth.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export declare const SERVE_COOKIE_NAME = "humanish_serve";
|
|
2
|
-
export interface ServeSessionStore {
|
|
3
|
-
mint(): {
|
|
4
|
-
cookieValue: string;
|
|
5
|
-
};
|
|
6
|
-
validate(cookieHeader: string | undefined): boolean;
|
|
7
|
-
revokeAll(): void;
|
|
8
|
-
sessionCount(): number;
|
|
9
|
-
}
|
|
10
|
-
export declare function mintServeToken(): string;
|
|
11
|
-
export declare function sha256Digest(value: string): Buffer;
|
|
12
|
-
export declare function verifyTokenDigest(candidate: string, digest: Buffer): boolean;
|
|
13
|
-
export declare function createServeSessionStore(options: {
|
|
14
|
-
ttlMs: number;
|
|
15
|
-
now?: () => number;
|
|
16
|
-
}): ServeSessionStore;
|
|
17
|
-
export declare function parseCookies(header: string | undefined): Record<string, string>;
|
|
18
|
-
export declare function buildSessionCookie(cookieValue: string, options: {
|
|
19
|
-
ttlSeconds: number;
|
|
20
|
-
secure: boolean;
|
|
21
|
-
}): string;
|
package/dist/observer-auth.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
|
-
export const SERVE_COOKIE_NAME = "humanish_serve";
|
|
3
|
-
export function mintServeToken() {
|
|
4
|
-
return randomBytes(32).toString("base64url");
|
|
5
|
-
}
|
|
6
|
-
export function sha256Digest(value) {
|
|
7
|
-
return createHash("sha256").update(value, "utf8").digest();
|
|
8
|
-
}
|
|
9
|
-
// Hash-first comparison: both sides become fixed-length digests before
|
|
10
|
-
// timingSafeEqual, so an attacker-controlled candidate can neither throw on
|
|
11
|
-
// length mismatch nor learn the token length.
|
|
12
|
-
export function verifyTokenDigest(candidate, digest) {
|
|
13
|
-
return timingSafeEqual(sha256Digest(candidate), digest);
|
|
14
|
-
}
|
|
15
|
-
export function createServeSessionStore(options) {
|
|
16
|
-
const now = options.now ?? (() => Date.now());
|
|
17
|
-
const sessions = new Map();
|
|
18
|
-
return {
|
|
19
|
-
mint() {
|
|
20
|
-
// Sweep expired records on each mint so the map cannot grow without bound
|
|
21
|
-
// when many links are tapped: without this, a record is only pruned when
|
|
22
|
-
// its own cookie is presented again, which an abandoned session never is.
|
|
23
|
-
const currentTime = now();
|
|
24
|
-
for (const [digest, record] of sessions) {
|
|
25
|
-
if (record.expiresAt <= currentTime) {
|
|
26
|
-
sessions.delete(digest);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
const cookieValue = randomBytes(32).toString("base64url");
|
|
30
|
-
sessions.set(sha256Digest(cookieValue).toString("hex"), {
|
|
31
|
-
expiresAt: currentTime + options.ttlMs,
|
|
32
|
-
scope: "viewer"
|
|
33
|
-
});
|
|
34
|
-
return { cookieValue };
|
|
35
|
-
},
|
|
36
|
-
validate(cookieHeader) {
|
|
37
|
-
const cookieValue = parseCookies(cookieHeader)[SERVE_COOKIE_NAME];
|
|
38
|
-
if (!cookieValue) {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
const record = sessions.get(sha256Digest(cookieValue).toString("hex"));
|
|
42
|
-
if (!record || record.scope !== "viewer") {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
if (record.expiresAt <= now()) {
|
|
46
|
-
sessions.delete(sha256Digest(cookieValue).toString("hex"));
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
return true;
|
|
50
|
-
},
|
|
51
|
-
revokeAll() {
|
|
52
|
-
sessions.clear();
|
|
53
|
-
},
|
|
54
|
-
sessionCount() {
|
|
55
|
-
return sessions.size;
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
export function parseCookies(header) {
|
|
60
|
-
if (!header) {
|
|
61
|
-
return {};
|
|
62
|
-
}
|
|
63
|
-
const cookies = {};
|
|
64
|
-
for (const part of header.split(";")) {
|
|
65
|
-
const separator = part.indexOf("=");
|
|
66
|
-
if (separator <= 0) {
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
const name = part.slice(0, separator).trim();
|
|
70
|
-
const value = part.slice(separator + 1).trim();
|
|
71
|
-
if (name) {
|
|
72
|
-
cookies[name] = value;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return cookies;
|
|
76
|
-
}
|
|
77
|
-
export function buildSessionCookie(cookieValue, options) {
|
|
78
|
-
const attributes = [
|
|
79
|
-
`${SERVE_COOKIE_NAME}=${cookieValue}`,
|
|
80
|
-
"Path=/",
|
|
81
|
-
"HttpOnly",
|
|
82
|
-
"SameSite=Lax",
|
|
83
|
-
`Max-Age=${options.ttlSeconds}`
|
|
84
|
-
];
|
|
85
|
-
if (options.secure) {
|
|
86
|
-
attributes.push("Secure");
|
|
87
|
-
}
|
|
88
|
-
// Deliberately no Domain attribute: a host-only cookie on the public origin
|
|
89
|
-
// can never leak to sibling subdomains of a shared tunnel domain.
|
|
90
|
-
return attributes.join("; ");
|
|
91
|
-
}
|
|
92
|
-
//# sourceMappingURL=observer-auth.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"observer-auth.js","sourceRoot":"","sources":["../src/observer-auth.ts"],"names":[],"mappings":"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"}
|